summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-11-03 06:48:56 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2009-11-03 06:48:56 (GMT)
commitee259b6c04cf4296f45eed31c4d3c5c195fc0924 (patch)
tree67645a557da11167e225704740e7a8aa928b5ee7
parent79d35acae62bf28c37022b763b04e94f5e67bf6f (diff)
parent7bc853890bbd8653c3d058d50811ae6dfaad1fd1 (diff)
downloadQt-ee259b6c04cf4296f45eed31c4d3c5c195fc0924.zip
Qt-ee259b6c04cf4296f45eed31c4d3c5c195fc0924.tar.gz
Qt-ee259b6c04cf4296f45eed31c4d3c5c195fc0924.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r--doc/src/declarative/elements.qdoc7
-rw-r--r--examples/declarative/fonts/banner.qml18
-rw-r--r--examples/declarative/fonts/fonts.qml56
-rw-r--r--examples/declarative/fonts/hello.qml27
-rw-r--r--src/declarative/extra/qmlgraphicsanimatedimageitem.cpp48
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsflickable.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsgridview.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage.cpp14
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsimage_p_p.h2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsloader.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspath.cpp12
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspositioners.cpp23
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsrepeater.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextedit.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicstextinput.cpp2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicswebview.cpp2
-rw-r--r--src/declarative/qml/qmlcontext.cpp16
-rw-r--r--src/declarative/qml/qmlcontext_p.h3
-rw-r--r--src/declarative/qml/qmlvaluetype.cpp60
-rw-r--r--src/declarative/qml/qmlvaluetype_p.h39
-rw-r--r--src/declarative/util/qmlstategroup.cpp85
-rw-r--r--src/declarative/util/qmltimer.cpp19
-rw-r--r--tests/auto/declarative/animatedimage/tst_animatedimage.cpp38
-rw-r--r--tests/auto/declarative/behaviors/data/simple.qml5
-rw-r--r--tests/auto/declarative/behaviors/tst_behaviors.cpp43
-rw-r--r--tests/auto/declarative/declarative.pro1
-rw-r--r--tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro7
-rw-r--r--tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp1059
-rw-r--r--tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp49
35 files changed, 1547 insertions, 110 deletions
diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc
index 0eda95e..69535ce 100644
--- a/doc/src/declarative/elements.qdoc
+++ b/doc/src/declarative/elements.qdoc
@@ -60,9 +60,10 @@ The following table lists the QML elements provided by the Qt Declarative module
\list
\o \l State
\o \l PropertyChanges
-\o \l ParentChange
-\o \l StateChangeScript
-\o \l AnchorChanges
+\o \l StateGroup
+\o \l ParentChange (Item-specific)
+\o \l StateChangeScript (Item-specific)
+\o \l AnchorChanges (Item-specific)
\endlist
\o
diff --git a/examples/declarative/fonts/banner.qml b/examples/declarative/fonts/banner.qml
new file mode 100644
index 0000000..ece481b
--- /dev/null
+++ b/examples/declarative/fonts/banner.qml
@@ -0,0 +1,18 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen
+ width: 640; height: 320; color: "steelblue"
+
+ property int pixelSize: screen.height * 1.25
+ property color textColor: "lightsteelblue"
+ property string text: "Hello world! "
+
+ Row {
+ y: -screen.height / 4.5
+ x: NumberAnimation { from: 0; to: -text.width; duration: 6000; running: true; repeat: true }
+ Text { id: text; font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
+ }
+}
diff --git a/examples/declarative/fonts/fonts.qml b/examples/declarative/fonts/fonts.qml
index e68bdb6..80d82ad 100644
--- a/examples/declarative/fonts/fonts.qml
+++ b/examples/declarative/fonts/fonts.qml
@@ -1,12 +1,10 @@
import Qt 4.6
Rectangle {
- property string myText: "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
+ property string myText: "The quick brown fox jumps over the lazy dog."
- width: 800; height: 600
- color: palette.base
-
- SystemPalette { id: palette; colorGroup: Qt.Active }
+ width: 800; height: 480
+ color: "steelblue"
FontLoader { id: fixedFont; name: "Courier" }
@@ -17,28 +15,36 @@ Rectangle {
FontLoader { id: webFont2; source: "http://wrong.address.org" }
Column {
- anchors.fill: parent
+ anchors.fill: parent; spacing: 10
anchors.leftMargin: 10; anchors.rightMargin: 10
Text {
- text: myText
- color: palette.windowText
+ text: myText; color: "lightsteelblue"
width: parent.width; elide: Text.ElideRight
- font.family: "Times"
- font.pointSize: 32
+ font.family: "Times"; font.pointSize: 36
}
Text {
- text: myText
- color: palette.windowText
- width: parent.width; elide: Text.ElideRight
- font.family: fixedFont.name
- font.pointSize: 32
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideLeft
+ font.family: "Times"; font.pointSize: 36
+ font.capitalization: "AllUppercase"
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideMiddle
+ font.family: fixedFont.name; font.pointSize: 36; font.weight: "Bold"
+ font.capitalization: "AllLowercase"
}
Text {
- text: myText
- color: palette.windowText
+ text: myText; color: "lightsteelblue"
width: parent.width; elide: Text.ElideRight
- font.family: localFont.name
- font.pointSize: 32
+ font.family: fixedFont.name; font.pointSize: 36; font.italic: true
+ font.capitalization: "SmallCaps"
+ }
+ Text {
+ text: myText; color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideLeft
+ font.family: localFont.name; font.pointSize: 36
+ font.capitalization: "Capitalize"
}
Text {
text: {
@@ -46,10 +52,9 @@ Rectangle {
else if (webFont.status == 2) "Loading..."
else if (webFont.status == 3) "Error loading font"
}
- color: palette.windowText
- width: parent.width; elide: Text.ElideRight
- font.family: webFont.name
- font.pointSize: 32
+ color: "lightsteelblue"
+ width: parent.width; elide: Text.ElideMiddle
+ font.family: webFont.name; font.pointSize: 36
}
Text {
text: {
@@ -57,10 +62,9 @@ Rectangle {
else if (webFont2.status == 2) "Loading..."
else if (webFont2.status == 3) "Error loading font"
}
- color: palette.windowText
+ color: "lightsteelblue"
width: parent.width; elide: Text.ElideRight
- font.family: webFont2.name
- font.pointSize: 32
+ font.family: webFont2.name; font.pointSize: 36
}
}
}
diff --git a/examples/declarative/fonts/hello.qml b/examples/declarative/fonts/hello.qml
new file mode 100644
index 0000000..6aef3e6
--- /dev/null
+++ b/examples/declarative/fonts/hello.qml
@@ -0,0 +1,27 @@
+import Qt 4.6
+
+Rectangle {
+ id: screen; width: 800; height: 480; color: "black"
+
+ Item {
+ id: container; x: screen.width / 2; y: screen.height / 2
+ Text {
+ id: text; color: "white"; anchors.centerIn: parent
+ text: "Hello world!"; font.pixelSize: 60
+
+ font.letterSpacing: SequentialAnimation {
+ repeat: true; running: true
+ NumberAnimation { from: 100; to: 300; easing: "easeInQuad"; duration: 3000 }
+ ScriptAction { script: {
+ container.y = (screen.height / 4) + (Math.random() * screen.height / 2)
+ container.x = (screen.width / 4) + (Math.random() * screen.width / 2)
+ } }
+ }
+ opacity: SequentialAnimation {
+ repeat: true; running: true
+ NumberAnimation { from: 1; to: 0; duration: 2600 }
+ PauseAnimation { duration: 400 }
+ }
+ }
+ }
+}
diff --git a/src/declarative/extra/qmlgraphicsanimatedimageitem.cpp b/src/declarative/extra/qmlgraphicsanimatedimageitem.cpp
index 5dbffc0..f3c2058 100644
--- a/src/declarative/extra/qmlgraphicsanimatedimageitem.cpp
+++ b/src/declarative/extra/qmlgraphicsanimatedimageitem.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include <QMovie>
-#include <QtDeclarative/qmlcontext.h>
#include <QtDeclarative/qmlengine.h>
#include "qmlgraphicsanimatedimageitem_p.h"
#include "qmlgraphicsanimatedimageitem_p_p.h"
@@ -179,6 +178,14 @@ int QmlGraphicsAnimatedImageItem::frameCount() const
return d->_movie->frameCount();
}
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
void QmlGraphicsAnimatedImageItem::setSource(const QUrl &url)
{
Q_D(QmlGraphicsAnimatedImageItem);
@@ -193,15 +200,46 @@ void QmlGraphicsAnimatedImageItem::setSource(const QUrl &url)
d->reply = 0;
}
- d->url = qmlContext(this)->resolvedUrl(url);
+ d->url = url;
if (url.isEmpty()) {
delete d->_movie;
d->status = Null;
} else {
+#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+ //### should be unified with movieRequestFinished
+ d->_movie = new QMovie(lf);
+ if (!d->_movie->isValid()){
+ qWarning() << "Error Reading Animated Image File " << d->url;
+ delete d->_movie;
+ d->_movie = 0;
+ return;
+ }
+ connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
+ this, SLOT(playingStatusChanged()));
+ connect(d->_movie, SIGNAL(frameChanged(int)),
+ this, SLOT(movieUpdate()));
+ d->_movie->setCacheMode(QMovie::CacheAll);
+ if(d->playing)
+ d->_movie->start();
+ else
+ d->_movie->jumpToFrame(0);
+ if(d->paused)
+ d->_movie->setPaused(true);
+ d->setPixmap(d->_movie->currentPixmap());
+ d->status = Ready;
+ d->progress = 1.0;
+ emit statusChanged(d->status);
+ emit sourceChanged(d->url);
+ emit progressChanged(d->progress);
+ return;
+ }
+#endif
d->status = Loading;
QNetworkRequest req(d->url);
- d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
+ d->reply = qmlEngine(this)->networkAccessManager()->get(req);
QObject::connect(d->reply, SIGNAL(finished()),
this, SLOT(movieRequestFinished()));
}
@@ -230,13 +268,13 @@ void QmlGraphicsAnimatedImageItem::movieRequestFinished()
d->_movie->jumpToFrame(0);
if(d->paused)
d->_movie->setPaused(true);
- setPixmap(d->_movie->currentPixmap());
+ d->setPixmap(d->_movie->currentPixmap());
}
void QmlGraphicsAnimatedImageItem::movieUpdate()
{
Q_D(QmlGraphicsAnimatedImageItem);
- setPixmap(d->_movie->currentPixmap());
+ d->setPixmap(d->_movie->currentPixmap());
emit frameChanged();
}
diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
index 8895977..19c5abc 100644
--- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp
@@ -344,7 +344,7 @@ void QmlGraphicsFlickablePrivate::updateBeginningEnd()
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Flickable,QmlGraphicsFlickable)
/*!
- \qmlclass Flickable QFxFlickable
+ \qmlclass Flickable QmlGraphicsFlickable
\brief The Flickable item provides a surface that can be "flicked".
\inherits Item
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp b/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp
index d3ee184..a19e355 100644
--- a/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsfocuspanel.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,FocusPanel,QmlGraphicsFocusPanel)
/*!
- \qmlclass FocusPanel QFxFocusPanel
+ \qmlclass FocusPanel QmlGraphicsFocusPanel
\brief The FocusPanel item explicitly creates a focus panel.
\inherits Item
diff --git a/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp b/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp
index cd30b2b..f03e3f1 100644
--- a/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsfocusscope.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,FocusScope,QmlGraphicsFocusScope)
/*!
- \qmlclass FocusScope QFxFocusScope
+ \qmlclass FocusScope QmlGraphicsFocusScope
\brief The FocusScope object explicitly creates a focus scope.
\inherits Item
diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
index cadd650..1ee4511 100644
--- a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp
@@ -658,7 +658,7 @@ void QmlGraphicsGridViewPrivate::updateCurrent(int modelIndex)
//----------------------------------------------------------------------------
/*!
- \qmlclass GridView QFxGridView
+ \qmlclass GridView QmlGraphicsGridView
\inherits Flickable
\brief The GridView item provides a grid view of items provided by a model.
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage.cpp b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
index fd220a3..938fe2a 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimage.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsimage.cpp
@@ -152,12 +152,18 @@ void QmlGraphicsImage::setPixmap(const QPixmap &pix)
Q_D(QmlGraphicsImage);
if (!d->url.isEmpty())
return;
- d->pix = pix;
+ d->setPixmap(pix);
+}
+
+void QmlGraphicsImagePrivate::setPixmap(const QPixmap &pixmap)
+{
+ Q_Q(QmlGraphicsImage);
+ pix = pixmap;
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ q->setImplicitWidth(pix.width());
+ q->setImplicitHeight(pix.height());
- update();
+ q->update();
}
/*!
diff --git a/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h
index 62a4d1e..f6b4e51 100644
--- a/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h
+++ b/src/declarative/graphicsitems/qmlgraphicsimage_p_p.h
@@ -69,7 +69,7 @@ public:
}
QmlGraphicsImage::FillMode fillMode;
-
+ void setPixmap(const QPixmap &pix);
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
index 0e741c4..5083f43 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
@@ -2918,5 +2918,5 @@ QML_DECLARE_TYPE(QmlGraphicsKeysAttached)
QML_DECLARE_TYPEINFO(QmlGraphicsKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Keys,QmlGraphicsKeysAttached)
QML_DECLARE_TYPE(QmlGraphicsKeyNavigationAttached)
+QML_DECLARE_TYPEINFO(QmlGraphicsKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,KeyNavigation,QmlGraphicsKeyNavigationAttached)
-
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
index cf399f9..a393cb1 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -954,7 +954,7 @@ void QmlGraphicsListViewPrivate::flickY(qreal velocity)
//----------------------------------------------------------------------------
/*!
- \qmlclass ListView QFxListView
+ \qmlclass ListView QmlGraphicsListView
\inherits Flickable
\brief The ListView item provides a list view of items provided by a model.
diff --git a/src/declarative/graphicsitems/qmlgraphicsloader.cpp b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
index 65753d8..4d463ab 100644
--- a/src/declarative/graphicsitems/qmlgraphicsloader.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsloader.cpp
@@ -56,7 +56,7 @@ QmlGraphicsLoaderPrivate::~QmlGraphicsLoaderPrivate()
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Loader,QmlGraphicsLoader)
/*!
- \qmlclass Loader QFxLoader
+ \qmlclass Loader QmlGraphicsLoader
\inherits Item
\brief The Loader item allows dynamically loading an Item-based
diff --git a/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp
index 75e31b8..1a57062 100644
--- a/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp
@@ -120,7 +120,7 @@ void QmlGraphicsDrag::setYmax(qreal m)
}
/*!
- \qmlclass MouseRegion QFxMouseRegion
+ \qmlclass MouseRegion QmlGraphicsMouseRegion
\brief The MouseRegion item enables simple mouse handling.
\inherits Item
diff --git a/src/declarative/graphicsitems/qmlgraphicspath.cpp b/src/declarative/graphicsitems/qmlgraphicspath.cpp
index c0e6caf..ed0dfaa 100644
--- a/src/declarative/graphicsitems/qmlgraphicspath.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicspath.cpp
@@ -57,7 +57,7 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PathQuad,QmlGraphicsPathQuad)
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PathCubic,QmlGraphicsPathCubic)
/*!
- \qmlclass PathElement QFxPathElement
+ \qmlclass PathElement QmlGraphicsPathElement
\brief PathElement is the base path type.
This type is the base for all path types. It cannot
@@ -464,7 +464,7 @@ void QmlGraphicsCurve::setY(qreal y)
/****************************************************************************/
/*!
- \qmlclass PathAttribute QFxPathAttribute
+ \qmlclass PathAttribute QmlGraphicsPathAttribute
\brief The PathAttribute allows setting an attribute at a given position in a Path.
The PathAttribute object allows attibutes consisting of a name and
@@ -543,7 +543,7 @@ void QmlGraphicsPathAttribute::setValue(qreal value)
/****************************************************************************/
/*!
- \qmlclass PathLine QFxPathLine
+ \qmlclass PathLine QmlGraphicsPathLine
\brief The PathLine defines a straight line.
The example below creates a path consisting of a straight line from
@@ -583,7 +583,7 @@ void QmlGraphicsPathLine::addToPath(QPainterPath &path)
/****************************************************************************/
/*!
- \qmlclass PathQuad QFxPathQuad
+ \qmlclass PathQuad QmlGraphicsPathQuad
\brief The PathQuad defines a quadratic Bezier curve with a control point.
The following QML produces the path shown below:
@@ -667,7 +667,7 @@ void QmlGraphicsPathQuad::addToPath(QPainterPath &path)
/****************************************************************************/
/*!
- \qmlclass PathCubic QFxPathCubic
+ \qmlclass PathCubic QmlGraphicsPathCubic
\brief The PathCubic defines a cubic Bezier curve with two control points.
The following QML produces the path shown below:
@@ -777,7 +777,7 @@ void QmlGraphicsPathCubic::addToPath(QPainterPath &path)
/****************************************************************************/
/*!
- \qmlclass PathPercent QFxPathPercent
+ \qmlclass PathPercent QmlGraphicsPathPercent
\brief The PathPercent manipulates the way a path is interpreted.
The examples below show the normal distrubution of items along a path
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
index 52d2fa9..d2a9be1 100644
--- a/src/declarative/graphicsitems/qmlgraphicspathview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
@@ -97,7 +97,7 @@ private:
*/
/*!
- \qmlclass PathView QFxPathView
+ \qmlclass PathView QmlGraphicsPathView
\brief The PathView element lays out model-provided items on a path.
\inherits Item
diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
index ba696e7..f599025 100644
--- a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp
@@ -333,7 +333,7 @@ void QmlGraphicsBasePositioner::applyRemove(const QList<QPair<QString, QVariant>
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Column,QmlGraphicsColumn)
/*!
- \qmlclass Column QFxColumn
+ \qmlclass Column QmlGraphicsColumn
\brief The Column item lines up its children vertically.
\inherits Item
@@ -481,6 +481,11 @@ QmlGraphicsColumn::QmlGraphicsColumn(QmlGraphicsItem *parent)
{
}
+inline bool isInvisible(QmlGraphicsItem *child)
+{
+ return child->opacity() == 0.0 || !child->isVisible() || !child->width() || !child->height();
+}
+
void QmlGraphicsColumn::doPositioning()
{
int voffset = 0;
@@ -495,7 +500,7 @@ void QmlGraphicsColumn::doPositioning()
QList<QGraphicsItem *> children = childItems();
for (int ii = 0; ii < children.count(); ++ii) {
QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(ii));
- if (!child || child->opacity() == 0.0)
+ if (!child || isInvisible(child))
continue;
bool needMove = (child->y() != voffset || child->x());
@@ -519,7 +524,7 @@ void QmlGraphicsColumn::doPositioning()
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Row,QmlGraphicsRow)
/*!
- \qmlclass Row QFxRow
+ \qmlclass Row QmlGraphicsRow
\brief The Row item lines up its children horizontally.
\inherits Item
@@ -651,7 +656,7 @@ void QmlGraphicsRow::doPositioning()
QList<QGraphicsItem *> children = childItems();
for (int ii = 0; ii < children.count(); ++ii) {
QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(ii));
- if (!child || child->opacity() == 0.0)
+ if (!child || isInvisible(child))
continue;
bool needMove = (child->x() != hoffset || child->y());
@@ -668,10 +673,8 @@ void QmlGraphicsRow::doPositioning()
child->setX(hoffset);
setMovingItem(0);
}
- if(child->width() && child->height()){//don't advance for invisible children
- hoffset += child->width();
- hoffset += spacing();
- }
+ hoffset += child->width();
+ hoffset += spacing();
}
}
@@ -867,7 +870,7 @@ void QmlGraphicsGrid::doPositioning()
if (childIndex == children.count())
continue;
QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(children.at(childIndex++));
- if (!child || child->opacity() == 0.0)
+ if (!child || isInvisible(child))
continue;
if (child->width() > maxColWidth[j])
maxColWidth[j] = child->width();
@@ -888,7 +891,7 @@ void QmlGraphicsGrid::doPositioning()
}
foreach(QGraphicsItem* schild, children){
QmlGraphicsItem *child = qobject_cast<QmlGraphicsItem *>(schild);
- if (!child || child->opacity() == 0.0)
+ if (!child || isInvisible(child))
continue;
bool needMove = (child->x()!=xoffset)||(child->y()!=yoffset);
QList<QPair<QString, QVariant> > changes;
diff --git a/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp b/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp
index ba860e9..646374f 100644
--- a/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsrepeater.cpp
@@ -59,7 +59,7 @@ QmlGraphicsRepeaterPrivate::~QmlGraphicsRepeaterPrivate()
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Repeater,QmlGraphicsRepeater)
/*!
- \qmlclass Repeater QFxRepeater
+ \qmlclass Repeater QmlGraphicsRepeater
\inherits Item
\brief The Repeater item allows you to repeat a component based on a model.
diff --git a/src/declarative/graphicsitems/qmlgraphicstextedit.cpp b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
index 0c81dca..13df329 100644
--- a/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicstextedit.cpp
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,TextEdit,QmlGraphicsTextEdit)
/*!
- \qmlclass TextEdit QFxTextEdit
+ \qmlclass TextEdit QmlGraphicsTextEdit
\brief The TextEdit item allows you to add editable formatted text to a scene.
It can display both plain and rich text. For example:
diff --git a/src/declarative/graphicsitems/qmlgraphicstextinput.cpp b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
index 44ccda1..9a4f627 100644
--- a/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicstextinput.cpp
@@ -54,7 +54,7 @@ QML_DEFINE_NOCREATE_TYPE(QValidator);
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,QIntValidator,QIntValidator);
/*!
- \qmlclass TextInput QFxTextInput
+ \qmlclass TextInput QmlGraphicsTextInput
The TextInput item allows you to add an editable line of text to a scene.
TextInput can only display a single line of text, and can only display
diff --git a/src/declarative/graphicsitems/qmlgraphicswebview.cpp b/src/declarative/graphicsitems/qmlgraphicswebview.cpp
index c6ab4c7..d1da0f2 100644
--- a/src/declarative/graphicsitems/qmlgraphicswebview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicswebview.cpp
@@ -208,7 +208,7 @@ public:
};
/*!
- \qmlclass WebView QFxWebView
+ \qmlclass WebView QmlGraphicsWebView
\brief The WebView item allows you to add web content to a canvas.
\inherits Item
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index d37d959..f8e685a 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -88,18 +88,6 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject,
scripts.append(scope);
}
-void QmlContextPrivate::dump()
-{
- dump(0);
-}
-
-void QmlContextPrivate::dump(int depth)
-{
- QByteArray ba(depth * 4, ' ');
- if (parent)
- parent->d_func()->dump(depth + 1);
-}
-
void QmlContextPrivate::destroyed(ContextGuard *guard)
{
Q_Q(QmlContext);
@@ -382,8 +370,8 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value)
if (d->notifyIndex == -1)
d->notifyIndex = this->metaObject()->methodCount();
- if (QmlMetaType::isObject(value.userType())) {
- QObject *o = QmlMetaType::toQObject(value);
+ if (d->engine && QmlEnginePrivate::get(d->engine)->isObject(value.userType())) {
+ QObject *o = *(QObject **)value.constData();
setContextProperty(name, o);
} else {
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index cc8fcc6..7f9be0f 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -101,9 +101,6 @@ public:
void init();
- void dump();
- void dump(int depth);
-
void invalidateEngines();
void refreshExpressions();
QSet<QmlContext *> childContexts;
diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp
index 1713205..859a93a 100644
--- a/src/declarative/qml/qmlvaluetype.cpp
+++ b/src/declarative/qml/qmlvaluetype.cpp
@@ -521,6 +521,16 @@ void QmlFontValueType::setBold(bool b)
font.setBold(b);
}
+QmlFontValueType::FontWeight QmlFontValueType::weight() const
+{
+ return (QmlFontValueType::FontWeight)font.weight();
+}
+
+void QmlFontValueType::setWeight(QmlFontValueType::FontWeight w)
+{
+ font.setWeight((QFont::Weight)w);
+}
+
bool QmlFontValueType::italic() const
{
return font.italic();
@@ -541,6 +551,26 @@ void QmlFontValueType::setUnderline(bool b)
font.setUnderline(b);
}
+bool QmlFontValueType::overline() const
+{
+ return font.overline();
+}
+
+void QmlFontValueType::setOverline(bool b)
+{
+ font.setOverline(b);
+}
+
+bool QmlFontValueType::strikeout() const
+{
+ return font.strikeOut();
+}
+
+void QmlFontValueType::setStrikeout(bool b)
+{
+ font.setStrikeOut(b);
+}
+
qreal QmlFontValueType::pointSize() const
{
return font.pointSizeF();
@@ -566,4 +596,34 @@ void QmlFontValueType::setPixelSize(int size)
hasPixelSize = true;
}
+QmlFontValueType::Capitalization QmlFontValueType::capitalization() const
+{
+ return (QmlFontValueType::Capitalization)font.capitalization();
+}
+
+void QmlFontValueType::setCapitalization(QmlFontValueType::Capitalization c)
+{
+ font.setCapitalization((QFont::Capitalization)c);
+}
+
+qreal QmlFontValueType::letterSpacing() const
+{
+ return font.letterSpacing();
+}
+
+void QmlFontValueType::setLetterSpacing(qreal size)
+{
+ font.setLetterSpacing(QFont::PercentageSpacing, size);
+}
+
+qreal QmlFontValueType::wordSpacing() const
+{
+ return font.wordSpacing();
+}
+
+void QmlFontValueType::setWordSpacing(qreal size)
+{
+ font.setWordSpacing(size);
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h
index 9842c02..0af3813 100644
--- a/src/declarative/qml/qmlvaluetype_p.h
+++ b/src/declarative/qml/qmlvaluetype_p.h
@@ -258,13 +258,34 @@ private:
class QmlFontValueType : public QmlValueType
{
Q_OBJECT
+ Q_ENUMS(FontWeight)
+ Q_ENUMS(Capitalization)
+
Q_PROPERTY(QString family READ family WRITE setFamily)
Q_PROPERTY(bool bold READ bold WRITE setBold)
+ Q_PROPERTY(FontWeight weight READ weight WRITE setWeight)
Q_PROPERTY(bool italic READ italic WRITE setItalic)
Q_PROPERTY(bool underline READ underline WRITE setUnderline)
+ Q_PROPERTY(bool overline READ overline WRITE setOverline)
+ Q_PROPERTY(bool strikeout READ strikeout WRITE setStrikeout)
Q_PROPERTY(qreal pointSize READ pointSize WRITE setPointSize)
Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize)
+ Q_PROPERTY(Capitalization capitalization READ capitalization WRITE setCapitalization)
+ Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing)
+ Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing)
+
public:
+ enum FontWeight { Light = QFont::Light,
+ Normal = QFont::Normal,
+ DemiBold = QFont::DemiBold,
+ Bold = QFont::Bold,
+ Black = QFont::Black };
+ enum Capitalization { MixedCase = QFont::MixedCase,
+ AllUppercase = QFont::AllUppercase,
+ AllLowercase = QFont::AllLowercase,
+ SmallCaps = QFont::SmallCaps,
+ Capitalize = QFont::Capitalize };
+
QmlFontValueType(QObject *parent = 0);
virtual void read(QObject *, int);
@@ -278,18 +299,36 @@ public:
bool bold() const;
void setBold(bool b);
+ FontWeight weight() const;
+ void setWeight(FontWeight);
+
bool italic() const;
void setItalic(bool b);
bool underline() const;
void setUnderline(bool b);
+ bool overline() const;
+ void setOverline(bool b);
+
+ bool strikeout() const;
+ void setStrikeout(bool b);
+
qreal pointSize() const;
void setPointSize(qreal size);
int pixelSize() const;
void setPixelSize(int size);
+ Capitalization capitalization() const;
+ void setCapitalization(Capitalization);
+
+ qreal letterSpacing() const;
+ void setLetterSpacing(qreal spacing);
+
+ qreal wordSpacing() const;
+ void setWordSpacing(qreal spacing);
+
private:
QFont font;
bool hasPixelSize;
diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp
index f518ea5..2eb9dca 100644
--- a/src/declarative/util/qmlstategroup.cpp
+++ b/src/declarative/util/qmlstategroup.cpp
@@ -84,6 +84,34 @@ public:
void updateAutoState();
};
+/*!
+ \qmlclass StateGroup QmlStateGroup
+ \brief The StateGroup element provides state support for non-Item elements.
+
+ Item (and all dervied elements) provides built in support for states and transitions
+ via its state, states and transitions properties. StateGroup provides an easy way to
+ use this support in other (non-Item-derived) elements.
+
+ \qml
+ MyCustomObject {
+ StateGroup {
+ id: myStateGroup
+ states: State {
+ name: "state1"
+ ...
+ }
+ transitions: Transition {
+ ...
+ }
+ }
+
+ onSomethingHappened: myStateGroup.state = "state1";
+ }
+ \endqml
+
+ \sa {qmlstate}{States} and {state-transitions}{Transitions}
+*/
+
QmlStateGroup::QmlStateGroup(QObject *parent)
: QObject(*(new QmlStateGroupPrivate(this)), parent)
{
@@ -99,18 +127,75 @@ QList<QmlState *> QmlStateGroup::states() const
return d->states;
}
+/*!
+ \qmlproperty list<State> StateGroup::states
+ This property holds a list of states defined by the state group.
+
+ \qml
+ StateGroup {
+ states: [
+ State { ... },
+ State { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {qmlstate}{States}
+*/
QmlList<QmlState *>* QmlStateGroup::statesProperty()
{
Q_D(QmlStateGroup);
return &(d->states);
}
+/*!
+ \qmlproperty list<Transition> StateGroup::transitions
+ This property holds a list of transitions defined by the state group.
+
+ \qml
+ StateGroup {
+ transitions: [
+ Transition { ... },
+ Transition { ... }
+ ...
+ ]
+ }
+ \endqml
+
+ \sa {state-transitions}{Transitions}
+*/
QmlList<QmlTransition *>* QmlStateGroup::transitionsProperty()
{
Q_D(QmlStateGroup);
return &(d->transitions);
}
+/*!
+ \qmlproperty string StateGroup::state
+
+ This property holds the name of the current state of the state group.
+
+ This property is often used in scripts to change between states. For
+ example:
+
+ \qml
+ Script {
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
+ }
+ }
+ \endqml
+
+ If the state group is in its base state (i.e. no explicit state has been
+ set), \c state will be a blank string. Likewise, you can return a
+ state group to its base state by setting its current state to \c ''.
+
+ \sa {qmlstates}{States}
+*/
QString QmlStateGroup::state() const
{
Q_D(const QmlStateGroup);
diff --git a/src/declarative/util/qmltimer.cpp b/src/declarative/util/qmltimer.cpp
index 268d5ec..2e844be 100644
--- a/src/declarative/util/qmltimer.cpp
+++ b/src/declarative/util/qmltimer.cpp
@@ -57,12 +57,12 @@ public:
: interval(1000), running(false), repeating(false), triggeredOnStart(false)
, classBegun(false), componentComplete(false) {}
int interval;
- bool running;
- bool repeating;
- bool triggeredOnStart;
QPauseAnimation pause;
- bool classBegun;
- bool componentComplete;
+ bool running : 1;
+ bool repeating : 1;
+ bool triggeredOnStart : 1;
+ bool classBegun : 1;
+ bool componentComplete : 1;
};
/*!
@@ -82,6 +82,9 @@ public:
}
\endqml
+ QmlTimer is synchronized with the animation timer. Since the animation
+ timer is usually set to 60fps, the resolution of QmlTimer will be
+ at best 16ms.
*/
QmlTimer::QmlTimer(QObject *parent)
@@ -89,7 +92,6 @@ QmlTimer::QmlTimer(QObject *parent)
{
Q_D(QmlTimer);
connect(&d->pause, SIGNAL(currentLoopChanged(int)), this, SLOT(ticked()));
- connect(&d->pause, SIGNAL(finished()), this, SLOT(ticked()));
connect(&d->pause, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State))
, this, SLOT(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)));
d->pause.setLoopCount(1);
@@ -259,7 +261,9 @@ void QmlTimer::componentComplete()
*/
void QmlTimer::ticked()
{
- emit triggered();
+ Q_D(QmlTimer);
+ if (d->running)
+ emit triggered();
}
void QmlTimer::stateChanged(QAbstractAnimation::State, QAbstractAnimation::State state)
@@ -267,6 +271,7 @@ void QmlTimer::stateChanged(QAbstractAnimation::State, QAbstractAnimation::State
Q_D(QmlTimer);
if (d->running && state != QAbstractAnimation::Running) {
d->running = false;
+ emit triggered();
emit runningChanged();
}
}
diff --git a/tests/auto/declarative/animatedimage/tst_animatedimage.cpp b/tests/auto/declarative/animatedimage/tst_animatedimage.cpp
index f6141cb..6ae2112 100644
--- a/tests/auto/declarative/animatedimage/tst_animatedimage.cpp
+++ b/tests/auto/declarative/animatedimage/tst_animatedimage.cpp
@@ -61,34 +61,40 @@ private slots:
void tst_animatedimage::play()
{
- QmlGraphicsAnimatedImageItem anim;
- anim.setSource(QUrl("file://" SRCDIR "/data/stickman.gif"));
- QVERIFY(anim.isPlaying());
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl("file://" SRCDIR "/data/stickman.qml"));
+ QmlGraphicsAnimatedImageItem *anim = qobject_cast<QmlGraphicsAnimatedImageItem *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
}
void tst_animatedimage::pause()
{
- QmlGraphicsAnimatedImageItem anim;
- anim.setSource(QUrl("file://" SRCDIR "/data/stickman.gif"));
- anim.setPaused(true);
- QVERIFY(!anim.isPlaying());
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl("file://" SRCDIR "/data/stickmanpause.qml"));
+ QmlGraphicsAnimatedImageItem *anim = qobject_cast<QmlGraphicsAnimatedImageItem *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QVERIFY(anim->isPaused());
}
void tst_animatedimage::setFrame()
{
- QmlGraphicsAnimatedImageItem anim;
- anim.setSource(QUrl("file://" SRCDIR "/data/stickman.gif"));
- anim.setPaused(true);
- QVERIFY(!anim.isPlaying());
- anim.setCurrentFrame(2);
- QCOMPARE(anim.currentFrame(), 2);
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl("file://" SRCDIR "/data/stickmanpause.qml"));
+ QmlGraphicsAnimatedImageItem *anim = qobject_cast<QmlGraphicsAnimatedImageItem *>(component.create());
+ QVERIFY(anim);
+ QVERIFY(anim->isPlaying());
+ QCOMPARE(anim->currentFrame(), 2);
}
void tst_animatedimage::frameCount()
{
- QmlGraphicsAnimatedImageItem anim;
- anim.setSource(QUrl("file://" SRCDIR "/data/stickman.gif"));
- QCOMPARE(anim.frameCount(), 299);
+ QmlEngine engine;
+ QmlComponent component(&engine, QUrl("file://" SRCDIR "/data/stickman.qml"));
+ QmlGraphicsAnimatedImageItem *anim = qobject_cast<QmlGraphicsAnimatedImageItem *>(component.create());
+ QVERIFY(anim);
+ QCOMPARE(anim->frameCount(), 299);
}
QTEST_MAIN(tst_animatedimage)
diff --git a/tests/auto/declarative/behaviors/data/simple.qml b/tests/auto/declarative/behaviors/data/simple.qml
index a715f7b..37c3915 100644
--- a/tests/auto/declarative/behaviors/data/simple.qml
+++ b/tests/auto/declarative/behaviors/data/simple.qml
@@ -6,7 +6,10 @@ Rectangle {
id: rect
objectName: "MyRect"
width: 100; height: 100; color: "green"
- x: Behavior { NumberAnimation { duration: 200; } }
+ x: Behavior {
+ objectName: "MyBehavior";
+ NumberAnimation { duration: 200; }
+ }
}
MouseRegion {
id: clicker
diff --git a/tests/auto/declarative/behaviors/tst_behaviors.cpp b/tests/auto/declarative/behaviors/tst_behaviors.cpp
index 9803a9d..29c631d 100644
--- a/tests/auto/declarative/behaviors/tst_behaviors.cpp
+++ b/tests/auto/declarative/behaviors/tst_behaviors.cpp
@@ -43,6 +43,7 @@
#include <QtDeclarative/qmlcomponent.h>
#include <QtDeclarative/qmlview.h>
#include <private/qmlgraphicsrectangle_p.h>
+#include <private/qmlbehavior_p.h>
#include <private/qmlanimation_p.h>
class tst_behaviors : public QObject
@@ -60,6 +61,9 @@ private slots:
void replaceBinding();
//void transitionOverrides();
void group();
+ void emptyBehavior();
+ void nonSelectingBehavior();
+ void reassignedAnimation();
};
void tst_behaviors::simpleBehavior()
@@ -68,6 +72,7 @@ void tst_behaviors::simpleBehavior()
QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/simple.qml"));
QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
QVERIFY(rect);
+ QVERIFY(qobject_cast<QmlBehavior*>(rect->findChild<QmlBehavior*>("MyBehavior"))->animation());
rect->setState("moved");
QTest::qWait(100);
@@ -189,6 +194,44 @@ void tst_behaviors::group()
}
}
+void tst_behaviors::emptyBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/empty.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+}
+
+void tst_behaviors::nonSelectingBehavior()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/nonSelecting.qml"));
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //should change immediately
+}
+
+void tst_behaviors::reassignedAnimation()
+{
+ QmlEngine engine;
+ QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/reassignedAnimation.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QML QmlBehavior (file://" SRCDIR "/data/reassignedAnimation.qml:9:12) Can't change the animation assigned to a Behavior.");
+ QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(c.create());
+ QVERIFY(rect);
+
+ rect->setState("moved");
+ QTest::qWait(200 + 100);
+ qreal x = qobject_cast<QmlGraphicsRectangle*>(rect->findChild<QmlGraphicsRectangle*>("MyRect"))->x();
+ QCOMPARE(x, qreal(200)); //i.e. the right behavior has been triggered
+}
+
QTEST_MAIN(tst_behaviors)
#include "tst_behaviors.moc"
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 40cdb58..0d55391 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -15,6 +15,7 @@ SUBDIRS += anchors \
qfxtextedit \
qfxtextinput \
qfxwebview \
+ qmetaobjectbuilder \
qmlcontext \
qmldom \
qmlecmascript \
diff --git a/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro b/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro
new file mode 100644
index 0000000..94ffe4b
--- /dev/null
+++ b/tests/auto/declarative/qmetaobjectbuilder/qmetaobjectbuilder.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += \
+ tst_qmetaobjectbuilder.cpp
+
diff --git a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..9beec17
--- /dev/null
+++ b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -0,0 +1,1059 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qlocale.h>
+#include <private/qmetaobjectbuilder_p.h>
+
+class tst_QMetaObjectBuilder : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMetaObjectBuilder() {}
+ ~tst_QMetaObjectBuilder() {}
+
+private slots:
+ void mocVersionCheck();
+ void create();
+ void className();
+ void superClass();
+ void method();
+ void slot();
+ void signal();
+ void constructor();
+ void property();
+ void notifySignal();
+ void enumerator();
+ void classInfo();
+ void relatedMetaObject();
+ void staticMetacall();
+ void copyMetaObject();
+ void serialize();
+
+private:
+ static bool checkForSideEffects
+ (const QMetaObjectBuilder& builder,
+ QMetaObjectBuilder::AddMembers members);
+ static bool sameMetaObject
+ (const QMetaObject *meta1, const QMetaObject *meta2);
+};
+
+void tst_QMetaObjectBuilder::mocVersionCheck()
+{
+ // This test will fail when the moc version number is changed.
+ // It is intended as a reminder to also update QMetaObjectBuilder
+ // whenenver moc changes. Once QMetaObjectBuilder has been
+ // updated, this test can be changed to check for the next version.
+ QCOMPARE(int(QObject::staticMetaObject.d.data[0]), 4);
+ QCOMPARE(int(staticMetaObject.d.data[0]), 4);
+}
+
+void tst_QMetaObjectBuilder::create()
+{
+ QMetaObjectBuilder builder;
+ QVERIFY(builder.className().isEmpty());
+ QVERIFY(builder.superClass() == &QObject::staticMetaObject);
+ QCOMPARE(builder.methodCount(), 0);
+ QCOMPARE(builder.constructorCount(), 0);
+ QCOMPARE(builder.propertyCount(), 0);
+ QCOMPARE(builder.enumeratorCount(), 0);
+ QCOMPARE(builder.classInfoCount(), 0);
+ QCOMPARE(builder.relatedMetaObjectCount(), 0);
+ QVERIFY(builder.staticMetacallFunction() == 0);
+}
+
+void tst_QMetaObjectBuilder::className()
+{
+ QMetaObjectBuilder builder;
+
+ // Change the class name.
+ builder.setClassName("Foo");
+ QCOMPARE(builder.className(), QByteArray("Foo"));
+
+ // Change it again.
+ builder.setClassName("Bar");
+ QCOMPARE(builder.className(), QByteArray("Bar"));
+
+ // Clone the class name off a static QMetaObject.
+ builder.addMetaObject(&QObject::staticMetaObject, QMetaObjectBuilder::ClassName);
+ QCOMPARE(builder.className(), QByteArray("QObject"));
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::ClassName));
+}
+
+void tst_QMetaObjectBuilder::superClass()
+{
+ QMetaObjectBuilder builder;
+
+ // Change the super class.
+ builder.setSuperClass(&QObject::staticMetaObject);
+ QVERIFY(builder.superClass() == &QObject::staticMetaObject);
+
+ // Change it again.
+ builder.setSuperClass(&staticMetaObject);
+ QVERIFY(builder.superClass() == &staticMetaObject);
+
+ // Clone the super class off a static QMetaObject.
+ builder.addMetaObject(&QObject::staticMetaObject, QMetaObjectBuilder::SuperClass);
+ QVERIFY(builder.superClass() == 0);
+ builder.addMetaObject(&staticMetaObject, QMetaObjectBuilder::SuperClass);
+ QVERIFY(builder.superClass() == staticMetaObject.superClass());
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::SuperClass));
+}
+
+void tst_QMetaObjectBuilder::method()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a method and check its attributes.
+ QMetaMethodBuilder method1 = builder.addMethod("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Public);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another method and check again.
+ QMetaMethodBuilder method2 = builder.addMethod("bar(QString)");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfMethod("foo(const QString&, int)"), 0);
+ QCOMPARE(builder.indexOfMethod("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfMethod("baz()"), -1);
+
+ // Modify the attributes on method1.
+ method1.setReturnType("int");
+ method1.setParameterNames(QList<QByteArray>() << "a" << "b");
+ method1.setTag("tag");
+ method1.setAccess(QMetaMethod::Private);
+ method1.setAttributes(42);
+
+ // Check that method1 is changed, but method2 is not.
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(method1.tag(), QByteArray("tag"));
+ QVERIFY(method1.access() == QMetaMethod::Private);
+ QCOMPARE(method1.attributes(), 42);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Modify the attributes on method2.
+ method2.setReturnType("QString");
+ method2.setParameterNames(QList<QByteArray>() << "c");
+ method2.setTag("Q_FOO");
+ method2.setAccess(QMetaMethod::Protected);
+ method2.setAttributes(24);
+
+ // This time check that only method2 changed.
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Method);
+ QCOMPARE(method1.returnType(), QByteArray("int"));
+ QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(method1.tag(), QByteArray("tag"));
+ QVERIFY(method1.access() == QMetaMethod::Private);
+ QCOMPARE(method1.attributes(), 42);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 24);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Remove method1 and check that method2 becomes index 0.
+ builder.removeMethod(0);
+ QCOMPARE(builder.methodCount(), 1);
+ method2 = builder.method(0);
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Method);
+ QCOMPARE(method2.returnType(), QByteArray("QString"));
+ QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 24);
+ QCOMPARE(method2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfMethod("foo(const QString&, int)"), -1);
+ QCOMPARE(builder.indexOfMethod("bar(QString)"), 0);
+ QCOMPARE(builder.indexOfMethod("baz()"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::slot()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a slot and check its attributes.
+ QMetaMethodBuilder method1 = builder.addSlot("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Slot);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Public);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another slot and check again.
+ QMetaMethodBuilder method2 = builder.addSlot("bar(QString)");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Slot);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Public);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::signal()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a signal and check its attributes.
+ QMetaMethodBuilder method1 = builder.addSignal("foo(const QString&, int)");
+ QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(method1.methodType() == QMetaMethod::Signal);
+ QVERIFY(method1.returnType().isEmpty());
+ QVERIFY(method1.parameterNames().isEmpty());
+ QVERIFY(method1.tag().isEmpty());
+ QVERIFY(method1.access() == QMetaMethod::Protected);
+ QCOMPARE(method1.attributes(), 0);
+ QCOMPARE(method1.index(), 0);
+ QCOMPARE(builder.methodCount(), 1);
+
+ // Add another signal and check again.
+ QMetaMethodBuilder method2 = builder.addSignal("bar(QString)");
+ QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(method2.methodType() == QMetaMethod::Signal);
+ QVERIFY(method2.returnType().isEmpty());
+ QVERIFY(method2.parameterNames().isEmpty());
+ QVERIFY(method2.tag().isEmpty());
+ QVERIFY(method2.access() == QMetaMethod::Protected);
+ QCOMPARE(method2.attributes(), 0);
+ QCOMPARE(method2.index(), 1);
+ QCOMPARE(builder.methodCount(), 2);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Methods));
+}
+
+void tst_QMetaObjectBuilder::constructor()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a constructor and check its attributes.
+ QMetaMethodBuilder ctor1 = builder.addConstructor("foo(const QString&, int)");
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor1.returnType().isEmpty());
+ QVERIFY(ctor1.parameterNames().isEmpty());
+ QVERIFY(ctor1.tag().isEmpty());
+ QVERIFY(ctor1.access() == QMetaMethod::Public);
+ QCOMPARE(ctor1.attributes(), 0);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(builder.constructorCount(), 1);
+
+ // Add another constructor and check again.
+ QMetaMethodBuilder ctor2 = builder.addConstructor("bar(QString)");
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor2.returnType().isEmpty());
+ QVERIFY(ctor2.parameterNames().isEmpty());
+ QVERIFY(ctor2.tag().isEmpty());
+ QVERIFY(ctor2.access() == QMetaMethod::Public);
+ QCOMPARE(ctor2.attributes(), 0);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfConstructor("foo(const QString&, int)"), 0);
+ QCOMPARE(builder.indexOfConstructor("bar(QString)"), 1);
+ QCOMPARE(builder.indexOfConstructor("baz()"), -1);
+
+ // Modify the attributes on ctor1.
+ ctor1.setReturnType("int");
+ ctor1.setParameterNames(QList<QByteArray>() << "a" << "b");
+ ctor1.setTag("tag");
+ ctor1.setAccess(QMetaMethod::Private);
+ ctor1.setAttributes(42);
+
+ // Check that ctor1 is changed, but ctor2 is not.
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(ctor1.tag(), QByteArray("tag"));
+ QVERIFY(ctor1.access() == QMetaMethod::Private);
+ QCOMPARE(ctor1.attributes(), 42);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QVERIFY(ctor2.returnType().isEmpty());
+ QVERIFY(ctor2.parameterNames().isEmpty());
+ QVERIFY(ctor2.tag().isEmpty());
+ QVERIFY(ctor2.access() == QMetaMethod::Public);
+ QCOMPARE(ctor2.attributes(), 0);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Modify the attributes on ctor2.
+ ctor2.setReturnType("QString");
+ ctor2.setParameterNames(QList<QByteArray>() << "c");
+ ctor2.setTag("Q_FOO");
+ ctor2.setAccess(QMetaMethod::Protected);
+ ctor2.setAttributes(24);
+
+ // This time check that only ctor2 changed.
+ QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
+ QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor1.returnType(), QByteArray("int"));
+ QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
+ QCOMPARE(ctor1.tag(), QByteArray("tag"));
+ QVERIFY(ctor1.access() == QMetaMethod::Private);
+ QCOMPARE(ctor1.attributes(), 42);
+ QCOMPARE(ctor1.index(), 0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(ctor2.access() == QMetaMethod::Protected);
+ QCOMPARE(ctor2.attributes(), 24);
+ QCOMPARE(ctor2.index(), 1);
+ QCOMPARE(builder.constructorCount(), 2);
+
+ // Remove ctor1 and check that ctor2 becomes index 0.
+ builder.removeConstructor(0);
+ QCOMPARE(builder.constructorCount(), 1);
+ ctor2 = builder.constructor(0);
+ QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
+ QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
+ QCOMPARE(ctor2.returnType(), QByteArray("QString"));
+ QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
+ QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
+ QVERIFY(ctor2.access() == QMetaMethod::Protected);
+ QCOMPARE(ctor2.attributes(), 24);
+ QCOMPARE(ctor2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfConstructor("foo(const QString&, int)"), -1);
+ QCOMPARE(builder.indexOfConstructor("bar(QString)"), 0);
+ QCOMPARE(builder.indexOfConstructor("baz()"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Constructors));
+}
+
+void tst_QMetaObjectBuilder::property()
+{
+ QMetaObjectBuilder builder;
+
+ // Add a property and check its attributes.
+ QMetaPropertyBuilder prop1 = builder.addProperty("foo", "const QString &");
+ QCOMPARE(prop1.name(), QByteArray("foo"));
+ QCOMPARE(prop1.type(), QByteArray("QString"));
+ QVERIFY(!prop1.hasNotifySignal());
+ QVERIFY(prop1.isReadable());
+ QVERIFY(prop1.isWritable());
+ QVERIFY(!prop1.isResettable());
+ QVERIFY(!prop1.isDesignable());
+ QVERIFY(!prop1.isScriptable());
+ QVERIFY(!prop1.isStored());
+ QVERIFY(!prop1.isEditable());
+ QVERIFY(!prop1.isUser());
+ QVERIFY(!prop1.hasStdCppSet());
+ QVERIFY(!prop1.isEnumOrFlag());
+ QCOMPARE(prop1.index(), 0);
+ QCOMPARE(builder.propertyCount(), 1);
+
+ // Add another property and check again.
+ QMetaPropertyBuilder prop2 = builder.addProperty("bar", "int");
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.hasNotifySignal());
+ QVERIFY(prop2.isReadable());
+ QVERIFY(prop2.isWritable());
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+ QCOMPARE(prop2.index(), 1);
+ QCOMPARE(builder.propertyCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfProperty("foo"), 0);
+ QCOMPARE(builder.indexOfProperty("bar"), 1);
+ QCOMPARE(builder.indexOfProperty("baz"), -1);
+
+ // Modify the attributes on prop1.
+ prop1.setReadable(false);
+ prop1.setWritable(false);
+ prop1.setResettable(true);
+ prop1.setDesignable(true);
+ prop1.setScriptable(true);
+ prop1.setStored(true);
+ prop1.setEditable(true);
+ prop1.setUser(true);
+ prop1.setStdCppSet(true);
+ prop1.setEnumOrFlag(true);
+
+ // Check that prop1 is changed, but prop2 is not.
+ QCOMPARE(prop1.name(), QByteArray("foo"));
+ QCOMPARE(prop1.type(), QByteArray("QString"));
+ QVERIFY(!prop1.isReadable());
+ QVERIFY(!prop1.isWritable());
+ QVERIFY(prop1.isResettable());
+ QVERIFY(prop1.isDesignable());
+ QVERIFY(prop1.isScriptable());
+ QVERIFY(prop1.isStored());
+ QVERIFY(prop1.isEditable());
+ QVERIFY(prop1.isUser());
+ QVERIFY(prop1.hasStdCppSet());
+ QVERIFY(prop1.isEnumOrFlag());
+ QVERIFY(prop2.isReadable());
+ QVERIFY(prop2.isWritable());
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+
+ // Remove prop1 and check that prop2 becomes index 0.
+ builder.removeProperty(0);
+ QCOMPARE(builder.propertyCount(), 1);
+ prop2 = builder.property(0);
+ QCOMPARE(prop2.name(), QByteArray("bar"));
+ QCOMPARE(prop2.type(), QByteArray("int"));
+ QVERIFY(!prop2.isResettable());
+ QVERIFY(!prop2.isDesignable());
+ QVERIFY(!prop2.isScriptable());
+ QVERIFY(!prop2.isStored());
+ QVERIFY(!prop2.isEditable());
+ QVERIFY(!prop2.isUser());
+ QVERIFY(!prop2.hasStdCppSet());
+ QVERIFY(!prop2.isEnumOrFlag());
+ QCOMPARE(prop2.index(), 0);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfProperty("foo"), -1);
+ QCOMPARE(builder.indexOfProperty("bar"), 0);
+ QCOMPARE(builder.indexOfProperty("baz"), -1);
+
+ // Check for side-effects between the flags on prop2.
+ // Setting a flag to true shouldn't set any of the others to true.
+ // This checks for cut-and-paste bugs in the implementation where
+ // the flag code was pasted but the flag name was not changed.
+#define CLEAR_FLAGS() \
+ do { \
+ prop2.setReadable(false); \
+ prop2.setWritable(false); \
+ prop2.setResettable(false); \
+ prop2.setDesignable(false); \
+ prop2.setScriptable(false); \
+ prop2.setStored(false); \
+ prop2.setEditable(false); \
+ prop2.setUser(false); \
+ prop2.setStdCppSet(false); \
+ prop2.setEnumOrFlag(false); \
+ } while (0)
+#define COUNT_FLAGS() \
+ ((prop2.isReadable() ? 1 : 0) + \
+ (prop2.isWritable() ? 1 : 0) + \
+ (prop2.isResettable() ? 1 : 0) + \
+ (prop2.isDesignable() ? 1 : 0) + \
+ (prop2.isScriptable() ? 1 : 0) + \
+ (prop2.isStored() ? 1 : 0) + \
+ (prop2.isEditable() ? 1 : 0) + \
+ (prop2.isUser() ? 1 : 0) + \
+ (prop2.hasStdCppSet() ? 1 : 0) + \
+ (prop2.isEnumOrFlag() ? 1 : 0))
+#define CHECK_FLAG(setFunc,isFunc) \
+ do { \
+ CLEAR_FLAGS(); \
+ QCOMPARE(COUNT_FLAGS(), 0); \
+ prop2.setFunc(true); \
+ QVERIFY(prop2.isFunc()); \
+ QCOMPARE(COUNT_FLAGS(), 1); \
+ } while (0)
+ CHECK_FLAG(setReadable, isReadable);
+ CHECK_FLAG(setWritable, isWritable);
+ CHECK_FLAG(setResettable, isResettable);
+ CHECK_FLAG(setDesignable, isDesignable);
+ CHECK_FLAG(setScriptable, isScriptable);
+ CHECK_FLAG(setStored, isStored);
+ CHECK_FLAG(setEditable, isEditable);
+ CHECK_FLAG(setUser, isUser);
+ CHECK_FLAG(setStdCppSet, hasStdCppSet);
+ CHECK_FLAG(setEnumOrFlag, isEnumOrFlag);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Properties));
+}
+
+void tst_QMetaObjectBuilder::notifySignal()
+{
+ QMetaObjectBuilder builder;
+
+ QMetaPropertyBuilder prop = builder.addProperty("foo", "const QString &");
+ builder.addSlot("setFoo(QString)");
+ QMetaMethodBuilder notify = builder.addSignal("fooChanged(QString)");
+
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ prop.setNotifySignal(notify);
+ QVERIFY(prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 1);
+
+ prop.setNotifySignal(QMetaMethodBuilder());
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ prop.setNotifySignal(notify);
+ prop.removeNotifySignal();
+ QVERIFY(!prop.hasNotifySignal());
+ QCOMPARE(prop.notifySignal().index(), 0);
+
+ QCOMPARE(builder.methodCount(), 2);
+ QCOMPARE(builder.propertyCount(), 1);
+
+ // Check that nothing else changed except methods and properties.
+ QVERIFY(checkForSideEffects
+ (builder, QMetaObjectBuilder::Methods | QMetaObjectBuilder::Properties));
+}
+
+void tst_QMetaObjectBuilder::enumerator()
+{
+ QMetaObjectBuilder builder;
+
+ // Add an enumerator and check its attributes.
+ QMetaEnumBuilder enum1 = builder.addEnumerator("foo");
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(!enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 0);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(builder.enumeratorCount(), 1);
+
+ // Add another enumerator and check again.
+ QMetaEnumBuilder enum2 = builder.addEnumerator("bar");
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(!enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 0);
+ QCOMPARE(enum2.index(), 1);
+ QCOMPARE(builder.enumeratorCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfEnumerator("foo"), 0);
+ QCOMPARE(builder.indexOfEnumerator("bar"), 1);
+ QCOMPARE(builder.indexOfEnumerator("baz"), -1);
+
+ // Modify the attributes on enum1.
+ enum1.setIsFlag(true);
+ QCOMPARE(enum1.addKey("ABC", 0), 0);
+ QCOMPARE(enum1.addKey("DEF", 1), 1);
+ QCOMPARE(enum1.addKey("GHI", -1), 2);
+
+ // Check that enum1 is changed, but enum2 is not.
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 3);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(enum1.key(0), QByteArray("ABC"));
+ QCOMPARE(enum1.key(1), QByteArray("DEF"));
+ QCOMPARE(enum1.key(2), QByteArray("GHI"));
+ QCOMPARE(enum1.value(0), 0);
+ QCOMPARE(enum1.value(1), 1);
+ QCOMPARE(enum1.value(2), -1);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(!enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 0);
+ QCOMPARE(enum2.index(), 1);
+
+ // Modify the attributes on enum2.
+ enum2.setIsFlag(true);
+ QCOMPARE(enum2.addKey("XYZ", 10), 0);
+ QCOMPARE(enum2.addKey("UVW", 19), 1);
+
+ // This time check that only method2 changed.
+ QCOMPARE(enum1.name(), QByteArray("foo"));
+ QVERIFY(enum1.isFlag());
+ QCOMPARE(enum1.keyCount(), 3);
+ QCOMPARE(enum1.index(), 0);
+ QCOMPARE(enum1.key(0), QByteArray("ABC"));
+ QCOMPARE(enum1.key(1), QByteArray("DEF"));
+ QCOMPARE(enum1.key(2), QByteArray("GHI"));
+ QCOMPARE(enum1.value(0), 0);
+ QCOMPARE(enum1.value(1), 1);
+ QCOMPARE(enum1.value(2), -1);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 2);
+ QCOMPARE(enum2.index(), 1);
+ QCOMPARE(enum2.key(0), QByteArray("XYZ"));
+ QCOMPARE(enum2.key(1), QByteArray("UVW"));
+ QCOMPARE(enum2.value(0), 10);
+ QCOMPARE(enum2.value(1), 19);
+
+ // Remove enum1 and check that enum2 becomes index 0.
+ builder.removeEnumerator(0);
+ QCOMPARE(builder.enumeratorCount(), 1);
+ enum2 = builder.enumerator(0);
+ QCOMPARE(enum2.name(), QByteArray("bar"));
+ QVERIFY(enum2.isFlag());
+ QCOMPARE(enum2.keyCount(), 2);
+ QCOMPARE(enum2.index(), 0);
+ QCOMPARE(enum2.key(0), QByteArray("XYZ"));
+ QCOMPARE(enum2.key(1), QByteArray("UVW"));
+ QCOMPARE(enum2.value(0), 10);
+ QCOMPARE(enum2.value(1), 19);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfEnumerator("foo"), -1);
+ QCOMPARE(builder.indexOfEnumerator("bar"), 0);
+ QCOMPARE(builder.indexOfEnumerator("baz"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Enumerators));
+}
+
+void tst_QMetaObjectBuilder::classInfo()
+{
+ QMetaObjectBuilder builder;
+
+ // Add two items of class information and check their attributes.
+ QCOMPARE(builder.addClassInfo("foo", "value1"), 0);
+ QCOMPARE(builder.addClassInfo("bar", "value2"), 1);
+ QCOMPARE(builder.classInfoName(0), QByteArray("foo"));
+ QCOMPARE(builder.classInfoValue(0), QByteArray("value1"));
+ QCOMPARE(builder.classInfoName(1), QByteArray("bar"));
+ QCOMPARE(builder.classInfoValue(1), QByteArray("value2"));
+ QCOMPARE(builder.classInfoCount(), 2);
+
+ // Perform index-based lookup.
+ QCOMPARE(builder.indexOfClassInfo("foo"), 0);
+ QCOMPARE(builder.indexOfClassInfo("bar"), 1);
+ QCOMPARE(builder.indexOfClassInfo("baz"), -1);
+
+ // Remove the first one and check again.
+ builder.removeClassInfo(0);
+ QCOMPARE(builder.classInfoName(0), QByteArray("bar"));
+ QCOMPARE(builder.classInfoValue(0), QByteArray("value2"));
+ QCOMPARE(builder.classInfoCount(), 1);
+
+ // Perform index-based lookup again.
+ QCOMPARE(builder.indexOfClassInfo("foo"), -1);
+ QCOMPARE(builder.indexOfClassInfo("bar"), 0);
+ QCOMPARE(builder.indexOfClassInfo("baz"), -1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::ClassInfos));
+}
+
+void tst_QMetaObjectBuilder::relatedMetaObject()
+{
+ QMetaObjectBuilder builder;
+
+ // Add two related meta objects and check their attributes.
+ QCOMPARE(builder.addRelatedMetaObject(&QObject::staticMetaObject), 0);
+ QCOMPARE(builder.addRelatedMetaObject(&staticMetaObject), 1);
+ QVERIFY(builder.relatedMetaObject(0) == &QObject::staticMetaObject);
+ QVERIFY(builder.relatedMetaObject(1) == &staticMetaObject);
+ QCOMPARE(builder.relatedMetaObjectCount(), 2);
+
+ // Remove the first one and check again.
+ builder.removeRelatedMetaObject(0);
+ QVERIFY(builder.relatedMetaObject(0) == &staticMetaObject);
+ QCOMPARE(builder.relatedMetaObjectCount(), 1);
+
+ // Check that nothing else changed.
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::RelatedMetaObjects));
+}
+
+static int smetacall(QMetaObject::Call, int, void **)
+{
+ return 0;
+}
+
+void tst_QMetaObjectBuilder::staticMetacall()
+{
+ QMetaObjectBuilder builder;
+ QVERIFY(!builder.staticMetacallFunction());
+ builder.setStaticMetacallFunction(smetacall);
+ QVERIFY(builder.staticMetacallFunction() == smetacall);
+ QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::StaticMetacall));
+}
+
+// Dummy class that has something of every type of thing moc can generate.
+class SomethingOfEverything : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("ci_foo", "ABC")
+ Q_CLASSINFO("ci_bar", "DEF")
+ Q_PROPERTY(QString prop READ prop WRITE setProp NOTIFY propChanged)
+ Q_PROPERTY(QString prop2 READ prop WRITE setProp)
+ Q_PROPERTY(SomethingEnum eprop READ eprop)
+ Q_PROPERTY(SomethingFlagEnum fprop READ fprop)
+ Q_PROPERTY(QLocale::Language language READ language)
+ Q_ENUMS(SomethingEnum)
+ Q_FLAGS(SomethingFlagEnum)
+public:
+ Q_INVOKABLE SomethingOfEverything() {}
+ ~SomethingOfEverything() {}
+
+ enum SomethingEnum
+ {
+ GHI,
+ JKL = 10
+ };
+
+ enum SomethingFlagEnum
+ {
+ XYZ = 1,
+ UVW = 8
+ };
+
+ Q_INVOKABLE Q_SCRIPTABLE void method1() {}
+
+ QString prop() const { return QString(); }
+ void setProp(const QString& v) { Q_UNUSED(v); }
+
+ SomethingOfEverything::SomethingEnum eprop() const { return GHI; }
+ SomethingOfEverything::SomethingFlagEnum fprop() const { return XYZ; }
+ QLocale::Language language() const { return QLocale::English; }
+
+public slots:
+ void slot1(const QString&) {}
+ void slot2(int, const QString&) {}
+
+private slots:
+ void slot3() {}
+
+protected slots:
+ Q_SCRIPTABLE void slot4(int) {}
+ void slot5(int a, const QString& b) { Q_UNUSED(a); Q_UNUSED(b); }
+
+signals:
+ void sig1();
+ void sig2(int x, const QString& y);
+ void propChanged(const QString&);
+};
+
+// Copy the entire contents of a static QMetaObject and then check
+// that QMetaObjectBuilder will produce an exact copy as output.
+void tst_QMetaObjectBuilder::copyMetaObject()
+{
+ QMetaObjectBuilder builder(&QObject::staticMetaObject);
+ QMetaObject *meta = builder.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &QObject::staticMetaObject));
+ qFree(meta);
+
+ QMetaObjectBuilder builder2(&staticMetaObject);
+ meta = builder2.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &staticMetaObject));
+ qFree(meta);
+
+ QMetaObjectBuilder builder3(&SomethingOfEverything::staticMetaObject);
+ meta = builder3.toMetaObject();
+ QVERIFY(sameMetaObject(meta, &SomethingOfEverything::staticMetaObject));
+ qFree(meta);
+}
+
+// Serialize and deserialize a meta object and check that
+// it round-trips to the exact same value.
+void tst_QMetaObjectBuilder::serialize()
+{
+ QMetaObjectBuilder builder(&SomethingOfEverything::staticMetaObject);
+ QMetaObject *meta = builder.toMetaObject();
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly | QIODevice::Append);
+ builder.serialize(stream);
+
+ QMetaObjectBuilder builder2;
+ QDataStream stream2(data);
+ QMap<QByteArray, const QMetaObject *> references;
+ references.insert(QByteArray("QLocale"), &QLocale::staticMetaObject);
+ builder2.deserialize(stream2, references);
+ builder2.setStaticMetacallFunction(builder.staticMetacallFunction());
+ QMetaObject *meta2 = builder2.toMetaObject();
+
+ QVERIFY(sameMetaObject(meta, meta2));
+ qFree(meta);
+ qFree(meta2);
+}
+
+// Check that the only changes to a "builder" relative to the default
+// state is specified by "members".
+bool tst_QMetaObjectBuilder::checkForSideEffects
+ (const QMetaObjectBuilder& builder,
+ QMetaObjectBuilder::AddMembers members)
+{
+ if ((members & QMetaObjectBuilder::ClassName) == 0) {
+ if (!builder.className().isEmpty())
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::SuperClass) == 0) {
+ if (builder.superClass() != &QObject::staticMetaObject)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Methods) == 0) {
+ if (builder.methodCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Constructors) == 0) {
+ if (builder.constructorCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Properties) == 0) {
+ if (builder.propertyCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::Enumerators) == 0) {
+ if (builder.enumeratorCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::ClassInfos) == 0) {
+ if (builder.classInfoCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::RelatedMetaObjects) == 0) {
+ if (builder.relatedMetaObjectCount() != 0)
+ return false;
+ }
+
+ if ((members & QMetaObjectBuilder::StaticMetacall) == 0) {
+ if (builder.staticMetacallFunction() != 0)
+ return false;
+ }
+
+ return true;
+}
+
+static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
+{
+ if (QByteArray(method1.signature()) != QByteArray(method2.signature()))
+ return false;
+
+ if (QByteArray(method1.typeName()) != QByteArray(method2.typeName()))
+ return false;
+
+ if (method1.parameterNames() != method2.parameterNames())
+ return false;
+
+ if (QByteArray(method1.tag()) != QByteArray(method2.tag()))
+ return false;
+
+ if (method1.access() != method2.access())
+ return false;
+
+ if (method1.methodType() != method2.methodType())
+ return false;
+
+ if (method1.attributes() != method2.attributes())
+ return false;
+
+ return true;
+}
+
+static bool sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
+{
+ if (QByteArray(prop1.name()) != QByteArray(prop2.name()))
+ return false;
+
+ if (QByteArray(prop1.typeName()) != QByteArray(prop2.typeName()))
+ return false;
+
+ if (prop1.isReadable() != prop2.isReadable() ||
+ prop1.isWritable() != prop2.isWritable() ||
+ prop1.isResettable() != prop2.isResettable() ||
+ prop1.isDesignable() != prop2.isDesignable() ||
+ prop1.isScriptable() != prop2.isScriptable() ||
+ prop1.isStored() != prop2.isStored() ||
+ prop1.isEditable() != prop2.isEditable() ||
+ prop1.isUser() != prop2.isUser() ||
+ prop1.isFlagType() != prop2.isFlagType() ||
+ prop1.isEnumType() != prop2.isEnumType() ||
+ prop1.hasNotifySignal() != prop2.hasNotifySignal() ||
+ prop1.hasStdCppSet() != prop2.hasStdCppSet())
+ return false;
+
+ if (prop1.hasNotifySignal()) {
+ if (prop1.notifySignalIndex() != prop2.notifySignalIndex())
+ return false;
+ }
+
+ return true;
+}
+
+static bool sameEnumerator(const QMetaEnum& enum1, const QMetaEnum& enum2)
+{
+ if (QByteArray(enum1.name()) != QByteArray(enum2.name()))
+ return false;
+
+ if (enum1.isFlag() != enum2.isFlag())
+ return false;
+
+ if (enum1.keyCount() != enum2.keyCount())
+ return false;
+
+ for (int index = 0; index < enum1.keyCount(); ++index) {
+ if (QByteArray(enum1.key(index)) != QByteArray(enum2.key(index)))
+ return false;
+ if (enum1.value(index) != enum2.value(index))
+ return false;
+ }
+
+ if (QByteArray(enum1.scope()) != QByteArray(enum2.scope()))
+ return false;
+
+ return true;
+}
+
+// Determine if two meta objects are identical.
+bool tst_QMetaObjectBuilder::sameMetaObject
+ (const QMetaObject *meta1, const QMetaObject *meta2)
+{
+ int index;
+
+ if (strcmp(meta1->className(), meta2->className()) != 0)
+ return false;
+
+ if (meta1->superClass() != meta2->superClass())
+ return false;
+
+ if (meta1->constructorCount() != meta2->constructorCount() ||
+ meta1->methodCount() != meta2->methodCount() ||
+ meta1->enumeratorCount() != meta2->enumeratorCount() ||
+ meta1->propertyCount() != meta2->propertyCount() ||
+ meta1->classInfoCount() != meta2->classInfoCount())
+ return false;
+
+ for (index = 0; index < meta1->constructorCount(); ++index) {
+ if (!sameMethod(meta1->constructor(index), meta2->constructor(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->methodCount(); ++index) {
+ if (!sameMethod(meta1->method(index), meta2->method(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->propertyCount(); ++index) {
+ if (!sameProperty(meta1->property(index), meta2->property(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->enumeratorCount(); ++index) {
+ if (!sameEnumerator(meta1->enumerator(index), meta2->enumerator(index)))
+ return false;
+ }
+
+ for (index = 0; index < meta1->classInfoCount(); ++index) {
+ if (QByteArray(meta1->classInfo(index).name()) !=
+ QByteArray(meta2->classInfo(index).name()))
+ return false;
+ if (QByteArray(meta1->classInfo(index).value()) !=
+ QByteArray(meta2->classInfo(index).value()))
+ return false;
+ }
+
+ const QMetaObject **objects1 = 0;
+ const QMetaObject **objects2 = 0;
+ if (meta1->d.data[0] == meta2->d.data[0] && meta1->d.data[0] >= 2) {
+ QMetaObjectExtraData *extra1 = (QMetaObjectExtraData *)(meta1->d.extradata);
+ QMetaObjectExtraData *extra2 = (QMetaObjectExtraData *)(meta2->d.extradata);
+ if (extra1 && !extra2)
+ return false;
+ if (extra2 && !extra1)
+ return false;
+ if (extra1 && extra2) {
+ if (extra1->static_metacall != extra2->static_metacall)
+ return false;
+ objects1 = extra1->objects;
+ objects2 = extra1->objects;
+ }
+ } else if (meta1->d.data[0] == meta2->d.data[0] && meta1->d.data[0] == 1) {
+ objects1 = (const QMetaObject **)(meta1->d.extradata);
+ objects2 = (const QMetaObject **)(meta2->d.extradata);
+ }
+ if (objects1 && !objects2)
+ return false;
+ if (objects2 && !objects1)
+ return false;
+ if (objects1 && objects2) {
+ while (*objects1 != 0 && *objects2 != 0) {
+ if (*objects1 != *objects2)
+ return false;
+ ++objects1;
+ ++objects2;
+ }
+ }
+
+ return true;
+}
+
+QTEST_MAIN(tst_QMetaObjectBuilder)
+
+#include "tst_qmetaobjectbuilder.moc"
diff --git a/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp b/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp
index 69d9091..3c60b2b 100644
--- a/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp
+++ b/tests/auto/declarative/qmlcontext/tst_qmlcontext.cpp
@@ -44,6 +44,7 @@
#include <QmlEngine>
#include <QmlContext>
#include <QmlComponent>
+#include <QmlExpression>
class tst_qmlcontext : public QObject
{
@@ -58,6 +59,7 @@ private slots:
void parentContext();
void setContextProperty();
void addDefaultObject();
+ void destruction();
private:
QmlEngine engine;
@@ -111,6 +113,14 @@ void tst_qmlcontext::resolvedUrl()
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
}
+
+ // Absolute
+ {
+ QmlContext ctxt(&engine);
+
+ QCOMPARE(ctxt.resolvedUrl(QUrl("http://www.nokia.com/main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
+ QCOMPARE(ctxt.resolvedUrl(QUrl("file:///main2.qml")), QUrl("file:///main2.qml"));
+ }
}
void tst_qmlcontext::engineMethod()
@@ -256,10 +266,10 @@ void tst_qmlcontext::setContextProperty()
// Static context properties
ctxt.setContextProperty("a", QVariant(10));
ctxt.setContextProperty("b", QVariant(9));
+ ctxt2.setContextProperty("d", &obj2);
ctxt2.setContextProperty("b", QVariant(19));
ctxt2.setContextProperty("c", QVariant(QString("Hello World!")));
ctxt.setContextProperty("d", &obj1);
- ctxt2.setContextProperty("d", &obj2);
ctxt.setContextProperty("e", &obj1);
TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(10));
@@ -334,6 +344,26 @@ void tst_qmlcontext::setContextProperty()
delete obj;
}
+
+ // Setting an object-variant context property
+ {
+ QmlComponent component(&engine);
+ component.setData("import Qt 4.6; Object { id: root; property int a: 10; property int test: ctxtProp.a; property var obj: root; }", QUrl());
+
+ QmlContext ctxt(engine.rootContext());
+ ctxt.setContextProperty("ctxtProp", QVariant());
+
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Result of expression 'ctxtProp' [undefined] is not an object.");
+ QObject *obj = component.create(&ctxt);
+
+ QVariant v = obj->property("obj");
+
+ ctxt.setContextProperty("ctxtProp", v);
+
+ QCOMPARE(obj->property("test"), QVariant(10));
+
+ delete obj;
+ }
}
void tst_qmlcontext::addDefaultObject()
@@ -382,6 +412,23 @@ void tst_qmlcontext::addDefaultObject()
}
}
+void tst_qmlcontext::destruction()
+{
+ QmlContext *ctxt = new QmlContext(&engine);
+
+ QObject obj;
+ QmlEngine::setContextForObject(&obj, ctxt);
+ QmlExpression expr(ctxt, "a", 0);
+
+ QCOMPARE(ctxt, QmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt, expr.context());
+
+ delete ctxt; ctxt = 0;
+
+ QCOMPARE(ctxt, QmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt, expr.context());
+}
+
QTEST_MAIN(tst_qmlcontext)
#include "tst_qmlcontext.moc"