From 9e2179544157a28aadfbbeaaf787a4a29f9996a2 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 26 Jan 2011 13:01:08 +0100 Subject: Plug memory leak when using qt_mac_set_dock_menu() on Cocoa Task-number: QTBUG-16918 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qt_cocoa_helpers_mac.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 3820bfc..20c1ddb 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1391,6 +1391,7 @@ void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayI void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) { + QMacCocoaAutoReleasePool pool; OSMenuRef menu = static_cast(theMenu); if (collapse) { bool previousIsSeparator = true; // setting to true kills all the separators placed at the top. -- cgit v0.12 From 8611cf0ba0dbd0ddd742a02e1c60669e83cd1710 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 3 Feb 2011 17:15:36 +1000 Subject: Allow unknown types to be passed opaquely through signals Task-number: QTBUG-16683 --- src/declarative/qml/qdeclarativeboundsignal.cpp | 21 ++++-- src/declarative/qml/qdeclarativemetatype.cpp | 87 ++++++++++++++++++++++ src/declarative/qml/qdeclarativemetatype_p.h | 1 + .../data/signalWithUnknownTypes.qml | 5 ++ .../qdeclarativeecmascript/testtypes.cpp | 2 + .../declarative/qdeclarativeecmascript/testtypes.h | 9 +++ .../tst_qdeclarativeecmascript.cpp | 21 ++++++ 7 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index d5c9bfc..28dfea9 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -197,13 +197,12 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method, - QObject *parent) + QObject *parent) : QObject(parent), types(0), values(0) { MetaObject *mo = new MetaObject(this); // ### Optimize! - // ### Ensure only supported types are allowed, otherwise it might crash QMetaObjectBuilder mob; mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject); mob.setClassName("QDeclarativeBoundSignalParameters"); @@ -226,9 +225,15 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*"); prop.setWritable(false); } else { - types[ii] = t; - QMetaPropertyBuilder prop = mob.addProperty(name, type); - prop.setWritable(false); + if (QDeclarativeMetaType::canCopy(t)) { + types[ii] = t; + QMetaPropertyBuilder prop = mob.addProperty(name, type); + prop.setWritable(false); + } else { + types[ii] = 0x80000000 | t; + QMetaPropertyBuilder prop = mob.addProperty(name, "QVariant"); + prop.setWritable(false); + } } } myMetaObject = mob.toMetaObject(); @@ -259,7 +264,11 @@ int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, voi return -1; if (c == QMetaObject::ReadProperty && id >= 1) { - QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]); + if (types[id - 1] & 0x80000000) { + *((QVariant *)a[0]) = QVariant(types[id - 1] & 0x7FFFFFFF, values[id]); + } else { + QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]); + } return -1; } else { return qt_metacall(c, id, a); diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 4867cc5..bf1f699 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -1015,6 +1015,93 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QScriptValue); QT_BEGIN_NAMESPACE + +bool QDeclarativeMetaType::canCopy(int type) +{ + switch(type) { + case QMetaType::VoidStar: + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + case QMetaType::Long: + case QMetaType::Int: + case QMetaType::Short: + case QMetaType::Char: + case QMetaType::ULong: + case QMetaType::UInt: + case QMetaType::LongLong: + case QMetaType::ULongLong: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::Bool: + case QMetaType::Float: + case QMetaType::Double: + case QMetaType::QChar: + case QMetaType::QVariantMap: + case QMetaType::QVariantHash: + case QMetaType::QVariantList: + case QMetaType::QByteArray: + case QMetaType::QString: + case QMetaType::QStringList: + case QMetaType::QBitArray: + case QMetaType::QDate: + case QMetaType::QTime: + case QMetaType::QDateTime: + case QMetaType::QUrl: + case QMetaType::QLocale: + case QMetaType::QRect: + case QMetaType::QRectF: + case QMetaType::QSize: + case QMetaType::QSizeF: + case QMetaType::QLine: + case QMetaType::QLineF: + case QMetaType::QPoint: + case QMetaType::QPointF: + case QMetaType::QVector3D: +#ifndef QT_NO_REGEXP + case QMetaType::QRegExp: +#endif + case QMetaType::Void: +#ifdef QT3_SUPPORT + case QMetaType::QColorGroup: +#endif + case QMetaType::QFont: + case QMetaType::QPixmap: + case QMetaType::QBrush: + case QMetaType::QColor: + case QMetaType::QPalette: + case QMetaType::QIcon: + case QMetaType::QImage: + case QMetaType::QPolygon: + case QMetaType::QRegion: + case QMetaType::QBitmap: +#ifndef QT_NO_CURSOR + case QMetaType::QCursor: +#endif + case QMetaType::QSizePolicy: + case QMetaType::QKeySequence: + case QMetaType::QPen: + case QMetaType::QTextLength: + case QMetaType::QTextFormat: + case QMetaType::QMatrix: + case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: + return true; + + default: + if (type == qMetaTypeId() || + type == qMetaTypeId() || + typeCategory(type) != Unknown) { + return true; + } + break; + } + + return false; +} + /*! Copies \a copy into \a data, assuming they both are of type \a type. If \a copy is zero, a default type is copied. Returns true if the copy was diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 0e4d61c..aab1c31 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -69,6 +69,7 @@ class QDeclarativeTypePrivate; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMetaType { public: + static bool canCopy(int type); static bool copy(int type, void *data, const void *copy = 0); static QList qmlTypeNames(); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml new file mode 100644 index 0000000..49293ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + onSignalWithUnknownType: variantMethod(arg); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index d7f0f42..7e63bd5 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -125,6 +125,8 @@ void registerTypes() qmlRegisterExtendedType("Qt.test",1,0,"QWidget"); qmlRegisterType("Qt.test",1,0,"QPlainTextEdit"); + + qRegisterMetaType("MyQmlObject::MyType"); } #include "testtypes.moc" diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index fb54a54..081cc4c 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -152,6 +152,11 @@ public: MyQmlObject *myinvokableObject; Q_INVOKABLE MyQmlObject *returnme() { return this; } + struct MyType { + int value; + }; + QVariant variant() const { return m_variant; } + signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); @@ -159,6 +164,7 @@ signals: void objectChanged(); void anotherBasicSignal(); void thirdBasicSignal(); + void signalWithUnknownType(const MyQmlObject::MyType &arg); public slots: void deleteMe() { delete this; } @@ -166,6 +172,7 @@ public slots: void method(int a) { if(a == 163) m_methodIntCalled = true; } void setString(const QString &s) { m_string = s; } void myinvokable(MyQmlObject *o) { myinvokableObject = o; } + void variantMethod(const QVariant &v) { m_variant = v; } private: friend class tst_qdeclarativeecmascript; @@ -178,6 +185,7 @@ private: int m_value; int m_resetProperty; QRegExp m_regExp; + QVariant m_variant; }; QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) @@ -898,6 +906,7 @@ QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) QML_DECLARE_TYPE(MyRevisionedClass) QML_DECLARE_TYPE(MyRevisionedSubclass) +Q_DECLARE_METATYPE(MyQmlObject::MyType) void registerTypes(); diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index f66cd0b..b19b3c9 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -142,6 +142,7 @@ private slots: void compiled(); void numberAssignment(); void propertySplicing(); + void signalWithUnknownTypes(); void bug1(); void bug2(); @@ -2340,6 +2341,26 @@ void tst_qdeclarativeecmascript::propertySplicing() delete object; } +// QTBUG-16683 +void tst_qdeclarativeecmascript::signalWithUnknownTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml")); + + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + MyQmlObject::MyType type; + type.value = 0x8971123; + emit object->signalWithUnknownType(type); + + MyQmlObject::MyType result = qvariant_cast(object->variant()); + + QCOMPARE(result.value, type.value); + + + delete object; +} + // Test that assigning a null object works // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4 void tst_qdeclarativeecmascript::nullObjectBinding() -- cgit v0.12 From 147df10403ba280b3f04c1e3d6c4b1cf386abe5d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 3 Feb 2011 12:28:27 +0100 Subject: Don't crash when creating backtrace for built-in JS function When the JIT is enabled, NativeFunctionWrapper (used for built-in functions such as Array.prototype.forEach) inherits JSFunction, so we must check whether the function is actually a JS (script) function before we start accessing script-specific properties. Task-number: QTBUG-17137 Reviewed-by: Olivier Goffart --- src/script/api/qscriptcontextinfo.cpp | 3 ++- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index db6b2d7..d39abe6 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -181,7 +181,8 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::JSObject *callee = frame->callee(); if (callee && callee->inherits(&JSC::InternalFunction::info)) functionName = JSC::asInternalFunction(callee)->name(frame); - if (callee && callee->inherits(&JSC::JSFunction::info)) { + if (callee && callee->inherits(&JSC::JSFunction::info) + && !JSC::asFunction(callee)->isHostFunction()) { functionType = QScriptContextInfo::ScriptFunction; JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); functionStartLineNumber = body->lineNo(); diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 1a1576b..dd21555 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -860,6 +860,21 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("js recursive") << source << expected; } + + { + QString source = QString::fromLatin1( + "[0].forEach(\n" + " function() {\n" + " result = bt();\n" + "}); result"); + + QStringList expected; + expected << "() at -1" + << "(0, 0, 0) at testfile:3" + << "forEach(0) at -1" + << "() at testfile:4"; + QTest::newRow("js callback from built-in") << source << expected; + } } -- cgit v0.12 From 71eb2bd23604d9c809f143496f781c1d5c065473 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 28 Jan 2011 17:46:30 +0100 Subject: move multiple inclusion check for feature files to correct location previously, features specified with an absolute path would not be covered by the multiple inclusion guard, unlike the one specified just by a name. this is of theoretical value only, as nobody specifies features via absolute path anyway ... Reviewed-by: mariusSO --- qmake/project.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 8d8d9e0..4e2d743 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1681,10 +1681,10 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QMap Date: Fri, 28 Jan 2011 17:51:22 +0100 Subject: use const ref Reviewed-by: mariusSO --- qmake/project.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 4e2d743..1a13639 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -228,7 +228,7 @@ static QString varMap(const QString &x) return ret; } -static QStringList split_arg_list(QString params) +static QStringList split_arg_list(const QString ¶ms) { int quote = 0; QStringList args; -- cgit v0.12 From dbfca8da2807921069c0e53da33f6e7bd3e73479 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 28 Jan 2011 18:03:16 +0100 Subject: complain about unmatched quotes/parens using WarnDeprecated instead of WarnParser is a bit backwards, but we need something which is on by default and i don't feel like introducing a second parser warning mode for that. Reviewed-by: mariusSO --- qmake/project.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 1a13639..9c99c44 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -280,6 +280,8 @@ static QStringList split_arg_list(const QString ¶ms) ++last; } } + // Could do a check for unmatched parens here, but split_value_list() + // is called on all our output, so mistakes will be caught anyway. return args; } @@ -288,6 +290,7 @@ static QStringList split_value_list(const QString &vals) QString build; QStringList ret; QStack quote; + int parens = 0; const ushort LPAREN = '('; const ushort RPAREN = ')'; @@ -298,7 +301,7 @@ static QStringList split_value_list(const QString &vals) ushort unicode; const QChar *vals_data = vals.data(); const int vals_len = vals.length(); - for(int x = 0, parens = 0; x < vals_len; x++) { + for(int x = 0; x < vals_len; x++) { unicode = vals_data[x].unicode(); if(x != (int)vals_len-1 && unicode == BACKSLASH && (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) { @@ -322,6 +325,11 @@ static QStringList split_value_list(const QString &vals) } if(!build.isEmpty()) ret << build; + if (parens) + warn_msg(WarnDeprecated, "%s:%d: Unmatched parentheses are deprecated.", + parser.file.toLatin1().constData(), parser.line_no); + // Could do a check for unmatched quotes here, but doVariableReplaceExpand() + // is called on all our output, so mistakes will be caught anyway. return ret; } @@ -2966,6 +2974,9 @@ QMakeProject::doVariableReplaceExpand(const QString &str, QMap Date: Thu, 3 Feb 2011 16:17:26 +0100 Subject: tst_qsvgrenderer: works on shadowbuild --- tests/auto/qsvgrenderer/qsvgrenderer.pro | 3 +++ tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/auto/qsvgrenderer/qsvgrenderer.pro b/tests/auto/qsvgrenderer/qsvgrenderer.pro index 0b785e3..9f0f886 100644 --- a/tests/auto/qsvgrenderer/qsvgrenderer.pro +++ b/tests/auto/qsvgrenderer/qsvgrenderer.pro @@ -18,3 +18,6 @@ wince*|symbian { } } +!symbian: { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 5928a09..9fbf2a0 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -51,6 +51,10 @@ #include #include +#ifndef SRCDIR +#define SRCDIR +#endif + //TESTED_CLASS= //TESTED_FILES= @@ -647,13 +651,13 @@ void tst_QSvgRenderer::gradientRefs() #ifndef QT_NO_COMPRESS void tst_QSvgRenderer::testGzLoading() { - QSvgRenderer renderer(QLatin1String("heart.svgz")); + QSvgRenderer renderer(QLatin1String(SRCDIR "heart.svgz")); QVERIFY(renderer.isValid()); QSvgRenderer resourceRenderer(QLatin1String(":/heart.svgz")); QVERIFY(resourceRenderer.isValid()); - QFile largeFileGz("large.svgz"); + QFile largeFileGz(SRCDIR "large.svgz"); largeFileGz.open(QIODevice::ReadOnly); QByteArray data = largeFileGz.readAll(); QSvgRenderer autoDetectGzData(data); -- cgit v0.12 From 9f8a181a619649c8a227e92f3d16677f4b7cb30a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 4 Feb 2011 14:11:09 +1000 Subject: Clarify case preservation in QDeclarativeImageProviders Task-number: QTBUG-15905 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeengine.cpp | 2 +- src/declarative/qml/qdeclarativeimageprovider.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 890f500..37df226 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -776,7 +776,7 @@ void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativ { Q_D(QDeclarativeEngine); QMutexLocker locker(&d->mutex); - d->imageProviders.insert(providerId, QSharedPointer(provider)); + d->imageProviders.insert(providerId.toLower(), QSharedPointer(provider)); } /*! diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp index 560077f..f111c20 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.cpp +++ b/src/declarative/qml/qdeclarativeimageprovider.cpp @@ -75,6 +75,16 @@ public: invokes the appropriate image provider according to the providers that have been registered through QDeclarativeEngine::addImageProvider(). + Note that the identifiers are case-insensitive, but the rest of the URL will be passed on with + preserved case. For example, the below snippet would still specify that the image is loaded by the + image provider named "myimageprovider", but it would request a different image than the above snippet + ("Image.png" instead of "image.png"). + \qml + Image { source: "image://MyImageProvider/Image.png" } + \endqml + + If you want the rest of the URL to be case insensitive, you will have to take care + of that yourself inside your image provider. \section2 An example -- cgit v0.12 From 80d0fe9cbd92288a08d5ced8767f1edb651dae37 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 3 Feb 2011 16:54:13 +1000 Subject: AnimatedImage does not notify on status change. Task-number: QTBUG-16520 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativeanimatedimage.cpp | 22 +++++++++++++++++--- .../graphicsitems/qdeclarativeanimatedimage_p.h | 1 + .../qdeclarativeanimatedimage/data/qtbug-16520.qml | 17 +++++++++++++++ .../tst_qdeclarativeanimatedimage.cpp | 24 ++++++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index 27bb6a2..016b87d 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -221,13 +221,22 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) } d->url = url; + emit sourceChanged(d->url); - if (url.isEmpty()) { + if (isComponentComplete()) + load(); +} + +void QDeclarativeAnimatedImage::load() +{ + Q_D(QDeclarativeAnimatedImage); + + if (d->url.isEmpty()) { delete d->_movie; d->status = Null; } else { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { //### should be unified with movieRequestFinished d->_movie = new QMovie(lf); @@ -235,6 +244,8 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString(); delete d->_movie; d->_movie = 0; + d->status = Error; + emit statusChanged(d->status); return; } connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)), @@ -264,7 +275,6 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(movieRequestFinished())); } - emit statusChanged(d->status); } @@ -294,6 +304,8 @@ void QDeclarativeAnimatedImage::movieRequestFinished() #endif delete d->_movie; d->_movie = 0; + d->status = Error; + emit statusChanged(d->status); return; } connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)), @@ -310,6 +322,8 @@ void QDeclarativeAnimatedImage::movieRequestFinished() if(d->paused) d->_movie->setPaused(true); d->setPixmap(d->_movie->currentPixmap()); + d->status = Ready; + emit statusChanged(d->status); } void QDeclarativeAnimatedImage::movieUpdate() @@ -336,6 +350,8 @@ void QDeclarativeAnimatedImage::componentComplete() { Q_D(QDeclarativeAnimatedImage); QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage + if (d->url.isValid()) + load(); if (!d->reply) { setCurrentFrame(d->preset_currentframe); d->preset_currentframe = 0; diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h index e5025bf..e2ed70b 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h @@ -97,6 +97,7 @@ private Q_SLOTS: void playingStatusChanged(); protected: + virtual void load(); void componentComplete(); private: diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml b/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml new file mode 100644 index 0000000..cf5b601 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml @@ -0,0 +1,17 @@ +import QtQuick 1.0 + +Rectangle { + width: 500 + height: 500 + + AnimatedImage { + objectName: "anim" + anchors.centerIn: parent + asynchronous: true + opacity: status == AnimatedImage.Ready ? 1 : 0 + + Behavior on opacity { + NumberAnimation { duration: 1000 } + } + } +} diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp index eba4239..104ee15 100644 --- a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp +++ b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp @@ -75,6 +75,7 @@ private slots: void sourceSize(); void sourceSizeReadOnly(); void invalidSource(); + void qtbug_16520(); private: QPixmap grabScene(QGraphicsScene *scene, int width, int height); @@ -307,6 +308,29 @@ void tst_qdeclarativeanimatedimage::invalidSource() QVERIFY(!anim->isPaused()); QCOMPARE(anim->currentFrame(), 0); QCOMPARE(anim->frameCount(), 0); + QTRY_VERIFY(anim->status() == 3); +} + +void tst_qdeclarativeanimatedimage::qtbug_16520() +{ + TestHTTPServer server(14449); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/qtbug-16520.qml")); + QTRY_VERIFY(component.isReady()); + + QDeclarativeRectangle *root = qobject_cast(component.create()); + QVERIFY(root); + QDeclarativeAnimatedImage *anim = root->findChild("anim"); + + anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif"); + + QTRY_VERIFY(anim->opacity() == 0); + QTRY_VERIFY(anim->opacity() == 1); + + delete anim; } QTEST_MAIN(tst_qdeclarativeanimatedimage) -- cgit v0.12 From a9f1eaa6a368bf7a72b52c428728a3e3e0a76209 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 4 Feb 2011 10:36:38 +1000 Subject: modelChanged() should not be emitted until view is repopulated Otherwise, itemAt() returns invalid values at the time that modelChanged() is emitted. Task-number: QTBUG-17156 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativerepeater.cpp | 2 +- .../qdeclarativerepeater/data/modelChanged.qml | 26 +++++++++++++++++ .../tst_qdeclarativerepeater.cpp | 33 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp index 8455513..4d0f34c 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp +++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp @@ -198,7 +198,6 @@ void QDeclarativeRepeater::setModel(const QVariant &model) */ } d->dataSource = model; - emit modelChanged(); QObject *object = qvariant_cast(model); QDeclarativeVisualModel *vim = 0; if (object && (vim = qobject_cast(object))) { @@ -226,6 +225,7 @@ void QDeclarativeRepeater::setModel(const QVariant &model) */ regenerate(); } + emit modelChanged(); emit countChanged(); } diff --git a/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml b/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml new file mode 100644 index 0000000..0b57d50 --- /dev/null +++ b/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml @@ -0,0 +1,26 @@ +import QtQuick 1.1 + +Column { + Repeater { + id: repeater + objectName: "repeater" + + property int itemsCount + property variant itemsFound: [] + + delegate: Rectangle { + color: "red" + width: (index+1)*50 + height: 50 + } + + onModelChanged: { + repeater.itemsCount = repeater.count + var items = [] + for (var i=0; icount(), dataA.count()); + for (int i=0; icount(); i++) + QCOMPARE(repeater->itemAt(i), container->childItems().at(i+1)); // +1 to skip first Text object + QSignalSpy modelChangedSpy(repeater, SIGNAL(modelChanged())); QSignalSpy countSpy(repeater, SIGNAL(countChanged())); QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); @@ -547,6 +551,7 @@ void tst_QDeclarativeRepeater::resetModel() ctxt->setContextProperty("testData", dataB); QCOMPARE(repeater->count(), dataB.count()); + QCOMPARE(modelChangedSpy.count(), 1); QCOMPARE(countSpy.count(), 1); QCOMPARE(removedSpy.count(), dataA.count()); QCOMPARE(addedSpy.count(), dataB.count()); @@ -554,6 +559,7 @@ void tst_QDeclarativeRepeater::resetModel() QCOMPARE(addedSpy.at(i).at(0).toInt(), i); QCOMPARE(addedSpy.at(i).at(1).value(), repeater->itemAt(i)); } + modelChangedSpy.clear(); countSpy.clear(); removedSpy.clear(); addedSpy.clear(); @@ -562,6 +568,7 @@ void tst_QDeclarativeRepeater::resetModel() repeater->setModel(dataA); QCOMPARE(repeater->count(), dataA.count()); + QCOMPARE(modelChangedSpy.count(), 1); QCOMPARE(countSpy.count(), 1); QCOMPARE(removedSpy.count(), dataB.count()); QCOMPARE(addedSpy.count(), dataA.count()); @@ -569,6 +576,32 @@ void tst_QDeclarativeRepeater::resetModel() QCOMPARE(addedSpy.at(i).at(0).toInt(), i); QCOMPARE(addedSpy.at(i).at(1).value(), repeater->itemAt(i)); } + + delete canvas; +} + +// QTBUG-17156 +void tst_QDeclarativeRepeater::modelChanged() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, TEST_FILE("/modelChanged.qml")); + + QDeclarativeItem *rootObject = qobject_cast(component.create()); + QVERIFY(rootObject); + QDeclarativeRepeater *repeater = findItem(rootObject, "repeater"); + QVERIFY(repeater); + + repeater->setModel(4); + QCOMPARE(repeater->count(), 4); + QCOMPARE(repeater->property("itemsCount"), 4); + QCOMPARE(repeater->property("itemsFound").toList().count(), 4); + + repeater->setModel(10); + QCOMPARE(repeater->count(), 10); + QCOMPARE(repeater->property("itemsCount"), 10); + QCOMPARE(repeater->property("itemsFound").toList().count(), 10); + + delete rootObject; } void tst_QDeclarativeRepeater::properties() -- cgit v0.12 From 9c61e9a40e774fe32b16c133a5cdd6b9d9d29d83 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Tue, 2 Nov 2010 12:14:03 +1000 Subject: QSqlTableModel/QSqlQueryModel and insertColumns problem. After inserting a column, fetching data through QSqlTableModel was off by one or more, since it passed the indexInQuery through to QSQM. Also, the headerData would sometimes return a blank string for an inserted column, and sometimes the column number. The autotests have been beefed up a little to check insertRows and insertColumns play nicely. Change-Id: I7399d4c4d94f958884b67ab9b39b5cf2485d8416 Task-number: QTBUG-12626 Reviewed-by: Charles Yin --- src/sql/models/qsqlquerymodel.cpp | 6 +- src/sql/models/qsqltablemodel.cpp | 10 +- tests/auto/qsqldatabase/tst_databases.h | 24 ++++ tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp | 31 ++++- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 166 ++++++++++++++++++++++- 5 files changed, 223 insertions(+), 14 deletions(-) diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 8730192..9800e67 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -279,7 +279,11 @@ QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, in val = d->headers.value(section).value(Qt::EditRole); if (val.isValid()) return val; - if (role == Qt::DisplayRole && d->rec.count() > section) + + // See if it's an inserted column (iiq.column() != -1) + QModelIndex dItem = indexInQuery(createIndex(0, section)); + + if (role == Qt::DisplayRole && d->rec.count() > section && dItem.column() != -1) return d->rec.fieldName(section); } return QAbstractItemModel::headerData(section, orientation, role); diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 3bb46cc..6f9c284 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -423,6 +423,10 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole)) return QVariant(); + // Problem.. we need to use QSQM::indexInQuery to handle inserted columns + // but inserted rows we need to handle + // and indexInQuery is not virtual (grrr) so any values we pass to QSQM need + // to handle the insertedRows QModelIndex item = indexInQuery(index); switch (d->strategy) { @@ -450,7 +454,9 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const return var; break; } } - return QSqlQueryModel::data(item, role); + + // We need to handle row mapping here, but not column mapping + return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role); } /*! @@ -1225,7 +1231,7 @@ int QSqlTableModel::rowCount(const QModelIndex &parent) const QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const { Q_D(const QSqlTableModel); - const QModelIndex it = QSqlQueryModel::indexInQuery(item); + const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only if (d->strategy == OnManualSubmit) { int rowOffset = 0; QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin(); diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index 5dcf754..350e0d0 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -166,6 +167,29 @@ public: return count; } + int fillTestTableWithStrategies( const QString& driverPrefix = QString() ) const + { + QTest::addColumn( "dbName" ); + QTest::addColumn("submitpolicy_i"); + int count = 0; + + for ( int i = 0; i < dbNames.count(); ++i ) { + QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) ); + + if ( !db.isValid() ) + continue; + + if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) { + QTest::newRow( QString("%1 [field]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnFieldChange; + QTest::newRow( QString("%1 [row]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnRowChange; + QTest::newRow( QString("%1 [manual]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnManualSubmit; + ++count; + } + } + + return count; + } + void addDb( const QString& driver, const QString& dbName, const QString& user = QString(), const QString& passwd = QString(), const QString& host = QString(), int port = -1, const QString params = QString() ) diff --git a/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp b/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp index 0ca1417..e876764 100644 --- a/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp +++ b/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp @@ -318,6 +318,11 @@ void tst_QSqlQueryModel::insertColumn() model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db)); model.fetchMore(); // necessary??? + bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"); + const QString idColumn(isToUpper ? "ID" : "id"); + const QString nameColumn(isToUpper ? "NAME" : "name"); + const QString titleColumn(isToUpper ? "TITLE" : "title"); + QSignalSpy spy(&model, SIGNAL(columnsInserted(QModelIndex, int, int))); QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); @@ -325,6 +330,11 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); QCOMPARE(model.data(model.index(0, 3)), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), QString("4")); + QVERIFY(model.insertColumn(1)); QCOMPARE(spy.count(), 1); @@ -344,6 +354,12 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.data(model.index(0, 3)).toInt(), 1); QCOMPARE(model.data(model.index(0, 4)), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), QString("2")); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), QString("5")); + QVERIFY(!model.insertColumn(-1)); QVERIFY(!model.insertColumn(100)); QVERIFY(!model.insertColumn(1, model.index(1, 1))); @@ -378,14 +394,21 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.indexInQuery(model.index(0, 5)).column(), -1); QCOMPARE(model.indexInQuery(model.index(0, 6)).column(), -1); - bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"); QCOMPARE(model.record().field(0).name(), QString()); - QCOMPARE(model.record().field(1).name(), isToUpper ? QString("ID") : QString("id")); + QCOMPARE(model.record().field(1).name(), idColumn); QCOMPARE(model.record().field(2).name(), QString()); - QCOMPARE(model.record().field(3).name(), isToUpper ? QString("NAME") : QString("name")); - QCOMPARE(model.record().field(4).name(), isToUpper ? QString("TITLE") : QString("title")); + QCOMPARE(model.record().field(3).name(), nameColumn); + QCOMPARE(model.record().field(4).name(), titleColumn); QCOMPARE(model.record().field(5).name(), QString()); QCOMPARE(model.record().field(6).name(), QString()); + + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("1")); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), QString("3")); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(5, Qt::Horizontal).toString(), QString("6")); + QCOMPARE(model.headerData(6, Qt::Horizontal).toString(), QString("7")); } void tst_QSqlQueryModel::record() diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index f9fcaf0..1821d9c 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -78,11 +78,13 @@ private slots: void select_data() { generic_data(); } void select(); + void insertColumns_data() { generic_data_with_strategies(); } + void insertColumns(); void submitAll_data() { generic_data(); } void submitAll(); void setRecord_data() { generic_data(); } void setRecord(); - void insertRow_data() { generic_data(); } + void insertRow_data() { generic_data_with_strategies(); } void insertRow(); void insertRecord_data() { generic_data(); } void insertRecord(); @@ -130,6 +132,7 @@ private slots: void insertBeforeDelete(); private: void generic_data(const QString& engine=QString()); + void generic_data_with_strategies(const QString& engine=QString()); }; tst_QSqlTableModel::tst_QSqlTableModel() @@ -227,7 +230,17 @@ void tst_QSqlTableModel::recreateTestTables() void tst_QSqlTableModel::generic_data(const QString &engine) { if ( dbs.fillTestTable(engine) == 0 ) { - if(engine.isEmpty()) + if (engine.isEmpty()) + QSKIP( "No database drivers are available in this Qt configuration", SkipAll ); + else + QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll ); + } +} + +void tst_QSqlTableModel::generic_data_with_strategies(const QString &engine) +{ + if ( dbs.fillTestTableWithStrategies(engine) == 0 ) { + if (engine.isEmpty()) QSKIP( "No database drivers are available in this Qt configuration", SkipAll ); else QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll ); @@ -289,6 +302,81 @@ void tst_QSqlTableModel::select() QCOMPARE(model.data(model.index(3, 3)), QVariant()); } +void tst_QSqlTableModel::insertColumns() +{ + // Just like the select test, with extra stuff + QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(submitpolicy); + + QVERIFY_SQL(model, select()); + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 3); + + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 3)), QVariant()); + + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 3)), QVariant()); + + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 3)), QVariant()); + + QCOMPARE(model.data(model.index(3, 0)), QVariant()); + QCOMPARE(model.data(model.index(3, 1)), QVariant()); + QCOMPARE(model.data(model.index(3, 2)), QVariant()); + QCOMPARE(model.data(model.index(3, 3)), QVariant()); + + // Now add a column at 0 and 2 + model.insertColumn(0); + model.insertColumn(2); + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 5); + + QCOMPARE(model.data(model.index(0, 0)), QVariant()); + QCOMPARE(model.data(model.index(0, 1)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 2)), QVariant()); + QCOMPARE(model.data(model.index(0, 3)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 4)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 5)), QVariant()); + + QCOMPARE(model.data(model.index(1, 0)), QVariant()); + QCOMPARE(model.data(model.index(1, 1)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 2)), QVariant()); + QCOMPARE(model.data(model.index(1, 3)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 4)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 5)), QVariant()); + + QCOMPARE(model.data(model.index(2, 0)), QVariant()); + QCOMPARE(model.data(model.index(2, 1)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 2)), QVariant()); + QCOMPARE(model.data(model.index(2, 3)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 4)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 5)), QVariant()); + + QCOMPARE(model.data(model.index(3, 0)), QVariant()); + QCOMPARE(model.data(model.index(3, 1)), QVariant()); + QCOMPARE(model.data(model.index(3, 2)), QVariant()); + QCOMPARE(model.data(model.index(3, 3)), QVariant()); + QCOMPARE(model.data(model.index(3, 4)), QVariant()); + QCOMPARE(model.data(model.index(3, 5)), QVariant()); +} + void tst_QSqlTableModel::setRecord() { QFETCH(QString, dbName); @@ -339,26 +427,90 @@ void tst_QSqlTableModel::setRecord() void tst_QSqlTableModel::insertRow() { QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlTableModel model(0, db); - model.setEditStrategy(QSqlTableModel::OnRowChange); + model.setEditStrategy(submitpolicy); model.setTable(test); model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QVERIFY(model.insertRow(2)); + + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 0); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 0); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); + QSqlRecord rec = model.record(1); rec.setValue(0, 42); - rec.setValue(1, QString("vohi")); + rec.setValue(1, QString("francis")); + + // FieldChange updates immediately and resorts + // Row/Manual submit does not resort QVERIFY(model.setRecord(2, rec)); - QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); - QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); - QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + + // See comment above setRecord + if (submitpolicy == QSqlTableModel::OnFieldChange) { + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); + } else { + QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); + } QVERIFY(model.submitAll()); + + // After the submit we should have the resorted view + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); + } void tst_QSqlTableModel::insertRecord() -- cgit v0.12 From 3bed865c35d8eb920ba5a68276fdf1690c834a64 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Wed, 3 Nov 2010 11:58:36 +1000 Subject: Make sure that setRecord emits dataChanged() with OnManualSubmit. Since the change is immediately visible through data(), this is needed so that QSortFilterProxyModel etc work correctly. Change-Id: Ied7afce2e6a1f516b502d3501f9d214df54e52f2 Task-number: QTBUG-14831 Reviewed-by: Charles Yin --- src/sql/models/qsqltablemodel.cpp | 3 +++ tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 6f9c284..61cd1d3 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -1338,6 +1338,9 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &record) else mrow.rec.setValue(idx, record.value(i)); } + + if (isOk) + emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); return isOk; } } return false; diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index 1821d9c..9428ef4 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -402,9 +402,14 @@ void tst_QSqlTableModel::setRecord() rec.setValue(2, rec.value(2).toString() + 'X'); QVERIFY(model.setRecord(i, rec)); - if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) + if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) { + // setRecord should emit dataChanged() itself for manualSubmit + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).count(), 2); + QCOMPARE(qvariant_cast(spy.at(0).at(0)), model.index(i, 0)); + QCOMPARE(qvariant_cast(spy.at(0).at(1)), model.index(i, rec.count() - 1)); QVERIFY(model.submitAll()); - else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1) + } else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1) model.submit(); else { // dataChanged() is not emitted when submitAll() is called -- cgit v0.12 From 741a5114c2c6bf4d89068d861db90c456cce371b Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Wed, 3 Nov 2010 15:45:43 +1000 Subject: Update some documentation about what happens with select()/setQuery(). Change-Id: I5f1afada766d40273526f2cd7537ad68d5f9d09a Task-number: QTBUG-12094 Reviewed-by: Charles Yin --- src/sql/models/qsqlquerymodel.cpp | 2 ++ src/sql/models/qsqltablemodel.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 9800e67..fbc31ff 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -310,6 +310,8 @@ void QSqlQueryModel::queryChange() lastError() can be used to retrieve verbose information if there was an error setting the query. + \note Calling setQuery() will remove any inserted columns. + \sa query(), QSqlQuery::isActive(), QSqlQuery::setForwardOnly(), lastError() */ void QSqlQueryModel::setQuery(const QSqlQuery &query) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 61cd1d3..c6efbad 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -393,6 +393,8 @@ QString QSqlTableModel::tableName() const specified filter and sort condition, and returns true if successful; otherwise returns false. + \note Calling select() will revert any unsubmitted changes and remove any inserted columns. + \sa setTable(), setFilter(), selectStatement() */ bool QSqlTableModel::select() -- cgit v0.12 From d300e8208928084b62bbde01fb81bd66bc967bc8 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Thu, 4 Nov 2010 15:47:51 +1000 Subject: Try to document that invalid database arguments use the default database. Some places documented this, some didn't. Change-Id: Id66678dbcd9af6ec9687db745ba6f5506e951d1d Task-number: QTBUG-3240 Reviewed-by: Charles Yin --- src/sql/kernel/qsqlquery.cpp | 3 ++- src/sql/models/qsqlquerymodel.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 4b92a3e..3cdc8b1 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -272,7 +272,7 @@ static void qInit(QSqlQuery *q, const QString& query, QSqlDatabase db) /*! Constructs a QSqlQuery object using the SQL \a query and the - database \a db. If \a db is not specified, the application's + database \a db. If \a db is not specified, or is invalid, the application's default database is used. If \a query is not an empty string, it will be executed. @@ -286,6 +286,7 @@ QSqlQuery::QSqlQuery(const QString& query, QSqlDatabase db) /*! Constructs a QSqlQuery object using the database \a db. + If \a db is invalid, the application's default database will be used. \sa QSqlDatabase */ diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index fbc31ff..d1051de 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -376,7 +376,8 @@ void QSqlQueryModel::setQuery(const QSqlQuery &query) /*! \overload Executes the query \a query for the given database connection \a - db. If no database is specified, the default connection is used. + db. If no database (or an invalid database) is specified, the + default connection is used. lastError() can be used to retrieve verbose information if there was an error setting the query. -- cgit v0.12 From 594e46bdd36d2964c20cbc5a8de32abd5e343f43 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Thu, 4 Nov 2010 16:34:02 +1000 Subject: Mention the requirement for OCI when building the SQL oracle driver. As suggested by Jean-Louis Mounier. Change-Id: I2284d00453ddcb981fe3e1b710d4453323fe1e9e Task-number: QTBUG-8875 Reviewed-by: Charles Yin --- doc/src/sql-programming/sql-driver.qdoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/src/sql-programming/sql-driver.qdoc b/doc/src/sql-programming/sql-driver.qdoc index 1476491..a4bcb97 100644 --- a/doc/src/sql-programming/sql-driver.qdoc +++ b/doc/src/sql-programming/sql-driver.qdoc @@ -314,7 +314,9 @@ \section3 How to Build the OCI Plugin on Windows Choosing the option "Programmer" in the Oracle Client Installer from - the Oracle Client Installation CD is sufficient to build the plugin. + the Oracle Client Installation CD is generally sufficient to build the + plugin. For some versions of Oracle Client, you may also need to select + the "Call Interface (OCI)" option if it is available. Build the plugin as follows (here it is assumed that Oracle Client is installed in \c{C:\oracle}): -- cgit v0.12 From bdd4a9149789f60974603e1f7621d51378f0a108 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Wed, 17 Nov 2010 17:30:40 +1000 Subject: Fix some removeRows issues with QSqlTableModel. Added some better unit testing around the problem areas. Change-Id: Ie4749da298aebbae6aec9558ebe8c8f2196c705f Task-number: QTBUG-14916 Reviewed-by: Charles Yin --- src/sql/models/qsqltablemodel.cpp | 7 +- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 175 ++++++++++++++++++++--- 2 files changed, 158 insertions(+), 24 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index c6efbad..4df1d63 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -1103,9 +1103,12 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) int idx = row + i; if (idx >= rowCount()) return false; - if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) + if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) { revertRow(idx); - else { + // Reverting a row means all the other cache entries have been adjusted downwards + // so fake this by adjusting row + --row; + } else { d->cache[idx].op = QSqlTableModelPrivate::Delete; d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row()); emit headerDataChanged(Qt::Vertical, idx, idx); diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index 9428ef4..f7d2180 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -94,8 +94,10 @@ private slots: void removeRow(); void removeRows_data() { generic_data(); } void removeRows(); - void removeInsertedRow_data() { generic_data(); } + void removeInsertedRow_data() { generic_data_with_strategies(); } void removeInsertedRow(); + void removeInsertedRows_data() { generic_data(); } + void removeInsertedRows(); void setFilter_data() { generic_data(); } void setFilter(); void setInvalidFilter_data() { generic_data(); } @@ -695,10 +697,19 @@ void tst_QSqlTableModel::removeRows() QCOMPARE(model.rowCount(), 3); QSignalSpy beforeDeleteSpy(&model, SIGNAL(beforeDelete(int))); + + // Make sure wrong stuff is ok + QVERIFY(!model.removeRows(-1,1)); // negative start + QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count + QVERIFY(!model.removeRows(1, 0)); // zero count + QVERIFY(!model.removeRows(5, 1)); // past end (causes a beforeDelete to be emitted) + QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex + QVERIFY_SQL(model, removeRows(0, 2)); - QVERIFY(beforeDeleteSpy.count() == 2); - QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 0); - QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 1); + QCOMPARE(beforeDeleteSpy.count(), 3); + QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 5); + QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 0); + QVERIFY(beforeDeleteSpy.at(2).at(0).toInt() == 1); QCOMPARE(model.rowCount(), 1); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi")); model.clear(); @@ -712,6 +723,13 @@ void tst_QSqlTableModel::removeRows() // When the edit strategy is OnManualSubmit the beforeDelete() signal // isn't emitted until submitAll() is called. + + QVERIFY(!model.removeRows(-1,1)); // negative start + QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count + QVERIFY(!model.removeRows(1, 0)); // zero count + QVERIFY(!model.removeRows(5, 1)); // past end (DOESN'T cause a beforeDelete to be emitted) + QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex + qRegisterMetaType("Qt::Orientation"); QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int))); QVERIFY(model.removeRows(0, 2, QModelIndex())); @@ -733,33 +751,146 @@ void tst_QSqlTableModel::removeRows() void tst_QSqlTableModel::removeInsertedRow() { QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); - for (int i = 0; i <= 1; ++i) { + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); - QSqlTableModel model(0, db); - model.setTable(test); - model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(submitpolicy); + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); - model.setEditStrategy(i == 0 - ? QSqlTableModel::OnRowChange : QSqlTableModel::OnManualSubmit); - QVERIFY_SQL(model, select()); - QCOMPARE(model.rowCount(), 3); + QVERIFY(model.insertRow(1)); + QCOMPARE(model.rowCount(), 4); - QVERIFY(model.insertRow(1)); - QCOMPARE(model.rowCount(), 4); + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 3); - QVERIFY(model.removeRow(1)); - QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); +} - QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); - QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); - QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); - model.clear(); +void tst_QSqlTableModel::removeInsertedRows() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); - recreateTestTables(); - } + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // First put two empty rows, and remove them one by one + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 4); + + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + // Now put two empty rows, and remove them all at once + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 2)); + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + + // Now put two empty rows, and remove one good and two empty + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(0, 3)); + QVERIFY(model.submitAll()); // otherwise the remove of the real row doesn't work + + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); + + // Reset back again + model.clear(); + recreateTestTables(); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // Now two empty and one good + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 3)); + QVERIFY(model.submitAll()); + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); + + // Reset back again + model.clear(); + recreateTestTables(); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // one empty, one good, one empty + QVERIFY(model.insertRows(1, 1)); + QVERIFY(model.insertRows(3, 1)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 3)); + QVERIFY(model.submitAll()); + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); } void tst_QSqlTableModel::emptyTable() -- cgit v0.12 From 47a134b9a9136dc961dc5dd07e345aeb94b2d401 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Thu, 3 Feb 2011 12:33:27 +1000 Subject: Namespace compilation - OCI typedefs should be outside Qt namespace. psql, sqlite2 drivers already do this correctly. Change-Id: I1f02401432d5c39fa1572e2f6255941b8a67e591 Task-number: QTBUG-17076 Reviewed-by: Charles Yin --- src/sql/drivers/oci/qsql_oci.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sql/drivers/oci/qsql_oci.h b/src/sql/drivers/oci/qsql_oci.h index 51fd14c..22bd78d 100644 --- a/src/sql/drivers/oci/qsql_oci.h +++ b/src/sql/drivers/oci/qsql_oci.h @@ -54,6 +54,9 @@ QT_BEGIN_HEADER +typedef struct OCIEnv OCIEnv; +typedef struct OCISvcCtx OCISvcCtx; + QT_BEGIN_NAMESPACE class QOCIDriver; @@ -61,9 +64,6 @@ class QOCICols; struct QOCIDriverPrivate; struct QOCIResultPrivate; -typedef struct OCIEnv OCIEnv; -typedef struct OCISvcCtx OCISvcCtx; - class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult { friend class QOCIDriver; -- cgit v0.12 From 7ced970542d1532fb9613897bc99828178aac5fe Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 4 Feb 2011 16:57:16 +1000 Subject: Initialize primitives when creating a new QVariant Change-Id: Ib9a089a9d912acac4d40c3a1e36e08e86d7832aa Task-number: QTBUG-16683 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 26249ab..8eeee30 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -138,7 +138,7 @@ template void *qMetaTypeConstructHelper(const T *t) { if (!t) - return new T; + return new T(); return new T(*static_cast(t)); } -- cgit v0.12 From dd7873cd7e02e42b384709f33a34f69bc06fb25d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 4 Feb 2011 09:28:58 +0100 Subject: Designer: Fix a crash in the Signal-Slot-Editor. Object search found deleted widgets by name when searching on the form window. Search main container instead, do not assert. Reviewed-by: Jarek Kobus Task-number: QTBUG-17179 --- .../signalsloteditor/signalslot_utils.cpp | 22 ++++++++++------------ .../signalsloteditor/signalsloteditorwindow.cpp | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp index aecd1e5..d0af770 100644 --- a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp +++ b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp @@ -72,7 +72,6 @@ static void memberList(QDesignerFormEditorInterface *core, { if (!object) return; - // 1) member sheet const QDesignerMemberSheetExtension *members = qt_extension(core->extensionManager(), object); Q_ASSERT(members != 0); @@ -118,15 +117,15 @@ static void memberList(QDesignerFormEditorInterface *core, if (!metaDataBase) return; - const qdesigner_internal::MetaDataBaseItem *mdbItem = metaDataBase->metaDataBaseItem(object); - Q_ASSERT(mdbItem); - const QStringList mdbFakeMethods = member_type == qdesigner_internal::SlotMember ? mdbItem->fakeSlots() : mdbItem->fakeSignals(); - if (!mdbFakeMethods.empty()) - foreach (const QString &fakeMethod, mdbFakeMethods) - if (predicate(fakeMethod)) { - *it = ClassNameSignaturePair(className, fakeMethod); - ++it; - } + if (const qdesigner_internal::MetaDataBaseItem *mdbItem = metaDataBase->metaDataBaseItem(object)) { + const QStringList mdbFakeMethods = member_type == qdesigner_internal::SlotMember ? mdbItem->fakeSlots() : mdbItem->fakeSignals(); + if (!mdbFakeMethods.empty()) + foreach (const QString &fakeMethod, mdbFakeMethods) + if (predicate(fakeMethod)) { + *it = ClassNameSignaturePair(className, fakeMethod); + ++it; + } + } } namespace { @@ -245,10 +244,9 @@ namespace qdesigner_internal { ClassesMemberFunctions reverseClassesMemberFunctions(const QString &obj_name, MemberType member_type, const QString &peer, QDesignerFormWindowInterface *form) { - QObject *object = qFindChild(form, obj_name); + QObject *object = qFindChild(form->mainContainer(), obj_name); if (!object) return ClassesMemberFunctions(); - QDesignerFormEditorInterface *core = form->core(); ClassesMemberFunctions rc; diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp index ecee08e..831649f 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp @@ -658,7 +658,7 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const qdesigner_internal::ClassesMemberFunctions class_list = qdesigner_internal::reverseClassesMemberFunctions(obj_name, type, peer, m_form); - QObject *object = qFindChild(m_form, obj_name); + QObject *object = qFindChild(m_form->mainContainer(), obj_name); inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("") : tr("")); foreach (const qdesigner_internal::ClassMemberFunctions &class_info, class_list) { -- cgit v0.12 From 231dcfc8b6a90c3a0ab4869e0a9ab45403fd9a8c Mon Sep 17 00:00:00 2001 From: axis Date: Thu, 3 Feb 2011 15:45:00 +0100 Subject: Fixed a bug where the softkeys would leave a see-through "hole". In cases where the widget was created from the event loop instead of main(), the middle three softkeys would not get the right visibility and would leave a "hole" in the application where one could see what was beneath it. It could also be clicked, which would bring the app to the background which was really annoying. Fixed by setting the visibility manually upon creation. It should still be possible to alter the visibility of the toolbar manually after the widget creation, if someone requires that. Task: QTBUG-16578 RevBy: Gareth Stockwell AutoTest: N/A, but tested with various combinations of fullscreen, non-fullscreen and softkey visibility modes. No regressions. --- src/gui/kernel/qwidget_s60.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 8e4e99a..6af809f 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -54,6 +54,7 @@ #ifdef Q_WS_S60 #include +#include #include #endif @@ -508,6 +509,18 @@ void QWidgetPrivate::show_sys() Q_ASSERT(!oldCba); S60->setButtonGroupContainer(cba); + // If the creation of the first widget is delayed, for example by doing it + // inside the event loop, S60 somehow "forgets" to set the visibility of the + // toolbar (the three middle softkeys) when you flip the phone over, so we + // need to do it ourselves to avoid a "hole" in the application, even though + // Qt itself does not use the toolbar directly.. + CAknAppUi *appui = dynamic_cast(CEikonEnv::Static()->AppUi()); + if (appui) { + CAknToolbar *toolbar = appui->PopupToolbar(); + if (toolbar && !toolbar->IsVisible()) + toolbar->SetToolbarVisibility(ETrue); + } + CEikMenuBar *menuBar = new(ELeave) CEikMenuBar; menuBar->ConstructL(ui, 0, R_AVKON_MENUPANE_EMPTY); menuBar->SetMenuType(CEikMenuBar::EMenuOptions); -- cgit v0.12 From 8fe811e14b6db6a9637a5bf6d276613786291762 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 3 Feb 2011 12:16:35 +0000 Subject: Fix random crashes when bearer suddenly goes down 1. QNetworkSession being deleted from the closed signal caused data abort or E32User-CBase 49 panics. (both observed) 2. Potential E32User-CBase 46 panic in ConnectionProgressNotifier::StartNotifications() Reviewed-by: Aaron Tunney Reviewed-By: Markus Goetz Task-Number: QTBUG-17196 --- src/network/access/qnetworkaccessmanager.cpp | 7 ++++--- src/network/bearer/qnetworksession.cpp | 3 +++ src/network/bearer/qnetworksession.h | 3 +++ src/plugins/bearer/symbian/qnetworksession_impl.cpp | 6 +++--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index ea18367..5b518de 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1369,10 +1369,11 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co networkSession = QSharedNetworkSessionManager::getSession(config); - QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); + //QueuedConnection is used to avoid deleting the networkSession inside its closed signal + QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), - q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); _q_networkSessionStateChanged(networkSession->state()); } diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index b0b7d3d..9503553 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -250,6 +250,9 @@ QNetworkSession::QNetworkSession(const QNetworkConfiguration& connectionConfig, break; } } + + qRegisterMetaType(); + qRegisterMetaType(); } /*! diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index c51cb4f..0bca4b6 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -139,6 +139,9 @@ private: friend class QNetworkSessionPrivate; }; +Q_DECLARE_METATYPE(QNetworkSession::State); +Q_DECLARE_METATYPE(QNetworkSession::SessionError); + #ifndef QT_MOBILITY_BEARER QT_END_NAMESPACE #else diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 433eef6..741f8c5 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1552,8 +1552,8 @@ void ConnectionProgressNotifier::StartNotifications() { if (!IsActive()) { SetActive(); + iConnection.ProgressNotification(iProgress, iStatus); } - iConnection.ProgressNotification(iProgress, iStatus); } void ConnectionProgressNotifier::StopNotifications() @@ -1569,10 +1569,10 @@ void ConnectionProgressNotifier::DoCancel() void ConnectionProgressNotifier::RunL() { if (iStatus == KErrNone) { - QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); - SetActive(); iConnection.ProgressNotification(iProgress, iStatus); + // warning, this object may be deleted in the callback - do nothing after handleSymbianConnectionStatusChange + QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); } } -- cgit v0.12 From 4cee615df52a3d984986d07e8125d3b01973f4a9 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 4 Feb 2011 12:06:23 +0000 Subject: Fix deployment issues with networkselftest Changed deployment in the .pro file from = to += so that the default executable deployment is not removed. Also added required symbian capabilities Reviewed-by: Markus Goetz --- tests/auto/networkselftest/networkselftest.pro | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/networkselftest/networkselftest.pro b/tests/auto/networkselftest/networkselftest.pro index d7cb7f3..3e680d8 100644 --- a/tests/auto/networkselftest/networkselftest.pro +++ b/tests/auto/networkselftest/networkselftest.pro @@ -6,12 +6,13 @@ QT = core network wince*: { addFiles.sources = rfc3252.txt addFiles.path = . - DEPLOYMENT = addFiles + DEPLOYMENT += addFiles DEFINES += SRCDIR=\\\"\\\" } else:symbian { addFiles.sources = rfc3252.txt addFiles.path = . - DEPLOYMENT = addFiles + DEPLOYMENT += addFiles + TARGET.CAPABILITY = NetworkServices ReadUserData } else:vxworks*: { DEFINES += SRCDIR=\\\"\\\" } else { -- cgit v0.12 From 10c7730877d314ec4eda6728e2d66c38beff8d62 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 4 Feb 2011 14:10:53 +0200 Subject: Implement Symbian support for enable_backup CONFIG value The enable_backup CONFIG value can be used to generate deployment for backup registration file for an application. BACKUP_REGISTRATION_FILE variable can be used to specify a custom backup registration file. Task-number: QTBUG-17214 Reviewed-by: axis --- doc/src/development/qmake-manual.qdoc | 18 ++++++++++++++++++ mkspecs/common/symbian/backup_registration.xml | 8 ++++++++ mkspecs/features/enable_backup.prf | 15 +++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 mkspecs/common/symbian/backup_registration.xml create mode 100644 mkspecs/features/enable_backup.prf diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc index b81d387..d1843a8 100644 --- a/doc/src/development/qmake-manual.qdoc +++ b/doc/src/development/qmake-manual.qdoc @@ -1086,6 +1086,18 @@ \tableofcontents{3} + + \target BACKUP_REGISTRATION_FILE + \section1 BACKUP_REGISTRATION_FILE + + \e {This is only used on the Symbian platform.} + + This variable can be used to specify a custom backup registration file to use + with \c enable_backup \c CONFIG value. See Symbian documentation + (\l{http://library.forum.nokia.com/index.jsp?topic=/S60_5th_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/sdk/doc_source/guide/Connectivity-subsystem-guide/Connectivity/PC_Connectivity_How-To_Write_Backup_Aware_Software.html}{How-To Write Backup-aware Software}) + for more information about backup registration files and how backup + works in Symbian in general. + \target BLD_INF_RULES \section1 BLD_INF_RULES @@ -1302,6 +1314,12 @@ to work. E.g. \c{myapp_en.ts}. \bold{Note:} All languages supported by Qt are not supported by Symbian, so some \c{.ts} files may be ignored by qmake. + \row \o enable_backup \o Generates deployment for backup registration file + to enable backing up the application during device backup. By default + application binaries, resources, and all files under application private + directory and \c{C:\Data} are backed up. If a custom backup rules are + needed, \l{#BACKUP_REGISTRATION_FILE}{BACKUP_REGISTRATION_FILE} variable + can be used to specify a custom backup registration file. \endtable These options have an effect on Linux/Unix platforms: diff --git a/mkspecs/common/symbian/backup_registration.xml b/mkspecs/common/symbian/backup_registration.xml new file mode 100644 index 0000000..794e11d --- /dev/null +++ b/mkspecs/common/symbian/backup_registration.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/mkspecs/features/enable_backup.prf b/mkspecs/features/enable_backup.prf new file mode 100644 index 0000000..9e81d56 --- /dev/null +++ b/mkspecs/features/enable_backup.prf @@ -0,0 +1,15 @@ +# Generate deployment for backup registration file +symbian { + isEmpty(BACKUP_REGISTRATION_FILE) { + BACKUP_REGISTRATION_FILE = $$[QT_INSTALL_DATA]/mkspecs/common/symbian/backup_registration.xml + } + + contains(TEMPLATE, app) { + backup_reg_deployment.path = /private/$$replace(TARGET.UID3, 0x,) + } else { + backup_reg_deployment.path = /private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,) + } + + backup_reg_deployment.sources = $$BACKUP_REGISTRATION_FILE + DEPLOYMENT += backup_reg_deployment +} \ No newline at end of file -- cgit v0.12 From de1cfc13c66fcb35d0a211bb5136ebc25279041a Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 4 Feb 2011 13:36:27 +0100 Subject: Don't crash when BMP color table is broken If the BMP's number of color table entries is out of bounds, we would resize our color table vector to a silly value, leading to crashes later on. If the number of color table entries is larger than 256, just stop processing the BMP since it's most probably corrupt. Task-number: QT-4534 Reviewed-by: Robert Griebl --- src/gui/image/qbmphandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 09c086a..6dea9d9 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -246,6 +246,8 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int if (depth != 32) { ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; + if (ncols > 256) // sanity check - don't run out of mem if color table is broken + return false; image.setColorCount(ncols); } -- cgit v0.12 From 2b5454432f132f98a1216f1dd8163acb4800191e Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 4 Feb 2011 15:10:08 +0200 Subject: Revert "Implement Symbian support for enable_backup CONFIG value" This reverts commit 10c7730877d314ec4eda6728e2d66c38beff8d62. Maemo/Meego support for this needs to be verified before this can be added so reverting this for now. --- doc/src/development/qmake-manual.qdoc | 18 ------------------ mkspecs/common/symbian/backup_registration.xml | 8 -------- mkspecs/features/enable_backup.prf | 15 --------------- 3 files changed, 41 deletions(-) delete mode 100644 mkspecs/common/symbian/backup_registration.xml delete mode 100644 mkspecs/features/enable_backup.prf diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc index d1843a8..b81d387 100644 --- a/doc/src/development/qmake-manual.qdoc +++ b/doc/src/development/qmake-manual.qdoc @@ -1086,18 +1086,6 @@ \tableofcontents{3} - - \target BACKUP_REGISTRATION_FILE - \section1 BACKUP_REGISTRATION_FILE - - \e {This is only used on the Symbian platform.} - - This variable can be used to specify a custom backup registration file to use - with \c enable_backup \c CONFIG value. See Symbian documentation - (\l{http://library.forum.nokia.com/index.jsp?topic=/S60_5th_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/sdk/doc_source/guide/Connectivity-subsystem-guide/Connectivity/PC_Connectivity_How-To_Write_Backup_Aware_Software.html}{How-To Write Backup-aware Software}) - for more information about backup registration files and how backup - works in Symbian in general. - \target BLD_INF_RULES \section1 BLD_INF_RULES @@ -1314,12 +1302,6 @@ to work. E.g. \c{myapp_en.ts}. \bold{Note:} All languages supported by Qt are not supported by Symbian, so some \c{.ts} files may be ignored by qmake. - \row \o enable_backup \o Generates deployment for backup registration file - to enable backing up the application during device backup. By default - application binaries, resources, and all files under application private - directory and \c{C:\Data} are backed up. If a custom backup rules are - needed, \l{#BACKUP_REGISTRATION_FILE}{BACKUP_REGISTRATION_FILE} variable - can be used to specify a custom backup registration file. \endtable These options have an effect on Linux/Unix platforms: diff --git a/mkspecs/common/symbian/backup_registration.xml b/mkspecs/common/symbian/backup_registration.xml deleted file mode 100644 index 794e11d..0000000 --- a/mkspecs/common/symbian/backup_registration.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/mkspecs/features/enable_backup.prf b/mkspecs/features/enable_backup.prf deleted file mode 100644 index 9e81d56..0000000 --- a/mkspecs/features/enable_backup.prf +++ /dev/null @@ -1,15 +0,0 @@ -# Generate deployment for backup registration file -symbian { - isEmpty(BACKUP_REGISTRATION_FILE) { - BACKUP_REGISTRATION_FILE = $$[QT_INSTALL_DATA]/mkspecs/common/symbian/backup_registration.xml - } - - contains(TEMPLATE, app) { - backup_reg_deployment.path = /private/$$replace(TARGET.UID3, 0x,) - } else { - backup_reg_deployment.path = /private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,) - } - - backup_reg_deployment.sources = $$BACKUP_REGISTRATION_FILE - DEPLOYMENT += backup_reg_deployment -} \ No newline at end of file -- cgit v0.12 From ff75ad64bb064d97582c8e3992a9db7aa4e016e1 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Fri, 4 Feb 2011 01:50:08 +0200 Subject: symbian/linux-gcce: Use -u _E32Dll when linking DLLs This is required when using older binutils versions (CodeSourcery 2009q1 requires it, while CodeSourcery 4.4-172 doesn't require it) with the linux-gcce mkspec. The -u option is already used in the same way for exe files, and the abld build system invokes ld with -u _E32Dll, too. Signed-off-by: axis Merge request: 2560 --- mkspecs/symbian/linux-gcce/qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/symbian/linux-gcce/qmake.conf b/mkspecs/symbian/linux-gcce/qmake.conf index faac2f1..648a591 100644 --- a/mkspecs/symbian/linux-gcce/qmake.conf +++ b/mkspecs/symbian/linux-gcce/qmake.conf @@ -54,7 +54,7 @@ DEFINES += __GCCE__ \ _STLP_NO_EXCEPTION_HEADER QMAKE_LFLAGS_APP += --entry=_E32Startup -u _E32Startup -QMAKE_LFLAGS_SHLIB += --default-symver --entry _E32Dll +QMAKE_LFLAGS_SHLIB += --default-symver --entry=_E32Dll -u _E32Dll QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB gcceExtraFlags = --include=${EPOCROOT}/epoc32/include/gcce/gcce.h -march=armv5t -mapcs -mthumb-interwork -nostdinc -c -msoft-float -T script -- cgit v0.12 From aeeb80bd223b900ad1990a38272b9bb94fe9e9fe Mon Sep 17 00:00:00 2001 From: axis Date: Fri, 4 Feb 2011 14:08:17 +0100 Subject: Added missing edllstub.lib for GCCE. RevBy: Trust me --- mkspecs/features/symbian/symbian_building.prf | 1 + 1 file changed, 1 insertion(+) diff --git a/mkspecs/features/symbian/symbian_building.prf b/mkspecs/features/symbian/symbian_building.prf index 0cedaa0..f3b6c25 100644 --- a/mkspecs/features/symbian/symbian_building.prf +++ b/mkspecs/features/symbian/symbian_building.prf @@ -147,6 +147,7 @@ contains(TEMPLATE, lib):!contains(CONFIG, static):!contains(CONFIG, staticlib) { LIBS += -ledllstub.lib -ledll.lib\\(uc_dll_.o\\) } else :linux-gcce { LIBS += \ + -l:edllstub.lib \ -l:edll.lib \ -l:usrt2_2.lib \ -l:dfpaeabi.dso \ -- cgit v0.12 From c6c647c22efaa9d101324920da81b891becb1cf1 Mon Sep 17 00:00:00 2001 From: axis Date: Fri, 4 Feb 2011 14:09:01 +0100 Subject: Avoided the Linux version of the --no-undefined switch. RevBy: Trust me --- mkspecs/symbian/linux-gcce/qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/symbian/linux-gcce/qmake.conf b/mkspecs/symbian/linux-gcce/qmake.conf index 648a591..4c346da 100644 --- a/mkspecs/symbian/linux-gcce/qmake.conf +++ b/mkspecs/symbian/linux-gcce/qmake.conf @@ -46,7 +46,7 @@ QMAKE_CXXFLAGS_STATIC_LIB -= -fPIC QMAKE_LFLAGS_SONAME = #QMAKE_LFLAGS_THREAD += -#QMAKE_LFLAGS_NOUNDEF += -Wl,--no-undefined +QMAKE_LFLAGS_NOUNDEF = QMAKE_LFLAGS_RPATH = --rpath= DEFINES += __GCCE__ \ -- cgit v0.12 From 1c15dab336bd1806ff0762a0f4c92c0d83da6d8a Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 1 Feb 2011 11:15:55 +0100 Subject: Fixed "not a valid preprocessing token" on GCCE. It seems to be fixed upstream already. RevBy: Gareth Stockwell --- src/3rdparty/phonon/mmf/abstractaudioeffect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index 70adcf6..517a334 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -124,7 +124,7 @@ private: #define PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Effect) \ \ -void Effect##::createEffect(AudioPlayer::NativePlayer *player) \ +void Effect::createEffect(AudioPlayer::NativePlayer *player) \ { \ C##Effect *ptr = 0; \ QT_TRAP_THROWING(ptr = C##Effect::NewL(*player)); \ -- cgit v0.12 From aa8d84efdc8e7dd26f36a3586050458d7be0c279 Mon Sep 17 00:00:00 2001 From: Denis Oliver Kropp Date: Fri, 4 Feb 2011 14:50:00 +0100 Subject: directfb: Pixmap creation always premultiplied the alpha even when it is already premultiplied in the image. This also avoids the temporary surface and blitting. Merge-request: 990 Reviewed-by: Marcel Schuette --- .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 6639983..50e0f5f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -300,40 +300,26 @@ void QDirectFBPixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags { alpha = QDirectFBPixmapData::hasAlphaChannel(img, flags); imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat(); + QImage image; if ((flags & ~Qt::NoOpaqueDetection) != Qt::AutoColor) { image = img.convertToFormat(imageFormat, flags); flags = Qt::AutoColor; } else if (img.format() == QImage::Format_RGB32 || img.depth() == 1) { image = img.convertToFormat(imageFormat, flags); + } else if (img.format() != imageFormat) { + image = img.convertToFormat(imageFormat, flags); } else { image = img; } - IDirectFBSurface *imageSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface); - if (!imageSurface) { - qWarning("QDirectFBPixmapData::fromImage()"); - invalidate(); - return; - } - - dfbSurface = screen->createDFBSurface(image.size(), imageFormat, QDirectFBScreen::TrackSurface); + dfbSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::NoPreallocated | QDirectFBScreen::TrackSurface); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fromImage()"); invalidate(); return; } - if (image.hasAlphaChannel()) { - dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL); - } else { - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); - } - - dfbSurface->Blit(dfbSurface, imageSurface, 0, 0, 0); - imageSurface->Release(imageSurface); - w = image.width(); h = image.height(); is_null = (w <= 0 || h <= 0); -- cgit v0.12 From e9ab35ef663e9562385c974dcbeb7cf2d03ab70f Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 4 Feb 2011 15:10:10 +0100 Subject: Move the QtHelp tests in its own profile Reviewed-by: Sergio Ahumada --- tests/auto/auto.pro | 1 + tests/auto/gui.pro | 10 ---------- tests/auto/help.pro | 8 ++++++++ 3 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 tests/auto/help.pro diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index c0004f7..c677249 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -19,4 +19,5 @@ contains(QT_CONFIG, multimedia): SUBDIRS += multimedia.pro contains(QT_CONFIG, phonon): SUBDIRS += phonon.pro contains(QT_CONFIG, svg): SUBDIRS += svg.pro contains(QT_CONFIG, declarative): SUBDIRS += declarative.pro +!symbian SUBDIRS += help.pro diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 802e74a..4b809fb 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -80,11 +80,6 @@ SUBDIRS=\ qgroupbox \ qguivariant \ qheaderview \ - qhelpcontentmodel \ - qhelpenginecore \ - qhelpgenerator \ - qhelpindexmodel \ - qhelpprojectdata \ qicoimageformat \ qicon \ qimageiohandler \ @@ -221,10 +216,5 @@ win32:SUBDIRS -= qtextpiecetable qtextpiecetable \ symbian:SUBDIRS -= \ - qhelpcontentmodel \ - qhelpenginecore \ - qhelpgenerator \ - qhelpindexmodel \ - qhelpprojectdata \ qsystemtrayicon \ diff --git a/tests/auto/help.pro b/tests/auto/help.pro new file mode 100644 index 0000000..e6ee552 --- /dev/null +++ b/tests/auto/help.pro @@ -0,0 +1,8 @@ +TEMPLATE=subdirs +SUBDIRS=\ + qhelpcontentmodel \ + qhelpenginecore \ + qhelpgenerator \ + qhelpindexmodel \ + qhelpprojectdata \ + -- cgit v0.12 From c696b4fe5a0acd85bc739fb148b8f76965f12d20 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 3 Feb 2011 19:26:36 +0100 Subject: Autotest: Use QElapsedTimer for timings --- tests/auto/qdbusperformance/tst_qdbusperformance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp b/tests/auto/qdbusperformance/tst_qdbusperformance.cpp index 42db697..a5b4b98 100644 --- a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp +++ b/tests/auto/qdbusperformance/tst_qdbusperformance.cpp @@ -125,7 +125,7 @@ void tst_QDBusPerformance::init() void tst_QDBusPerformance::callSpeed() { - QTime timer; + QElapsedTimer timer; int callCount = 0; timer.start(); @@ -141,7 +141,7 @@ void tst_QDBusPerformance::callSpeed() bool tst_QDBusPerformance::executeTest(const char *funcname, int size, const QVariant &data) { - QTime timer; + QElapsedTimer timer; int callCount = 0; qint64 transferred = 0; -- cgit v0.12 From fa9b8b6420b0805000435a0b312f47f990dab9a5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 4 Feb 2011 15:32:35 +0100 Subject: Autotest: simple improvements --- tests/auto/qprocess/tst_qprocess.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index 4ee8957..b0f7a9f 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -249,6 +249,8 @@ void tst_QProcess::constructing() char c; QCOMPARE(process.read(&c, 1), qlonglong(-1)); QCOMPARE(process.write(&c, 1), qlonglong(-1)); + + QProcess proc2; } void tst_QProcess::simpleStart() @@ -265,7 +267,7 @@ void tst_QProcess::simpleStart() process->start("testProcessNormal/testProcessNormal"); if (process->state() != QProcess::Starting) QCOMPARE(process->state(), QProcess::Running); - QVERIFY(process->waitForStarted(5000)); + QVERIFY2(process->waitForStarted(5000), qPrintable(process->errorString())); QCOMPARE(process->state(), QProcess::Running); #if defined(Q_OS_WINCE) // Note: This actually seems incorrect, it will only exit the while loop when finishing fails @@ -277,7 +279,7 @@ void tst_QProcess::simpleStart() while (process->waitForReadyRead(5000)) { } #endif - QCOMPARE(process->state(), QProcess::NotRunning); + QCOMPARE(int(process->state()), int(QProcess::NotRunning)); delete process; process = 0; -- cgit v0.12 From 4f29c5d5381a76f24e13628da3edc5b19c6b1cd2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 2 Feb 2011 13:23:40 +0100 Subject: Doc: Fix the docs saying what the locale codec is used for --- src/corelib/tools/qstring.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b96edb9..c1b8740 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3868,8 +3868,7 @@ const char *QString::latin1_helper() const If \a size is -1 (default), it is taken to be qstrlen(\a str). - QTextCodec::codecForLocale() is used to perform the conversion - from Unicode. + QTextCodec::codecForLocale() is used to perform the conversion. \sa toLocal8Bit(), fromAscii(), fromLatin1(), fromUtf8() */ -- cgit v0.12 From fd2e832657a38d4dba9b86ce190f7736a837d53d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 28 Jan 2011 16:40:51 +0100 Subject: Make qdbus show all types, even those that it doesn't know about --- src/dbus/qdbusmetaobject.cpp | 18 +++++++++++++++++- tools/qdbus/qdbus/qdbus.cpp | 11 +++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 5fe0589..6683505 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -169,6 +169,8 @@ QDBusMetaObjectGenerator::QDBusMetaObjectGenerator(const QString &interfaceName, } } +Q_DBUS_EXPORT bool qt_dbus_metaobject_skip_annotations = false; + QDBusMetaObjectGenerator::Type QDBusMetaObjectGenerator::findType(const QByteArray &signature, const QDBusIntrospection::Annotations &annotations, @@ -178,7 +180,7 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, result.id = QVariant::Invalid; int type = QDBusMetaType::signatureToType(signature); - if (type == QVariant::Invalid) { + if (type == QVariant::Invalid && !qt_dbus_metaobject_skip_annotations) { // it's not a type normally handled by our meta type system // it must contain an annotation QString annotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); @@ -201,6 +203,20 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, return result; // unknown type is invalid too result.name = typeName; + } else if (type == QVariant::Invalid) { + // this case is used only by the qdbus command-line tool + // invalid, let's create an impossible type that contains the signature + + if (signature == "av") { + result.name = "QVariantList"; + type = QVariant::List; + } else if (signature == "a{sv}") { + result.name = "QVariantMap"; + type = QVariant::Map; + } else { + result.name = "QDBusRawType::" + signature; + type = -1; + } } else { result.name = QVariant::typeToName( QVariant::Type(type) ); } diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index 6ec8224..4e5cf9a 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -50,6 +50,8 @@ #include #include +Q_DBUS_EXPORT extern bool qt_dbus_metaobject_skip_annotations; + static QDBusConnection connection(QLatin1String("")); static bool printArgumentsLiterally = false; @@ -99,7 +101,7 @@ static void printArg(const QVariant &v) else if (arg.currentSignature() == QLatin1String("a{sv}")) printArg(qdbus_cast(arg)); else - printf("qdbus: I don't know how to display an argument of type '%s'\n", + printf("qdbus: I don't know how to display an argument of type '%s', run with --literal.\n", qPrintable(arg.currentSignature())); } else { printf("%s\n", qPrintable(v.toString())); @@ -311,7 +313,11 @@ static int placeCall(const QString &service, const QString &path, const QString int id = QVariant::nameToType(types.at(i)); if (id == QVariant::UserType) id = QMetaType::type(types.at(i)); - Q_ASSERT(id); + if (!id) { + fprintf(stderr, "Cannot call method '%s' because type '%s' is unknown to this tool\n", + qPrintable(member), types.at(i).constData()); + return 1; + } QVariant p; QString argument; @@ -435,6 +441,7 @@ static void printAllServices(QDBusConnectionInterface *bus) int main(int argc, char **argv) { + qt_dbus_metaobject_skip_annotations = true; QCoreApplication app(argc, argv); QStringList args = app.arguments(); args.takeFirst(); -- cgit v0.12 From 2b72330127cf045d324bc20dfbc9fac2d12c6cdb Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 28 Jan 2011 16:43:56 +0100 Subject: QtDBus: do not wait for reply for AddMatch and RemoveMatch We can't recover from these functions failing anyway, so don't ask for an error condition. The D-Bus library will set the no-reply flag under these conditions. Reviewed-by: Will Thompson --- src/dbus/qdbusintegrator.cpp | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 2e7b052..bc03896 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -2074,30 +2074,20 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook if (connection) { qDBusDebug("Adding rule: %s", hook.matchRule.constData()); - QDBusErrorInternal error; - q_dbus_bus_add_match(connection, hook.matchRule, error); - if (!!error) { - QDBusError qerror = error; - qWarning("QDBusConnectionPrivate::connectSignal: received error from D-Bus server " - "while connecting signal to %s::%s: %s (%s)", - hook.obj->metaObject()->className(), - hook.obj->metaObject()->method(hook.midx).signature(), - qPrintable(qerror.name()), qPrintable(qerror.message())); - Q_ASSERT(false); - } else { - // Successfully connected the signal - // Do we need to watch for this name? - if (shouldWatchService(hook.service)) { - WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; - if (++data.refcount == 1) { - // we need to watch for this service changing - connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), - QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); - data.owner = getNameOwnerNoCache(hook.service); - qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" - << data.owner << ")"; - } + q_dbus_bus_add_match(connection, hook.matchRule, NULL); + + // Successfully connected the signal + // Do we need to watch for this name? + if (shouldWatchService(hook.service)) { + WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; + if (++data.refcount == 1) { + // we need to watch for this service changing + connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), + QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), + this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + data.owner = getNameOwnerNoCache(hook.service); + qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" + << data.owner << ")"; } } } -- cgit v0.12 From 9ae73fcd011e26c920f91cf0b609f051c14920a8 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Sun, 6 Feb 2011 23:48:39 +0200 Subject: Fix native child window Symbian decoration handling. Resizing native child window like QVideoWidget caused S60 cba and status pane to appear. Task-number: QTBUG-17040 Reviewed-by: Gareth Stockwell --- src/gui/kernel/qapplication_s60.cpp | 14 ++++++++------ src/gui/kernel/qwidget_s60.cpp | 24 +++++++++++++++--------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 40a7ec6..6bddb19 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1245,12 +1245,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) #ifdef Q_WS_S60 // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. QWidget *const window = qwidget->window(); - const bool visible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = visible; - const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; - const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; - const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + if (!window->parentWidget()) { // Only top level native windows have control over cba/status pane + const bool decorationsVisible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = decorationsVisible; + const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; + const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; + const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaVisibilityHint)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + } #endif } else if (QApplication::activeWindow() == qwidget->window()) { bool focusedControlFound = false; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 6af809f..1551162 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -485,6 +485,7 @@ void QWidgetPrivate::show_sys() QSymbianControl *id = static_cast(q->internalWinId()); const bool isFullscreen = q->windowState() & Qt::WindowFullScreen; + const TBool cbaRequested = q->windowFlags() & Qt::WindowSoftkeysVisibleHint; #ifdef Q_WS_S60 // Lazily initialize the S60 screen furniture when the first window is shown. @@ -504,6 +505,8 @@ void QWidgetPrivate::show_sys() CEikButtonGroupContainer *cba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba, CEikButtonGroupContainer::EHorizontal,ui,R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + if (isFullscreen && !cbaRequested) + cba->MakeVisible(false); CEikButtonGroupContainer *oldCba = factory->SwapButtonGroup(cba); Q_ASSERT(!oldCba); @@ -1169,14 +1172,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } #ifdef Q_WS_S60 - // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration. - // The window decoration visibility has to be changed before doing actual window state - // change since in that order the availableGeometry will return directly the right size and - // we will avoid unnecessarty redraws - const bool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = visible; - const bool buttonGroupVisibility = (visible || (isFullscreen && cbaRequested)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + bool decorationsVisible(false); + if (!parentWidget()) { // Only top level native windows have control over cba/status pane + // Hide window decoration when switching to fullscreen / minimized otherwise show decoration. + // The window decoration visibility has to be changed before doing actual window state + // change since in that order the availableGeometry will return directly the right size and + // we will avoid unnecessary redraws + decorationsVisible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = decorationsVisible; + const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaRequested)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + } #endif // Q_WS_S60 // Ensure the initial size is valid, since we store it as normalGeometry below. @@ -1200,7 +1206,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) // accurate because it did not consider the status pane. This means that when returning // normal mode after showing the status pane, the geometry would overlap so we should // move it if it never had an explicit position. - if (!wasMoved && S60->statusPane() && visible) { + if (!wasMoved && S60->statusPane() && decorationsVisible) { TPoint tl = static_cast(S60->appUi())->ClientRect().iTl; normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); } -- cgit v0.12 From 24d8e96624af91ab01a20c10625858300f16099b Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 7 Feb 2011 10:03:25 +1000 Subject: Disable lineHeight test while implementing the feature in master properly. --- tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 320a6e7..44059f5 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -1113,13 +1113,13 @@ void tst_qdeclarativetext::lineHeight() myText->setLineHeightMode(QDeclarativeText::MultiplyHeight); myText->setLineHeight(1); - qreal h2 = myText->height(); + //qreal h2 = myText->height(); myText->setLineHeight(2.0); - QVERIFY(myText->height() == h2 * 2.0); + //QVERIFY(myText->height() == h2 * 2.0); myText->setLineHeightMode(QDeclarativeText::PixelHeight); myText->setLineHeight(10); - QCOMPARE(myText->height(), myText->lineCount() * 10.0); + //QCOMPARE(myText->height(), myText->lineCount() * 10.0); delete canvas; } -- cgit v0.12 From 27339962c023820ef9cd76843e256c7f3d624116 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 7 Feb 2011 11:23:49 +1000 Subject: Make test compile --- .../declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp index 820a282..ba52987 100644 --- a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp +++ b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp @@ -593,12 +593,12 @@ void tst_QDeclarativeRepeater::modelChanged() repeater->setModel(4); QCOMPARE(repeater->count(), 4); - QCOMPARE(repeater->property("itemsCount"), 4); + QCOMPARE(repeater->property("itemsCount").toInt(), 4); QCOMPARE(repeater->property("itemsFound").toList().count(), 4); repeater->setModel(10); QCOMPARE(repeater->count(), 10); - QCOMPARE(repeater->property("itemsCount"), 10); + QCOMPARE(repeater->property("itemsCount").toInt(), 10); QCOMPARE(repeater->property("itemsFound").toList().count(), 10); delete rootObject; -- cgit v0.12 From e57716ad44e5894890d662f9ac596b70c109104f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 7 Feb 2011 10:59:38 +1000 Subject: Ensure section delegates are updated when the section property changes. If the section property changes and the existing section delegate is reused the section property in the delegate must be updated. Change-Id: I6c3dcdb697e80e1ab5162a179da52e0a0f41144c Task-number: QTBUG-17068 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativelistview.cpp | 3 ++ .../data/listview-sections_delegate.qml | 63 ++++++++++++++++++++++ .../tst_qdeclarativelistview.cpp | 53 ++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 075c3af..bb5bd75 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -936,6 +936,9 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) } } listItem->setPosition(pos); + } else { + QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section)->parentContext(); + context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); } } else if (listItem->section) { qreal pos = listItem->position(); diff --git a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml new file mode 100644 index 0000000..35a398b --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml @@ -0,0 +1,63 @@ +import QtQuick 1.0 + +Rectangle { + width: 240 + height: 320 + color: "#ffffff" + resources: [ + Component { + id: myDelegate + Item { + id: wrapper + objectName: "wrapper" + height: 20; + width: 240 + Rectangle { + height: 20 + width: parent.width + color: wrapper.ListView.isCurrentItem ? "lightsteelblue" : "white" + Text { + text: index + } + Text { + x: 30 + id: textName + objectName: "textName" + text: name + } + Text { + x: 100 + id: textNumber + objectName: "textNumber" + text: number + } + Text { + objectName: "nextSection" + x: 150 + text: wrapper.ListView.nextSection + } + Text { + x: 200 + text: wrapper.y + } + } + } + } + ] + ListView { + id: list + objectName: "list" + width: 240 + height: 320 + model: testModel + delegate: myDelegate + section.property: "number" + section.delegate: Rectangle { + objectName: "sect_" + section + color: "#99bb99" + height: 20 + width: list.width + Text { text: section } + } + } +} diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 86b68ca..8df0bb9 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -90,6 +90,7 @@ private slots: void enforceRange(); void spacing(); void sections(); + void sectionsDelegate(); void cacheBuffer(); void positionViewAtIndex(); void resetModel(); @@ -1017,6 +1018,58 @@ void tst_QDeclarativeListView::sections() delete canvas; } +void tst_QDeclarativeListView::sectionsDelegate() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), QString::number(i/5)); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections_delegate.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = findItem(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // Confirm items positioned correctly + int itemCount = findItems(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem(contentItem, "wrapper", i); + QTRY_VERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20)); + QDeclarativeText *next = findItem(item, "nextSection"); + QCOMPARE(next->text().toInt(), (i+1)/5); + } + + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem(contentItem, "sect_" + QString::number(i)); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*6)); + } + + model.modifyItem(0, "One", "aaa"); + model.modifyItem(1, "Two", "aaa"); + model.modifyItem(2, "Three", "aaa"); + model.modifyItem(3, "Four", "aaa"); + model.modifyItem(4, "Five", "aaa"); + + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem(contentItem, + "sect_" + (i == 0 ? QString("aaa") : QString::number(i))); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*6)); + } + + delete canvas; +} + void tst_QDeclarativeListView::currentIndex() { TestModel model; -- cgit v0.12 From 6bd233953ac87603ddee8c5f087fbe523dd3793e Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 7 Feb 2011 14:24:36 +1000 Subject: Changing header/footer size during creation caused recusion If the size of the header or footer was changed during creation it would trigger itemGeometryChanged() which called updateHeader() and updateFooter() thereby causing recusion. We should only call those methods if the header/footer is already created. Change-Id: Ia2ae4047d745d1f301d243278550e65854fa830a Task-number: QT-4439 Reviewed-by: Joona Petrell --- src/declarative/graphicsitems/qdeclarativegridview.cpp | 6 ++++-- src/declarative/graphicsitems/qdeclarativelistview.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 9aade98..c2c4ed7 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -331,8 +331,10 @@ public: } } } else if ((header && header->item == item) || (footer && footer->item == item)) { - updateHeader(); - updateFooter(); + if (header) + updateHeader(); + if (footer) + updateFooter(); } } diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index bb5bd75..800e82e 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -413,8 +413,10 @@ public: } } if ((header && header->item == item) || (footer && footer->item == item)) { - updateHeader(); - updateFooter(); + if (header) + updateHeader(); + if (footer) + updateFooter(); } if (currentItem && currentItem->item == item) updateHighlight(); -- cgit v0.12 From 512b53969408fdd9c0a2950f3249fd3ca07b319e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 4 Feb 2011 15:44:07 +0200 Subject: Fix the broken QPixmap::fromSymbianRSgImage(). The retrieved VGImage handle was accidentally assigned to a local variable instead of the member with the same name so it always ended up creating an empty pixmap. Reviewed-by: Jani Hautakangas --- src/openvg/qvg_symbian.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index 3ee1181..2ea38c1 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -147,7 +147,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) destroyImages(); prevSize = QSize(); - VGImage vgImage = sgImageToVGImage(context, *sgImage); + vgImage = sgImageToVGImage(context, *sgImage); if (vgImage != VG_INVALID_HANDLE) { w = vgGetParameteri(vgImage, VG_IMAGE_WIDTH); h = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT); -- cgit v0.12 From b1d877e32361e8ca5c092a4df4528e5aa868008f Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 7 Feb 2011 10:06:36 +0000 Subject: Fix namespace error Reviewed-by: Olivier Goffart --- src/network/bearer/qnetworksession.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index 0bca4b6..7739218 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -139,15 +139,15 @@ private: friend class QNetworkSessionPrivate; }; -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); - #ifndef QT_MOBILITY_BEARER QT_END_NAMESPACE #else QTM_END_NAMESPACE #endif +Q_DECLARE_METATYPE(QNetworkSession::State); +Q_DECLARE_METATYPE(QNetworkSession::SessionError); + QT_END_HEADER #endif // QT_NO_BEARERMANAGEMENT -- cgit v0.12 From d0d0763f6e0c7709208ad1c573266ee527f6e4ff Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 7 Feb 2011 15:51:05 +0000 Subject: Fix duplicate definition error As the metatype declaration is now in the qnetworksession header file, it is not needed in the test code (and causes compile error on some platforms) Reviewed-By: Markus Goetz --- tests/auto/qnetworksession/test/tst_qnetworksession.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 37fc9cd..3315836 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -60,8 +60,6 @@ QT_USE_NAMESPACE Q_DECLARE_METATYPE(QNetworkConfiguration) Q_DECLARE_METATYPE(QNetworkConfiguration::Type); -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); class tst_QNetworkSession : public QObject { @@ -126,8 +124,6 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur void tst_QNetworkSession::initTestCase() { - qRegisterMetaType("QNetworkSession::State"); - qRegisterMetaType("QNetworkSession::SessionError"); qRegisterMetaType("QNetworkConfiguration"); qRegisterMetaType("QNetworkConfiguration::Type"); -- cgit v0.12 From 4cc2c1d87a90279cd024768c905da013f037cea1 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 7 Feb 2011 17:56:43 +0100 Subject: Revert "Improved performance of mapFromGlobal/mapToGlobal on X11" This change introduced regressions with some window managers (for example with metacity when you maximize the window) This reverts commit cdd776a91e65bf5c30cea1bab9823134a3f797d0. --- src/gui/kernel/qwidget_x11.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 28eb3f0..b0375ef 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -1318,40 +1318,12 @@ QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const QPoint QWidget::mapToGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos + offset; - return d->mapToGlobal(pos); } QPoint QWidget::mapFromGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos - offset; - return d->mapFromGlobal(pos); } -- cgit v0.12 From cad4964276151879e3e6cf5f7ab610dba512d988 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 7 Feb 2011 17:16:57 +1000 Subject: Scroll TextInput to ensure preedit text is visible. Update the scroll position on text input events and ensure the end of the pre-edit text is visible, unless that hides the cursor in which case display as much as possible while still displaying the cursor and a preceding pre-edit character. Change-Id: Iec6f82b00333f7c9ea21fe536c8f11be0f8de710 Task-number: QTBUG-16999 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextinput.cpp | 12 +++- .../tst_qdeclarativetextinput.cpp | 76 ++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 57e60ac..2258ce6 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -980,6 +980,7 @@ void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev) } else { d->control->processInputMethodEvent(ev); updateSize(); + d->updateHorizontalScroll(); } if (!ev->isAccepted()) QDeclarativePaintedItem::inputMethodEvent(ev); @@ -1098,7 +1099,8 @@ int QDeclarativeTextInputPrivate::calculateTextWidth() void QDeclarativeTextInputPrivate::updateHorizontalScroll() { Q_Q(QDeclarativeTextInput); - int cix = qRound(control->cursorToX()); + const int preeditLength = control->preeditAreaText().length(); + int cix = qRound(control->cursorToX(control->cursor() + preeditLength)); QRect br(q->boundingRect().toRect()); int widthUsed = calculateTextWidth(); Qt::Alignment va = QStyle::visualAlignment(control->layoutDirection(), QFlag(Qt::Alignment(hAlign))); @@ -1128,6 +1130,14 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll() // right hscroll = widthUsed - br.width() + 1; } + if (preeditLength > 0) { + // check to ensure long pre-edit text doesn't push the cursor + // off to the left + cix = qRound(control->cursorToX( + control->cursor() + qMax(0, control->preeditCursor() - 1))); + if (cix < hscroll) + hscroll = cix; + } } else { switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 42a0659..a6d30a5 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -124,6 +124,8 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void preeditAutoScroll(); + private: void simulateKey(QDeclarativeView *, int key); QDeclarativeView *createView(const QString &filename); @@ -1435,6 +1437,17 @@ public: closeInputPanelReceived = true; return QInputContext::filterEvent(event); } + + 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; }; @@ -1724,6 +1737,69 @@ void tst_qdeclarativetextinput::testQtQuick11Attributes_data() << ""; } +void tst_qdeclarativetextinput::preeditAutoScroll() +{ + QString committedText = "super"; + QString preeditText = "califragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(QFontMetricsF(input.font()).width(committedText)); + input.setText(committedText); + 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)); + + // test the text is scrolled so the preedit is visible. + ic.sendPreeditText(preeditText.mid(0, 3), 1); + QVERIFY(input.positionAt(0) != 0); + QCOMPARE(input.positionAt(input.width()), 8); + + // test the text is scrolled back when the preedit is removed. + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(input.positionAt(0), 0); + QCOMPARE(input.positionAt(input.width()), 5); + + // test if the preedit is larger than the text input that the + // character preceding the cursor is still visible. + for (int i = 0; i < 3; ++i) { + ic.sendPreeditText(preeditText, i + 1); + QCOMPARE(input.positionAt(0), 5 + i); + } + for (int i = 1; i >= 0; --i) { + ic.sendPreeditText(preeditText, i + 1); + QCOMPARE(input.positionAt(0), 5 + i); + } + + // Test incrementing the preedit cursor doesn't cause further + // scrolling when right most text is visible. + ic.sendPreeditText(preeditText, preeditText.length() - 3); + int position = input.positionAt(0); + for (int i = 2; i >= 0; --i) { + ic.sendPreeditText(preeditText, preeditText.length() - i); + QCOMPARE(input.positionAt(0), position); + } + for (int i = 1; i < 3; ++i) { + ic.sendPreeditText(preeditText, preeditText.length() - i); + QCOMPARE(input.positionAt(0), position); + } + + // Test disabling auto scroll. + ic.sendEvent(QInputMethodEvent()); + + input.setAutoScroll(false); + ic.sendPreeditText(preeditText.mid(0, 3), 1); + QCOMPARE(input.positionAt(0), 0); + QCOMPARE(input.positionAt(input.width()), 5); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v0.12 From 77bd529c04b2f08ca40a282a3ff20df699b27295 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 8 Feb 2011 14:07:09 +1000 Subject: Autotest to go with 9f8a181a619649c8a227e92f3d16677f4b7cb30a --- .../qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp index 5b214e6..6d35332 100644 --- a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp +++ b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp @@ -180,6 +180,10 @@ void tst_qdeclarativeimageprovider::fillRequestTestsData(const QString &id) << "image://test/" + fileName << fileName << "" << QSize(100,100) << ""; fileName = newImageFileName(); + QTest::newRow(QTest::toString(id + " simple test with capitalization"))//As it's a URL, should make no difference + << "image://Test/" + fileName << fileName << "" << QSize(100,100) << ""; + + fileName = newImageFileName(); QTest::newRow(QTest::toString(id + " url with no id")) << "image://test/" + fileName << "" + fileName << "" << QSize(100,100) << ""; -- cgit v0.12 From 50e7bea8bb4ce5a97ab8ff9c7062fc0fa092aec0 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 8 Feb 2011 10:50:48 +0100 Subject: Fixed compilerwarnings regression in public headers. RevBy: Trust me --- src/network/bearer/qnetworksession.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index 7739218..e107c62 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -145,8 +145,8 @@ QT_END_NAMESPACE QTM_END_NAMESPACE #endif -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); +Q_DECLARE_METATYPE(QNetworkSession::State) +Q_DECLARE_METATYPE(QNetworkSession::SessionError) QT_END_HEADER -- cgit v0.12 From 640436345645b6cf6ff3334399f33c9d1c089492 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 7 Feb 2011 14:53:59 +0100 Subject: Don't crash when creating backtrace for built-in JS function (2nd try) Commit 147df10403ba280b3f04c1e3d6c4b1cf386abe5d did not quite fix the issue; other places need the same checks. When the JIT is enabled, frames for built-in JS host calls (such as Array.prototype.forEach) are not fully initialized. In particular, the CodeBlock register of such frames is not set (see comment in JITCall.cpp). We need to check if the codeBlock is actually valid before we start using it. This fixes the crash(es) but not the problem of actually getting the arguments for such frames through the API. There's also a related problem when a QtScript function (newFunction()) is called as a callback of a built-in JS host function (QTBUG-17287). These problems will go away once JavaScriptCore is updated to a more recent version (4.8 at the earliest), since the native-vs-script frame handling has been unified. Task-number: QTBUG-17137 Reviewed-by: Olivier Goffart --- src/script/api/qscriptcontext.cpp | 9 ++++++- src/script/api/qscriptcontextinfo.cpp | 4 +-- src/script/api/qscriptengine.cpp | 3 ++- src/script/api/qscriptengine_p.h | 18 ++++++++++++++ tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 31 +++++++++++++++++++++++- tests/auto/qscriptengine/tst_qscriptengine.cpp | 16 ++++++++++++ 6 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 59ea52d..2468a46 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -299,6 +299,12 @@ QScriptValue QScriptContext::argumentsObject() const //for a js function if (frame->codeBlock() && frame->callee()) { + if (!QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { + // We have a built-in JS host call. + // codeBlock is needed by retrieveArguments(), but since it + // contains junk, we would crash. Return an invalid value for now. + return QScriptValue(); + } JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee())); return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } @@ -309,7 +315,8 @@ QScriptValue QScriptContext::argumentsObject() const } //for a native function - if (!frame->optionalCalleeArguments()) { + if (!frame->optionalCalleeArguments() + && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { // Make sure we don't go here for host JSFunctions Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters); frame->setCalleeArguments(arguments); diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index d39abe6..0f9de1d 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -157,7 +157,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::Instruction *returnPC = rewindContext->returnPC(); JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (returnPC && codeBlock) { + if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { #if ENABLE(JIT) unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC)); #else @@ -171,7 +171,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the filename and the scriptId: JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (codeBlock) { + if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { JSC::SourceProvider *source = codeBlock->source(); scriptId = source->asID(); fileName = source->url(); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 54039c0..478fdaa 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -858,7 +858,8 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS { JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag(); while (frame) { - if (frame->codeBlock() && frame->codeBlock()->source() + if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame) + && frame->codeBlock()->source() && !frame->codeBlock()->source()->url().isEmpty()) { context = engine->translationContextFromUrl(frame->codeBlock()->source()->url()); break; diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index f8144e9..94d195e 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -56,6 +56,7 @@ #include "Debugger.h" #include "ErrorInstance.h" #include "JSArray.h" +#include "Executable.h" #include "Lexer.h" #include "RefPtr.h" #include "RegExpConstructor.h" @@ -231,6 +232,8 @@ public: static inline JSC::ExecState *frameForContext(QScriptContext *context); static inline const JSC::ExecState *frameForContext(const QScriptContext *context); + static inline bool hasValidCodeBlockRegister(JSC::ExecState *frame); + JSC::JSGlobalObject *originalGlobalObject() const; JSC::JSObject *getOriginalGlobalObjectProxy(); JSC::JSObject *customGlobalObject() const; @@ -862,6 +865,21 @@ inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScript return reinterpret_cast(context); } +inline bool QScriptEnginePrivate::hasValidCodeBlockRegister(JSC::ExecState *frame) +{ +#if ENABLE(JIT) + // Frames created by the VM don't have their CodeBlock register + // initialized. We can detect such frames by checking if the + // callee is a host JSFunction. + JSC::JSObject *callee = frame->callee(); + return !(callee && callee->inherits(&JSC::JSFunction::info) + && JSC::asFunction(callee)->isHostFunction()); +#else + Q_UNUSED(frame); + return true; +#endif +} + inline JSC::ExecState *QScriptEnginePrivate::globalExec() const { return originalGlobalObject()->globalExec(); diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index dd21555..7915eb0 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -871,7 +871,36 @@ void tst_QScriptContext::backtrace_data() QStringList expected; expected << "() at -1" << "(0, 0, 0) at testfile:3" - << "forEach(0) at -1" + << QString::fromLatin1("forEach(%0) at -1") + // Because the JIT doesn't store the arguments in the frame + // for built-in functions, arguments are not available. + // Will work when the copy of JavaScriptCore is updated + // (QTBUG-16568). + .arg(qt_script_isJITEnabled() + ? "" + : "function () {\n result = bt();\n}") + << "() at testfile:4"; + QTest::newRow("js callback from built-in") << source << expected; + } + + { + QString source = QString::fromLatin1( + "[10,20].forEach(\n" + " function() {\n" + " result = bt();\n" + "}); result"); + + QStringList expected; + expected << "() at -1" + << "(20, 1, 10,20) at testfile:3" + << QString::fromLatin1("forEach(%0) at -1") + // Because the JIT doesn't store the arguments in the frame + // for built-in functions, arguments are not available. + // Will work when the copy of JavaScriptCore is updated + // (QTBUG-16568). + .arg(qt_script_isJITEnabled() + ? "" + : "function () {\n result = bt();\n}") << "() at testfile:4"; QTest::newRow("js callback from built-in") << source << expected; } diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index c3a0ba1..8de6fbc 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -164,6 +164,7 @@ private slots: void translationContext_data(); void translationContext(); void translateScriptIdBased(); + void translateFromBuiltinCallback(); void functionScopes(); void nativeFunctionScopes(); void evaluateProgram(); @@ -4725,6 +4726,21 @@ void tst_QScriptEngine::translateScriptIdBased() QString::fromLatin1("qtn_foo_bar")); // Doesn't have plural } +void tst_QScriptEngine::translateFromBuiltinCallback() +{ + QScriptEngine eng; + eng.installTranslatorFunctions(); + + // Callback has no translation context. + eng.evaluate("function foo() { qsTr('foo'); }"); + + // Stack at translation time will be: + // qsTr, foo, forEach, global + // qsTr() needs to walk to the outer-most (global) frame before it finds + // a translation context, and this should not crash. + eng.evaluate("[10,20].forEach(foo)", "script.js"); +} + void tst_QScriptEngine::functionScopes() { QScriptEngine eng; -- cgit v0.12 From c718d992865de7015df0173c816b257d72e13f24 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 8 Feb 2011 11:08:37 +0100 Subject: Fix compilation error: symbol is namespaced. Reviewed-by: Rohan McGovern --- tools/qdbus/qdbus/qdbus.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index 4e5cf9a..d8433fc 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -50,7 +50,9 @@ #include #include +QT_BEGIN_NAMESPACE Q_DBUS_EXPORT extern bool qt_dbus_metaobject_skip_annotations; +QT_END_NAMESPACE static QDBusConnection connection(QLatin1String("")); static bool printArgumentsLiterally = false; -- cgit v0.12 From dd49b322b327fe87d8420abcce0e6cee877a88d7 Mon Sep 17 00:00:00 2001 From: mae Date: Tue, 8 Feb 2011 12:33:03 +0100 Subject: Support seperate versions of installed modules QML supports versioned types in modules. There's a version major and a version minor. This makes it possible to have a module com.organisation.fancycomponents with version 1.0, and later you could ship a new module com.organisation.fancycomponents which contains a more recent version 1.1 or 2.0 AND also the old versions to keep old code running. This is good. The problem is that this is difficult with certain QA procedures. It's hard to verify that a new module is indeed 100% compatible with the previous versions. The change extends the import mechanism by adding optional versioning to the component patch. With the patch, you can add a new module com.organisation.fancycomponents.2.0 which will be loaded when the QML file specifies "import com.organisation.fancycomponents 2.0". The patch works as follows: if you try to load com.organisation.fancycomponents in version 2.0, the engine first looks for com/organisation/fancycomponents.2.0, then for com/organisation/fancycomponents.2 then for com.organisation/fancycomponents. Reviewed-by: Aaron Kennedy Task-number: QTBUG-16455 --- doc/src/declarative/modules.qdoc | 9 +++ src/declarative/qml/qdeclarativeimport.cpp | 76 ++++++++++++++++---- .../qdeclarativemoduleplugin/data/works2.qml | 3 + .../qdeclarativemoduleplugin/data/works21.qml | 3 + .../com/nokia/AutoTestQmlPluginType.2.1/qmldir | 1 + .../com/nokia/AutoTestQmlPluginType.2/qmldir | 1 + .../plugin.2.1/plugin.2.1.pro | 9 +++ .../qdeclarativemoduleplugin/plugin.2.1/plugin.cpp | 84 ++++++++++++++++++++++ .../qdeclarativemoduleplugin/plugin.2/plugin.2.pro | 9 +++ .../qdeclarativemoduleplugin/plugin.2/plugin.cpp | 84 ++++++++++++++++++++++ .../qdeclarativemoduleplugin.pro | 2 +- .../tst_qdeclarativemoduleplugin.cpp | 34 +++++++++ 12 files changed, 302 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc index 1dca28c..4b2b33a 100644 --- a/doc/src/declarative/modules.qdoc +++ b/doc/src/declarative/modules.qdoc @@ -134,6 +134,15 @@ Installed modules that are installed into the import path or created as a \l{QDeclarativeExtensionPlugin}{QML C++ plugin} must define a \l{Writing a qmldir file}{qmldir file}. +Modules that are installed into the import path translate the URI into +directory names. For example, the qmldir file of the module \c com.nokia.qml.mymodule +must be located in the subpath \c com/nokia/qml/mymodule/qmldir somewhere in the +QML import path. In addition it is possible to store different versions of the +module in subdirectories of its own. For example, a version 2.1 of the +module could be located under \c com/nokia/qml/mymodule.2/qmldir or +\c com/nokia/qml/mymodule.2.1/qmldir. The engine will automatically load +the module which matches best. + \section2 The QML import path diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index c89666d..22dcb44 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -425,8 +425,18 @@ QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclara break; } } + + stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('/')); + + // remove optional versioning in dot notation from uri + int lastSlash = stableRelativePath.lastIndexOf(QLatin1Char('/')); + if (lastSlash >= 0) { + int versionDot = stableRelativePath.indexOf(QLatin1Char('.'), lastSlash); + if (versionDot >= 0) + stableRelativePath = stableRelativePath.left(versionDot); + } + stableRelativePath.replace(QLatin1Char('/'), QLatin1Char('.')); - stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('.')); return stableRelativePath; } @@ -453,20 +463,62 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp QString dir; - foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + // step 1: search for extension with fully encoded version number + if (vmaj >= 0 && vmin >= 0) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; - QFileInfo fi(dir+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); + QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); - if (fi.isFile()) { - found = true; + if (fi.isFile()) { + found = true; - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); - uri = resolvedUri(dir, database); - if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) - return false; - break; + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; + } + } + } + // step 2: search for extension with encoded version major + if (vmaj >= 0 && vmin >= 0) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; + + QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); + + if (fi.isFile()) { + found = true; + + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; + } + } + } + if (!found) { + // step 3: search for extension without version number + + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; + + QFileInfo fi(dir+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); + + if (fi.isFile()) { + found = true; + + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; + } } } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml new file mode 100644 index 0000000..cc322bf --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestQmlPluginType 2.0 + +MyPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml new file mode 100644 index 0000000..c08160a --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestQmlPluginType 2.1 + +MyPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir new file mode 100644 index 0000000..0a8b5d4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir @@ -0,0 +1 @@ +plugin plugin diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir new file mode 100644 index 0000000..0a8b5d4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir @@ -0,0 +1 @@ +plugin plugin diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro new file mode 100644 index 0000000..661675a --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlPluginType.2.1 + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp new file mode 100644 index 0000000..1ae2bd4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import2.1 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyPlugin() + { + qWarning("plugin2.1 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType"); + qmlRegisterType(uri, 2, 1, "MyPluginType"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro new file mode 100644 index 0000000..d254642 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlPluginType.2 + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp new file mode 100644 index 0000000..6bd8542 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import2 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyPlugin() + { + qWarning("plugin2 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType"); + qmlRegisterType(uri, 2, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro index 221e465..10864df 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro @@ -1,6 +1,6 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin pluginWrongCase +SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase tst_qdeclarativemoduleplugin_pro.depends += plugin SUBDIRS += tst_qdeclarativemoduleplugin.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 96ec21b..7e381ee 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -54,6 +54,8 @@ public: private slots: void importsPlugin(); + void importsPlugin2(); + void importsPlugin21(); void incorrectPluginCase(); }; @@ -121,6 +123,38 @@ void tst_qdeclarativemoduleplugin::importsPlugin() delete object; } +void tst_qdeclarativemoduleplugin::importsPlugin2() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QTest::ignoreMessage(QtWarningMsg, "plugin2 created"); + QTest::ignoreMessage(QtWarningMsg, "import2 worked"); + QDeclarativeComponent component(&engine, TEST_FILE("data/works2.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + +void tst_qdeclarativemoduleplugin::importsPlugin21() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QTest::ignoreMessage(QtWarningMsg, "plugin2.1 created"); + QTest::ignoreMessage(QtWarningMsg, "import2.1 worked"); + QDeclarativeComponent component(&engine, TEST_FILE("data/works21.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + void tst_qdeclarativemoduleplugin::incorrectPluginCase() { QDeclarativeEngine engine; -- cgit v0.12 From 8d6ad569495d389b111ab8879117cc7832287fa8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 6 Feb 2011 18:51:34 +0100 Subject: Make sure we use at least 1024 bytes when calling getpwuid_r. On some systems, sysconf may return -1 to indicate that there's no such limit (limitless), so don't create a buffer of size -1. Reviewed-by: Bradley T. Hughes --- src/gui/kernel/qapplication_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index f28868c..8fef6fb 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5657,7 +5657,7 @@ static void sm_performSaveYourself(QSessionManagerPrivate* smd) // tell the session manager about our user as well. struct passwd *entryPtr = 0; #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - QVarLengthArray buf(sysconf(_SC_GETPW_R_SIZE_MAX)); + QVarLengthArray buf(qMax(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr); #else -- cgit v0.12 From 609bcb4f9ab3f8fecd037e9c401891ca4d6f2172 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 6 Feb 2011 18:58:00 +0100 Subject: Use an increasing size for the getpwuid_r buffer. Reviewed-by: Bradley T. Hughes --- src/gui/kernel/qapplication_x11.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 8fef6fb..4cdb82f 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5659,7 +5659,18 @@ static void sm_performSaveYourself(QSessionManagerPrivate* smd) #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) QVarLengthArray buf(qMax(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; - getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr); + while (getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr) == ERANGE) { + if (buf.size() >= 32768) { + // too big already, fail + static char badusername[] = ""; + entryPtr = &entry; + entry.pw_name = badusername; + break; + } + + // retry with a bigger buffer + buf.resize(buf.size() * 2); + } #else entryPtr = getpwuid(geteuid()); #endif -- cgit v0.12 From 6b6b13130a95b896202ad09fa349e3f69c2807de Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 6 Feb 2011 19:43:50 +0100 Subject: Check that _POSIX_THREAD_SAFE_FUNCTIONS is larger than zero. POSIX allows this symbol to be defined to -1 to indicate that the interfaces aren't present. On FreeBSD 8, it's defined to -1, but the functions are present (supposedly, they don't work -- just stubs). Guessing that OpenBSD is the same. Also removing the QT_NO_THREAD, since Qt can't be built without threading support. It's only used by our bootstrapped tools, which in turn use QCoreApplication only (no QApplication). Reviewed-By: Bradley T. Hughes --- src/gui/kernel/qapplication_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 4cdb82f..e0447cc 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5656,7 +5656,7 @@ static void sm_performSaveYourself(QSessionManagerPrivate* smd) sm_setProperty(QString::fromLatin1(SmProgram), argument0); // tell the session manager about our user as well. struct passwd *entryPtr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) QVarLengthArray buf(qMax(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; while (getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr) == ERANGE) { -- cgit v0.12 From e5fbadc54b8e25c94c50f0d0a49bc1a44674dac7 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Thu, 3 Feb 2011 21:10:59 +0100 Subject: Use the thread-default glib context for the DBus connection in the ICD bearer manager. This allows the bearer management plugin to be ran on a thread different than the main one. Task-number: QTBUG-17199 Reviewed-by: Kranthi --- src/plugins/bearer/icd/dbusdispatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/bearer/icd/dbusdispatcher.cpp b/src/plugins/bearer/icd/dbusdispatcher.cpp index 5fc2a38..f100a48 100644 --- a/src/plugins/bearer/icd/dbusdispatcher.cpp +++ b/src/plugins/bearer/icd/dbusdispatcher.cpp @@ -468,7 +468,7 @@ void DBusDispatcher::setupDBus() d_ptr->signal_vtable.message_function = signalHandler; dbus_connection_set_exit_on_disconnect(d_ptr->connection, FALSE); - dbus_connection_setup_with_g_main(d_ptr->connection, NULL); + dbus_connection_setup_with_g_main(d_ptr->connection, g_main_context_get_thread_default()); dbus_connection_register_object_path(d_ptr->connection, d_ptr->signalPath.toLatin1(), &d_ptr->signal_vtable, -- cgit v0.12 From 97c07046f9031f19005e7f57fc0dee09437f378b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 8 Feb 2011 16:21:47 +0100 Subject: Fix the compilation error that the previous fix didn't fix --- tools/qdbus/qdbus/qdbus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp index d8433fc..8e1c384 100644 --- a/tools/qdbus/qdbus/qdbus.cpp +++ b/tools/qdbus/qdbus/qdbus.cpp @@ -443,7 +443,7 @@ static void printAllServices(QDBusConnectionInterface *bus) int main(int argc, char **argv) { - qt_dbus_metaobject_skip_annotations = true; + QT_PREPEND_NAMESPACE(qt_dbus_metaobject_skip_annotations) = true; QCoreApplication app(argc, argv); QStringList args = app.arguments(); args.takeFirst(); -- cgit v0.12 From a6ccb1a72173cec6381d519a720dc08cfdc03720 Mon Sep 17 00:00:00 2001 From: David Faure Date: Tue, 8 Feb 2011 16:33:42 +0100 Subject: Fix compilation of QMutableSetIterator::value() with QT_STRICT_ITERATORS Merge-request: 1078 Reviewed-by: Thiago Macieira --- src/corelib/tools/qset.h | 2 +- tests/auto/qset/tst_qset.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 8075fbd..1074f99 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -330,7 +330,7 @@ class QMutableSetIterator typedef typename QSet::iterator iterator; QSet *c; iterator i, n; - inline bool item_exists() const { return n != c->constEnd(); } + inline bool item_exists() const { return c->constEnd() != n; } public: inline QMutableSetIterator(QSet &container) diff --git a/tests/auto/qset/tst_qset.cpp b/tests/auto/qset/tst_qset.cpp index 204ca55..164bf1e 100644 --- a/tests/auto/qset/tst_qset.cpp +++ b/tests/auto/qset/tst_qset.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +//#define QT_STRICT_ITERATORS #include #include @@ -815,6 +816,16 @@ void tst_QSet::javaMutableIterator() int sum = 0; QMutableSetIterator i(set1); while (i.hasNext()) { + i.next(); + sum += toNumber(i.value()); + } + QVERIFY(sum == 24999 * 25000 / 2); + } + + { + int sum = 0; + QMutableSetIterator i(set1); + while (i.hasNext()) { sum += toNumber(i.peekNext()); i.next(); } -- cgit v0.12 From f7e789710568d263816f50bd5782cc7adec41249 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 8 Feb 2011 13:43:19 +1000 Subject: Don't clear pre-edit text when a graphics items loses focus. Don't forceably reset the input method state when a graphics item loses focus, reset the input context and let it handle sending the appropriate events itself. That way behavior is consistent with QWidget and the input context can opt to commit its current pre-edit text instead of discarding it. And don't change the focus until after the input context has been reset or the input method events won't be delivered. Change-Id: Ic545bccab6bf671709c1d06d499217baf614e6f9 Task-number: QTBUG-16997 Reviewed-by: axis --- src/gui/graphicsview/qgraphicsscene.cpp | 19 ++++++-------- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 32 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5e5077b..c395a54 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -806,28 +806,23 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, } if (focusItem) { - QFocusEvent event(QEvent::FocusOut, focusReason); lastFocusItem = focusItem; - focusItem = 0; - sendEvent(lastFocusItem, &event); #ifndef QT_NO_IM if (lastFocusItem && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { - // Reset any visible preedit text - QInputMethodEvent imEvent; - sendEvent(lastFocusItem, &imEvent); - // Close any external input method panel. This happens // automatically by removing WA_InputMethodEnabled on // the views, but if we are changing focus, we have to // do it ourselves. - if (item) { - for (int i = 0; i < views.size(); ++i) - if (views.at(i)->inputContext()) - views.at(i)->inputContext()->reset(); - } + for (int i = 0; i < views.size(); ++i) + if (views.at(i)->inputContext()) + views.at(i)->inputContext()->reset(); } + + focusItem = 0; + QFocusEvent event(QEvent::FocusOut, focusReason); + sendEvent(lastFocusItem, &event); #endif //QT_NO_IM } diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index b221cd9..d446ca7 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -3838,6 +3838,23 @@ public: mutable int queryCalls; }; +class TestInputContext : public QInputContext +{ +public: + TestInputContext() {} + + QString identifierName() { return QString(); } + QString language() { return QString(); } + + void reset() { + ++resetCalls; + sendEvent(QInputMethodEvent()); } + + bool isComposing() const { return false; } + + int resetCalls; +}; + void tst_QGraphicsScene::inputMethod() { QFETCH(int, flags); @@ -3847,14 +3864,22 @@ void tst_QGraphicsScene::inputMethod() item->setFlags((QGraphicsItem::GraphicsItemFlags)flags); QGraphicsScene scene; - QEvent activate(QEvent::WindowActivate); - QApplication::sendEvent(&scene, &activate); + QGraphicsView view(&scene); + TestInputContext inputContext; + view.setInputContext(&inputContext); + view.show(); + QApplication::setActiveWindow(&view); + view.setFocus(); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + inputContext.resetCalls = 0; scene.addItem(item); QInputMethodEvent event; scene.setFocusItem(item); QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item); + QCOMPARE(inputContext.resetCalls, 0); item->eventCalls = 0; qApp->sendEvent(&scene, &event); @@ -3865,6 +3890,9 @@ void tst_QGraphicsScene::inputMethod() QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); scene.setFocusItem(0); + // the input context is reset twice, once because an item has lost focus and again because + // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus. + QCOMPARE(inputContext.resetCalls, callFocusItem ? 2 : 0); QCOMPARE(item->eventCalls, callFocusItem ? 2 : 0); // verify correct delivery of "reset" event QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected -- cgit v0.12 From ccd1b7dd5c8e6b1c4bf5b21354f7b9acaf881b00 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 7 Feb 2011 17:23:42 +1000 Subject: Use same values for Text.lineHeightMode and QTextBlock::lineHeightMode from master. - MultiplyHeight becomes ProportionalHeight - PixelHeight becomes FixedHeight Change-Id: I2a1ebc6ff9db7e62f513919f19773f985b08f8d7 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativetext.cpp | 12 +++++++----- src/declarative/graphicsitems/qdeclarativetext_p.h | 2 +- src/gui/text/qtextdocumentlayout.cpp | 8 +++++--- src/gui/text/qtextdocumentlayout_p.h | 4 +++- .../declarative/qdeclarativetext/tst_qdeclarativetext.cpp | 12 ++++++------ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 54b4c3a..4c6c34f 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -99,7 +99,8 @@ QString QDeclarativeTextPrivate::elideChar = QString(0x2026); QDeclarativeTextPrivate::QDeclarativeTextPrivate() : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1), lineHeightMode(QDeclarativeText::MultiplyHeight), + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1), + lineHeightMode(QDeclarativeText::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX), maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), naturalWidth(0), doc(0) @@ -189,7 +190,7 @@ QDeclarativeTextDocumentLayout::QDeclarativeTextDocumentLayout(QTextDocument *do : QTextDocumentLayout(doc) { } -void QDeclarativeTextDocumentLayout::setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode = QDeclarativeText::MultiplyHeight) +void QDeclarativeTextDocumentLayout::setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode = QDeclarativeText::ProportionalHeight) { QTextDocumentLayout::setLineHeight(lineHeight, QTextDocumentLayout::LineHeightMode(mode)); } @@ -468,7 +469,7 @@ QSize QDeclarativeTextPrivate::setupTextLayout() for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); line.setPosition(QPointF(0, height)); - height += (lineHeightMode == QDeclarativeText::PixelHeight) ? lineHeight : line.height() * lineHeight; + height += (lineHeightMode == QDeclarativeText::FixedHeight) ? lineHeight : line.height() * lineHeight; if (!cacheAllTextAsImage) { if ((hAlignment == QDeclarativeText::AlignLeft) || (hAlignment == QDeclarativeText::AlignJustify)) { @@ -1461,8 +1462,9 @@ void QDeclarativeText::setLineHeight(qreal lineHeight) The possible values are: \list - \o Text.MultiplyHeight (default) - specifies a line height multiplier, - \o Text.PixelHeight - specifies the line height in pixels. + \o Text.ProportionalHeight (default) - this sets the spacing proportional to the + line (as a multiplier). For example, set to 2 for double spacing. + \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels). \endlist */ QDeclarativeText::LineHeightMode QDeclarativeText::lineHeightMode() const diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index f3697d5..b8835d1 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -114,7 +114,7 @@ public: Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; - enum LineHeightMode { MultiplyHeight, PixelHeight }; + enum LineHeightMode { ProportionalHeight, FixedHeight }; QString text() const; void setText(const QString &); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index c1c3768..a1dcb63 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -525,7 +525,7 @@ QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() lazyLayoutStepSize(1000), lastPageCount(-1), lineH(1), - lineHeightMode(QTextDocumentLayout::MultiplyHeight) + lineHeightMode(QTextDocumentLayout::ProportionalHeight) { showLayoutProgress = true; insideDocumentChange = false; @@ -2644,7 +2644,9 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } - QFixed lineHeight = (lineHeightMode == QTextDocumentLayout::PixelHeight) ? QFixed::fromReal(lineH) : QFixed::fromReal(line.height() * lineH); + // TODO: replace with proper line height support in 4.8 + QFixed lineHeight = (lineHeightMode == QTextDocumentLayout::FixedHeight) + ? QFixed::fromReal(lineH) : QFixed::fromReal(line.height() * lineH); if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) { layoutStruct->newPage(); @@ -2720,7 +2722,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } } -void QTextDocumentLayout::setLineHeight(qreal lineH, QTextDocumentLayout::LineHeightMode mode = QTextDocumentLayout::MultiplyHeight) +void QTextDocumentLayout::setLineHeight(qreal lineH, QTextDocumentLayout::LineHeightMode mode = QTextDocumentLayout::ProportionalHeight) { Q_D(QTextDocumentLayout); d->lineH = lineH; diff --git a/src/gui/text/qtextdocumentlayout_p.h b/src/gui/text/qtextdocumentlayout_p.h index efc408b..3e3e485 100644 --- a/src/gui/text/qtextdocumentlayout_p.h +++ b/src/gui/text/qtextdocumentlayout_p.h @@ -109,7 +109,9 @@ protected: void drawInlineObject(QPainter *p, const QRectF &rect, QTextInlineObject item, int posInDocument, const QTextFormat &format); virtual void timerEvent(QTimerEvent *e); - enum LineHeightMode { MultiplyHeight, PixelHeight }; + + // TODO: remove when we support line height properly in 4.8 + enum LineHeightMode { ProportionalHeight, FixedHeight }; void setLineHeight(qreal lineHeight, QTextDocumentLayout::LineHeightMode mode); private: diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 44059f5..05546cb 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -1099,25 +1099,25 @@ void tst_qdeclarativetext::lineHeight() QVERIFY(myText != 0); QVERIFY(myText->lineHeight() == 1); - QVERIFY(myText->lineHeightMode() == QDeclarativeText::MultiplyHeight); + QVERIFY(myText->lineHeightMode() == QDeclarativeText::ProportionalHeight); qreal h = myText->height(); myText->setLineHeight(1.5); QVERIFY(myText->height() == h * 1.5); - myText->setLineHeightMode(QDeclarativeText::PixelHeight); + myText->setLineHeightMode(QDeclarativeText::FixedHeight); myText->setLineHeight(20); QCOMPARE(myText->height(), myText->lineCount() * 20.0); myText->setText("Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum."); - myText->setLineHeightMode(QDeclarativeText::MultiplyHeight); - myText->setLineHeight(1); + myText->setLineHeightMode(QDeclarativeText::ProportionalHeight); + myText->setLineHeight(1.0); //qreal h2 = myText->height(); myText->setLineHeight(2.0); //QVERIFY(myText->height() == h2 * 2.0); - myText->setLineHeightMode(QDeclarativeText::PixelHeight); + myText->setLineHeightMode(QDeclarativeText::FixedHeight); myText->setLineHeight(10); //QCOMPARE(myText->height(), myText->lineCount() * 10.0); @@ -1189,7 +1189,7 @@ void tst_qdeclarativetext::testQtQuick11Attributes_data() << "QDeclarativeComponent: Component is not ready" << ":1 \"Text.lineHeight\" is not available in QtQuick 1.0.\n"; - QTest::newRow("lineHeightMode") << "lineHeightMode: Text.MultiplyHeight" + QTest::newRow("lineHeightMode") << "lineHeightMode: Text.ProportionalHeight" << "QDeclarativeComponent: Component is not ready" << ":1 \"Text.lineHeightMode\" is not available in QtQuick 1.0.\n"; -- cgit v0.12 From b3080d78f2ff2d98410249e09d5d7d6e20fd155c Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 8 Feb 2011 17:55:17 +1000 Subject: Call onAdd() for first items added to ListView and GridView The bug was caused by the fact that the itemsInserted() implementation in ListView and GridView returned early for cases where (model->count() <= 1) and so did not call onAdd() unlike for other cases. This change also fixes some incorrect values in the header() and footer() unit tests for ListView and GridView. Change-Id: I24f5c86afcd62c26e17b0932f257f4767a287b8e Task-number: QTBUG-15642 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativegridview.cpp | 56 ++++----- .../graphicsitems/qdeclarativelistview.cpp | 29 ++--- .../qdeclarativegridview/data/attachedSignals.qml | 27 +++++ .../tst_qdeclarativegridview.cpp | 135 ++++++++++++++++++++- .../qdeclarativelistview/data/attachedSignals.qml | 24 ++++ .../tst_qdeclarativelistview.cpp | 126 ++++++++++++++++++- 6 files changed, 340 insertions(+), 57 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml create mode 100644 tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 9aade98..f4f7d29 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -2388,24 +2388,9 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) Q_D(QDeclarativeGridView); if (!isComponentComplete()) return; - if (!d->visibleItems.count() || d->model->count() <= 1) { - d->scheduleLayout(); - if (d->itemCount && d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { - d->updateCurrent(0); - } - d->itemCount += count; - emit countChanged(); - return; - } - int index = d->mapFromModel(modelIndex); - if (index == -1) { + int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0; + if (index < 0) { int i = d->visibleItems.count() - 1; while (i > 0 && d->visibleItems.at(i)->index == -1) --i; @@ -2436,28 +2421,35 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) } } - // At least some of the added items will be visible int insertCount = count; - if (index < d->visibleIndex) { + if (index < d->visibleIndex && d->visibleItems.count()) { insertCount -= d->visibleIndex - index; index = d->visibleIndex; modelIndex = d->visibleIndex; } - index -= d->visibleIndex; int to = d->buffer+d->position()+d->size()-1; - int colPos, rowPos; - if (index < d->visibleItems.count()) { - colPos = d->visibleItems.at(index)->colPos(); - rowPos = d->visibleItems.at(index)->rowPos(); - } else { - // appending items to visible list - colPos = d->visibleItems.at(index-1)->colPos() + d->colSize(); - rowPos = d->visibleItems.at(index-1)->rowPos(); - if (colPos > d->colSize() * (d->columns-1)) { - colPos = 0; - rowPos += d->rowSize(); + int colPos = 0; + int rowPos = 0; + if (d->visibleItems.count()) { + index -= d->visibleIndex; + if (index < d->visibleItems.count()) { + colPos = d->visibleItems.at(index)->colPos(); + rowPos = d->visibleItems.at(index)->rowPos(); + } else { + // appending items to visible list + colPos = d->visibleItems.at(index-1)->colPos() + d->colSize(); + rowPos = d->visibleItems.at(index-1)->rowPos(); + if (colPos > d->colSize() * (d->columns-1)) { + colPos = 0; + rowPos += d->rowSize(); + } } + } else if (d->itemCount == 0 && d->header) { + if (d->flow == QDeclarativeGridView::LeftToRight) + rowPos = d->headerSize(); + else + colPos = d->headerSize(); } // Update the indexes of the following visible items. @@ -2510,6 +2502,8 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) if (d->currentItem) { d->currentItem->index = d->currentIndex; d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex)); + } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { + d->updateCurrent(0); } emit currentIndexChanged(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 075c3af..74e9826 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2848,23 +2848,8 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) return; d->updateUnrequestedIndexes(); d->moveReason = QDeclarativeListViewPrivate::Other; - if (!d->visibleItems.count() || d->model->count() <= 1) { - d->scheduleLayout(); - if (d->itemCount && d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { - d->updateCurrent(0); - } - d->itemCount += count; - emit countChanged(); - return; - } - int index = d->mapFromModel(modelIndex); + int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0; if (index < 0) { int i = d->visibleItems.count() - 1; while (i > 0 && d->visibleItems.at(i)->index == -1) @@ -2900,11 +2885,15 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) } } - // At least some of the added items will be visible - // index can be the next item past the end of the visible items list (i.e. appended) - int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position() + int pos = 0; + if (d->visibleItems.count()) { + pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position() : d->visibleItems.last()->endPosition()+d->spacing+1; + } else if (d->itemCount == 0 && d->header) { + pos = d->header->size(); + } + int initialPos = pos; int diff = 0; QList added; @@ -2971,6 +2960,8 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) if (d->currentItem) { d->currentItem->index = d->currentIndex; d->currentItem->setPosition(d->currentItem->position() + diff); + } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { + d->updateCurrent(0); } emit currentIndexChanged(); } diff --git a/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml b/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml new file mode 100644 index 0000000..d527e9d --- /dev/null +++ b/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml @@ -0,0 +1,27 @@ +import QtQuick 1.0 + +GridView { + id: view + width: 240; height: 320 + + property variant addedDelegates: [] + property int removedDelegateCount + + model: testModel + + cellWidth: delegateWidth; cellHeight: delegateHeight + + delegate: Rectangle { + width: delegateWidth; height: delegateHeight + border.width: 1 + GridView.onAdd: { + var obj = GridView.view.addedDelegates + obj.push(model.name) + GridView.view.addedDelegates = obj + } + GridView.onRemove: { + view.removedDelegateCount += 1 + } + } +} + diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index 82a1a4a..79189a7 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -86,6 +86,10 @@ private slots: void footer(); void header(); void indexAt(); + void onAdd(); + void onAdd_data(); + void onRemove(); + void onRemove_data(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); @@ -131,6 +135,13 @@ public: emit endInsertRows(); } + void addItems(const QList > &items) { + emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1); + for (int i=0; i(items[i].first, items[i].second)); + emit endInsertRows(); + } + void insertItem(int index, const QString &name, const QString &number) { emit beginInsertRows(QModelIndex(), index, index); list.insert(index, QPair(name, number)); @@ -143,6 +154,13 @@ public: emit endRemoveRows(); } + void removeItems(int index, int count) { + emit beginRemoveRows(QModelIndex(), index, index+count-1); + while (count--) + list.removeAt(index); + emit endRemoveRows(); + } + void moveItem(int from, int to) { emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); list.move(from, to); @@ -1388,7 +1406,7 @@ void tst_QDeclarativeGridView::footer() footer = findItem(contentItem, "footer2"); QVERIFY(footer); - QCOMPARE(footer->y(), 0.0); + QCOMPARE(footer->y(), 600.0); QCOMPARE(footer->height(), 20.0); QCOMPARE(gridview->contentY(), 0.0); } @@ -1437,9 +1455,9 @@ void tst_QDeclarativeGridView::header() header = findItem(contentItem, "header2"); QVERIFY(header); - QCOMPARE(header->y(), 0.0); + QCOMPARE(header->y(), 10.0); QCOMPARE(header->height(), 20.0); - QCOMPARE(gridview->contentY(), 0.0); + QCOMPARE(gridview->contentY(), 10.0); } void tst_QDeclarativeGridView::indexAt() @@ -1479,6 +1497,117 @@ void tst_QDeclarativeGridView::indexAt() delete canvas; } +void tst_QDeclarativeGridView::onAdd() +{ + QFETCH(int, initialItemCount); + QFETCH(int, itemsToAdd); + + const int delegateWidth = 50; + const int delegateHeight = 100; + TestModel model; + QDeclarativeView *canvas = createView(); + canvas->setFixedSize(5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit + + // these initial items should not trigger GridView.onAdd + for (int i=0; irootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateWidth", delegateWidth); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + + QObject *object = canvas->rootObject(); + object->setProperty("width", canvas->width()); + object->setProperty("height", canvas->height()); + qApp->processEvents(); + + QList > items; + for (int i=0; iprocessEvents(); + + QVariantList result = object->property("addedDelegates").toList(); + QCOMPARE(result.count(), items.count()); + for (int i=0; i("initialItemCount"); + QTest::addColumn("itemsToAdd"); + + QTest::newRow("0, add 1") << 0 << 1; + QTest::newRow("0, add 2") << 0 << 2; + QTest::newRow("0, add 10") << 0 << 10; + + QTest::newRow("1, add 1") << 1 << 1; + QTest::newRow("1, add 2") << 1 << 2; + QTest::newRow("1, add 10") << 1 << 10; + + QTest::newRow("5, add 1") << 5 << 1; + QTest::newRow("5, add 2") << 5 << 2; + QTest::newRow("5, add 10") << 5 << 10; +} + +void tst_QDeclarativeGridView::onRemove() +{ + QFETCH(int, initialItemCount); + QFETCH(int, indexToRemove); + QFETCH(int, removeCount); + + const int delegateWidth = 50; + const int delegateHeight = 100; + TestModel model; + for (int i=0; irootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateWidth", delegateWidth); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + QObject *object = canvas->rootObject(); + + qApp->processEvents(); + + model.removeItems(indexToRemove, removeCount); + qApp->processEvents(); + QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + + delete canvas; +} + +void tst_QDeclarativeGridView::onRemove_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("indexToRemove"); + QTest::addColumn("removeCount"); + + QTest::newRow("remove first") << 1 << 0 << 1; + QTest::newRow("two items, remove first") << 2 << 0 << 1; + QTest::newRow("two items, remove last") << 2 << 1 << 1; + QTest::newRow("two items, remove all") << 2 << 0 << 2; + + QTest::newRow("four items, remove first") << 4 << 0 << 1; + QTest::newRow("four items, remove 0-2") << 4 << 0 << 2; + QTest::newRow("four items, remove 1-3") << 4 << 1 << 2; + QTest::newRow("four items, remove 2-4") << 4 << 2 << 2; + QTest::newRow("four items, remove last") << 4 << 3 << 1; + QTest::newRow("four items, remove all") << 4 << 0 << 4; + + QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8; + QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5; + QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6; +} + void tst_QDeclarativeGridView::testQtQuick11Attributes() { QFETCH(QString, code); diff --git a/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml b/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml new file mode 100644 index 0000000..5ca1a45 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 + +ListView { + id: view + width: 240; height: 320 + + property variant addedDelegates: [] + property int removedDelegateCount + + model: testModel + + delegate: Rectangle { + width: 200; height: delegateHeight + border.width: 1 + ListView.onAdd: { + var obj = ListView.view.addedDelegates + obj.push(model.name) + ListView.view.addedDelegates = obj + } + ListView.onRemove: { + view.removedDelegateCount += 1 + } + } +} diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 86b68ca..cfb04f9 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -108,6 +108,10 @@ private slots: void QTBUG_16037(); void indexAt(); void incrementalModel(); + void onAdd(); + void onAdd_data(); + void onRemove(); + void onRemove_data(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); @@ -296,6 +300,13 @@ public: emit endInsertRows(); } + void addItems(const QList > &items) { + emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1); + for (int i=0; i(items[i].first, items[i].second)); + emit endInsertRows(); + } + void insertItem(int index, const QString &name, const QString &number) { emit beginInsertRows(QModelIndex(), index, index); list.insert(index, QPair(name, number)); @@ -1612,7 +1623,7 @@ void tst_QDeclarativeListView::QTBUG_9791() // Confirm items positioned correctly int itemCount = findItems(contentItem, "wrapper").count(); - QVERIFY(itemCount == 3); + QCOMPARE(itemCount, 3); for (int i = 0; i < itemCount; ++i) { QDeclarativeItem *item = findItem(contentItem, "wrapper", i); @@ -1753,9 +1764,9 @@ void tst_QDeclarativeListView::header() header = findItem(contentItem, "header2"); QVERIFY(header); - QCOMPARE(header->y(), 0.0); + QCOMPARE(header->y(), 10.0); QCOMPARE(header->height(), 10.0); - QCOMPARE(listview->contentY(), 0.0); + QCOMPARE(listview->contentY(), 10.0); delete canvas; } @@ -1829,7 +1840,7 @@ void tst_QDeclarativeListView::footer() footer = findItem(contentItem, "footer2"); QVERIFY(footer); - QCOMPARE(footer->y(), 0.0); + QCOMPARE(footer->y(), 600.0); QCOMPARE(footer->height(), 20.0); QCOMPARE(listview->contentY(), 0.0); @@ -2089,6 +2100,113 @@ void tst_QDeclarativeListView::incrementalModel() delete canvas; } +void tst_QDeclarativeListView::onAdd() +{ + QFETCH(int, initialItemCount); + QFETCH(int, itemsToAdd); + + const int delegateHeight = 10; + TestModel2 model; + + // these initial items should not trigger ListView.onAdd + for (int i=0; isetFixedSize(200, delegateHeight * (initialItemCount + itemsToAdd)); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + + QObject *object = canvas->rootObject(); + object->setProperty("width", canvas->width()); + object->setProperty("height", canvas->height()); + qApp->processEvents(); + + QList > items; + for (int i=0; iprocessEvents(); + + QVariantList result = object->property("addedDelegates").toList(); + QCOMPARE(result.count(), items.count()); + for (int i=0; i("initialItemCount"); + QTest::addColumn("itemsToAdd"); + + QTest::newRow("0, add 1") << 0 << 1; + QTest::newRow("0, add 2") << 0 << 2; + QTest::newRow("0, add 10") << 0 << 10; + + QTest::newRow("1, add 1") << 1 << 1; + QTest::newRow("1, add 2") << 1 << 2; + QTest::newRow("1, add 10") << 1 << 10; + + QTest::newRow("5, add 1") << 5 << 1; + QTest::newRow("5, add 2") << 5 << 2; + QTest::newRow("5, add 10") << 5 << 10; +} + +void tst_QDeclarativeListView::onRemove() +{ + QFETCH(int, initialItemCount); + QFETCH(int, indexToRemove); + QFETCH(int, removeCount); + + const int delegateHeight = 10; + TestModel2 model; + for (int i=0; irootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + QObject *object = canvas->rootObject(); + + qApp->processEvents(); + + model.removeItems(indexToRemove, removeCount); + qApp->processEvents(); + QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + + delete canvas; +} + +void tst_QDeclarativeListView::onRemove_data() +{ + QTest::addColumn("initialItemCount"); + QTest::addColumn("indexToRemove"); + QTest::addColumn("removeCount"); + + QTest::newRow("remove first") << 1 << 0 << 1; + QTest::newRow("two items, remove first") << 2 << 0 << 1; + QTest::newRow("two items, remove last") << 2 << 1 << 1; + QTest::newRow("two items, remove all") << 2 << 0 << 2; + + QTest::newRow("four items, remove first") << 4 << 0 << 1; + QTest::newRow("four items, remove 0-2") << 4 << 0 << 2; + QTest::newRow("four items, remove 1-3") << 4 << 1 << 2; + QTest::newRow("four items, remove 2-4") << 4 << 2 << 2; + QTest::newRow("four items, remove last") << 4 << 3 << 1; + QTest::newRow("four items, remove all") << 4 << 0 << 4; + + QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8; + QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5; + QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6; +} + void tst_QDeclarativeListView::testQtQuick11Attributes() { QFETCH(QString, code); -- cgit v0.12 From a78f6b1718b8285cb65ae989a070bf8703746b5d Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 9 Feb 2011 14:56:47 +1000 Subject: Add test for importing plugins that contain QML files --- .../data/pluginWithQmlFile.qml | 3 ++ .../nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml | 3 ++ .../com/nokia/AutoTestPluginWithQmlFile/qmldir | 3 ++ .../pluginWithQmlFile/plugin.cpp | 58 ++++++++++++++++++++++ .../pluginWithQmlFile/pluginWithQmlFile.pro | 9 ++++ .../qdeclarativemoduleplugin.pro | 2 +- .../tst_qdeclarativemoduleplugin.cpp | 14 ++++++ 7 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml new file mode 100644 index 0000000..a9e28e5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestPluginWithQmlFile 1.0 + +MyQmlFile {} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml new file mode 100644 index 0000000..18dcd26 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml @@ -0,0 +1,3 @@ +import QtQuick 1.0 + +Item {} \ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir new file mode 100644 index 0000000..858ba14 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir @@ -0,0 +1,3 @@ +MyQmlFile 1.0 MyQmlFile.qml +plugin pluginWithQmlFile + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp new file mode 100644 index 0000000..20e2d80 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestPluginWithQmlFile"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro new file mode 100644 index 0000000..aa9c95c --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestPluginWithQmlFile + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro index 221e465..4582554 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro @@ -1,6 +1,6 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin pluginWrongCase +SUBDIRS = plugin pluginWithQmlFile pluginWrongCase tst_qdeclarativemoduleplugin_pro.depends += plugin SUBDIRS += tst_qdeclarativemoduleplugin.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 96ec21b..b30f9cf 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -55,6 +55,7 @@ public: private slots: void importsPlugin(); void incorrectPluginCase(); + void importPluginWithQmlFile(); }; #ifdef Q_OS_SYMBIAN @@ -145,6 +146,19 @@ void tst_qdeclarativemoduleplugin::incorrectPluginCase() QCOMPARE(errors.at(0).description(), expectedError); } +void tst_qdeclarativemoduleplugin::importPluginWithQmlFile() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QDeclarativeComponent component(&engine, TEST_FILE("data/pluginWithQmlFile.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" -- cgit v0.12 From 3ebbb660d6f0c29b438f49dc8187b1b353ee1b8a Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 9 Feb 2011 15:03:53 +1000 Subject: Fix docs for variant and list basic types Make it clear that QML properties never store JavaScript object data, and that inefficient serialization must be performed when JavaScript objects are copied to QML properties. Task-number: QTBUG-16624 --- doc/src/declarative/basictypes.qdoc | 183 +++++++++++++++++------------------- 1 file changed, 84 insertions(+), 99 deletions(-) diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 463e4a3..eac509e 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -400,14 +400,11 @@ \c child1, \c child2 and \c child3 will be added to the children list in the order in which they appear. - List \l {Adding Properties}{properties} can be created as a - \c variant type, or as a \c list type, where \c Type is the - type of the object in the list: + List \l {Adding Properties}{properties} can be declared as \c list + type, where \c Type is the type of the object in the list: \qml Item { - property variant values: [ 10, 20, 'abc', 'xyz' ] - property list rects: [ Rectangle { width: 100; height: 100}, Rectangle { width: 200; height: 200} @@ -415,136 +412,124 @@ } \endqml - A \c variant list can contain values of any of the \l {QML Basic Types}{basic QML types} - such as numbers, strings, etc. while a \c list list can only contain values - that match (or are derived from) the specified \c Type. + A list property can only contain values that match (or are derived from) the + specified \c Type. - A list property can be cleared by setting it to an empty list: + While the \c rects property can be reassigned to a different list value (including + an empty list), its individual values cannot be modified. See the \l variant type + documentation for details. - \qml - Item { - children: [] - } - \endqml + \sa {QML Basic Types} +*/ + +/*! + \qmlbasictype variant + \ingroup qmlbasictypes - A list property cannot be modified in any other way. Items cannot be dynamically added to - or removed from the list through JavaScript operations; any \c push() operations on the - list only modify a \e copy of the list and not the actual list. (These current limitations - are due to restrictions on \l {Property Binding} where lists are involved.) + \brief A variant type is a generic property type. - You can, however, modify a copy of the list and then reassign the property to the modified - value. Other options are to create an array object from within a \c .js JavaScript file, - or implement a custom list element in C++. Here is a QML element that modifies the list in a - JavaScript file: + A variant is a generic property type. A variant type property can hold + any of the \l {QML Basic Types}{basic type} values: - \table - \row - \o \qml - // QML - import "script.js" as Script - Item { - Component.onCompleted: { - Script.addItem('abc') - console.log("Added:", Script.getList()[0]) - } + property variant aNumber: 100 + property variant aString: "Hello world!" + property variant aBool: false } \endqml - \o - \code - // script.js - var myArray = new Array() + The \c variant type can also hold: - function getList() { - return myArray - } - - function addItem(item) { - myArray.push(item) - } - \endcode - \endtable - - However, note that a JavaScript list should not be used as a QML \c property value, - as the property is not updated when the list changes. + \list + \o An array of \l {QML Basic Types}{basic type} values + \o A map of key-value pairs with \l {QML Basic Types}{basic-type} values + \endlist - \sa {QML Basic Types} -*/ + For example, below is an \c items array and an \c attributes map. Their + contents can be examined using JavaScript \c for loops. Individual array + values are accessible by index, and individual map values are accessible + by key: + \qml + Item { + property variant items: [1, 2, 3, "four", "five"] + property variant attributes: { 'color': 'red', 'width': 100 } -/*! - \qmlbasictype variant - \ingroup qmlbasictypes + Component.onCompleted: { + for (var i=0; i Date: Wed, 9 Feb 2011 14:57:09 +1000 Subject: PathView regression: dragging the path didn't update currentIndex Some refectoring while fixing QTBUG-13687 resulted in the private setOffset() method being called rather than the public. The public version was responsible for updating currentIndex. Change-Id: Iac9c7a19d6fa64550b9498e77b8983512e199370 Task-number: QTBUG-17319 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativepathview.cpp | 2 +- .../qdeclarativepathview/data/dragpath.qml | 19 +++++++++++++ .../tst_qdeclarativepathview.cpp | 33 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativepathview/data/dragpath.qml diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 64656af..050a9ca 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1152,7 +1152,7 @@ void QDeclarativePathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent moveReason = QDeclarativePathViewPrivate::Mouse; qreal diff = (newPc - startPc)*modelCount*mappedRange; if (diff) { - setOffset(offset + diff); + q->setOffset(offset + diff); if (diff > modelCount/2) diff -= modelCount; diff --git a/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml new file mode 100644 index 0000000..a361bdc --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +PathView { + width: 400 + height: 200 + model: 100 + pathItemCount: 20 + path: Path { + startX: 0; startY: 100 + PathLine { x: 400; y: 100 } + } + delegate: Rectangle { height: 100; width: 1; color: PathView.isCurrentItem?"red" : "black" } + dragMargin: 100 + preferredHighlightBegin: 0.5 + preferredHighlightEnd: 0.5 + Text { + text: "current index: " + parent.currentIndex + } +} diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 23ae907..f39e4b9 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -89,6 +89,7 @@ private slots: void pathUpdate(); void visualDataModel(); void undefinedPath(); + void mouseDrag(); private: QDeclarativeView *createView(); @@ -867,6 +868,38 @@ void tst_QDeclarativePathView::undefinedPath() delete obj; } +void tst_QDeclarativePathView::mouseDrag() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml")); + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QDeclarativePathView *pathview = qobject_cast(canvas->rootObject()); + QVERIFY(pathview != 0); + + int current = pathview->currentIndex(); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(10,100))); + + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(30,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + + QVERIFY(pathview->currentIndex() != current); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(40,100))); + + delete canvas; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); -- cgit v0.12 From 1759f7d688903210a142d7f93a6d173c52995d2f Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 9 Feb 2011 16:34:57 +1000 Subject: Fix auto test failure. Allow the input context to be reset twice. The context is reset because of two events, the first is because an item lost focus and that reset needs to occur before the focus moves away from the item or events won't be delivered to it. The second redundant reset is because the Qt::WA_InputMethodEnabled flag was cleared on the view widget because no item has focus and it has no way to know the context doesn't need to be reset. Change-Id: Ie3b3fc6898d144ed3f8b3822e49ea0eee7e029f4 Reviewed-by: Martin Jones --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index dcd679f..3c4984e 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -4141,11 +4141,14 @@ void tst_QGraphicsView::inputContextReset() inputContext.resets = 0; scene.setFocusItem(0); - QCOMPARE(inputContext.resets, 1); + // the input context is reset twice, once because an item has lost focus and again because + // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus. + QCOMPARE(inputContext.resets, 2); // introduce another item that is focusable but does not accept input methods QGraphicsItem *item2 = new QGraphicsRectItem; - item1->setFlags(QGraphicsItem::ItemIsFocusable); + item2->setFlags(QGraphicsItem::ItemIsFocusable); + scene.addItem(item2); inputContext.resets = 0; scene.setFocusItem(item2); @@ -4154,6 +4157,11 @@ void tst_QGraphicsView::inputContextReset() inputContext.resets = 0; scene.setFocusItem(item1); QCOMPARE(inputContext.resets, 0); + + // test changing between between items that accept input methods. + item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); + scene.setFocusItem(item2); + QCOMPARE(inputContext.resets, 1); } void tst_QGraphicsView::indirectPainting() -- cgit v0.12 From ca663a7252637f8066a0e7368650e72094220b69 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 9 Feb 2011 09:45:09 +0000 Subject: Recreate Symbian raster backing store when WA_TranslucentBackground set Task-number: QTBUG-17288 Reviewed-by: Jani Hautakangas --- src/gui/image/qpixmap_s60.cpp | 26 ++++++++++++++++++++++++++ src/gui/image/qpixmap_s60_p.h | 3 +++ src/gui/painting/qwindowsurface_s60.cpp | 17 +++++++++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index dbe8177..a7aeb84 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -1012,6 +1012,32 @@ void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) } } +void QS60PixmapData::convertToDisplayMode(TDisplayMode mode) +{ + if (!cfbsBitmap || cfbsBitmap->DisplayMode() == mode) + return; + if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode)) { + qWarning("Cannot convert display mode due to depth mismatch"); + return; + } + + const TSize size = cfbsBitmap->SizeInPixels(); + QScopedPointer newBitmap(createSymbianCFbsBitmap(size, mode)); + + const uchar *sptr = const_cast(image).bits(); + symbianBitmapDataAccess->beginDataAccess(newBitmap.data()); + uchar *dptr = (uchar*)newBitmap->DataAddress(); + Mem::Copy(dptr, sptr, image.byteCount()); + symbianBitmapDataAccess->endDataAccess(newBitmap.data()); + + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + delete cfbsBitmap; + lock.relock(); + cfbsBitmap = newBitmap.take(); + setSerialNumber(cfbsBitmap->Handle()); + UPDATE_BUFFER(); +} + QPixmapData *QS60PixmapData::createCompatiblePixmapData() const { return new QS60PixmapData(pixelType()); diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index e4060dc..c1d7941 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -54,6 +54,7 @@ // #include +#include QT_BEGIN_NAMESPACE @@ -107,6 +108,8 @@ public: void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); + void convertToDisplayMode(TDisplayMode mode); + private: void release(); void fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat=false); diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index 7dc5cb7..9f371a8 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -61,13 +61,11 @@ struct QS60WindowSurfacePrivate QList bufferImages; }; -QS60WindowSurface::QS60WindowSurface(QWidget* widget) - : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +TDisplayMode displayMode(bool opaque) { TDisplayMode mode = S60->screenDevice()->DisplayMode(); - bool isOpaque = qt_widget_private(widget)->isOpaque; - if (isOpaque) { + if (opaque) { mode = EColor16MU; } else { if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) @@ -75,7 +73,13 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) else mode = EColor16MA; // Symbian prior to Symbian^3 sw accelerates EColor16MA } + return mode; +} +QS60WindowSurface::QS60WindowSurface(QWidget* widget) + : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +{ + TDisplayMode mode = displayMode(qt_widget_private(widget)->isOpaque); // We create empty CFbsBitmap here -> it will be resized in setGeometry CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); @@ -121,6 +125,11 @@ void QS60WindowSurface::beginPaint(const QRegion &rgn) if (!qt_widget_private(window())->isOpaque) { QS60PixmapData *pixmapData = static_cast(d_ptr->device.data_ptr().data()); + + TDisplayMode mode = displayMode(false); + if (pixmapData->cfbsBitmap->DisplayMode() != mode) + pixmapData->convertToDisplayMode(mode); + pixmapData->beginDataAccess(); QPainter p(&pixmapData->image); -- cgit v0.12 From 36f8782a5994d5ea2cd71695daf0f33b5e37e609 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 9 Feb 2011 09:50:30 +0000 Subject: Changes for 4.7.2 Reviewed-by: Jani Hautakangas --- dist/changes-4.7.2 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index 0d93052..b981fd2 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -47,10 +47,10 @@ QtGui - QWidget * [QTMOBILITY-645] Send WinIdChange event when winId is set to zero. - The window handle of a native widget may be set to zero in two - situations: (i) temporarily, during reparenting and (ii) during - widget destruction. Previously, no WinIdChange event was sent in - either of these cases; now, it is sent in both cases. + The window handle of a native widget may be set to zero in two + situations: (i) temporarily, during reparenting and (ii) during + widget destruction. Previously, no WinIdChange event was sent in + either of these cases; now, it is sent in both cases. QtDBus ------ @@ -137,6 +137,12 @@ Qt for Symbian * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing network proxies configured on the device to be used by applications. + - QWidget + * [QT-4416, QTBUG-17288] On devices which lack support for transparency + in EGL surfaces, setting Qt::WA_TranslucentBackground on a widget + whose windowType() is Qt::Window causes that widget to be rendered + using the raster graphics system. + Qt for Embedded Linux --------------------- -- cgit v0.12 From a1f695f7b3b671c26925d41fba7dff1d3cb49da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 9 Feb 2011 13:31:04 +0100 Subject: Fixed tst_qpixmap::toImageDeepCopy autotest for GL graphicssystem. We need to copy the image if painting is active. Reviewed-by: Jani Hautakangas --- src/opengl/qpixmapdata_gl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 9980f2d..43e80c1 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -586,6 +586,12 @@ QImage QGLPixmapData::toImage() const if (m_renderFbo) { copyBackFromRenderFbo(true); } else if (!m_source.isNull()) { + QImageData *data = const_cast(m_source).data_ptr(); + if (data->paintEngine && data->paintEngine->isActive() + && data->paintEngine->paintDevice() == &m_source) + { + return m_source.copy(); + } return m_source; } else if (m_dirty || m_hasFillColor) { return fillImage(m_fillColor); -- cgit v0.12 From 67405c1b4d8ae5b47191ff1c28606453bf52295c Mon Sep 17 00:00:00 2001 From: Niklas Kurkisuo Date: Wed, 9 Feb 2011 13:56:00 +0100 Subject: Stop focus propagation of touch events when flag is set. Added check to stop propagation of touch events for items that have the QGraphicsItem::ItemStopsClickFocusPropagation flag set. Merge-request: 1085 Reviewed-by: Harald Fernengel --- src/gui/graphicsview/qgraphicsscene.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5e5077b..069f4dd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5941,6 +5941,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item->isPanel()) break; + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; } // If nobody could take focus, clear it. @@ -5973,6 +5975,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; + if (item && (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)) + break; } touchEvent->setAccepted(eventAccepted); -- cgit v0.12 From b52bf57e46520fb65d3d4c43bdb9c3d972690cb8 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 9 Feb 2011 14:12:42 +0200 Subject: Fix regression in creating mkspecs/default Copy all files from original mkspec to default one and modify *.conf, *.prf, and *.h to include their original counterparts. Task-number: QTBUG-17258 Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 30 ++++---------------- tools/configure/environment.cpp | 61 +++++++++++++++++++++++++++++++++++++--- tools/configure/environment.h | 4 ++- 3 files changed, 66 insertions(+), 29 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 8fa03ab..1b77058 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3244,8 +3244,7 @@ void Configure::generateConfigfiles() } // Copy configured mkspec to default directory, but remove the old one first, if there is any - QString mkspecsPath = buildPath + "/mkspecs"; - QString defSpec = mkspecsPath + "/default"; + QString defSpec = buildPath + "/mkspecs/default"; QFileInfo defSpecInfo(defSpec); if (defSpecInfo.exists()) { if (!Environment::rmdir(defSpec)) { @@ -3255,30 +3254,13 @@ void Configure::generateConfigfiles() } } - QDir mkspecsDir(mkspecsPath); - if (!mkspecsDir.mkdir("default")) { - cout << "Couldn't create default mkspec dir!" << endl; - dictionary["DONE"] = "error"; - return; - } - QString spec = dictionary.contains("XQMAKESPEC") ? dictionary["XQMAKESPEC"] : dictionary["QMAKESPEC"]; QString pltSpec = sourcePath + "/mkspecs/" + spec; - outName = defSpec + "/qmake.conf"; - QFile qmakeConfFile(outName); - if (qmakeConfFile.open(QFile::WriteOnly | QFile::Text)) { - QTextStream qmakeConfStream; - qmakeConfStream.setDevice(&qmakeConfFile); - // While QMAKESPEC_ORIGINAL being relative or absolute doesn't matter for the - // primary use of this variable by qmake to identify the original mkspec, the - // variable is also used for few special cases where the absolute path is required. - // Conversely, the include of the original qmake.conf must be done using relative path, - // as some Qt binary deployments are done in a manner that doesn't allow for patching - // the paths at the installation time. - qmakeConfStream << "QMAKESPEC_ORIGINAL=" << pltSpec << endl << endl; - qmakeConfStream << "include(" << "../" << spec << "/qmake.conf)" << endl << endl; - qmakeConfStream.flush(); - qmakeConfFile.close(); + QString includeSpec = buildPath + "/mkspecs/" + spec; + if (!Environment::cpdir(pltSpec, defSpec, includeSpec)) { + cout << "Couldn't update default mkspec! Does " << qPrintable(pltSpec) << " exist?" << endl; + dictionary["DONE"] = "error"; + return; } // Generate the new qconfig.cpp file diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 05fd567..9d1c23a 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -407,10 +407,25 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv return exitCode; } -bool Environment::cpdir(const QString &srcDir, const QString &destDir) +/*! + Copies the \a srcDir contents into \a destDir. + + If \a includeSrcDir is not empty, any files with 'h', 'prf', or 'conf' suffixes + will not be copied over from \a srcDir. Instead a new file will be created + in \a destDir with the same name and that file will include a file with the + same name from the \a includeSrcDir using relative path and appropriate + syntax for the file type. + + Returns true if copying was successful. +*/ +bool Environment::cpdir(const QString &srcDir, + const QString &destDir, + const QString &includeSrcDir) { QString cleanSrcName = QDir::cleanPath(srcDir); QString cleanDstName = QDir::cleanPath(destDir); + QString cleanIncludeName = QDir::cleanPath(includeSrcDir); + #ifdef CONFIGURE_DEBUG_CP_DIR qDebug() << "Attempt to cpdir " << cleanSrcName << "->" << cleanDstName; #endif @@ -421,21 +436,59 @@ bool Environment::cpdir(const QString &srcDir, const QString &destDir) bool result = true; QDir dir = QDir(cleanSrcName); + QDir destinationDir = QDir(cleanDstName); QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); for (int i = 0; result && (i < allEntries.count()); ++i) { QFileInfo entry = allEntries.at(i); bool intermediate = true; if (entry.isDir()) { + QString newIncSrcDir; + if (!includeSrcDir.isEmpty()) + newIncSrcDir = QString("%1/%2").arg(cleanIncludeName).arg(entry.fileName()); + intermediate = cpdir(QString("%1/%2").arg(cleanSrcName).arg(entry.fileName()), - QString("%1/%2").arg(cleanDstName).arg(entry.fileName())); + QString("%1/%2").arg(cleanDstName).arg(entry.fileName()), + newIncSrcDir); } else { QString destFile = QString("%1/%2").arg(cleanDstName).arg(entry.fileName()); #ifdef CONFIGURE_DEBUG_CP_DIR qDebug() << "About to cp (file)" << entry.absoluteFilePath() << "->" << destFile; #endif QFile::remove(destFile); - intermediate = QFile::copy(entry.absoluteFilePath(), destFile); - SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL); + QString suffix = entry.suffix(); + if (!includeSrcDir.isEmpty() && (suffix == "prf" || suffix == "conf" || suffix == "h")) { + QString relativeIncludeFilePath = QString("%1/%2").arg(cleanIncludeName).arg(entry.fileName()); + relativeIncludeFilePath = destinationDir.relativeFilePath(relativeIncludeFilePath); +#ifdef CONFIGURE_DEBUG_CP_DIR + qDebug() << "...instead generate relative include to" << relativeIncludeFilePath; +#endif + QFile currentFile(destFile); + if (currentFile.open(QFile::WriteOnly | QFile::Text)) { + QTextStream fileStream; + fileStream.setDevice(¤tFile); + + if (suffix == "prf" || suffix == "conf") { + if (entry.fileName() == "qmake.conf") { + // While QMAKESPEC_ORIGINAL being relative or absolute doesn't matter for the + // primary use of this variable by qmake to identify the original mkspec, the + // variable is also used for few special cases where the absolute path is required. + // Conversely, the include of the original qmake.conf must be done using relative path, + // as some Qt binary deployments are done in a manner that doesn't allow for patching + // the paths at the installation time. + fileStream << "QMAKESPEC_ORIGINAL=" << cleanSrcName << endl << endl; + } + fileStream << "include(" << relativeIncludeFilePath << ")" << endl << endl; + } else if (suffix == "h") { + fileStream << "#include \"" << relativeIncludeFilePath << "\"" << endl << endl; + } + + fileStream.flush(); + currentFile.close(); + } + } else { + intermediate = QFile::copy(entry.absoluteFilePath(), destFile); + SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL); + } } if(!intermediate) { qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir(); diff --git a/tools/configure/environment.h b/tools/configure/environment.h index e3e8629..61e97eb 100644 --- a/tools/configure/environment.h +++ b/tools/configure/environment.h @@ -69,7 +69,9 @@ public: static bool detectExecutable(const QString &executable); static int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv); - static bool cpdir(const QString &srcDir, const QString &destDir); + static bool cpdir(const QString &srcDir, + const QString &destDir, + const QString &includeSrcDir = QString()); static bool rmdir(const QString &name); static QString symbianEpocRoot(); -- cgit v0.12 From bf47aa67e286f31db5a8b84060f278f7fea217b2 Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Wed, 9 Feb 2011 15:00:26 +0000 Subject: Fix build failure Task-number: QTBUG-17288 Reviewed-by: trustme --- src/gui/image/qpixmap_s60.cpp | 9 +++++---- src/gui/image/qpixmap_s60_p.h | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index a7aeb84..ca5f133 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -1012,17 +1012,18 @@ void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) } } -void QS60PixmapData::convertToDisplayMode(TDisplayMode mode) +void QS60PixmapData::convertToDisplayMode(int mode) { - if (!cfbsBitmap || cfbsBitmap->DisplayMode() == mode) + const TDisplayMode displayMode = static_cast(mode); + if (!cfbsBitmap || cfbsBitmap->DisplayMode() == displayMode) return; - if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode)) { + if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)) { qWarning("Cannot convert display mode due to depth mismatch"); return; } const TSize size = cfbsBitmap->SizeInPixels(); - QScopedPointer newBitmap(createSymbianCFbsBitmap(size, mode)); + QScopedPointer newBitmap(createSymbianCFbsBitmap(size, displayMode)); const uchar *sptr = const_cast(image).bits(); symbianBitmapDataAccess->beginDataAccess(newBitmap.data()); diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index c1d7941..c440bbc 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -54,7 +54,6 @@ // #include -#include QT_BEGIN_NAMESPACE @@ -108,7 +107,7 @@ public: void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); - void convertToDisplayMode(TDisplayMode mode); + void convertToDisplayMode(int mode); private: void release(); -- cgit v0.12 From 34aca9f03e25e94b4ca730ddd3c88aa95653a0b5 Mon Sep 17 00:00:00 2001 From: Iain Date: Wed, 9 Feb 2011 17:34:27 +0000 Subject: Change paging attributes for Symbian binaries Removed UNPAGED workaround from QtCore and QtSql on OS releases where data paging is supported. Depends on new macro being defined in the OS builds (SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED) to allow us to detect this. Data exports are supported in all S^3 builds after early 2009, however, this macro is only added recently (and thus isn't defined in, eg. Symbian Foundation PDKs (v3.0.4), or current releases (v0.9) of the S^3 SDK from Nokia). Thus building Qt against these older S^3 builds will still result in QtCore and QtSql being unpaged. Also, remove PAGED keyword from all Qt-based software. This changes the code paging field in the Symbian (E32Image) header from "paged" to "default". Thus it is left to the configuration of the particular device whether paging is used for the binary or not. All devices that support code paging should have it turned on (the value is stored in the HAL, so can be checked using eg. fshell); data paging may or may not be turned on depending on the device characteristics. Leaving both code and data paging as "default" means that any limitations in the device (eg. around flash wear) can be controlled by that device by disabling the appropriate types of paging. This change also leaves the way open to deprecated PAGED as a keyword in the Symbian build systems, so you can only opt out of paging. This makes more sense, as the default for code paging will be on, the default for data paging will be on if the device can handle it, and binaries should only be opting out of paging if they have some specific real-time requirements that paging inhibits. Task-number: QT-3503 Task-number: QTBUG-13931 Reviewed-by: Shane Kearns --- mkspecs/common/symbian/symbian-mmp.conf | 5 +++-- src/corelib/corelib.pro | 9 ++++++--- src/sql/sql.pro | 9 ++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mkspecs/common/symbian/symbian-mmp.conf b/mkspecs/common/symbian/symbian-mmp.conf index 4d554bd..8ed326a 100644 --- a/mkspecs/common/symbian/symbian-mmp.conf +++ b/mkspecs/common/symbian/symbian-mmp.conf @@ -13,7 +13,7 @@ symbian-abld { } else { MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA = "OPTION_REPLACE ARMCC --export_all_vtbl // don't use --export_all_vtbl" } -MMP_RULES += PAGED BYTEPAIRCOMPRESSTARGET +MMP_RULES += BYTEPAIRCOMPRESSTARGET MMP_RULES += $$MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA SYMBIAN_PLATFORMS = WINSCW GCCE ARMV5 ARMV6 @@ -28,7 +28,8 @@ INCLUDEPATH = \ # RVCT seems to do this automatically, but WINSCW compiler does not, so add it here. MMP_RULES += "USERINCLUDE ." -contains(S60_VERSION, 3.1):MMP_RULES -= PAGED BYTEPAIRCOMPRESSTARGET +# S60 3.1 devices don't support paging for non-ROM components, so no point in using the less efficient compression mechanism +contains(S60_VERSION, 3.1):MMP_RULES -= BYTEPAIRCOMPRESSTARGET QMAKE_CXXFLAGS_FAST_VFP.ARMCC = --fpmode fast # [TODO] QMAKE_CXXFLAGS_FAST_VFP.GCCE = diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index a001940..06aa191 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -33,7 +33,10 @@ contains(DEFINES,QT_EVAL):include(eval.pri) symbian: { TARGET.UID3=0x2001B2DC - # Workaroud for problems with paging this dll - MMP_RULES -= PAGED - MMP_RULES *= UNPAGED + # Problems using data exports from this DLL mean that we can't page it on releases that don't support + # data exports (currently that's any release before Symbian^3) + pagingBlock = "$${LITERAL_HASH}ifndef SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED" \ + "UNPAGED" \ + "$${LITERAL_HASH}endif" + MMP_RULES += pagingBlock } diff --git a/src/sql/sql.pro b/src/sql/sql.pro index b8f819d..a02b0f4 100644 --- a/src/sql/sql.pro +++ b/src/sql/sql.pro @@ -20,7 +20,10 @@ include(models/models.pri) symbian: { TARGET.UID3=0x2001E61D - # Workaroud for problems with paging this dll - MMP_RULES -= PAGED - MMP_RULES *= UNPAGED + # Problems using data exports from this DLL mean that we can't page it on releases that don't support + # data exports (currently that's any release before Symbian^3) + pagingBlock = "$${LITERAL_HASH}ifndef SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED" \ + "UNPAGED" \ + "$${LITERAL_HASH}endif" + MMP_RULES += pagingBlock } -- cgit v0.12 From 97305f4ca91b380f42ff5d3fd49c268df0c5ff8c Mon Sep 17 00:00:00 2001 From: Iain Date: Wed, 9 Feb 2011 18:16:29 +0000 Subject: 4.7.2 changes Reviewed-by: TrustMe --- dist/changes-4.7.2 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index b981fd2..7207d88 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -129,6 +129,22 @@ Qt for Mac OS X Qt for Symbian -------------- + - Paging changes + * [QT-3503] Remove PAGED keyword from all Qt-based binaries for + MMP-based build systems (abld, SBSv2 (a.k.a. Raptor)). + This changes the code paging field in the Symbian (E32Image) header + from "paged" to "default". Thus it is left to the configuration + of the particular device whether paging is used for the binary or + not. All devices that support code paging should have it turned + on (the value is stored in the HAL, so can be checked using eg. + fshell); data paging may or may not be turned on depending on the + device characteristics. Leaving both code and data paging as + "default" means that any limitations in the device (eg. around + flash wear) can be controlled by that device by disabling the + appropriate types of paging rather than being forced by the binary + (which may be deployed to several different devices with different + characteristics). + - Phonon MMF backend * [QTBUG-11436] Added a MediaObject property which allows the client to specify which Internet Access Point should be used for streaming. -- cgit v0.12 From 8b653d4fa183f985d5c1bfb4b5c1d932305cacfa Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 10 Feb 2011 10:04:02 +1000 Subject: CLeanup registers after AddString Reviewed-by: Martin Jones Change-Id: I7bd2806770fe5b86fbc589644107d74981d32abe --- .../qml/qdeclarativecompiledbindings.cpp | 41 ++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 3721fb0..a6fcce4 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ // #define COMPILEDBINDINGS_DEBUG +// #define REGISTER_CLEANUP_DEBUG #include "private/qdeclarativecompiledbindings_p.h" @@ -171,6 +172,24 @@ struct Register { int type; // Optional type void *data[2]; // Object stored here + +#ifdef REGISTER_CLEANUP_DEBUG + Register() { + type = 0; + } + + ~Register() { + int allowedTypes[] = { QMetaType::QObjectStar, QMetaType::QReal, QMetaType::Int, QMetaType::Bool, 0 }; + bool found = (type == 0); + int *ctype = allowedTypes; + while (!found && *ctype) { + found = (*ctype == type); + ++ctype; + } + if (!found) + qWarning("Register leaked of type %d", type); + } +#endif }; } @@ -1412,10 +1431,16 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, QML_BEGIN_INSTR(CleanupString) registers[instr->cleanup.reg].getstringptr()->~QString(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif QML_END_INSTR(CleanupString) QML_BEGIN_INSTR(CleanupUrl) registers[instr->cleanup.reg].geturlptr()->~QUrl(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif QML_END_INSTR(CleanupUrl) QML_BEGIN_INSTR(Fetch) @@ -1533,10 +1558,19 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, int type = registers[instr->cleanup.reg].gettype(); if (type == qMetaTypeId()) { registers[instr->cleanup.reg].getvariantptr()->~QVariant(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } else if (type == QMetaType::QString) { registers[instr->cleanup.reg].getstringptr()->~QString(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } else if (type == QMetaType::QUrl) { registers[instr->cleanup.reg].geturlptr()->~QUrl(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } } QML_END_INSTR(CleanupGeneric) @@ -1749,7 +1783,6 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node done.common.type = Instr::Done; bytecode << done; - return true; } else { // Can we store the final value? if (type.type == QVariant::Int && @@ -1791,12 +1824,12 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node Instr done; done.common.type = Instr::Done; bytecode << done; - - return true; } else { return false; } } + + return true; } bool QDeclarativeBindingCompilerPrivate::parseExpression(QDeclarativeJS::AST::Node *node, Result &type) @@ -2236,6 +2269,8 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result if (lhsTmp != -1) releaseReg(lhsTmp); if (rhsTmp != -1) releaseReg(rhsTmp); + releaseReg(lhs.reg); + releaseReg(rhs.reg); return true; } -- cgit v0.12 From d7e42d7c5b0eb6513526d0c21025939a467e8d68 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 10 Feb 2011 11:30:47 +1000 Subject: Update modules-related tests and docs Added tests for remote imports and fixed/improved examples and text in the docs. Change-Id: I8f411a0287c4d50ec3cebe5567d803689cd5b1c7 --- doc/src/declarative/modules.qdoc | 187 +++++++++++++-------- src/declarative/qml/qdeclarativeengine.cpp | 3 +- src/declarative/qml/qdeclarativeimport.cpp | 23 ++- .../imports/com/nokia/PureQmlModule/ComponentA.qml | 3 + .../imports/com/nokia/PureQmlModule/ComponentB.qml | 4 + .../imports/com/nokia/PureQmlModule/qmldir | 3 + .../tst_qdeclarativemoduleplugin.cpp | 53 ++++++ .../tst_qdeclarativemoduleplugin.pro | 7 +- 8 files changed, 210 insertions(+), 73 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc index 4b2b33a..1b73025 100644 --- a/doc/src/declarative/modules.qdoc +++ b/doc/src/declarative/modules.qdoc @@ -44,7 +44,7 @@ example, an \c import statement is required to use: \list \o A component defined in another QML file that is not in the same directory \o A component defined in a QML file located on a remote server -\o A \l{QDeclarativeExtensionPlugin}{QML C++ plugin} library (unless the plugin is installed in the same directory) +\o A \l{QDeclarativeExtensionPlugin}{QML extension plugin} library (unless the plugin is installed in the same directory) \o A JavaScript file (note this must be imported using \l {#namespaces}{named imports}) \endlist @@ -61,12 +61,12 @@ are not included in the global namespace by default.) The \c Qt module is an \e installed module; it is found in the \l{The QML import path}{import path}. There are two types of QML modules: -location modules (defined by a URL) and installed modules (defined by a URI). +located modules (defined by a URL) and installed modules (defined by a URI). -\section1 Location Modules +\section1 Located Modules -Location modules can reside on the local filesystem or a network resource, +Located modules can reside on the local filesystem or a network resource, and are referred to by a quoted location URL that specifies the filesystem or network URL. They allow any directory with QML content to be imported as a module, whether the directory is on the local filesystem or a remote @@ -86,8 +86,9 @@ directory using a relative or absolute path, like this: \code MyQMLProject |- MyComponents - |- Slider.qml |- CheckBox.qml + |- Slider.qml + |- Window.qml |- Main |- application.qml \endcode @@ -96,8 +97,10 @@ MyQMLProject \code import "../MyComponents" -Slider { ... } -CheckBox { ... } +Window { + Slider { ... } + CheckBox { ... } +} \endcode \endtable @@ -106,23 +109,51 @@ Similarly, if the directory resided on a network source, it could be imported like this: \code - import "https://qml.nokia.com/qml/qmlcomponents" - import "https://qml.nokia.com/qml/qmlcomponents" 1.0 + import "http://www.my-server.com/MyQMLProject/MyComponents" + import "http://www.my-server.com/MyQMLProject/MyComponents" 1.0 \endcode -Remote location modules must have a \l{Writing a qmldir file}{qmldir file} in the -same directory to specify which QML files should be made available. See the -\l {#qmldirexample}{example} below. The qmldir file is optional for modules on -the local filesystem. +A located module can also be imported as a network resource if it has a +\l{Writing a qmldir file}{qmldir file} in the directory that specifies the QML files +to be made available by the module. For example, if the \c MyComponents directory +contained a \c qmldir file defined like this: +\code +Slider 1.0 Slider.qml +CheckBox 1.0 CheckBox.qml +Window 1.0 Window.qml +\endcode + +If the \c MyComponents directory was then hosted as a network resource, it could +be imported as a module, like this: + +\code +import "http://the-server-name.com/MyQMLProject/MyComponents" + +Window { + Slider { ... } + CheckBox { ... } +} +\endcode + +with an optional "1.0" version specification. Notice the import would fail if +a later version was used, as the \c qmldir file specifies that these elements +are only available in the 1.0 version. + +Note that modules imported as a network resource allow only access to components +defined in QML files; components defined by C++ \l{QDeclarativeExtensionPlugin}{QML extension plugins} +are not available. \section1 Installed modules +Installed modules are modules that are made available through the QML import path, +as defined by QDeclarativeEngine::importPathList(), or modules defined within +C++ application code. An installed module is referred to by a URI, which allows +the module to be imported from QML code without specifying a complete filesystem +path or network resource URL. -Installed modules are modules that are installed on the -local filesystem within the QML import path, or modules defined in C++ -application code. When importing an installed module, an un-quoted URI is +When importing an installed module, an un-quoted URI is used, with a mandatory version number: \code @@ -130,9 +161,10 @@ used, with a mandatory version number: import com.nokia.qml.mymodule 1.0 \endcode -Installed modules that are installed into the import path or created -as a \l{QDeclarativeExtensionPlugin}{QML C++ plugin} must define a -\l{Writing a qmldir file}{qmldir file}. +When a module is imported, the QML engine searches the QML import path for a matching +module. The root directory of the module must contain a +\l{Writing a qmldir file}{qmldir file} that defines the QML files +and/or C++ QML extension plugins that are made available to the module. Modules that are installed into the import path translate the URI into directory names. For example, the qmldir file of the module \c com.nokia.qml.mymodule @@ -143,11 +175,9 @@ module could be located under \c com/nokia/qml/mymodule.2/qmldir or \c com/nokia/qml/mymodule.2.1/qmldir. The engine will automatically load the module which matches best. - -\section2 The QML import path - -The QML engine will search the import path for a requested installed module. -The default import path includes: +The import path, as returned by QDeclarativeEngine::importPathList(), defines the default +locations to be searched by the QML engine for a matching module. By default, this list +contains: \list \o The directory of the current file @@ -155,30 +185,80 @@ The default import path includes: \o Paths specified by the \c QML_IMPORT_PATH environment variable \endlist -The import path can be queried using QDeclarativeEngine::importPathList() and modified using QDeclarativeEngine::addImportPath(). +Additional import paths can be added through QDeclarativeEngine::addImportPath() or the +\c QML_IMPORT_PATH environment variable. When running the \l {QML Viewer}, you +can also use the \c -I option to add an import path. + + +\section2 Creating installed modules + +As an example, suppose the \c MyQMLProject directory in the \l{Located Modules}{previous example} +was located on the local filesystem at \c C:\qml\projects\MyQMLProject. The \c MyComponents +subdirectory could be made available as an installed module by adding a +\l{Writing a qmldir file}{qmldir file} to the \c MyComponents directory that looked like this: + +\code +Slider 1.0 Slider.qml +CheckBox 1.0 CheckBox.qml +Window 1.0 Window.qml +\endcode + +Providing the path \c C:\qml is added to the QML import path using any of the methods listed previously, +a QML file located anywhere on the local filesystem can then import the module as shown below, +without referring to the module's absolute filesystem location: + +\qml +import projects.MyQMLProject.MyComponents 1.0 + +Window { + Slider { ... } + CheckBox { ... } +} +\endqml + +Installed modules are also accessible as a network resource. If the \c C:\qml directory was hosted +as \c http://www.some-server.com/qml and this URL was added to the QML import path, the above +QML code would work just the same. -When running the \l {QML Viewer}, use the \c -I option to add paths to the import path. +Note that modules imported as a network resource allow only access to components +defined in QML files; components defined by C++ \l{QDeclarativeExtensionPlugin}{QML extension plugins} +are not available. \section2 Creating installed modules in C++ -C++ applications can dynamically define installed modules using -qmlRegisterType(). +C++ applications can define installed modules directly within the application using qmlRegisterType(). +For example, the \l {Tutorial: Writing QML extensions with C++}{Writing QML extensions with C++ tutorial} +defines a C++ class named \c PieChart and makes this type available to QML by calling qmlRegisterType(): + +\qml +qmlRegisterType("Charts", 1, 0, "PieChart"); +\endqml -For \l{QDeclarativeExtensionPlugin}{QML C++ plugins}, the -module URI is automatically passed to QDeclarativeExtensionPlugin::registerTypes(). -The QDeclarativeExtensionPlugin documentation shows how to use this URI -to call qmlRegisterType() to enable the plugin library to be built as -an installed module. Once the plugin is built and installed, the module is importable -in QML, like this: +This allows the application's QML files to use the \c PieChart type by importing the declared +\c Charts module: + +\qml +import Charts 1.0 +\endqml + +For \l{QDeclarativeExtensionPlugin}{QML plugins}, the +module URI is automatically passed to QDeclarativeExtensionPlugin::registerTypes(). This method +can be reimplemented by the developer to register the necessary types for the module. Below is the +\c registerTypes() implementation from the \l{declarative/cppextensions/plugins}{QML plugins} +example: + +\snippet examples/declarative/cppextensions/plugins/plugin.cpp plugin + +Once the plugin is built and installed, and includes a \l{Writing a qmldir file}{qmldir file}, +the module can be imported from QML, like this: \code import com.nokia.TimeExample 1.0 \endcode -A \l{QDeclarativeExtensionPlugin}{QML C++ plugin} also requires a -\l{Writing a qmldir file}{qmldir file} to make it available to the -QML engine. +Unlike QML types defined by QML files, a QML type defined in a C++ extension plugin cannot be loaded by +a module that is imported as a network resource. @@ -233,7 +313,7 @@ Unlike ordinary modules, multiple scripts cannot be imported into the same names A \c qmldir file is a metadata file for a module that maps all type names in the module to versioned QML files. It is required for installed modules, and -location modules that are loaded from a network source. +located modules that are loaded from a network source. It is defined by a plain text file named "qmldir" that contains one or more lines of the form: @@ -283,37 +363,6 @@ containing the plugin file. By default the engine searches for the plugin librar file. The plugin search path can be queried with QDeclarativeEngine::pluginPathList() and modified using QDeclarativeEngine::addPluginPath(). When running the \l {QML Viewer}, use the \c -P option to add paths to the plugin search path. -\target qmldirexample -\section2 Example - -If the components in the \c MyComponents directory from the -\l{Location Modules}{earlier example} were to be made available as a network resource, -the directory would need to contain a \c qmldir file similar to this: - -\code -ComponentA 1.0 ComponentA.qml -ComponentB 1.0 ComponentB.qml -\endcode - -The \c MyComponents directory could then be imported as a module using: - -\code -import "http://the-server-name.com/MyComponents" - -Slider { ... } -CheckBox { ... } -\endcode - -with an optional "1.0" version specification. Notice the import fails if -a later version is used, as the \c qmldir file specifies that these elements -are only available in the 1.0 version. - - -For examples of \c qmldir files for plugins, see the -\l {declarative/cppextensions/plugins}{Plugins} example and -\l {Tutorial: Writing QML extensions with C++}. - - \section1 Debugging The \c QML_IMPORT_TRACE environment variable can be useful for debugging diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 37df226..2227146 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -2103,10 +2103,11 @@ QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val /*! Adds \a path as a directory where the engine searches for installed modules in a URL-based directory structure. + The \a path may be a local filesystem directory or a URL. The newly added \a path will be first in the importPathList(). - \sa setImportPathList() + \sa setImportPathList(), \l {QML Modules} */ void QDeclarativeEngine::addImportPath(const QString& path) { diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 22dcb44..87183c4 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -712,6 +712,7 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in /*! \class QDeclarativeImportDatabase \brief The QDeclarativeImportDatabase class manages the QML imports for a QDeclarativeEngine. +\internal */ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) : engine(e) @@ -926,16 +927,25 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const #endif } +/*! + \internal +*/ QStringList QDeclarativeImportDatabase::pluginPathList() const { return filePluginPath; } +/*! + \internal +*/ void QDeclarativeImportDatabase::setPluginPathList(const QStringList &paths) { filePluginPath = paths; } +/*! + \internal +*/ void QDeclarativeImportDatabase::addPluginPath(const QString& path) { if (qmlImportTrace()) @@ -950,6 +960,9 @@ void QDeclarativeImportDatabase::addPluginPath(const QString& path) } } +/*! + \internal +*/ void QDeclarativeImportDatabase::addImportPath(const QString& path) { if (qmlImportTrace()) @@ -974,17 +987,25 @@ void QDeclarativeImportDatabase::addImportPath(const QString& path) fileImportPath.prepend(cPath); } +/*! + \internal +*/ QStringList QDeclarativeImportDatabase::importPathList() const { return fileImportPath; } +/*! + \internal +*/ void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths) { fileImportPath = paths; } - +/*! + \internal +*/ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QString *errorString) { if (qmlImportTrace()) diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml new file mode 100644 index 0000000..49613aa --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml @@ -0,0 +1,3 @@ +import QtQuick 1.0 + +Item {} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml new file mode 100644 index 0000000..f19a336 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml @@ -0,0 +1,4 @@ +import QtQuick 1.0 + +Item {} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir new file mode 100644 index 0000000..167bb10 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir @@ -0,0 +1,3 @@ +ComponentA 1.0 ComponentA.qml +ComponentB 1.0 ComponentB.qml + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index a4e9270..9ec0f84 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -44,6 +44,13 @@ #include #include +#include "../shared/testhttpserver.h" +#include "../../../shared/util.h" + +#define SERVER_ADDR "http://127.0.0.1:14450" +#define SERVER_PORT 14450 + + class tst_qdeclarativemoduleplugin : public QObject { Q_OBJECT @@ -58,6 +65,8 @@ private slots: void importsPlugin21(); void incorrectPluginCase(); void importPluginWithQmlFile(); + void remoteImportWithQuotedUrl(); + void remoteImportWithUnquotedUri(); }; #ifdef Q_OS_SYMBIAN @@ -193,6 +202,50 @@ void tst_qdeclarativemoduleplugin::importPluginWithQmlFile() delete object; } +void tst_qdeclarativemoduleplugin::remoteImportWithQuotedUrl() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/imports"); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine); + component.setData("import \"http://127.0.0.1:14450/com/nokia/PureQmlModule\" \nComponentA { width: 300; ComponentB{} }", QUrl()); + + QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready); + QObject *object = component.create(); + QCOMPARE(object->property("width").toInt(), 300); + QVERIFY(object != 0); + delete object; + + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); +} + +void tst_qdeclarativemoduleplugin::remoteImportWithUnquotedUri() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/imports"); + + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QDeclarativeComponent component(&engine); + component.setData("import com.nokia.PureQmlModule 1.0 \nComponentA { width: 300; ComponentB{} }", QUrl()); + + + QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("width").toInt(), 300); + delete object; + + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro index fb3630f..a92d3a2 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro @@ -1,6 +1,9 @@ load(qttest_p4) -SOURCES = tst_qdeclarativemoduleplugin.cpp -QT += declarative + +HEADERS = ../shared/testhttpserver.h +SOURCES = tst_qdeclarativemoduleplugin.cpp \ + ../shared/testhttpserver.cpp +QT += declarative network CONFIG -= app_bundle symbian: { -- cgit v0.12 From 32b68e009da38a2c85ceacce72c919606331522c Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 10 Feb 2011 10:52:29 +1000 Subject: Allow text to selected in a TextEdit or TextInput inside a Flickable. Set keepMouseGrabs to true when the selectByMouse property is enabled to prevent flickable from stealing the mouse grab and interrupting a selection. Change-Id: I08e11265ab9c55d239fd09aceef4fdb8e74aba9d Task-number: QTBUG-16956 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 1 + .../graphicsitems/qdeclarativetextinput.cpp | 17 + .../graphicsitems/qdeclarativetextinput_p.h | 1 + .../graphicsitems/qdeclarativetextinput_p_p.h | 1 + .../qdeclarativetextedit/data/flickableEdit.0.png | Bin 0 -> 850 bytes .../qdeclarativetextedit/data/flickableEdit.1.png | Bin 0 -> 859 bytes .../qdeclarativetextedit/data/flickableEdit.2.png | Bin 0 -> 1049 bytes .../qdeclarativetextedit/data/flickableEdit.3.png | Bin 0 -> 1051 bytes .../qdeclarativetextedit/data/flickableEdit.4.png | Bin 0 -> 698 bytes .../qdeclarativetextedit/data/flickableEdit.5.png | Bin 0 -> 698 bytes .../qdeclarativetextedit/data/flickableEdit.6.png | Bin 0 -> 1063 bytes .../qdeclarativetextedit/data/flickableEdit.qml | 3551 ++++++++++++++++++++ .../qdeclarativetextedit/flickableEdit.qml | 20 + .../data/flickableInput.0.png | Bin 0 -> 850 bytes .../data/flickableInput.1.png | Bin 0 -> 1037 bytes .../data/flickableInput.2.png | Bin 0 -> 1042 bytes .../data/flickableInput.3.png | Bin 0 -> 850 bytes .../data/flickableInput.4.png | Bin 0 -> 850 bytes .../data/flickableInput.5.png | Bin 0 -> 632 bytes .../data/flickableInput.6.png | Bin 0 -> 830 bytes .../data/flickableInput.7.png | Bin 0 -> 849 bytes .../qdeclarativetextinput/data/flickableInput.qml | 3279 ++++++++++++++++++ .../qdeclarativetextinput/flickableInput.qml | 21 + 23 files changed, 6891 insertions(+) create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 17354eb..87a49bd 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -974,6 +974,7 @@ void QDeclarativeTextEdit::setSelectByMouse(bool on) Q_D(QDeclarativeTextEdit); if (d->selectByMouse != on) { d->selectByMouse = on; + setKeepMouseGrab(on); emit selectByMouseChanged(on); } } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 2258ce6..dce7346 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1019,6 +1019,10 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) } } } + if (d->selectByMouse) { + setKeepMouseGrab(false); + d->pressPos = event->pos(); + } bool mark = event->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(event->pos().x()); d->control->moveCursor(cursor, mark); @@ -1029,6 +1033,8 @@ void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); if (d->selectByMouse) { + if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance()) + setKeepMouseGrab(true); moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode); event->setAccepted(true); } else { @@ -1043,6 +1049,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->selectByMouse) + setKeepMouseGrab(false); if (!d->showInputPanelOnFocus) { // input panel on click if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) { if (QGraphicsView * view = qobject_cast(qApp->focusWidget())) { @@ -1058,6 +1066,15 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QDeclarativePaintedItem::mouseReleaseEvent(event); } +bool QDeclarativeTextInput::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + setKeepMouseGrab(false); + } + return rv; +} + bool QDeclarativeTextInput::event(QEvent* ev) { Q_D(QDeclarativeTextInput); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 63d0e53..e1e66a9 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -240,6 +240,7 @@ protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + bool sceneEvent(QEvent *event); void keyPressEvent(QKeyEvent* ev); void inputMethodEvent(QInputMethodEvent *); bool event(QEvent *e); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 7a0086e..f7446b4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -118,6 +118,7 @@ public: QDeclarativeTextInput::SelectionMode mouseSelectionMode; QPointer cursorComponent; QPointer cursorItem; + QPointF pressPos; int lastSelectionStart; int lastSelectionEnd; diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png new file mode 100644 index 0000000..431bed8 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png new file mode 100644 index 0000000..d8d6bac Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png new file mode 100644 index 0000000..27e02e5 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png new file mode 100644 index 0000000..00549b3 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png new file mode 100644 index 0000000..5c2a885 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png new file mode 100644 index 0000000..5c2a885 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png new file mode 100644 index 0000000..fd7f010 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml new file mode 100644 index 0000000..dff5452 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml @@ -0,0 +1,3551 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "flickableEdit.0.png" + } + Frame { + msec: 32 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 48 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 64 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 80 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 96 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 112 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 128 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 144 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 160 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 176 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 192 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 208 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 224 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 240 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 256 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 272 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 288 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 304 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 320 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 336 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 352 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 368 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 384 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 400 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 416 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 432 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 448 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 464 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 480 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 496 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 512 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 528 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 544 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 560 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 576 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 592 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 608 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 624 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 640 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 656 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 672 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 688 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 704 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 720 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 736 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 752 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 768 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 784 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 800 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 816 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 832 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 848 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 864 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 880 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 896 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 29; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 912 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 928 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 944 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 960 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 976 + image: "flickableEdit.1.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 32; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 992 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 34; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 36; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 39; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1024 + hash: "4626e25f67dfd0fe3846322455762b3b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 44; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1040 + hash: "4626e25f67dfd0fe3846322455762b3b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 50; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1056 + hash: "e506425ea4a8eb6d94442ac0bccd0911" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 56; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1072 + hash: "3c45be5d00748154f9abce8d525b5791" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 61; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1088 + hash: "3e33ff0dfd478bad91472fa2bb4908a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 64; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1104 + hash: "3e33ff0dfd478bad91472fa2bb4908a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 71; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "e8e7e98f3d7dbcdb4040ae81ef656e02" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1136 + hash: "e8e7e98f3d7dbcdb4040ae81ef656e02" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 78; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 80; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1152 + hash: "309c25ff85a361dfebd6464984fd9d79" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 83; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 85; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1168 + hash: "4b4fc7d9263af761222bb23f41021731" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1184 + hash: "4b4fc7d9263af761222bb23f41021731" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 93; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 96; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1200 + hash: "bd00eeda31cfc8d59a2c9677e771dadb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 99; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1216 + hash: "adce307d674b8425fa39b69958d6acc5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1232 + hash: "36e04d9124f32a21784f3017cc26ee71" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 116; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1248 + hash: "36e04d9124f32a21784f3017cc26ee71" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 119; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1264 + hash: "c6548ac358dd0eb4fa07ed305039d4e2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 126; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1280 + hash: "a0c4b8e21b0b04edaf7b32b2ab40edb2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 130; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1296 + hash: "a0c4b8e21b0b04edaf7b32b2ab40edb2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 134; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1312 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1328 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 141; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1344 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 143; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 144; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1360 + hash: "90f44df899138e894b1a7e42657b8331" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 147; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1376 + hash: "90f44df899138e894b1a7e42657b8331" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 149; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1392 + hash: "8ec6bb08aac10a622df934421f64beb4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1408 + hash: "d4e52b7ca07033e4f2124607454fd81b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 152; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1424 + hash: "499d7c3d9cfb35db68f6eece23130e6b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1440 + hash: "499d7c3d9cfb35db68f6eece23130e6b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1456 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 160; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1472 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1488 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Frame { + msec: 1504 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1520 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1536 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1552 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 167; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1568 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1584 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1600 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1616 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1632 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1648 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1664 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1680 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1696 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1712 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1728 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1744 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1760 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1776 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1792 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1808 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1824 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1840 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 170; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1856 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1872 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1888 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1904 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1920 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1936 + image: "flickableEdit.2.png" + } + Frame { + msec: 1952 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1968 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1984 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2000 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2016 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2032 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2048 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2064 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2080 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2096 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2112 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2128 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2144 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2160 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2176 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2192 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2208 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2224 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2240 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2256 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2272 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2288 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2304 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2320 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2336 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2352 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2368 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2384 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2400 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2416 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2432 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2448 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2464 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2480 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2496 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2512 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2528 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2544 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2560 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2576 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2592 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2608 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2624 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2640 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2656 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2672 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2688 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2704 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2720 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2736 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2752 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2768 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2784 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2800 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2816 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2832 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2848 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2864 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2880 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2896 + image: "flickableEdit.3.png" + } + Frame { + msec: 2912 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2928 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2944 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2960 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2976 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2992 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 24; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3008 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 25; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3024 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 26; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3040 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 29; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3056 + hash: "e5daa45e1d798fdf2562dbb9a1a2c97b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 31; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3072 + hash: "698b572adf95ddc235b781b126a1cc10" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 35; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3088 + hash: "7a87fe9484b00f8c7039e3129fc24fb5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 37; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 40; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3104 + hash: "2f17e7980a28789d0f262e3682c2da27" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 42; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 45; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3120 + hash: "0757f4c05233a25e6a8825b2c6052d8d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 49; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 52; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3136 + hash: "799da712f376033efdbaf9a342e4bc3f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3152 + hash: "bf7b2a29664fe4acf52d56c73cf079b1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3168 + hash: "7928b280e7a9ab89217c9abf3b709cd2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3184 + hash: "3102339f3e18640f6b508e88aafefb79" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 78; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3200 + hash: "98cddfbea5b96f9dd08c5a3655155d35" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 81; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3216 + hash: "5604b2f85c3a90f8b29da3fec2f6c509" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 91; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3232 + hash: "5ca4055c8dded5d30c326d6d304da28d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 94; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 97; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3248 + hash: "b0afe256f8f89a77a5fa87c023cda469" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 101; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 104; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3264 + hash: "d7408be78c80e2b6e5848ee696a79ee0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 108; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3280 + hash: "f7e12621527fd52e21595cfbf804879c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 115; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 118; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3296 + hash: "6b8c9413ba1a791e42b06aaa711cdb4e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3312 + hash: "1c80e0f89033dedc66b236561042f4f6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3328 + hash: "6ec06d8844ff57e34af5316895250858" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3344 + hash: "f3c0159243555e919fd736866b00a5ab" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3360 + hash: "973ced5d6155240490acd6241610429d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3376 + hash: "0aee5feb94508f70c62cc3255c53bc8a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 182; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3392 + hash: "840cc661a50dd8bc1af8f6d53ccbece5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 187; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 191; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3408 + hash: "34a470358ccfb7592cf47399ab6dbc19" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 195; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 198; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3424 + hash: "25c53ff3977ca8422c545c1608782833" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 202; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 205; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3440 + hash: "d4388550549d54e31640cda4672c3bfb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 209; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 213; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3456 + hash: "8904c3b225a5e732fca4fc605d0fc12a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 216; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 219; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3472 + hash: "415a630fc6a963e99a0e13bf5e461849" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 223; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 226; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3488 + hash: "1526e90e0345e20a3455554c8f249de7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 229; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 233; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3504 + hash: "2b215748d63e505469d343919b245af9" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 235; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 238; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3520 + hash: "6821e559cb1e45b0cd731c90c3b16934" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 241; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 243; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3536 + hash: "334ddaa8c2cd0506528fe20a21991b03" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 245; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 247; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3552 + hash: "6e651889e91d3de96d9aaf91f4ed9a2c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 250; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 251; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3568 + hash: "0554f22d8079ef0213dc25f9f1b59055" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 252; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 253; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3584 + hash: "1eb0805e4c706af1c7cfa113d32edda1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 255; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 256; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3600 + hash: "482f30ca992e9f92241523a47125d9b4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 257; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 259; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3616 + hash: "6b2bec317fad51fe85bab6a00ced9655" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 261; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 262; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3632 + hash: "acc661684f507375518fc73fe081f61e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 263; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 265; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3648 + hash: "f77143d0d7a3cf8c0163bf950940ad07" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 266; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 267; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3664 + hash: "8d0407ae3f55305e1d9780deaa30c064" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 268; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3680 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 3696 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 3712 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3728 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3744 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3760 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3776 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3792 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3808 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3824 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3840 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3856 + image: "flickableEdit.4.png" + } + Frame { + msec: 3872 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3888 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3904 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3920 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3936 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3952 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3968 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3984 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4000 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4016 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4032 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4048 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4064 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4080 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4096 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4112 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4128 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4144 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4160 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4176 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4192 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4208 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4224 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4240 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4256 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4272 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4288 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4304 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4320 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4336 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4352 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4368 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4384 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4400 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4416 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4432 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4448 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4464 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4480 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4496 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4512 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4528 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4544 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4560 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4576 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4592 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4608 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4624 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4640 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4656 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4672 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4688 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4704 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4720 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4736 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4752 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4768 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4784 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4800 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4816 + image: "flickableEdit.5.png" + } + Frame { + msec: 4832 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4848 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4864 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4880 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 266; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4896 + hash: "e5a6693779ffb4e8a333756690a8f9e0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 264; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 262; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4912 + hash: "6acabe70146611091621ef5079cc97ec" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 259; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 256; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4928 + hash: "f75b5eaa04bfec866f088f665edb225e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 253; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 249; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4944 + hash: "1888acd9f3e48348c22e324d67ab2724" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 245; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 240; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4960 + hash: "cd24be347f20371f9d0796fa4a38ad0c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 235; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 231; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4976 + hash: "f39bc67a8e83340f8e89cf11c89fb27c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 227; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 222; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4992 + hash: "80d8019485231c061ba1cf81fd4c42ca" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 217; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 213; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5008 + hash: "72893900dfd007ea25a7d75982be6320" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 207; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 203; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5024 + hash: "f3d02c4d2f0b8b75b0b6159c0ba8f4db" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 199; y: 28 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 195; y: 28 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5040 + hash: "8ecdf1325bb2084bf6212216bd86b324" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 190; y: 27 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 186; y: 27 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5056 + hash: "be5c62268b337c9d7f69ab01b02c816d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 182; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 178; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5072 + hash: "a0eea6c818a1cb71809aff4613e9655d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5088 + hash: "27fcf1d4cd00dc7ac54fa92f9c7e2ac2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5104 + hash: "32f6bdc5e2f6ce34436a21dd8ee348dd" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 159; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5120 + hash: "4c11c9075429acd4acddc6ede4e5fe69" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 23 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 23 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5136 + hash: "8fdaf03e0b03698613092303945787d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 23 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5152 + hash: "d9bc269f21d5eade8bb9555d05a86744" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 22 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5168 + hash: "f9dd0735682dba198febffcc85c9835a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 21 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 21 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5184 + hash: "a98869bb654e3b4c1f4d9d0e7e24197a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 21 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5200 + hash: "50ceb9d6d58129b71009079a0028e7c4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 121; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 118; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5216 + hash: "6b8c9413ba1a791e42b06aaa711cdb4e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5232 + hash: "f7e12621527fd52e21595cfbf804879c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 108; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5248 + hash: "d7408be78c80e2b6e5848ee696a79ee0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 99; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5264 + hash: "e648f25a978b9f14cf71d5f1d90edf15" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 96; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 93; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5280 + hash: "64ce73aa32f2c08f4cee9a35a103a1d0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 91; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 88; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5296 + hash: "1db1d100eb1f97a7c85ab8df3e558188" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 86; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5312 + hash: "5604b2f85c3a90f8b29da3fec2f6c509" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 81; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 79; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5328 + hash: "fb57c6295d512821945754020ea6a3ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 77; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5344 + hash: "14dfd5b78901c9f63e4f5d0889f77805" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5360 + hash: "cc105198e78269be1240785b791c8612" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 67; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5376 + hash: "1ef97830b4f1be66a4f443ee4573547b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 64; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5392 + hash: "0ef86edc381e75c39ba067404817edb8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 63; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 60; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5408 + hash: "6a7605f59eb364fbc166aeea7b54695a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 59; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 57; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5424 + hash: "e86bb3698ad8b46e70237088ea056ab0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5440 + hash: "56db36cde05d74d6bf8eec0b21515b20" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 51; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 49; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5456 + hash: "05adc602e827635ca43c0cff2b5b857d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 45; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5472 + hash: "cbdcdf9b7e640a79e2269247bb4d6cc2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 43; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5488 + hash: "bc014e9feb5e69c4042385a6753d1884" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 38; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 37; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5504 + hash: "544e9ddbedae500955e6cec79eae709c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 35; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5520 + hash: "ec17a9dba3846c1919b67eaf3d234471" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 28; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5536 + hash: "8ab538f8baa170798c93e6eb4d5441f8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 26; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5552 + hash: "1b1636fecff90e602b87dbf84a986d2a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 25; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 24; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5568 + hash: "27a84ee3fb8b306e22e50ba753828b7c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5584 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5600 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5616 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5632 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5648 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5664 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5680 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5696 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5712 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5728 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5744 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5760 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5776 + image: "flickableEdit.6.png" + } + Frame { + msec: 5792 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5808 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5824 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5840 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5856 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5872 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5888 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5904 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5920 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5936 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5952 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5968 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5984 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6000 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6016 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6032 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6048 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6064 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6080 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6096 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6112 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6128 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6144 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6160 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6176 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6192 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6208 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6224 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6240 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6256 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6272 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6288 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6304 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6320 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6336 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6352 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6368 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6384 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6400 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6416 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6432 + hash: "ee9cd90fbe594efb411315a97b702a40" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml new file mode 100644 index 0000000..6913fdd --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml @@ -0,0 +1,20 @@ +import QtQuick 1.0 + +Flickable { + width: 200 + height: 50 + contentWidth: 400 + + Column { + anchors.fill: parent + + TextEdit { + selectByMouse: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + TextEdit { + selectByMouse: false + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png new file mode 100644 index 0000000..431bed8 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png new file mode 100644 index 0000000..9708b4f Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png new file mode 100644 index 0000000..7034946 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png new file mode 100644 index 0000000..7c56f00 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png new file mode 100644 index 0000000..431bed8 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png new file mode 100644 index 0000000..30b7a08 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png new file mode 100644 index 0000000..54e13cb Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png new file mode 100644 index 0000000..34c099b Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml new file mode 100644 index 0000000..de69c6a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml @@ -0,0 +1,3279 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "flickableInput.0.png" + } + Frame { + msec: 32 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 48 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 64 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 80 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 96 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 112 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 128 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 144 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 160 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 176 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 192 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 208 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 224 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 240 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 256 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 272 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 288 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 304 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 320 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 336 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 352 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 368 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 384 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 400 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 416 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 432 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 448 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 464 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 480 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 496 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 512 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 528 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 544 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 560 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 576 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 592 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 608 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 624 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 640 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 656 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 672 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 688 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 704 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 720 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 736 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 752 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 768 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 39; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 784 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 800 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 816 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 832 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 43; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 848 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 46; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 50; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 864 + hash: "c54c442eb01186dc8d5be7ff7b242aa1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 57; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 880 + hash: "8eb5252ed783eae4dd998ea5a451c6bb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 68; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 896 + hash: "f80423adedb40b1c9ed88bb171590626" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 79; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 912 + hash: "afb2d22b60113d05b038fd09b5966151" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 928 + hash: "e0a4a243acd0c4f3960ea77fdb5e30c1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 95; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 101; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 944 + hash: "24c5185a748dc4b02fdd40fd2d0420ff" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 960 + hash: "e271a2cd9847828da3e39c1e618f828a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 117; y: 7 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 7 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 976 + image: "flickableInput.1.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 7 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 6 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 992 + hash: "3f40064784f716ce75ef9390d90a1eac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 6 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 6 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "77a95b3d8d4682eb8e613bd86ea7b3c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 5 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 5 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1024 + hash: "308ea214fc63e47141623bc436df0efc" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 5 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 5 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1040 + hash: "3e0a860238ab282aebd733a92321f86f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 156; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1056 + hash: "ed4c6a18ed003922f5724ebc8e798c6c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 159; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1072 + hash: "ed4c6a18ed003922f5724ebc8e798c6c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 163; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1088 + hash: "90bc837ada7b6cd08028e790b1a87ae2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1104 + hash: "90bc837ada7b6cd08028e790b1a87ae2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 173; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1136 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1152 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1168 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1184 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1200 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1216 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1232 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1248 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1264 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1280 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1296 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1312 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1328 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1344 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1360 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1376 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 176; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1392 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1408 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1424 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1440 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1456 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1472 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1488 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1504 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1520 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1536 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1552 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1568 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1584 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1600 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1616 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1632 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1648 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1664 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1680 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1696 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1712 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1728 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1744 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1760 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1776 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1792 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1808 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1824 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1840 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1856 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1872 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1888 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1904 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1920 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1936 + image: "flickableInput.2.png" + } + Frame { + msec: 1952 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1968 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1984 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2000 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2016 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2032 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2048 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2064 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2080 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2096 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2112 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2128 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2144 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2160 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2176 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2192 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2208 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2224 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2240 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2256 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2272 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2288 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 17; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2304 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2320 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2336 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2352 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2368 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2384 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2400 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2416 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2432 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 13 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 14 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2448 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 15 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2464 + hash: "6865c870740497e31dfeb91e09737206" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2480 + hash: "541acf0d74762064d970506a40f6600b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2496 + hash: "956939b887f2bb0d45400214685f1fac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 21 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2512 + hash: "956939b887f2bb0d45400214685f1fac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2528 + hash: "3eff05a088e55df16f0b30546ad8c87f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 23 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2544 + hash: "3eff05a088e55df16f0b30546ad8c87f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2560 + hash: "5b0488fc2a7f840f73d4fc9d17a5a738" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 27 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2576 + hash: "e17d039213c12708ff378789705e281a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 28 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2592 + hash: "2e2eaab559d0dd7543c2e6e17e0f7740" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2608 + hash: "49a9baad5178009409e28618a4132544" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2624 + hash: "49a9baad5178009409e28618a4132544" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 32 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2640 + hash: "a867fe835626e562d5e060c0b2bc4ea3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 33 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 34 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2656 + hash: "1479e0feffdff866bfd14cbbf76017c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 35 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2672 + hash: "1479e0feffdff866bfd14cbbf76017c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 36 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 37 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2688 + hash: "dfa99d1eee5ed8d2913c0e603be3ad0e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 38 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2704 + hash: "b55abbe5e7d2c3f5cdaf6dcf5a12c00a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 40 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2720 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 41 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2736 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Frame { + msec: 2752 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 42 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2768 + hash: "c9ec87a419171b4d6311a36c952eaef1" + } + Frame { + msec: 2784 + hash: "c9ec87a419171b4d6311a36c952eaef1" + } + Frame { + msec: 2800 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2816 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2832 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2848 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2864 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2880 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2896 + image: "flickableInput.3.png" + } + Frame { + msec: 2912 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2928 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2944 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2960 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2976 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2992 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3008 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 17; y: 42 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3024 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3040 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3056 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3072 + hash: "09201585ad57e87efda13c469e1bc95d" + } + Frame { + msec: 3088 + hash: "09201585ad57e87efda13c469e1bc95d" + } + Frame { + msec: 3104 + hash: "b816b96270a846ed5776e6f53d507eb8" + } + Frame { + msec: 3120 + hash: "6ee997c78cadb4357b30db81acf4ee40" + } + Frame { + msec: 3136 + hash: "abbab9e07614915a49fc8f30242932a7" + } + Frame { + msec: 3152 + hash: "47f0d0fe751a8ad3dd3f6341d76c929d" + } + Frame { + msec: 3168 + hash: "0304cbed0c52d5486df52312898fe81d" + } + Frame { + msec: 3184 + hash: "6ac82afa8805f1bdb4c67a2f1a1aff32" + } + Frame { + msec: 3200 + hash: "4cc6db0a1dbe6c70d5e2dfe60fe70a51" + } + Frame { + msec: 3216 + hash: "cf04ff1b13f5aa36470fd8ae23523153" + } + Frame { + msec: 3232 + hash: "20fcdfd24f21125d61ac45cbe94e48a7" + } + Frame { + msec: 3248 + hash: "e017109961b5e6c6701c3045f284ebf7" + } + Frame { + msec: 3264 + hash: "e017109961b5e6c6701c3045f284ebf7" + } + Frame { + msec: 3280 + hash: "c2a770b8c95959f4abf91420c0a3e8b2" + } + Frame { + msec: 3296 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3312 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3328 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3344 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3360 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3376 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3392 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3408 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3424 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3440 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3456 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3472 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3488 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3504 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3520 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3536 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3552 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3568 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3584 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3600 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3616 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3632 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3648 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3664 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3680 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3696 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3712 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3728 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3744 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3760 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3776 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3792 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3808 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3824 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3840 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3856 + image: "flickableInput.4.png" + } + Frame { + msec: 3872 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3888 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3904 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3920 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3936 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3952 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 12; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3968 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 3984 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4000 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4016 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4032 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4048 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 13; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4064 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 16; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 20; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4080 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4096 + hash: "ab2ea5988d2b3288d3c57369f68933dc" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 31; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 36; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4112 + hash: "986834600427959d170d547a1c5ecce0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4128 + hash: "52847e87c1fef2d7357c86abb0944df4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 52; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4144 + hash: "bc68a47163712646cf8439459fb0d100" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4160 + hash: "9e9f66e9545c77a2e7ee02d46acd102e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 76; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4176 + hash: "4e9e7500185499c5a5f9d65e0e9406a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 80; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 83; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4192 + hash: "550d6c645bf694c544734d67e2ae5ac3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4208 + hash: "0736bab3f9c1cec0f944003bebe3d499" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 94; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 97; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4224 + hash: "efffb9f6d6a7dacf297530b1cb68a713" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 100; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4240 + hash: "d5458a8dd8a9bf22e67439c9d8d9c366" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 109; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4256 + hash: "2d30acf6dc0e186577bd6f7ce858ab92" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 112; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 115; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4272 + hash: "e1a926cc5f7a49c9320a8d49c8a1bb3f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 117; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 120; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4288 + hash: "cfc9c0bca9e269887ad5c67cc684b753" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4304 + hash: "7b561e04ef93399460eb3b4b850c3cab" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 126; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4320 + hash: "1c17d036e08b24b47239f9a38df3d87d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 130; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4336 + hash: "3ec95ad7622048b68a53cfd3fdeac999" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 133; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4352 + hash: "1e20084ed70b7423885a2d0f06fba660" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 134; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4368 + hash: "f19e136b3c3d57d8b8e63c64b17c29e4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4384 + hash: "f19e136b3c3d57d8b8e63c64b17c29e4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4400 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4416 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4432 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4448 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4464 + hash: "03c99addee96254d19db72746f1bef11" + } + Frame { + msec: 4480 + hash: "03c99addee96254d19db72746f1bef11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4496 + hash: "cb087b0af44fd7e767b3ff5da1f49790" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 143; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4512 + hash: "8c36fa6a9c8bfb66e272c8628aec7077" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4528 + hash: "971154dba58b18b1d82999f5b6a40cc1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 149; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4544 + hash: "253397b603f99f7d092dda82d794e944" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 153; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4560 + hash: "f8ded9e6f36a35a73fbe2264321838ca" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4576 + hash: "83b9cec7bbe65ba9d68b089211296116" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4592 + hash: "525ffec3a2d2a7a9e0c82f2c98b09ea0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4608 + hash: "c4fb902f66abebb6b7c3489a073e17d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 172; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 173; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4624 + hash: "0f4526d9f840c0a95e9d145c9822d6e1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4640 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Frame { + msec: 4656 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4672 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4688 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 177; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4704 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 178; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4720 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 179; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4736 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Frame { + msec: 4752 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 180; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4768 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4784 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4800 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4816 + image: "flickableInput.5.png" + } + Frame { + msec: 4832 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4848 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4864 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4880 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4896 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4912 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4928 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4944 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4960 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 4976 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 4992 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5008 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5024 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5040 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5056 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5072 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5088 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5104 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5120 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5136 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5152 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5168 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5184 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5200 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5216 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5232 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5248 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5264 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5280 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5296 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5312 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5328 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5344 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5360 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5376 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5392 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5408 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5424 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5440 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5456 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5472 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5488 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5504 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5520 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5536 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 177; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5552 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5568 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5584 + hash: "c4fb902f66abebb6b7c3489a073e17d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5600 + hash: "04c6accf277b5bca4c53c1817f85bafe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5616 + hash: "8eb14964fea798ceccc150310a12fd4b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 160; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5632 + hash: "83b9cec7bbe65ba9d68b089211296116" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5648 + hash: "e59ae71a5636c48e6befa305eba76ec8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 153; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5664 + hash: "73e178775ee01d28cf03378f267753b1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5680 + hash: "253397b603f99f7d092dda82d794e944" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5696 + hash: "971154dba58b18b1d82999f5b6a40cc1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 144; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5712 + hash: "5bd30e73b37592c06f735541f802f367" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5728 + hash: "cb087b0af44fd7e767b3ff5da1f49790" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5744 + hash: "03c99addee96254d19db72746f1bef11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5760 + hash: "0f76d8a89e383e7e742a3d194d770061" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 133; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5776 + image: "flickableInput.6.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 129; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5792 + hash: "f047f32822850b2c0fee18b4a8f8a96a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 121; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5808 + hash: "160c8c8447a469291fc2f87c2b6c97ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 119; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 116; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5824 + hash: "4a9d610f3fa37336c0cab7b4e575713b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 112; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5840 + hash: "5a00b185983ad89bcf1ceb036c424dd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 110; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 109; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5856 + hash: "a578449e7df3994d0806f7ee2e5a7815" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 107; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5872 + hash: "445cb1ae1934659c3c8b5800bc30fc74" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5888 + hash: "ad22110876a867ca80530ca6d132dfe3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 105; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5904 + hash: "7a644a888de5691c69543699229ec8ca" + } + Frame { + msec: 5920 + hash: "7a644a888de5691c69543699229ec8ca" + } + Frame { + msec: 5936 + hash: "41c14cc9ea05712aea8d1feb18ca85f3" + } + Frame { + msec: 5952 + hash: "921d476813711e64b9c2272aeff3ed40" + } + Frame { + msec: 5968 + hash: "2dad691263389dce74c99530f188cd20" + } + Frame { + msec: 5984 + hash: "b426ff8ba6d1c52974b117fb8b912b76" + } + Frame { + msec: 6000 + hash: "bbcae0d0547e1cfe9a4db1a6f86bf4b6" + } + Frame { + msec: 6016 + hash: "b8e54bc1a48d7a225cce25c3735c2933" + } + Frame { + msec: 6032 + hash: "b59e0f6eea3c41cedb10ac7a7e2629ef" + } + Frame { + msec: 6048 + hash: "48add89789f9d1be82aedeecf6fda362" + } + Frame { + msec: 6064 + hash: "3cf7a035a5b7dbc81c3da5e99efa5024" + } + Frame { + msec: 6080 + hash: "ff9c7173f7138e273cdbdfa8c6f5fedf" + } + Frame { + msec: 6096 + hash: "bc5e19862dfb38e687d1bfc37690a3b8" + } + Frame { + msec: 6112 + hash: "6ff97512731fd97d3c540245ffff6205" + } + Frame { + msec: 6128 + hash: "290e8c8bf51ced134e965f72a868e467" + } + Frame { + msec: 6144 + hash: "3a63687a5179896572be2e1e0d00766f" + } + Frame { + msec: 6160 + hash: "80f8d13272a23e8816ef45fbbef922fe" + } + Frame { + msec: 6176 + hash: "7888e0ece9522f751417944855824be8" + } + Frame { + msec: 6192 + hash: "3d81f8cde15b7d0b009fc9b46a1144e1" + } + Frame { + msec: 6208 + hash: "3d81f8cde15b7d0b009fc9b46a1144e1" + } + Frame { + msec: 6224 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6240 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6256 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6272 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6288 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6304 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6320 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6336 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6352 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6368 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6384 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6400 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6416 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6432 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6448 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6464 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6480 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6496 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6512 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6528 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6544 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6560 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6576 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6592 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6608 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6624 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6640 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6656 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6672 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6688 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6704 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6720 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6736 + image: "flickableInput.7.png" + } + Frame { + msec: 6752 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6768 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6784 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6800 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6816 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6832 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6848 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6864 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6880 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6896 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6912 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6928 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6944 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6960 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6976 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6992 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7008 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7024 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7040 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7056 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7072 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7088 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7104 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7120 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7136 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7152 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7168 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7184 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7200 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7216 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7232 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7248 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7264 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7280 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7296 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml new file mode 100644 index 0000000..7af74ac --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml @@ -0,0 +1,21 @@ +import QtQuick 1.0 + +Flickable { + width: 200 + height: 50 + contentWidth: 400 + contentHeight: 100 + + Column { + anchors.fill: parent + + TextInput { + selectByMouse: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + TextInput { + selectByMouse: false + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } +} -- cgit v0.12 From db8462b107ad3dbf13c1eed43588fb1d9420f4ad Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 10 Feb 2011 15:31:40 +1000 Subject: PathView items were not correctly updated when rootIndex changed. PathView got confused because it queried the model when removing items due to the rootIndex change. This caused new items to be added since the model->count() was not zero (it was the count for the new rootIndex). Calculate the PathView modelCount similarly to the other views (rather than querying the model) and correctly handle the modelCount being set to zero. Change-Id: I9e4fb27c14aa8c77ad37ff01d95c123f909db20d Task-number: QTBUG-16366 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativepathview.cpp | 44 ++++++++++++-------- .../qdeclarativepathview/data/treemodel.qml | 19 +++++++++ .../tst_qdeclarativepathview.cpp | 48 ++++++++++++++++++++++ 3 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativepathview/data/treemodel.qml diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 050a9ca..269d3b7 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1455,17 +1455,18 @@ void QDeclarativePathView::itemsInserted(int modelIndex, int count) if (!d->isValid() || !isComponentComplete()) return; - d->itemCache += d->items; - d->items.clear(); - if (modelIndex <= d->currentIndex) { - d->currentIndex += count; - emit currentIndexChanged(); - } else if (d->offset != 0) { - d->offset += count; - d->offsetAdj += count; + if (d->modelCount) { + d->itemCache += d->items; + d->items.clear(); + if (modelIndex <= d->currentIndex) { + d->currentIndex += count; + emit currentIndexChanged(); + } else if (d->offset != 0) { + d->offset += count; + d->offsetAdj += count; + } } - - d->modelCount = d->model->count(); + d->modelCount += count; if (d->flicking || d->moving) { d->regenerate(); d->updateCurrent(); @@ -1502,18 +1503,29 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count) d->itemCache += d->items; d->items.clear(); + bool changedOffset = false; if (modelIndex > d->currentIndex) { if (d->offset >= count) { + changedOffset = true; d->offset -= count; d->offsetAdj -= count; } } - d->modelCount = d->model->count(); - d->regenerate(); - d->updateCurrent(); - if (!d->modelCount) + d->modelCount -= count; + if (!d->modelCount) { + while (d->itemCache.count()) + d->releaseItem(d->itemCache.takeLast()); + d->offset = 0; + changedOffset = true; + d->tl.reset(d->moveOffset); update(); + } else { + d->regenerate(); + d->updateCurrent(); + } + if (changedOffset) + emit offsetChanged(); if (currentChanged) emit currentIndexChanged(); emit countChanged(); @@ -1601,7 +1613,7 @@ void QDeclarativePathView::movementEnding() int QDeclarativePathViewPrivate::calcCurrentIndex() { int current = -1; - if (model && items.count()) { + if (modelCount && model && items.count()) { offset = qmlMod(offset, modelCount); if (offset < 0) offset += modelCount; @@ -1617,7 +1629,7 @@ void QDeclarativePathViewPrivate::updateCurrent() Q_Q(QDeclarativePathView); if (moveReason != Mouse) return; - if (!haveHighlightRange || highlightRangeMode != QDeclarativePathView::StrictlyEnforceRange) + if (!modelCount || !haveHighlightRange || highlightRangeMode != QDeclarativePathView::StrictlyEnforceRange) return; int idx = calcCurrentIndex(); diff --git a/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml b/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml new file mode 100644 index 0000000..56f7ae4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +PathView { + width: 320 + height: 240 + function setRoot(index) { + vdm.rootIndex = vdm.modelIndex(index); + } + model: VisualDataModel { + id: vdm + model: myModel + delegate: Text { objectName: "wrapper"; text: display } + } + + path: Path { + startX: 0; startY: 120 + PathLine { x: 320; y: 120 } + } +} diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index f39e4b9..ebb5f98 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include "../../../shared/util.h" @@ -62,6 +63,25 @@ #define SRCDIR "." #endif +static void initStandardTreeModel(QStandardItemModel *model) +{ + QStandardItem *item; + item = new QStandardItem(QLatin1String("Row 1 Item")); + model->insertRow(0, item); + + item = new QStandardItem(QLatin1String("Row 2 Item")); + item->setCheckable(true); + model->insertRow(1, item); + + QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item")); + item->setChild(0, childItem); + + item = new QStandardItem(QLatin1String("Row 3 Item")); + item->setIcon(QIcon()); + model->insertRow(2, item); +} + + class tst_QDeclarativePathView : public QObject { Q_OBJECT @@ -90,6 +110,7 @@ private slots: void visualDataModel(); void undefinedPath(); void mouseDrag(); + void treeModel(); private: QDeclarativeView *createView(); @@ -900,6 +921,33 @@ void tst_QDeclarativePathView::mouseDrag() delete canvas; } +void tst_QDeclarativePathView::treeModel() +{ + QDeclarativeView *canvas = createView(); + + QStandardItemModel model; + initStandardTreeModel(&model); + canvas->engine()->rootContext()->setContextProperty("myModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/treemodel.qml")); + + QDeclarativePathView *pathview = qobject_cast(canvas->rootObject()); + QVERIFY(pathview != 0); + QCOMPARE(pathview->count(), 3); + + QDeclarativeText *item = findItem(pathview, "wrapper", 0); + QVERIFY(item); + QCOMPARE(item->text(), QLatin1String("Row 1 Item")); + + QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1))); + QCOMPARE(pathview->count(), 1); + + QTRY_VERIFY(item = findItem(pathview, "wrapper", 0)); + QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item")); + + delete canvas; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); -- cgit v0.12 From 20097c27f55d8bc61ba41de5997d25f86daa18ed Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Feb 2011 13:34:20 +0100 Subject: fix QMAKE_COPY_DIR for mingw+sh Task-number: QTBUG-17315 --- mkspecs/win32-g++/qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 2d9833b..65ae590 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -77,7 +77,7 @@ QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain QMAKE_DIR_SEP = / QMAKE_QMAKE ~= s,\\\\,/, QMAKE_COPY = cp - QMAKE_COPY_DIR = xcopy /s /q /y /i + QMAKE_COPY_DIR = cp -r QMAKE_MOVE = mv QMAKE_DEL_FILE = rm QMAKE_MKDIR = mkdir -- cgit v0.12 From 5ec67c969dce335a26c402b73bb19a6751401871 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 10 Feb 2011 14:39:41 +0200 Subject: Fix QFileDialog Symbian native file dialog filename filtering. Now QFileDialog static functions that use Symbian native file dialog should find the same files as non-native QFileDialog for any given filename filter. Task-number: QTBUG-17298 Reviewed-by: Janne Koskinen --- src/gui/dialogs/qfiledialog_symbian.cpp | 52 ++++++++++++--------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/src/gui/dialogs/qfiledialog_symbian.cpp b/src/gui/dialogs/qfiledialog_symbian.cpp index b8ea5e5..ed98950 100644 --- a/src/gui/dialogs/qfiledialog_symbian.cpp +++ b/src/gui/dialogs/qfiledialog_symbian.cpp @@ -54,6 +54,9 @@ QT_BEGIN_NAMESPACE +extern QStringList qt_make_filter_list(const QString &filter); // defined in qfiledialog.cpp +extern QStringList qt_clean_filter_list(const QString &filter); // defined in qfiledialog.cpp + enum DialogMode { DialogOpen, DialogSave, DialogFolder }; #if defined(Q_WS_S60) && defined(SYMBIAN_VERSION_SYMBIAN3) class CExtensionFilter : public MAknFileFilter @@ -61,56 +64,39 @@ class CExtensionFilter : public MAknFileFilter public: void setFilter(const QString filter) { - filterList.clear(); - if (filter.left(2) == QLatin1String("*.")) { - //Filter has only extensions - filterList << filter.split(QLatin1String(" ")); - return; - } else { - //Extensions are in parenthesis and there may be several filters - QStringList separatedFilters(filter.split(QLatin1String(";;"))); - for (int i = 0; i < separatedFilters.size(); i++) { - if (separatedFilters.at(i).contains(QLatin1String("(*)"))) { - filterList << QLatin1String("(*)"); - return; - } - } - QRegExp rx(QLatin1String("\\(([^\\)]*)\\)")); - int pos = 0; - while ((pos = rx.indexIn(filter, pos)) != -1) { - filterList << rx.cap(1).split(QLatin1String(" ")); - pos += rx.matchedLength(); - } + QStringList unparsedFiltersList = qt_make_filter_list(filter); + QStringList filterList; + filterRxList.clear(); + + foreach (QString unparsedFilter, unparsedFiltersList) { + filterList << qt_clean_filter_list(unparsedFilter); + } + foreach (QString currentFilter, filterList) { + QRegExp filterRx(currentFilter, Qt::CaseInsensitive, QRegExp::Wildcard); + filterRxList << filterRx; } } TBool Accept(const TDesC &/*aDriveAndPath*/, const TEntry &aEntry) const { - if (aEntry.IsDir()) - return ETrue; - //If no filter for files, all can be accepted - if (filterList.isEmpty()) + if (filterRxList.isEmpty()) return ETrue; - if (filterList == QStringList(QLatin1String("(*)"))) + if (aEntry.IsDir()) return ETrue; - for (int i = 0; i < filterList.size(); ++i) { - QString extension = filterList.at(i); - //remove '*' from the beginning of the extension - if (extension.at(0) == QLatin1Char('*')) - extension = extension.mid(1); - + foreach (QRegExp rx, filterRxList) { QString fileName = qt_TDesC2QString(aEntry.iName); - if (fileName.endsWith(extension)) + if (rx.exactMatch(fileName)) return ETrue; } + return EFalse; } private: - QStringList filterList; + QList filterRxList; }; #endif -- cgit v0.12 From ab38731fe5dcfaa1a7a70bc290a8856b5b01524d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 10 Feb 2011 15:01:58 +0100 Subject: My 4.7.2 changes --- dist/changes-4.7.2 | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index d351856..cf20e2e 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -39,8 +39,8 @@ Optimizations QtCore ------ - - foo - * bar + - QStateMachine + * [QTBUG-14491] Fix compilation on AIX 5.3 with gcc. QtGui ----- @@ -73,8 +73,23 @@ QtOpenGL QtScript -------- - - foo - * bar + - QScriptContext + * [QTBUG-17137] Fix crash when generating backtrace involving a + built-in (ECMA) function. + - QScriptEngine + * [QTBUG-16987] Ensure QScriptProgram objects are invalidated + when engine is destroyed. + * [QTBUG-16828] Fix alignment issue causing crashes on platforms + with only 4-byte-aligned malloc'ed memory (e.g. Symbian debug + builds). + * [QTBUG-15144] Fix GC-related crash in QScriptValue::setData(). + * [QTBUG-15079] Fix crash when QScriptClass property getter + returns an invalid value. + * [QTBUG-13440] Fix bug that caused Math.random() not to + produce random values. + - QScriptValue + * [QTBUG-14801] Fix crash in QScriptValue::construct() when + the function throws a non-Object value. QtSql ----- @@ -155,6 +170,11 @@ Qt for Symbian - QLineEdit * [QTBUG-16238] Fix one character displacement for cursor in line edits. + - QtScript + * [QTBUG-16685] Fix crash in JavaScript stack allocator. + * [QTBUG-15847] Add compiler optimizations. + * [QTBUG-14293] Enhanced JavaScript heap allocator. + - qmake & mkspecs * [QT-4193] Only add ICON for application projects in symbianpkgrules.pri * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate files. -- cgit v0.12 From abd0103ef31b1aad5bfa0e75ee0270d9342c92e7 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 10 Feb 2011 12:53:33 +1000 Subject: MouseArea docs - link to onCanceled() from onReleased() --- src/declarative/graphicsitems/qdeclarativemousearea.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 273fc53..0aa0c1b 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -314,6 +314,8 @@ QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate() position of the release of the click, and whether the click was held. The \e accepted property of the MouseEvent parameter is ignored in this handler. + + \sa onCanceled() */ /*! -- cgit v0.12 From 974db3ce58307069fcafdee2c5636ff72b061134 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 10 Feb 2011 15:31:17 +1000 Subject: Report any exceptions occurring in WorkerScript javascript code Task-number: QTBUG-17183 Change-Id: I709cca0bdce247ca9250c4f334654e2ff57b0b32 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativeworkerscript.cpp | 66 +++++++++++++++++++++- .../data/script_error_onCall.js | 6 ++ .../data/script_error_onLoad.js | 5 ++ .../data/worker_error_onCall.qml | 6 ++ .../data/worker_error_onLoad.qml | 7 +++ .../tst_qdeclarativeworkerscript.cpp | 52 +++++++++++++++++ 6 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js create mode 100644 tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js create mode 100644 tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml create mode 100644 tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index ac13c68..9721389 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -43,6 +43,7 @@ #include "private/qdeclarativelistmodel_p.h" #include "private/qdeclarativelistmodelworkeragent_p.h" #include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativeexpression_p.h" #include #include @@ -104,6 +105,19 @@ private: int m_id; }; +class WorkerErrorEvent : public QEvent +{ +public: + enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 }; + + WorkerErrorEvent(const QDeclarativeError &error); + + QDeclarativeError error() const; + +private: + QDeclarativeError m_error; +}; + class QDeclarativeWorkerScriptEnginePrivate : public QObject { Q_OBJECT @@ -146,6 +160,7 @@ public: WorkerScript(); int id; + QUrl source; bool initialized; QDeclarativeWorkerScript *owner; QScriptValue object; @@ -173,6 +188,7 @@ protected: private: void processMessage(int, const QVariant &); void processLoad(int, const QUrl &); + void reportScriptException(WorkerScript *); }; QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine) @@ -273,6 +289,11 @@ void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVarian args.setProperty(0, variantToScriptValue(data, workerEngine)); script->callback.call(script->object, args); + + if (workerEngine->hasUncaughtException()) { + reportScriptException(script); + workerEngine->clearExceptions(); + } } } @@ -286,7 +307,7 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) QFile f(fileName); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); - QString script = QString::fromUtf8(data); + QString sourceCode = QString::fromUtf8(data); QScriptValue activation = getWorker(id); @@ -296,10 +317,19 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) ctxt->pushScope(urlContext); ctxt->pushScope(activation); ctxt->setActivationObject(activation); - QDeclarativeScriptParser::extractPragmas(script); + QDeclarativeScriptParser::extractPragmas(sourceCode); workerEngine->baseUrl = url; - workerEngine->evaluate(script); + workerEngine->evaluate(sourceCode); + + WorkerScript *script = workers.value(id); + if (script) { + script->source = url; + if (workerEngine->hasUncaughtException()) { + reportScriptException(script); + workerEngine->clearExceptions(); + } + } workerEngine->popContext(); } else { @@ -307,6 +337,22 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) } } +void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script) +{ + if (!script || !workerEngine->hasUncaughtException()) + return; + + QDeclarativeError error; + QDeclarativeExpressionPrivate::exceptionToError(workerEngine, error); + error.setUrl(script->source); + + QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(workerEngine); + + QMutexLocker(&p->m_lock); + if (script->owner) + QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error)); +} + QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value) { if (value.isBool()) { @@ -453,6 +499,16 @@ int WorkerRemoveEvent::workerId() const return m_id; } +WorkerErrorEvent::WorkerErrorEvent(const QDeclarativeError &error) +: QEvent((QEvent::Type)WorkerError), m_error(error) +{ +} + +QDeclarativeError WorkerErrorEvent::error() const +{ + return m_error; +} + QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngine *parent) : QThread(parent), d(new QDeclarativeWorkerScriptEnginePrivate(parent)) { @@ -687,6 +743,10 @@ bool QDeclarativeWorkerScript::event(QEvent *event) emit message(value); } return true; + } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) { + WorkerErrorEvent *workerEvent = static_cast(event); + QDeclarativeEnginePrivate::warning(qmlEngine(this), workerEvent->error()); + return true; } else { return QObject::event(event); } diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js new file mode 100644 index 0000000..f589b0e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js @@ -0,0 +1,6 @@ +WorkerScript.onMessage = function(msg) { + var a = 123 + var b = 345 + var f = getData() +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js new file mode 100644 index 0000000..1d6eab2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js @@ -0,0 +1,5 @@ +WorkerScript.onMessage = function(msg) { + var a = 123 + aoij awef aljfaow eij +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml new file mode 100644 index 0000000..90c4617 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +BaseWorker { + source: "script_error_onCall.js" +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml new file mode 100644 index 0000000..0b9d21d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +BaseWorker { + source: "script_error_onLoad.js" +} + + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp index aaedd82..4b922fb 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp +++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -58,6 +60,13 @@ Q_DECLARE_METATYPE(QScriptValue) #define SRCDIR "." #endif +inline QUrl TEST_FILE(const QString &filename) +{ + QFileInfo fileInfo(__FILE__); + return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(filename)); +} + + class tst_QDeclarativeWorkerScript : public QObject { Q_OBJECT @@ -70,6 +79,8 @@ private slots: void messaging_sendQObjectList(); void messaging_sendJsObject(); void script_with_pragma(); + void scriptError_onLoad(); + void scriptError_onCall(); private: void waitForEchoMessage(QDeclarativeWorkerScript *worker) { @@ -215,6 +226,47 @@ void tst_QDeclarativeWorkerScript::script_with_pragma() delete worker; } +static QString qdeclarativeworkerscript_lastWarning; +static void qdeclarativeworkerscript_warningsHandler(QtMsgType type, const char *msg) +{ + if (type == QtWarningMsg) + qdeclarativeworkerscript_lastWarning = QString::fromUtf8(msg); +} + +void tst_QDeclarativeWorkerScript::scriptError_onLoad() +{ + QDeclarativeComponent component(&m_engine, SRCDIR "/data/worker_error_onLoad.qml"); + + QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler); + QDeclarativeWorkerScript *worker = qobject_cast(component.create()); + QVERIFY(worker != 0); + + QTRY_COMPARE(qdeclarativeworkerscript_lastWarning, + TEST_FILE("data/script_error_onLoad.js").toString() + QLatin1String(":3: SyntaxError: Parse error")); + + qInstallMsgHandler(previousMsgHandler); + qApp->processEvents(); + delete worker; +} + +void tst_QDeclarativeWorkerScript::scriptError_onCall() +{ + QDeclarativeComponent component(&m_engine, SRCDIR "/data/worker_error_onCall.qml"); + QDeclarativeWorkerScript *worker = qobject_cast(component.create()); + QVERIFY(worker != 0); + + QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler); + QVariant value; + QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value))); + + QTRY_COMPARE(qdeclarativeworkerscript_lastWarning, + TEST_FILE("data/script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: Can't find variable: getData")); + + qInstallMsgHandler(previousMsgHandler); + qApp->processEvents(); + delete worker; +} + QTEST_MAIN(tst_QDeclarativeWorkerScript) -- cgit v0.12 From 33512bc223be373975426ffcc6f8fa783a7582c9 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 11 Feb 2011 11:33:37 +1000 Subject: Make addImportPath() work for windows paths starting with lower case Was causing assert failure on windows if the 'c:' was lower case, since it was being added to the import path database with a lower case and thus later lookups with an upper case 'c:' would fail. This change fixes the check for whether the path refers to a local path or not. Task-number: QTBUG-16885 Change-Id: I0a2a2f705443ed453fb2b13f8599e035c2bd2877 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeimport.cpp | 6 ++++-- .../tst_qdeclarativemoduleplugin.cpp | 12 +++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 87183c4..244f2ad 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -952,7 +952,8 @@ void QDeclarativeImportDatabase::addPluginPath(const QString& path) qDebug().nospace() << "QDeclarativeImportDatabase::addPluginPath: " << path; QUrl url = QUrl(path); - if (url.isRelative() || url.scheme() == QLatin1String("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file") + || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path QDir dir = QDir(path); filePluginPath.prepend(dir.canonicalPath()); } else { @@ -974,7 +975,8 @@ void QDeclarativeImportDatabase::addImportPath(const QString& path) QUrl url = QUrl(path); QString cPath; - if (url.isRelative() || url.scheme() == QLatin1String("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file") + || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path QDir dir = QDir(path); cPath = dir.canonicalPath(); } else { diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 9ec0f84..8e31fd1 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -191,8 +191,18 @@ void tst_qdeclarativemoduleplugin::incorrectPluginCase() void tst_qdeclarativemoduleplugin::importPluginWithQmlFile() { + QString path = QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports"); + + // QTBUG-16885: adding an import path with a lower-case "c:" causes assert failure + // (this only happens if the plugin includes pure QML files) + #ifdef Q_OS_WIN + QVERIFY(path.at(0).isUpper() && path.at(1) == QLatin1Char(':')); + path = path.at(0).toLower() + path.mid(1); + #endif + QDeclarativeEngine engine; - engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + engine.addImportPath(path); + QDeclarativeComponent component(&engine, TEST_FILE("data/pluginWithQmlFile.qml")); foreach (QDeclarativeError err, component.errors()) qWarning() << err; -- cgit v0.12 From f4fedd8981bf89b690bc9167bf48c1cf5e5120f2 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Feb 2011 13:08:55 +1000 Subject: Flickable uses the flick velocity to determine whether to retain grab Flickable keeps the mouse grab if it was recently flicked and another flick is started before it has settled. However, it is using the velocity of the flick rather than the instantaneous velocity of the view, which causes it to be grabbed unless the view has come to a complete stop. Use smoothedVelocity which is updated during the view movement. Also increase the threshold a little. Change-Id: I970318680d38103468155fa566c489c7874d1b00 Task-number: QTBUG-17383 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativeflickable.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 87578b4..5d5fd0b 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -53,6 +53,10 @@ QT_BEGIN_NAMESPACE // before we perform a flick. static const int FlickThreshold = 20; +// RetainGrabVelocity is the maxmimum instantaneous velocity that +// will ensure the Flickable retains the grab on consecutive flicks. +static const int RetainGrabVelocity = 15; + QDeclarativeFlickableVisibleArea::QDeclarativeFlickableVisibleArea(QDeclarativeFlickable *parent) : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.) , m_yPosition(0.), m_heightRatio(0.) @@ -672,7 +676,8 @@ void QDeclarativeFlickable::setFlickableDirection(FlickableDirection direction) void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); - if (interactive && timeline.isActive() && (qAbs(hData.velocity) > 10 || qAbs(vData.velocity) > 10)) + if (interactive && timeline.isActive() + && (qAbs(hData.smoothVelocity.value()) > RetainGrabVelocity || qAbs(vData.smoothVelocity.value()) > RetainGrabVelocity)) stealMouse = true; // If we've been flicked then steal the click. else stealMouse = false; -- cgit v0.12 From 48b9220a1c53ccb6726147381e2ace41927d3b0d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 11 Feb 2011 14:54:16 +1000 Subject: Correct the "module not installed" error handling The not installed error will be issued if, after loading plugins and considering the contents of qmldir, there are no elements in the particular minor version. For example, if a plugin/qmldir provides the following types (either from C++ or as QML files specified in the qmldir file): Foo 1.1 Bar 1.3 importing versions 1.0, 1.2, or 1.4 will fail with the not installed error. Change-Id: I8566fda6918cb48936144e67a1ce75add0f160d8 Task-number: QTBUG-17324 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeimport.cpp | 25 ++++---- .../data/importsMixedQmlCppPlugin.2.qml | 21 +++++++ .../data/importsMixedQmlCppPlugin.qml | 13 ++++ .../data/versionNotInstalled.2.errors.txt | 1 + .../data/versionNotInstalled.2.qml | 5 ++ .../data/versionNotInstalled.errors.txt | 1 + .../data/versionNotInstalled.qml | 6 ++ .../com/nokia/AutoTestQmlMixedPluginType/Foo.qml | 5 ++ .../com/nokia/AutoTestQmlMixedPluginType/qmldir | 2 + .../com/nokia/AutoTestQmlVersionPluginType/qmldir | 1 + .../pluginMixed/plugin.cpp | 73 ++++++++++++++++++++++ .../pluginMixed/pluginMixed.pro | 9 +++ .../pluginVersion/plugin.cpp | 73 ++++++++++++++++++++++ .../pluginVersion/pluginVersion.pro | 9 +++ .../qdeclarativemoduleplugin.pro | 2 +- .../tst_qdeclarativemoduleplugin.cpp | 52 +++++++++++++++ 16 files changed, 285 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp create mode 100644 tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index 244f2ad..7a1234d 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -457,6 +457,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } QString url = uri; + bool versionFound = false; if (importType == QDeclarativeScriptParser::Import::Library) { url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; @@ -522,18 +523,18 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } } - if (!found) { - found = QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin); - if (!found) { - if (errorString) { - bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); - if (anyversion) - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); - else - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg); - } - return false; + if (QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin)) + versionFound = true; + + if (!versionFound && qmldircomponents.isEmpty()) { + if (errorString) { + bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); + if (anyversion) + *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + else + *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg); } + return false; } } else { @@ -578,7 +579,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url.chop(1); } - if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { + if (!versionFound && vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { QList::ConstIterator it = qmldircomponents.begin(); int lowest_maj = INT_MAX; int lowest_min = INT_MAX; diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml new file mode 100644 index 0000000..70b2bfd --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml @@ -0,0 +1,21 @@ +import com.nokia.AutoTestQmlMixedPluginType 1.5 +import QtQuick 1.0 + +Item { + property bool test: false + property bool test2: false + + Bar { + id: bar + } + + Foo { + id: foo + } + + Component.onCompleted: { + test = (bar.value == 16); + test2 = (foo.value == 89); + } +} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml new file mode 100644 index 0000000..da6ff46 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml @@ -0,0 +1,13 @@ +import com.nokia.AutoTestQmlMixedPluginType 1.0 +import QtQuick 1.0 + +Item { + property bool test: false + Bar { + id: bar + } + + Component.onCompleted: { + test = (bar.value == 16); + } +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt new file mode 100644 index 0000000..a40c1c8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt @@ -0,0 +1 @@ +1:1:module "com.nokia.AutoTestQmlVersionPluginType" version 1.9 is not installed diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml new file mode 100644 index 0000000..59fd084 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml @@ -0,0 +1,5 @@ +import com.nokia.AutoTestQmlVersionPluginType 1.9 +import QtQuick 1.0 + +QtObject { +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt new file mode 100644 index 0000000..2634223 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt @@ -0,0 +1 @@ +1:1:module "com.nokia.AutoTestQmlVersionPluginType" version 1.1 is not installed diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml new file mode 100644 index 0000000..2065c07 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml @@ -0,0 +1,6 @@ +import com.nokia.AutoTestQmlVersionPluginType 1.1 +import QtQuick 1.0 + +QtObject { +} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml new file mode 100644 index 0000000..ce51cbd --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +Item { + property int value: 89 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir new file mode 100644 index 0000000..065dc3b --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir @@ -0,0 +1,2 @@ +plugin pluginMixed +Foo 1.5 Foo.qml diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir new file mode 100644 index 0000000..640967f --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir @@ -0,0 +1 @@ +plugin pluginVersion diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp new file mode 100644 index 0000000..c7796e2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +class BarPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value); + +public: + int value() const { return 16; } +}; + + +class MyMixedPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyMixedPlugin() + { + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlMixedPluginType"); + qmlRegisterType(uri, 1, 0, "Bar"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro new file mode 100644 index 0000000..9766003 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlMixedPluginType + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp new file mode 100644 index 0000000..27a6341 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include +#include + +class FloorPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value); + +public: + int value() const { return 16; } +}; + + +class MyMixedPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyMixedPlugin() + { + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlVersionPluginType"); + qmlRegisterType(uri, 1, 4, "Floor"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro new file mode 100644 index 0000000..70a38b9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlVersionPluginType + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro index 9d0e94e..6e72d98 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro @@ -1,6 +1,6 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile +SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile pluginMixed pluginVersion tst_qdeclarativemoduleplugin_pro.depends += plugin SUBDIRS += tst_qdeclarativemoduleplugin.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 8e31fd1..dc104e2 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -63,10 +63,13 @@ private slots: void importsPlugin(); void importsPlugin2(); void importsPlugin21(); + void importsMixedQmlCppPlugin(); void incorrectPluginCase(); void importPluginWithQmlFile(); void remoteImportWithQuotedUrl(); void remoteImportWithUnquotedUri(); + void versionNotInstalled(); + void versionNotInstalled_data(); }; #ifdef Q_OS_SYMBIAN @@ -256,6 +259,55 @@ void tst_qdeclarativemoduleplugin::remoteImportWithUnquotedUri() VERIFY_ERRORS(0); } +// QTBUG-17324 +void tst_qdeclarativemoduleplugin::importsMixedQmlCppPlugin() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + + { + QDeclarativeComponent component(&engine, TEST_FILE("data/importsMixedQmlCppPlugin.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toBool(), true); + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("data/importsMixedQmlCppPlugin.2.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + delete o; + } + + +} + +void tst_qdeclarativemoduleplugin::versionNotInstalled_data() +{ + QTest::addColumn("file"); + QTest::addColumn("errorFile"); + + QTest::newRow("versionNotInstalled") << "data/versionNotInstalled.qml" << "versionNotInstalled.errors.txt"; + QTest::newRow("versionNotInstalled") << "data/versionNotInstalled.2.qml" << "versionNotInstalled.2.errors.txt"; +} + +void tst_qdeclarativemoduleplugin::versionNotInstalled() +{ + QFETCH(QString, file); + QFETCH(QString, errorFile); + + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + + QDeclarativeComponent component(&engine, TEST_FILE(file)); + VERIFY_ERRORS(errorFile.toLatin1().constData()); +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" -- cgit v0.12 From 2855782a45b08aedbed960125514fdd9663ff1c8 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Feb 2011 14:37:15 +0100 Subject: Rename 'plugins\qmldebugging' (work around qmake issues) On Windows, qmake places the tcpserver.dll in a 'plugins\qmlreleaseging' folder, which broke remote debugging of QtDeclarative completely. New name 'qmltooling' while being not so specific, avoids the use of 'debug' in the folder name. Task-number: QTBUG-17360 Reviewed-by: Martin Jones --- .../debugger/qdeclarativedebugserver.cpp | 2 +- src/plugins/plugins.pro | 2 +- src/plugins/qmldebugging/qmldebugging.pro | 4 - .../tcpserver/qtcpserverconnection.cpp | 173 --------------------- .../qmldebugging/tcpserver/qtcpserverconnection.h | 84 ---------- src/plugins/qmldebugging/tcpserver/tcpserver.pro | 18 --- src/plugins/qmltooling/qmltooling.pro | 4 + .../qmltooling/tcpserver/qtcpserverconnection.cpp | 173 +++++++++++++++++++++ .../qmltooling/tcpserver/qtcpserverconnection.h | 84 ++++++++++ src/plugins/qmltooling/tcpserver/tcpserver.pro | 18 +++ tools/qml/qml.pro | 4 +- 11 files changed, 283 insertions(+), 283 deletions(-) delete mode 100644 src/plugins/qmldebugging/qmldebugging.pro delete mode 100644 src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp delete mode 100644 src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h delete mode 100644 src/plugins/qmldebugging/tcpserver/tcpserver.pro create mode 100644 src/plugins/qmltooling/qmltooling.pro create mode 100644 src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp create mode 100644 src/plugins/qmltooling/tcpserver/qtcpserverconnection.h create mode 100644 src/plugins/qmltooling/tcpserver/tcpserver.pro diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp index a269984..ea3d9a3 100644 --- a/src/declarative/debugger/qdeclarativedebugserver.cpp +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -118,7 +118,7 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio QStringList pluginCandidates; const QStringList paths = QCoreApplication::libraryPaths(); foreach (const QString &libPath, paths) { - const QDir dir(libPath + QLatin1String("/qmldebugging")); + const QDir dir(libPath + QLatin1String("/qmltooling")); if (dir.exists()) { QStringList plugins(dir.entryList(QDir::Files)); foreach (const QString &pluginPath, plugins) { diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 07825d9..afa0901 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -14,4 +14,4 @@ embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio -contains(QT_CONFIG, declarative): SUBDIRS *= qmldebugging +contains(QT_CONFIG, declarative): SUBDIRS *= qmltooling diff --git a/src/plugins/qmldebugging/qmldebugging.pro b/src/plugins/qmldebugging/qmldebugging.pro deleted file mode 100644 index 01cf1a9..0000000 --- a/src/plugins/qmldebugging/qmldebugging.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS = tcpserver - diff --git a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp deleted file mode 100644 index 69c1ef5..0000000 --- a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtcpserverconnection.h" - -#include -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -class QTcpServerConnectionPrivate { -public: - QTcpServerConnectionPrivate(); - - int port; - QTcpSocket *socket; - QPacketProtocol *protocol; - QTcpServer *tcpServer; - - QDeclarativeDebugServer *debugServer; -}; - -QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() : - port(0), - socket(0), - protocol(0), - tcpServer(0), - debugServer(0) -{ -} - -QTcpServerConnection::QTcpServerConnection() : - d_ptr(new QTcpServerConnectionPrivate) -{ - -} - -QTcpServerConnection::~QTcpServerConnection() -{ - delete d_ptr; -} - -void QTcpServerConnection::setServer(QDeclarativeDebugServer *server) -{ - Q_D(QTcpServerConnection); - d->debugServer = server; -} - -bool QTcpServerConnection::isConnected() const -{ - Q_D(const QTcpServerConnection); - return d->socket && d->socket->state() == QTcpSocket::ConnectedState; -} - -void QTcpServerConnection::send(const QByteArray &message) -{ - Q_D(QTcpServerConnection); - - if (!isConnected()) - return; - - QPacket pack; - pack.writeRawData(message.data(), message.length()); - - d->protocol->send(pack); - d->socket->flush(); -} - -void QTcpServerConnection::disconnect() -{ - Q_D(QTcpServerConnection); - - delete d->protocol; - d->protocol = 0; - delete d->socket; - d->socket = 0; -} - -void QTcpServerConnection::setPort(int port, bool block) -{ - Q_D(QTcpServerConnection); - d->port = port; - - listen(); - if (block) - d->tcpServer->waitForNewConnection(-1); -} - -void QTcpServerConnection::listen() -{ - Q_D(QTcpServerConnection); - - d->tcpServer = new QTcpServer(this); - QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); - if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); - else - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); -} - - -void QTcpServerConnection::readyRead() -{ - Q_D(QTcpServerConnection); - QPacket packet = d->protocol->read(); - - QByteArray content = packet.data(); - d->debugServer->receiveMessage(content); -} - -void QTcpServerConnection::newConnection() -{ - Q_D(QTcpServerConnection); - - if (d->socket) { - qWarning("QDeclarativeDebugServer: Another client is already connected"); - QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); - delete faultyConnection; - return; - } - - d->socket = d->tcpServer->nextPendingConnection(); - d->socket->setParent(this); - d->protocol = new QPacketProtocol(d->socket, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - - -Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection) - -QT_END_NAMESPACE - diff --git a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h deleted file mode 100644 index a6e17e6..0000000 --- a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTCPSERVERCONNECTION_H -#define QTCPSERVERCONNECTION_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QDeclarativeDebugServer; -class QTcpServerConnectionPrivate; -class QTcpServerConnection : public QObject, public QDeclarativeDebugServerConnection -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QTcpServerConnection) - Q_DISABLE_COPY(QTcpServerConnection) - Q_INTERFACES(QDeclarativeDebugServerConnection) - - -public: - QTcpServerConnection(); - ~QTcpServerConnection(); - - void setServer(QDeclarativeDebugServer *server); - void setPort(int port, bool bock); - - bool isConnected() const; - void send(const QByteArray &message); - void disconnect(); - - void listen(); - void waitForConnection(); - -private Q_SLOTS: - void readyRead(); - void newConnection(); - -private: - QTcpServerConnectionPrivate *d_ptr; -}; - -QT_END_NAMESPACE - -#endif // QTCPSERVERCONNECTION_H diff --git a/src/plugins/qmldebugging/tcpserver/tcpserver.pro b/src/plugins/qmldebugging/tcpserver/tcpserver.pro deleted file mode 100644 index e90fb34..0000000 --- a/src/plugins/qmldebugging/tcpserver/tcpserver.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tcpserver -QT += declarative network - -include(../../qpluginbase.pri) - -QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmldebugging -QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)" - -SOURCES += \ - qtcpserverconnection.cpp - -HEADERS += \ - qtcpserverconnection.h - -target.path += $$[QT_INSTALL_PLUGINS]/qmldebugging -INSTALLS += target - -symbian:TARGET.UID3=0x20031E90 \ No newline at end of file diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro new file mode 100644 index 0000000..01cf1a9 --- /dev/null +++ b/src/plugins/qmltooling/qmltooling.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS = tcpserver + diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp new file mode 100644 index 0000000..69c1ef5 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtcpserverconnection.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QTcpServerConnectionPrivate { +public: + QTcpServerConnectionPrivate(); + + int port; + QTcpSocket *socket; + QPacketProtocol *protocol; + QTcpServer *tcpServer; + + QDeclarativeDebugServer *debugServer; +}; + +QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() : + port(0), + socket(0), + protocol(0), + tcpServer(0), + debugServer(0) +{ +} + +QTcpServerConnection::QTcpServerConnection() : + d_ptr(new QTcpServerConnectionPrivate) +{ + +} + +QTcpServerConnection::~QTcpServerConnection() +{ + delete d_ptr; +} + +void QTcpServerConnection::setServer(QDeclarativeDebugServer *server) +{ + Q_D(QTcpServerConnection); + d->debugServer = server; +} + +bool QTcpServerConnection::isConnected() const +{ + Q_D(const QTcpServerConnection); + return d->socket && d->socket->state() == QTcpSocket::ConnectedState; +} + +void QTcpServerConnection::send(const QByteArray &message) +{ + Q_D(QTcpServerConnection); + + if (!isConnected()) + return; + + QPacket pack; + pack.writeRawData(message.data(), message.length()); + + d->protocol->send(pack); + d->socket->flush(); +} + +void QTcpServerConnection::disconnect() +{ + Q_D(QTcpServerConnection); + + delete d->protocol; + d->protocol = 0; + delete d->socket; + d->socket = 0; +} + +void QTcpServerConnection::setPort(int port, bool block) +{ + Q_D(QTcpServerConnection); + d->port = port; + + listen(); + if (block) + d->tcpServer->waitForNewConnection(-1); +} + +void QTcpServerConnection::listen() +{ + Q_D(QTcpServerConnection); + + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} + + +void QTcpServerConnection::readyRead() +{ + Q_D(QTcpServerConnection); + QPacket packet = d->protocol->read(); + + QByteArray content = packet.data(); + d->debugServer->receiveMessage(content); +} + +void QTcpServerConnection::newConnection() +{ + Q_D(QTcpServerConnection); + + if (d->socket) { + qWarning("QDeclarativeDebugServer: Another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; + return; + } + + d->socket = d->tcpServer->nextPendingConnection(); + d->socket->setParent(this); + d->protocol = new QPacketProtocol(d->socket, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + + +Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection) + +QT_END_NAMESPACE + diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h new file mode 100644 index 0000000..a6e17e6 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCPSERVERCONNECTION_H +#define QTCPSERVERCONNECTION_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeDebugServer; +class QTcpServerConnectionPrivate; +class QTcpServerConnection : public QObject, public QDeclarativeDebugServerConnection +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTcpServerConnection) + Q_DISABLE_COPY(QTcpServerConnection) + Q_INTERFACES(QDeclarativeDebugServerConnection) + + +public: + QTcpServerConnection(); + ~QTcpServerConnection(); + + void setServer(QDeclarativeDebugServer *server); + void setPort(int port, bool bock); + + bool isConnected() const; + void send(const QByteArray &message); + void disconnect(); + + void listen(); + void waitForConnection(); + +private Q_SLOTS: + void readyRead(); + void newConnection(); + +private: + QTcpServerConnectionPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QTCPSERVERCONNECTION_H diff --git a/src/plugins/qmltooling/tcpserver/tcpserver.pro b/src/plugins/qmltooling/tcpserver/tcpserver.pro new file mode 100644 index 0000000..f4f2666 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/tcpserver.pro @@ -0,0 +1,18 @@ +TARGET = tcpserver +QT += declarative network + +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmltooling +QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)" + +SOURCES += \ + qtcpserverconnection.cpp + +HEADERS += \ + qtcpserverconnection.h + +target.path += $$[QT_INSTALL_PLUGINS]/qmltooling +INSTALLS += target + +symbian:TARGET.UID3=0x20031E90 \ No newline at end of file diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index 5d6192d..b1d56ea 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -39,8 +39,8 @@ symbian { TARGET.CAPABILITY = NetworkServices ReadUserData # Deploy plugin for remote debugging - qmldebuggingplugin.sources = $$QT_BUILD_TREE/plugins/qmldebugging/tcpserver$${QT_LIBINFIX}.dll - qmldebuggingplugin.path = c:$$QT_PLUGINS_BASE_DIR/qmldebugging + qmldebuggingplugin.sources = $$QT_BUILD_TREE/plugins/qmltooling/tcpserver$${QT_LIBINFIX}.dll + qmldebuggingplugin.path = c:$$QT_PLUGINS_BASE_DIR/qmltooling DEPLOYMENT += qmldebuggingplugin } mac { -- cgit v0.12 From 1c05257ed6de27c7d9dcc90f23f868035eb738e5 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 11 Feb 2011 13:51:48 +0100 Subject: Build Qt with GCCE 4.4.1, Symbian^3 PDK on Linux and Mac OS X. Remove the define of _STLP_NO_EXCEPTION_HEADER after OpenC team's suggestion. Remove the hardcoded include path for openc, it is already provided by mkspecs/features/symbian/platform_paths.prf. RevBy: Miikka Heikkinen Backport from 7c12d841fb2e2963b506c1ffc857cdd88bf78f6c in master. --- mkspecs/symbian/linux-gcce/qmake.conf | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mkspecs/symbian/linux-gcce/qmake.conf b/mkspecs/symbian/linux-gcce/qmake.conf index 4c346da..62cc9ae 100644 --- a/mkspecs/symbian/linux-gcce/qmake.conf +++ b/mkspecs/symbian/linux-gcce/qmake.conf @@ -50,8 +50,7 @@ QMAKE_LFLAGS_NOUNDEF = QMAKE_LFLAGS_RPATH = --rpath= DEFINES += __GCCE__ \ - UNICODE \ - _STLP_NO_EXCEPTION_HEADER + UNICODE QMAKE_LFLAGS_APP += --entry=_E32Startup -u _E32Startup QMAKE_LFLAGS_SHLIB += --default-symver --entry=_E32Dll -u _E32Dll @@ -89,7 +88,5 @@ INCLUDEPATH = ${EPOCROOT}/epoc32/include/ \ $${EPOCROOT}/epoc32/include/variant \ $${EPOCROOT}/epoc32/include/stdapis \ $${EPOCROOT}/epoc32/include/gcce \ - ${EPOCROOT}/epoc32/include/stdapis/sys \ - ${EPOCROOT}/epoc32/include/stdapis/stlport \ $$INCLUDEPATH -- cgit v0.12 From 46de2eb6aacc862b60cb01cc6a0c5e1775265099 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 11 Feb 2011 13:53:34 +0100 Subject: Apply the gcce link rules for LIBS_PRIVATE too. It's needed by building QtOpenGL of Qt for Symbian on Linux and Mac with gcce at least. RevBy: axis --- mkspecs/features/symbian/symbian_building.prf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/symbian/symbian_building.prf b/mkspecs/features/symbian/symbian_building.prf index f3b6c25..0d2e053 100644 --- a/mkspecs/features/symbian/symbian_building.prf +++ b/mkspecs/features/symbian/symbian_building.prf @@ -51,7 +51,7 @@ defineReplace(processSymbianLibrary) { } # This part turn "-llibc" into "libc.dso", and moves -L entries to QMAKE_LIBDIR. -libsToProcess = LIBS QMAKE_LIBS +libsToProcess = LIBS LIBS_PRIVATE QMAKE_LIBS for(libToProcess, libsToProcess) { qt_libraries = $$split($$libToProcess, " ") eval($$libToProcess =) @@ -90,8 +90,8 @@ count(splitVersion, 0) { } else { count(splitVersion, 3) { hexVersion = $$system("sh -c 'printf %02x $$member(splitVersion, 0)'") - hexPart2 = $$system("sh -c 'printf %02x $$member(splitVersion, 1)'")" - hexPart2 = $$hexPart2$$system("sh -c 'printf %02x $$member(splitVersion, 2)'")" + hexPart2 = $$system("sh -c 'printf %02x $$member(splitVersion, 1)'") + hexPart2 = $$hexPart2$$system("sh -c 'printf %02x $$member(splitVersion, 2)'") decVersion = $$system("sh -c 'printf %1d 0x$$hexVersion'"). hexVersion = $$hexVersion$$hexPart2 decVersion = $$decVersion$$system("sh -c 'printf %d 0x$$hexPart2'") -- cgit v0.12 From f7e75244ab62b1fe0d1d73b84a6089d6b2a81d1a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 11 Feb 2011 14:27:39 +0100 Subject: Designer: Slots of main container not visible in signal/slot editor. Fix a regression introduced by dd7873cd7e02e42b384709f33a34f69bc06fb25d of QTBUG-17179. Reviewed-by: Kai Koehne Task-number: QTBUG-17358 --- .../designer/src/components/signalsloteditor/signalslot_utils.cpp | 7 ++++++- .../src/components/signalsloteditor/signalsloteditorwindow.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp index d0af770..9f72816 100644 --- a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp +++ b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp @@ -244,7 +244,12 @@ namespace qdesigner_internal { ClassesMemberFunctions reverseClassesMemberFunctions(const QString &obj_name, MemberType member_type, const QString &peer, QDesignerFormWindowInterface *form) { - QObject *object = qFindChild(form->mainContainer(), obj_name); + QObject *object = 0; + if (obj_name == form->mainContainer()->objectName()) { + object = form->mainContainer(); + } else { + object = qFindChild(form->mainContainer(), obj_name); + } if (!object) return ClassesMemberFunctions(); QDesignerFormEditorInterface *core = form->core(); diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp index 831649f..6690948 100644 --- a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp +++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp @@ -658,8 +658,12 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const qdesigner_internal::ClassesMemberFunctions class_list = qdesigner_internal::reverseClassesMemberFunctions(obj_name, type, peer, m_form); - QObject *object = qFindChild(m_form->mainContainer(), obj_name); - + QObject *object = 0; + if (obj_name == m_form->mainContainer()->objectName()) { + object = m_form->mainContainer(); + } else { + object = qFindChild(m_form->mainContainer(), obj_name); + } inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("") : tr("")); foreach (const qdesigner_internal::ClassMemberFunctions &class_info, class_list) { if (class_info.m_className.isEmpty() || class_info.m_memberList.isEmpty()) -- cgit v0.12 From 3bc6f8d8dd630cd0298e27fc4b7430d2bf73a232 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 14 Feb 2011 14:25:15 +1000 Subject: Don't leak ScopeChainNode's Create a sub-scope of the global scope chain, rather than a completely new scope chain. Leaks are difficult to autotest, but an autotest for QScriptDeclarativeClass::pushCleanContext() was added to ensure its behavior doesn't regress. To reproduce the leak (prior to this change) use: while (true) { QScriptDeclarativeClass::pushCleanContext(&engine); engine.popContext(); } Change-Id: I41ac61ea1664da569eb329c8276f2a0bb6d2f1f7 Task-number: QTBUG-17166 Reviewed-by: Martin Jones --- src/script/api/qscriptengine.cpp | 4 +-- .../tst_qdeclarativeecmascript.cpp | 40 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 54039c0..e58c43b 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -2761,9 +2761,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV if (!clearScopeChain) { newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { - JSC::JSObject *jscObject = originalGlobalObject(); - JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject); - newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); + newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } } else { setContextFlags(newCallFrame, flags); diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index b19b3c9..40b0e1b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "testtypes.h" #include "testhttpserver.h" #include "../../../shared/util.h" @@ -174,6 +175,7 @@ private slots: void aliasBindingsAssignCorrectly(); void aliasBindingsOverrideTarget(); void aliasWritesOverrideBindings(); + void pushCleanContext(); void include(); @@ -3015,6 +3017,44 @@ void tst_qdeclarativeecmascript::revision() } } +// Test for QScriptDeclarativeClass::pushCleanContext() +void tst_qdeclarativeecmascript::pushCleanContext() +{ + QScriptEngine engine; + engine.globalObject().setProperty("a", 6); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + + // First confirm pushContext() behaves as we expect + QScriptValue object = engine.newObject(); + object.setProperty("a", 15); + QScriptContext *context1 = engine.pushContext(); + context1->pushScope(object); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + QScriptContext *context2 = engine.pushContext(); + Q_UNUSED(context2); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + QScriptValue func1 = engine.evaluate("(function() { return a; })"); + + // Now check that pushCleanContext() works + QScriptDeclarativeClass::pushCleanContext(&engine); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + QScriptValue func2 = engine.evaluate("(function() { return a; })"); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + + // Check that function objects created in these contexts work + QCOMPARE(func1.call().toInt32(), 15); + QCOMPARE(func2.call().toInt32(), 6); +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" -- cgit v0.12 From 984bc6626c4f290572ac721fd10edda99691306f Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 14 Feb 2011 10:12:21 +0100 Subject: Worked around a SC issue in S60 3.x vs 5.0 versions. Task: QTBUG-16578 RevBy: Gareth Stockwell --- src/gui/kernel/qwidget_s60.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 1551162..af9ae47 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -54,7 +54,6 @@ #ifdef Q_WS_S60 #include -#include #include #endif @@ -64,6 +63,19 @@ // CCoeControl objects until after the CONE event handler has finished running. Q_DECLARE_METATYPE(WId) +// Workaround for the fact that S60 SDKs 3.x do not contain the akntoolbar.h +// header, even though the documentation says that it should be there, and indeed +// it is present in the library. +class CAknToolbar : public CAknControl, + public MCoeControlObserver, + public MCoeControlBackground, + public MEikCommandObserver, + public MAknFadedComponent +{ +public: + IMPORT_C void SetToolbarVisibility(const TBool visible); +}; + QT_BEGIN_NAMESPACE extern bool qt_nograb(); -- cgit v0.12 From 0bf70c35bd51be4435c95f28dab96bf9f00b49db Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 14 Feb 2011 10:57:26 +0100 Subject: QStyleSheetStyle: dont crash in PE_WIDGET when widget is null Reviewed-by: Gabriel Task-number: QTBUG-15910 --- src/gui/styles/qstylesheetstyle.cpp | 2 +- tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 2b3dffc..a4e7c38 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4248,7 +4248,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasDrawable()) { + if (w && !rule.hasDrawable()) { QWidget *container = containerWidget(w); if (autoFillDisabledWidgets->contains(container) && (container == w || !renderRule(container, opt).hasBackground())) { diff --git a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp index f3e21a0..c386ffb 100644 --- a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -100,6 +100,7 @@ private slots: void task188195_baseBackground(); void task232085_spinBoxLineEditBg(); void changeStyleInChangeEvent(); + void QTBUG15910_crashNullWidget(); //at the end because it mess with the style. void widgetStyle(); @@ -1626,6 +1627,24 @@ void tst_QStyleSheetStyle::changeStyleInChangeEvent() wid.ensurePolished(); } +void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget() +{ + struct : QWidget { + virtual void paintEvent(QPaintEvent* ) { + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, 0); + style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, 0); + style()->drawControl(QStyle::CE_PushButton, &opt, &p, 0); + } + } w; + w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }"); + w.show(); + QTest::qWaitForWindowShown(&w); +} + + QTEST_MAIN(tst_QStyleSheetStyle) #include "tst_qstylesheetstyle.moc" -- cgit v0.12 From 220efa578b7d032257c7fa95aaf1295330fd474e Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 14 Feb 2011 13:29:14 +0100 Subject: Keep sending posted events after commit 7196045b78b33cf135683d5c0b4e164f95231791 This commit put in place a timer based mechanism to ensure that posted events continue to be sent. As pointed out in commit eb1015c7bbf135af3656110a4d112377c1209db8, GetQueueStatus() can indicate that there are messages in the queue but our hook never actually receives them, hence the timer solution. However, having the message type and hwnd "guards" in the conditional for starting a timer would cause us to lose events in some situations, due to the fact that QEventDispatcherWin32::processEvents() will only allow one WM_QT_SENDPOSTEDEVENTS message per call (multiple messages will be compressed into a single one). When racing with other threads, it would be possible to end up blocking one thread that has pending posted events unintentionally. This fix removes the guards and makes sure that we start the keep alive timer when it's really needed, and only stops it when we really know that there is nothing left in the Windows message queue. Task-number: QTBUG-17014 Reviewed-by: joao Reviewed-by: Marius Storm-Olsen --- src/corelib/kernel/qeventdispatcher_win.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index bba563a..6d90a51 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -530,10 +530,7 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); } } else if (d->sendPostedEventsWindowsTimerId == 0 - && localSerialNumber != d->lastSerialNumber - // if this message IS the one that triggers sendPostedEvents(), no need to post it again - && (msg->hwnd != d->internalHwnd - || msg->message != WM_QT_SENDPOSTEDEVENTS)) { + && localSerialNumber != d->lastSerialNumber) { // start a special timer to continue delivering posted events while // there are still input and timer messages in the message queue d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd, -- cgit v0.12 From 04ddaa986504e3842920770927cb7247e5e0fb78 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Mon, 14 Feb 2011 23:47:53 +0200 Subject: Fix for ARMV6 drawhelper blending Asm code used wrong source register when doing constant alpha blending. Task-number: QTBUG-16008 Reviewed-by: TRUSTME --- src/gui/painting/qdrawhelper_arm_simd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qdrawhelper_arm_simd.cpp b/src/gui/painting/qdrawhelper_arm_simd.cpp index 806df29..af9854c 100644 --- a/src/gui/painting/qdrawhelper_arm_simd.cpp +++ b/src/gui/painting/qdrawhelper_arm_simd.cpp @@ -201,8 +201,8 @@ argb32constalpha_next_pixel uxtb16 r10, r9 uxtb16 r6, r9, ror #8 - // Negate r11 and extract src alpha - mvn r9, r11 // bitwise not + // Negate r8 and extract src alpha + mvn r9, r8 // bitwise not uxtb r9, r9, ror #24 mla r10, r9, r10, r14 -- cgit v0.12 From 5f9f98ec047024fadbfdea334fbea7c357179032 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 11 Feb 2011 14:30:21 +1000 Subject: Fix inheritance of widget input contexts. If a parent widget has an input context assigned return that from QWidget::inputContext() before returning QApplication::inputContext(). Change-Id: I4982a91ace9b7485534f1c31fa4e2d549482640e Task-number: QTBUG-17390 Reviewed-by: axis --- src/gui/kernel/qwidget.cpp | 21 +++++++++++++---- src/gui/kernel/qwidget_p.h | 1 + tests/auto/qinputcontext/tst_qinputcontext.cpp | 32 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e542a59..7065e85 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -393,11 +393,24 @@ void QWidgetPrivate::scrollChildren(int dx, int dy) } } +QInputContext *QWidgetPrivate::assignedInputContext() const +{ +#ifndef QT_NO_IM + const QWidget *widget = q_func(); + while (widget) { + if (QInputContext *qic = widget->d_func()->ic) + return qic; + widget = widget->parentWidget(); + } +#endif + return 0; +} + QInputContext *QWidgetPrivate::inputContext() const { #ifndef QT_NO_IM - if (ic) - return ic; + if (QInputContext *qic = assignedInputContext()) + return qic; return qApp->inputContext(); #else return 0; @@ -10721,7 +10734,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); - QInputContext *ic = focusWidget->d_func()->ic; + QInputContext *ic = focusWidget->d_func()->assignedInputContext(); if (!ic && (!on || hasFocus())) ic = focusWidget->d_func()->inputContext(); if (ic) { @@ -11208,7 +11221,7 @@ void QWidget::updateMicroFocus() #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) Q_D(QWidget); // and optimization to update input context only it has already been created. - if (d->ic || qApp->d_func()->inputContext) { + if (d->assignedInputContext() || qApp->d_func()->inputContext) { QInputContext *ic = inputContext(); if (ic) ic->update(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 3759dd1..9f6ba6f 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -559,6 +559,7 @@ public: // sub-classes that their internals are about to be released. virtual void aboutToDestroy() {} + QInputContext *assignedInputContext() const; QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 800f9de..6a047f2 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -88,6 +88,7 @@ private slots: void closeSoftwareInputPanel(); void selections(); void focusProxy(); + void contextInheritance(); void symbianTestCoeFepInputContext_data(); void symbianTestCoeFepInputContext(); void symbianTestCoeFepAutoCommit_data(); @@ -473,6 +474,37 @@ void tst_QInputContext::focusProxy() QCOMPARE(gic->focusWidget(), &proxy); } +void tst_QInputContext::contextInheritance() +{ + QWidget parent; + QWidget child(&parent); + + parent.setAttribute(Qt::WA_InputMethodEnabled, true); + child.setAttribute(Qt::WA_InputMethodEnabled, true); + + QCOMPARE(parent.inputContext(), qApp->inputContext()); + QCOMPARE(child.inputContext(), qApp->inputContext()); + + QInputContext *qic = new QFilterInputContext; + parent.setInputContext(qic); + QCOMPARE(parent.inputContext(), qic); + QCOMPARE(child.inputContext(), qic); + + parent.setAttribute(Qt::WA_InputMethodEnabled, false); + QVERIFY(!parent.inputContext()); + QCOMPARE(child.inputContext(), qic); + parent.setAttribute(Qt::WA_InputMethodEnabled, true); + + parent.setInputContext(0); + QCOMPARE(parent.inputContext(), qApp->inputContext()); + QCOMPARE(child.inputContext(), qApp->inputContext()); + + qic = new QFilterInputContext; + qApp->setInputContext(qic); + QCOMPARE(parent.inputContext(), qic); + QCOMPARE(child.inputContext(), qic); +} + #ifdef QT_WEBKIT_LIB class AutoWebView : public QWebView { -- cgit v0.12 From fbd07cf7b756b903ab888785eb520cdbf64f38d4 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 15 Feb 2011 16:05:35 +1000 Subject: Document the TextInput accepted() signal. Change-Id: I30a36ba2724c9641e9cfe5ceafa651728907ef63 --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index dce7346..ddfa3aa 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -776,6 +776,15 @@ bool QDeclarativeTextInput::hasAcceptableInput() const } /*! + \qmlsignal TextInput::accepted() + + This signal is emitted when the Return or Enter key is pressed. + Note that if there is a \l validator or \l inputMask set on the text + input, the accepted signal will only be emitted if the input + is in an acceptable state. +*/ + +/*! \qmlproperty enumeration TextInput::echoMode Specifies how the text should be displayed in the TextInput. -- cgit v0.12 From 3997977cdb712042c540b143f2ce2f5376e9d1e0 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 15 Feb 2011 16:14:29 +1000 Subject: Use QML notation for documenting TextInput::accepted() signal. Use the name onAccepted() and refer to it as a handler rather than a signal. Change-Id: Ibd4144aa809e6d9db136187a07e9a660afa5df1b --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index ddfa3aa..88f36b4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -776,12 +776,12 @@ bool QDeclarativeTextInput::hasAcceptableInput() const } /*! - \qmlsignal TextInput::accepted() + \qmlsignal TextInput::onAccepted() - This signal is emitted when the Return or Enter key is pressed. + This handler is called when the Return or Enter key is pressed. Note that if there is a \l validator or \l inputMask set on the text - input, the accepted signal will only be emitted if the input - is in an acceptable state. + input, the handler will only be emitted if the input is in an acceptable + state. */ /*! -- cgit v0.12 From 0a84c39a92c4d4d7f2a5e19e949116df24219aa1 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Thu, 10 Feb 2011 22:28:12 +0200 Subject: Fix for clipping failure in OpenVG paint engine. OpenVG implementation for Broadcom chip has limited scissor rect count to 32. Because of that Qt OpenVG paint engine fails to clip correctly if clip rect count exceeds 32. This patch makes Qt OpenVG paint engine to use mask instead of scissors in such cases. Task-number: QTBUG-16932 Reviewed-by: Jason Barron --- src/openvg/qpaintengine_vg.cpp | 35 +++++++++++++++++++++++++++++++++-- src/openvg/qwindowsurface_vgegl.cpp | 3 --- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index a15f0c3..22cbbf5 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -2201,6 +2201,12 @@ void QVGPaintEngine::updateScissor() #if defined(QVG_SCISSOR_CLIP) // Using the scissor to do clipping, so combine the systemClip // with the current painting clipRegion. + + if (d->maskValid) { + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + } + QVGPainterState *s = state(); if (s->clipEnabled) { if (region.isEmpty()) @@ -2250,8 +2256,33 @@ void QVGPaintEngine::updateScissor() QVector rects = region.rects(); int count = rects.count(); - if (count > d->maxScissorRects) - count = d->maxScissorRects; + if (count > d->maxScissorRects) { +#if !defined(QVG_SCISSOR_CLIP) + count = d->maxScissorRects; +#else + // Use masking + int width = paintDevice()->width(); + int height = paintDevice()->height(); + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, + 0, 0, width, height); + for (int i = 0; i < rects.size(); ++i) { + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, + rects[i].x(), height - rects[i].y() - rects[i].height(), + rects[i].width(), rects[i].height()); + } + + vgSeti(VG_SCISSORING, VG_FALSE); + vgSeti(VG_MASKING, VG_TRUE); + d->maskValid = true; + d->maskIsSet = false; + d->scissorMask = false; + d->scissorActive = false; + d->scissorDirty = false; + d->scissorRegion = region; + return; +#endif + } + QVarLengthArray params(count * 4); int height = paintDevice()->height(); for (int i = 0; i < count; ++i) { diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp index c6db869..ca80886 100644 --- a/src/openvg/qwindowsurface_vgegl.cpp +++ b/src/openvg/qwindowsurface_vgegl.cpp @@ -267,10 +267,7 @@ static QEglContext *createContext(QPaintDevice *device) int redSize = configProps.value(EGL_RED_SIZE); if (redSize == EGL_DONT_CARE || redSize == 0) configProps.setPixelFormat(QImage::Format_ARGB32); // XXX -#ifndef QVG_SCISSOR_CLIP - // If we are using the mask to clip, then explicitly request a mask. configProps.setValue(EGL_ALPHA_MASK_SIZE, 1); -#endif #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT); -- cgit v0.12 From e340844bd614add505a39a3a6b915632476f6305 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 15 Feb 2011 11:19:26 +0100 Subject: Fix crash in KPackageKit QTreeViewPrivate::itemHeight() may refer to an invalid QModelIndex after calling QTreeView::indexRowSizeHint(). Same thing inside QTreeView::indexRowSizeHint(), since QHeaderView::count() will call QAbstractItemViewPrivate::executePostedLayout() which may invalidate all the QModelIndex. Reviewed-by: Olivier Task-number: QTBUG-16292 --- src/gui/itemviews/qtreeview.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index f1f3236..c0573bb 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2753,6 +2753,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int start = -1; int end = -1; + int indexRow = index.row(); int count = d->header->count(); bool emptyHeader = (count == 0); QModelIndex parent = index.parent(); @@ -2789,7 +2790,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int logicalColumn = emptyHeader ? column : d->header->logicalIndex(column); if (d->header->isSectionHidden(logicalColumn)) continue; - QModelIndex idx = d->model->index(index.row(), logicalColumn, parent); + QModelIndex idx = d->model->index(indexRow, logicalColumn, parent); if (idx.isValid()) { QWidget *editor = d->editorForIndex(idx).editor; if (editor && d->persistent.contains(editor)) { @@ -3224,14 +3225,14 @@ int QTreeViewPrivate::itemHeight(int item) const if (viewItems.isEmpty()) return 0; const QModelIndex &index = viewItems.at(item).index; + if (!index.isValid()) + return 0; int height = viewItems.at(item).height; - if (height <= 0 && index.isValid()) { + if (height <= 0) { height = q_func()->indexRowSizeHint(index); viewItems[item].height = height; } - if (!index.isValid() || height < 0) - return 0; - return height; + return qMax(height, 0); } -- cgit v0.12 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 89b754d30eaa5c9c57fb50bc563a3c60cc314c4e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 16 Feb 2011 10:29:50 +0100 Subject: Use QElapsedTimer in QFutureInterface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QElapsedTimer can also keep its on vlaid/invalid state, so we don't need to keep an additional boolean. Task-number: https://projects.maemo.org/bugzilla/show_bug.cgi?id=227660 Reviewed-by: Morten Sørvig --- src/corelib/concurrent/qfutureinterface.cpp | 9 +++++---- src/corelib/concurrent/qfutureinterface_p.h | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/corelib/concurrent/qfutureinterface.cpp b/src/corelib/concurrent/qfutureinterface.cpp index 6256944..627d0c7 100644 --- a/src/corelib/concurrent/qfutureinterface.cpp +++ b/src/corelib/concurrent/qfutureinterface.cpp @@ -421,9 +421,11 @@ bool QFutureInterfaceBase::referenceCountIsOne() const QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState) : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0), - state(initialState), progressTimeStarted(false), pendingResults(0), + state(initialState), pendingResults(0), manualProgress(false), m_expectedResultCount(0), runnable(0) -{ } +{ + progressTime.invalidate(); +} int QFutureInterfaceBasePrivate::internal_resultCount() const { @@ -455,12 +457,11 @@ bool QFutureInterfaceBasePrivate::internal_updateProgress(int progress, m_progressValue = progress; m_progressText = progressText; - if (progressTimeStarted == true && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted. + if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted. if (progressTime.elapsed() < (1000 / MaxProgressEmitsPerSecond)) return false; progressTime.start(); - progressTimeStarted = true; return true; } diff --git a/src/corelib/concurrent/qfutureinterface_p.h b/src/corelib/concurrent/qfutureinterface_p.h index 7f93c75..538947e 100644 --- a/src/corelib/concurrent/qfutureinterface_p.h +++ b/src/corelib/concurrent/qfutureinterface_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include +#include #include #include #include @@ -137,8 +137,7 @@ public: int m_progressMinimum; int m_progressMaximum; QFutureInterfaceBase::State state; - QTime progressTime; - bool progressTimeStarted; + QElapsedTimer progressTime; QWaitCondition pausedWaitCondition; int pendingResults; QtConcurrent::ResultStoreBase m_results; -- cgit v0.12 From df129c2449181869f0b95ae92d174b9eca52b2f7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 16 Feb 2011 11:06:08 +0100 Subject: Add a mutex to protect the access to the QSet. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In theory, there should be no problems with doing this unlocked, as the test should only run one thread at a time in this particular code section. In practice, if the test is failing, multiple threads would be modifying the QSet. So the mutex is necessary to detect the test failing. Reviewed-By: Morten Sørvig --- .../auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp index a6499ff..92e8608 100644 --- a/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +++ b/tests/auto/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp @@ -201,6 +201,7 @@ void tst_QtConcurrentIterateKernel::noIterations() startThreadEngine(new IterateKernel(0, 0)).startBlocking(); } +QMutex threadsMutex; QSet threads; class ThrottleFor : public IterateKernel { @@ -219,8 +220,10 @@ public: QThread *thread = QThread::currentThread(); - if (begin > 140 && end < 160) + if (begin > 140 && end < 160) { + QMutexLocker locker(&threadsMutex); threads.insert(thread); + } if (100 >= begin && 100 < end) { throttling = true; -- cgit v0.12 From 02f2ac6d090547f5b13534d77fe7761d6f236fb2 Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Wed, 16 Feb 2011 12:46:36 +0100 Subject: SSL: fix memory leak when loading certificates on Mac OS X Reviewed-by: Markus Goetz --- src/network/ssl/qsslsocket_openssl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 7d21bd3..84e14ff 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -780,6 +780,7 @@ QList QSslSocketPrivate::systemCaCertificates() systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der)); } } + CFRelease(cfCerts); } else { // no detailed error handling here -- cgit v0.12 From 899094da212e5bb1c3b9bce03b6c91d60cbdd13f Mon Sep 17 00:00:00 2001 From: Sami Merila Date: Wed, 16 Feb 2011 16:26:00 +0200 Subject: Introduce new flag for splitview support in Symbian Introduce new flag for splitview support as internal to Qt 4.7.2. The actual implementation will be delivered to Qt 4.7.3. Task-number: QTBUG-16572 Reviewed-by: Janne Koskinen --- src/corelib/global/qnamespace.h | 1 + src/corelib/global/qnamespace.qdoc | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index e492345..398f9bf 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -541,6 +541,7 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, + AA_S60DisablePartialScreenInputMode = 9, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 8440542..22382cd 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,6 +156,13 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \omitvalue AA_S60DisablePartialScreenInputMode By default in Symbian^3, + a separate editing window is opened on top of an application. This is exactly + like editing on previous versions of Symbian behave. When this attribute + is true, a virtual keyboard window is shown on top of application and it + is ensured that the focused text widget is visible. This is only supported in + Symbian^3. (internal) + \omitvalue AA_AttributeCount */ -- cgit v0.12 From 48e7ac0eee8beb9d2c597ff5fa3c913d56ffb9b0 Mon Sep 17 00:00:00 2001 From: Eckhart Koppen Date: Wed, 16 Feb 2011 17:34:00 +0200 Subject: Made Q_ASSERT meaningful again m_bytesPadding is an unsigned integer, assert would never have been triggered. Reviewed-by: TrustMe --- src/multimedia/audio/qaudiooutput_symbian_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index ea7cd9f..5db7099 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -436,8 +436,8 @@ void QAudioOutputPrivate::writePaddingData() unsigned char *ptr = const_cast(outputBuffer.Ptr()); Mem::FillZ(ptr, paddingBytes); outputBuffer.SetLength(outputBuffer.Length() + paddingBytes); + Q_ASSERT(m_bytesPadding >= paddingBytes); m_bytesPadding -= paddingBytes; - Q_ASSERT(m_bytesPadding >= 0); if (m_pullMode && m_source->atEnd()) lastBufferFilled(); -- 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 dfde84cccb14b109bebd672108a0ce0d6131361f Mon Sep 17 00:00:00 2001 From: Ademar de Souza Reis Jr Date: Wed, 16 Feb 2011 17:05:55 -0300 Subject: Bump QtWebKit version to 2.0.2 QtWebKit 2.0.1 was part of Qt-4.7.1, QtWebKit as included in 4.7.2 should be 2.0.2. Merge-request: 1095 Task-number: QTBUG-17480 Reviewed-by: Jason McDonald --- src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h index 63d9e55..2c0bf6d 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebkitglobal.h @@ -22,9 +22,9 @@ #include -#define QTWEBKIT_VERSION_STR "2.0.1" +#define QTWEBKIT_VERSION_STR "2.0.2" // QTWEBKIT_VERSION is (major << 16) + (minor << 8) + patch. Similar to Qt. -#define QTWEBKIT_VERSION 0x020001 +#define QTWEBKIT_VERSION 0x020002 // Use: #if (QTWEBKIT_VERSION >= QTWEBKIT_VERSION_CHECK(2, 0, 0)). Similar to Qt. #define QTWEBKIT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) -- cgit v0.12 From 924bcf1ccd9d25484fda8b8d68b8de7744a4693e Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 17 Feb 2011 12:15:48 +0200 Subject: Remove sqlite3.sis from qt.sis. Nokia Content Signing doesn't like embedded sis packages, so remove the embedded sqlite3.sis from qt.sis. It must now be installed separately just like Open C packages. Task-number: QTBUG-17399 Reviewed-by: axis --- doc/src/getting-started/installation.qdoc | 23 ++++++++++++++++------- doc/src/snippets/code/doc_src_installation.qdoc | 7 ++++--- src/s60installs/s60installs.pro | 17 ----------------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc index 4b4dab5..899ff49 100644 --- a/doc/src/getting-started/installation.qdoc +++ b/doc/src/getting-started/installation.qdoc @@ -874,9 +874,10 @@ If the installation fails, please make sure that there is no previously installed version of Qt on the phone. Qt requires some dependent packages to be installed on the device, -they are shipped in the Symbian SDK and can be installed using the -runonphone tool as well. -The packages can be found in the EPOCROOT at the following locations; +which can be installed using the runonphone tool as well. One is +the \c{sqlite3.sis}, which is included in the Qt distribution, while +the others are shipped with the Symbian SDK. The required packages +can be found from the following locations: \snippet doc/src/snippets/code/doc_src_installation.qdoc 50 @@ -1273,10 +1274,18 @@ We hope you will enjoy using Qt. in this release. \endlist - Running Qt on real device requires the Open C to be installed on the device. - The Open C installation packages are embedded into \c{qt_installer.sis}, which is included in - Qt for Symbian binary package. If you are building Qt from scratch, you can find the - required packages in the Symbian SDK where you installed Open C/C++: + Running Qt on real device requires the Open C and sqlite3 to be installed on the device. + These installation packages are embedded into \c{qt_installer.sis}, which is included in + Qt for Symbian binary package. + + If you are building Qt from scratch, you can find the sqlite3 package from + under your Qt installation: + + \list + \o \c{src\s60installs\sqlite3.sis} + \endlist + + The Open C packages you can find in the Symbian SDK where you installed Open C/C++: \list \o \c{nokia_plugin\openc\s60opencsis\pips_s60_.sis} \o \c{nokia_plugin\openc\s60opencsis\openc_ssl_s60_.sis} diff --git a/doc/src/snippets/code/doc_src_installation.qdoc b/doc/src/snippets/code/doc_src_installation.qdoc index 0374320..1a87566 100644 --- a/doc/src/snippets/code/doc_src_installation.qdoc +++ b/doc/src/snippets/code/doc_src_installation.qdoc @@ -328,9 +328,10 @@ runonphone -s myapp.sis myapp.exe //! [49] //! [50] -nokia_plugin/openc/s60opencsis/openc_ssl_s60_1_6_ss.sis -nokia_plugin/openc/s60opencsis/pips_s60_1_6_ss.sis -nokia_plugin/opencpp/s60opencppsis/stdcpp_s60_1_6_ss.sis +src/s60installs/sqlite3.sis +$EPOCROOT/nokia_plugin/openc/s60opencsis/openc_ssl_s60_1_6_ss.sis +$EPOCROOT/nokia_plugin/openc/s60opencsis/pips_s60_1_6_ss.sis +$EPOCROOT/nokia_plugin/opencpp/s60opencppsis/stdcpp_s60_1_6_ss.sis //! [50] diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index c282b1e..43cfd6b 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -11,23 +11,6 @@ symbian: { isEmpty(QT_LIBINFIX) { TARGET.UID3 = 0x2001E61C - - # Sqlite3 is expected to be already found on phone if infixed configuration is built. - # It is also expected that devices newer than those based on S60 5.0 all have sqlite3.dll. - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { - BLD_INF_RULES.prj_exports += \ - "sqlite3.sis /epoc32/data/qt/sis/sqlite3.sis" - symbian-abld|symbian-sbsv2 { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${EPOCROOT}epoc32/data/qt/sis/sqlite3.sis\", (0x2002af5f)" - } else { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${PWD}/sqlite3.sis\", (0x2002af5f)" - } - qtlibraries.pkg_postrules += sqlitedeployment - } } else { # Always use experimental UID for infixed configuration to avoid UID clash TARGET.UID3 = 0xE001E61C -- cgit v0.12 From b0822a83a3719ed32f6bf7f78c2ff1ba46837355 Mon Sep 17 00:00:00 2001 From: Tero Tiittanen Date: Thu, 17 Feb 2011 14:56:13 +0100 Subject: RGBA32 -> RGB565 dithering in Meego Graphicssystem, MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dithering in QMeeGoPixmapData::imageToEGLSharedImage is now done using Ordered Dithering, not anymore Floyd-Steinberg dithering. This provides better overall results. Fixes: NB#208927 - X dithering looks better than meego graphicssystem one Merge-request: 1079 Reviewed-by: Samuel Rødal --- src/plugins/graphicssystems/meego/dithering.cpp | 147 +++++++++--------------- 1 file changed, 52 insertions(+), 95 deletions(-) diff --git a/src/plugins/graphicssystems/meego/dithering.cpp b/src/plugins/graphicssystems/meego/dithering.cpp index 91e3337..2561c22 100644 --- a/src/plugins/graphicssystems/meego/dithering.cpp +++ b/src/plugins/graphicssystems/meego/dithering.cpp @@ -39,15 +39,22 @@ ** ****************************************************************************/ -// This is an implementation of the 32bit => 16bit Floyd-Steinberg dithering. +// Implements two dithering methods: +// +// * convertRGBA32_to_RGB565 +// +// This is implemented using Ordered Bayer Dithering. The code has been adapted +// from QX11PixmapData::fromImage. This method was originally implemented using +// Floyd-Steinberg dithering but was later changed to Ordered Dithering because +// of the better quality of the results. +// +// * convertRGBA32_to_RGBA4444 +// +// This is implemented using Floyd-Steinberg dithering. +// // The alghorithm used here is not the fastest possible but it's prolly fast enough: // uses look-up tables, integer-only arthmetics and works in one pass on two lines // at a time. It's a high-quality dithering using 1/8 diffusion precission. -// Two functions here to look at: -// -// * convertRGBA32_to_RGB565 -// * convertRGBA32_to_RGBA4444 -// // Each channel (RGBA) is diffused independently and alpha is dithered too. #include @@ -76,113 +83,63 @@ // Converts incoming RGB32 (QImage::Format_RGB32) to RGB565. Returns the newly allocated data. unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride) { + static bool thresholdMapInitialized = false; + static int thresholdMap[16][16]; + + if (!thresholdMapInitialized) { + int i; + int j; + int n; + + thresholdMap[0][0] = 0; + thresholdMap[1][0] = 2; + thresholdMap[0][1] = 3; + thresholdMap[1][1] = 1; + + for (n=2; n<16; n*=2) { + for (i=0; i 0) alignedWidth++; // Will store output - unsigned short *out = (unsigned short *) malloc(alignedWidth * height * 2); - - // Lookup tables for the 8bit => 6bit and 8bit => 5bit conversion - unsigned char lookup_8bit_to_5bit[256]; - short lookup_8bit_to_5bit_diff[256]; - unsigned char lookup_8bit_to_6bit[256]; - short lookup_8bit_to_6bit_diff[256]; - - // Macros for the conversion using the lookup table. - #define CONVERT_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit[v]) - #define DIFF_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit_diff[v]) - - #define CONVERT_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit[v]) - #define DIFF_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit_diff[v]) - - int i; - int x, y, c; // Pixel we're processing. c is component number (0, 1, 2 for r, b, b) - short component[3]; // Stores the new components (r, g, b) for pixel produced during conversion - short diff; // The difference between the converted value and the original one. To be accumulated. - QVarLengthArray accumulatorData(3 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. - short *accumulator[3]; // Helper for accessing the accumulator on a per-channel basis more easily. - accumulator[0] = accumulatorData.data(); - accumulator[1] = accumulatorData.data() + width; - accumulator[2] = accumulatorData.data() + (width * 2); - - // Produce the conversion lookup tables. - for (i = 0; i < 256; i++) { - lookup_8bit_to_5bit[i] = round(i / 8.0); - - // Before bitshifts: (i * 8) - (... * 8 * 8) - lookup_8bit_to_5bit_diff[i] = (i << 3) - (lookup_8bit_to_5bit[i] << 6); - if (lookup_8bit_to_5bit[i] > 31) - lookup_8bit_to_5bit[i] -= 1; - - lookup_8bit_to_6bit[i] = round(i / 4.0); - - // Before bitshifts: (i * 8) - (... * 4 * 8) - lookup_8bit_to_6bit_diff[i] = (i << 3) - (lookup_8bit_to_6bit[i] << 5); - if (lookup_8bit_to_6bit[i] > 63) - lookup_8bit_to_6bit[i] -= 1; - } + unsigned short *out = (unsigned short *)malloc (alignedWidth * height * 2); - // Clear the accumulators - memset(accumulator[0], 0, width * 4); - memset(accumulator[1], 0, width * 4); - memset(accumulator[2], 0, width * 4); + int x; + int y; + int threshold; // For each line... for (y = 0; y < height; y++) { - // For each accumulator, move the second line (index 1) to replace the first line (index 0). - // Clear the second line (index 1) - memcpy(accumulator[0], accumulator[0] + width, width * 2); - memset(accumulator[0] + width, 0, width * 2); - - memcpy(accumulator[1], accumulator[1] + width, width * 2); - memset(accumulator[1] + width, 0, width * 2); - - memcpy(accumulator[2], accumulator[2] + width, width * 2); - memset(accumulator[2] + width, 0, width * 2); - // For each column.... for (x = 0; x < width; x++) { - // For each component (r, g, b)... - for (c = 0; c < 3; c++) { + int r = GET_RGBA_COMPONENT(in, x, y, stride, 0); + int g = GET_RGBA_COMPONENT(in, x, y, stride, 1); + int b = GET_RGBA_COMPONENT(in, x, y, stride, 2); - // Get the 8bit value from the original image - component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); - - // Add the diffusion for this pixel we stored in the accumulator. - // >> 7 because the values in accumulator are stored * 128 - if (x != 0 && x != (width - 1)) { - if (accumulator[c][x] >> 7 != 0) - component[c] += rand() % accumulator[c][x] >> 7; - } - - // Make sure we're not over the boundaries. - CLAMP_256(component[c]); - - // For green component we use 6 bits. Otherwise 5 bits. - // Store the difference from converting 8bit => 6 bit and the orig pixel. - // Convert 8bit => 6(5) bit. - if (c == 1) { - diff = DIFF_8BIT_TO_6BIT(component[c]); - component[c] = CONVERT_8BIT_TO_6BIT(component[c]); - } else { - diff = DIFF_8BIT_TO_5BIT(component[c]); - component[c] = CONVERT_8BIT_TO_5BIT(component[c]); - } + threshold = thresholdMap[x%16][y%16]; - // Distribute the difference according to the matrix in the - // accumulation bufffer. - ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 3); - ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 3); - } + if (r <= (255-(1<<3)) && ((r<<5) & 255) > threshold) r += (1<<3); + if (g <= (255-(1<<2)) && ((g<<6) & 255) > threshold) g += (1<<2); + if (b <= (255-(1<<3)) && ((b<<5) & 255) > threshold) b += (1<<3); // Write the newly produced pixel - PUT_565(out, x, y, alignedWidth, component[2], component[1], component[0]); + PUT_565(out, x, y, alignedWidth, ((b >> 3) & 0x1f), ((g >> 2) & 0x3f), ((r >> 3) & 0x1f)); } } -- cgit v0.12 From baed5fdbc1d14e3190b9834f00be9926f9600d62 Mon Sep 17 00:00:00 2001 From: Denis Oliver Kropp Date: Thu, 17 Feb 2011 15:28:47 +0100 Subject: fix-layer-getsurface-result-check-for-screen-size-determination GetSurface() was checked for NOT returning DFB_OK, but it should Merge-request: 2528 Reviewed-by: Marcel Schuette --- src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 09cc465..ff15078 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1285,7 +1285,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); #elif (Q_DIRECTFB_VERSION >= 0x010000) IDirectFBSurface *layerSurface; - if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) { + if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) == DFB_OK) { result = layerSurface->GetSize(layerSurface, &w, &h); layerSurface->Release(layerSurface); } -- cgit v0.12 From 1b5ee40f491daf0f0b1d44b648ffb7b0ca8b8a63 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Feb 2011 11:23:17 +0100 Subject: Make the QtDBus parser not complain about unknown things Keep only the warnings about application errors. If the unknown things come from the outside, it's not our job to make noise. Task-number: QTBUG-17476 --- src/dbus/qdbusdemarshaller.cpp | 14 +++---- src/dbus/qdbusxmlparser.cpp | 52 +++++++++++++----------- tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp | 13 +++--- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index ab1455f..91dbf25 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -176,10 +176,10 @@ QDBusArgument::ElementType QDBusDemarshaller::currentType() case DBUS_TYPE_INVALID: return QDBusArgument::UnknownType; - default: - qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", - q_dbus_message_iter_get_arg_type(&iterator), - q_dbus_message_iter_get_arg_type(&iterator)); +// default: +// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", +// q_dbus_message_iter_get_arg_type(&iterator), +// q_dbus_message_iter_get_arg_type(&iterator)); } return QDBusArgument::UnknownType; } @@ -232,9 +232,9 @@ QVariant QDBusDemarshaller::toVariantInternal() return qVariantFromValue(duplicate()); default: - qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", - q_dbus_message_iter_get_arg_type(&iterator), - q_dbus_message_iter_get_arg_type(&iterator)); +// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", +// q_dbus_message_iter_get_arg_type(&iterator), +// q_dbus_message_iter_get_arg_type(&iterator)); return QVariant(); break; }; diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 1b99ced..413ebbe 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -52,6 +52,13 @@ #ifndef QT_NO_DBUS +//#define QDBUS_PARSER_DEBUG +#ifdef QDBUS_PARSER_DEBUG +# define qDBusParserError qWarning +#else +# define qDBusParserError if (true) {} else qDebug +#endif + QT_BEGIN_NAMESPACE static QDBusIntrospection::Annotations @@ -69,8 +76,8 @@ parseAnnotations(const QDomElement& elem) value = ann.attribute(QLatin1String("value")); if (!QDBusUtil::isValidInterfaceName(name)) { - qWarning("Invalid D-BUS annotation '%s' found while parsing introspection", - qPrintable(name)); + qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection", + qPrintable(name)); continue; } @@ -99,9 +106,8 @@ parseArgs(const QDomElement& elem, const QLatin1String& direction, bool acceptEm argData.name = arg.attribute(QLatin1String("name")); // can be empty argData.type = arg.attribute(QLatin1String("type")); if (!QDBusUtil::isValidSingleSignature(argData.type)) { - qWarning("Invalid D-BUS type signature '%s' found while parsing introspection", - qPrintable(argData.type)); - continue; + qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection", + qPrintable(argData.type)); } retval << argData; @@ -141,8 +147,8 @@ QDBusXmlParser::interfaces() const if (iface.isNull()) continue; // for whatever reason if (!QDBusUtil::isValidInterfaceName(ifaceName)) { - qWarning("Invalid D-BUS interface name '%s' found while parsing introspection", - qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection", + qPrintable(ifaceName)); continue; } @@ -166,8 +172,8 @@ QDBusXmlParser::interfaces() const if (method.isNull()) continue; if (!QDBusUtil::isValidMemberName(methodName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(methodName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(methodName), qPrintable(ifaceName)); continue; } @@ -192,8 +198,8 @@ QDBusXmlParser::interfaces() const if (signal.isNull()) continue; if (!QDBusUtil::isValidMemberName(signalName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(signalName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(signalName), qPrintable(ifaceName)); continue; } @@ -217,8 +223,8 @@ QDBusXmlParser::interfaces() const if (property.isNull()) continue; if (!QDBusUtil::isValidMemberName(propertyName)) { - qWarning("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(propertyName), qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", + qPrintable(propertyName), qPrintable(ifaceName)); continue; } @@ -231,9 +237,9 @@ QDBusXmlParser::interfaces() const if (!QDBusUtil::isValidSingleSignature(propertyData.type)) { // cannot be! - qWarning("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", - qPrintable(propertyData.type), qPrintable(ifaceName), - qPrintable(propertyName)); + qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", + qPrintable(propertyData.type), qPrintable(ifaceName), + qPrintable(propertyName)); continue; } @@ -245,9 +251,9 @@ QDBusXmlParser::interfaces() const else if (access == QLatin1String("readwrite")) propertyData.access = QDBusIntrospection::Property::ReadWrite; else { - qWarning("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", - qPrintable(access), qPrintable(ifaceName), - qPrintable(propertyName)); + qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", + qPrintable(access), qPrintable(ifaceName), + qPrintable(propertyName)); continue; // invalid one! } @@ -286,8 +292,8 @@ QDBusXmlParser::object() const if (obj.isNull()) continue; // for whatever reason if (!QDBusUtil::isValidObjectPath(m_path + QLatin1Char('/') + objName)) { - qWarning("Invalid D-BUS object path '%s/%s' found while parsing introspection", - qPrintable(m_path), qPrintable(objName)); + qDBusParserError("Invalid D-BUS object path '%s/%s' found while parsing introspection", + qPrintable(m_path), qPrintable(objName)); continue; } @@ -301,8 +307,8 @@ QDBusXmlParser::object() const if (iface.isNull()) continue; if (!QDBusUtil::isValidInterfaceName(ifaceName)) { - qWarning("Invalid D-BUS interface name '%s' found while parsing introspection", - qPrintable(ifaceName)); + qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection", + qPrintable(ifaceName)); continue; } diff --git a/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp b/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp index 25595c5..f83795c 100644 --- a/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp +++ b/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp @@ -287,11 +287,14 @@ void tst_QDBusXmlParser::methods_data() "" << map; // one invalid arg + method.inputArgs << arg("~", "invalid"); + map.clear(); + map << method; QTest::newRow("two-in-one-invalid") << "" "" - "" // this line should be ignored "" + "" "" << map; // one out argument @@ -380,8 +383,6 @@ void tst_QDBusXmlParser::methods() QFETCH(QString, xmlDataFragment); - if (strcmp(QTest::currentDataTag(), "two-in-one-invalid") == 0) - QTest::ignoreMessage(QtWarningMsg, "Invalid D-BUS type signature '~' found while parsing introspection"); QDBusIntrospection::Interface iface = QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter); @@ -390,9 +391,9 @@ void tst_QDBusXmlParser::methods() QFETCH(MethodMap, methodMap); MethodMap parsedMap = iface.methods; - QCOMPARE(methodMap.count(), parsedMap.count()); - QCOMPARE(methodMap, parsedMap); -} + QCOMPARE(parsedMap.count(), methodMap.count()); + QCOMPARE(parsedMap, methodMap); +} void tst_QDBusXmlParser::signals__data() { -- cgit v0.12 From 5b53b44a2be8478adeee4a9e4796345828ad0248 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Feb 2011 13:05:53 +0100 Subject: Autotest: add a new test for parsing an introspection with unknown types Task-number: QTBUG-17476 --- tests/auto/qdbusinterface/tst_qdbusinterface.cpp | 35 ++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index c1938b1..37e1c64 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -169,6 +169,25 @@ public slots: int MyObject::callCount = 0; QVariantList MyObject::callArgs; +class MyObjectUnknownType: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +}; + class Spy: public QObject { Q_OBJECT @@ -228,6 +247,7 @@ private slots: void notValidDerived(); void invalidAfterServiceOwnerChanged(); void introspect(); + void introspectUnknownTypes(); void callMethod(); void invokeMethod(); void invokeMethodWithReturn(); @@ -250,8 +270,7 @@ void tst_QDBusInterface::initTestCase() con.registerObject("/", &obj, QDBusConnection::ExportAllProperties | QDBusConnection::ExportAllSlots - | QDBusConnection::ExportAllInvokables - | QDBusConnection::ExportChildObjects); + | QDBusConnection::ExportAllInvokables); } void tst_QDBusInterface::notConnected() @@ -322,6 +341,18 @@ void tst_QDBusInterface::introspect() QVERIFY(mo->indexOfProperty("complexProp") != -1); } +void tst_QDBusInterface::introspectUnknownTypes() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + MyObjectUnknownType obj; + con.registerObject("/unknownTypes", &obj, QDBusConnection::ExportAllContents); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/unknownTypes"), + "com.trolltech.QtDBus.MyObjectUnknownTypes"); + + const QMetaObject *mo = iface.metaObject(); + QVERIFY(mo->indexOfMethod("regularMethod()") != -1); +} + void tst_QDBusInterface::callMethod() { QDBusConnection con = QDBusConnection::sessionBus(); -- cgit v0.12 From cc2db7a49c9208a00a913f7c4a410009814a5580 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Feb 2011 13:26:56 +0100 Subject: QtDBus meta object: keep methods, signals and props with unknown types Use VoidStar as the metatype, with an unknown type called "QDBusRawType". The actual D-Bus type is saved as an hex value as a template parameter. D-Bus type Qt type comment h QDBusRawType<0x68>* Unix file descriptors ~ QDBusRawType<0x7e>* invalid type ai QDBusRawType<0x6169>* array of int32 a{i(ssy)} QDBusRawType<0x617b6928737379297d>* Note that the number in the template doesn't have to be valid. The QDBusRawType class doesn't exist anyway. I thought of just leaving the raw D-Bus type there, but who knows what kind of things can appear there, like other '>' (which may cause problems for anything trying to parse the meta object later). Task-number: QTBUG-17476 --- src/dbus/qdbusmetaobject.cpp | 21 +++++++++++++-------- src/dbus/qdbusxmlparser.cpp | 1 - tests/auto/qdbusinterface/tst_qdbusinterface.cpp | 11 ++++++++++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 6683505..df8bc1d 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -193,14 +193,19 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, QByteArray typeName = annotations.value(annotationName).toLatin1(); // verify that it's a valid one - if (typeName.isEmpty()) - return result; // invalid - - type = QVariant::nameToType(typeName); - if (type == QVariant::UserType) - type = QMetaType::type(typeName); - if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) - return result; // unknown type is invalid too + if (!typeName.isEmpty()) { + // type name found + type = QVariant::nameToType(typeName); + if (type == QVariant::UserType) + type = QMetaType::type(typeName); + } + + if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) { + // type is still unknown or doesn't match back to the signature that it + // was expected to, so synthesize a fake type + type = QMetaType::VoidStar; + typeName = "QDBusRawType<0x" + signature.toHex() + ">*"; + } result.name = typeName; } else if (type == QVariant::Invalid) { diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 413ebbe..3feedde 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -240,7 +240,6 @@ QDBusXmlParser::interfaces() const qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", qPrintable(propertyData.type), qPrintable(ifaceName), qPrintable(propertyName)); - continue; } QString access = property.attribute(QLatin1String("access")); diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index 37e1c64..39f0677 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -350,7 +350,16 @@ void tst_QDBusInterface::introspectUnknownTypes() "com.trolltech.QtDBus.MyObjectUnknownTypes"); const QMetaObject *mo = iface.metaObject(); - QVERIFY(mo->indexOfMethod("regularMethod()") != -1); + QVERIFY(mo->indexOfMethod("regularMethod()") != -1); // this is the control + QVERIFY(mo->indexOfMethod("somethingHappened(QDBusRawType<0x7e>*)") != -1); + + QVERIFY(mo->indexOfMethod("ping(QDBusRawType<0x7e>*)") != -1); + int midx = mo->indexOfMethod("ping(QDBusRawType<0x7e>*)"); + QCOMPARE(mo->method(midx).typeName(), "QDBusRawType<0x7e>*"); + + QVERIFY(mo->indexOfProperty("prop1") != -1); + int pidx = mo->indexOfProperty("prop1"); + QCOMPARE(mo->property(pidx).typeName(), "QDBusRawType<0x7e>*"); } void tst_QDBusInterface::callMethod() -- cgit v0.12 From 1d8ebff955d357d3723487308e2906a12c6c043b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Feb 2011 14:38:35 +0100 Subject: QtDBus: Make sure we can receive unknown types We must make sure we advance the receiving iterator, or we end up in an infinite loop. Task-number: QTBUG-17476 --- src/dbus/qdbusdemarshaller.cpp | 7 +- tests/auto/qdbusmarshall/test/test.pro | 3 +- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 107 ++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 3 deletions(-) diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index 91dbf25..ac3b5fa 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -235,7 +235,12 @@ QVariant QDBusDemarshaller::toVariantInternal() // qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", // q_dbus_message_iter_get_arg_type(&iterator), // q_dbus_message_iter_get_arg_type(&iterator)); - return QVariant(); + char *ptr = 0; + ptr += q_dbus_message_iter_get_arg_type(&iterator); + q_dbus_message_iter_next(&iterator); + + // I hope you never dereference this pointer! + return QVariant::fromValue(ptr); break; }; } diff --git a/tests/auto/qdbusmarshall/test/test.pro b/tests/auto/qdbusmarshall/test/test.pro index 8901999..71fc656 100644 --- a/tests/auto/qdbusmarshall/test/test.pro +++ b/tests/auto/qdbusmarshall/test/test.pro @@ -5,4 +5,5 @@ TARGET = ../tst_qdbusmarshall QT = core QT += dbus - +LIBS += $$QT_LIBS_DBUS +QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index c05e49c..0d28dbd 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -38,7 +38,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#define DBUS_API_SUBJECT_TO_CHANGE #include #include #include @@ -47,6 +46,8 @@ #include "common.h" #include +#include + static const char serviceName[] = "com.trolltech.autotests.qpong"; static const char objectPath[] = "/com/trolltech/qpong"; static const char *interfaceName = serviceName; @@ -88,6 +89,9 @@ private slots: void sendCallErrors_data(); void sendCallErrors(); + void receiveUnknownType_data(); + void receiveUnknownType(); + private: QProcess proc; }; @@ -938,5 +942,106 @@ void tst_QDBusMarshall::sendCallErrors() QCOMPARE(reply.errorMessage(), errorMsg); } +void tst_QDBusMarshall::receiveUnknownType_data() +{ + QTest::newRow("in-call"); + QTest::newRow("type-variant"); + QTest::newRow("type-array"); + QTest::newRow("type-struct"); + QTest::newRow("type-naked"); +} + +void tst_QDBusMarshall::receiveUnknownType() +{ +#ifndef DBUS_TYPE_UNIX_FD + QSKIP("Your system's D-Bus library is too old for this test", SkipAll); +#else + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + // this needs to be implemented in raw + // open a new connection to the bus daemon + DBusError error; + dbus_error_init(&error); + DBusConnection *rawcon = dbus_bus_get_private(DBUS_BUS_SESSION, &error); + QVERIFY2(rawcon, error.name); + + // check if this bus supports passing file descriptors + if (!dbus_connection_can_send_type(rawcon, DBUS_TYPE_UNIX_FD)) + QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll); + + if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { + // create a call back to us containing a file descriptor + DBusMessage *msg = dbus_message_new_method_call(con.baseService().toLatin1(), "/irrelevant/path", NULL, "irrelevantMethod"); + + int fd = fileno(stdout); + dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); + + // try to send to us + DBusPendingCall *pending; + dbus_connection_send_with_reply(rawcon, msg, &pending, 1000); + dbus_message_unref(msg); + + // check that it got sent + while (dbus_connection_dispatch(rawcon) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now spin our event loop. We don't catch this call, so let's get the reply + QEventLoop loop; + QTimer::singleShot(200, &loop, SLOT(quit())); + loop.exec(); + + // now try to receive the reply + dbus_pending_call_block(pending); + msg = dbus_pending_call_steal_reply(pending); + dbus_pending_call_unref(pending); + QVERIFY(msg); + QCOMPARE(dbus_message_get_type(msg), DBUS_MESSAGE_TYPE_ERROR); + QCOMPARE(dbus_message_get_error_name(msg), "org.freedesktop.DBus.Error.UnknownObject"); + qDebug() << dbus_message_get_signature(msg); + } else { + // create a signal that we'll emit + static const char signalName[] = "signalName"; + static const char interfaceName[] = "local.interface.name"; + DBusMessage *msg = dbus_message_new_signal("/", interfaceName, signalName); + con.connect(dbus_bus_get_unique_name(rawcon), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); + + DBusMessageIter iter; + dbus_message_iter_init_append(msg, &iter); + int fd = fileno(stdout); + + if (qstrcmp(QTest::currentDataTag(), "type-naked") == 0) { + // send naked + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd); + } else { + DBusMessageIter subiter; + if (qstrcmp(QTest::currentDataTag(), "type-variant") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-array") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_UNIX_FD_AS_STRING, &subiter); + else if (qstrcmp(QTest::currentDataTag(), "type-struct") == 0) + dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, 0, &subiter); + dbus_message_iter_append_basic(&subiter, DBUS_TYPE_UNIX_FD, &fd); + dbus_message_iter_close_container(&iter, &subiter); + } + + // send it + dbus_connection_send(rawcon, msg, 0); + dbus_message_unref(msg); + + // check that it got sent + while (dbus_connection_dispatch(rawcon) == DBUS_DISPATCH_DATA_REMAINS) + ; + + // now let's see what happens + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + } + + dbus_connection_close(rawcon); + dbus_connection_unref(rawcon); +#endif +} + QTEST_MAIN(tst_QDBusMarshall) #include "tst_qdbusmarshall.moc" -- cgit v0.12 From ebdbd453a7612b3764b2e423ecb97aa9fb6cd28e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Feb 2011 15:01:40 +0100 Subject: Autotest: avoid memory leaks if test fails --- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 65 ++++++++++++++++---------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index 0d28dbd..6ad991b 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -951,6 +951,29 @@ void tst_QDBusMarshall::receiveUnknownType_data() QTest::newRow("type-naked"); } +struct DisconnectRawDBus { + static void cleanup(DBusConnection *connection) + { + if (!connection) + return; + dbus_connection_close(connection); + dbus_connection_unref(connection); + } +}; +template struct GenericUnref +{ + static void cleanup(T *type) + { + if (!type) return; + unref(type); + } +}; + +// use these scoped types to avoid memory leaks if QVERIFY or QCOMPARE fails +typedef QScopedPointer ScopedDBusConnection; +typedef QScopedPointer > ScopedDBusMessage; +typedef QScopedPointer > ScopedDBusPendingCall; + void tst_QDBusMarshall::receiveUnknownType() { #ifndef DBUS_TYPE_UNIX_FD @@ -963,27 +986,27 @@ void tst_QDBusMarshall::receiveUnknownType() // open a new connection to the bus daemon DBusError error; dbus_error_init(&error); - DBusConnection *rawcon = dbus_bus_get_private(DBUS_BUS_SESSION, &error); - QVERIFY2(rawcon, error.name); + ScopedDBusConnection rawcon(dbus_bus_get_private(DBUS_BUS_SESSION, &error)); + QVERIFY2(rawcon.data(), error.name); // check if this bus supports passing file descriptors - if (!dbus_connection_can_send_type(rawcon, DBUS_TYPE_UNIX_FD)) + if (!dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD)) QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll); if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { // create a call back to us containing a file descriptor - DBusMessage *msg = dbus_message_new_method_call(con.baseService().toLatin1(), "/irrelevant/path", NULL, "irrelevantMethod"); + ScopedDBusMessage msg(dbus_message_new_method_call(con.baseService().toLatin1(), "/irrelevant/path", NULL, "irrelevantMethod")); int fd = fileno(stdout); - dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); + dbus_message_append_args(msg.data(), DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); // try to send to us - DBusPendingCall *pending; - dbus_connection_send_with_reply(rawcon, msg, &pending, 1000); - dbus_message_unref(msg); + DBusPendingCall *pending_ptr; + dbus_connection_send_with_reply(rawcon.data(), msg.data(), &pending_ptr, 1000); + ScopedDBusPendingCall pending(pending_ptr); // check that it got sent - while (dbus_connection_dispatch(rawcon) == DBUS_DISPATCH_DATA_REMAINS) + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) ; // now spin our event loop. We don't catch this call, so let's get the reply @@ -992,22 +1015,20 @@ void tst_QDBusMarshall::receiveUnknownType() loop.exec(); // now try to receive the reply - dbus_pending_call_block(pending); - msg = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + dbus_pending_call_block(pending.data()); + msg.reset(dbus_pending_call_steal_reply(pending.data())); QVERIFY(msg); - QCOMPARE(dbus_message_get_type(msg), DBUS_MESSAGE_TYPE_ERROR); - QCOMPARE(dbus_message_get_error_name(msg), "org.freedesktop.DBus.Error.UnknownObject"); - qDebug() << dbus_message_get_signature(msg); + QCOMPARE(dbus_message_get_type(msg.data()), DBUS_MESSAGE_TYPE_ERROR); + QCOMPARE(dbus_message_get_error_name(msg.data()), "org.freedesktop.DBus.Error.UnknownObject"); } else { // create a signal that we'll emit static const char signalName[] = "signalName"; static const char interfaceName[] = "local.interface.name"; - DBusMessage *msg = dbus_message_new_signal("/", interfaceName, signalName); - con.connect(dbus_bus_get_unique_name(rawcon), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); + ScopedDBusMessage msg(dbus_message_new_signal("/", interfaceName, signalName)); + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); DBusMessageIter iter; - dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_init_append(msg.data(), &iter); int fd = fileno(stdout); if (qstrcmp(QTest::currentDataTag(), "type-naked") == 0) { @@ -1026,20 +1047,16 @@ void tst_QDBusMarshall::receiveUnknownType() } // send it - dbus_connection_send(rawcon, msg, 0); - dbus_message_unref(msg); + dbus_connection_send(rawcon.data(), msg.data(), 0); // check that it got sent - while (dbus_connection_dispatch(rawcon) == DBUS_DISPATCH_DATA_REMAINS) + while (dbus_connection_dispatch(rawcon.data()) == DBUS_DISPATCH_DATA_REMAINS) ; // now let's see what happens QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); } - - dbus_connection_close(rawcon); - dbus_connection_unref(rawcon); #endif } -- cgit v0.12 From a8a84f1667966acfa093c4be0b7d4b0900ddd3d9 Mon Sep 17 00:00:00 2001 From: Eckhart Koppen Date: Thu, 17 Feb 2011 17:49:48 +0200 Subject: Changed the localized vendor name for Qt SIS packages to "Nokia" The previously used name "Nokia, Qt" was not usable for Nokia Content Signing, which only allows "Nokia" as the visible vendor name. The unique vendor ID remains as "Nokia, Qt" Reviewed-by: TrustMe --- src/3rdparty/webkit/WebCore/WebCore.pro | 2 +- src/qbase.pri | 2 +- src/s60installs/s60installs.pro | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 981dba2..37d216d 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -15,7 +15,7 @@ symbian: { webkitlibs.path = /sys/bin vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/qbase.pri b/src/qbase.pri index 3a40928..75da3dc 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -190,7 +190,7 @@ symbian { # Partial upgrade SIS file vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index c282b1e..98a9ea9 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -92,7 +92,7 @@ symbian: { vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ -- cgit v0.12 From 00f689370ce97d557f8af4596c780f381aa66cb7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 17 Feb 2011 14:25:07 +0100 Subject: Fix warnings in QtDeclarative --- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 2 +- src/declarative/qml/qdeclarativeproperty.cpp | 2 +- src/declarative/qml/qdeclarativevaluetypescriptclass.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 2aa2059..dc3ecca 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -368,7 +368,7 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, newBinding = new QDeclarativeBinding(value, obj, evalContext); newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext)); - if (newBinding->expression().contains("this")) + if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 61e3002..0dd0edb 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -427,7 +427,7 @@ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const */ int QDeclarativeProperty::propertyType() const { - return d ? d->propertyType() : QVariant::Invalid; + return d ? d->propertyType() : int(QVariant::Invalid); } bool QDeclarativePropertyPrivate::isValueType() const diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index 200cc1c..4c312b5 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -184,7 +184,7 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); newBinding->setTarget(prop); - if (newBinding->expression().contains("this")) + if (newBinding->expression().contains(QLatin1String("this"))) newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); } -- cgit v0.12 From 426833486c3d801ec4dbce96407ec6e1e6c525f8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 17 Feb 2011 17:03:13 +0100 Subject: Autotest: be nicer to the subprocess and SIGTERM it --- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index 6ad991b..d0c9675 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -151,7 +151,8 @@ void tst_QDBusMarshall::initTestCase() void tst_QDBusMarshall::cleanupTestCase() { proc.close(); - proc.kill(); + proc.terminate(); + proc.waitForFinished(200); } void tst_QDBusMarshall::sendBasic_data() -- cgit v0.12 From 63bfd78b6a80f608f9b09254d815b6da04f8e2fc Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 16 Feb 2011 14:56:24 +0100 Subject: Autotest: don't use the deprecated signal from QDBusConnectionInterface --- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 56 ++++++++------------------ 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index d0c9675..0c53087 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -99,53 +99,29 @@ private: struct UnregisteredType { }; Q_DECLARE_METATYPE(UnregisteredType) -class WaitForQPong: public QObject -{ - Q_OBJECT -public: - WaitForQPong(); - bool ok(); -public Q_SLOTS: - void ownerChange(const QString &name) - { - if (name == serviceName) - loop.quit(); - } - -private: - QEventLoop loop; -}; - -WaitForQPong::WaitForQPong() -{ - QDBusConnection con = QDBusConnection::sessionBus(); - if (!ok()) { - connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), - SLOT(ownerChange(QString))); - QTimer::singleShot(2000, &loop, SLOT(quit())); - loop.exec(); - } -} - -bool WaitForQPong::ok() -{ - return QDBusConnection::sessionBus().isConnected() && - QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName); -} - void tst_QDBusMarshall::initTestCase() { commonInit(); + QDBusConnection con = QDBusConnection::sessionBus(); #ifdef Q_OS_WIN proc.start("qpong"); #else proc.start("./qpong/qpong"); #endif - QVERIFY(proc.waitForStarted()); - - WaitForQPong w; - QVERIFY(w.ok()); - //QTest::qWait(2000); + if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)) { + QVERIFY(proc.waitForStarted()); + + QVERIFY(con.isConnected()); + con.connect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)); + con.disconnect("org.freedesktop.DBus", QString(), "org.freedesktop.DBus", "NameOwnerChanged", + QStringList() << serviceName << QString(""), QString(), + &QTestEventLoop::instance(), SLOT(exitLoop())); + } } void tst_QDBusMarshall::cleanupTestCase() @@ -705,6 +681,8 @@ void tst_QDBusMarshall::sendBasic() msg << value; QDBusMessage reply = con.call(msg); + QVERIFY2(reply.type() == QDBusMessage::ReplyMessage, + qPrintable(reply.errorName() + ": " + reply.errorMessage())); //qDebug() << reply; QCOMPARE(reply.arguments().count(), msg.arguments().count()); -- cgit v0.12 From a6e1a7caeb7f03d1c102c250df8e602d5e40ab62 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Thu, 17 Feb 2011 18:37:15 +0100 Subject: Make Qt/DirectFB less verbose about failing to load pixmaps. Qt/DirectFB is way too verbose about not being able to use DirectFB for loading images. A lot of times DirectFB doesn't have support for e.g. pngs or gifs and currently one gets a message for every failed pixmap load, even if they will succeed when falling back to Qt. Merge-request: 2552 Reviewed-by: Marcel Schuette --- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 50e0f5f..eaff74a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -245,10 +245,9 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti QDirectFBPointer dataBuffer(dataBufferPtr); IDirectFBImageProvider *providerPtr; - if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) { - DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result); + if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) return false; - } + QDirectFBPointer provider(providerPtr); DFBImageDescription imageDescription; -- cgit v0.12 From 1a9ea90144c7131029fdf19950d1f313a64eb4a1 Mon Sep 17 00:00:00 2001 From: Denis Oliver Kropp Date: Thu, 17 Feb 2011 19:01:29 +0100 Subject: directfb: fix crash in client/server mode of qws The server was crashing due to client pointer being sent as "sibling". Instead surface flags are sent and sibling code is removed. Also the window ID is transfered and used on receiver side to get a local handle to the window. Click to focus window works, but it is not raised. Merge-request: 989 Reviewed-by: Marcel Schuette --- .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 46 +++++++++++++++------- .../gfxdrivers/directfb/qdirectfbwindowsurface.h | 1 - 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index d0056a7..3d8cf50 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) - , sibling(0) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif @@ -75,7 +74,6 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) : QWSWindowSurface(widget), QDirectFBPaintDevice(scr) - , sibling(0) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif @@ -123,7 +121,7 @@ void QDirectFBWindowSurface::raise() IDirectFBWindow *QDirectFBWindowSurface::directFBWindow() const { - return (dfbWindow ? dfbWindow : (sibling ? sibling->dfbWindow : 0)); + return dfbWindow; } void QDirectFBWindowSurface::createWindow(const QRect &rect) @@ -287,17 +285,40 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) QByteArray QDirectFBWindowSurface::permanentState() const { - QByteArray state(sizeof(this), 0); - *reinterpret_cast(state.data()) = this; + QByteArray state(sizeof(SurfaceFlags) + sizeof(DFBWindowID), 0); + char *ptr = state.data(); + SurfaceFlags flags = surfaceFlags(); + memcpy(ptr, &flags, sizeof(SurfaceFlags)); + ptr += sizeof(SurfaceFlags); + DFBWindowID did = (DFBWindowID)(-1); + if (dfbWindow) + dfbWindow->GetID(dfbWindow, &did); + memcpy(ptr, &did, sizeof(DFBWindowID)); return state; } void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { - if (state.size() == sizeof(this)) { - sibling = *reinterpret_cast(state.constData()); - Q_ASSERT(sibling); - setSurfaceFlags(sibling->surfaceFlags()); + const char *ptr = state.constData(); + IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer(); + SurfaceFlags flags; + memcpy(&flags, ptr, sizeof(SurfaceFlags)); + + setSurfaceFlags(flags); + ptr += sizeof(SurfaceFlags); + DFBWindowID id; + memcpy(&id, ptr, sizeof(DFBWindowID)); + if (dfbSurface) + dfbSurface->Release(dfbSurface); + if (id != (DFBWindowID)-1) { + IDirectFBWindow *dw; + layer->GetWindow(layer, id, &dw); + if (dw->GetSurface(dw, &dfbSurface) != DFB_OK) + dfbSurface = 0; + dw->Release(dw); + } + else { + dfbSurface = 0; } } @@ -406,8 +427,6 @@ void QDirectFBWindowSurface::endPaint(const QRegion &) IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const { - if (!dfbSurface && sibling && sibling->dfbSurface) - return sibling->dfbSurface; return dfbSurface; } @@ -415,11 +434,8 @@ IDirectFBSurface *QDirectFBWindowSurface::directFBSurface() const IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const { Q_ASSERT(widget); - if (!dfbSurface) { - if (sibling && (!sibling->sibling || sibling->dfbSurface)) - return sibling->surfaceForWidget(widget, rect); + if (!dfbSurface) return 0; - } QWidget *win = window(); Q_ASSERT(win); if (rect) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index f683fc8..75d462b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -100,7 +100,6 @@ private: void updateIsOpaque(); void setOpaque(bool opaque); void releaseSurface(); - QDirectFBWindowSurface *sibling; #ifdef QT_DIRECTFB_WM void createWindow(const QRect &rect); -- 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 346af37b7bc8d97ae4cc24b0a1cfe9cf4802057b Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Fri, 18 Feb 2011 12:16:04 +1000 Subject: Fix an issue with removing rows in a table model. Tables with nulls in a row were not being deleted properly in some cases. Made sure the responsible function no longer has default parameters so this doesn't happen again. Change-Id: I479121172d5ac172ca49da78638b9353d7a67548 Task-number: QTBUG-16007, QTBUG-15979 Reviewed-by: Charles Yin --- src/sql/models/qsqltablemodel.cpp | 4 ++-- src/sql/models/qsqltablemodel_p.h | 2 +- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 4df1d63..bf7c0aa 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -657,7 +657,7 @@ bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values) return false; } - return d->exec(stmt, prepStatement, rec); + return d->exec(stmt, prepStatement, rec, QSqlRecord() /* no where values */); } /*! @@ -695,7 +695,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) } stmt.append(QLatin1Char(' ')).append(where); - return d->exec(stmt, prepStatement, whereValues); + return d->exec(stmt, prepStatement, QSqlRecord() /* no new values */, whereValues); } /*! diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index d2b96e6..f4f3811 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -75,7 +75,7 @@ public: QSqlRecord record(const QVector &values) const; bool exec(const QString &stmt, bool prepStatement, - const QSqlRecord &rec, const QSqlRecord &whereValues = QSqlRecord()); + const QSqlRecord &rec, const QSqlRecord &whereValues); virtual void revertCachedRow(int row); void revertInsertedRow(); bool setRecord(int row, const QSqlRecord &record); diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index f7d2180..bf68375 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -773,6 +773,27 @@ void tst_QSqlTableModel::removeInsertedRow() QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + // Now insert a row with a null, and check that removing it also works (QTBUG-15979 etc) + model.insertRow(1); + model.setData(model.index(1,0), 55); + model.setData(model.index(1,1), QString("null columns")); + model.setData(model.index(1,2), QVariant()); + + model.submitAll(); + + QCOMPARE(model.rowCount(), 4); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 55); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns")); + QCOMPARE(model.data(model.index(3, 2)).isNull(), true); + + QVERIFY(model.removeRow(3)); + model.submitAll(); + QCOMPARE(model.rowCount(), 3); + + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); } void tst_QSqlTableModel::removeInsertedRows() -- 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 From 23f9cec65a76e6aa0675ca426f9e4f6717790dbb Mon Sep 17 00:00:00 2001 From: Niklas Kurkisuo Date: Fri, 18 Feb 2011 09:30:46 +0100 Subject: QImage crash when invalid XPM is read. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sanity check for cpp, which would otherwise lead to a segfault later in the code. Task-number: QTBUG-17254 Merge-request: 1080 Reviewed-by: Samuel Rødal --- src/gui/image/qxpmhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index a02b3ff..76cd813 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -882,7 +882,7 @@ static bool read_xpm_body( QByteArray buf(200, 0); int i; - if (cpp > 15) + if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until -- cgit v0.12 From db9925a187a9ad395ba2cabf23487b9a0e09c67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 18 Feb 2011 09:25:50 +0100 Subject: Added test case for corrupt pixel count in XPM image. Fixed by merge request 1080. Task-number: QTBUG-17254 --- tests/auto/qimagereader/images/corrupt-pixel-count.xpm | 11 +++++++++++ tests/auto/qimagereader/tst_qimagereader.cpp | 3 +++ 2 files changed, 14 insertions(+) create mode 100644 tests/auto/qimagereader/images/corrupt-pixel-count.xpm diff --git a/tests/auto/qimagereader/images/corrupt-pixel-count.xpm b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm new file mode 100644 index 0000000..3a736ff --- /dev/null +++ b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm @@ -0,0 +1,11 @@ +/* XPM */ +static const char *marble_xpm[] = { +/* width height num_colors chars_per_pixel */ +"2 2 2 -2", +/* colors */ +"a c #adadad", +"b c #dedede", +/* pixels */ +"ab", +"ba" +}; diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 69e8ead..5321864 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -1399,6 +1399,9 @@ void tst_QImageReader::readFromResources_data() QTest::newRow("corrupt-pixels.xpm") << QString("corrupt-pixels.xpm") << QByteArray("xpm") << QSize(0, 0) << QString("QImage: XPM pixels missing on image line 3"); + QTest::newRow("corrupt-pixel-count.xpm") << QString("corrupt-pixel-count.xpm") + << QByteArray("xpm") << QSize(0, 0) + << QString(""); QTest::newRow("marble.xpm") << QString("marble.xpm") << QByteArray("xpm") << QSize(240, 240) << QString(""); -- cgit v0.12 From d6c1e5d78bdfbeb373970b65d8260f7e9f9ce1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauri=20Vehni=C3=A4inen?= Date: Fri, 18 Feb 2011 10:10:08 +0100 Subject: Prevents crashing when ICO file has bad color table value When color table value is read from ICO header memory allocation is made based on this value. This case is relevant only when reading 8bit images. Therefore values over 256 will abort reading the image. Task-number: QT-4535 Merge-request: 1090 Reviewed-by: Harald Fernengel --- src/plugins/imageformats/ico/qicohandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 5aa26d3..701207d 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -559,6 +559,8 @@ QImage ICOReader::iconAt(int index) icoAttrib.ncolors = 0; else // # colors used icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits; + if (icoAttrib.ncolors > 256) //color table can't be more than 256 + return img; icoAttrib.w = iconEntry.bWidth; if (icoAttrib.w == 0) icoAttrib.w = header.biWidth; -- cgit v0.12 From 5949c215bd53582d0c6481f606a9ec015f067b37 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 18 Feb 2011 10:19:58 +0100 Subject: Cocoa: fix crash when using a drawer with a focus widget The crash happends when you close down an application that has a drawer that contains a widget with keyboard focus. The NSView backing this widget is then the first responder in Cocoa. This bug was a bit more hard-boiled than usual, and I can't say I truly understand whats going on. My findings are that both the drawer and the parent window both points to the same view inside the drawer as its first responder. And when deleting the drawer (togheter with the focus widget), the parent window is left pointing to a first responder that is actually deleted. Is seems that us refusing to release a view as first responder if we have no attached widget is wrong. So we choose to return YES instead, which after all makes much more sense. Task-number: QTBUG-15897 Reviewed-by: msorvig --- src/gui/kernel/qcocoaview_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 749472a..d9f428c 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -1115,7 +1115,7 @@ static int qCocoaViewCount = 0; - (BOOL)resignFirstResponder { if (!qwidget) - return NO; + return YES; // Seems like the following test only triggers if this // view is inside a QMacNativeWidget: if (qwidget == QApplication::focusWidget()) -- cgit v0.12 From c658394f1b34c98b141eff22a69a3f4c7bbd4c51 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Fri, 18 Feb 2011 22:03:55 +1000 Subject: Attempt to fix symbian 3.1 and 3.2 compile break. e46c44f9538dbe5b44ce61d3a42403cfa471ae8b restructured qml.pri. In the original version the else part at the bottom of the file was processed for Symbian 3.1 and 3.2, but the commit stopped that from happening. This commit makes the minimal change to make the statements in the else part apply to 3.1 and 3.2 again. Really the file should be restructured to have separate logic for setting each vairable, but I'll leave that task for the developers. Reviewed-by: Eckhart Koppen --- tools/qml/qml.pri | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri index 08cd506..650de94 100644 --- a/tools/qml/qml.pri +++ b/tools/qml/qml.pri @@ -19,17 +19,21 @@ SOURCES += $$PWD/qmlruntime.cpp \ RESOURCES = $$PWD/browser/browser.qrc \ $$PWD/startup/startup.qrc -symbian: { - contains(QT_CONFIG, s60): { +symbian { + contains(QT_CONFIG, s60) { LIBS += -lavkon -lcone } !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { LIBS += -lsensrvclient -lsensrvutil } - !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2): { + !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { SOURCES += $$PWD/deviceorientation_symbian.cpp FORMS = $$PWD/recopts.ui \ $$PWD/proxysettings.ui + } else { + SOURCES += $$PWD/deviceorientation.cpp + FORMS = $$PWD/recopts.ui \ + $$PWD/proxysettings.ui } } else:maemo5 { QT += dbus -- cgit v0.12 From 7b6b9201bdc6435aaa50370c8cf511e47f6e630d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 16 Feb 2011 14:05:54 +0100 Subject: Autotest: check that the type received is the expected one Task-number: QTBUG-17476 --- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 51 ++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index 0c53087..9bae6af 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -96,6 +96,19 @@ private: QProcess proc; }; +class QDBusMessageSpy: public QObject +{ + Q_OBJECT +public slots: + Q_SCRIPTABLE int theSlot(const QDBusMessage &msg) + { + list << msg; + return 42; + } +public: + QList list; +}; + struct UnregisteredType { }; Q_DECLARE_METATYPE(UnregisteredType) @@ -923,11 +936,12 @@ void tst_QDBusMarshall::sendCallErrors() void tst_QDBusMarshall::receiveUnknownType_data() { - QTest::newRow("in-call"); - QTest::newRow("type-variant"); - QTest::newRow("type-array"); - QTest::newRow("type-struct"); - QTest::newRow("type-naked"); + QTest::addColumn("receivedTypeId"); + QTest::newRow("in-call") << qMetaTypeId(); + QTest::newRow("type-variant") << qMetaTypeId(); + QTest::newRow("type-array") << qMetaTypeId(); + QTest::newRow("type-struct") << qMetaTypeId(); + QTest::newRow("type-naked") << qMetaTypeId(); } struct DisconnectRawDBus { @@ -974,7 +988,9 @@ void tst_QDBusMarshall::receiveUnknownType() if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { // create a call back to us containing a file descriptor - ScopedDBusMessage msg(dbus_message_new_method_call(con.baseService().toLatin1(), "/irrelevant/path", NULL, "irrelevantMethod")); + QDBusMessageSpy spy; + con.registerObject("/spyObject", &spy, QDBusConnection::ExportAllSlots); + ScopedDBusMessage msg(dbus_message_new_method_call(con.baseService().toLatin1(), "/spyObject", NULL, "theSlot")); int fd = fileno(stdout); dbus_message_append_args(msg.data(), DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); @@ -995,10 +1011,21 @@ void tst_QDBusMarshall::receiveUnknownType() // now try to receive the reply dbus_pending_call_block(pending.data()); + + // check that the spy received what it was supposed to receive + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().size(), 1); + QFETCH(int, receivedTypeId); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); + msg.reset(dbus_pending_call_steal_reply(pending.data())); QVERIFY(msg); - QCOMPARE(dbus_message_get_type(msg.data()), DBUS_MESSAGE_TYPE_ERROR); - QCOMPARE(dbus_message_get_error_name(msg.data()), "org.freedesktop.DBus.Error.UnknownObject"); + QCOMPARE(dbus_message_get_type(msg.data()), DBUS_MESSAGE_TYPE_METHOD_RETURN); + QCOMPARE(dbus_message_get_signature(msg.data()), DBUS_TYPE_INT32_AS_STRING); + + int retval; + QVERIFY(dbus_message_get_args(msg.data(), &error, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID)); + QCOMPARE(retval, 42); } else { // create a signal that we'll emit static const char signalName[] = "signalName"; @@ -1006,6 +1033,9 @@ void tst_QDBusMarshall::receiveUnknownType() ScopedDBusMessage msg(dbus_message_new_signal("/", interfaceName, signalName)); con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &QTestEventLoop::instance(), SLOT(exitLoop())); + QDBusMessageSpy spy; + con.connect(dbus_bus_get_unique_name(rawcon.data()), QString(), interfaceName, signalName, &spy, SLOT(theSlot(QDBusMessage))); + DBusMessageIter iter; dbus_message_iter_init_append(msg.data(), &iter); int fd = fileno(stdout); @@ -1035,6 +1065,11 @@ void tst_QDBusMarshall::receiveUnknownType() // now let's see what happens QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(spy.list.size(), 1); + QCOMPARE(spy.list.at(0).arguments().count(), 1); + QFETCH(int, receivedTypeId); + //qDebug() << spy.list.at(0).arguments().at(0).typeName(); + QCOMPARE(spy.list.at(0).arguments().at(0).userType(), receivedTypeId); } #endif } -- cgit v0.12 From d6e509936358141b1fef93852edd10b3b324ec5b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 19 Feb 2011 13:53:41 +0100 Subject: Doc: setSslConfiguration also sets the CA certificates --- src/network/access/qnetworkrequest.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 89f7d44..7eec24e 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -529,8 +529,9 @@ QSslConfiguration QNetworkRequest::sslConfiguration() const /*! Sets this network request's SSL configuration to be \a config. The settings that apply are the private key, the local certificate, - the SSL protocol (SSLv2, SSLv3, TLSv1 where applicable) and the - ciphers that the SSL backend is allowed to use. + the SSL protocol (SSLv2, SSLv3, TLSv1 where applicable), the CA + certificates and the ciphers that the SSL backend is allowed to + use. By default, no SSL configuration is set, which allows the backends to choose freely what configuration is best for them. -- cgit v0.12 From ef06cbef2e3240d49848f398b2d19adbbea1e781 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 19 Feb 2011 11:46:22 +0100 Subject: Fix warning about id maybe used when uninitialised The code would indicate it's never used uninitialised, but gcc doesn't know it. --- src/declarative/util/qdeclarativepropertychanges.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index ccd122e..9bcb263 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -281,7 +281,7 @@ QDeclarativePropertyChangesParser::compile(const QList(data.at(ii).second); QVariant var; bool isScript = v.isScript(); - QDeclarativeBinding::Identifier id; + QDeclarativeBinding::Identifier id = 0; switch(v.type()) { case QDeclarativeParser::Variant::Boolean: var = QVariant(v.asBoolean()); -- cgit v0.12 From 13e9642616ab480d09bda2603cc89dcaea7a1ad6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 20 Feb 2011 15:37:06 +0100 Subject: Autotest: make at least one update before checking if more are needed The timer gets started only by making updates. If you try to check if an update is needed without making the first update, the timer won't be started and the function will return false. --- tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp index 2ca1a47..9875fb5 100644 --- a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp @@ -484,8 +484,6 @@ class ProgressTextTask : public RunFunctionTask public: void runFunctor() { - while (this->isProgressUpdateNeeded() == false) - QTest::qSleep(1); this->setProgressValueAndText(1, QLatin1String("Foo 1")); while (this->isProgressUpdateNeeded() == false) @@ -495,6 +493,10 @@ public: while (this->isProgressUpdateNeeded() == false) QTest::qSleep(1); this->setProgressValueAndText(3, QLatin1String("Foo 3")); + + while (this->isProgressUpdateNeeded() == false) + QTest::qSleep(1); + this->setProgressValueAndText(4, QLatin1String("Foo 4")); } }; @@ -522,14 +524,16 @@ void tst_QFutureWatcher::progressText() QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(f.progressText(), QLatin1String("Foo 3")); - QCOMPARE(f.progressValue(), 3); + QCOMPARE(f.progressText(), QLatin1String("Foo 4")); + QCOMPARE(f.progressValue(), 4); QVERIFY(progressValues.contains(1)); QVERIFY(progressValues.contains(2)); QVERIFY(progressValues.contains(3)); + QVERIFY(progressValues.contains(4)); QVERIFY(progressTexts.contains(QLatin1String("Foo 1"))); QVERIFY(progressTexts.contains(QLatin1String("Foo 2"))); QVERIFY(progressTexts.contains(QLatin1String("Foo 3"))); + QVERIFY(progressTexts.contains(QLatin1String("Foo 4"))); } } -- cgit v0.12 From 32e8cef8f0792727134ee64f196529ed19f35d6a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 21 Feb 2011 09:42:09 +1000 Subject: Ensure QDeclarativeListProperty docs are associated with QtDeclarative. There is a copy of QDeclarativeListProperty in qgraphicsitem_p.h, which confused qdoc. Change-Id: I159b5e51af11a8b5874b0ffeb923cbd67df86d0d Task-number: QTBUG-17555 --- src/declarative/qml/qdeclarativelist.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/qml/qdeclarativelist.cpp b/src/declarative/qml/qdeclarativelist.cpp index 9598d98..346fee5 100644 --- a/src/declarative/qml/qdeclarativelist.cpp +++ b/src/declarative/qml/qdeclarativelist.cpp @@ -88,6 +88,7 @@ void QDeclarativeListReferencePrivate::release() /*! \class QDeclarativeListReference \since 4.7 +\module QtDeclarative \brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties. QDeclarativeListReference allows C++ programs to read from, and assign values to a QML list property in a -- cgit v0.12 From f141b42b87e0835552c85dbfd1ccce950da5aee3 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 21 Feb 2011 09:50:19 +1000 Subject: Docs: fix inherits tag for SpringAnimation --- src/declarative/util/qdeclarativespringanimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativespringanimation.cpp b/src/declarative/util/qdeclarativespringanimation.cpp index ec2b083..1212a1c 100644 --- a/src/declarative/util/qdeclarativespringanimation.cpp +++ b/src/declarative/util/qdeclarativespringanimation.cpp @@ -236,7 +236,7 @@ void QDeclarativeSpringAnimationPrivate::updateMode() /*! \qmlclass SpringAnimation QDeclarativeSpringAnimation \ingroup qml-animation-transition - \inherits Animation + \inherits NumberAnimation \since 4.7 \brief The SpringAnimation element allows a property to track a value in a spring-like motion. -- cgit v0.12 From 521a9bba59fe198ec7b1afe9bb25a9d3334675cf Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 14 Feb 2011 18:00:15 +1000 Subject: Forward mouse events from TextInput and TextEdit to QInputContext. This brings TextInput in line with QLineEdit. The fix for TextEdit applies equally to QTextEdit. Change-Id: I5c47e5c8e951ee53cb1fe45d9c302050cd19deef Task-number: QTBUG-15705 Reviewed-by: axis --- .../graphicsitems/qdeclarativetextedit.cpp | 36 +++--- .../graphicsitems/qdeclarativetextinput.cpp | 47 +++++++ .../graphicsitems/qdeclarativetextinput_p_p.h | 1 + src/gui/text/qtextcontrol.cpp | 120 +++++++++++------ src/gui/text/qtextcontrol_p_p.h | 20 ++- .../tst_qdeclarativetextedit.cpp | 142 ++++++++++++++++++++- .../tst_qdeclarativetextinput.cpp | 140 +++++++++++++++++++- 7 files changed, 442 insertions(+), 64 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 87a49bd..2946f6e 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -975,6 +975,10 @@ void QDeclarativeTextEdit::setSelectByMouse(bool on) if (d->selectByMouse != on) { d->selectByMouse = on; setKeepMouseGrab(on); + if (on) + setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse); + else + setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse); emit selectByMouseChanged(on); } } @@ -1027,11 +1031,10 @@ void QDeclarativeTextEdit::setReadOnly(bool r) setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r); Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse; - if (r) { + if (d->selectByMouse) flags = flags | Qt::TextSelectableByMouse; - } else { - flags = flags | Qt::TextEditorInteraction; - } + if (!r) + flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable; d->control->setTextInteractionFlags(flags); if (!r) d->control->moveCursor(QTextCursor::End); @@ -1249,8 +1252,8 @@ void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event) } } } - if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse) - d->control->processEvent(event, QPointF(0, -d->yoff)); + + d->control->processEvent(event, QPointF(0, -d->yoff)); if (!event->isAccepted()) QDeclarativePaintedItem::mousePressEvent(event); } @@ -1285,13 +1288,11 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, -d->yoff)); - if (!event->isAccepted()) - QDeclarativePaintedItem::mouseDoubleClickEvent(event); - } else { + + d->control->processEvent(event, QPointF(0, -d->yoff)); + if (!event->isAccepted()) QDeclarativePaintedItem::mouseDoubleClickEvent(event); - } + } /*! @@ -1301,14 +1302,9 @@ Handles the given mouse \a event. void QDeclarativeTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextEdit); - if (d->selectByMouse) { - d->control->processEvent(event, QPointF(0, -d->yoff)); - if (!event->isAccepted()) - QDeclarativePaintedItem::mouseMoveEvent(event); - event->setAccepted(true); - } else { + d->control->processEvent(event, QPointF(0, -d->yoff)); + if (!event->isAccepted()) QDeclarativePaintedItem::mouseMoveEvent(event); - } } /*! @@ -1407,7 +1403,7 @@ void QDeclarativeTextEditPrivate::init() control = new QTextControl(q); control->setIgnoreUnusedNavigationEvents(true); - control->setTextInteractionFlags(control->textInteractionFlags() | Qt::LinksAccessibleByMouse); + control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable); control->setDragEnabled(false); // QTextControl follows the default text color diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index e7c2ac7..bfcd715 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifndef QT_NO_LINEEDIT @@ -1002,6 +1003,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick)) + return; if (d->selectByMouse) { int cursor = d->xToPos(event->pos().x()); d->control->selectWordAtPos(cursor); @@ -1014,6 +1017,8 @@ void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *even void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress)) + return; if(d->focusOnPress){ bool hadActiveFocus = hasActiveFocus(); forceActiveFocus(); @@ -1041,6 +1046,8 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseMove)) + event->setAccepted(true); if (d->selectByMouse) { if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance()) setKeepMouseGrab(true); @@ -1058,6 +1065,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease)) + return; if (d->selectByMouse) setKeepMouseGrab(false); if (!d->showInputPanelOnFocus) { // input panel on click @@ -1075,6 +1084,44 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QDeclarativePaintedItem::mouseReleaseEvent(event); } +bool QDeclarativeTextInputPrivate::sendMouseEventToInputContext( + QGraphicsSceneMouseEvent *event, QEvent::Type eventType) +{ +#if !defined QT_NO_IM + if (event->widget() && control->composeMode()) { + int tmp_cursor = xToPos(event->pos().x()); + int mousePos = tmp_cursor - control->cursor(); + if (mousePos < 0 || mousePos > control->preeditAreaText().length()) { + mousePos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + + QInputContext *qic = event->widget()->inputContext(); + if (qic) { + QMouseEvent mouseEvent( + eventType, + event->widget()->mapFromGlobal(event->screenPos()), + event->screenPos(), + event->button(), + event->buttons(), + event->modifiers()); + // may be causing reset() in some input methods + qic->mouseHandler(mousePos, &mouseEvent); + event->setAccepted(mouseEvent.isAccepted()); + } + if (!control->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(event); + Q_UNUSED(eventType) +#endif + + return false; +} + bool QDeclarativeTextInput::sceneEvent(QEvent *event) { bool rv = QDeclarativeItem::sceneEvent(event); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index f7446b4..ab2838b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -104,6 +104,7 @@ public: void focusChanged(bool hasFocus); void updateHorizontalScroll(); int calculateTextWidth(); + bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType); QLineControl* control; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index e380b37..b25588d 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -932,15 +932,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::MouseMove: { QMouseEvent *ev = static_cast(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonRelease: { QMouseEvent *ev = static_cast(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonDblClick: { QMouseEvent *ev = static_cast(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::InputMethod: d->inputMethodEvent(static_cast(e)); @@ -1000,15 +1003,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::GraphicsSceneMouseMove: { QGraphicsSceneMouseEvent *ev = static_cast(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseRelease: { QGraphicsSceneMouseEvent *ev = static_cast(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseDoubleClick: { QGraphicsSceneMouseEvent *ev = static_cast(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneContextMenu: { QGraphicsSceneContextMenuEvent *ev = static_cast(e); @@ -1017,7 +1023,8 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte case QEvent::GraphicsSceneHoverMove: { QGraphicsSceneHoverEvent *ev = static_cast(e); - d->mouseMoveEvent(Qt::NoButton, matrix.map(ev->pos())); + d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, + ev->screenPos()); break; } case QEvent::GraphicsSceneDragEnter: { @@ -1487,6 +1494,11 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { anchorOnMousePress = q->anchorAt(pos); @@ -1529,22 +1541,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - if (ctx) { - QMouseEvent ev(QEvent::MouseButtonPress, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos - cursor.position(), &ev); - } - if (!layout->preeditAreaText().isEmpty()) { - e->ignore(); - return; - } - } -#endif - if (modifiers == Qt::ShiftModifier) { + if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { selectedWordOnDoubleClick = cursor; selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); @@ -1589,10 +1586,16 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con hadSelectionOnMousePress = cursor.hasSelection(); } -void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &mousePos) +void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { QString anchor = q->anchorAt(mousePos); if (anchor != highlightedAnchor) { @@ -1622,12 +1625,6 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF } const qreal mouseX = qreal(mousePos.x()); -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); if (newCursorPos == -1) return; @@ -1641,7 +1638,7 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(newCursorPos, mouseX); - else + else if (interactionFlags & Qt::TextSelectableByMouse) setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextEditable) { @@ -1665,10 +1662,16 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF repaintOldAndNewSelection(oldSelection); } -void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { + return; + } + const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -1726,19 +1729,21 @@ void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPoint } } -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (button != Qt::LeftButton || !(interactionFlags & Qt::TextSelectableByMouse)) { e->ignore(); return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; @@ -1767,6 +1772,45 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto } } +bool QTextControlPrivate::sendMouseEventToInputContext( + QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) +{ +#if !defined(QT_NO_IM) + Q_Q(QTextControl); + + QTextLayout *layout = cursor.block().layout(); + if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { + QInputContext *ctx = inputContext(); + int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); + + if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { + cursorPos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + if (ctx) { + QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, + button, buttons, modifiers); + ctx->mouseHandler(cursorPos, &ev); + e->setAccepted(ev.isAccepted()); + } + if (!layout->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); + Q_UNUSED(eventType); + Q_UNUSED(button); + Q_UNUSED(pos); + Q_UNUSED(modifiers); + Q_UNUSED(buttons); + Q_UNUSED(globalPos); +#endif + return false; +} + void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) { #ifdef QT_NO_CONTEXTMENU diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index ecd13ea..94670e2 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -135,9 +135,23 @@ public: Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos); - void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos); - void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos); - void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos); + void mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + bool sendMouseEventToInputContext(QEvent *e, QEvent::Type eventType, Qt::MouseButton button, + const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); void contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget); void focusEvent(QFocusEvent *e); #ifdef QT_KEYPAD_NAVIGATION diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index a052752..f74a27d 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -138,6 +138,7 @@ private slots: void testQtQuick11Attributes_data(); void preeditMicroFocus(); + void inputContextMouseHandler(); private: void simulateKey(QDeclarativeView *, int key); @@ -1464,7 +1465,7 @@ QDeclarativeView *tst_qdeclarativetextedit::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1495,9 +1496,27 @@ public: sendEvent(event); } + void mouseHandler(int x, QMouseEvent *event) + { + cursor = x; + eventType = event->type(); + eventPosition = event->pos(); + eventGlobalPosition = event->globalPos(); + eventButton = event->button(); + eventButtons = event->buttons(); + eventModifiers = event->modifiers(); + } + bool openInputPanelReceived; bool closeInputPanelReceived; bool updateReceived; + int cursor; + QEvent::Type eventType; + QPoint eventPosition; + QPoint eventGlobalPosition; + Qt::MouseButton eventButton; + Qt::MouseButtons eventButtons; + Qt::KeyboardModifiers eventModifiers; }; void tst_qdeclarativetextedit::textInput() @@ -1824,7 +1843,6 @@ void tst_qdeclarativetextedit::preeditMicroFocus() MyInputContext ic; view.setInputContext(&ic); QDeclarativeTextEdit edit; - edit.setPos(0, 0); edit.setFocus(true); scene.addItem(&edit); view.show(); @@ -1870,6 +1888,126 @@ void tst_qdeclarativetextedit::preeditMicroFocus() #endif } +void tst_qdeclarativetextedit::inputContextMouseHandler() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextEdit edit; + edit.setPos(0, 0); + edit.setWidth(200); + edit.setText(text.mid(0, 5)); + edit.setPos(0, 0); + edit.setCursorPosition(5); + edit.setFocus(true); + scene.addItem(&edit); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + view.setFocus(); + + QFontMetricsF fm(edit.font()); + const qreal y = fm.height() / 2; + + QPoint position2 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); + QPoint position4 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 4)), y))); + QPoint position7 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 7)), y))); + QPoint position12 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 12)), y))); + QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); + QPoint globalPosition4 = view.viewport()->mapToGlobal(position4); + QPoint globalPosition7 = view.viewport()->mapToGlobal(position7); + QPoint globalPosition12 = view.viewport()->mapToGlobal(position12); + + ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); + + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position4, globalPosition4, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + { QMouseEvent mv(QEvent::MouseMove, position12, globalPosition12, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + // And in the other direction. + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position7, globalPosition7, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position7); + QCOMPARE(ic.eventGlobalPosition, globalPosition7); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 2); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; +} + 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 7753f11..b601af8 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -126,6 +126,7 @@ private slots: void preeditAutoScroll(); void preeditMicroFocus(); + void inputContextMouseHandler(); private: void simulateKey(QDeclarativeView *, int key); @@ -1420,7 +1421,7 @@ QDeclarativeView *tst_qdeclarativetextinput::createView(const QString &filename) class MyInputContext : public QInputContext { public: - MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false) {} + MyInputContext() : openInputPanelReceived(false), closeInputPanelReceived(false), updateReceived(false), eventType(QEvent::None) {} ~MyInputContext() {} QString identifierName() { return QString(); } @@ -1441,6 +1442,17 @@ public: void update() { updateReceived = true; } + void mouseHandler(int x, QMouseEvent *event) + { + cursor = x; + eventType = event->type(); + eventPosition = event->pos(); + eventGlobalPosition = event->globalPos(); + eventButton = event->button(); + eventButtons = event->buttons(); + eventModifiers = event->modifiers(); + } + void sendPreeditText(const QString &text, int cursor) { QList attributes; @@ -1454,6 +1466,13 @@ public: bool openInputPanelReceived; bool closeInputPanelReceived; bool updateReceived; + int cursor; + QEvent::Type eventType; + QPoint eventPosition; + QPoint eventGlobalPosition; + Qt::MouseButton eventButton; + Qt::MouseButtons eventButtons; + Qt::KeyboardModifiers eventModifiers; }; void tst_qdeclarativetextinput::openInputPanelOnClick() @@ -1859,6 +1878,125 @@ void tst_qdeclarativetextinput::preeditMicroFocus() #endif } +void tst_qdeclarativetextinput::inputContextMouseHandler() +{ + QString text = "supercalifragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(200); + input.setText(text.mid(0, 5)); + 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)); + + ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); + + QFontMetricsF fm(input.font()); + const qreal y = fm.height() / 2; + + QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); + QPoint position4 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 4)), y))); + QPoint position7 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 7)), y))); + QPoint position12 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 12)), y))); + QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); + QPoint globalPosition4 = view.viewport()->mapToGlobal(position4); + QPoint globalPosition7 = view.viewport()->mapToGlobal(position7); + QPoint globalPosition12 = view.viewport()->mapToGlobal(position12); + + ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); + + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position4, globalPosition4, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + { QMouseEvent mv(QEvent::MouseMove, position12, globalPosition12, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::NoModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + // And in the other direction. + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::LeftButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position12); + QCOMPARE(ic.eventType, QEvent::MouseButtonPress); + QCOMPARE(ic.eventPosition, position12); + QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 7); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position7, globalPosition7, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::MouseMove); + QCOMPARE(ic.eventPosition, position7); + QCOMPARE(ic.eventGlobalPosition, globalPosition7); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QCOMPARE(ic.cursor, 2); + ic.eventType = QEvent::None; + + { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + QApplication::sendEvent(view.viewport(), &mv); } + QCOMPARE(ic.eventType, QEvent::None); + + QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2); + QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); + QCOMPARE(ic.eventPosition, position2); + QCOMPARE(ic.eventGlobalPosition, globalPosition2); + QCOMPARE(ic.eventButton, Qt::RightButton); + QCOMPARE(ic.eventModifiers, Qt::ControlModifier); + QVERIFY(ic.cursor < 0); + ic.eventType = QEvent::None; +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v0.12 From fd198736e1da02f535bc81d9934cb4e8412a87bc Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 16 Feb 2011 13:33:52 +1000 Subject: Hide the TextInput/Edit cursor when the view doesn't have focus. Only display a cursor if both the item and its scene have focus. Change-Id: I0c91ab4d533cd7d773ffc2489633e12c0d399ad9 Task-number: QTBUG-17365 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 2 +- .../graphicsitems/qdeclarativetextinput.cpp | 2 +- .../tst_qdeclarativetextedit.cpp | 71 ++++++++++++++++++++++ .../tst_qdeclarativetextinput.cpp | 70 +++++++++++++++++++++ 4 files changed, 143 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 2946f6e..83c7420 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -1126,7 +1126,7 @@ void QDeclarativeTextEdit::keyReleaseEvent(QKeyEvent *event) void QDeclarativeTextEditPrivate::focusChanged(bool hasFocus) { Q_Q(QDeclarativeTextEdit); - q->setCursorVisible(hasFocus); + q->setCursorVisible(hasFocus && scene && scene->hasFocus()); QDeclarativeItemPrivate::focusChanged(hasFocus); } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index bfcd715..ba1ae63 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -948,7 +948,7 @@ void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) { Q_Q(QDeclarativeTextInput); focused = hasFocus; - q->setCursorVisible(hasFocus); + q->setCursorVisible(hasFocus && scene && scene->hasFocus()); if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus) control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events if (!hasFocus) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index f74a27d..ba410ce 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -122,6 +122,7 @@ private slots: void inputMethodHints(); void cursorDelegate(); + void cursorVisible(); void delegateLoading_data(); void delegateLoading(); void navigation(); @@ -1277,6 +1278,76 @@ void tst_qdeclarativetextedit::cursorDelegate() delete view; } +void tst_qdeclarativetextedit::cursorVisible() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + view.setFocus(); + + QDeclarativeTextEdit edit; + QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool))); + + QCOMPARE(edit.isCursorVisible(), false); + + edit.setCursorVisible(true); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 1); + + edit.setCursorVisible(false); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + edit.setFocus(true); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + scene.addItem(&edit); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 3); + + edit.setFocus(false); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 4); + + edit.setFocus(true); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 5); + + scene.clearFocus(); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 6); + + scene.setFocus(); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 7); + + view.clearFocus(); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 8); + + view.setFocus(); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 9); + + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) + QApplication::setActiveWindow(0); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(0)); + QCOMPARE(edit.isCursorVisible(), false); + QCOMPARE(spy.count(), 10); + + QApplication::setActiveWindow(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + QCOMPARE(edit.isCursorVisible(), true); + QCOMPARE(spy.count(), 11); +#endif +} + void tst_qdeclarativetextedit::delegateLoading_data() { QTest::addColumn("qmlfile"); diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index b601af8..b8f73bd 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -110,6 +110,7 @@ private slots: void passwordCharacter(); void cursorDelegate(); + void cursorVisible(); void navigation(); void copyAndPaste(); void readOnly(); @@ -1316,6 +1317,75 @@ void tst_qdeclarativetextinput::cursorDelegate() delete view; } +void tst_qdeclarativetextinput::cursorVisible() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + + QDeclarativeTextInput input; + QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool))); + + QCOMPARE(input.isCursorVisible(), false); + + input.setCursorVisible(true); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 1); + + input.setCursorVisible(false); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + input.setFocus(true); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 2); + + scene.addItem(&input); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 3); + + input.setFocus(false); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 4); + + input.setFocus(true); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 5); + + scene.clearFocus(); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 6); + + scene.setFocus(); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 7); + + view.clearFocus(); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 8); + + view.setFocus(); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 9); + + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) + QApplication::setActiveWindow(0); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(0)); + QCOMPARE(input.isCursorVisible(), false); + QCOMPARE(spy.count(), 10); + + QApplication::setActiveWindow(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + QCOMPARE(input.isCursorVisible(), true); + QCOMPARE(spy.count(), 11); +#endif +} + void tst_qdeclarativetextinput::readOnly() { QDeclarativeView *canvas = createView(SRCDIR "/data/readOnly.qml"); -- cgit v0.12 From 8e9c28eaa4d7a3372b9a9a21a984701b62f96456 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 18 Feb 2011 13:52:10 +1000 Subject: Ensure animations start correctly when running is bound to a value. Animations register to be started when the component is finalized, but in the case of a binding, the registration doesn't happen until we are already working with a copy of the finalization list. With this patch, we no longer work with a copy, but with the actual list. Change-Id: If460c250d2403590907e9ac854d277db68ba8b2a Task-number: QTBUG-14042 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativecomponent.cpp | 23 ++++++++++------------ src/declarative/qml/qdeclarativecomponent_p.h | 1 - src/declarative/qml/qdeclarativevme.cpp | 1 - .../data/registrationBug.qml | 18 +++++++++++++++++ .../tst_qdeclarativeanimations.cpp | 12 +++++++++++ 5 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 5840f70..cf40182 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -870,7 +870,6 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -878,7 +877,6 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); - enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -909,7 +907,6 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi state->bindValues = enginePriv->bindValues; state->parserStatus = enginePriv->parserStatus; - state->finalizedParserStatus = enginePriv->finalizedParserStatus; state->componentAttached = enginePriv->componentAttached; if (state->componentAttached) state->componentAttached->prev = &state->componentAttached; @@ -917,7 +914,6 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi enginePriv->componentAttached = 0; enginePriv->bindValues.clear(); enginePriv->parserStatus.clear(); - enginePriv->finalizedParserStatus.clear(); state->completePending = true; enginePriv->inProgressCreations++; } @@ -955,14 +951,17 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri QDeclarativeEnginePrivate::clear(ps); } - for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) { - QPair, int> status = state->finalizedParserStatus.at(ii); - QObject *obj = status.first; - if (obj) { - void *args[] = { 0 }; - QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, - status.second, args); + if (1 == enginePriv->inProgressCreations) { + for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) { + QPair, int> status = enginePriv->finalizedParserStatus.at(ii); + QObject *obj = status.first; + if (obj) { + void *args[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, + status.second, args); + } } + enginePriv->finalizedParserStatus.clear(); } while (state->componentAttached) { @@ -977,7 +976,6 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri state->bindValues.clear(); state->parserStatus.clear(); - state->finalizedParserStatus.clear(); state->completePending = false; enginePriv->inProgressCreations--; @@ -987,7 +985,6 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri enginePriv->erroredBindings->removeError(); } } - } } diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index f8bec2b..020c5e0 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -101,7 +101,6 @@ public: ConstructionState() : componentAttached(0), completePending(false) {} QList > bindValues; QList > parserStatus; - QList, int> > finalizedParserStatus; QDeclarativeComponentAttached *componentAttached; QList errors; bool completePending; diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 366c64b..2d551f2 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -938,7 +938,6 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeEnginePrivate::clear(bindValues); QDeclarativeEnginePrivate::clear(parserStatus); - ep->finalizedParserStatus.clear(); return 0; } diff --git a/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml b/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml new file mode 100644 index 0000000..7dc29f9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/registrationBug.qml @@ -0,0 +1,18 @@ +import QtQuick 1.0 + +Rectangle { + id: rect + width: 200 + height: 200 + + property bool animating: true + property int value: 0 + + NumberAnimation { + target: rect + property: "value" + running: rect.animating + to: 100 + duration: 50 + } +} diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp index 6f71dec..d1b7c1b 100644 --- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp +++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp @@ -85,6 +85,7 @@ private slots: void rotation(); void runningTrueBug(); void nonTransitionBug(); + void registrationBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -793,6 +794,17 @@ void tst_qdeclarativeanimations::nonTransitionBug() QCOMPARE(mover->x(), qreal(100)); } +//QTBUG-14042 +void tst_qdeclarativeanimations::registrationBug() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/registrationBug.qml"); + QDeclarativeRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + QTRY_COMPARE(rect->property("value"), QVariant(int(100))); +} + QTEST_MAIN(tst_qdeclarativeanimations) #include "tst_qdeclarativeanimations.moc" -- cgit v0.12 From 1bcddaaf318fc37c71c5191913f3487c49444ec6 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 21 Feb 2011 14:57:08 +1000 Subject: Prevent recursion due to nested Flickables with pressDelay The outermost Flickable handles pressDelay for all descendents, rather than having it cascade up and replayed multiple times. Change-Id: Id294862469f3ce56b0940fbbb0e041d4c9f64f28 Task-number: QTBUG-17361 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativeflickable.cpp | 48 ++++++++++++++++++++-- .../graphicsitems/qdeclarativeflickable_p.h | 1 + .../graphicsitems/qdeclarativeflickable_p_p.h | 1 + .../tst_qdeclarativeflickable.cpp | 29 +++++++++++++ .../tst_qdeclarativemousearea.cpp | 20 +++------ 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 5d5fd0b..a3d9f41 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -845,7 +845,8 @@ void QDeclarativeFlickable::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); if (d->interactive) { - d->handleMousePressEvent(event); + if (!d->pressed) + d->handleMousePressEvent(event); event->accept(); } else { QDeclarativeItem::mousePressEvent(event); @@ -910,11 +911,27 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) } } +bool QDeclarativeFlickablePrivate::isOutermostPressDelay() const +{ + Q_Q(const QDeclarativeFlickable); + QDeclarativeItem *item = q->parentItem(); + while (item) { + QDeclarativeFlickable *flick = qobject_cast(item); + if (flick && flick->pressDelay() > 0 && flick->isInteractive()) + return false; + item = item->parentItem(); + } + + return true; +} + void QDeclarativeFlickablePrivate::captureDelayedPress(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); if (!q->scene() || pressDelay <= 0) return; + if (!isOutermostPressDelay()) + return; delayedPressTarget = q->scene()->mouseGrabberItem(); delayedPressEvent = new QGraphicsSceneMouseEvent(event->type()); delayedPressEvent->setAccepted(false); @@ -970,9 +987,10 @@ void QDeclarativeFlickable::timerEvent(QTimerEvent *event) if (scene()->mouseGrabberItem() == d->delayedPressTarget) d->delayedPressTarget->ungrabMouse(); //Use the event handler that will take care of finding the proper item to propagate the event - QApplication::sendEvent(scene(), d->delayedPressEvent); + QApplication::postEvent(scene(), d->delayedPressEvent); + } else { + delete d->delayedPressEvent; } - delete d->delayedPressEvent; d->delayedPressEvent = 0; } } @@ -1364,6 +1382,22 @@ bool QDeclarativeFlickable::yflick() const return d->flickableDirection & QDeclarativeFlickable::VerticalFlick; } +bool QDeclarativeFlickable::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + Q_D(QDeclarativeFlickable); + if (d->pressed) { + // if our mouse grab has been removed (probably by another Flickable), + // fix our state + d->pressed = false; + d->stealMouse = false; + setKeepMouseGrab(false); + } + } + return rv; +} + bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeFlickable); @@ -1391,7 +1425,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->handleMouseMoveEvent(&mouseEvent); break; case QEvent::GraphicsSceneMousePress: - if (d->delayedPressEvent) + if (d->pressed) // we are already pressed - this is a delayed replay return false; d->handleMousePressEvent(&mouseEvent); @@ -1410,6 +1444,8 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) // We send the release scene()->sendEvent(s->mouseGrabberItem(), event); // And the event has been consumed + d->stealMouse = false; + d->pressed = false; return true; } d->handleMouseReleaseEvent(&mouseEvent); @@ -1432,6 +1468,7 @@ bool QDeclarativeFlickable::sendMouseEvent(QGraphicsSceneMouseEvent *event) d->stealMouse = false; d->pressed = false; } + return false; } @@ -1530,6 +1567,9 @@ bool QDeclarativeFlickable::isFlickingVertically() const If the flickable is dragged/flicked before the delay times out the press event will not be delivered. If the button is released within the timeout, both the press and release will be delivered. + + Note that for nested Flickables with pressDelay set, the pressDelay of + inner Flickables is overridden by the outermost Flickable. */ int QDeclarativeFlickable::pressDelay() const { diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 4fde1d5..a14cc1c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -204,6 +204,7 @@ protected: virtual void viewportMoved(); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + bool sceneEvent(QEvent *event); bool sendMouseEvent(QGraphicsSceneMouseEvent *event); bool xflick() const; diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 5ad6ff6..1b6081c 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -118,6 +118,7 @@ public: void updateBeginningEnd(); + bool isOutermostPressDelay() const; void captureDelayedPress(QGraphicsSceneMouseEvent *event); void clearDelayedPress(); diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index f4bec8f..736f8f4 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -69,6 +69,7 @@ private slots: void maximumFlickVelocity(); void flickDeceleration(); void pressDelay(); + void nestedPressDelay(); void flickableDirection(); void qgraphicswidget(); void resizeContent(); @@ -246,6 +247,34 @@ void tst_qdeclarativeflickable::pressDelay() QCOMPARE(spy.count(),1); } +// QTBUG-17361 +void tst_qdeclarativeflickable::nestedPressDelay() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedPressDelay.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *outer = qobject_cast(canvas->rootObject()); + QVERIFY(outer != 0); + + QDeclarativeFlickable *inner = canvas->rootObject()->findChild("innerFlickable"); + QVERIFY(inner != 0); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150))); + // the MouseArea is not pressed immediately + QVERIFY(outer->property("pressed").toBool() == false); + + // The outer pressDelay will prevail (50ms, vs. 10sec) + QTest::qWait(300); + QVERIFY(outer->property("pressed").toBool() == true); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150))); + + delete canvas; +} + void tst_qdeclarativeflickable::flickableDirection() { QDeclarativeComponent component(&engine); diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 60d51c6..e1c34fc 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -541,15 +541,11 @@ void tst_QDeclarativeMouseArea::preventStealing() 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); + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80))); // Without preventStealing, mouse movement over MouseArea would // cause the Flickable to steal mouse and trigger content movement. + QGraphicsScene *scene = canvas->scene(); QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove); moveEvent.setScenePos(QPointF(70, 70)); moveEvent.setButton(Qt::LeftButton); @@ -574,17 +570,12 @@ void tst_QDeclarativeMouseArea::preventStealing() 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); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); // Now allow stealing and confirm Flickable does its thing. canvas->rootObject()->setProperty("stealing", false); - pressEvent.setScenePos(QPointF(80, 80)); - QApplication::sendEvent(scene, &pressEvent); + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(80, 80))); // Without preventStealing, mouse movement over MouseArea would // cause the Flickable to steal mouse and trigger content movement. @@ -606,8 +597,7 @@ void tst_QDeclarativeMouseArea::preventStealing() QCOMPARE(flickable->contentX(), 10.); QCOMPARE(flickable->contentY(), 10.); - releaseEvent.setScenePos(QPointF(50, 50)); - QApplication::sendEvent(scene, &releaseEvent); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); delete canvas; } -- cgit v0.12 From 95a9ab2d0e94c735ac813c809a4fe98dd466cc64 Mon Sep 17 00:00:00 2001 From: Dean Dettman Date: Mon, 21 Feb 2011 12:18:09 +0100 Subject: Wheel delta is always zero in QEventTransition's event When a QGraphicsSceneWheelEvent was cloned, the original event's delta property was not copied. Task-number: QTBUG-17536 Reviewed-by: Kent Hansen --- src/gui/statemachine/qguistatemachine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index eadb8ff..2a0de3c 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -404,6 +404,7 @@ static QEvent *cloneEvent(QEvent *e) we2->setButtons(we->buttons()); we2->setModifiers(we->modifiers()); we2->setOrientation(we->orientation()); + we2->setDelta(we->delta()); return we2; } #endif -- cgit v0.12 From 2d4298854ba57667a8aa0a0dd3a4bd7ce41aceae Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 21 Feb 2011 15:38:24 +0200 Subject: Only add NetworkServices capability automatically if no caps are set. This allows overriding the NetworkServices capability for the applications that do not need the capability even though they link network, webkit, or declarative. It is also more intuitive as there are no magic additions to user defined capabilities. Task-number: QTBUG-17540 Reviewed-by: Janne Koskinen --- doc/src/platforms/platform-notes.qdoc | 6 +++--- mkspecs/features/qt_functions.prf | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc index aac6bb0..de6eb7f 100644 --- a/doc/src/platforms/platform-notes.qdoc +++ b/doc/src/platforms/platform-notes.qdoc @@ -735,9 +735,9 @@ \row \o QtCore \o \c AllFiles when \l{http://developer.symbian.org/wiki/index.php/Capabilities_%28Symbian_Signed%29/AllFiles_Capability}{accessing specific areas.} \row \o QtDeclarative - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \row \o QtNetwork - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \row \o QtNetwork \o \c ReadUserData is required to include all the phone's SSL certificates in the system's default CA certificate list (for example those added by the user or stored in the SIM card), @@ -745,7 +745,7 @@ \row \o QtMultiMedia \o \c UserEnvironment if QAudioInput is used. \row \o QtWebkit - \o \c NetworkServices is automatically added for this module. + \o \c NetworkServices is automatically added for this module if no capabilities are explicitly specified. \endtable \note Some modules rely on other modules. E.g. QtWebkit and QtDeclarative diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 964e13b..24c84a5 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -53,15 +53,15 @@ defineTest(qtAddLibrary) { # Needed for because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtXmlPatterns INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 } else:isEqual(LIB_NAME, QtXmlPatterns) { # Needed for #include because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork } else:isEqual(LIB_NAME, QtNetwork) { - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices } else:isEqual(LIB_NAME, QtDeclarative) { - TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.CAPABILITY): TARGET.CAPABILITY = NetworkServices isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 } export(TARGET.EPOCHEAPSIZE) -- cgit v0.12 From de1417c6648a2589f56a7df0603b26387037aa31 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 21 Feb 2011 16:00:07 +0200 Subject: Added support for QMAKE_CLEAN in symbian-sbsv2 Files specified in QMAKE_CLEAN variable will now be properly cleaned in symbian-sbsv2 builds. Task-number: QTBUG-17004 Reviewed-by: Janne Koskinen --- mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm | 18 ++++++++++++++++++ mkspecs/symbian-sbsv2/flm/qt/qt.xml | 5 +++++ qmake/generators/symbian/symmake_sbsv2.cpp | 12 ++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm new file mode 100644 index 0000000..fe35e6e --- /dev/null +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_clean.flm @@ -0,0 +1,18 @@ +# /**************************************************************************** +# ** +# ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# ** Contact: Nokia Corporation (qt-info@nokia.com) +# ** +# ** This file is part of symbian-sbsv2 mkspec. +# ** +# ****************************************************************************/ + + +SINGLETON:=$(call sanitise,QMAKE_CLEAN_SINGLETON_$(EXTENSION_ROOT)) + +ifeq ($($(SINGLETON)),) +# Prevent duplicate targets from being created +$(SINGLETON):=1 +$(eval $(call GenerateStandardCleanTarget,$(CLEAN_FILES),'')) +endif + diff --git a/mkspecs/symbian-sbsv2/flm/qt/qt.xml b/mkspecs/symbian-sbsv2/flm/qt/qt.xml index ddd8d55..f2f32ee 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qt.xml +++ b/mkspecs/symbian-sbsv2/flm/qt/qt.xml @@ -38,4 +38,9 @@ + + + + diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index 9eccd46..f94a63f 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -721,6 +721,18 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t t << "END" << endl; t << endl; + // Handle QMAKE_CLEAN + QStringList cleanFiles = project->values("QMAKE_CLEAN"); + if (!cleanFiles.isEmpty()) { + QStringList absoluteCleanFiles; + foreach (QString cleanFile, cleanFiles) { + QFileInfo fi(cleanFile); + absoluteCleanFiles << fi.absoluteFilePath(); + } + t << "START EXTENSION qt/qmake_clean" << endl; + t << "OPTION CLEAN_FILES " << absoluteCleanFiles.join(" ") << endl; + t << "END" << endl; + } t << endl; } -- cgit v0.12 From 11f11f8ad562472759df24a410d52edd63eb2cf4 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Tue, 22 Feb 2011 00:58:12 +1000 Subject: Add selected P1 tasks to changes file. Reviewed-by: Trust Me --- dist/changes-4.7.2 | 271 +++++++++++++++++++++++++++-------------------------- 1 file changed, 138 insertions(+), 133 deletions(-) diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index 17a066f..c7e0089 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -16,35 +16,48 @@ Qt Bug Tracker: http://bugreports.qt.nokia.com Merge Request: http://qt.gitorious.org **************************************************************************** -* General * -**************************************************************************** - -New features ------------- - - - SomeClass, SomeOtherClass - * New classes for foo, bar and baz - -Optimizations -------------- - - - Optimized foo in QSomeClass - * See list of Important Behavior Changes below - - -**************************************************************************** * Library * **************************************************************************** QtCore ------ + - QMutex + * [QTBUG-16115] Fixed deadlock when calling tryLock repeatedly. - QStateMachine - * [QTBUG-14491] Fix compilation on AIX 5.3 with gcc. + * [QTBUG-14491] Fixed compilation on AIX 5.3 with gcc. + - QThread + * [QTBUG-15378] QThread::exec returaed immediately if QThread::exit had + been called when event loop was not running. QtGui ----- + - Painting + * [QTBUG-14907] Fix OpenVG painting artifacts after restoreState(). + * [QTBUG-15320] QPainter::drawRect crashed when drawing a null QRectF + with OpenGL. + * [QTBUG-15693] Prevent crash in drawhelper code when the cpu has MMXEXT + but no SSE. + - QDoubleValidator + * [QTBUG-14935] With some locales, QDoubleValidator would not accept "C" + locale valid numbers. + - QFileDialog + * [QTBUG-17298] QFileDialog::getOpenFileNames didn't show any file. + - QGraphicsView + * [QTBUG-16063] Fix precision loss when querying micro focus rectangle + in QGraphicsView. + - QPainterPath + * [QTBUG-16377] Prevent QPainterPath::connectPath() returning incorrect + path, which caused OpenGL paint engine to crash. + - QTableWidget + * [QTBUG-15973] Resizinag a QTableWidget column where a cell contains a + QProgressBar made it crash. + - QTextDocument + * [QTBUG-15777] Fxied crash in QTextDocument::markContentsDirty. + - QTextLayout + * [QTBUG-15823] Fixed crash in QTextLayout when drawing full width + selection spanning multiple QTextLine's. - QWidget * [QTMOBILITY-645] Send WinIdChange event when winId is set to zero. The window handle of a native widget may be set to zero in two @@ -52,27 +65,32 @@ QtGui widget destruction. Previously, no WinIdChange event was sent in either of these cases; now, it is sent in both cases. -QtDBus ------- - - - foo - * bar - QtNetwork --------- - - foo - * bar + - Bearer Management + * [QTBUG-15276] Fixed possible crash when parsing new connection. + - QUrl + * [QTBUG-16425] QUrl::setUrl() did not call detach(). -QtOpenGL --------- +QtQuick +------- - - foo - * bar + - [QTBUG-14374] Fixed broken alignment of rich text. + - [QTBUG-14727] QML Text element did not play nice with transformations. + - [QTBUG-14761] Fixed memory leak in QDeclarativeComponent. + - [QTBUG-14830] Fixed crash when adjusting width inside onWidthChanged. + - [QTBUG-15710] Ensure header is considered when positioning content with + snapping. + - [QTBUG-16365] When using a PathView with a VisualDataModel which in turn + used a Tree model (DirModel, for example), nothing was shown. + - [QTBUG-16769] QML BorderImage failed if .sci file contained a URL. QtScript -------- + - General + * [QTBUG-17166] Fix ScopeChainNode memory leak in JavaScriptCore. - QScriptContext * [QTBUG-17137] Fix crash when generating backtrace involving a built-in (ECMA) function. @@ -94,56 +112,55 @@ QtScript QtSql ----- - - foo - * bar - -QtXml ------ - - - foo - * bar - -Qt Plugins ----------- - - - foo - * bar - -Third party components ----------------------- - - - Updated foo to version 2.3.9. - - - Updated bar to the latest version from baz.org. + - [QTBUG-14132] Fix errors in Oracle (xe) stored procedures with bind + variables. + - [QTBUG-14831] Fix regression in dynamic sorting of a QSortFilterProxyModel + on a QSqlTableModel with OnManualSubmit. + - [QTBUG-17076] Fix plugins/sqldrivers/oci compile error when using + QT_NAMESPACE. **************************************************************************** * Platform Specific Changes * **************************************************************************** -Qt for Unix (X11 and Mac OS X) ------------------------------- - - - - Qt for Linux/X11 ---------------- - - + - [QTBUG-15008] Fix broken prefix setting in configure when EPOCROOT shell + variable is set. Qt for Windows -------------- - - + - QtQuick + * [QTBUG-16885] QDeclarativeEngine::addImportPath() did not work if the + drive letter is in lowercase. + * [QTBUG-17360] Make sure $QTDIR/plugins/qmldebugging/tcpserver.dll is + found in windows release builds. Qt for Mac OS X --------------- - - + - [QTBUG-13772] Returning form fullscreen mode causes assertion failure. + - [QTBUG-14023] Added missing plugins to debug-libs package. + - [QTBUG-14420] Switching from an application with undocked widgets hid the + application. + - [QTBUG-15638] Fixed incorrect QComboBox drop-down menu Z-ordering. + - [QTBUG-15666] Fixed crash when closing QFontDialog::getFont() dialog before + its event loop finished. + - [QTBUG-16279] Fixed deadlock in QSyntaxHighlighter::highlightBlock. Qt for Symbian -------------- + - Multimedia + * [QTBUG-17040] Prevent menu and native title pane area popping up when + setting fullscreen mode off during video playback. + - Packaging changes + * [QTBUG-17399] Remove sqlite3 from Qt SIS for S60 3.2 and 5.0 to allow + Nokia Content Signing, which doesn't permit sis files to have other + sis files embedded inside. - Paging changes * [QT-3503] Remove PAGED keyword from all Qt-based binaries for MMP-based build systems (abld, SBSv2 (a.k.a. Raptor)). @@ -159,65 +176,92 @@ Qt for Symbian appropriate types of paging rather than being forced by the binary (which may be deployed to several different devices with different characteristics). - - Phonon MMF backend * [QTBUG-11436] Added a MediaObject property which allows the client to specify which Internet Access Point should be used for streaming. - - - QNetworkProxyFactory - * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing - network proxies configured on the device to be used by applications. - - QApplication - * [QTBUG-15915] Fix crash when creating more than one QApplication in single test case. - + * [QTBUG-15915] Fix crash when creating more than one QApplication in single + test case. + * [QTBUG-16065] QApplication object with QApplication::GuiServer type caused + crash on Symbian devices. - QDesktopWidget * [QTBUG-16095] Resize event for QDesktopWidget was sent too early. - - - QFileDialog - * [QTBUG-16204] Fix using QFileDialog statics in Symbian. - - QDialog * [QTBUG-16277] Fix fullscreen/Maximized dialog misplacement in Symbian. - - - QSystemSemaphore - * [QTBUG-16615] Fix QSystemSemaphore handle management issues in Symbian. - + * [QTBUG-16110] QMessageBox softkeys were dimmed when application returned + to foreground. + - QEventDispatcherSymbian + * [QTBUG-16380] Fix leaking of RTimer handles. + - QFileDialog + * [QTBUG-16204] Fix using QFileDialog statics in Symbian. + - QFontDatabase + * [QTBUG-16514] Avoid collision of application fonts. + - QGraphicsView + * [QTBUG-16932] Fix rendering errors on QGraphicsView with OpenVG engine. - QLineEdit * [QTBUG-16238] Fix one character displacement for cursor in line edits. - - - QtScript - * [QTBUG-16685] Fix crash in JavaScript stack allocator. - * [QTBUG-15847] Add compiler optimizations. - * [QTBUG-14293] Enhanced JavaScript heap allocator. - - qmake & mkspecs * [QT-4193] Only add ICON for application projects in symbianpkgrules.pri - * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate files. - * [QTBUG-13367] Make default application deployment removable & added .flags modifier - support for DEPLOYMENT items in Symbian. + * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate + files. + * [QTBUG-13367] Make default application deployment removable & added .flags + modifier support for DEPLOYMENT items in Symbian. * [QTBUG-14280] Implement support for DEPLOYMENT.display_name in Symbian. * [QTBUG-13917] Localize .loc and .pkg content based on TRANSLATIONS. - * [QTBUG-15159] Use include(original mkspec) instead of copying of mkspec to default. + * [QTBUG-15159] Use include(original mkspec) instead of copying of mkspec to + default. * [QTBUG-15393] Resolve EPOCROOT in qt.conf using same logic as in .pro. * [QTBUG-15501] Fix symbian-mmp.conf include path. - * [QTBUG-15539] Use parent class function to generate Makefile headers in Symbian. - * [QTBUG-14472] Add NetworkServices capability automatically for network apps + * [QTBUG-15539] Use parent class function to generate Makefile headers. + * [QTBUG-14472] Add NetworkServices capability automatically for network apps. * [QTBUG-14736] Add libinfix support for QML plugins in Symbian. - * [QT-4375] Fix incorrect file name case for OpenGL libraries in symbian.conf. - * [QTBUG-16172] Use relative include instead of absolute in default qmake.conf. + * [QT-4375] Fix incorrect file name case for OpenGL libraries in + symbian.conf. + * [QTBUG-16172] Use relative include instead of absolute in default + qmake.conf. * [QTBUG-16221] Fix libinfixed usage in Symbian when def files are used. * [QTBUG-16261] Fix infinite loop in qmake when reading malformed .ts files. * [QTBUG-16298] Ignore static_and_shared in Symbian builds. + * [QTBUG-16477] Fix compile error when QT_NO_BEARERMANAGEMENT is defined. * [QTBUG-13769] Generate freeze targets in Symbian. - * [QTBUG-16691] Remove toolcheck from generic clean targets for symbian-sbsv2. - * [QT-4476] Fixed UTF-8 application names in device application menu in Symbian. + * [QTBUG-16691] Remove toolcheck from generic clean targets for + symbian-sbsv2. + * [QT-4476] Fixed UTF-8 application names in device application menu. * [QTBUG-16753] Improved QMAKE_POST_LINK support in symbian-sbsv2. - * [QTBUG-16881] Fix QMAKE_POST_LINK in Symbian for targets with special characters. - * [QTBUG-16888] No longer replace dash and dot in TARGET with underscore in Symbian. + * [QTBUG-16881] Fix QMAKE_POST_LINK for targets with special characters. + * [QTBUG-16888] No longer replace dash and dot in TARGET with underscore. + * [QTBUG-17187] Ensure that package generated against Symbian^3 SDK has no + Symbian^1 platforms as dependencies. * Fix partial upgrade package UID for libinfixed Qt. * Cleaned up sis_targets.prf. - + - QNetworkProxyFactory + * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing + network proxies configured on the device to be used by applications. + - QPaintEngine + * [QTBUG-16008] Fixed broken constant alpha blending on ARMV6. + * [QTBUG-16240] Fix blurry text in word-wrapped, center-aligned text items + with OpenVG. + - QSystemSemaphore + * [QTBUG-16615] Fix QSystemSemaphore handle management issues in Symbian. + - qtmain.lib + * [QTBUG-14735] Use qtmain.lib to provide entry point for all applications. + - QtQuick + * [QTBUG-15405] QML Plugins were not loaded when installed on different + drives. + - QtScript + * [QTBUG-14293] Enhanced JavaScript heap allocator. + * [QTBUG-15800] Creating QScriptEngine on the heap caused app crash. + * [QTBUG-15847] Add compiler optimizations. + * [QTBUG-16685] Fix crash in JavaScript stack allocator. + - QWidget + * [QTBUG-16578] In cases where the widget was created from the event loop + instead of main(), the middle three softkeys would not get the right + visibility and would leave a "hole" in the application where one could + see what was beneath it. + * [QT-4416, QTBUG-17288] On devices which lack support for transparency + in EGL surfaces, setting Qt::WA_TranslucentBackground on a widget + whose windowType() is Qt::Window causes that widget to be rendered + using the raster graphics system. - Tool scripts * [QTBUG-13886] Disallow patching capabilities of executables. * [QTBUG-13891] Add Location as self signable capability in patch_capabilities.pl. @@ -225,49 +269,10 @@ Qt for Symbian * Fix epocroot handling in createpackage.pl script. * Unify epocroot usage in createpackage and patch_capabilities scripts. - - qtmain.lib - * [QTBUG-14735] Use qtmain.lib to provide entry point for all Symbian applications. - - - QWidget - * [QT-4416, QTBUG-17288] On devices which lack support for transparency - in EGL surfaces, setting Qt::WA_TranslucentBackground on a widget - whose windowType() is Qt::Window causes that widget to be rendered - using the raster graphics system. - -Qt for Embedded Linux ---------------------- - - - - -DirectFB --------- - - - - -Qt for Windows CE ------------------ - - - - **************************************************************************** * Tools * **************************************************************************** - - Designer - * foo - - - qdoc3 - * bar - - - Linguist - * baz - - qmake * [QTBUG-14357] Make qmake to pass all UTF-8 characters unchanged through parser. -**************************************************************************** -* Important Behavior Changes * -**************************************************************************** - - - - -- cgit v0.12 From 0c24787a2f35a7b0585c9dfb3bf0a8cb34ce867f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 22 Feb 2011 10:03:14 +1000 Subject: Add missing test file. Missed in 1bcddaaf318fc37c71c5191913f3487c49444ec6 Change-Id: I4f71e5fb2b0e67a6e64ee64ae03b9d9cfc7a244f Task-number: QTBUG-17361 --- .../data/nestedPressDelay.qml | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml diff --git a/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml b/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml new file mode 100644 index 0000000..d0ee545 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/nestedPressDelay.qml @@ -0,0 +1,33 @@ +import QtQuick 1.0 + +Flickable { + property bool pressed: ma.pressed + width: 240 + height: 320 + contentWidth: 480 + contentHeight: 320 + flickableDirection: Flickable.HorizontalFlick + pressDelay: 50 + Flickable { + objectName: "innerFlickable" + flickableDirection: Flickable.VerticalFlick + width: 480 + height: 320 + contentWidth: 480 + contentHeight: 400 + pressDelay: 10000 + Rectangle { + y: 100 + anchors.horizontalCenter: parent.horizontalCenter + width: 240 + height: 100 + color: ma.pressed ? 'blue' : 'green' + MouseArea { + id: ma + objectName: "mouseArea" + anchors.fill: parent + } + } + } +} + -- cgit v0.12 From 5fa90e4bc83541dc23db150166157e2a3f04a668 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 21 Feb 2011 16:11:50 +1000 Subject: Prevent an animation from being registered to run twice. This could cause animations to start running that could not later be stopped. Change-Id: I320f50121f3566619f08181664d049b02e2848e5 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeanimation.cpp | 5 ++--- src/declarative/util/qdeclarativeanimation_p_p.h | 3 ++- .../declarative/qdeclarativeanimations/data/Double.qml | 14 ++++++++++++++ .../qdeclarativeanimations/data/doubleRegistrationBug.qml | 8 ++++++++ .../qdeclarativeanimations/tst_qdeclarativeanimations.cpp | 14 ++++++++++++++ 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeanimations/data/Double.qml create mode 100644 tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index f22b9dd..014d368 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -182,12 +182,11 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) { Q_D(QDeclarativeAbstractAnimation); if (!d->componentComplete) { - if (d->running && r == d->running) //don't re-register - return; d->running = r; if (r == false) d->avoidPropertyValueSourceStart = true; - else { + else if (!d->registered) { + d->registered = true; QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this)); engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()")); } diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index 84bc0ef..3c41565 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -210,7 +210,7 @@ public: : running(false), paused(false), alwaysRunToEnd(false), connectedTimeLine(false), componentComplete(true), avoidPropertyValueSourceStart(false), disableUserControl(false), - loopCount(1), group(0) {} + registered(false), loopCount(1), group(0) {} bool running:1; bool paused:1; @@ -219,6 +219,7 @@ public: bool componentComplete:1; bool avoidPropertyValueSourceStart:1; bool disableUserControl:1; + bool registered:1; int loopCount; diff --git a/tests/auto/declarative/qdeclarativeanimations/data/Double.qml b/tests/auto/declarative/qdeclarativeanimations/data/Double.qml new file mode 100644 index 0000000..b247fce --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/Double.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 + +Rectangle { + id: container + property bool on: false + border.color: "#ffffff" + color: "green" + width: 50 + height: 50 + NumberAnimation on x { + objectName: "animation" + running: container.on; from: 0; to: 600; loops: Animation.Infinite; duration: 2000 + } +} diff --git a/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml b/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml new file mode 100644 index 0000000..f0fdf9c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimations/data/doubleRegistrationBug.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +Rectangle { + width: 400; height: 400 + + Double { id: dub; on: parent.width < 800 } + Component.onCompleted: dub.on = false +} diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp index d1b7c1b..f7fee3b 100644 --- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp +++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp @@ -86,6 +86,7 @@ private slots: void runningTrueBug(); void nonTransitionBug(); void registrationBug(); + void doubleRegistrationBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -805,6 +806,19 @@ void tst_qdeclarativeanimations::registrationBug() QTRY_COMPARE(rect->property("value"), QVariant(int(100))); } +void tst_qdeclarativeanimations::doubleRegistrationBug() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/doubleRegistrationBug.qml"); + QDeclarativeRectangle *rect = qobject_cast(c.create()); + QVERIFY(rect != 0); + + QDeclarativeAbstractAnimation *anim = rect->findChild("animation"); + QVERIFY(anim != 0); + QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Stopped); +} + QTEST_MAIN(tst_qdeclarativeanimations) #include "tst_qdeclarativeanimations.moc" -- cgit v0.12 From 15ebe8a375542826278aac2b920f0e3dac3ffaea Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 21 Feb 2011 14:41:38 +1000 Subject: Another stab at fixing compilation on old Symbian platforms Task-number: QTBUG-17472 Reviewed-by: Martin Jones --- tools/qml/qml.pri | 6 ++---- tools/qml/qmlruntime.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri index 08cd506..5397384 100644 --- a/tools/qml/qml.pri +++ b/tools/qml/qml.pri @@ -25,12 +25,10 @@ symbian: { } !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { LIBS += -lsensrvclient -lsensrvutil - } - !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2): { SOURCES += $$PWD/deviceorientation_symbian.cpp - FORMS = $$PWD/recopts.ui \ - $$PWD/proxysettings.ui } + FORMS += $$PWD/recopts.ui \ + $$PWD/proxysettings.ui } else:maemo5 { QT += dbus HEADERS += $$PWD/texteditautoresizer_maemo5.h diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index c746d8e..36915d1 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -50,7 +50,7 @@ # include # include # include "ui_recopts_maemo5.h" -#elif !defined(__SERIES60_31__) && !defined(__S60_32__) +#else # include "ui_recopts.h" #endif -- cgit v0.12 From ceecec1083bac96bdb600020b01c299c389eaa8c Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 22 Feb 2011 11:39:56 +1000 Subject: Update QtGui def files Task-number: Reviewed-by: Martin Jones --- src/s60installs/bwins/QtGuiu.def | 2 ++ src/s60installs/eabi/QtGuiu.def | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index adf2b3c..a41f784 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -12950,4 +12950,6 @@ EXPORTS ?dynamicPageCount@QTextDocumentLayout@@QBEHXZ @ 12949 NONAME ; int QTextDocumentLayout::dynamicPageCount(void) const ?setWordSelectionEnabled@QTextControl@@QAEX_N@Z @ 12950 NONAME ; void QTextControl::setWordSelectionEnabled(bool) ?isWordSelectionEnabled@QTextControl@@QBE_NXZ @ 12951 NONAME ; bool QTextControl::isWordSelectionEnabled(void) const + ?assignedInputContext@QWidgetPrivate@@QBEPAVQInputContext@@XZ @ 12952 NONAME ; class QInputContext * QWidgetPrivate::assignedInputContext(void) const + ?updateMicroFocus@QLineControl@@IAEXXZ @ 12953 NONAME ; void QLineControl::updateMicroFocus(void) diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 564f530..2de88f2 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12145,4 +12145,6 @@ EXPORTS _ZTV19QTextDocumentLayout @ 12144 NONAME _ZN12QTextControl23setWordSelectionEnabledEb @ 12145 NONAME _ZNK12QTextControl22isWordSelectionEnabledEv @ 12146 NONAME + _ZN12QLineControl16updateMicroFocusEv @ 12147 NONAME + _ZNK14QWidgetPrivate20assignedInputContextEv @ 12148 NONAME -- cgit v0.12 From 2dad737a8cef6191a46eead8ea9940034d083884 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 22 Feb 2011 10:51:18 +1000 Subject: Fix auto test failure on mac. Allow for some error in the cursor position due to plaform specific offsets and the like. Change-Id: I2bef793596ab2a5e38cf77aee624bd9fdd5ca38c --- .../tst_qdeclarativetextedit.cpp | 60 ++++++++++----------- .../tst_qdeclarativetextinput.cpp | 61 +++++++++++----------- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index ba410ce..2c3ec7c 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1970,9 +1970,9 @@ void tst_qdeclarativetextedit::inputContextMouseHandler() QDeclarativeTextEdit edit; edit.setPos(0, 0); edit.setWidth(200); - edit.setText(text.mid(0, 5)); + edit.setText(text.mid(0, 12)); edit.setPos(0, 0); - edit.setCursorPosition(5); + edit.setCursorPosition(12); edit.setFocus(true); scene.addItem(&edit); view.show(); @@ -1985,15 +1985,15 @@ void tst_qdeclarativetextedit::inputContextMouseHandler() const qreal y = fm.height() / 2; QPoint position2 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); - QPoint position4 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 4)), y))); - QPoint position7 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 7)), y))); - QPoint position12 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 12)), y))); + QPoint position8 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 8)), y))); + QPoint position20 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 20)), y))); + QPoint position27 = view.mapFromScene(edit.mapToScene(QPointF(fm.width(text.mid(0, 27)), y))); QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); - QPoint globalPosition4 = view.viewport()->mapToGlobal(position4); - QPoint globalPosition7 = view.viewport()->mapToGlobal(position7); - QPoint globalPosition12 = view.viewport()->mapToGlobal(position12); + QPoint globalposition8 = view.viewport()->mapToGlobal(position8); + QPoint globalposition20 = view.viewport()->mapToGlobal(position20); + QPoint globalposition27 = view.viewport()->mapToGlobal(position27); - ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); + ic.sendEvent(QInputMethodEvent(text.mid(12), QList())); QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); @@ -2013,56 +2013,56 @@ void tst_qdeclarativetextedit::inputContextMouseHandler() QVERIFY(ic.cursor < 0); ic.eventType = QEvent::None; - { QMouseEvent mv(QEvent::MouseMove, position4, globalPosition4, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::None); - { QMouseEvent mv(QEvent::MouseMove, position12, globalPosition12, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::MouseMove); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::NoModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one. ic.eventType = QEvent::None; - QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position12); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::NoModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; // And in the other direction. - QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position12); + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; - QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position12); + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonPress); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::RightButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; - { QMouseEvent mv(QEvent::MouseMove, position7, globalPosition7, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::MouseMove); - QCOMPARE(ic.eventPosition, position7); - QCOMPARE(ic.eventGlobalPosition, globalPosition7); + QCOMPARE(ic.eventPosition, position20); + QCOMPARE(ic.eventGlobalPosition, globalposition20); QCOMPARE(ic.eventButton, Qt::RightButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 2); + QVERIFY(ic.cursor >= 7 && ic.cursor <= 9); ic.eventType = QEvent::None; { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index b8f73bd..49a05a3 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -1958,7 +1958,8 @@ void tst_qdeclarativetextinput::inputContextMouseHandler() view.setInputContext(&ic); QDeclarativeTextInput input; input.setWidth(200); - input.setText(text.mid(0, 5)); + input.setText(text.mid(0, 12)); + input.setCursorPosition(12); input.setPos(0, 0); input.setFocus(true); scene.addItem(&input); @@ -1967,21 +1968,19 @@ void tst_qdeclarativetextinput::inputContextMouseHandler() QTest::qWaitForWindowShown(&view); QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); - ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); - QFontMetricsF fm(input.font()); const qreal y = fm.height() / 2; QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y))); - QPoint position4 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 4)), y))); - QPoint position7 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 7)), y))); - QPoint position12 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 12)), y))); + QPoint position8 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 8)), y))); + QPoint position20 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 20)), y))); + QPoint position27 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 27)), y))); QPoint globalPosition2 = view.viewport()->mapToGlobal(position2); - QPoint globalPosition4 = view.viewport()->mapToGlobal(position4); - QPoint globalPosition7 = view.viewport()->mapToGlobal(position7); - QPoint globalPosition12 = view.viewport()->mapToGlobal(position12); + QPoint globalposition8 = view.viewport()->mapToGlobal(position8); + QPoint globalposition20 = view.viewport()->mapToGlobal(position20); + QPoint globalposition27 = view.viewport()->mapToGlobal(position27); - ic.sendEvent(QInputMethodEvent(text.mid(5), QList())); + ic.sendEvent(QInputMethodEvent(text.mid(12), QList())); QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2); QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); @@ -2001,56 +2000,56 @@ void tst_qdeclarativetextinput::inputContextMouseHandler() QVERIFY(ic.cursor < 0); ic.eventType = QEvent::None; - { QMouseEvent mv(QEvent::MouseMove, position4, globalPosition4, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::None); - { QMouseEvent mv(QEvent::MouseMove, position12, globalPosition12, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::MouseMove); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::NoModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); // 15 is expected but some platforms may be off by one. ic.eventType = QEvent::None; - QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position12); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonRelease); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::NoModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; // And in the other direction. - QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position12); + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonDblClick); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::LeftButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; - QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position12); + QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27); QCOMPARE(ic.eventType, QEvent::MouseButtonPress); - QCOMPARE(ic.eventPosition, position12); - QCOMPARE(ic.eventGlobalPosition, globalPosition12); + QCOMPARE(ic.eventPosition, position27); + QCOMPARE(ic.eventGlobalPosition, globalposition27); QCOMPARE(ic.eventButton, Qt::RightButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 7); + QVERIFY(ic.cursor >= 14 && ic.cursor <= 16); ic.eventType = QEvent::None; - { QMouseEvent mv(QEvent::MouseMove, position7, globalPosition7, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); + { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); QApplication::sendEvent(view.viewport(), &mv); } QCOMPARE(ic.eventType, QEvent::MouseMove); - QCOMPARE(ic.eventPosition, position7); - QCOMPARE(ic.eventGlobalPosition, globalPosition7); + QCOMPARE(ic.eventPosition, position20); + QCOMPARE(ic.eventGlobalPosition, globalposition20); QCOMPARE(ic.eventButton, Qt::RightButton); QCOMPARE(ic.eventModifiers, Qt::ControlModifier); - QCOMPARE(ic.cursor, 2); + QVERIFY(ic.cursor >= 7 && ic.cursor <= 9); ic.eventType = QEvent::None; { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier); -- cgit v0.12 From b254be20c03d4dbfc1803cd40dc95d52115b955c Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 22 Feb 2011 13:33:12 +1000 Subject: Fix animations with alwaysRunToEnd that are frequently stopped/started. A previous refactoring of the animation logic introduced a regression -- 'restart' rather than 'continue' behavior. Change-Id: I8ade2286298fad48f5e268793a0b2571884bc5d0 Task-number: QTBUG-16736 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeanimation.cpp | 5 ++++- .../tst_qdeclarativeanimations.cpp | 25 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 014d368..58c346c 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -203,6 +203,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) d->running = r; if (d->running) { + bool supressStart = false; if (d->alwaysRunToEnd && d->loopCount != 1 && qtAnimation()->state() == QAbstractAnimation::Running) { //we've restarted before the final loop finished; restore proper loop count @@ -210,6 +211,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) qtAnimation()->setLoopCount(d->loopCount); else qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount); + supressStart = true; //we want the animation to continue, rather than restart } if (!d->connectedTimeLine) { @@ -217,7 +219,8 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) this, SLOT(timelineComplete())); d->connectedTimeLine = true; } - d->commence(); + if (!supressStart) + d->commence(); emit started(); } else { if (d->alwaysRunToEnd) { diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp index f7fee3b..e2a54c0 100644 --- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp +++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp @@ -87,6 +87,7 @@ private slots: void nonTransitionBug(); void registrationBug(); void doubleRegistrationBug(); + void alwaysRunToEndRestartBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -819,6 +820,30 @@ void tst_qdeclarativeanimations::doubleRegistrationBug() QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimation::Stopped); } +//QTBUG-16736 +void tst_qdeclarativeanimations::alwaysRunToEndRestartBug() +{ + QDeclarativeRectangle rect; + QDeclarativePropertyAnimation animation; + animation.setTarget(&rect); + animation.setProperty("x"); + animation.setTo(200); + animation.setDuration(1000); + animation.setLoops(-1); + animation.setAlwaysRunToEnd(true); + QVERIFY(animation.loops() == -1); + QVERIFY(animation.alwaysRunToEnd() == true); + animation.start(); + animation.stop(); + animation.start(); + animation.stop(); + QTest::qWait(500); + QVERIFY(rect.x() != qreal(200)); + QTest::qWait(800); + QTIMED_COMPARE(rect.x(), qreal(200)); + QCOMPARE(static_cast(&animation)->qtAnimation()->state(), QAbstractAnimation::Stopped); +} + QTEST_MAIN(tst_qdeclarativeanimations) #include "tst_qdeclarativeanimations.moc" -- cgit v0.12 From e32f432127bd049c6c11431055360c536e259114 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 22 Feb 2011 09:25:53 +0100 Subject: Cocoa: Sheets looses focus when moving parent window The reason seems to be that we need to be more careful what we answer when cocoa ask us if a sheet should get main window status, and if the parent window should get key status. So we add in two extra checks so we can return the correct answer. Task-number: QTBUG-15474 Reviewed-by: msorvig --- src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 9c110fd..6254061 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -89,6 +89,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if (QApplicationPrivate::isBlockedByModal(widget)) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); @@ -100,6 +102,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if ([self isSheet]) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); -- cgit v0.12 From 0442b383dced6b5cc31e4fc2bf939e3125354f82 Mon Sep 17 00:00:00 2001 From: Nikos Giotis Date: Wed, 23 Feb 2011 18:50:02 +0200 Subject: Fixed problematic lupdate & lrelease links in Qt-Linguist documentation. --- doc/src/internationalization/linguist-manual.qdoc | 103 ++++++++++++---------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/doc/src/internationalization/linguist-manual.qdoc b/doc/src/internationalization/linguist-manual.qdoc index 1f413f9..f4cce3a 100644 --- a/doc/src/internationalization/linguist-manual.qdoc +++ b/doc/src/internationalization/linguist-manual.qdoc @@ -46,10 +46,10 @@ at the person with overall responsibility for the release of the application. They will typically coordinate the work of the software engineers and the translator. The chapter describes the - use of two tools. The \l{lupdate} tool is used to synchronize - source code and translations. The \l{lrelease} tool is used to - create run-time translation files for use by the released - application. + use of two tools. The \l{linguist-manager.html#lupdate}{lupdate} + tool is used to synchronize source code and translations. The + \l{linguist-manager.html#lrelease}{lrelease} tool is used to create + run-time translation files for use by the released application. The \l{linguist-translators.html}{Translators} chapter is for translators. It describes the use of the \QL tool. @@ -149,20 +149,16 @@ \previouspage Qt Linguist Manual \nextpage Qt Linguist Manual: Translators - \keyword lupdate - \keyword lrelease - Two tools are provided for the release manager, \l lupdate and \l lrelease. These tools can process \l qmake project files, or operate directly on the file system. \section1 Qt Project Files - The easiest method to use \l{#lupdate} {lupdate} and \l{#lrelease} - {lrelease} is by specifying a \c .pro Qt project file. There must - be an entry in the \c TRANSLATIONS section of the project file for - each language that is additional to the native language. A typical - entry looks like this: + The easiest method to use \l lupdate and \l lrelease is by specifing + a \c .pro Qt project file. There must be an entry in the \c TRANSLATIONS + section of the project file for each language that is additional to + the native language. A typical entry looks like this: \snippet examples/linguist/arrowpad/arrowpad.pro 1 @@ -203,7 +199,6 @@ \snippet doc/src/snippets/code/doc_src_linguist-manual.qdoc 3 - \target lupdate manual \section1 lupdate Usage: \c {lupdate myproject.pro} @@ -271,7 +266,7 @@ are available the application will detect them and use them automatically. - Note that lrelease will only incorporate translations that are + Note that \l lrelease will only incorporate translations that are marked as "finished". Otherwise the original text will be used instead. @@ -606,8 +601,8 @@ If the source context shows the wrong source line, it probably means the translation file is out of sync with the source files. - To re-sync the translation file with the source files, see the - \l{lupdate manual} {lupdate manual}. + To re-sync the translation file with the source files, see the + \l{linguist-manager.html#lupdate}{lupdate} manual. The Sources and Forms window is a dockable window. If it has been closed, it can be made visible again by pressing the \e{Sources @@ -947,8 +942,8 @@ \list \o TS \e {translation source files} \BR are human-readable XML files containing source phrases and their translations. These files are - usually created and updated by \l lupdate and are specific to an - application. + usually created and updated by \l{linguist-manager.html#lupdate}{lupdate} + and are specific to an application. \o \c .xlf \e {XLIFF files} \BR are human-readable XML files that adhere to the international XML Localization Interchange File Format. \QL can be used to edit XLIFF files generated by other programs. However, for @@ -957,7 +952,8 @@ are not supported. \o QM \e {Qt message files} \BR are binary files that contain translations used by an application at run-time. These files are - generated by \l lrelease, but can also be generated by \QL. + generated by \l{linguist-manager.html#lrelease}{lrelease}, but can also + be generated by \QL. \o \c .qph \e {Qt phrase book files} \BR are human-readable XML files containing standard phrases and their translations. These files are created and updated by \QL and may be used by any @@ -982,13 +978,15 @@ name, format and/or put in a different location. \o \gui {Release} \BR create a Qt message QM file with the same base name as the current translation source file. The release manager's - command line tool \l lrelease performs the same function on - \e all of an application's translation source files. + command line tool \l{linguist-manager.html#lrelease}{lrelease} + performs the same function on \e all of an application's translation + source files. \o \gui {Release As...} \BR pops up a save as file dialog. The filename entered will be a Qt message QM file of the translation based on the current translation source file. The release manager's - command line tool \l lrelease performs the same function on - \e all of an application's translation source files. + command line tool \l{linguist-manager.html#lrelease}{lrelease} + performs the same function on \e all of an application's translation + source files. \o \gui {Print... Ctrl+P} \BR pops up a print dialog. If you click OK the translation source and the translations will be printed. \o \gui {Exit Ctrl+Q} \BR closes \QL. @@ -1262,28 +1260,32 @@ Translation files are created as follows: \list 1 - \o Run \l lupdate initially to generate the first set of TS - translation source files with all the user-visible text but no - translations. + \o Run \l {linguist-manager.html#lupdate}{lupdate} initially to + generate the first set of TS translation source files with all the + user-visible text but no translations. \o The TS files are given to the translator who adds translations using \QL. \QL takes care of any changed or deleted source text. - \o Run \l lupdate to incorporate any new text added to the - application. \l lupdate synchronizes the user-visible text from the - application with the translations; it does not destroy any data. + \o Run \l{linguist-manager.html#lupdate}{lupdate} to incorporate any new + text added to the application. \l{linguist-manager.html#lupdate}{lupdate} + synchronizes the user-visible text from the application with the + translations; it does not destroy any data. \o Steps 2 and 3 are repeated as often as necessary. - \o When a release of the application is needed \l lrelease is run to + \o When a release of the application is needed + \l{linguist-manager.html#lrelease}{lrelease} is run to read the TS files and produce the QM files used by the application at runtime. \endlist - For \l lupdate to work successfully, it must know which translation - files to produce. The files are simply listed in the application's \c + For \l{linguist-manager.html#lupdate}{lupdate} to work successfully, + it must know which translation files to produce. The files are simply + listed in the application's \c .pro Qt project file, for example: \snippet examples/linguist/arrowpad/arrowpad.pro 1 - If your sources contain genuine non-Latin1 strings, \l lupdate needs + If your sources contain genuine non-Latin1 strings, + \l{linguist-manager.html#lupdate}{lupdate} needs to be told about it in the \c .pro file by using, for example, the following line: @@ -1291,7 +1293,8 @@ CODECFORTR = UTF-8 \endcode - See the \l lupdate and \l lrelease sections. + See the \l{linguist-manager.html#lupdate}{lupdate} and + \l{linguist-manager.html#lrelease}{lrelease} sections. \section2 Loading Translations @@ -1354,14 +1357,14 @@ \section2 Distinguishing Between Identical Translatable Strings - The \l lupdate program automatically provides a \e context for every - source text. This context is the class name of the class that contains - the \c tr() call. This is sufficient in the vast majority of cases. - Sometimes however, the translator will need further information to - uniquely identify a source text; for example, a dialog that contained - two separate frames, each of which contained an "Enabled" option would - need each identified because in some languages the translation would - differ between the two. This is easily achieved using the + The \l{linguist-manager.html#lupdate}{lupdate} program automatically + provides a \e context for every source text. This context is the class + name of the class that contains the \c tr() call. This is sufficient in + the vast majority of cases. Sometimes however, the translator will need + further information to uniquely identify a source text; for example, + a dialog that contained two separate frames, each of which contained an + "Enabled" option would need each identified because in some languages the + translation would differ between the two. This is easily achieved using the two argument form of the \c tr() call, e.g. \snippet doc/src/snippets/code/doc_src_linguist-manual.qdoc 10 @@ -1410,7 +1413,8 @@ replaced with count's value (e.g., "6 item(s) replaced"). To handle plural forms in the native language, you need to load a - translation file for this language, too. \l lupdate has the + translation file for this language, too. + \l{linguist-manager.html#lupdate}{lupdate} has the \c -pluralonly command line option, which allows the creation of TS files containing only entries with plural forms. @@ -1421,8 +1425,9 @@ \section2 Coping With C++ Namespaces C++ namespaces and the \c {using namespace} statement can confuse - \l lupdate. It will interpret \c MyClass::tr() as meaning just - that, not as \c MyNamespace::MyClass::tr(), even if \c MyClass is + \l{linguist-manager.html#lupdate}{lupdate}. It will interpret + \c MyClass::tr() as meaning just that, not as + \c MyNamespace::MyClass::tr(), even if \c MyClass is defined in the \c MyNamespace namespace. Runtime translation of these strings will fail because of that. @@ -1449,7 +1454,8 @@ If you need to have translatable text completely outside a function, there are two macros to help: QT_TR_NOOP() and QT_TRANSLATE_NOOP(). - These macros merely mark the text for extraction by \l{lupdate}. + These macros merely mark the text for extraction by + \l{linguist-manager.html#lupdate}{lupdate}. The macros expand to just the text (without the context). Example of QT_TR_NOOP(): @@ -1484,8 +1490,9 @@ applications for translation. At the beginning of a project add the translation source files to be - used to the project file and add calls to \l lupdate and \l lrelease to - the makefile. + used to the project file and add calls to + \l{linguist-manager.html#lupdate}{lupdate} and + \l{linguist-manager.html#lrelease}{lrelease} to the makefile. During the project all the programmer must do is wrap any user-visible text in \c tr() calls. They should also use the two argument form for -- cgit v0.12