diff options
22 files changed, 457 insertions, 236 deletions
diff --git a/src/qml/debugger/qqmlabstractprofileradapter.cpp b/src/qml/debugger/qqmlabstractprofileradapter.cpp index 3c6752419a..ac673a89a2 100644 --- a/src/qml/debugger/qqmlabstractprofileradapter.cpp +++ b/src/qml/debugger/qqmlabstractprofileradapter.cpp @@ -36,6 +36,7 @@ QT_BEGIN_NAMESPACE /*! + * \internal * \class QQmlAbstractProfilerAdapter * \inmodule QtQml * Abstract base class for all adapters between profilers and the QQmlProfilerService. Adapters have @@ -45,6 +46,7 @@ QT_BEGIN_NAMESPACE */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::dataRequested() * Signals that data has been requested by the \c QQmlProfilerService. This signal should be * connected to a slot in the profiler and the profiler should then transfer its currently available @@ -52,6 +54,7 @@ QT_BEGIN_NAMESPACE */ /*! + * \internal * \fn qint64 QQmlAbstractProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages) * Append the messages up to the timestamp \a until, chronologically sorted, to \a messages. Keep * track of the messages already sent and with each subsequent call to this method start with the @@ -64,10 +67,11 @@ QT_BEGIN_NAMESPACE */ /*! - * \fn void QQmlAbstractProfilerAdapter::startProfiling() - * Emits either \c profilingEnabled() or \c profilingEnabledWhileWaiting(), depending on \c waiting. - * If the profiler's thread is waiting for an initial start signal we can emit the signal over a - * \c Qt::DirectConnection to avoid the delay of the event loop. + * \internal + * Emits either \c profilingEnabled(quint64) or \c profilingEnabledWhileWaiting(quint64), depending + * on \c waiting. If the profiler's thread is waiting for an initial start signal, we can emit the + * signal over a Qt::DirectConnection to avoid the delay of the event loop. The \a features are + * passed on to the signal. */ void QQmlAbstractProfilerAdapter::startProfiling(quint64 features) { @@ -79,10 +83,10 @@ void QQmlAbstractProfilerAdapter::startProfiling(quint64 features) } /*! - * \fn void QQmlAbstractProfilerAdapter::stopProfiling() + * \internal * Emits either \c profilingDisabled() or \c profilingDisabledWhileWaiting(), depending on - * \c waiting. If the profiler's thread is waiting for an initial start signal we can emit the - * signal over a \c Qt::DirectConnection to avoid the delay of the event loop. This should trigger + * \c waiting. If the profiler's thread is waiting for an initial start signal, we can emit the + * signal over a Qt::DirectConnection to avoid the delay of the event loop. This should trigger * the profiler to report its collected data and subsequently delete it. */ void QQmlAbstractProfilerAdapter::stopProfiling() { @@ -94,56 +98,67 @@ void QQmlAbstractProfilerAdapter::stopProfiling() { } /*! + * \internal * \fn bool QQmlAbstractProfilerAdapter::isRunning() const * Returns if the profiler is currently running. The profiler is considered to be running after - * \c startProfiling() has been called until \c stopProfiling() is called. That is independent of - * \c waiting. The profiler may be running and waiting at the same time. + * \c startProfiling(quint64) has been called until \c stopProfiling() is called. That is + * independent of \c waiting. The profiler may be running and waiting at the same time. */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::profilingDisabled() * This signal is emitted if \c stopProfiling() is called while the profiler is not considered to * be waiting. The profiler is expected to handle the signal asynchronously. */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting() * This signal is emitted if \c stopProfiling() is called while the profiler is considered to be - * waiting. In many cases this signal can be connected with a \c Qt::DirectConnection. + * waiting. In many cases this signal can be connected with a Qt::DirectConnection. */ /*! - * \fn void QQmlAbstractProfilerAdapter::profilingEnabled() - * This signal is emitted if \c startProfiling() is called while the profiler is not considered to - * be waiting. The profiler is expected to handle the signal asynchronously. + * \internal + * \fn void QQmlAbstractProfilerAdapter::profilingEnabled(quint64 features) + * This signal is emitted if \c startProfiling(quint64) is called while the profiler is not + * considered to be waiting. The profiler is expected to handle the signal asynchronously. The + * \a features are passed on from \c startProfiling(quint64). */ /*! - * \fn void QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting() - * This signal is emitted if \c startProfiling() is called while the profiler is considered to be - * waiting. In many cases this signal can be connected with a \c Qt::DirectConnection. By starting - * the profiler synchronously when the QML engine starts instead of waiting for the first iteration - * of the event loop the engine startup can be profiled. + * \internal + * \fn void QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting(quint64 features) + * This signal is emitted if \c startProfiling(quint64) is called while the profiler is considered + * to be waiting. In many cases this signal can be connected with a Qt::DirectConnection. By + * starting the profiler synchronously when the QML engine starts instead of waiting for the first + * iteration of the event loop the engine startup can be profiled. The \a features are passed on + * from \c startProfiling(quint64). */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::referenceTimeKnown(const QElapsedTimer &timer) * This signal is used to synchronize the profiler's timer to the QQmlProfilerservice's. The * profiler is expected to save \a timer and use it for timestamps on its data. */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::synchronize(const QElapsedTimer &timer) * Synchronize the profiler to \a timer. This emits \c referenceTimeKnown(). */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::reportData() * Make the profiler report its current data without stopping the collection. The same (and * additional) data can later be requested again with \c stopProfiling() or \c reportData(). */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::startWaiting() * Consider the profiler to be waiting from now on. While the profiler is waiting it can be directly * accessed even if it is in a different thread. This method should only be called if it is actually @@ -151,6 +166,7 @@ void QQmlAbstractProfilerAdapter::stopProfiling() { */ /*! + * \internal * \fn void QQmlAbstractProfilerAdapter::stopWaiting() * Consider the profiler not to be waiting anymore. If it lives in a different threads any requests * for it have to be done via a queued connection then. diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc index 50af8543ab..ed73a2b9ba 100644 --- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc +++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc @@ -43,17 +43,14 @@ documentation about \section1 Contents of a Module Definition qmldir File -A \c qmldir file which defines a module is a plain-text file which consists -of the following commands: +A \c qmldir file is a plain-text file that contains +the following commands: \table \header - \li Command \li Syntax \li Usage - \row - \li Module Identifier Directive \li \code module <ModuleIdentifier> @@ -73,14 +70,14 @@ module ExampleModule \endcode \row - \li Object Type Declaration \li \code -<TypeName> <InitialVersion> <File> +[singleton] <TypeName> <InitialVersion> <File> \endcode \li Declares a \l{qtqml-typesystem-objecttypes.html}{QML object type} to be made available by the module. \list + \li \c [singleton] Optional. Used to declare a singleton type. \li \c <TypeName> is the type being made available \li \c <InitialVersion> is the module version for which the type is to be made available \li \c <File> is the (relative) file name of the QML file that defines the type @@ -89,14 +86,36 @@ module ExampleModule Zero or more object type declarations may exist in the \c qmldir file, however each object type must have a unique type name within any particular version of the module. + \note To declare a \c singleton type, the QML file defining the + type must include the \c {pragma Singleton} statement. Example: \code -MyCustomType 1.0 MyCustomType.qml +//Style.qml with custom singleton type definition +pragma Singleton +import QtQuick 2.0 + +QtObject { + property int textSize: 20 + property color textColor: "green" +} + +// qmldir declaring the singleton type +module CustomStyles +singleton Style 1.0 Style.qml + +// singleton type in use +import QtQuick 2.0 +import CustomStyles 1.0 + +Text { + font.pixelSize: Style.textSize + color: Style.textColor + text: "Hello World" +} \endcode \row - \li Internal Object Type Declaration \li \code internal <TypeName> <File> @@ -119,7 +138,6 @@ internal MyPrivateType MyPrivateType.qml load the non-exported type. \row - \li JavaScript Resource Declaration \li \code <ResourceIdentifier> <InitialVersion> <File> @@ -143,7 +161,6 @@ MyScript 1.0 MyScript.js {Importing JavaScript Resources In QML} for more information. \row - \li C++ Plugin Declaration \li \code plugin <Name> [<Path>] @@ -178,7 +195,6 @@ plugin <Name> [<Path>] plugin MyPluginLibrary \endcode \row - \li C++ Plugin Class \li \code classname <C++ plugin class> @@ -191,7 +207,6 @@ classname <C++ plugin class> this information. \row - \li Type Information Description File Declaration \li \code typeinfo <File> @@ -210,7 +225,6 @@ typeinfo mymodule.qmltypes as code completion for the types defined in your plugins. \row - \li Dependency Declaration \li \code depends <ModuleIdentifier> <InitialVersion> @@ -229,7 +243,6 @@ depends MyOtherModule 1.0 to include the other modules in application packages. \row - \li Comment \li \code # <Comment> @@ -242,10 +255,9 @@ depends MyOtherModule 1.0 \endcode \row - \li designersupported \li - \code - designersupported + \code +designersupported \endcode \li Set this property if the plugin is supported by Qt Quick Designer. diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 9ec1ed36c8..05d3876466 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -210,7 +210,6 @@ InstructionSelection::~InstructionSelection() void InstructionSelection::run(int functionIndex) { IR::Function *function = irModule->functions[functionIndex]; - QVector<Lookup> lookups; qSwap(_function, function); IR::Optimizer opt(_function); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index fd3b66226e..a4283825f7 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1390,11 +1390,11 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) case QMetaType::UShort: return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr)); case QMetaType::Char: - return QV4::Encode((int)*reinterpret_cast<const char*>(ptr)); + return newString(QChar::fromLatin1(*reinterpret_cast<const char *>(ptr)))->asReturnedValue(); case QMetaType::UChar: - return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr)); + return newString(QChar::fromLatin1(*reinterpret_cast<const unsigned char *>(ptr)))->asReturnedValue(); case QMetaType::QChar: - return QV4::Encode((int)(*reinterpret_cast<const QChar*>(ptr)).unicode()); + return newString(*reinterpret_cast<const QChar *>(ptr))->asReturnedValue(); case QMetaType::QDateTime: return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(ptr))); case QMetaType::QDate: diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index a7e3b22cd2..f2cd5da302 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -41,6 +41,9 @@ #include <private/qv4scopedvalue_p.h> #include "qv4runtime_p.h" #include "qv4objectiterator_p.h" +#include <private/qqmlvaluetypewrapper_p.h> +#include <private/qqmlmodelindexvaluetype_p.h> +#include <QtCore/qabstractitemmodel.h> #include <algorithm> @@ -71,7 +74,9 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description F(bool, Bool, QList<bool>, false) \ F(QString, String, QList<QString>, QString()) \ F(QString, QString, QStringList, QString()) \ - F(QUrl, Url, QList<QUrl>, QUrl()) + F(QUrl, Url, QList<QUrl>, QUrl()) \ + F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \ + F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange()) static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QString &element) { @@ -88,6 +93,19 @@ static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, co return engine->newString(element.toString())->asReturnedValue(); } +static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QModelIndex &element) +{ + const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(QMetaType::QModelIndex); + return QV4::QQmlValueTypeWrapper::create(engine, QVariant(element), vtmo, QMetaType::QModelIndex); +} + +static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QItemSelectionRange &element) +{ + int metaTypeId = qMetaTypeId<QItemSelectionRange>(); + const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(metaTypeId); + return QV4::QQmlValueTypeWrapper::create(engine, QVariant::fromValue(element), vtmo, metaTypeId); +} + static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *, qreal element) { return QV4::Encode(element); @@ -113,6 +131,16 @@ static QString convertElementToString(const QUrl &element) return element.toString(); } +static QString convertElementToString(const QModelIndex &element) +{ + return reinterpret_cast<const QQmlModelIndexValueType *>(&element)->toString(); +} + +static QString convertElementToString(const QItemSelectionRange &element) +{ + return reinterpret_cast<const QQmlItemSelectionRangeValueType *>(&element)->toString(); +} + static QString convertElementToString(qreal element) { QString qstr; @@ -145,6 +173,22 @@ template <> QUrl convertValueToElement(const Value &value) return QUrl(value.toQString()); } +template <> QModelIndex convertValueToElement(const Value &value) +{ + const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>(); + if (v) + return v->toVariant().toModelIndex(); + return QModelIndex(); +} + +template <> QItemSelectionRange convertValueToElement(const Value &value) +{ + const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>(); + if (v) + return v->toVariant().value<QItemSelectionRange>(); + return QItemSelectionRange(); +} + template <> qreal convertValueToElement(const Value &value) { return value.toNumber(); @@ -541,6 +585,12 @@ DEFINE_OBJECT_VTABLE(QQmlIntList); typedef QQmlSequence<QList<QUrl> > QQmlUrlList; template<> DEFINE_OBJECT_VTABLE(QQmlUrlList); +typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList; +template<> +DEFINE_OBJECT_VTABLE(QQmlQModelIndexList); +typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList; +template<> +DEFINE_OBJECT_VTABLE(QQmlQItemSelectionRangeList); typedef QQmlSequence<QList<bool> > QQmlBoolList; template<> DEFINE_OBJECT_VTABLE(QQmlBoolList); diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index 695884053e..df673c1fd5 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -78,7 +78,6 @@ class QQmlExpression; class QQmlContext; class QQmlType; class QUrl; -class QScriptContext; class QNetworkAccessManager; class QQmlNetworkAccessManagerFactory; class QQmlIncubationController; diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index d45f3ac19b..931adb9a13 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1387,8 +1387,30 @@ bool QQmlPropertyPrivate::write(QObject *object, bool ok = false; QVariant v; - if (variantType == QVariant::String) - v = QQmlStringConverters::variantFromString(value.toString(), propertyType, &ok); + if (variantType == QVariant::String) { + const QString &str = value.toString(); + const bool targetIsChar = (propertyType == qMetaTypeId<QChar>() + || propertyType == qMetaTypeId<char>() + || propertyType == qMetaTypeId<unsigned char>()); + // If the string contains only one character and the target is a char, try converting it. + if (targetIsChar) { + if (str.size() != 1) + return false; // We can only convert if the string contains exactly one character. + + const QChar &qChar = str.at(0); + if (propertyType == qMetaTypeId<QChar>()) { + v = qChar; + ok = true; + } else if (propertyType == qMetaTypeId<char>() || propertyType == qMetaTypeId<unsigned char>()) { + const char c = qChar.toLatin1(); + v = c; + ok = (qChar == c); + } + } else { + v = QQmlStringConverters::variantFromString(str, propertyType, &ok); + } + } + if (!ok) { v = value; if (v.convert(propertyType)) { diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 2b3f78b676..490ac66f1f 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -64,9 +64,7 @@ QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl() valueTypes[ii] = 0; // See types wrapped in qqmlmodelindexvaluetype_p.h - qRegisterMetaType<QModelIndexList>(); qRegisterMetaType<QItemSelectionRange>(); - qRegisterMetaType<QItemSelection>(); } QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl() @@ -112,18 +110,14 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) case QVariant::PersistentModelIndex: return &QQmlPersistentModelIndexValueType::staticMetaObject; default: + if (t == qMetaTypeId<QItemSelectionRange>()) + return &QQmlItemSelectionRangeValueType::staticMetaObject; + if (const QMetaObject *mo = QQml_valueTypeProvider()->metaObjectForMetaType(t)) return mo; break; } - if (t == qMetaTypeId<QModelIndexList>()) - return &QQmlModelIndexListValueType::staticMetaObject; - else if (t == qMetaTypeId<QItemSelectionRange>()) - return &QQmlItemSelectionRangeValueType::staticMetaObject; - else if (t == qMetaTypeId<QItemSelection>()) - return &QQmlItemSelectionValueType::staticMetaObject; - QMetaType metaType(t); if (metaType.flags() & QMetaType::IsGadget) return metaType.metaObject(); diff --git a/src/qml/types/qqmlitemmodels.qdoc b/src/qml/types/qqmlitemmodels.qdoc index 25c9321115..4e64aaa338 100644 --- a/src/qml/types/qqmlitemmodels.qdoc +++ b/src/qml/types/qqmlitemmodels.qdoc @@ -60,6 +60,17 @@ should not store any QModelIndex. You can, however, store QPersistentModelIndexes in a safe way. + \section1 QModelIndexList + + \l QModelIndexList is exposed in QML as a JavaScript array. Conversions are + automatically made from and to C++. In fact, any JavaScript array can be + converted back to QModelIndexList, with non-QModelIndex objects replaced by + invalid QModelIndexes. + + \note QModelIndex to QPersistentModelIndex conversion happens when accessing + the array elements because any QModelIndexList property retains reference + semantics when exposed this way. + \section1 \l QItemSelectionRange \list @@ -87,29 +98,13 @@ \li QItemSelectionRange \b{intersected}(QItemSelectionRange other) \endlist - \section1 \l QModelIndexList and \l QItemSelection - - Both \l QModelIndexList and \l QItemSelection expose the following properties - and functions as part of their \l QList API: - - \list - \li \b length : int - \li object \b{at}(int i) - \li void \b{append}(object o) - \li void \b{prepend}(o) - \li void \b{insert}(int i, object o) - \li void \b{removeFirst}() - \li void \b{removeLast}() - \li void \b{removeAt}(int i) - \endlist + \section1 QItemSelection - In addition, \l QItemSelection also exposes the following functions: + Similarly to QModelIndexList, \l QItemSelection is exposed in QML as a JavaScript + array of QItemSelectionRanges. Conversions are automatically made from and to C++. + In fact, any JavaScript array can be converted back to QItemSelection, with + non-QItemSelectionRange objects replaced by empty QItemSelectionRanges. - \list - \li void \b{select}(QModelIndex topLeft, QModelIndex bottomRight) - \li bool \b{contains}(QModelIndex index) - \li void \b{merge}(QItemSelection other, QItemSelectionModel::SelectionFlags command) - \endlist \sa ItemSelectionModel */ diff --git a/src/qml/types/qqmlmodelindexvaluetype_p.h b/src/qml/types/qqmlmodelindexvaluetype_p.h index 0e655ab3d7..371335c9f3 100644 --- a/src/qml/types/qqmlmodelindexvaluetype_p.h +++ b/src/qml/types/qqmlmodelindexvaluetype_p.h @@ -150,63 +150,6 @@ public: inline bool isEmpty() const { return v.isEmpty(); } }; -template<typename V, typename T> -QString q_listToString(const QList<T> &list, const QLatin1String &typeName) -{ - QString result = typeName; - result.append(QLatin1Char('(')); - for (typename QList<T>::size_type i = 0; i < list.count(); ++i) { - if (i) - result.append(QLatin1String(", ")); - result.append(reinterpret_cast<const V *>(&list.at(i))->toString()); - } - return result.append(QLatin1Char(')')); -} - -// Invokable QList<T> API forwarding for value types -#define QLISTVALUETYPE_QML_API(T) \ - Q_PROPERTY(int length READ length FINAL) \ - Q_INVOKABLE T at(int i) { return v.at(i); } \ - Q_INVOKABLE void append(const T &o) { v.append(o); } \ - Q_INVOKABLE void prepend(const T &o) { v.prepend(o); } \ - Q_INVOKABLE void insert(int i, const T &o) { v.insert(i, o); } \ - Q_INVOKABLE void removeFirst() { v.removeFirst(); } \ - Q_INVOKABLE void removeLast() { v.removeLast(); } \ - Q_INVOKABLE void removeAt(int i) { v.removeAt(i); } \ - int length() const { return v.length(); } - -struct QQmlModelIndexListValueType -{ - QModelIndexList v; - - Q_GADGET - -public: - Q_INVOKABLE QString toString() - { return q_listToString<QQmlModelIndexValueType>(v, QLatin1String("")); } - - QLISTVALUETYPE_QML_API(QModelIndex) -}; - -struct QQmlItemSelectionValueType -{ - QItemSelection v; - - Q_GADGET - -public: - Q_INVOKABLE QString toString() - { return q_listToString<QQmlItemSelectionRangeValueType>(v, QLatin1String("QItemSelection")); } - Q_INVOKABLE void select(const QModelIndex &topLeft, const QModelIndex &bottomRight) - { v.select(topLeft, bottomRight); } - Q_INVOKABLE bool contains(const QModelIndex &index) const - { return v.contains(index); } - Q_INVOKABLE void merge(const QItemSelection &other, int command) - { v.merge(other, QItemSelectionModel::SelectionFlags(command)); } - - QLISTVALUETYPE_QML_API(QItemSelectionRange) -}; - #undef QLISTVALUETYPE_INVOKABLE_API QT_END_NAMESPACE diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro index 04588f110c..24b87588b8 100644 --- a/src/qmltest/qmltest.pro +++ b/src/qmltest/qmltest.pro @@ -5,8 +5,8 @@ QT = core QT_PRIVATE = testlib-private quick qml-private gui core-private # Testlib is only a private dependency, which results in our users not -# inheriting CONFIG+=console transitively. Make it explicit. -MODULE_CONFIG = console +# inheriting testlibs's MODULE_CONFIG transitively. Make it explicit. +MODULE_CONFIG += $${QT.testlib.CONFIG} qtHaveModule(widgets) { QT += widgets diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index a9396051ab..52142346ab 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1010,6 +1010,9 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp bool rejectY = false; bool rejectX = false; + bool keepY = q->yflick(); + bool keepX = q->xflick(); + bool stealY = false; bool stealX = false; if (eventType == QEvent::MouseMove) { @@ -1082,6 +1085,11 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp } if (!rejectY && overThreshold) stealY = true; + + if ((newY >= minY && vData.pressPos == minY && vData.move.value() == minY && dy > 0) + || (newY <= maxY && vData.pressPos == maxY && vData.move.value() == maxY && dy < 0)) { + keepY = false; + } } vData.previousDragDelta = dy; } @@ -1144,13 +1152,19 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp if (!rejectX && overThreshold) stealX = true; + + if ((newX >= minX && vData.pressPos == minX && vData.move.value() == minX && dx > 0) + || (newX <= maxX && vData.pressPos == maxX && vData.move.value() == maxX && dx < 0)) { + keepX = false; + } } hData.previousDragDelta = dx; } stealMouse = stealX || stealY; if (stealMouse) { - q->setKeepMouseGrab(true); + if ((stealX && keepX) || (stealY && keepY)) + q->setKeepMouseGrab(true); clearDelayedPress(); } diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index 14d305ad50..7903f79e89 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -50,6 +50,14 @@ QT_BEGIN_NAMESPACE +QQuickTextNodeEngine::BinaryTreeNodeKey::BinaryTreeNodeKey(BinaryTreeNode *node) + : fontEngine(QRawFontPrivate::get(node->glyphRun.rawFont())->fontEngine) + , clipNode(node->clipNode) + , color(node->color.rgba()) + , selectionState(node->selectionState) +{ +} + QQuickTextNodeEngine::BinaryTreeNode::BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect, @@ -680,35 +688,34 @@ uint qHash(const QQuickTextNodeEngine::BinaryTreeNodeKey &key) void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularNodes, QList<BinaryTreeNode *> *imageNodes) { - QMultiHash<BinaryTreeNodeKey, BinaryTreeNode *> map; + QHash<BinaryTreeNodeKey, QList<BinaryTreeNode *> > map; for (int i = 0; i < m_processedNodes.size(); ++i) { BinaryTreeNode *node = m_processedNodes.data() + i; if (node->image.isNull()) { - QRawFont rawFont = node->glyphRun.rawFont(); - QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont); - QFontEngine *fontEngine = rawFontD->fontEngine; - - BinaryTreeNodeKey key(fontEngine, - node->clipNode, - node->color.rgba(), - int(node->selectionState)); - map.insertMulti(key, node); + BinaryTreeNodeKey key(node); + + QList<BinaryTreeNode *> &nodes = map[key]; + if (nodes.isEmpty()) + regularNodes->append(node); + + nodes.append(node); } else { imageNodes->append(node); } } - QMultiHash<BinaryTreeNodeKey, BinaryTreeNode *>::const_iterator it = map.constBegin(); - while (it != map.constEnd()) { - BinaryTreeNode *primaryNode = it.value(); - regularNodes->append(primaryNode); + for (int i = 0; i < regularNodes->size(); ++i) { + BinaryTreeNode *primaryNode = regularNodes->at(i); + BinaryTreeNodeKey key(primaryNode); + + const QList<BinaryTreeNode *> &nodes = map.value(key); + Q_ASSERT(nodes.first() == primaryNode); int count = 0; - QMultiHash<BinaryTreeNodeKey, BinaryTreeNode *>::const_iterator jt; - for (jt = it; jt != map.constEnd() && jt.key() == it.key(); ++jt) - count += jt.value()->glyphRun.glyphIndexes().size(); + for (int j = 0; j < nodes.size(); ++j) + count += nodes.at(j)->glyphRun.glyphIndexes().size(); if (count != primaryNode->glyphRun.glyphIndexes().size()) { QGlyphRun &glyphRun = primaryNode->glyphRun; @@ -718,24 +725,21 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN QVector<QPointF> glyphPositions = glyphRun.positions(); glyphPositions.reserve(count); - for (jt = it + 1; jt != map.constEnd() && jt.key() == it.key(); ++jt) { - BinaryTreeNode *otherNode = jt.value(); + for (int j = 1; j < nodes.size(); ++j) { + BinaryTreeNode *otherNode = nodes.at(j); glyphIndexes += otherNode->glyphRun.glyphIndexes(); primaryNode->ranges += otherNode->ranges; QVector<QPointF> otherPositions = otherNode->glyphRun.positions(); - for (int j = 0; j < otherPositions.size(); ++j) - glyphPositions += otherPositions.at(j) + (otherNode->position - primaryNode->position); + for (int k = 0; k < otherPositions.size(); ++k) + glyphPositions += otherPositions.at(k) + (otherNode->position - primaryNode->position); } - it = jt; Q_ASSERT(glyphPositions.size() == count); Q_ASSERT(glyphIndexes.size() == count); glyphRun.setGlyphIndexes(glyphIndexes); glyphRun.setPositions(glyphPositions); - } else { - ++it; } } } diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h index 178454b19e..2f6cacf601 100644 --- a/src/quick/items/qquicktextnodeengine_p.h +++ b/src/quick/items/qquicktextnodeengine_p.h @@ -104,16 +104,7 @@ public: struct BinaryTreeNodeKey { - BinaryTreeNodeKey(QFontEngine *fe, - QQuickDefaultClipNode *cn, - QRgb col, - int selState) - : fontEngine(fe) - , clipNode(cn) - , color(col) - , selectionState(selState) - { - } + BinaryTreeNodeKey(BinaryTreeNode *node); bool operator==(const BinaryTreeNodeKey &otherKey) const { diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 35f4a84980..696f8f9080 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1868,19 +1868,23 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event) Qt::TouchPointStates states; for (int i = 0; i < event->touchPoints().count(); ++i) { const QTouchEvent::TouchPoint &tp = tpts.at(i); - const QTouchEvent::TouchPoint &tp2 = delayedTouch->touchPoints().at(i); - if (tp.id() != tp2.id()) { + const QTouchEvent::TouchPoint &tpDelayed = delayedTouch->touchPoints().at(i); + if (tp.id() != tpDelayed.id()) { mismatch = true; break; } - if (tp2.state() == Qt::TouchPointMoved && tp.state() == Qt::TouchPointStationary) + if (tpDelayed.state() == Qt::TouchPointMoved && tp.state() == Qt::TouchPointStationary) tpts[i].setState(Qt::TouchPointMoved); + tpts[i].setLastPos(tpDelayed.lastPos()); + tpts[i].setLastScenePos(tpDelayed.lastScenePos()); + tpts[i].setLastScreenPos(tpDelayed.lastScreenPos()); + tpts[i].setLastNormalizedPos(tpDelayed.lastNormalizedPos()); states |= tpts.at(i).state(); } - // same touch event? then merge if so + // matching touch event? then merge the new event into the old one if (!mismatch) { delayedTouch->setTouchPoints(tpts); delayedTouch->setTimestamp(event->timestamp()); @@ -1888,8 +1892,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event) } } - // otherwise; we need to deliver the delayed event first, and - // then delay this one.. + // merging wasn't possible, so deliver the delayed event first, and then delay this one reallyDeliverTouchEvent(delayedTouch); delete delayedTouch; delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints()); diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index 64f3d0ba6c..50481d4312 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -200,8 +200,8 @@ public: protected: QQuickTransformAnimatorJob(); - void initialize(QQuickAnimatorController *controller); - void nodeWasDestroyed(); + void initialize(QQuickAnimatorController *controller) Q_DECL_OVERRIDE; + void nodeWasDestroyed() Q_DECL_OVERRIDE; void targetWasDeleted() Q_DECL_OVERRIDE; Helper *m_helper; diff --git a/tests/auto/qml/qqmlitemmodels/data/itemselection.qml b/tests/auto/qml/qqmlitemmodels/data/itemselection.qml index 57cb6436e9..c2da71627a 100644 --- a/tests/auto/qml/qqmlitemmodels/data/itemselection.qml +++ b/tests/auto/qml/qqmlitemmodels/data/itemselection.qml @@ -1,9 +1,10 @@ import Test 1.0 ItemModelsTest { - property var itemSelection property int count property bool contains: false + property var itemSelectionBinding: itemSelection + property var itemSelectionRead function range(top, bottom, left, right, parent) { if (parent === undefined) @@ -14,23 +15,15 @@ ItemModelsTest { } onModelChanged: { - itemSelection = createItemSelection() - itemSelection.prepend(range(0, 0, 0, 5)) - itemSelection.append(range(0, 5, 0, 0)) + itemSelection = [] + itemSelection.push(range(0, 0, 0, 5)) + itemSelection.push(range(0, 5, 0, 0)) for (var i = 0; i < 3; i++) - itemSelection.insert(i, range(i, i + 1, i + 2, i + 3)) + itemSelection.splice(i, 0, range(i, i + 1, i + 2, i + 3)) - var itemSelection2 = createItemSelection() - for (i = 3; i < 6; i++) - itemSelection2.select(model.index(i, i + 1), model.index(i + 2, i + 3)) - - itemSelection.merge(itemSelection2, 2 /*ItemSelectionModel.Select*/) + itemSelectionRead = itemSelection count = itemSelection.length - contains = itemSelection.contains(model.index(0, 0)) - - itemSelection.removeAt(3) - itemSelection.removeFirst() - itemSelection.removeLast() + contains = itemSelection.some(function (range, idx) { return range.contains(model.index(0, 0)) }) } } diff --git a/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml b/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml index 44393392d3..389c5daaf5 100644 --- a/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml +++ b/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml @@ -1,21 +1,30 @@ import Test 1.0 ItemModelsTest { - property var modelIndexList property int count + property var modelIndexListCopy + property var modelIndexListRead + property var modelIndexListBinding: modelIndexList + property bool varPropIsArray + property bool varIsArray + property bool propIsArray onModelChanged: { - modelIndexList = createModelIndexList() - modelIndexList.prepend(model.index(0, 0)) - modelIndexList.append(model.index(1, 1)) + var jsModelIndexList = [] for (var i = 0; i < 3; i++) - modelIndexList.insert(i, model.index(2 + i, 2 + i)) + jsModelIndexList.push(model.index(2 + i, 2 + i)) + jsModelIndexList.push("Hi Bronsky!") + modelIndex = jsModelIndexList[0] count = modelIndexList.length - modelIndex = modelIndexList.at(0) + propIsArray = modelIndexList instanceof Array + modelIndexList = jsModelIndexList + modelIndexListRead = modelIndexList - modelIndexList.removeAt(3) - modelIndexList.removeFirst() - modelIndexList.removeLast() + modelIndexListCopy = someModelIndexList() + varPropIsArray = modelIndexListCopy instanceof Array + + jsModelIndexList = someModelIndexList() + varIsArray = jsModelIndexList instanceof Array } } diff --git a/tests/auto/qml/qqmlitemmodels/testtypes.h b/tests/auto/qml/qqmlitemmodels/testtypes.h index 986db54912..69da24ec6e 100644 --- a/tests/auto/qml/qqmlitemmodels/testtypes.h +++ b/tests/auto/qml/qqmlitemmodels/testtypes.h @@ -45,11 +45,15 @@ class ItemModelsTest : public QObject Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QModelIndex modelIndex READ modelIndex WRITE setModelIndex NOTIFY changed) Q_PROPERTY(QPersistentModelIndex persistentModelIndex READ persistentModelIndex WRITE setPersistentModelIndex NOTIFY changed) + Q_PROPERTY(QModelIndexList modelIndexList READ modelIndexList WRITE setModelIndexList NOTIFY changed) + Q_PROPERTY(QItemSelection itemSelection READ itemSelection WRITE setItemSelection NOTIFY changed) public: - ItemModelsTest() - : m_model(0) - {} + ItemModelsTest(QObject *parent = 0) + : QObject(parent) + , m_model(0) + { + } QModelIndex modelIndex() const { @@ -61,6 +65,31 @@ public: return m_persistentModelIndex; } + QModelIndexList modelIndexList() + { + static bool firstTime = true; + if (firstTime && m_model && m_modelIndexList.isEmpty()) { + firstTime = false; + for (int i = 0; i < m_model->rowCount(); i++) + m_modelIndexList << m_model->index(i, 0); + } + return m_modelIndexList; + } + + Q_INVOKABLE QModelIndexList someModelIndexList() const + { + QModelIndexList list; + if (m_model) + for (int i = 0; i < m_model->rowCount(); i++) + list << m_model->index(i, 0); + return list; + } + + QItemSelection itemSelection() const + { + return m_itemSelection; + } + void emitChanged() { emit changed(); @@ -86,11 +115,6 @@ public: return QModelIndex(); } - Q_INVOKABLE QModelIndexList createModelIndexList() const - { - return QModelIndexList(); - } - Q_INVOKABLE QItemSelectionRange createItemSelectionRange(const QModelIndex &tl, const QModelIndex &br) const { return QItemSelectionRange(tl, br); @@ -134,6 +158,24 @@ public slots: emit modelChanged(arg); } + void setModelIndexList(QModelIndexList arg) + { + if (m_modelIndexList == arg) + return; + + m_modelIndexList = arg; + emit changed(); + } + + void setItemSelection(QItemSelection arg) + { + if (m_itemSelection == arg) + return; + + m_itemSelection = arg; + emit changed(); + } + signals: void changed(); @@ -146,6 +188,8 @@ private: QModelIndex m_modelIndex; QPersistentModelIndex m_persistentModelIndex; QAbstractItemModel *m_model; + QModelIndexList m_modelIndexList; + QItemSelection m_itemSelection; }; #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp index 84e8011685..637b9e4b90 100644 --- a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp +++ b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp @@ -184,31 +184,53 @@ void tst_qqmlitemmodels::itemSelection() TestModel model(10, 10); object->setModel(&model); - QCOMPARE(object->property("count").toInt(), 8); + QCOMPARE(object->property("count").toInt(), 5); QCOMPARE(object->property("contains").toBool(), true); - QVariant milVariant = object->property("itemSelection"); - QCOMPARE(milVariant.userType(), qMetaTypeId<QItemSelection>()); + const char *propNames[] = { "itemSelectionRead", "itemSelectionBinding", 0 }; + for (const char **name = propNames; *name; name++) { + QVariant isVariant = object->property(*name); + QCOMPARE(isVariant.userType(), qMetaTypeId<QItemSelection>()); - const QItemSelection &mil = milVariant.value<QItemSelection>(); - QCOMPARE(mil.count(), 5); + const QItemSelection &sel = isVariant.value<QItemSelection>(); + QCOMPARE(sel.count(), object->itemSelection().count()); + QCOMPARE(sel, object->itemSelection()); + } } void tst_qqmlitemmodels::modelIndexList() { INIT_TEST_OBJECT("modelindexlist.qml", object); TestModel model(10, 10); + model.fetchMore(QModelIndex()); object->setModel(&model); - QCOMPARE(object->property("count").toInt(), 5); - - QVariant milVariant = object->property("modelIndexList"); - QCOMPARE(milVariant.userType(), qMetaTypeId<QModelIndexList>()); - - const QModelIndexList &mil = milVariant.value<QModelIndexList>(); - QCOMPARE(mil.count(), 2); - QCOMPARE(mil.at(0), model.index(3, 3)); - QCOMPARE(mil.at(1), model.index(4, 4)); + QVERIFY(object->property("propIsArray").toBool()); + QVERIFY(object->property("varPropIsArray").toBool()); + QVERIFY(object->property("varIsArray").toBool()); + + QCOMPARE(object->property("count").toInt(), 10); + const QModelIndexList &mil = object->modelIndexList(); + QCOMPARE(mil.count(), 4); + for (int i = 0; i < 3; i++) + QCOMPARE(mil.at(i), model.index(2 + i, 2 + i)); + QCOMPARE(mil.at(3), QModelIndex()); // The string inserted at the end should result in an invalid index + QCOMPARE(mil.at(0), object->modelIndex()); + + QVariant cppMILVariant = object->property("modelIndexListCopy"); + QCOMPARE(cppMILVariant.userType(), qMetaTypeId<QModelIndexList>()); + QModelIndexList someMIL = object->someModelIndexList(); + QCOMPARE(cppMILVariant.value<QModelIndexList>(), someMIL); + + const char *propNames[] = { "modelIndexListRead", "modelIndexListBinding", 0 }; + for (const char **name = propNames; *name; name++) { + QVariant milVariant = object->property(*name); + QCOMPARE(milVariant.userType(), qMetaTypeId<QModelIndexList>()); + + const QModelIndexList &milProp = milVariant.value<QModelIndexList>(); + QCOMPARE(milProp.count(), mil.count()); + QCOMPARE(milProp, mil); + } } #undef INIT_TEST_OBJECT diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index f8af13582e..c4b2325843 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -326,10 +326,16 @@ class PropertyObject : public QObject Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal) Q_PROPERTY(MyQmlObject *qmlObject READ qmlObject) Q_PROPERTY(MyQObject *qObject READ qObject WRITE setQObject NOTIFY qObjectChanged) + Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) + Q_PROPERTY(char charProperty READ charProperty WRITE setCharProperty) + Q_PROPERTY(QChar qcharProperty READ qcharProperty WRITE setQcharProperty) + Q_PROPERTY(QChar constQChar READ constQChar STORED false CONSTANT FINAL) + Q_PROPERTY(char constChar READ constChar STORED false CONSTANT FINAL) + Q_PROPERTY(int constInt READ constInt STORED false CONSTANT FINAL) Q_CLASSINFO("DefaultProperty", "defaultProperty") public: - PropertyObject() : m_resetProperty(9), m_qObject(0) {} + PropertyObject() : m_resetProperty(9), m_qObject(0), m_stringProperty("foo") {} int defaultProperty() { return 10; } QRect rectProperty() { return QRect(10, 10, 1, 209); } @@ -361,6 +367,18 @@ public: } } + QString stringProperty() const { return m_stringProperty;} + char charProperty() const { return m_charProperty; } + QChar qcharProperty() const { return m_qcharProperty; } + + QChar constQChar() const { return 0x25cf; /* Unicode: black circle */ } + char constChar() const { return 'A'; } + int constInt() const { return 123456; } + + void setStringProperty(QString arg) { m_stringProperty = arg; } + void setCharProperty(char arg) { m_charProperty = arg; } + void setQcharProperty(QChar arg) { m_qcharProperty = arg; } + signals: void clicked(); void oddlyNamedNotifySignal(); @@ -374,6 +392,9 @@ private: int m_propertyWithNotify; MyQmlObject m_qmlObject; MyQObject *m_qObject; + QString m_stringProperty; + char m_charProperty; + QChar m_qcharProperty; }; QML_DECLARE_TYPE(PropertyObject); @@ -1382,6 +1403,71 @@ void tst_qqmlproperty::write() QCOMPARE(o.url(), result); } + // Char/string-property + { + PropertyObject o; + QQmlProperty charProperty(&o, "charProperty"); + QQmlProperty qcharProperty(&o, "qcharProperty"); + QQmlProperty stringProperty(&o, "stringProperty"); + + const int black_circle = 0x25cf; + + QCOMPARE(charProperty.write(QString("foo")), false); + QCOMPARE(charProperty.write('Q'), true); + QCOMPARE(charProperty.read(), QVariant('Q')); + QCOMPARE(charProperty.write(QString("t")), true); + QCOMPARE(charProperty.read(), QVariant('t')); + + QCOMPARE(qcharProperty.write(QString("foo")), false); + QCOMPARE(qcharProperty.write('Q'), true); + QCOMPARE(qcharProperty.read(), QVariant('Q')); + QCOMPARE(qcharProperty.write(QString("t")), true); + QCOMPARE(qcharProperty.read(), QVariant('t')); + QCOMPARE(qcharProperty.write(QChar(black_circle)), true); + QCOMPARE(qcharProperty.read(), QVariant(QChar(black_circle))); + + QCOMPARE(o.stringProperty(), QString("foo")); // Default value + QCOMPARE(stringProperty.write(QString("bar")), true); + QCOMPARE(o.stringProperty(), QString("bar")); + QCOMPARE(stringProperty.write(QVariant(1234)), true); + QCOMPARE(stringProperty.read().toString(), QString::number(1234)); + QCOMPARE(stringProperty.write(QChar(black_circle)), true); + QCOMPARE(stringProperty.read(), QVariant(QString(QChar(black_circle)))); + + { // char -> QString + QQmlComponent component(&engine); + component.setData("import Test 1.0\nPropertyObject { stringProperty: constChar }", QUrl()); + PropertyObject *obj = qobject_cast<PropertyObject*>(component.create()); + QVERIFY(obj != 0); + if (obj) { + QQmlProperty stringProperty(obj, "stringProperty"); + QCOMPARE(stringProperty.read(), QVariant(QString(obj->constChar()))); + } + } + + { // QChar -> QString + QQmlComponent component(&engine); + component.setData("import Test 1.0\nPropertyObject { stringProperty: constQChar }", QUrl()); + PropertyObject *obj = qobject_cast<PropertyObject*>(component.create()); + QVERIFY(obj != 0); + if (obj) { + QQmlProperty stringProperty(obj, "stringProperty"); + QCOMPARE(stringProperty.read(), QVariant(QString(obj->constQChar()))); + } + } + + { // int -> QString + QQmlComponent component(&engine); + component.setData("import Test 1.0\nPropertyObject { stringProperty: constInt }", QUrl()); + PropertyObject *obj = qobject_cast<PropertyObject*>(component.create()); + QVERIFY(obj != 0); + if (obj) { + QQmlProperty stringProperty(obj, "stringProperty"); + QCOMPARE(stringProperty.read(), QVariant(QString::number(obj->constInt()))); + } + } + } + // VariantMap-property QVariantMap vm; vm.insert("key", "value"); diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 5c96cc151e..7d08c3c81e 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -1427,17 +1427,30 @@ void tst_qquickflickable::nestedStopAtBounds_data() { QTest::addColumn<bool>("transpose"); QTest::addColumn<bool>("invert"); - - QTest::newRow("left") << false << false; - QTest::newRow("right") << false << true; - QTest::newRow("top") << true << false; - QTest::newRow("bottom") << true << true; + QTest::addColumn<int>("boundsBehavior"); + QTest::addColumn<qreal>("margin"); + + QTest::newRow("left,stop") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(0); + QTest::newRow("right,stop") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(0); + QTest::newRow("top,stop") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(0); + QTest::newRow("bottom,stop") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(0); + QTest::newRow("left,over") << false << false << int(QQuickFlickable::DragOverBounds) << qreal(0); + QTest::newRow("right,over") << false << true << int(QQuickFlickable::DragOverBounds) << qreal(0); + QTest::newRow("top,over") << true << false << int(QQuickFlickable::DragOverBounds) << qreal(0); + QTest::newRow("bottom,over") << true << true << int(QQuickFlickable::DragOverBounds) << qreal(0); + + QTest::newRow("left,stop,margin") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(20); + QTest::newRow("right,stop,margin") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(20); + QTest::newRow("top,stop,margin") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(20); + QTest::newRow("bottom,stop,margin") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(20); } void tst_qquickflickable::nestedStopAtBounds() { QFETCH(bool, transpose); QFETCH(bool, invert); + QFETCH(int, boundsBehavior); + QFETCH(qreal, margin); QQuickView view; view.setSource(testFileUrl("nestedStopAtBounds.qml")); @@ -1455,8 +1468,20 @@ void tst_qquickflickable::nestedStopAtBounds() QQuickFlickable *inner = outer->findChild<QQuickFlickable*>("innerFlickable"); QVERIFY(inner); inner->setFlickableDirection(transpose ? QQuickFlickable::VerticalFlick : QQuickFlickable::HorizontalFlick); - inner->setContentX(invert ? 0 : 100); - inner->setContentY(invert ? 0 : 100); + inner->setBoundsBehavior(QQuickFlickable::BoundsBehavior(boundsBehavior)); + + invert ? inner->setRightMargin(margin) : inner->setLeftMargin(margin); + invert ? inner->setBottomMargin(margin) : inner->setTopMargin(margin); + + inner->setContentX(invert ? -margin : 100 - margin); + inner->setContentY(invert ? -margin : 100 - margin); + inner->setContentWidth(400 - margin); + inner->setContentHeight(400 - margin); + + QCOMPARE(inner->isAtXBeginning(), invert); + QCOMPARE(inner->isAtXEnd(), !invert); + QCOMPARE(inner->isAtYBeginning(), invert); + QCOMPARE(inner->isAtYEnd(), !invert); const int threshold = qApp->styleHints()->startDragDistance(); @@ -1495,10 +1520,10 @@ void tst_qquickflickable::nestedStopAtBounds() QTRY_VERIFY(!outer->isMoving()); axis = 200; - inner->setContentX(0); - inner->setContentY(0); - inner->setContentWidth(inner->width()); - inner->setContentHeight(inner->height()); + inner->setContentX(-margin); + inner->setContentY(-margin); + inner->setContentWidth(inner->width() - margin); + inner->setContentHeight(inner->height() - margin); // Drag inner with equal size and contentSize QTest::mousePress(&view, Qt::LeftButton, 0, position); @@ -1512,8 +1537,8 @@ void tst_qquickflickable::nestedStopAtBounds() QTest::mouseRelease(&view, Qt::LeftButton, 0, position); axis = 200; - inner->setContentX(0); - inner->setContentY(0); + inner->setContentX(-margin); + inner->setContentY(-margin); inner->setContentWidth(inner->width() - 100); inner->setContentHeight(inner->height() - 100); |
