From f3f4e93f482c1ff579cb78cc1765a6930de3d766 Mon Sep 17 00:00:00 2001 From: Martin Pejcoch Date: Mon, 1 Nov 2010 18:00:23 +0100 Subject: Use file names in header include guards instead of namespace names dumpcpp used "-n" option value for guard macros in headers which was wrong, because that implies that every QtAx COM wrapper must have a unique namespace. Task-number: QTBUG-14383 Reviewed-by: Prasanth --- tools/activeqt/dumpcpp/main.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/activeqt/dumpcpp/main.cpp b/tools/activeqt/dumpcpp/main.cpp index bb65806..f95d31d 100644 --- a/tools/activeqt/dumpcpp/main.cpp +++ b/tools/activeqt/dumpcpp/main.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -129,10 +130,10 @@ void writeEnums(QTextStream &out, const QMetaObject *mo) } } -void writeHeader(QTextStream &out, const QByteArray &nameSpace) +void writeHeader(QTextStream &out, const QByteArray &nameSpace, const QString &outFileName) { - out << "#ifndef QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl; - out << "#define QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl; + out << "#ifndef QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl; + out << "#define QAX_DUMPCPP_" << outFileName.toUpper() << "_H" << endl; out << endl; out << "// Define this symbol to __declspec(dllexport) or __declspec(dllimport)" << endl; out << "#ifndef " << nameSpace.toUpper() << "_EXPORT" << endl; @@ -880,7 +881,7 @@ bool generateClass(QAxObject *object, const QByteArray &className, const QByteAr out << "****************************************************************************/" << endl; out << endl; - writeHeader(out, nameSpace); + writeHeader(out, nameSpace, outfile.fileName()); generateNameSpace(out, mo, nameSpace); // close namespace file @@ -1040,7 +1041,8 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O declOut << "****************************************************************************/" << endl; declOut << endl; - writeHeader(declOut, libName.toLatin1()); + QFileInfo cppFileInfo(cppFile); + writeHeader(declOut, libName.toLatin1(), cppFileInfo.fileName()); UINT typeCount = typelib->GetTypeInfoCount(); if (declFile.isOpen()) { -- cgit v0.12 From 2ded1317af10b4565d497e4e1b8b6da85c49904f Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Mon, 27 Dec 2010 14:56:18 -0300 Subject: QScriptValueIterator: fix iterateArray and iterateString tests This removes the assumption that the properties will be ordered by index and that length will be visited after the indexes, which are not part of QScriptValueIterator API. Reviewed-by: Kent Hansen --- .../tst_qscriptvalueiterator.cpp | 230 +++++++++++++-------- 1 file changed, 143 insertions(+), 87 deletions(-) diff --git a/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp b/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp index eb7f94f..03e5c0f 100644 --- a/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp +++ b/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp @@ -212,106 +212,138 @@ void tst_QScriptValueIterator::iterateBackward() void tst_QScriptValueIterator::iterateArray_data() { - QTest::addColumn("inputPropertyNames"); - QTest::addColumn("inputPropertyValues"); QTest::addColumn("propertyNames"); QTest::addColumn("propertyValues"); - QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList(); + QTest::newRow("no elements") << QStringList() << QStringList(); QTest::newRow("0=foo, 1=barr") << (QStringList() << "0" << "1") - << (QStringList() << "foo" << "bar") - << (QStringList() << "0" << "1") << (QStringList() << "foo" << "bar"); QTest::newRow("0=foo, 3=barr") << (QStringList() << "0" << "1" << "2" << "3") - << (QStringList() << "foo" << "" << "" << "bar") - << (QStringList() << "0" << "1" << "2" << "3") << (QStringList() << "foo" << "" << "" << "bar"); } void tst_QScriptValueIterator::iterateArray() { - QFETCH(QStringList, inputPropertyNames); - QFETCH(QStringList, inputPropertyValues); QFETCH(QStringList, propertyNames); QFETCH(QStringList, propertyValues); QScriptEngine engine; QScriptValue array = engine.newArray(); - for (int i = 0; i < inputPropertyNames.size(); ++i) { - array.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i)); + + // Fill the array + for (int i = 0; i < propertyNames.size(); ++i) { + array.setProperty(propertyNames.at(i), propertyValues.at(i)); } + // Iterate thru array properties. Note that the QScriptValueIterator doesn't guarantee + // any order on the iteration! int length = array.property("length").toInt32(); QCOMPARE(length, propertyNames.size()); + + bool iteratedThruLength = false; + QHash arrayProperties; QScriptValueIterator it(array); - for (int i = 0; i < length; ++i) { - QCOMPARE(it.hasNext(), true); + + // Iterate forward + while (it.hasNext()) { it.next(); - QCOMPARE(it.name(), propertyNames.at(i)); - QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); - QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); - QCOMPARE(it.value().toString(), propertyValues.at(i)); + + const QString name = it.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it.value()); + QCOMPARE(it.flags(), array.propertyFlags(name)); + QVERIFY(it.value().strictlyEquals(array.property(name))); } - QVERIFY(it.hasNext()); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("length")); - QVERIFY(it.value().isNumber()); - QCOMPARE(it.value().toInt32(), length); - QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); - it.previous(); - QCOMPARE(it.hasPrevious(), length > 0); - for (int i = length - 1; i >= 0; --i) { - it.previous(); - QCOMPARE(it.name(), propertyNames.at(i)); - QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); - QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); - QCOMPARE(it.value().toString(), propertyValues.at(i)); - QCOMPARE(it.hasPrevious(), i > 0); + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); } - QCOMPARE(it.hasPrevious(), false); - // hasNext() and hasPrevious() cache their result; verify that the result is in sync - if (length > 1) { - QVERIFY(it.hasNext()); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("0")); - QVERIFY(it.hasNext()); + // Iterate backwards + arrayProperties.clear(); + iteratedThruLength = false; + it.toBack(); + + while (it.hasPrevious()) { it.previous(); - QCOMPARE(it.name(), QString::fromLatin1("0")); - QVERIFY(!it.hasPrevious()); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("0")); - QVERIFY(it.hasPrevious()); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("1")); - } - { - // same test as object: - QScriptValue originalArray = engine.newArray(); - for (int i = 0; i < inputPropertyNames.size(); ++i) { - originalArray.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i)); + + const QString name = it.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; } - QScriptValue array = originalArray.toObject(); - int length = array.property("length").toInt32(); - QCOMPARE(length, propertyNames.size()); - QScriptValueIterator it(array); - for (int i = 0; i < length; ++i) { - QCOMPARE(it.hasNext(), true); - it.next(); - QCOMPARE(it.name(), propertyNames.at(i)); - QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); - QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); - QCOMPARE(it.value().toString(), propertyValues.at(i)); + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it.value()); + QCOMPARE(it.flags(), array.propertyFlags(name)); + QVERIFY(it.value().strictlyEquals(array.property(name))); + } + + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); + } + + // ### Do we still need this test? + // Forward test again but as object + arrayProperties.clear(); + iteratedThruLength = false; + QScriptValue arrayObject = engine.toObject(array); + QScriptValueIterator it2(arrayObject); + + while (it2.hasNext()) { + it2.next(); + + const QString name = it2.name(); + if (name == QString::fromLatin1("length")) { + QVERIFY(it2.value().isNumber()); + QCOMPARE(it2.value().toInt32(), length); + QCOMPARE(it2.flags(), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; } - QCOMPARE(it.hasNext(), true); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("length")); + + // Storing the properties we iterate in a hash to compare with test data. + QVERIFY2(!arrayProperties.contains(name), "property appeared more than once during iteration."); + arrayProperties.insert(name, it2.value()); + QCOMPARE(it2.flags(), arrayObject.propertyFlags(name)); + QVERIFY(it2.value().strictlyEquals(arrayObject.property(name))); + } + + // Verify properties + QVERIFY(iteratedThruLength); + QCOMPARE(arrayProperties.size(), propertyNames.size()); + for (int i = 0; i < propertyNames.size(); ++i) { + QVERIFY(arrayProperties.contains(propertyNames.at(i))); + QCOMPARE(arrayProperties.value(propertyNames.at(i)).toString(), propertyValues.at(i)); } } @@ -419,35 +451,59 @@ void tst_QScriptValueIterator::iterateString() QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao")); QVERIFY(str.isString()); QScriptValue obj = str.toObject(); + QVERIFY(obj.property("length").isNumber()); int length = obj.property("length").toInt32(); QCOMPARE(length, 4); + QScriptValueIterator it(obj); - for (int i = 0; i < length; ++i) { - QCOMPARE(it.hasNext(), true); - QString indexStr = QScriptValue(&engine, i).toString(); + QHash stringProperties; + bool iteratedThruLength = false; + + while (it.hasNext()) { it.next(); - QCOMPARE(it.name(), indexStr); - QCOMPARE(it.flags(), obj.propertyFlags(indexStr)); - QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true); + const QString name = it.name(); + + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration."); + stringProperties.insert(name, it.value()); + QCOMPARE(it.flags(), obj.propertyFlags(name)); + QVERIFY(it.value().strictlyEquals(obj.property(name))); } - QVERIFY(it.hasNext()); - it.next(); - QCOMPARE(it.name(), QString::fromLatin1("length")); - QVERIFY(it.value().isNumber()); - QCOMPARE(it.value().toInt32(), length); - QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); - it.previous(); - QCOMPARE(it.hasPrevious(), length > 0); - for (int i = length - 1; i >= 0; --i) { + QVERIFY(iteratedThruLength); + QCOMPARE(stringProperties.size(), length); + + // And going backwards + iteratedThruLength = false; + stringProperties.clear(); + it.toBack(); + + while (it.hasPrevious()) { it.previous(); - QString indexStr = QScriptValue(&engine, i).toString(); - QCOMPARE(it.name(), indexStr); - QCOMPARE(it.flags(), obj.propertyFlags(indexStr)); - QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true); - QCOMPARE(it.hasPrevious(), i > 0); + const QString name = it.name(); + + if (name == QString::fromLatin1("length")) { + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable); + QVERIFY2(!iteratedThruLength, "'length' appeared more than once during iteration."); + iteratedThruLength = true; + continue; + } + + QVERIFY2(!stringProperties.contains(name), "property appeared more than once during iteration."); + stringProperties.insert(name, it.value()); + QCOMPARE(it.flags(), obj.propertyFlags(name)); + QVERIFY(it.value().strictlyEquals(obj.property(name))); } - QCOMPARE(it.hasPrevious(), false); } static QScriptValue myGetterSetter(QScriptContext *ctx, QScriptEngine *) -- cgit v0.12 From c848769c06515675caa2dfaf32c6e20be87e869f Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Wed, 29 Dec 2010 15:10:03 -0300 Subject: QtScript: add more tests to QObject binding This adds a few more tests to exercise dynamic properties and child objects as properties of QObject binding. Some of these were implicitly tested elsewhere, but is good to have the "properties" clearly stated in our test suite. Reviewed-by: Jedrzej Nowacki --- .../qscriptextqobject/tst_qscriptextqobject.cpp | 111 +++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index e9d2d1f..cb29586 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -543,6 +543,10 @@ private slots: void getSetStaticProperty_customGetterSetter(); void getSetStaticProperty_methodPersistence(); void getSetDynamicProperty(); + void getSetDynamicProperty_deleteFromCpp(); + void getSetDynamicProperty_hideChildObject(); + void getSetDynamicProperty_setBeforeGet(); + void getSetDynamicProperty_doNotHideJSProperty(); void getSetChildren(); void callQtInvokable(); void connectAndDisconnect(); @@ -555,6 +559,7 @@ private slots: void transferInvokable(); void findChild(); void findChildren(); + void childObjects(); void overloadedSlots(); void enumerate_data(); void enumerate(); @@ -1035,6 +1040,69 @@ void tst_QScriptExtQObject::getSetDynamicProperty() QCOMPARE(m_engine->evaluate("myObject.hasOwnProperty('dynamicProperty')").toBoolean(), false); } +void tst_QScriptExtQObject::getSetDynamicProperty_deleteFromCpp() +{ + QScriptValue val = m_engine->newQObject(m_myObject); + + m_myObject->setProperty("dynamicFromCpp", 1234); + QVERIFY(val.property("dynamicFromCpp").strictlyEquals(QScriptValue(m_engine, 1234))); + + m_myObject->setProperty("dynamicFromCpp", 4321); + QVERIFY(val.property("dynamicFromCpp").strictlyEquals(QScriptValue(m_engine, 4321))); + QCOMPARE(m_myObject->property("dynamicFromCpp").toInt(), 4321); + + // In this case we delete the property from C++ + m_myObject->setProperty("dynamicFromCpp", QVariant()); + QVERIFY(!m_myObject->property("dynamicFromCpp").isValid()); + QVERIFY(!val.property("dynamicFromCpp").isValid()); +} + +void tst_QScriptExtQObject::getSetDynamicProperty_hideChildObject() +{ + QScriptValue val = m_engine->newQObject(m_myObject); + + // Add our named child and access it + QObject *child = new QObject(m_myObject); + child->setObjectName("testName"); + QCOMPARE(val.property("testName").toQObject(), child); + + // Dynamic properties have precedence, hiding the child object + m_myObject->setProperty("testName", 42); + QVERIFY(val.property("testName").strictlyEquals(QScriptValue(m_engine, 42))); + + // Remove dynamic property + m_myObject->setProperty("testName", QVariant()); + QCOMPARE(val.property("testName").toQObject(), child); +} + +void tst_QScriptExtQObject::getSetDynamicProperty_setBeforeGet() +{ + QScriptValue val = m_engine->newQObject(m_myObject); + + m_myObject->setProperty("dynamic", 1111); + val.setProperty("dynamic", 42); + + QVERIFY(val.property("dynamic").strictlyEquals(QScriptValue(m_engine, 42))); + QCOMPARE(m_myObject->property("dynamic").toInt(), 42); +} + +void tst_QScriptExtQObject::getSetDynamicProperty_doNotHideJSProperty() +{ + QScriptValue val = m_engine->newQObject(m_myObject); + + // Set property on JS and dynamically on our QObject + val.setProperty("x", 42); + m_myObject->setProperty("x", 2222); + + QEXPECT_FAIL("", "", Continue); + + // JS should see the original JS value + QVERIFY(val.property("x").strictlyEquals(QScriptValue(m_engine, 42))); + + // The dynamic property is intact + QCOMPARE(m_myObject->property("x").toInt(), 2222); +} + void tst_QScriptExtQObject::getSetChildren() { QScriptValue mobj = m_engine->evaluate("myObject"); @@ -2661,6 +2729,49 @@ void tst_QScriptExtQObject::findChildren() delete child; } +void tst_QScriptExtQObject::childObjects() +{ + QObject *child1 = new QObject(m_myObject); + child1->setObjectName("child1"); + QObject *child2 = new QObject(m_myObject); + QScriptValue wrapped = m_engine->newQObject(m_myObject); + + QVERIFY(wrapped.property("child1").isQObject()); + QCOMPARE(wrapped.property("child1").toQObject(), child1); + QVERIFY(!wrapped.property("child2").isQObject()); + QVERIFY(!wrapped.property("child2").isValid()); + + // Setting the name later + child2->setObjectName("child2"); + + QVERIFY(wrapped.property("child1").isQObject()); + QCOMPARE(wrapped.property("child1").toQObject(), child1); + QVERIFY(wrapped.property("child2").isQObject()); + QCOMPARE(wrapped.property("child2").toQObject(), child2); + + // Adding a child later + QObject *child3 = new QObject(m_myObject); + child3->setObjectName("child3"); + + QVERIFY(wrapped.property("child3").isQObject()); + QCOMPARE(wrapped.property("child3").toQObject(), child3); + + // Changing a child name + child1->setObjectName("anotherName"); + + QVERIFY(!wrapped.property("child1").isValid()); + QVERIFY(wrapped.property("anotherName").isQObject()); + QCOMPARE(wrapped.property("anotherName").toQObject(), child1); + + // Creating another object wrapper excluding child from + // properties. + QScriptValue wrapped2 = m_engine->newQObject(m_myObject, QScriptEngine::QtOwnership, QScriptEngine::ExcludeChildObjects); + + QVERIFY(!wrapped2.property("anotherName").isValid()); + QVERIFY(!wrapped2.property("child2").isValid()); + QVERIFY(!wrapped2.property("child3").isValid()); +} + void tst_QScriptExtQObject::overloadedSlots() { // should pick myOverloadedSlot(double) -- cgit v0.12 From 66669ef4e0abf48fcf8282fc4f746f3f45f0cca0 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Wed, 19 Jan 2011 10:04:42 +0100 Subject: Allow hard-coding the Unix temp path This came as a requirement from a device manufacturer that couldn't agree whether tmp is /var/tmp or /tmp, which lead to all kinds of side effects. QSharedMemory token generation was broken depending on where TMPDIR pointed to. This patch allows hard-coding a Qt-wide temp-dir in qplatformdefs. Reviewed-by: Robert Griebl --- src/corelib/io/qfilesystemengine_unix.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 40fb0c0..6acd811 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -612,10 +612,14 @@ QString QFileSystemEngine::rootPath() QString QFileSystemEngine::tempPath() { +#ifdef QT_UNIX_TEMP_PATH_OVERRIDE + return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE); +#else QString temp = QFile::decodeName(qgetenv("TMPDIR")); if (temp.isEmpty()) temp = QLatin1String("/tmp/"); return QDir::cleanPath(temp); +#endif } bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path) -- cgit v0.12 From 4c57b9d3f1865beb87120fc4691241c57a2bfb01 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Fri, 21 Jan 2011 16:03:41 +0100 Subject: Doc: Fixing typo --- doc/src/declarative/basictypes.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 463e4a3..99f1bed 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -582,7 +582,7 @@ An enumeration type consists of a set of named values. - An enumeration value may be specifed as either a string: + An enumeration value may be specified as either a string: \qml Text { horizontalAlignment: "AlignRight" } \endqml -- cgit v0.12 From 972fcb6de69fb7ed3ae8147498ceb5d2ac79f057 Mon Sep 17 00:00:00 2001 From: Ademar de Souza Reis Jr Date: Fri, 21 Jan 2011 08:19:00 -0600 Subject: QPainterPath: Ignore calls with NaN/Infinite parameters QPainterPath can't handle NaNs/Inf inside coordinates, but instead of safely ignoring or aborting an operation, it shows a warning and keeps going on, with undefined behavior. Sometimes leading to infinite loops, leaks or crashes (see qtwebkit example below). This is particularly bad when QPainterPath is used to render content from untrusted sources (web or user data). As an example, there's a qtwebkit bug where the browser crashes when a particular SVG is loaded: https://bugs.webkit.org/show_bug.cgi?id=51698. Please note that "untrusted sources" doesn't apply only to network sources. This behavior can probably be exploited on applications such as file-browsers with previews enabled. Task-number: QTBUG-16664 Signed-off-by: Ademar de Souza Reis Jr Merge-request: 1026 Reviewed-by: Marius Storm-Olsen Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpainterpath.cpp | 66 ++++++++++++++++++++-------- tests/auto/qpainterpath/tst_qpainterpath.cpp | 46 +++++++++++++++++++ 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index fddc4d0..9f49b2f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -636,10 +636,14 @@ void QPainterPath::moveTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::moveTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -682,10 +686,14 @@ void QPainterPath::lineTo(const QPointF &p) #ifdef QPP_DEBUG printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y()); #endif + + if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(p.x()) || qt_is_nan(p.y())) - qWarning("QPainterPath::lineTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -737,11 +745,15 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF & printf("QPainterPath::cubicTo() (%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)\n", c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y()) + || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c1.x()) || qt_is_nan(c1.y()) || qt_is_nan(c2.x()) || qt_is_nan(c2.y()) - || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -790,10 +802,14 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e) printf("QPainterPath::quadTo() (%.2f,%.2f), (%.2f,%.2f)\n", c.x(), c.y(), e.x(), e.y()); #endif + + if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(c.x()) || qt_is_nan(c.y()) || qt_is_nan(e.x()) || qt_is_nan(e.y())) - qWarning("QPainterPath::quadTo: Adding point where x or y is NaN, results are undefined"); + qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call"); #endif + return; + } + ensureData(); detach(); @@ -857,11 +873,15 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength printf("QPainterPath::arcTo() (%.2f, %.2f, %.2f, %.2f, angle=%.2f, sweep=%.2f\n", rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif + + if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) + || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(rect.x()) || qt_is_nan(rect.y()) || qt_is_nan(rect.width()) || qt_is_nan(rect.height()) - || qt_is_nan(startAngle) || qt_is_nan(sweepLength)) - qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (rect.isNull()) return; @@ -960,10 +980,13 @@ QPointF QPainterPath::currentPosition() const */ void QPainterPath::addRect(const QRectF &r) { + if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(r.x()) || qt_is_nan(r.y()) || qt_is_nan(r.width()) || qt_is_nan(r.height())) - qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (r.isNull()) return; @@ -1040,11 +1063,14 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) */ void QPainterPath::addEllipse(const QRectF &boundingRect) { + if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y()) + || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) { #ifndef QT_NO_DEBUG - if (qt_is_nan(boundingRect.x()) || qt_is_nan(boundingRect.y()) - || qt_is_nan(boundingRect.width()) || qt_is_nan(boundingRect.height())) - qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN, results are undefined"); + qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call"); #endif + return; + } + if (boundingRect.isNull()) return; @@ -2366,10 +2392,12 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) s >> x; s >> y; Q_ASSERT(type >= 0 && type <= 3); + if (!qt_is_finite(x) || !qt_is_finite(y)) { #ifndef QT_NO_DEBUG - if (qt_is_nan(x) || qt_is_nan(y)) - qWarning("QDataStream::operator>>: Adding a NaN element to path, results are undefined"); + qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it"); #endif + continue; + } QPainterPath::Element elm = { x, y, QPainterPath::ElementType(type) }; p.d_func()->elements.append(elm); } diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp index f60e782..fb3a4ea 100644 --- a/tests/auto/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp @@ -103,6 +103,8 @@ private slots: void testToFillPolygons(); + void testNaNandInfinites(); + void closing(); void operators_data(); @@ -1163,6 +1165,50 @@ void tst_QPainterPath::testToFillPolygons() QCOMPARE(polygons.first().count(QPointF(70, 50)), 0); } +void tst_QPainterPath::testNaNandInfinites() +{ + QPainterPath path1; + QPainterPath path2 = path1; + + QPointF p1 = QPointF(qSNaN(), 1); + QPointF p2 = QPointF(qQNaN(), 1); + QPointF p3 = QPointF(qQNaN(), 1); + QPointF pInf = QPointF(qInf(), 1); + + // all these operations with NaN/Inf should be ignored + // can't test operator>> reliably, as we can't create a path with NaN to << later + + path1.moveTo(p1); + path1.moveTo(qSNaN(), qQNaN()); + path1.moveTo(pInf); + + path1.lineTo(p1); + path1.lineTo(qSNaN(), qQNaN()); + path1.lineTo(pInf); + + path1.cubicTo(p1, p2, p3); + path1.cubicTo(p1, QPointF(1, 1), QPointF(2, 2)); + path1.cubicTo(pInf, QPointF(10, 10), QPointF(5, 1)); + + path1.quadTo(p1, p2); + path1.quadTo(QPointF(1, 1), p3); + path1.quadTo(QPointF(1, 1), pInf); + + path1.arcTo(QRectF(p1, p2), 5, 5); + path1.arcTo(QRectF(pInf, QPointF(1, 1)), 5, 5); + + path1.addRect(QRectF(p1, p2)); + path1.addRect(QRectF(pInf, QPointF(1, 1))); + + path1.addEllipse(QRectF(p1, p2)); + path1.addEllipse(QRectF(pInf, QPointF(1, 1))); + + QCOMPARE(path1, path2); + + path1.lineTo(QPointF(1, 1)); + QVERIFY(path1 != path2); +} + void tst_QPainterPath::connectPathDuplicatePoint() { QPainterPath a; -- cgit v0.12 From f3200133a385be03299c1b7ebe65c4304f65b9af Mon Sep 17 00:00:00 2001 From: miniak Date: Thu, 13 Jan 2011 15:08:01 +0100 Subject: Add comctl32 v6 assembly dependency to applications only (not libraries) This improves the patch from merge request #2526 to add the comctl32 v6 assembly dependency to applications only, as it was being done previously (although only when /SUBSYSTEM:WINDOWS, not when /SUBSYSTEM:CONSOLE). Other existing makespecs are not affected, as they still have all flags in QMAKE_LFLAGS, and QMAKE_LFLAGS_EXE is simply empty. Merge-request: 1020 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/win32/console.prf | 4 +++- mkspecs/features/win32/windows.prf | 2 +- mkspecs/win32-msvc2005/qmake.conf | 3 ++- mkspecs/win32-msvc2008/qmake.conf | 3 ++- mkspecs/win32-msvc2010/qmake.conf | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/mkspecs/features/win32/console.prf b/mkspecs/features/win32/console.prf index b34e1c6..8a1725d 100644 --- a/mkspecs/features/win32/console.prf +++ b/mkspecs/features/win32/console.prf @@ -1,2 +1,4 @@ CONFIG -= windows -contains(TEMPLATE, ".*app") : QMAKE_LFLAGS += $$QMAKE_LFLAGS_CONSOLE +contains(TEMPLATE, ".*app") { + QMAKE_LFLAGS += $$QMAKE_LFLAGS_CONSOLE $$QMAKE_LFLAGS_EXE +} diff --git a/mkspecs/features/win32/windows.prf b/mkspecs/features/win32/windows.prf index cf81388..f41db80 100644 --- a/mkspecs/features/win32/windows.prf +++ b/mkspecs/features/win32/windows.prf @@ -1,6 +1,6 @@ CONFIG -= console contains(TEMPLATE, ".*app"){ - QMAKE_LFLAGS += $$QMAKE_LFLAGS_WINDOWS + QMAKE_LFLAGS += $$QMAKE_LFLAGS_WINDOWS $$QMAKE_LFLAGS_EXE win32-g++:DEFINES += QT_NEEDS_QMAIN win32-borland:DEFINES += QT_NEEDS_QMAIN diff --git a/mkspecs/win32-msvc2005/qmake.conf b/mkspecs/win32-msvc2005/qmake.conf index 63bef80..5b717e7 100644 --- a/mkspecs/win32-msvc2005/qmake.conf +++ b/mkspecs/win32-msvc2005/qmake.conf @@ -53,12 +53,13 @@ QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $< QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<< QMAKE_LINK = link -QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" +QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS +QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL QMAKE_LFLAGS_LTCG = /LTCG diff --git a/mkspecs/win32-msvc2008/qmake.conf b/mkspecs/win32-msvc2008/qmake.conf index 9f9c919..c765562 100644 --- a/mkspecs/win32-msvc2008/qmake.conf +++ b/mkspecs/win32-msvc2008/qmake.conf @@ -55,12 +55,13 @@ QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $< QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<< QMAKE_LINK = link -QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" +QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS +QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL QMAKE_LFLAGS_LTCG = /LTCG diff --git a/mkspecs/win32-msvc2010/qmake.conf b/mkspecs/win32-msvc2010/qmake.conf index 9471034..1cad99e 100644 --- a/mkspecs/win32-msvc2010/qmake.conf +++ b/mkspecs/win32-msvc2010/qmake.conf @@ -55,12 +55,13 @@ QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $< QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<< QMAKE_LINK = link -QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" +QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS +QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL QMAKE_LFLAGS_LTCG = /LTCG -- cgit v0.12 From fa845566b3733bc06454b71e33b1ff405ba32280 Mon Sep 17 00:00:00 2001 From: Ralf Engels Date: Mon, 20 Dec 2010 16:47:07 +0100 Subject: Improve overshooting behaviour --- src/gui/util/qscroller.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index 2ca4a6e..a9906f0 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -1253,17 +1253,6 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp qScrollerDebug() << "+++ createScrollingSegments: s:" << startPos << "maxPos:" << maxPos << "o:" << int(orientation); - // -- check if we are in overshoot - if (startPos < minPos) { - createScrollToSegments(v, sp->overshootScrollTime * 0.5, minPos, orientation, ScrollTypeOvershoot); - return; - } - - if (startPos > maxPos) { - createScrollToSegments(v, sp->overshootScrollTime * 0.5, maxPos, orientation, ScrollTypeOvershoot); - return; - } - qScrollerDebug() << "v = " << v << ", decelerationFactor = " << sp->decelerationFactor << ", curveType = " << sp->scrollingCurve.type(); // This is only correct for QEasingCurve::OutQuad (linear velocity, @@ -1299,6 +1288,20 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp if (nextSnap < lowerSnapPos || qIsNaN(lowerSnapPos)) lowerSnapPos = nextSnap; + // -- check if we end in overshoot + if ((startPos < minPos && endPos < minPos) || + (startPos > maxPos && endPos > maxPos)) { + qreal stopPos = endPos < minPos ? minPos : maxPos; + qreal oDistance = viewSize * sp->overshootScrollDistanceFactor * v / sp->maximumVelocity; + qreal oDeltaTime = sp->overshootScrollTime; + + if (qAbs(v) > sp->minimumVelocity) + pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.5, startPos, startPos + oDistance, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.3, startPos + oDistance, stopPos + oDistance * 0.3, QEasingCurve::InQuad, orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.2, stopPos + oDistance * 0.3, stopPos, QEasingCurve::OutQuad, orientation); + return; + } + if (qAbs(v) < sp->minimumVelocity) { qScrollerDebug() << "### below minimum Vel" << orientation; -- cgit v0.12 From 4f9a318d639c4e7e09e56751d31608fb39d472af Mon Sep 17 00:00:00 2001 From: Ralf Engels Date: Tue, 21 Dec 2010 17:08:21 +0100 Subject: Review and improve scroller documentation --- src/gui/util/qscroller.cpp | 178 ++++++++++++++++++----------------- src/gui/util/qscrollerproperties.cpp | 78 ++++++++------- 2 files changed, 127 insertions(+), 129 deletions(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index a9906f0..ae66cd4 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -243,7 +243,7 @@ private: intuitive user experience. The QScroller object is the object that stores the current position and - speed of the scrolling and takes care of updates. + scrolling speed and takes care of updates. QScroller can be triggered by a flick gesture \code @@ -259,20 +259,20 @@ private: scroller->scrollTo(QPointF(100, 100)); \endcode - The scrolled QObjects will be receive a QScrollPrepareEvent whenever the scroller needs to + The scrolled QObjects receive a QScrollPrepareEvent whenever the scroller needs to update its geometry information and a QScrollEvent whenever the content of the object should actually be scrolled. - The scroller uses the global QAbstractAnimation timer to generate its QScrollEvents, but this - can be slowed down with QScrollerProperties::FrameRate on a per-QScroller basis. + The scroller uses the global QAbstractAnimation timer to generate its QScrollEvents. This + can be changed with QScrollerProperties::FrameRate on a per-QScroller basis. Several examples in the \c scroller examples directory show how QScroller, QScrollEvent and the scroller gesture can be used. - Even though this kinetic scroller has a huge number of settings available via + Even though this kinetic scroller has a large number of settings available via QScrollerProperties, we recommend that you leave them all at their default, platform optimized - values. In case you really want to change them you can experiment with the \c plot example in - the \c scroller examples directory first. + values. Before changing them you can experiment with the \c plot example in + the \c scroller examples directory. \sa QScrollEvent, QScrollPrepareEvent, QScrollerProperties */ @@ -293,9 +293,9 @@ bool QScroller::hasScroller(QObject *target) /*! Returns the scroller for the given \a target. - As long as the object exist this function will always return the same QScroller. - If a QScroller does not exist yet for the \a target, it will implicitly be created. - At no point will two QScrollers be active on one object. + As long as the object exists this function will always return the same QScroller instance. + If no QScroller exists for the \a target, one will implicitly be created. + At no point more than one QScroller will be active on an object. \sa hasScroller(), target() */ @@ -324,9 +324,9 @@ const QScroller *QScroller::scroller(const QObject *target) } /*! - Returns an application wide list of currently active, i.e. state() != - QScroller::Inactive, QScroller objects. - This routine is mostly useful when writing your own gesture recognizer. + Returns an application wide list of currently active QScroller objects. + Active QScroller objects are in a state() that is not QScroller::Inactive. + This function is useful when writing your own gesture recognizer. */ QList QScroller::activeScrollers() { @@ -346,8 +346,8 @@ QObject *QScroller::target() const /*! \fn QScroller::scrollerPropertiesChanged(const QScrollerProperties &newProperties); - QScroller emits this signal whenever its scroller properties have been - changed. \a newProperties are the new scroller properties. + QScroller emits this signal whenever its scroller properties change. + \a newProperties are the new scroller properties. \sa scrollerProperties */ @@ -355,7 +355,7 @@ QObject *QScroller::target() const /*! \property QScroller::scrollerProperties \brief The scroller properties of this scroller. - The properties will be used by the QScroller to determine its scrolling behaviour. + The properties are used by the QScroller to determine its scrolling behavior. */ QScrollerProperties QScroller::scrollerProperties() const { @@ -378,24 +378,25 @@ void QScroller::setScrollerProperties(const QScrollerProperties &sp) /*! - Registers a custom scroll gesture recognizer and grabs it for the \a + Registers a custom scroll gesture recognizer, grabs it for the \a target and returns the resulting gesture type. If \a scrollGestureType is - set to TouchGesture the gesture will trigger on touch events - if set to + set to TouchGesture the gesture triggers on touch events. If it is set to one of LeftMouseButtonGesture, RightMouseButtonGesture or - MiddleMouseButtonGesture it will trigger on mouse events of the + MiddleMouseButtonGesture it triggers on mouse events of the corresponding button. Only one scroll gesture can be active on a single object at the same - time, so if you call this function twice on the same object, it will + time. If you call this function twice on the same object, it will ungrab the existing gesture before grabbing the new one. - Please note: To avoid nasty side-effects, all mouse events will be - consumed while the gesture is triggered. Since the mouse press event is - not consumed, the gesture needs to also send a fake mouse release event - at the global position \c{(INT_MIN, INT_MIN)} to make sure that it - doesn't mess with the internal states of the widget that received the - mouse press in the first place (which could e.g. be a QPushButton - inside a QScrollArea). + \note To avoid unwanted side-effects, mouse events are consumed while + the gesture is triggered. Since the initial mouse press event is + not consumed, the gesture sends a fake mouse release event + at the global position \c{(INT_MIN, INT_MIN)}. This ensures that + internal states of the widget that received the original mouse press + are consistent. + + \sa ungrabGesture, grabbedGesture */ Qt::GestureType QScroller::grabGesture(QObject *target, ScrollerGestureType scrollGestureType) { @@ -437,6 +438,8 @@ Qt::GestureType QScroller::grabGesture(QObject *target, ScrollerGestureType scro /*! Returns the gesture type currently grabbed for the \a target or 0 if no gesture is grabbed. + + \sa grabGesture, ungrabGesture */ Qt::GestureType QScroller::grabbedGesture(QObject *target) { @@ -449,6 +452,9 @@ Qt::GestureType QScroller::grabbedGesture(QObject *target) /*! Ungrabs the gesture for the \a target. + Does nothing if no gesture is grabbed. + + \sa grabGesture, grabbedGesture */ void QScroller::ungrabGesture(QObject *target) { @@ -521,7 +527,7 @@ QScroller::State QScroller::state() const } /*! - Stops the scroller and resets the state back to Inactive. + Stops the scroller and resets its state back to Inactive. */ void QScroller::stop() { @@ -543,13 +549,13 @@ void QScroller::stop() } /*! - \brief Returns the pixel per meter metric for the scrolled widget. + Returns the pixel per meter metric for the scrolled widget. The value is reported for both the x and y axis separately by using a QPointF. - \note Please note that this value should be physically correct, while the actual DPI settings - that Qt returns for the display may be reported wrongly (on purpose) by the underlying - windowing system (e.g. Mac OS X or Maemo 5). + \note Please note that this value should be physically correct. The actual DPI settings + that Qt returns for the display may be reported wrongly on purpose by the underlying + windowing system, for example on Mac OS X or Maemo 5. */ QPointF QScroller::pixelPerMeter() const { @@ -574,10 +580,8 @@ QPointF QScroller::pixelPerMeter() const } /*! - \brief Returns the current velocity of the scroller. - - Returns the current scrolling velocity in meter per second when in the state Scrolling. - Returns a null velocity otherwise. + Returns the current scrolling velocity in meter per second when the state is Scrolling or Dragging. + Returns a zero velocity otherwise. The velocity is reported for both the x and y axis separately by using a QPointF. @@ -617,11 +621,9 @@ QPointF QScroller::velocity() const } /*! - \brief Returns the target position for the scroll movement. - - Returns the planned final position for the current scroll movement or the current - position if the scroller is not in the scrolling state. - The result is undefined when the scroller is in the inactive state. + Returns the estimated final position for the current scroll movement. + Returns the current position if the scroller state is not Scrolling. + The result is undefined when the scroller state is Inactive. The target position is in pixel. @@ -642,7 +644,7 @@ QPointF QScroller::finalPosition() const In this case the scroller might or might not overshoot. The scrolling speed will be calculated so that the given position will - be reached after a platform-defined time span (e.g. 1 second for Maemo 5). + be reached after a platform-defined time span. \a pos is given in viewport coordinates. @@ -656,7 +658,7 @@ void QScroller::scrollTo(const QPointF &pos) /*! \overload - This version will reach its destination position in \a scrollTime milli seconds. + This version will reach its destination position in \a scrollTime milliseconds. */ void QScroller::scrollTo(const QPointF &pos, int scrollTime) { @@ -704,10 +706,12 @@ void QScroller::scrollTo(const QPointF &pos, int scrollTime) In cases where it is not possible to fit the rect plus margins inside the viewport the contents are scrolled so that as much as possible is visible from \a rect. - The scrolling speed will be calculated so that the given position will - be reached after a platform-defined time span (e.g. 1 second for Maemo 5). + The scrolling speed is calculated so that the given position is reached after a platform-defined + time span. This function performs the actual scrolling by calling scrollTo(). + + \sa scrollTo */ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin) { @@ -717,7 +721,7 @@ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin) /*! \overload - This version will reach its destination position in \a scrollTime milli seconds. + This version will reach its destination position in \a scrollTime milliseconds. */ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, int scrollTime) { @@ -787,11 +791,11 @@ void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, } /*! This function resends the QScrollPrepareEvent. - * Calling resendPrepareEvent triggers a QScrollPrepareEvent from the scroller. - * This will allow the receiver to re-set content position and content size while - * scrolling. - * Calling this function while in the Inactive state is useless as the prepare event - * is send again right before scrolling starts. + Calling resendPrepareEvent triggers a QScrollPrepareEvent from the scroller. + This allows the receiver to re-set content position and content size while + scrolling. + Calling this function while in the Inactive state is useless as the prepare event + is sent again before scrolling starts. */ void QScroller::resendPrepareEvent() { @@ -799,11 +803,10 @@ void QScroller::resendPrepareEvent() d->prepareScrolling(d->pressPosition); } -/*! Set the snap positions for the horizontal axis. - * Set the snap positions to a list of \a positions. - * This will overwrite all previously set snap positions and also a previously - * set snapping interval. - * Snapping can be deactivated by setting an empty list of positions. +/*! Set the snap positions for the horizontal axis to a list of \a positions. + This overwrites all previously set snap positions and also a previously + set snapping interval. + Snapping can be deactivated by setting an empty list of positions. */ void QScroller::setSnapPositionsX(const QList &positions) { @@ -814,13 +817,12 @@ void QScroller::setSnapPositionsX(const QList &positions) d->recalcScrollingSegments(); } -/*! Set the snap positions for the horizontal axis. - * Set the snap positions to regular spaced intervals. - * The first snap position will be at \a first from the beginning of the list. The next at \a first + \a interval and so on. - * This can be used to implement a list header. - * This will overwrite all previously set snap positions and also a previously - * set snapping interval. - * Snapping can be deactivated by setting an interval of 0.0 +/*! Set the snap positions for the horizontal axis to regular spaced intervals. + The first snap position is at \a first. The next at \a first + \a interval. + This can be used to implement a list header. + This overwrites all previously set snap positions and also a previously + set snapping interval. + Snapping can be deactivated by setting an interval of 0.0 */ void QScroller::setSnapPositionsX(qreal first, qreal interval) { @@ -832,11 +834,10 @@ void QScroller::setSnapPositionsX(qreal first, qreal interval) d->recalcScrollingSegments(); } -/*! Set the snap positions for the vertical axis. - * Set the snap positions to a list of \a positions. - * This will overwrite all previously set snap positions and also a previously - * set snapping interval. - * Snapping can be deactivated by setting an empty list of positions. +/*! Set the snap positions for the vertical axis to a list of \a positions. + This overwrites all previously set snap positions and also a previously + set snapping interval. + Snapping can be deactivated by setting an empty list of positions. */ void QScroller::setSnapPositionsY(const QList &positions) { @@ -847,12 +848,11 @@ void QScroller::setSnapPositionsY(const QList &positions) d->recalcScrollingSegments(); } -/*! Set the snap positions for the vertical axis. - * Set the snap positions to regular spaced intervals. - * The first snap position will be at \a first. The next at \a first + \a interval and so on. - * This will overwrite all previously set snap positions and also a previously - * set snapping interval. - * Snapping can be deactivated by setting an interval of 0.0 +/*! Set the snap positions for the vertical axis to regular spaced intervals. + The first snap position is at \a first. The next at \a first + \a interval. + This overwrites all previously set snap positions and also a previously + set snapping interval. + Snapping can be deactivated by setting an interval of 0.0 */ void QScroller::setSnapPositionsY(qreal first, qreal interval) { @@ -951,14 +951,15 @@ void QScrollerPrivate::timerTick() /*! This function is used by gesture recognizers to inform the scroller about a new input event. - The scroller will change its internal state() according to the input event and its attached - scroller properties. Since the scroller doesn't care about the actual kind of input device the - event came from, you need to decompose the event into the \a input type, a \a position and a + The scroller changes its internal state() according to the input event and its attached + scroller properties. The scroller doesn't distinguish between the kind of input device the + event came from. Therefore the event needs to be split into the \a input type, a \a position and a milli-second \a timestamp. The \a position needs to be in the target's coordinate system. + The return value is \c true if the event should be consumed by the calling filter or \c false if the event should be forwarded to the control. - \note Using grabGesture() should be sufficient for most use cases though. + \note Using grabGesture() should be sufficient for most use cases. */ bool QScroller::handleInput(Input input, const QPointF &position, qint64 timestamp) { @@ -1380,7 +1381,8 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp } -/*! Prepares scrolling by sending a QScrollPrepareEvent to the receiver widget. +/*! \internal + Prepares scrolling by sending a QScrollPrepareEvent to the receiver widget. Returns true if the scrolling was accepted and a target was returned. */ bool QScrollerPrivate::prepareScrolling(const QPointF &position) @@ -1838,12 +1840,12 @@ void QScrollerPrivate::setContentPositionHelperScrolling() } /*! \internal - * Returns the next snap point in direction. - * If \a direction >0 it will return the next snap point that is larger than the current position. - * If \a direction <0 it will return the next snap point that is smaller than the current position. - * If \a direction ==0 it will return the nearest snap point (or the current position if we are already - * on a snap point. - * Returns the nearest snap position or NaN if no such point could be found. + Returns the next snap point in direction. + If \a direction >0 it will return the next snap point that is larger than the current position. + If \a direction <0 it will return the next snap point that is smaller than the current position. + If \a direction ==0 it will return the nearest snap point (or the current position if we are already + on a snap point. + Returns the nearest snap position or NaN if no such point could be found. */ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientation) { @@ -1965,7 +1967,7 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio This enum contains the different QScroller states. \value Inactive The scroller is not scrolling and nothing is pressed. - \value Pressed A touch event was received or the mouse button pressed but the scroll area is currently not dragged. + \value Pressed A touch event was received or the mouse button was pressed but the scroll area is currently not dragged. \value Dragging The scroll area is currently following the touch point or mouse. \value Scrolling The scroll area is moving on it's own. */ @@ -1976,8 +1978,8 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio This enum contains the different gesture types that are supported by the QScroller gesture recognizer. \value TouchGesture The gesture recognizer will only trigger on touch - events. Specifically it will react on single touch points when using a - touch screen and dual touch points when using a touchpad. + events. Specifically it will react on single touch points when using a + touch screen and dual touch points when using a touchpad. \value LeftMouseButtonGesture The gesture recognizer will only trigger on left mouse button events. \value MiddleMouseButtonGesture The gesture recognizer will only trigger on middle mouse button events. \value RightMouseButtonGesture The gesture recognizer will only trigger on right mouse button events. diff --git a/src/gui/util/qscrollerproperties.cpp b/src/gui/util/qscrollerproperties.cpp index 2e52959..b159e05 100644 --- a/src/gui/util/qscrollerproperties.cpp +++ b/src/gui/util/qscrollerproperties.cpp @@ -95,11 +95,11 @@ QScrollerPropertiesPrivate *QScrollerPropertiesPrivate::defaults() The QScrollerProperties class stores the parameters used by QScroller. - The default settings are platform dependant and Qt will emulate the + The default settings are platform dependent so that Qt emulates the platform behaviour for kinetic scrolling. As a convention the QScrollerProperties are in physical units (meter, - seconds) and will be converted by QScroller using the current DPI. + seconds) and are converted by QScroller using the current DPI. \sa QScroller */ @@ -179,10 +179,10 @@ bool QScrollerPropertiesPrivate::operator==(const QScrollerPropertiesPrivate &p) } /*! - Sets the scroller properties returned by the default constructor to \a sp. + Sets the scroller properties for all new QScrollerProperties objects to \a sp. Use this function to override the platform default properties returned by the default - constructor. If you only want to change the scroller properties of a single scroller, then use + constructor. If you only want to change the scroller properties of a single scroller, use QScroller::setScrollerProperties() \note Calling this function will not change the content of already existing @@ -291,50 +291,48 @@ void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &v This enum describes the various modes of overshooting. - \value OvershootWhenScrollable Overshooting is when the content is scrollable. This is the + \value OvershootWhenScrollable Overshooting is possible when the content is scrollable. This is the default. - \value OvershootAlwaysOff Overshooting is never enabled (even when the content is scrollable). + \value OvershootAlwaysOff Overshooting is never enabled, even when the content is scrollable. - \value OvershootAlwaysOn Overshooting is always enabled (even when the content is not - scrollable). + \value OvershootAlwaysOn Overshooting is always enabled, even when the content is not + scrollable. */ /*! \enum QScrollerProperties::ScrollMetric This enum contains the different scroll metric types. When not indicated otherwise the - setScrollMetric function expects a QVariant of a real value. + setScrollMetric function expects a QVariant of type qreal. - See the QScroller documentation for a further explanation of the concepts behind the different + See the QScroller documentation for further details of the concepts behind the different values. - \value MousePressEventDelay This is the time a mouse press event will be delayed when starting + \value MousePressEventDelay This is the time a mouse press event is delayed when starting a flick gesture in \c{[s]}. If the gesture is triggered within that time, no mouse press or - release will be sent to the scrolled object. If it triggers after that delay the (delayed) - mouse press plus a faked release event (at global postion \c{QPoint(-QWIDGETSIZE_MAX, - -QWIDGETSIZE_MAX)} will be sent. If the gesture is canceled, then both the (delayed) mouse - press plus the real release event will be delivered. + release is sent to the scrolled object. If it triggers after that delay the delayed + mouse press plus a faked release event at global postion \c{QPoint(-QWIDGETSIZE_MAX, + -QWIDGETSIZE_MAX)} is sent. If the gesture is canceled, then both the delayed mouse + press plus the real release event are delivered. \value DragStartDistance This is the minimum distance the touch or mouse point needs to be moved before the flick gesture is triggered in \c m. - \value DragVelocitySmoothingFactor A value that describes how much new drag velocities are + \value DragVelocitySmoothingFactor A value that describes to which extent new drag velocities are included in the final scrolling velocity. This value should be in the range between \c 0 and - \c 1. The lower the value, the more smoothing will be applied to the dragging velocity. The - default value is \c 0.8. + \c 1. The lower the value, the more smoothing is applied to the dragging velocity. - \value AxisLockThreshold If greater than zero a scroll movement will be restricted to one axis - only if the movement is inside an angle about the axis. The threshold must be in the range \c 0 - to \c 1. + \value AxisLockThreshold Restricts the movement to one axis if the movement is inside an angle + around the axis. The threshold must be in the range \c 0 to \c 1. \value ScrollingCurve The QEasingCurve used when decelerating the scrolling velocity after an user initiated flick. Please note that this is the easing curve for the positions, \bold{not} - the velocity: the default is QEasingCurve::OutQuad, which results is a linear decrease in + the velocity: the default is QEasingCurve::OutQuad, which results in a linear decrease in velocity (1st derivative) and a constant deceleration (2nd derivative). \value DecelerationFactor This factor influences how long it takes the scroller to decelerate - to 0 velocity. The actual value heavily depends on the chosen ScrollingCurve, but for most + to 0 velocity. The actual value depends on the chosen ScrollingCurve. For most types the value should be in the range from \c 0.1 to \c 2.0 \value MinimumVelocity The minimum velocity that is needed after ending the touch or releasing @@ -344,39 +342,38 @@ void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &v \value MaximumClickThroughVelocity This is the maximum allowed scroll speed for a click-through in \c{m/s}. This means that a click on a currently (slowly) scrolling object will not only stop - the scrolling but the click event will also be delivered to the UI control - this is very + the scrolling but the click event will also be delivered to the UI control. This is useful when using exponential-type scrolling curves. \value AcceleratingFlickMaximumTime This is the maximum time in \c seconds that a flick gesture - can take to be recognized as an accelerating flick. If set to zero no such gesture will be + can take to be recognized as an accelerating flick. If set to zero no such gesture is detected. An "accelerating flick" is a flick gesture executed on an already scrolling object. In such cases the scrolling speed is multiplied by AcceleratingFlickSpeedupFactor in order to accelerate it. - \value AcceleratingFlickSpeedupFactor The current speed will be multiplied by this number if an - accelerating flick is detected. Should be \c{> 1}. + \value AcceleratingFlickSpeedupFactor The current speed is multiplied by this number if an + accelerating flick is detected. Should be \c{>= 1}. \value SnapPositionRatio This is the distance that the user must drag the area beween two snap - points in order to snap it to the next position. e.g. \c{0.33} means that the scroll must only + points in order to snap it to the next position. \c{0.33} means that the scroll must only reach one third of the distance between two snap points to snap to the next one. The ratio must - be in the range \c 0 to \c 1. + be between \c 0 and \c 1. \value SnapTime This is the time factor for the scrolling curve. A lower value means that the scrolling will take longer. The scrolling distance is independet of this value. \value OvershootDragResistanceFactor This value is the factor between the mouse dragging and - the actual scroll area movement (during overshoot). The factor must be in the range \c 0 to \c - 1. + the actual scroll area movement (during overshoot). The factor must be between \c 0 and \c 1. \value OvershootDragDistanceFactor This is the maximum distance for overshoot movements while - dragging. The actual overshoot distance will be calculated by multiplying this value with the - viewport size of the scrolled object. The factor must be in the range \c 0 to \c 1. + dragging. The actual overshoot distance is calculated by multiplying this value with the + viewport size of the scrolled object. The factor must be between \c 0 and \c 1. \value OvershootScrollDistanceFactor This is the maximum distance for overshoot movements while - scrolling. The actual overshoot distance will be calculated by multiplying this value with the - viewport size of the scrolled object. The factor must be in the range \c 0 to \c 1. + scrolling. The actual overshoot distance is calculated by multiplying this value with the + viewport size of the scrolled object. The factor must be between \c 0 and \c 1. - \value OvershootScrollTime This is the time in \c seconds that will be used to play the + \value OvershootScrollTime This is the time in \c seconds that is used to play the complete overshoot animation. \value HorizontalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy). @@ -385,13 +382,12 @@ void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &v \value FrameRate This is the frame rate which should be used while dragging or scrolling. QScroller uses a QAbstractAnimation timer internally to sync all scrolling operations to other - animations that might be active at the same time. If the Standard value of 60 frames per - second is too fast for your use case, you can lower the frames per second with this setting - (while still being in-sync with QAbstractAnimation). Please note that only the values of the + animations that might be active at the same time. If the standard value of 60 frames per + second is too fast, it can be lowered with this setting, + while still being in-sync with QAbstractAnimation. Please note that only the values of the FrameRates enum are allowed here. - \value ScrollMetricCount This is just used when enumerating the metrics. It is always the last - entry. + \value ScrollMetricCount This is always the last entry. */ QT_END_NAMESPACE -- cgit v0.12 From 4810b587a65d81f8f90646efd09cadeb1276a756 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Thu, 20 Jan 2011 14:47:37 +0100 Subject: Fix Xrandr DPI calculation for NVidia TwinView. The problem is that a Xinerama 'screen' (as used by QDesktopWidget) does NOT correspond to a Xrandr 'screen', so we have to convert via the root windows. Reviewed-by: Ralf Engels --- src/gui/util/qscroller.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index ae66cd4..2eb6d2f 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -1006,9 +1006,18 @@ QPointF QScrollerPrivate::realDpi(int screen) return QPointF(260, 260); # elif defined(Q_WS_X11) && !defined(QT_NO_XRANDR) - if (X11->use_xrandr && X11->ptrXRRSizes) { + if (X11 && X11->use_xrandr && X11->ptrXRRSizes && X11->ptrXRRRootToScreen) { int nsizes = 0; - XRRScreenSize *sizes = X11->ptrXRRSizes(X11->display, screen == -1 ? X11->defaultScreen : screen, &nsizes); + // QDesktopWidget is based on Xinerama screens, which do not always + // correspond to RandR screens: NVidia's TwinView e.g. will show up + // as 2 screens in QDesktopWidget, but libXRandR will only see 1 screen. + // (although with the combined size of the Xinerama screens). + // Additionally, libXrandr will simply crash when calling XRRSizes + // for (the non-existant) screen 1 in this scenario. + Window root = RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen); + int randrscreen = (root != XNone) ? X11->ptrXRRRootToScreen(X11->display, root) : -1; + + XRRScreenSize *sizes = X11->ptrXRRSizes(X11->display, randrscreen == -1 ? 0 : randrscreen, &nsizes); if (nsizes > 0 && sizes && sizes->width && sizes->height && sizes->mwidth && sizes->mheight) { qScrollerDebug() << "XRandR DPI:" << QPointF(qreal(25.4) * qreal(sizes->width) / qreal(sizes->mwidth), qreal(25.4) * qreal(sizes->height) / qreal(sizes->mheight)); -- cgit v0.12 From 7bad867382ad6c84155ffcfbb361709a8e8184ab Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Mon, 24 Jan 2011 12:45:03 +0100 Subject: Fixed overshooting with a very low start velocity. Before this patch, the slow down (overshoot) was a separate scroll segment. This could lead to an actual acceleration when going into overshoot with a very low velocity. The new approach is to just continue with the normal scroll segment, until the max overshoot distance is reached and only add one additional segment for the bounce-back animation to complete the overshoot animation. Reviewed-by: Ralf Engels --- src/gui/util/qscroller.cpp | 153 +++++++++++++++++++++++++-------------------- src/gui/util/qscroller_p.h | 5 +- 2 files changed, 87 insertions(+), 71 deletions(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index 2eb6d2f..7173270 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -83,9 +83,9 @@ bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); QDebug &operator<<(QDebug &dbg, const QScrollerPrivate::ScrollSegment &s) { - dbg << "\n Time: start:" << s.startTime << " duration:" << s.deltaTime; - dbg << "\n Pos: start:" << s.startPos << " delta:" << s.deltaPos; - dbg << "\n Curve: type:" << s.curve.type() << " max progress:" << s.maxProgress << "\n"; + dbg << "\n Time: start:" << s.startTime << " duration:" << s.deltaTime << " stop progress:" << s.stopProgress; + dbg << "\n Pos: start:" << s.startPos << " delta:" << s.deltaPos << " stop:" << s.stopPos; + dbg << "\n Curve: type:" << s.curve.type() << "\n"; return dbg; } @@ -601,18 +601,17 @@ QPointF QScroller::velocity() const if (!d->xSegments.isEmpty()) { const QScrollerPrivate::ScrollSegment &s = d->xSegments.head(); - qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress); - qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / s.maxProgress / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); + qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); + qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); vel.setX(v); } if (!d->ySegments.isEmpty()) { const QScrollerPrivate::ScrollSegment &s = d->ySegments.head(); - qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress); - qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / s.maxProgress / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); + qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); + qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress); vel.setY(v); } - //qScrollerDebug() << "Velocity: " << vel; return vel; } default: @@ -1083,8 +1082,23 @@ void QScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint64 delta deltaPixel = deltaPixelRaw * qreal(2.5) * ppm / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength(); QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / ppm; - if (releaseVelocity != QPointF(0, 0)) - newv = newv * sp->dragVelocitySmoothingFactor + releaseVelocity * (qreal(1) - sp->dragVelocitySmoothingFactor); + // around 95% of all updates are in the [1..50] ms range, so make sure + // to scale the smoothing factor over that range: this way a 50ms update + // will have full impact, while 5ms update will only have a 10% impact. + qreal smoothing = sp->dragVelocitySmoothingFactor * qMin(qreal(deltaTime), qreal(50)) / qreal(50); + + // only smooth if we already have a release velocity and only if the + // user hasn't stopped to move his finger for more than 100ms + if ((releaseVelocity != QPointF(0, 0)) && (deltaTime < 100)) { + qScrollerDebug() << "SMOOTHED from " << newv << " to " << newv * smoothing + releaseVelocity * (qreal(1) - smoothing); + // smooth x or y only if the new velocity is either 0 or at least in + // the same direction of the release velocity + if (!newv.x() || (qSign(releaseVelocity.x()) == qSign(newv.x()))) + newv.setX(newv.x() * smoothing + releaseVelocity.x() * (qreal(1) - smoothing)); + if (!newv.y() || (qSign(releaseVelocity.y()) == qSign(newv.y()))) + newv.setY(newv.y() * smoothing + releaseVelocity.y() * (qreal(1) - smoothing)); + } else + qScrollerDebug() << "NO SMOOTHING to " << newv; releaseVelocity.setX(qBound(-sp->maximumVelocity, newv.x(), sp->maximumVelocity)); releaseVelocity.setY(qBound(-sp->maximumVelocity, newv.y(), sp->maximumVelocity)); @@ -1092,23 +1106,24 @@ void QScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint64 delta qScrollerDebug() << " --> new velocity:" << releaseVelocity; } -void QScrollerPrivate::pushSegment(ScrollType type, qreal deltaTime, qreal startPos, qreal endPos, QEasingCurve::Type curve, Qt::Orientation orientation, qreal maxProgress) +void QScrollerPrivate::pushSegment(ScrollType type, qreal deltaTime, qreal stopProgress, qreal startPos, qreal deltaPos, qreal stopPos, QEasingCurve::Type curve, Qt::Orientation orientation) { - if (startPos == endPos) + if (startPos == stopPos || deltaPos == 0) return; ScrollSegment s; if (orientation == Qt::Horizontal && !xSegments.isEmpty()) - s.startTime = xSegments.last().startTime + xSegments.last().deltaTime; + s.startTime = xSegments.last().startTime + xSegments.last().deltaTime * xSegments.last().stopProgress; else if (orientation == Qt::Vertical && !ySegments.isEmpty()) - s.startTime = ySegments.last().startTime + ySegments.last().deltaTime; + s.startTime = ySegments.last().startTime + ySegments.last().deltaTime * ySegments.last().stopProgress; else s.startTime = monotonicTimer.elapsed(); s.startPos = startPos; - s.deltaPos = endPos - startPos; + s.deltaPos = deltaPos; + s.stopPos = stopPos; s.deltaTime = deltaTime * 1000; - s.maxProgress = maxProgress; + s.stopProgress = stopProgress; s.curve.setType(curve); s.type = type; @@ -1143,23 +1158,17 @@ void QScrollerPrivate::recalcScrollingSegments(bool forceRecalc) */ qreal QScrollerPrivate::scrollingSegmentsEndPos(Qt::Orientation orientation) const { - const QQueue *segments; - qreal endPos; - if (orientation == Qt::Horizontal) { - segments = &xSegments; - endPos = contentPosition.x() + overshootPosition.x(); + if (xSegments.isEmpty()) + return contentPosition.x() + overshootPosition.x(); + else + return xSegments.last().stopPos; } else { - segments = &ySegments; - endPos = contentPosition.y() + overshootPosition.y(); - } - - if (!segments->isEmpty()) { - const ScrollSegment &last = segments->last(); - endPos = last.startPos + last.deltaPos; + if (ySegments.isEmpty()) + return contentPosition.y() + overshootPosition.y(); + else + return ySegments.last().stopPos; } - - return endPos; } /*! \internal @@ -1185,23 +1194,23 @@ bool QScrollerPrivate::scrollingSegmentsValid(Qt::Orientation orientation) return true; const ScrollSegment &last = segments->last(); - qreal endPos = last.startPos + last.deltaPos; + qreal stopPos = last.stopPos; if (last.type == ScrollTypeScrollTo) return true; // scrollTo is always valid if (last.type == ScrollTypeOvershoot && - endPos != minPos && endPos != maxPos) + (stopPos != minPos && stopPos != maxPos)) return false; - if (endPos < minPos || endPos > maxPos) + if (stopPos < minPos || stopPos > maxPos) return false; - if (endPos == minPos || endPos == maxPos) // the begin and the end of the list are always ok + if (stopPos == minPos || stopPos == maxPos) // the begin and the end of the list are always ok return true; - qreal nextSnap = nextSnapPos(endPos, 0, orientation); - if (!qIsNaN(nextSnap) && endPos != nextSnap) + qreal nextSnap = nextSnapPos(stopPos, 0, orientation); + if (!qIsNaN(nextSnap) && stopPos != nextSnap) return false; return true; @@ -1214,11 +1223,10 @@ void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal en { Q_UNUSED(v); - if (orientation == Qt::Horizontal) { + if (orientation == Qt::Horizontal) xSegments.clear(); - } else { + else ySegments.clear(); - } qScrollerDebug() << "+++ createScrollToSegments: t:" << deltaTime << "ep:" << endPos << "o:" << int(orientation); @@ -1226,10 +1234,10 @@ void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal en qreal startPos = (orientation == Qt::Horizontal) ? contentPosition.x() + overshootPosition.x() : contentPosition.y() + overshootPosition.y(); - qreal deltaPos = endPos - startPos; + qreal deltaPos = (endPos - startPos) / 2; - pushSegment(type, deltaTime * 0.3, startPos, startPos + deltaPos * 0.5, QEasingCurve::InQuad, orientation); - pushSegment(type, deltaTime * 0.7, startPos + deltaPos * 0.5, endPos, sp->scrollingCurve.type(), orientation); + pushSegment(type, deltaTime * 0.3, 1.0, startPos, deltaPos, startPos + deltaPos, QEasingCurve::InQuad, orientation); + pushSegment(type, deltaTime * 0.7, 1.0, startPos + deltaPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); } /*! \internal @@ -1298,17 +1306,13 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp if (nextSnap < lowerSnapPos || qIsNaN(lowerSnapPos)) lowerSnapPos = nextSnap; - // -- check if we end in overshoot + // -- check if are in overshoot and end in overshoot if ((startPos < minPos && endPos < minPos) || (startPos > maxPos && endPos > maxPos)) { qreal stopPos = endPos < minPos ? minPos : maxPos; - qreal oDistance = viewSize * sp->overshootScrollDistanceFactor * v / sp->maximumVelocity; qreal oDeltaTime = sp->overshootScrollTime; - if (qAbs(v) > sp->minimumVelocity) - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.5, startPos, startPos + oDistance, sp->scrollingCurve.type(), orientation); - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.3, startPos + oDistance, stopPos + oDistance * 0.3, QEasingCurve::InQuad, orientation); - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.2, stopPos + oDistance * 0.3, stopPos, QEasingCurve::OutQuad, orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, 1.0, startPos, stopPos - startPos, stopPos, sp->scrollingCurve.type(), orientation); return; } @@ -1337,8 +1341,9 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp endPos = higherSnapPos; deltaPos = endPos - startPos; - pushSegment(ScrollTypeFlick, sp->snapTime * 0.3, startPos, startPos + deltaPos * 0.3, QEasingCurve::InQuad, orientation); - pushSegment(ScrollTypeFlick, sp->snapTime * 0.7, startPos + deltaPos * 0.3, endPos, sp->scrollingCurve.type(), orientation); + qreal midPos = startPos + deltaPos * 0.3; + pushSegment(ScrollTypeFlick, sp->snapTime * 0.3, 1.0, startPos, midPos - startPos, midPos, QEasingCurve::InQuad, orientation); + pushSegment(ScrollTypeFlick, sp->snapTime * 0.7, 1.0, midPos, endPos - midPos, endPos, sp->scrollingCurve.type(), orientation); return; } @@ -1365,28 +1370,33 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp qScrollerDebug() << "Overshoot: delta:" << (stopPos - startPos); - qreal maxProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos - startPos) / deltaPos)); - qScrollerDebug() << "Overshoot maxp:" << maxProgress; + qreal stopProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos - startPos) / deltaPos)); - pushSegment(ScrollTypeFlick, deltaTime * maxProgress, startPos, stopPos, sp->scrollingCurve.type(), orientation, maxProgress); + if (!canOvershoot) { + qScrollerDebug() << "Overshoot stopp:" << stopProgress; - if (canOvershoot) { - qreal endV = qSign(v) * deltaTime * sp->decelerationFactor * qreal(0.5) * differentialForProgress(sp->scrollingCurve, maxProgress); - qScrollerDebug() << "Overshoot: velocity" << endV; - qScrollerDebug() << "Overshoot: maxVelocity" << sp->maximumVelocity; - qScrollerDebug() << "Overshoot: viewsize" << viewSize; - qScrollerDebug() << "Overshoot: factor" << sp->overshootScrollDistanceFactor; - - qreal oDistance = viewSize * sp->overshootScrollDistanceFactor * endV / sp->maximumVelocity; + pushSegment(ScrollTypeFlick, deltaTime, stopProgress, startPos, endPos, stopPos, sp->scrollingCurve.type(), orientation); + } else { qreal oDeltaTime = sp->overshootScrollTime; + qreal oStopProgress = qMin(stopProgress + oDeltaTime * 0.3 / deltaTime, qreal(1)); + qreal oDistance = startPos + deltaPos * sp->scrollingCurve.valueForProgress(oStopProgress) - stopPos; + qreal oMaxDistance = qSign(oDistance) * (viewSize * sp->overshootScrollDistanceFactor); - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.3, stopPos, stopPos + oDistance, sp->scrollingCurve.type(), orientation); - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, stopPos + oDistance, stopPos, sp->scrollingCurve.type(), orientation); + qScrollerDebug() << "1 oDistance:" << oDistance << "Max:" << oMaxDistance << "stopP/oStopP" << stopProgress << oStopProgress; + + if (qAbs(oDistance) > qAbs(oMaxDistance)) { + oStopProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos + oMaxDistance - startPos) / deltaPos)); + oDistance = oMaxDistance; + qScrollerDebug() << "2 oDistance:" << oDistance << "Max:" << oMaxDistance << "stopP/oStopP" << stopProgress << oStopProgress; + } + + pushSegment(ScrollTypeFlick, deltaTime, oStopProgress, startPos, deltaPos, stopPos + oDistance, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, 1.0, stopPos + oDistance, -oDistance, stopPos, sp->scrollingCurve.type(), orientation); } return; } - pushSegment(ScrollTypeFlick, deltaTime, startPos, endPos, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeFlick, deltaTime, 1.0, startPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); } @@ -1810,13 +1820,18 @@ qreal QScrollerPrivate::nextSegmentPosition(QQueue &segments, qin while (!segments.isEmpty()) { const ScrollSegment s = segments.head(); - if ((s.startTime + s.deltaTime) <= now) { + if ((s.startTime + s.deltaTime * s.stopProgress) <= now) { segments.dequeue(); - pos = s.startPos + s.deltaPos; + pos = s.stopPos; } else if (s.startTime <= now) { - qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress); - pos = s.startPos + s.deltaPos * s.curve.valueForProgress(progress) / s.curve.valueForProgress(s.maxProgress); - break; + qreal progress = qreal(now - s.startTime) / qreal(s.deltaTime); + pos = s.startPos + s.deltaPos * s.curve.valueForProgress(progress); + if (s.deltaPos > 0 ? pos > s.stopPos : pos < s.stopPos) { + segments.dequeue(); + pos = s.stopPos; + } else { + break; + } } else { break; } diff --git a/src/gui/util/qscroller_p.h b/src/gui/util/qscroller_p.h index 98f34f7..d16eef9 100644 --- a/src/gui/util/qscroller_p.h +++ b/src/gui/util/qscroller_p.h @@ -98,7 +98,8 @@ public: qreal startPos; qreal deltaPos; QEasingCurve curve; - qreal maxProgress; + qreal stopProgress; // whatever is.. + qreal stopPos; // ..reached first ScrollType type; }; @@ -122,7 +123,7 @@ public: void setDpiFromWidget(QWidget *widget); void updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime); - void pushSegment(ScrollType type, qreal deltaTime, qreal startPos, qreal endPos, QEasingCurve::Type curve, Qt::Orientation orientation, qreal maxProgress = 1.0); + void pushSegment(ScrollType type, qreal deltaTime, qreal stopProgress, qreal startPos, qreal deltaPos, qreal stopPos, QEasingCurve::Type curve, Qt::Orientation orientation); void recalcScrollingSegments(bool forceRecalc = false); qreal scrollingSegmentsEndPos(Qt::Orientation orientation) const; bool scrollingSegmentsValid(Qt::Orientation orientation); -- cgit v0.12 From 64ec011c6132496eb9555c1d09e7fd4ddf472837 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Mon, 24 Jan 2011 18:39:25 +0100 Subject: Use qreal everywhere to avoid double/float errors on embedded platforms. Reviewed-by: Ralf Engels --- src/gui/util/qscroller.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index 7173270..815b3d1 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -1236,8 +1236,8 @@ void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal en : contentPosition.y() + overshootPosition.y(); qreal deltaPos = (endPos - startPos) / 2; - pushSegment(type, deltaTime * 0.3, 1.0, startPos, deltaPos, startPos + deltaPos, QEasingCurve::InQuad, orientation); - pushSegment(type, deltaTime * 0.7, 1.0, startPos + deltaPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); + pushSegment(type, deltaTime * qreal(0.3), qreal(1.0), startPos, deltaPos, startPos + deltaPos, QEasingCurve::InQuad, orientation); + pushSegment(type, deltaTime * qreal(0.7), qreal(1.0), startPos + deltaPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); } /*! \internal @@ -1312,7 +1312,7 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp qreal stopPos = endPos < minPos ? minPos : maxPos; qreal oDeltaTime = sp->overshootScrollTime; - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, 1.0, startPos, stopPos - startPos, stopPos, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * qreal(0.7), qreal(1.0), startPos, stopPos - startPos, stopPos, sp->scrollingCurve.type(), orientation); return; } @@ -1341,9 +1341,9 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp endPos = higherSnapPos; deltaPos = endPos - startPos; - qreal midPos = startPos + deltaPos * 0.3; - pushSegment(ScrollTypeFlick, sp->snapTime * 0.3, 1.0, startPos, midPos - startPos, midPos, QEasingCurve::InQuad, orientation); - pushSegment(ScrollTypeFlick, sp->snapTime * 0.7, 1.0, midPos, endPos - midPos, endPos, sp->scrollingCurve.type(), orientation); + qreal midPos = startPos + deltaPos * qreal(0.3); + pushSegment(ScrollTypeFlick, sp->snapTime * qreal(0.3), qreal(1.0), startPos, midPos - startPos, midPos, QEasingCurve::InQuad, orientation); + pushSegment(ScrollTypeFlick, sp->snapTime * qreal(0.7), qreal(1.0), midPos, endPos - midPos, endPos, sp->scrollingCurve.type(), orientation); return; } @@ -1378,7 +1378,7 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp pushSegment(ScrollTypeFlick, deltaTime, stopProgress, startPos, endPos, stopPos, sp->scrollingCurve.type(), orientation); } else { qreal oDeltaTime = sp->overshootScrollTime; - qreal oStopProgress = qMin(stopProgress + oDeltaTime * 0.3 / deltaTime, qreal(1)); + qreal oStopProgress = qMin(stopProgress + oDeltaTime * qreal(0.3) / deltaTime, qreal(1)); qreal oDistance = startPos + deltaPos * sp->scrollingCurve.valueForProgress(oStopProgress) - stopPos; qreal oMaxDistance = qSign(oDistance) * (viewSize * sp->overshootScrollDistanceFactor); @@ -1391,12 +1391,12 @@ void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal pp } pushSegment(ScrollTypeFlick, deltaTime, oStopProgress, startPos, deltaPos, stopPos + oDistance, sp->scrollingCurve.type(), orientation); - pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, 1.0, stopPos + oDistance, -oDistance, stopPos, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeOvershoot, oDeltaTime * qreal(0.7), qreal(1.0), stopPos + oDistance, -oDistance, stopPos, sp->scrollingCurve.type(), orientation); } return; } - pushSegment(ScrollTypeFlick, deltaTime, 1.0, startPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); + pushSegment(ScrollTypeFlick, deltaTime, qreal(1.0), startPos, deltaPos, endPos, sp->scrollingCurve.type(), orientation); } -- cgit v0.12 From 81492e56aba5b5761500543665012a85d6835513 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Mon, 24 Jan 2011 18:46:40 +0100 Subject: Various small fixes for the QScroller examples Reviewed-By: TrustMe --- examples/scroller/graphicsview/main.cpp | 12 ++++++++---- examples/scroller/plot/main.cpp | 9 ++++----- examples/scroller/plot/plot.pro | 5 ----- examples/scroller/plot/plotwidget.cpp | 2 +- examples/scroller/plot/plotwidget.h | 2 +- examples/scroller/plot/settingswidget.cpp | 2 +- examples/scroller/plot/settingswidget.h | 2 +- examples/scroller/wheel/main.cpp | 16 ++++++++++------ examples/scroller/wheel/wheel.pro | 5 ----- examples/scroller/wheel/wheelwidget.cpp | 2 +- examples/scroller/wheel/wheelwidget.h | 2 +- 11 files changed, 28 insertions(+), 31 deletions(-) diff --git a/examples/scroller/graphicsview/main.cpp b/examples/scroller/graphicsview/main.cpp index e28978f..77d00f0 100644 --- a/examples/scroller/graphicsview/main.cpp +++ b/examples/scroller/graphicsview/main.cpp @@ -279,14 +279,18 @@ protected: int main(int argc, char *argv[]) { - QApplication app(argc, argv); - bool useTouch = (app.arguments().contains(QLatin1String("--touch"))); - MainWindow mw(useTouch); + QApplication a(argc, argv); + bool touch = (a.arguments().contains(QLatin1String("--touch"))); + MainWindow mw(touch); +#ifdef Q_WS_S60 + mw.showMaximized(); +#else mw.show(); +#endif #ifdef Q_WS_MAC mw.raise(); #endif - return app.exec(); + return a.exec(); } #include "main.moc" diff --git a/examples/scroller/plot/main.cpp b/examples/scroller/plot/main.cpp index acf83ee..6166505 100644 --- a/examples/scroller/plot/main.cpp +++ b/examples/scroller/plot/main.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -208,15 +208,14 @@ int main(int argc, char **argv) if (a.arguments().contains(QLatin1String("--touch"))) touch = true; - MainWindow *mw = new MainWindow(smallscreen, touch); + MainWindow mw(smallscreen, touch); if (smallscreen) - mw->showMaximized(); + mw.showMaximized(); else - mw->show(); + mw.show(); #if defined(Q_WS_MAC) mw->raise(); #endif - return a.exec(); } diff --git a/examples/scroller/plot/plot.pro b/examples/scroller/plot/plot.pro index 8c37b04..04fdf70 100644 --- a/examples/scroller/plot/plot.pro +++ b/examples/scroller/plot/plot.pro @@ -11,8 +11,3 @@ target.path = $$[QT_INSTALL_EXAMPLES]/scroller/plot sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS plot.pro sources.path = $$[QT_INSTALL_EXAMPLES]/scroller/plot INSTALLS += target sources - -symbian { - TARGET.UID3 = 0xA000CF66 - include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) -} diff --git a/examples/scroller/plot/plotwidget.cpp b/examples/scroller/plot/plotwidget.cpp index 5f0df67..a03f613 100644 --- a/examples/scroller/plot/plotwidget.cpp +++ b/examples/scroller/plot/plotwidget.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/examples/scroller/plot/plotwidget.h b/examples/scroller/plot/plotwidget.h index 4987ebc..c96ceac 100644 --- a/examples/scroller/plot/plotwidget.h +++ b/examples/scroller/plot/plotwidget.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/examples/scroller/plot/settingswidget.cpp b/examples/scroller/plot/settingswidget.cpp index 840e3fc..1929eb6 100644 --- a/examples/scroller/plot/settingswidget.cpp +++ b/examples/scroller/plot/settingswidget.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/examples/scroller/plot/settingswidget.h b/examples/scroller/plot/settingswidget.h index 0ea201d..13edbf4 100644 --- a/examples/scroller/plot/settingswidget.h +++ b/examples/scroller/plot/settingswidget.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/examples/scroller/wheel/main.cpp b/examples/scroller/wheel/main.cpp index 4264377..203c930 100644 --- a/examples/scroller/wheel/main.cpp +++ b/examples/scroller/wheel/main.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -107,12 +107,16 @@ private: int main(int argc, char **argv) { QApplication a(argc, argv); - bool touch = a.arguments().contains(QLatin1String("--touch")); - - MainWindow *mw = new MainWindow(touch); - mw->show(); - + MainWindow mw(touch); +#ifdef Q_WS_S60 + mw.showMaximized(); +#else + mw.show(); +#endif +#ifdef Q_WS_MAC + mw.raise(); +#endif return a.exec(); } diff --git a/examples/scroller/wheel/wheel.pro b/examples/scroller/wheel/wheel.pro index 1f9b789..48fe171 100644 --- a/examples/scroller/wheel/wheel.pro +++ b/examples/scroller/wheel/wheel.pro @@ -9,8 +9,3 @@ target.path = $$[QT_INSTALL_EXAMPLES]/scroller/wheel sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS wheel.pro sources.path = $$[QT_INSTALL_EXAMPLES]/scroller/wheel INSTALLS += target sources - -symbian { - TARGET.UID3 = 0xA000CF66 - include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) -} diff --git a/examples/scroller/wheel/wheelwidget.cpp b/examples/scroller/wheel/wheelwidget.cpp index 64a459b..0449f53 100644 --- a/examples/scroller/wheel/wheelwidget.cpp +++ b/examples/scroller/wheel/wheelwidget.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/examples/scroller/wheel/wheelwidget.h b/examples/scroller/wheel/wheelwidget.h index c50f951..8f49169 100644 --- a/examples/scroller/wheel/wheelwidget.h +++ b/examples/scroller/wheel/wheelwidget.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtGui module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From b668857b3749b39c3a61e0a25e750740b74df552 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Mon, 24 Jan 2011 23:21:44 +0100 Subject: Fixed spelling. Reviewed-by: TrustMe --- src/gui/util/qscroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp index 815b3d1..d60f44e 100644 --- a/src/gui/util/qscroller.cpp +++ b/src/gui/util/qscroller.cpp @@ -1012,7 +1012,7 @@ QPointF QScrollerPrivate::realDpi(int screen) // as 2 screens in QDesktopWidget, but libXRandR will only see 1 screen. // (although with the combined size of the Xinerama screens). // Additionally, libXrandr will simply crash when calling XRRSizes - // for (the non-existant) screen 1 in this scenario. + // for (the non-existent) screen 1 in this scenario. Window root = RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen); int randrscreen = (root != XNone) ? X11->ptrXRRRootToScreen(X11->display, root) : -1; -- cgit v0.12 From 7052bcc0c6da28f9554f560fef36a5ae3d1e26fd Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Jan 2011 20:28:56 +0100 Subject: remove the completely insane quote nesting from split_value_list() "foo 'bar "whee"' baz" would be actually treated like nested quotes. of course, this makes utterly no sense, as both the layers below and above couldn't do anything with that. and it would break actually useful things like quoting an apostrophe. Reviewed-by: mariusSO --- qmake/project.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index f314b8b..cbe3a94 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -287,7 +287,7 @@ static QStringList split_value_list(const QString &vals) { QString build; QStringList ret; - QStack quote; + ushort quote = 0; const ushort LPAREN = '('; const ushort RPAREN = ')'; @@ -303,17 +303,17 @@ static QStringList split_value_list(const QString &vals) if(x != (int)vals_len-1 && unicode == BACKSLASH && (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) { build += vals_data[x++]; //get that 'escape' - } else if(!quote.isEmpty() && unicode == quote.top()) { - quote.pop(); - } else if(unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) { - quote.push(unicode); + } else if(quote && unicode == quote) { + quote = 0; + } else if(!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { + quote = unicode; } else if(unicode == RPAREN) { --parens; } else if(unicode == LPAREN) { ++parens; } - if(!parens && quote.isEmpty() && (vals_data[x] == Option::field_sep)) { + if(!parens && !quote && (vals_data[x] == Option::field_sep)) { ret << build; build.clear(); } else { -- cgit v0.12 From 9e0f4a89564997856c784aed6611b91a9f9f184a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 24 Jan 2011 20:44:22 +0100 Subject: remove the somewhat bizarre unquoting of the last argument in split_arg_list() the last argument would be unquoted, but only if currently in a quote. that means that an invalid construct like "foo"" would be reduced to another invalid construct foo". this doesn't sound overly useful ... Reviewed-by: mariusSO --- qmake/project.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index cbe3a94..4053b3d 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -254,11 +254,6 @@ static QStringList split_arg_list(QString params) while(x && params_data[x-1].unicode() == SPACE) --x; QString mid(params_data+last, x-last); - if(quote) { - if(mid[0] == quote && mid[(int)mid.length()-1] == quote) - mid = mid.mid(1, mid.length()-2); - quote = 0; - } args << mid; break; } -- cgit v0.12 From 1f28efe4125397f2a61af421dbeb9f6954ca2a9c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 25 Jan 2011 13:17:08 +0100 Subject: slightly reorganize split_arg_list() cut down code duplication Reviewed-by: mariusSO --- qmake/project.cpp | 59 ++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 4053b3d..d690770 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -241,41 +241,38 @@ static QStringList split_arg_list(QString params) const ushort SPACE = ' '; //const ushort TAB = '\t'; - ushort unicode; const QChar *params_data = params.data(); const int params_len = params.length(); - int last = 0; - while(last < params_len && (params_data[last].unicode() == SPACE - /*|| params_data[last].unicode() == TAB*/)) - ++last; - for(int x = last, parens = 0; x <= params_len; x++) { - unicode = params_data[x].unicode(); - if(x == params_len) { - while(x && params_data[x-1].unicode() == SPACE) - --x; - QString mid(params_data+last, x-last); - args << mid; - break; - } - if(unicode == LPAREN) { - --parens; - } else if(unicode == RPAREN) { - ++parens; - } else if(quote && unicode == quote) { - quote = 0; - } else if(!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { - quote = unicode; - } - if(!parens && !quote && unicode == COMMA) { - QString mid = params.mid(last, x - last).trimmed(); - args << mid; - last = x+1; - while(last < params_len && (params_data[last].unicode() == SPACE - /*|| params_data[last].unicode() == TAB*/)) - ++last; + for(int last = 0; ;) { + while(last < params_len && (params_data[last].unicode() == SPACE + /*|| params_data[last].unicode() == TAB*/)) + ++last; + for(int x = last, parens = 0; ; x++) { + if(x == params_len) { + while(x && params_data[x-1].unicode() == SPACE) + --x; + QString mid(params_data+last, x-last); + args << mid; + return args; + } + ushort unicode = params_data[x].unicode(); + if(unicode == LPAREN) { + --parens; + } else if(unicode == RPAREN) { + ++parens; + } else if(quote && unicode == quote) { + quote = 0; + } else if(!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { + quote = unicode; + } + if(!parens && !quote && unicode == COMMA) { + QString mid = params.mid(last, x - last).trimmed(); + args << mid; + last = x+1; + break; + } } } - return args; } static QStringList split_value_list(const QString &vals) -- cgit v0.12 From 005e39a2aab88d47044fa2108a6d04bd490b169e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 25 Jan 2011 13:23:24 +0100 Subject: cleanup split_arg_list() some more unify the code paths for last and intermediate arguments. as a side effect, this should be somewhat more efficient. Reviewed-by: mariusSO --- qmake/project.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index d690770..7951d11 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -249,10 +249,9 @@ static QStringList split_arg_list(QString params) ++last; for(int x = last, parens = 0; ; x++) { if(x == params_len) { - while(x && params_data[x-1].unicode() == SPACE) + while(x > last && params_data[x-1].unicode() == SPACE) --x; - QString mid(params_data+last, x-last); - args << mid; + args << params.mid(last, x - last); return args; } ushort unicode = params_data[x].unicode(); @@ -266,9 +265,11 @@ static QStringList split_arg_list(QString params) quote = unicode; } if(!parens && !quote && unicode == COMMA) { - QString mid = params.mid(last, x - last).trimmed(); - args << mid; + int prev = last; last = x+1; + while(x > prev && params_data[x-1].unicode() == SPACE) + --x; + args << params.mid(prev, x - prev); break; } } -- cgit v0.12 From 648dbc62e9c4e3fc15613c86bbf3c33029d56366 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 25 Jan 2011 13:59:20 +0100 Subject: interpret backslash escaping of quotes in split_arg_list() split_value_list() interprets them, too, but this is useless if the higher layer doesn't and is thus confused by unmatched quotes. note the top-level parsing layer doesn't support escapes, but that's ok, because there function calls are "isolated" by non-escapable parenthesis counting (and the RHS of assignments is not subject to any parsing at all). Reviewed-by: mariusSO --- qmake/project.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 7951d11..88d5962 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -237,6 +237,7 @@ static QStringList split_arg_list(QString params) const ushort RPAREN = ')'; const ushort SINGLEQUOTE = '\''; const ushort DOUBLEQUOTE = '"'; + const ushort BACKSLASH = '\\'; const ushort COMMA = ','; const ushort SPACE = ' '; //const ushort TAB = '\t'; @@ -255,14 +256,17 @@ static QStringList split_arg_list(QString params) return args; } ushort unicode = params_data[x].unicode(); - if(unicode == LPAREN) { - --parens; - } else if(unicode == RPAREN) { - ++parens; + if(x != (int)params_len-1 && unicode == BACKSLASH && + (params_data[x+1].unicode() == SINGLEQUOTE || params_data[x+1].unicode() == DOUBLEQUOTE)) { + x++; //get that 'escape' } else if(quote && unicode == quote) { quote = 0; } else if(!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) { quote = unicode; + } else if(unicode == RPAREN) { + --parens; + } else if(unicode == LPAREN) { + ++parens; } if(!parens && !quote && unicode == COMMA) { int prev = last; -- cgit v0.12 From e881b19ba3f2f4bfda460e1a043f461fb0517d70 Mon Sep 17 00:00:00 2001 From: Sergey Belyashov Date: Tue, 25 Jan 2011 20:41:07 +0100 Subject: Added scrollbars support to the Linguist form preview. Merge-request: 1030 Reviewed-by: Oswald Buddenhagen --- tools/linguist/linguist/formpreviewview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/linguist/linguist/formpreviewview.cpp b/tools/linguist/linguist/formpreviewview.cpp index d46cf76..a2a6002 100644 --- a/tools/linguist/linguist/formpreviewview.cpp +++ b/tools/linguist/linguist/formpreviewview.cpp @@ -463,6 +463,8 @@ FormPreviewView::FormPreviewView(QWidget *parent, MultiDataModel *dataModel) m_mdiArea = new QMdiArea(this); m_mdiArea->addSubWindow(m_mdiSubWindow); setCentralWidget(m_mdiArea); + m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } void FormPreviewView::setSourceContext(int model, MessageItem *messageItem) -- cgit v0.12