summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorIan Walters <ian.walters@nokia.com>2009-05-07 05:14:04 (GMT)
committerIan Walters <ian.walters@nokia.com>2009-05-07 05:14:04 (GMT)
commit45f531b9863fb64e6d4df2c77af01f14019f217e (patch)
tree8d65d6c7b64bd0aec300a3f396b175fbb70ff747 /src/declarative
parent73667e2618ecbd00f6496006fcfc3c56ac99be6d (diff)
parente82217bf8e4ebaba20eb255bd52a9f261467b9d8 (diff)
downloadQt-45f531b9863fb64e6d4df2c77af01f14019f217e.zip
Qt-45f531b9863fb64e6d4df2c77af01f14019f217e.tar.gz
Qt-45f531b9863fb64e6d4df2c77af01f14019f217e.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/debugger/qmldebugger.cpp154
-rw-r--r--src/declarative/debugger/qmldebugger.h12
-rw-r--r--src/declarative/fx/qfximage.cpp106
-rw-r--r--src/declarative/fx/qfximage.h5
-rw-r--r--src/declarative/fx/qfximage_p.h12
-rw-r--r--src/declarative/fx/qfxpixmap.cpp8
-rw-r--r--src/declarative/fx/qfxpixmap.h3
-rw-r--r--src/declarative/qml/qmlengine.cpp36
-rw-r--r--src/declarative/qml/qmlengine_p.h11
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp12
-rw-r--r--src/declarative/qml/qmlmetaproperty.h1
-rw-r--r--src/declarative/util/qmlanimation.cpp3
-rw-r--r--src/declarative/util/qmlanimation_p.h14
-rw-r--r--src/declarative/util/qmllistmodel.cpp68
14 files changed, 368 insertions, 77 deletions
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
index 033a15f..a1956f9 100644
--- a/src/declarative/debugger/qmldebugger.cpp
+++ b/src/declarative/debugger/qmldebugger.cpp
@@ -43,6 +43,8 @@
#include <QtGui/qtreewidget.h>
#include <QtGui/qboxlayout.h>
#include <QtGui/qplaintextedit.h>
+#include <QTextBlock>
+#include <QtGui/qtabwidget.h>
#include <QtDeclarative/qmlbindablevalue.h>
#include <private/qmlboundsignal_p.h>
#include <private/qmlcontext_p.h>
@@ -52,10 +54,11 @@
#include <QtCore/qurl.h>
#include <QtGui/qsplitter.h>
#include <QtGui/qpushbutton.h>
+#include <QtGui/qtablewidget.h>
#include <QtGui/qevent.h>
QmlDebugger::QmlDebugger(QWidget *parent)
-: QWidget(parent), m_tree(0)
+: QWidget(parent), m_tree(0), m_warnings(0), m_watchers(0), m_text(0)
{
QHBoxLayout *layout = new QHBoxLayout;
setLayout(layout);
@@ -69,18 +72,34 @@ QmlDebugger::QmlDebugger(QWidget *parent)
splitter->addWidget(treeWid);
m_tree = new QTreeWidget(treeWid);
+ m_tree->setSelectionMode(QTreeWidget::NoSelection);
m_tree->setHeaderHidden(true);
- QObject::connect(m_tree, SIGNAL(itemPressed(QTreeWidgetItem *, int)), this, SLOT(itemPressed(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
+ QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
vlayout->addWidget(m_tree);
QPushButton *pb = new QPushButton("Refresh", treeWid);
QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
vlayout->addWidget(pb);
+ QTabWidget *tabs = new QTabWidget(this);
+
m_text = new QPlainTextEdit(this);
m_text->setReadOnly(true);
- splitter->addWidget(m_text);
+ tabs->addTab(m_text, "File");
+
+ m_warnings = new QTreeWidget(this);
+ m_warnings->setHeaderHidden(true);
+ tabs->addTab(m_warnings, "Warnings");
+
+ m_watchers = new QTableWidget(this);
+ m_watchers->setSelectionMode(QTableWidget::NoSelection);
+ tabs->addTab(m_watchers, "Watchers");
+
+ splitter->addWidget(tabs);
splitter->setStretchFactor(1, 2);
+
+ setGeometry(0, 100, 800, 600);
}
class QmlDebuggerItem : public QTreeWidgetItem
@@ -103,31 +122,29 @@ public:
QPointer<QmlBindableValue> bindableValue;
};
-void QmlDebugger::itemPressed(QTreeWidgetItem *i)
+void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *i)
{
QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
if(item->bindableValue) {
- QString str;
-
QmlExpressionPrivate *p = item->bindableValue->d;
- if(p->log) {
- QString str;
- QDebug d(&str);
- for(int ii = 0; ii < p->log->count(); ++ii) {
- d << p->log->at(ii).result() << "\n";
- QStringList warnings = p->log->at(ii).warnings();
- foreach(const QString &warning, warnings)
- d << " " << warning << "\n";
- }
- m_text->setPlainText(str);
+ if(m_watchedIds.contains(p->id)) {
+ m_watchedIds.remove(p->id);
+ item->setForeground(0, Qt::green);
} else {
- m_text->setPlainText("No history");
+ m_watchedIds.insert(p->id);
+ item->setForeground(0, QColor("purple"));
}
- } else if(item->url.scheme() == QLatin1String("file")) {
+ }
+}
+
+void QmlDebugger::itemClicked(QTreeWidgetItem *i)
+{
+ QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
+ if(item->url.scheme() == QLatin1String("file")) {
QString f = item->url.toLocalFile();
QFile file(f);
file.open(QIODevice::ReadOnly);
@@ -141,17 +158,11 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
QTextDocument *document = m_text->document();
QTextCharFormat format;
format.setForeground(Qt::lightGray);
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor, item->startLine - 1);
- cursor.setCharFormat(format);
- }
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->endLine);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
cursor.setCharFormat(format);
}
@@ -159,31 +170,87 @@ void QmlDebugger::itemPressed(QTreeWidgetItem *i)
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.setCharFormat(QTextCharFormat());
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
+ cursor.setCharFormat(format);
}
{
QTextCursor cursor(document);
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, item->startLine - 1);
+ cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
m_text->setTextCursor(cursor);
m_text->centerCursor();
}
+
+
}
}
}
-static bool makeItem(QObject *obj, QmlDebuggerItem *item)
+bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
{
bool rv = true;
QString text;
if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
+ QmlExpressionPrivate *p = bv->d;
+
text = bv->property().name() + ": " + bv->expression();
- item->setForeground(0, Qt::green);
+ bool watched = m_watchedIds.contains(p->id);
+ if(watched)
+ item->setForeground(0, QColor("purple"));
+ else
+ item->setForeground(0, Qt::green);
item->bindableValue = bv;
+
+ if(p->log) {
+ QTreeWidgetItem *warningItem = 0;
+
+ int column = m_watchers->columnCount();
+
+ if(watched) {
+ m_watchers->insertColumn(column);
+ QTableWidgetItem *tableheader = new QTableWidgetItem;
+ tableheader->setText(bv->expression());
+ tableheader->setToolTip(bv->expression());
+ m_watchers->setHorizontalHeaderItem(column, tableheader);
+ }
+
+ for(int ii = 0; ii < p->log->count(); ++ii) {
+ const QmlExpressionLog &log = p->log->at(ii);
+
+ QString variant; QDebug d(&variant); d << log.result();
+ if(watched) {
+ QString str = log.result().toString();
+ if(str.isEmpty())
+ str = variant;
+ m_expressions << qMakePair(log.time(), qMakePair(column, str));
+ }
+
+ if(!log.warnings().isEmpty()) {
+
+ if(!warningItem) {
+ warningItem = new QTreeWidgetItem(m_warnings);
+ warningItem->setText(0, bv->expression());
+ }
+
+ QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
+ entry->setExpanded(true);
+
+ entry->setText(0, variant);
+
+ foreach(const QString &warning, log.warnings()) {
+ QTreeWidgetItem *w = new QTreeWidgetItem(entry);
+ w->setText(0, warning);
+ }
+ }
+
+ }
+
+ }
+
} else if(QmlBoundSignal *bs = qobject_cast<QmlBoundSignal *>(obj)) {
QMetaMethod method = obj->parent()->metaObject()->method(bs->index());
QByteArray sig = method.signature();
@@ -237,7 +304,7 @@ static bool makeItem(QObject *obj, QmlDebuggerItem *item)
return rv;
}
-static void buildTree(QObject *obj, QmlDebuggerItem *parent)
+void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
{
QObjectList children = obj->children();
@@ -253,9 +320,20 @@ void QmlDebugger::refresh()
setDebugObject(m_object);
}
+bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
+ const QPair<quint32, QPair<int, QString> > &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
void QmlDebugger::setDebugObject(QObject *obj)
{
m_tree->clear();
+ m_warnings->clear();
+ m_watchers->clear();
+ m_watchers->setColumnCount(0);
+ m_watchers->setRowCount(0);
+ m_expressions.clear();
m_object = obj;
if(!obj)
@@ -265,6 +343,20 @@ void QmlDebugger::setDebugObject(QObject *obj)
makeItem(obj, item);
buildTree(obj, item);
item->setExpanded(true);
- setGeometry(0, 100, 800, 600);
+
+ m_watchers->setRowCount(m_expressions.count());
+
+ qSort(m_expressions.begin(), m_expressions.end());
+
+ for(int ii = 0; ii < m_expressions.count(); ++ii) {
+
+ const QPair<quint32, QPair<int, QString> > &expr = m_expressions.at(ii);
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setText(expr.second.second);
+ m_watchers->setItem(ii, expr.second.first, item);
+
+ }
+
+
}
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
index 943abef..e04eb2e 100644
--- a/src/declarative/debugger/qmldebugger.h
+++ b/src/declarative/debugger/qmldebugger.h
@@ -43,6 +43,7 @@
#define QMLDEBUGGER_H
#include <QtCore/qpointer.h>
+#include <QtCore/qset.h>
#include <QtGui/qwidget.h>
QT_BEGIN_HEADER
@@ -54,6 +55,8 @@ QT_MODULE(Declarative)
class QTreeWidget;
class QTreeWidgetItem;
class QPlainTextEdit;
+class QmlDebuggerItem;
+class QTableWidget;
class QmlDebugger : public QWidget
{
Q_OBJECT
@@ -66,12 +69,19 @@ public slots:
void refresh();
private slots:
- void itemPressed(QTreeWidgetItem *);
+ void itemClicked(QTreeWidgetItem *);
+ void itemDoubleClicked(QTreeWidgetItem *);
private:
+ void buildTree(QObject *obj, QmlDebuggerItem *parent);
+ bool makeItem(QObject *obj, QmlDebuggerItem *item);
QTreeWidget *m_tree;
+ QTreeWidget *m_warnings;
+ QTableWidget *m_watchers;
QPlainTextEdit *m_text;
QPointer<QObject> m_object;
+ QList<QPair<quint32, QPair<int, QString> > > m_expressions;
+ QSet<quint32> m_watchedIds;
};
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp
index 106d551..d66846d 100644
--- a/src/declarative/fx/qfximage.cpp
+++ b/src/declarative/fx/qfximage.cpp
@@ -125,8 +125,8 @@ QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent)
QFxImage::~QFxImage()
{
Q_D(const QFxImage);
- if (d->reply)
- d->reply->deleteLater();
+ if (d->sciReply)
+ d->sciReply->deleteLater();
}
/*!
@@ -783,6 +783,19 @@ QString QFxImage::propertyInfo() const
return d->url.toString();
}
+/*!
+ \qmlproperty enum Image::status
+
+ This property holds the status of image loading. It can be one of:
+ \list
+ \o Idle - no image has been set, or the image has been loaded
+ \o Loading - the images is currently being loaded
+ \o Error - an error occurred while loading the image
+ \endlist
+
+ \sa progress
+*/
+
QFxImage::Status QFxImage::status() const
{
Q_D(const QFxImage);
@@ -790,6 +803,21 @@ QFxImage::Status QFxImage::status() const
}
/*!
+ \qmlproperty real Image::progress
+
+ This property holds the progress of image loading, from 0.0 (nothing loaded)
+ to 1.0 (finished).
+
+ \sa status
+*/
+
+qreal QFxImage::progress() const
+{
+ Q_D(const QFxImage);
+ return d->progress;
+}
+
+/*!
\qmlproperty string Image::source
Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
@@ -831,9 +859,9 @@ void QFxImage::setSource(const QString &url)
if (url == d->source)
return;
- if (d->reply) {
- d->reply->deleteLater();
- d->reply = 0;
+ if (d->sciReply) {
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
}
if (!d->url.isEmpty())
@@ -844,10 +872,25 @@ void QFxImage::setSource(const QString &url)
d->source = url;
d->url = qmlContext(this)->resolvedUrl(url);
d->sciurl = QUrl();
+ if (d->progress != 0.0) {
+ d->progress = 0.0;
+ emit progressChanged(d->progress);
+ }
if (url.isEmpty()) {
setPixmap(QPixmap());
d->status = Idle;
+ d->progress = 1.0;
+ setImplicitWidth(0);
+ setImplicitHeight(0);
+#if defined(QFX_RENDER_OPENGL)
+ d->_texDirty = true;
+ d->_tex.clear();
+#endif
+ emit statusChanged(d->status);
+ emit sourceChanged(d->source);
+ emit progressChanged(1.0);
+ update();
} else {
d->status = Loading;
if (d->url.path().endsWith(QLatin1String(".sci"))) {
@@ -861,12 +904,19 @@ void QFxImage::setSource(const QString &url)
{
QNetworkRequest req(d->url);
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
- d->reply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->reply, SIGNAL(finished()),
+ d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
+ QObject::connect(d->sciReply, SIGNAL(finished()),
this, SLOT(sciRequestFinished()));
}
} else {
- QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished()));
+ d->reply = QFxPixmap::get(qmlEngine(this), d->url, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
}
}
@@ -879,6 +929,12 @@ void QFxImage::requestFinished()
if (d->url.path().endsWith(QLatin1String(".sci"))) {
d->_pix = QFxPixmap(d->sciurl);
} else {
+ if (d->reply) {
+ disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ if (d->reply->error() != QNetworkReply::NoError)
+ d->status = Error;
+ }
d->_pix = QFxPixmap(d->url);
d->_pix.setOpaque(d->_opaque);
setOptions(QFxImage::SimpleItem, true);
@@ -886,32 +942,43 @@ void QFxImage::requestFinished()
setImplicitWidth(d->_pix.width());
setImplicitHeight(d->_pix.height());
- d->status = Idle;
+ if (d->status == Loading)
+ d->status = Idle;
+ d->progress = 1.0;
#if defined(QFX_RENDER_OPENGL)
d->_texDirty = true;
d->_tex.clear();
#endif
emit statusChanged(d->status);
emit sourceChanged(d->source);
+ emit progressChanged(1.0);
update();
}
void QFxImage::sciRequestFinished()
{
Q_D(QFxImage);
- if (d->reply->error() != QNetworkReply::NoError) {
+ if (d->sciReply->error() != QNetworkReply::NoError) {
d->status = Error;
- d->reply->deleteLater();
- d->reply = 0;
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
emit statusChanged(d->status);
} else {
- QFxGridScaledImage sci(d->reply);
- d->reply->deleteLater();
- d->reply = 0;
+ QFxGridScaledImage sci(d->sciReply);
+ d->sciReply->deleteLater();
+ d->sciReply = 0;
setGridScaledImage(sci);
}
}
+void QFxImage::requestProgress(qint64 received, qint64 total)
+{
+ Q_D(QFxImage);
+ if (d->status == Loading && total > 0) {
+ d->progress = qreal(received)/total;
+ emit progressChanged(d->progress);
+ }
+}
void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci)
{
@@ -921,7 +988,14 @@ void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci)
emit statusChanged(d->status);
} else {
d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
- QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished()));
+ d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, this, SLOT(requestFinished()));
+ if (d->reply) {
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ } else {
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
+ }
QFxScaleGrid *sg = scaleGrid();
sg->setTop(sci.gridTop());
sg->setBottom(sci.gridBottom());
diff --git a/src/declarative/fx/qfximage.h b/src/declarative/fx/qfximage.h
index 37fe5be..dc13a97 100644
--- a/src/declarative/fx/qfximage.h
+++ b/src/declarative/fx/qfximage.h
@@ -43,6 +43,7 @@
#define QFXIMAGE_H
#include <qfxitem.h>
+#include <QtNetwork/qnetworkreply.h>
QT_BEGIN_HEADER
@@ -58,6 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxImage : public QFxItem
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(QFxScaleGrid *scaleGrid READ scaleGrid)
Q_PROPERTY(bool tile READ isTiled WRITE setTiled)
@@ -84,6 +86,7 @@ public:
enum Status { Idle, Loading, Error };
Status status() const;
+ qreal progress() const;
QString source() const;
virtual void setSource(const QString &url);
@@ -101,6 +104,7 @@ public:
Q_SIGNALS:
void sourceChanged(const QString &);
void statusChanged(Status);
+ void progressChanged(qreal progress);
protected:
QFxImage(QFxImagePrivate &dd, QFxItem *parent);
@@ -109,6 +113,7 @@ protected:
private Q_SLOTS:
void requestFinished();
void sciRequestFinished();
+ void requestProgress(qint64,qint64);
private:
Q_DISABLE_COPY(QFxImage)
diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h
index fbb4c44..8227ce4 100644
--- a/src/declarative/fx/qfximage_p.h
+++ b/src/declarative/fx/qfximage_p.h
@@ -76,7 +76,7 @@ public:
#if defined(QFX_RENDER_OPENGL)
_texDirty(true),
#endif
- status(QFxImage::Idle), reply(0)
+ status(QFxImage::Idle), sciReply(0), progress(0.0)
{
}
@@ -95,10 +95,10 @@ public:
}
QFxScaleGrid *_scaleGrid;
- bool _tiled;
QFxPixmap _pix;
- bool _smooth;
- bool _opaque;
+ bool _tiled : 1;
+ bool _smooth : 1;
+ bool _opaque : 1;
#if defined(QFX_RENDER_OPENGL)
void checkDirty();
bool _texDirty;
@@ -109,7 +109,9 @@ public:
QString source;
QUrl url;
QUrl sciurl;
- QNetworkReply *reply;
+ QNetworkReply *sciReply;
+ QPointer<QNetworkReply> reply;
+ qreal progress;
};
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxpixmap.cpp b/src/declarative/fx/qfxpixmap.cpp
index 0d456c6..3fdd8e5 100644
--- a/src/declarative/fx/qfxpixmap.cpp
+++ b/src/declarative/fx/qfxpixmap.cpp
@@ -233,8 +233,11 @@ QFxPixmap::operator const QSimpleCanvasConfig::Image &() const
Starts a network request to load \a url. When the URL is loaded,
the given slot is invoked. Note that if the image is already cached,
the slot may be invoked immediately.
+
+ Returns a QNetworkReply if the image is not immediately available, otherwise
+ returns 0. The QNetworkReply must not be stored - it may be destroyed at any time.
*/
-void QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot)
+QNetworkReply *QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char* slot)
{
QString key = url.toString();
QFxPixmapCache::Iterator iter = qfxPixmapCache.find(key);
@@ -259,11 +262,14 @@ void QFxPixmap::get(QmlEngine *engine, const QUrl& url, QObject* obj, const char
if ((*iter)->reply) {
// still loading
QObject::connect((*iter)->reply, SIGNAL(finished()), obj, slot);
+ return (*iter)->reply;
} else {
// already loaded
QObject dummy;
QObject::connect(&dummy, SIGNAL(destroyed()), obj, slot);
}
+
+ return 0;
}
/*!
diff --git a/src/declarative/fx/qfxpixmap.h b/src/declarative/fx/qfxpixmap.h
index 9a3ba4e..748991e 100644
--- a/src/declarative/fx/qfxpixmap.h
+++ b/src/declarative/fx/qfxpixmap.h
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QmlEngine;
+class QNetworkReply;
class QFxPixmapPrivate;
class Q_DECLARATIVE_EXPORT QFxPixmap
{
@@ -65,7 +66,7 @@ public:
QFxPixmap &operator=(const QFxPixmap &);
- static void get(QmlEngine *, const QUrl& url, QObject*, const char* slot);
+ static QNetworkReply *get(QmlEngine *, const QUrl& url, QObject*, const char* slot);
static void cancelGet(const QUrl& url, QObject* obj, const char* slot);
bool isNull() const;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index be5226e..15b5879 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -139,7 +139,7 @@ QStack<QmlEngine *> *QmlEngineStack::engines()
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
- rootComponent(0), networkAccessManager(0), typeManager(e)
+ rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
{
QScriptValue proto = scriptEngine.newObject();
proto.setProperty(QLatin1String("emit"),
@@ -720,17 +720,17 @@ QmlEngine *QmlEngine::activeEngine()
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
-: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), log(0)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
-: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
}
QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile)
-: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), log(0)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true), id(0), log(0)
{
if (ssecompile) {
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -765,6 +765,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
: d(new QmlExpressionPrivate(this, expr, rc))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -774,6 +776,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
: d(new QmlExpressionPrivate(this, expr, ssecompile))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = me;
}
@@ -789,6 +793,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
: d(new QmlExpressionPrivate(this, expression, true))
{
d->ctxt = ctxt;
+ if(ctxt && ctxt->engine())
+ d->id = ctxt->engine()->d_func()->getUniqueId();
d->me = scope;
}
@@ -810,7 +816,7 @@ QmlEngine *QmlExpression::engine() const
}
/*!
- Returns teh QmlContext this expression is associated with, or 0 if there
+ Returns the QmlContext this expression is associated with, or 0 if there
is no association or the QmlContext has been destroyed.
*/
QmlContext *QmlExpression::context() const
@@ -988,6 +994,7 @@ QVariant QmlExpression::value()
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
@@ -997,8 +1004,8 @@ QVariant QmlExpression::value()
if (prop.hasChangedNotifier()) {
prop.connectNotifier(d->proxy, changedIndex);
- } else {
- QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: ") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String(".") + prop.name();
+ } else if (prop.needsChangedNotifier()) {
+ QString warn = QLatin1String("Expression depends on property without a NOTIFY signal: [") + QLatin1String(prop.object()->metaObject()->className()) + QLatin1String("].") + prop.name();
log.addWarning(warn);
}
}
@@ -1015,6 +1022,7 @@ QVariant QmlExpression::value()
}
} else {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1023,6 +1031,7 @@ QVariant QmlExpression::value()
} else {
if(qmlDebugger()) {
QmlExpressionLog log;
+ log.setTime(engine()->d_func()->getUniqueId());
log.setExpression(expression());
log.setResult(rv);
d->addLog(log);
@@ -1421,7 +1430,8 @@ QmlExpressionLog::QmlExpressionLog()
}
QmlExpressionLog::QmlExpressionLog(const QmlExpressionLog &o)
-: m_expression(o.m_expression),
+: m_time(o.m_time),
+ m_expression(o.m_expression),
m_result(o.m_result),
m_warnings(o.m_warnings)
{
@@ -1433,12 +1443,22 @@ QmlExpressionLog::~QmlExpressionLog()
QmlExpressionLog &QmlExpressionLog::operator=(const QmlExpressionLog &o)
{
+ m_time = o.m_time;
m_expression = o.m_expression;
m_result = o.m_result;
m_warnings = o.m_warnings;
return *this;
}
+void QmlExpressionLog::setTime(quint32 time)
+{
+ m_time = time;
+}
+
+quint32 QmlExpressionLog::time() const
+{
+ return m_time;
+}
QString QmlExpressionLog::expression() const
{
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 7d5176e..63df0ba 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -114,6 +114,11 @@ public:
QmlCompositeTypeManager typeManager;
QMap<QString,QString> nameSpacePaths;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
};
@@ -201,6 +206,9 @@ public:
QmlExpressionLog &operator=(const QmlExpressionLog &);
+ void setTime(quint32);
+ quint32 time() const;
+
QString expression() const;
void setExpression(const QString &);
@@ -211,6 +219,7 @@ public:
void setResult(const QVariant &);
private:
+ quint32 m_time;
QString m_expression;
QVariant m_result;
QStringList m_warnings;
@@ -233,6 +242,8 @@ public:
QObject *me;
bool trackChange;
+ quint32 id;
+
void addLog(const QmlExpressionLog &);
QList<QmlExpressionLog> *log;
};
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 40c9b0e..59d6b38 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -988,6 +988,18 @@ bool QmlMetaProperty::hasChangedNotifier() const
}
/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached);
+}
+
+/*!
Connects the property's change notifier signal to the
specified \a method of the \a dest object and returns
true. Returns false if this metaproperty does not
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
index 4836038..68b06e5 100644
--- a/src/declarative/qml/qmlmetaproperty.h
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -89,6 +89,7 @@ public:
void emitSignal();
bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
bool connectNotifier(QObject *dest, const char *slot) const;
bool connectNotifier(QObject *dest, int method) const;
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index 08a7a28..dd4e1eb 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -791,6 +791,7 @@ void QmlColorAnimation::prepare(QmlMetaProperty &p)
d->fromSourced = false;
d->value.QmlTimeLineValue::setValue(0.);
d->ca->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->ca->setFromSourcedValue(&d->fromSourced);
}
QAbstractAnimation *QmlColorAnimation::qtAnimation()
@@ -1595,6 +1596,7 @@ void QmlNumericAnimation::prepare(QmlMetaProperty &p)
d->fromSourced = false;
d->value.QmlTimeLineValue::setValue(0.);
d->na->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->na->setFromSourcedValue(&d->fromSourced);
}
QAbstractAnimation *QmlNumericAnimation::qtAnimation()
@@ -2152,6 +2154,7 @@ void QmlVariantAnimation::prepare(QmlMetaProperty &p)
d->fromSourced = false;
d->value.QmlTimeLineValue::setValue(0.);
d->va->setAnimValue(&d->value, QAbstractAnimation::KeepWhenStopped);
+ d->va->setFromSourcedValue(&d->fromSourced);
}
void QmlVariantAnimation::transition(QmlStateActions &actions,
diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h
index 06b7c08..00937a6 100644
--- a/src/declarative/util/qmlanimation_p.h
+++ b/src/declarative/util/qmlanimation_p.h
@@ -116,8 +116,7 @@ private:
class QmlTimeLineValueAnimator : public QVariantAnimation
{
public:
- QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), policy(KeepWhenStopped) {}
- QmlTimeLineValueAnimator(QmlTimeLineValue *value, QObject *parent = 0) : QVariantAnimation(parent), animValue(value), policy(KeepWhenStopped) {}
+ QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {}
void setAnimValue(QmlTimeLineValue *value, DeletionPolicy p)
{
if (state() == Running)
@@ -125,6 +124,10 @@ public:
animValue = value;
policy = p;
}
+ void setFromSourcedValue(bool *value)
+ {
+ fromSourced = value;
+ }
protected:
virtual void updateCurrentValue(const QVariant &value)
{
@@ -134,7 +137,11 @@ protected:
virtual void updateState(State oldState, State newState)
{
QVariantAnimation::updateState(oldState, newState);
- if (newState == Stopped && policy == DeleteWhenStopped) {
+ if (newState == Running) {
+ //check for new from every loop
+ if (fromSourced)
+ *fromSourced = false;
+ } else if (newState == Stopped && policy == DeleteWhenStopped) {
delete animValue;
animValue = 0;
}
@@ -142,6 +149,7 @@ protected:
private:
QmlTimeLineValue *animValue;
+ bool *fromSourced;
DeletionPolicy policy;
};
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp
index 1cd2f69..8184bda 100644
--- a/src/declarative/util/qmllistmodel.cpp
+++ b/src/declarative/util/qmllistmodel.cpp
@@ -93,8 +93,7 @@ Q_DECLARE_METATYPE(QListModelInterface *);
}
\endcode
- Elements beginning with a capital are items. Elements beginning
- with lower-case are the data roles. The above example defines a
+ Item roles (properties) must begin with a lower-case letter. The above example defines a
ListModel containing three items, with the roles "name" and "cost".
The defined model can be used in views such as ListView:
@@ -102,15 +101,9 @@ Q_DECLARE_METATYPE(QListModelInterface *);
Component {
id: FruitDelegate
Item {
- width: 200
- height: 50
- Text {
- text: name
- }
- Text {
- text: '$'+cost
- anchors.right: parent.right
- }
+ width: 200; height: 50
+ Text { text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
}
}
@@ -120,6 +113,59 @@ Q_DECLARE_METATYPE(QListModelInterface *);
anchors.fill: parent
}
\endcode
+
+ It is possible for roles to contain list data. In the example below we create a list of fruit attributes:
+
+ \code
+ ListModel {
+ id: FruitModel
+ ListElement {
+ name: "Apple"
+ cost: 2.45
+ attributes: [
+ ListElement { description: "Core" },
+ ListElement { description: "Deciduous" }
+ ]
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3.25
+ attributes: [
+ ListElement { description: "Citrus" }
+ ]
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1.95
+ attributes: [
+ ListElement { description: "Tropical" }
+ ListElement { description: "Seedless" }
+ ]
+ }
+ }
+ \endcode
+
+ The delegate below will list all the fruit attributes:
+ \code
+ Component {
+ id: FruitDelegate
+ Item {
+ width: 200; height: 50
+ Text { id: Name; text: name }
+ Text { text: '$'+cost; anchors.right: parent.right }
+ HorizontalLayout {
+ anchors.top: Name.bottom
+ spacing: 5
+ Text { text: "Attributes:" }
+ Repeater {
+ dataSource: attributes
+ Component { Text { text: description } }
+ }
+ }
+ }
+ }
+ \endcode
+
*/
struct ModelNode;