From 6c3868572d8f109884a1b3fb806331fda3ef84d4 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 9 Feb 2011 10:23:03 +1000 Subject: Update the input context when the pre-edit cursor position changes. The micro focus rect changes both when the regular cursor position and the pre-edit cursor positions change. Ensure updateMicroFocus is called TextInput in both cases. Change-Id: I6822a710b841e106ce2462f74fea398250596913 Task-number: QTBUG-17396 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextinput.cpp | 2 + src/gui/widgets/qlinecontrol.cpp | 3 + src/gui/widgets/qlinecontrol_p.h | 1 + .../tst_qdeclarativetextedit.cpp | 67 +++++++++++++++++++++- .../tst_qdeclarativetextinput.cpp | 55 +++++++++++++++++- 5 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 88f36b4..e7c2ac7 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1662,6 +1662,8 @@ void QDeclarativeTextInputPrivate::init() q->connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged())); #endif // QT_NO_CLIPBOARD + q->connect(control, SIGNAL(updateMicroFocus()), + q, SLOT(updateMicroFocus())); q->updateSize(); oldValidity = control->hasAcceptableInput(); lastSelectionStart = 0; diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index c7a3913..d108ad9 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -456,6 +456,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) #ifndef QT_NO_IM setPreeditArea(m_cursor, event->preeditString()); #endif //QT_NO_IM + const int oldPreeditCursor = m_preeditCursor; m_preeditCursor = event->preeditString().length(); m_hideCursor = false; QList formats; @@ -479,6 +480,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) updateDisplayText(/*force*/ true); if (cursorPositionChanged) emitCursorPositionChanged(); + else if (m_preeditCursor != oldPreeditCursor) + emit updateMicroFocus(); if (isGettingInput) finishChange(priorState); } diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bfe50fe..3c505c8 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -425,6 +425,7 @@ Q_SIGNALS: void textEdited(const QString &); void resetInputContext(); + void updateMicroFocus(); void accepted(); void editingFinished(); diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 7d5101c..7226dc9 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -137,6 +137,8 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void preeditMicroFocus(); + private: void simulateKey(QDeclarativeView *, int key); QDeclarativeView *createView(const QString &filename); @@ -1460,7 +1462,7 @@ QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1478,8 +1480,22 @@ public: closeInputPanelReceived = true; return QInputContext::filterEvent(event); } + + void update() { updateReceived = true; } + + void sendPreeditText(const QString &text, int cursor) + { + QList attributes; + attributes.append(QInputMethodEvent::Attribute( + QInputMethodEvent::Cursor, cursor, text.length(), QVariant())); + + QInputMethodEvent event(text, attributes); + sendEvent(event); + } + bool openInputPanelReceived; bool closeInputPanelReceived; + bool updateReceived; }; void tst_qdeclarativetextedit::textInput() @@ -1797,6 +1813,55 @@ void tst_qdeclarativetextedit::testQtQuick11Attributes_data() << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n"; } +void tst_qdeclarativetextedit::preeditMicroFocus() +{ + QString preeditText = "super"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setPos(0, 0); + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + + QRect currentRect; + QRect previousRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + + // Verify that the micro focus rect is positioned the same for position 0 as + // it would be if there was no preedit text. + ic.updateReceived = false; + ic.sendPreeditText(preeditText, 0); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); + QCOMPARE(ic.updateReceived, true); + + // Verify that the micro focus rect moves to the left as the cursor position + // is incremented. + for (int i = 1; i <= 5; ++i) { + ic.updateReceived = false; + ic.sendPreeditText(preeditText, i); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QVERIFY(previousRect.left() < currentRect.left()); + QCOMPARE(ic.updateReceived, true); + previousRect = currentRect; + } + + // Verify that if there is no preedit cursor then the micro focus rect is the + // same as it would be if it were positioned at the end of the preedit text. + ic.sendPreeditText(preeditText, 0); + ic.updateReceived = false; + ic.sendEvent(QInputMethodEvent(preeditText, QList())); + currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); + QCOMPARE(ic.updateReceived, true); +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index a6d30a5..77cb323 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -125,6 +125,7 @@ private slots: void testQtQuick11Attributes_data(); void preeditAutoScroll(); + void preeditMicroFocus(); private: void simulateKey(QDeclarativeView *, int key); @@ -1419,7 +1420,7 @@ QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1438,6 +1439,8 @@ public: return QInputContext::filterEvent(event); } + void update() { updateReceived = true; } + void sendPreeditText(const QString &text, int cursor) { QList attributes; @@ -1450,6 +1453,7 @@ public: bool openInputPanelReceived; bool closeInputPanelReceived; + bool updateReceived; }; void tst_qdeclarativetextinput::openInputPanelOnClick() @@ -1800,6 +1804,55 @@ void tst_qdeclarativetextinput::preeditAutoScroll() QCOMPARE(input.positionAt(input.width()), 5); } +void tst_qdeclarativetextinput::preeditMicroFocus() +{ + QString preeditText = "super"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setPos(0, 0); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + + QRect currentRect; + QRect previousRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + + // Verify that the micro focus rect is positioned the same for position 0 as + // it would be if there was no preedit text. + ic.updateReceived = false; + ic.sendPreeditText(preeditText, 0); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); + QCOMPARE(ic.updateReceived, true); + + // Verify that the micro focus rect moves to the left as the cursor position + // is incremented. + for (int i = 1; i <= 5; ++i) { + ic.updateReceived = false; + ic.sendPreeditText(preeditText, i); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QVERIFY(previousRect.left() < currentRect.left()); + QCOMPARE(ic.updateReceived, true); + previousRect = currentRect; + } + + // Verify that if there is no preedit cursor then the micro focus rect is the + // same as it would be if it were positioned at the end of the preedit text. + ic.sendPreeditText(preeditText, 0); + ic.updateReceived = false; + ic.sendEvent(QInputMethodEvent(preeditText, QList())); + currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); + QCOMPARE(currentRect, previousRect); + QCOMPARE(ic.updateReceived, true); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v0.12 From 35a36e91606eaf8374a2273cbb0101e0e614321e Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 15 Feb 2011 14:00:27 +0100 Subject: QDeclarativeDebug: Fix crash when serializing list of QObjects Task-number: QTBUG-17444 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativeenginedebug.cpp | 18 ++++++++++-------- .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 8c7f3ad..31fd516 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -167,17 +167,19 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx) QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const { int userType = value.userType(); - if (QDeclarativeValueTypeFactory::isValueType(userType)) - return value; - /* - if (QDeclarativeMetaType::isList(userType)) { - int count = QDeclarativeMetaType::listCount(value); + if (value.type() == QVariant::List) { QVariantList contents; - for (int i=0; imetaObject(); - QDeclarativeType *type = QDeclarativeMetaType::qmlType(o->metaObject()); - QString className = type ? type->qmlTypeName() : QString(); + QDeclarativeType *type = QDeclarativeMetaType::qmlType(meta); + QString className = type ? QString(type->qmlTypeName()) : QString(meta->className()); className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); QCOMPARE(oref.debugId(), QDeclarativeDebugService::idForObject(o)); @@ -292,12 +292,21 @@ void tst_QDeclarativeDebug::initTestCase() QList qml; qml << "import QtQuick 1.0\n" "Item {" + "id: root\n" "width: 10; height: 20; scale: blueRect.scale;" "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }" "Text { color: blueRect.color; }" "MouseArea {" "onEntered: { console.log('hello') }" "}" + "property variant varObj\n" + "property variant varObjList: []\n" + "Component.onCompleted: {\n" + "varObj = blueRect;\n" + "var list = varObjList;\n" + "list[0] = blueRect;\n" + "varObjList = list;\n" + "}\n" "}"; // add second component to test multiple root contexts @@ -741,7 +750,6 @@ void tst_QDeclarativeDebug::queryObject() QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue"))); QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue"))); - } else { foreach(const QDeclarativeDebugObjectReference &child, obj.children()) QCOMPARE(child.properties().count(), 0); @@ -798,6 +806,8 @@ void tst_QDeclarativeDebug::queryExpressionResult_data() QTest::newRow("width + 50") << "width + 50" << qVariantFromValue(60); QTest::newRow("blueRect.width") << "blueRect.width" << qVariantFromValue(500); QTest::newRow("bad expr") << "aeaef" << qVariantFromValue(QString("")); + QTest::newRow("QObject*") << "varObj" << qVariantFromValue(QString("")); + QTest::newRow("list of QObject*") << "varObjList" << qVariantFromValue(QString("")); } void tst_QDeclarativeDebug::tst_QDeclarativeDebugFileReference() -- cgit v0.12 From bfdecd0e2047fc49ed28ed095e657080897c91d1 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 16 Feb 2011 17:08:10 +1000 Subject: Fix TextInput, TextEdit auto test failure on windows and mac. Micro focus is only updated on X11, QWS and Symbian platforms. Change-Id: Id02655cba79429e91022593ff0d1d6b8068c84ec Reviewed-by: Martin Jones --- .../declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp | 6 ++++++ .../declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 7226dc9..87c2c60 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1839,7 +1839,9 @@ void tst_qdeclarativetextedit::preeditMicroFocus() ic.sendPreeditText(preeditText, 0); currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif // Verify that the micro focus rect moves to the left as the cursor position // is incremented. @@ -1848,7 +1850,9 @@ void tst_qdeclarativetextedit::preeditMicroFocus() ic.sendPreeditText(preeditText, i); currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); QVERIFY(previousRect.left() < currentRect.left()); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif previousRect = currentRect; } @@ -1859,7 +1863,9 @@ void tst_qdeclarativetextedit::preeditMicroFocus() ic.sendEvent(QInputMethodEvent(preeditText, QList())); currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif } QTEST_MAIN(tst_qdeclarativetextedit) diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 77cb323..7753f11 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -1830,7 +1830,9 @@ void tst_qdeclarativetextinput::preeditMicroFocus() ic.sendPreeditText(preeditText, 0); currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif // Verify that the micro focus rect moves to the left as the cursor position // is incremented. @@ -1839,7 +1841,9 @@ void tst_qdeclarativetextinput::preeditMicroFocus() ic.sendPreeditText(preeditText, i); currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); QVERIFY(previousRect.left() < currentRect.left()); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif previousRect = currentRect; } @@ -1850,7 +1854,9 @@ void tst_qdeclarativetextinput::preeditMicroFocus() ic.sendEvent(QInputMethodEvent(preeditText, QList())); currentRect = input.inputMethodQuery(Qt::ImMicroFocus).toRect(); QCOMPARE(currentRect, previousRect); +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); +#endif } QTEST_MAIN(tst_qdeclarativetextinput) -- cgit v0.12 From 4df66da8f9e5a9f3c981c6c60254899146dd1cc0 Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Thu, 3 Feb 2011 13:54:13 +1000 Subject: Fix QTBUG-17008 XmlListModel blocks Windows system events XmlListModel uses a worker thread to process XML query, however the worker thread doesn't use it's own event loop. So after processing the query, the worker thread just blocks on a wait condition and then blocks all posted system events. Change-Id: Icdd9ddd1f3f26fd632726f7200c2a81b0877d2d1 Task-number:QTBUG-17008 Reviewed-by:Martin Jones --- src/declarative/util/qdeclarativexmllistmodel.cpp | 170 ++++++++++----------- .../tst_qdeclarativexmllistmodel.cpp | 23 +++ 2 files changed, 103 insertions(+), 90 deletions(-) diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 976fc4a..5ed10cf 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -46,11 +46,9 @@ #include #include -#include +#include #include #include -#include -#include #include #include #include @@ -58,6 +56,7 @@ #include #include #include +#include #include @@ -142,39 +141,32 @@ struct XmlQueryJob QStringList keyRoleResultsCache; }; -class QDeclarativeXmlQuery : public QThread +class QDeclarativeXmlQuery : public QObject { Q_OBJECT public: QDeclarativeXmlQuery(QObject *parent=0) - : QThread(parent), m_quit(false), m_abortQueryId(-1), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { + : QObject(parent), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) { qRegisterMetaType("QDeclarativeXmlQueryResult"); - m_currentJob.queryId = -1; + moveToThread(&m_thread); + m_thread.start(QThread::IdlePriority); } ~QDeclarativeXmlQuery() { - m_mutex.lock(); - m_quit = true; - m_condition.wakeOne(); - m_mutex.unlock(); - - wait(); + if(m_thread.isRunning()) { + m_thread.quit(); + m_thread.wait(); + } } void abort(int id) { - QMutexLocker locker(&m_mutex); - QQueue::iterator it; - for (it = m_jobs.begin(); it != m_jobs.end(); ++it) { - if ((*it).queryId == id) { - m_jobs.erase(it); - return; - } + QMutexLocker ml(&m_mutex); + if (id != -1) { + m_jobs.remove(id); } - m_abortQueryId = id; } - int doQuery(QString query, QString namespaces, QByteArray data, QList *roleObjects, QStringList keyRoleResultsCache) { - QMutexLocker locker(&m_mutex); + int doQuery(QString query, QString namespaces, QByteArray data, QList* roleObjects, QStringList keyRoleResultsCache) { XmlQueryJob job; job.queryId = m_queryIds; @@ -193,69 +185,69 @@ public: if (roleObjects->at(i)->isKey()) job.keyRoleQueries << job.roleQueries.last(); } - m_jobs.enqueue(job); - m_queryIds++; - if (!isRunning()) - start(QThread::IdlePriority); - else - m_condition.wakeOne(); + { + QMutexLocker ml(&m_mutex); + m_jobs.insert(m_queryIds, job); + m_queryIds++; + if (m_queryIds <= 0) + m_queryIds = 1; + } + + QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId)); return job.queryId; } +private slots: + void processQuery(int queryId) { + XmlQueryJob job; + + { + QMutexLocker ml(&m_mutex); + if (!m_jobs.contains(queryId)) + return; + job = m_jobs.value(queryId); + } + + QDeclarativeXmlQueryResult r; + doQueryJob(&job); + doSubQueryJob(&job); + r.queryId = job.queryId; + r.size = m_size; + r.data = m_modelData; + r.inserted = m_insertedItemRanges; + r.removed = m_removedItemRanges; + r.keyRoleResultsCache = job.keyRoleResultsCache; + + { + QMutexLocker ml(&m_mutex); + if (m_jobs.contains(queryId)) { + emit queryCompleted(r); + m_jobs.remove(queryId); + } + } + } + Q_SIGNALS: void queryCompleted(const QDeclarativeXmlQueryResult &); void error(void*, const QString&); protected: - void run() { - m_mutex.lock(); - - while (!m_quit) { - if (!m_jobs.isEmpty()) - m_currentJob = m_jobs.dequeue(); - m_mutex.unlock(); - - QDeclarativeXmlQueryResult r; - if (m_currentJob.queryId != -1) { - doQueryJob(); - doSubQueryJob(); - r.queryId = m_currentJob.queryId; - r.size = m_size; - r.data = m_modelData; - r.inserted = m_insertedItemRanges; - r.removed = m_removedItemRanges; - r.keyRoleResultsCache = m_currentJob.keyRoleResultsCache; - } - m_mutex.lock(); - if (m_currentJob.queryId != -1 && m_abortQueryId != m_currentJob.queryId) - emit queryCompleted(r); - if (m_jobs.isEmpty() && !m_quit) - m_condition.wait(&m_mutex); - m_currentJob.queryId = -1; - m_abortQueryId = -1; - } - - m_mutex.unlock(); - } private: - void doQueryJob(); - void doSubQueryJob(); - void getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const; + void doQueryJob(XmlQueryJob* job); + void doSubQueryJob(XmlQueryJob* job); + void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const; void addIndexToRangeList(QList *ranges, int index) const; private: QMutex m_mutex; - QWaitCondition m_condition; - QQueue m_jobs; - XmlQueryJob m_currentJob; - bool m_quit; - int m_abortQueryId; + QThread m_thread; + QMap m_jobs; + int m_queryIds; QString m_prefix; int m_size; - int m_queryIds; QList > m_modelData; QList m_insertedItemRanges; QList m_removedItemRanges; @@ -263,16 +255,16 @@ private: Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery) -void QDeclarativeXmlQuery::doQueryJob() +void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob) { - Q_ASSERT(m_currentJob.queryId != -1); + Q_ASSERT(currentJob->queryId != -1); QString r; QXmlQuery query; - QBuffer buffer(&m_currentJob.data); + QBuffer buffer(¤tJob->data); buffer.open(QIODevice::ReadOnly); query.bindVariable(QLatin1String("src"), &buffer); - query.setQuery(m_currentJob.namespaces + m_currentJob.query); + query.setQuery(currentJob->namespaces + currentJob->query); query.evaluateTo(&r); //always need a single root element @@ -280,9 +272,9 @@ void QDeclarativeXmlQuery::doQueryJob() QBuffer b(&xml); b.open(QIODevice::ReadOnly); - QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + m_currentJob.namespaces; + QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + currentJob->namespaces; QString prefix = QLatin1String("doc($inputDocument)/dummy:items") + - m_currentJob.query.mid(m_currentJob.query.lastIndexOf(QLatin1Char('/'))); + currentJob->query.mid(currentJob->query.lastIndexOf(QLatin1Char('/'))); //figure out how many items we are dealing with int count = -1; @@ -297,18 +289,16 @@ void QDeclarativeXmlQuery::doQueryJob() count = item.toAtomicValue().toInt(); } - m_currentJob.data = xml; + currentJob->data = xml; m_prefix = namespaces + prefix + QLatin1Char('/'); m_size = 0; if (count > 0) m_size = count; } -void QDeclarativeXmlQuery::getValuesOfKeyRoles(QStringList *values, QXmlQuery *query) const +void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const { - Q_ASSERT(m_currentJob.queryId != -1); - - const QStringList &keysQueries = m_currentJob.keyRoleQueries; + const QStringList &keysQueries = currentJob.keyRoleQueries; QString keysQuery; if (keysQueries.count() == 1) keysQuery = m_prefix + keysQueries[0]; @@ -336,34 +326,34 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList * ranges->append(qMakePair(index, 1)); } -void QDeclarativeXmlQuery::doSubQueryJob() +void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob) { - Q_ASSERT(m_currentJob.queryId != -1); + Q_ASSERT(currentJob->queryId != -1); m_modelData.clear(); - QBuffer b(&m_currentJob.data); + QBuffer b(¤tJob->data); b.open(QIODevice::ReadOnly); QXmlQuery subquery; subquery.bindVariable(QLatin1String("inputDocument"), &b); QStringList keyRoleResults; - getValuesOfKeyRoles(&keyRoleResults, &subquery); + getValuesOfKeyRoles(*currentJob, &keyRoleResults, &subquery); // See if any values of key roles have been inserted or removed. m_insertedItemRanges.clear(); m_removedItemRanges.clear(); - if (m_currentJob.keyRoleResultsCache.isEmpty()) { + if (currentJob->keyRoleResultsCache.isEmpty()) { m_insertedItemRanges << qMakePair(0, m_size); } else { - if (keyRoleResults != m_currentJob.keyRoleResultsCache) { + if (keyRoleResults != currentJob->keyRoleResultsCache) { QStringList temp; - for (int i=0; ikeyRoleResultsCache.count(); i++) { + if (!keyRoleResults.contains(currentJob->keyRoleResultsCache[i])) addIndexToRangeList(&m_removedItemRanges, i); else - temp << m_currentJob.keyRoleResultsCache[i]; + temp << currentJob->keyRoleResultsCache[i]; } for (int i=0; ikeyRoleResultsCache = keyRoleResults; // Get the new values for each role. //### we might be able to condense even further (query for everything in one go) - const QStringList &queries = m_currentJob.roleQueries; + const QStringList &queries = currentJob->roleQueries; for (int i = 0; i < queries.size(); ++i) { QList resultList; if (!queries[i].isEmpty()) { @@ -392,7 +382,7 @@ void QDeclarativeXmlQuery::doSubQueryJob() item = resultItems.next(); } } else { - emit error(m_currentJob.roleQueryErrorId.at(i), queries[i]); + emit error(currentJob->roleQueryErrorId.at(i), queries[i]); } } //### should warn here if things have gone wrong. diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp index 19d7967..af54008 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp +++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp @@ -569,6 +569,11 @@ void tst_qdeclarativexmllistmodel::reload() QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int))); QSignalSpy spyCount(model, SIGNAL(countChanged())); + //reload multiple times to test the xml query aborting + model->reload(); + model->reload(); + QCoreApplication::processEvents(); + model->reload(); model->reload(); QTRY_COMPARE(spyCount.count(), 1); QTRY_COMPARE(spyInsert.count(), 1); @@ -839,9 +844,27 @@ void tst_qdeclarativexmllistmodel::threading() data3 += "name=C" + QString::number(i) + ",age=3" + QString::number(i) + ",sport=Curling;"; } + //Set the xml data multiple times with randomized order and mixed with multiple event loops + //to test the xml query reloading/aborting, the result should be stable. + m1->setXml(makeItemXmlAndData(data1)); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); m1->setXml(makeItemXmlAndData(data1)); m2->setXml(makeItemXmlAndData(data2)); + QCoreApplication::processEvents(); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); + m1->setXml(makeItemXmlAndData(data1)); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); + m2->setXml(makeItemXmlAndData(data2)); + m3->setXml(makeItemXmlAndData(data3)); m3->setXml(makeItemXmlAndData(data3)); + QCoreApplication::processEvents(); QTRY_VERIFY(m1->count() == dataCount && m2->count() == dataCount && m3->count() == dataCount); -- cgit v0.12 From 57676c237992e0aa5a93a4e8fa66b3e7b90c2c90 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 17 Feb 2011 14:54:09 +1000 Subject: Allow MouseArea to prevent mouse grab begin stolen by Flickable. Placing a MouseArea in a Flickable (or PinchArea, or PathView) allows the Flickable to steal mouse events when it detects a flick/drag event. In some cases this is not desireable and MouseArea should be able to retain its grab. Added a 'preventStealing' property to prevent an ancestor item from stealing the MouseArea's grab. Change-Id: I6277fbb76919b2b35d4e32a247b38a90e305dbdf Task-number: QTBUG-17285 Reviewed-by: Joona Petrell --- .../graphicsitems/qdeclarativeitemsmodule.cpp | 1 + .../graphicsitems/qdeclarativemousearea.cpp | 38 +++++- .../graphicsitems/qdeclarativemousearea_p.h | 5 + .../graphicsitems/qdeclarativemousearea_p_p.h | 3 +- .../qdeclarativemousearea/data/preventstealing.qml | 24 ++++ .../tst_qdeclarativemousearea.cpp | 135 +++++++++++++++++++++ 6 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index bc4a2d0..3c8f64e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -180,6 +180,7 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"Pinch"); qmlRegisterType(); qmlRegisterType("QtQuick",1,1,"Item"); + qmlRegisterType("QtQuick",1,1,"MouseArea"); qmlRegisterType("QtQuick",1,1,"Flickable"); qmlRegisterType("QtQuick",1,1,"ListView"); qmlRegisterType("QtQuick",1,1,"GridView"); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 0aa0c1b..1308e73 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -416,6 +416,40 @@ void QDeclarativeMouseArea::setEnabled(bool a) emit enabledChanged(); } } + +/*! + \qmlproperty bool MouseArea::preventStealing + \since Quick 1.1 + This property holds whether the mouse events may be stolen from this + MouseArea. + + If a MouseArea is placed within an item that filters child mouse + events, such as Flickable, the mouse + events may be stolen from the MouseArea if a gesture is recognized + by the parent element, e.g. a flick gesture. If preventStealing is + set to true, no element will steal the mouse events. + + Note that setting preventStealing to true once an element has started + stealing events will have no effect until the next press event. + + By default this property is false. +*/ +bool QDeclarativeMouseArea::preventStealing() const +{ + Q_D(const QDeclarativeMouseArea); + return d->preventStealing; +} + +void QDeclarativeMouseArea::setPreventStealing(bool prevent) +{ + Q_D(QDeclarativeMouseArea); + if (prevent != d->preventStealing) { + d->preventStealing = prevent; + setKeepMouseGrab(d->preventStealing && d->absorb); + emit preventStealingChanged(); + } +} + /*! \qmlproperty MouseButtons MouseArea::pressedButtons This property holds the mouse buttons currently pressed. @@ -443,7 +477,7 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeMouseArea); d->moved = false; - d->stealMouse = false; + d->stealMouse = d->preventStealing; if (!d->absorb) QDeclarativeItem::mousePressEvent(event); else { @@ -460,7 +494,7 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) // we should only start timer if pressAndHold is connected to. if (d->isPressAndHoldConnected()) d->pressAndHoldTimer.start(PressAndHoldDelay, this); - setKeepMouseGrab(false); + setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(true)); } } diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index 937ac78..985f27e 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -129,6 +129,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeMouseArea : public QDeclarativeItem Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged) Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged) Q_PROPERTY(QDeclarativeDrag *drag READ drag CONSTANT) //### add flicking to QDeclarativeDrag or add a QDeclarativeFlick ??? + Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1) public: QDeclarativeMouseArea(QDeclarativeItem *parent=0); @@ -153,6 +154,9 @@ public: QDeclarativeDrag *drag(); + bool preventStealing() const; + void setPreventStealing(bool prevent); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); @@ -161,6 +165,7 @@ Q_SIGNALS: void hoverEnabledChanged(); void positionChanged(QDeclarativeMouseEvent *mouse); void mousePositionChanged(QDeclarativeMouseEvent *mouse); + Q_REVISION(1) void preventStealingChanged(); void pressed(QDeclarativeMouseEvent *mouse); void pressAndHold(QDeclarativeMouseEvent *mouse); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h index 2a327af..67694fb 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h @@ -68,7 +68,7 @@ class QDeclarativeMouseAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativeMouseAreaPrivate() : absorb(true), hovered(false), pressed(false), longPress(false), - moved(false), stealMouse(false), doubleClick(false), drag(0) + moved(false), stealMouse(false), doubleClick(false), preventStealing(false), drag(0) { } @@ -110,6 +110,7 @@ public: bool dragY : 1; bool stealMouse : 1; bool doubleClick : 1; + bool preventStealing : 1; QDeclarativeDrag *drag; QPointF startScene; qreal startX; diff --git a/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml b/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml new file mode 100644 index 0000000..11553fa --- /dev/null +++ b/tests/auto/declarative/qdeclarativemousearea/data/preventstealing.qml @@ -0,0 +1,24 @@ +import QtQuick 1.1 + +Flickable { + property bool stealing: true + width: 200 + height: 200 + contentWidth: 400 + contentHeight: 400 + Rectangle { + color: "black" + width: 400 + height: 400 + Rectangle { + x: 50; y: 50 + width: 100; height: 100 + color: "steelblue" + MouseArea { + objectName: "mousearea" + anchors.fill: parent + preventStealing: stealing + } + } + } +} diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 845d6bb..60d51c6 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -43,8 +43,10 @@ #include #include #include +#include #include #include +#include #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -65,6 +67,9 @@ private slots: void doubleClick(); void clickTwice(); void pressedOrdering(); + void preventStealing(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -356,6 +361,8 @@ void tst_QDeclarativeMouseArea::noOnClickedWithPressAndHold() QVERIFY(!canvas->rootObject()->property("clicked").toBool()); QVERIFY(canvas->rootObject()->property("held").toBool()); + + delete canvas; } void tst_QDeclarativeMouseArea::onMousePressRejected() @@ -399,6 +406,8 @@ void tst_QDeclarativeMouseArea::onMousePressRejected() QVERIFY(canvas->rootObject()->property("mr1_released").toBool()); QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool()); QVERIFY(!canvas->rootObject()->property("mr2_released").toBool()); + + delete canvas; } void tst_QDeclarativeMouseArea::doubleClick() @@ -436,6 +445,7 @@ void tst_QDeclarativeMouseArea::doubleClick() QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1); QCOMPARE(canvas->rootObject()->property("released").toInt(), 2); + delete canvas; } // QTBUG-14832 @@ -476,6 +486,8 @@ void tst_QDeclarativeMouseArea::clickTwice() QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2); QCOMPARE(canvas->rootObject()->property("released").toInt(), 2); QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2); + + delete canvas; } void tst_QDeclarativeMouseArea::pressedOrdering() @@ -512,6 +524,129 @@ void tst_QDeclarativeMouseArea::pressedOrdering() delete canvas; } +void tst_QDeclarativeMouseArea::preventStealing() +{ + QDeclarativeView *canvas = createView(); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/preventstealing.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flickable = qobject_cast(canvas->rootObject()); + QVERIFY(flickable != 0); + + QDeclarativeMouseArea *mouseArea = canvas->rootObject()->findChild("mousearea"); + QVERIFY(mouseArea != 0); + + QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QDeclarativeMouseEvent*))); + + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress); + pressEvent.setScenePos(QPointF(80, 80)); + pressEvent.setButton(Qt::LeftButton); + pressEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &pressEvent); + + // Without preventStealing, mouse movement over MouseArea would + // cause the Flickable to steal mouse and trigger content movement. + QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove); + moveEvent.setScenePos(QPointF(70, 70)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(60, 60)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(50, 50)); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &moveEvent); + + // We should have received all three move events + QCOMPARE(mousePositionSpy.count(), 3); + QVERIFY(mouseArea->pressed()); + + // Flickable content should not have moved. + QCOMPARE(flickable->contentX(), 0.); + QCOMPARE(flickable->contentY(), 0.); + + QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease); + releaseEvent.setScenePos(QPointF(50, 50)); + releaseEvent.setButton(Qt::LeftButton); + releaseEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &releaseEvent); + + // Now allow stealing and confirm Flickable does its thing. + canvas->rootObject()->setProperty("stealing", false); + + pressEvent.setScenePos(QPointF(80, 80)); + QApplication::sendEvent(scene, &pressEvent); + + // Without preventStealing, mouse movement over MouseArea would + // cause the Flickable to steal mouse and trigger content movement. + moveEvent.setScenePos(QPointF(70, 70)); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(60, 60)); + QApplication::sendEvent(scene, &moveEvent); + + moveEvent.setScenePos(QPointF(50, 50)); + QApplication::sendEvent(scene, &moveEvent); + + // We should only have received the first move event + QCOMPARE(mousePositionSpy.count(), 4); + // Our press should be taken away + QVERIFY(!mouseArea->pressed()); + + // Flickable content should have moved. + QCOMPARE(flickable->contentX(), 10.); + QCOMPARE(flickable->contentY(), 10.); + + releaseEvent.setScenePos(QPointF(50, 50)); + QApplication::sendEvent(scene, &releaseEvent); + + delete canvas; +} + +void tst_QDeclarativeMouseArea::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; MouseArea { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; MouseArea { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeMouseArea::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("preventStealing") << "preventStealing: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"MouseArea.preventStealing\" is not available in QtQuick 1.0.\n"; +} + QTEST_MAIN(tst_QDeclarativeMouseArea) #include "tst_qdeclarativemousearea.moc" -- cgit v0.12 From 935b7ab960cf417336571754659d04958b707fc8 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 17 Feb 2011 13:54:52 +1000 Subject: Export symbols from qtestlib required for QtQuickTest Task-number: QTBUG-16084 Reviewed-by: Jason McDonald --- src/testlib/qbenchmark_p.h | 4 ++-- src/testlib/qtestcase.cpp | 42 ++++++++++++++++++++++++++++++++++++++---- src/testlib/qtestlog_p.h | 2 +- src/testlib/qtestresult_p.h | 2 +- src/testlib/qtesttable_p.h | 2 +- 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index 9a83a1a..ace17db 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -130,7 +130,7 @@ public: QBenchmarkGlobalData:current is created at the beginning of qExec() and cleared at the end. */ -class QBenchmarkGlobalData +class Q_TESTLIB_EXPORT QBenchmarkGlobalData { public: static QBenchmarkGlobalData *current; @@ -161,7 +161,7 @@ private: created at the beginning of qInvokeTestMethod() and cleared at the end. */ -class QBenchmarkTestMethodData +class Q_TESTLIB_EXPORT QBenchmarkTestMethodData { public: static QBenchmarkTestMethodData *current; diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 0ceb71d..97f069e 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -956,6 +956,10 @@ static bool isValidSlot(const QMetaMethod &sl) return true; } +Q_TESTLIB_EXPORT bool printAvailableFunctions = false; +Q_TESTLIB_EXPORT QStringList testFunctions; +Q_TESTLIB_EXPORT QStringList testTags; + static void qPrintTestSlots() { for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) { @@ -976,7 +980,7 @@ static int qToInt(char *str) return l; } -static void qParseArgs(int argc, char *argv[]) +Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) { lastTestFuncIdx = -1; @@ -1025,8 +1029,12 @@ static void qParseArgs(int argc, char *argv[]) "%s", argv[0], testOptions); exit(0); } else if (strcmp(argv[i], "-functions") == 0) { - qPrintTestSlots(); - exit(0); + if (qml) { + QTest::printAvailableFunctions = true; + } else { + qPrintTestSlots(); + exit(0); + } } else if(strcmp(argv[i], "-xunitxml") == 0){ QTestLog::setLogMode(QTestLog::XunitXML); } else if (strcmp(argv[i], "-xml") == 0) { @@ -1146,6 +1154,32 @@ static void qParseArgs(int argc, char *argv[]) } else if (argv[i][0] == '-') { printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); + } else if (qml) { + // We can't check the availability of test functions until + // we load the QML files. So just store the data for now. + int colon = -1; + int offset; + for(offset = 0; *(argv[i]+offset); ++offset) { + if (*(argv[i]+offset) == ':') { + if (*(argv[i]+offset+1) == ':') { + // "::" is used as a test name separator. + // e.g. "ClickTests::test_click:row1". + ++offset; + } else { + colon = offset; + break; + } + } + } + if (colon == -1) { + QTest::testFunctions += QString::fromLatin1(argv[i]); + QTest::testTags += QString(); + } else { + QTest::testFunctions += + QString::fromLatin1(argv[i], colon); + QTest::testTags += + QString::fromLatin1(argv[i] + colon + 1); + } } else { int colon = -1; char buf[512], *data=0; @@ -1695,7 +1729,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QTEST_ASSERT(metaObject); QTestResult::setCurrentTestObject(metaObject->className()); - qParseArgs(argc, argv); + qtest_qParseArgs(argc, argv, false); #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { const QStringList origAppArgs(QCoreApplication::arguments()); diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index 08c86d1..6648beb 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QBenchmarkResult; -class QTestLog +class Q_TESTLIB_EXPORT QTestLog { public: enum LogMode { Plain = 0, XML, LightXML, XunitXML }; diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h index 15523f5..7ff120a 100644 --- a/src/testlib/qtestresult_p.h +++ b/src/testlib/qtestresult_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE class QTestResultPrivate; class QTestData; -class QTestResult +class Q_TESTLIB_EXPORT QTestResult { public: enum TestLocation { NoWhere = 0, DataFunc = 1, InitFunc = 2, Func = 3, CleanupFunc = 4 }; diff --git a/src/testlib/qtesttable_p.h b/src/testlib/qtesttable_p.h index d085b57..f835506 100644 --- a/src/testlib/qtesttable_p.h +++ b/src/testlib/qtesttable_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE class QTestData; class QTestTablePrivate; -class QTestTable +class Q_TESTLIB_EXPORT QTestTable { public: QTestTable(); -- cgit v0.12 From fcd12e1826f2974ec9cf10af4e6893774d666362 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 18 Feb 2011 10:53:16 +1000 Subject: Fix compilation on old Symbian platforms Task-number: QTBUG-17472 Reviewed-by: Martin Jones --- tools/qml/qmlruntime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 36915d1..c746d8e 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -50,7 +50,7 @@ # include # include # include "ui_recopts_maemo5.h" -#else +#elif !defined(__SERIES60_31__) && !defined(__S60_32__) # include "ui_recopts.h" #endif -- cgit v0.12 From b1d036fd9fc45060bf2886114051eef8db735311 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 18 Feb 2011 11:33:17 +1000 Subject: Fix FocusScope example. Task-number: QTBUG-17501 Reviewed-by: Martin Jones --- examples/declarative/keyinteraction/focus/focus.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/declarative/keyinteraction/focus/focus.qml b/examples/declarative/keyinteraction/focus/focus.qml index 9cb1fef..935db25 100644 --- a/examples/declarative/keyinteraction/focus/focus.qml +++ b/examples/declarative/keyinteraction/focus/focus.qml @@ -91,7 +91,7 @@ Rectangle { MouseArea { anchors.fill: parent; anchors.margins: -10 - onClicked: window.state = "contextMenuOpen" + onClicked: contextMenu.focus = true } } -- cgit v0.12 From 9e063f7e4790cc15b279a44807ff59c620d53ce6 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 18 Feb 2011 17:19:05 +1000 Subject: Fix TextEdit auto test failure on windows. A leaked window from a previous test held focus meaning events weren't being delivered to the expected widget. Delete the offending widget. --- .../auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 87c2c60..a052752 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1179,6 +1179,8 @@ void tst_qdeclarativetextedit::dragMouseSelection() QVERIFY(str2.length() > 3); QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. + + delete canvas; } void tst_qdeclarativetextedit::mouseSelectionMode_data() -- cgit v0.12