aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-03-24 22:09:49 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2015-03-24 22:09:49 +0100
commitc8427a542bc61d95e4f313f22a0118ccf1e963a4 (patch)
treecc9a9c6e31180c50a8d0a2f9b82ca84c9049c741
parent7b7297470cde5645b2ea1db4cec7ac4bec87c1a3 (diff)
parent3f2eabc8d90c4ee535cb0a2500e033171e203537 (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts: tests/auto/qml/qqmlitemmodels/testtypes.h Change-Id: I2f2f3f47fd873ddd4fd027414654a861b56357f4
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter.cpp52
-rw-r--r--src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc48
-rw-r--r--src/qml/jit/qv4isel_masm.cpp1
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp52
-rw-r--r--src/qml/qml/qqmlengine.h1
-rw-r--r--src/qml/qml/qqmlproperty.cpp26
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp12
-rw-r--r--src/qml/types/qqmlitemmodels.qdoc37
-rw-r--r--src/qml/types/qqmlmodelindexvaluetype_p.h57
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/quick/items/qquickflickable.cpp16
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp52
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h11
-rw-r--r--src/quick/items/qquickwindow.cpp15
-rw-r--r--src/quick/util/qquickanimatorjob_p.h4
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/itemselection.qml23
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml27
-rw-r--r--tests/auto/qml/qqmlitemmodels/testtypes.h60
-rw-r--r--tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp50
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp88
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp51
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);