aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp1
-rw-r--r--src/imports/folderlistmodel/plugin.cpp3
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp60
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h5
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/configure.json1
-rw-r--r--src/qml/parser/qqmljs.g25
-rw-r--r--src/qml/qml/qqmltypeloader.cpp97
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
-rw-r--r--src/qml/types/qqmlinstantiator_p.h3
-rw-r--r--src/qml/types/qqmlinstantiator_p_p.h5
-rw-r--r--src/qml/util/qqmladaptormodel.cpp2
-rw-r--r--src/quick/items/qquickborderimage.cpp26
-rw-r--r--src/quick/items/qquickitemview.cpp1
-rw-r--r--src/quick/items/qquicklistview.cpp38
-rw-r--r--src/quick/items/qquicktableview.cpp10
-rw-r--r--src/quick/items/qquicktableview_p_p.h1
-rw-r--r--src/quick/items/qquickwindow.cpp26
-rw-r--r--src/quick/scenegraph/qsgbasicinternalimagenode.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp25
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/data/sortdir/Uppercase.txt0
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/data/sortdir/lowercase.txt0
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp45
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp1
-rw-r--r--tests/auto/quick/qquicklistview/data/sectionSnapping.qml49
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp58
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h15
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp40
28 files changed, 421 insertions, 121 deletions
diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp
index 5b44ed012f..a006f659c9 100644
--- a/src/imports/folderlistmodel/fileinfothread.cpp
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -135,6 +135,7 @@ void FileInfoThread::setSortFlags(QDir::SortFlags flags)
QMutexLocker locker(&mutex);
sortFlags = flags;
sortUpdate = true;
+ needUpdate = true;
condition.wakeAll();
}
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index 7089fed4ad..31cd793737 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -65,6 +65,9 @@ public:
// revision in Qt 5.11: added status property
qmlRegisterType<QQuickFolderListModel,11>(uri, 2, 11, "FolderListModel");
+
+ // revision in Qt 5.12: added sortCaseSensitive property
+ qmlRegisterType<QQuickFolderListModel,12>(uri, 2, 12, "FolderListModel");
}
};
//![class decl]
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 66d9e7ae46..affb1e9fe2 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -51,15 +51,7 @@ class QQuickFolderListModelPrivate
Q_DECLARE_PUBLIC(QQuickFolderListModel)
public:
- QQuickFolderListModelPrivate(QQuickFolderListModel *q)
- : q_ptr(q),
- sortField(QQuickFolderListModel::Name), sortReversed(false), showFiles(true),
- showDirs(true), showDirsFirst(false), showDotAndDotDot(false), showOnlyReadable(false),
- showHidden(false), caseSensitive(true), status(QQuickFolderListModel::Null)
- {
- nameFilters << QLatin1String("*");
- }
-
+ QQuickFolderListModelPrivate(QQuickFolderListModel *q) : q_ptr(q) { }
QQuickFolderListModel *q_ptr;
QUrl currentDir;
@@ -67,17 +59,18 @@ public:
FileInfoThread fileInfoThread;
QList<FileProperty> data;
QHash<int, QByteArray> roleNames;
- QQuickFolderListModel::SortField sortField;
- QStringList nameFilters;
- bool sortReversed;
- bool showFiles;
- bool showDirs;
- bool showDirsFirst;
- bool showDotAndDotDot;
- bool showOnlyReadable;
- bool showHidden;
- bool caseSensitive;
- QQuickFolderListModel::Status status;
+ QQuickFolderListModel::SortField sortField = QQuickFolderListModel::Name;
+ QStringList nameFilters = { QLatin1String("*") };
+ QQuickFolderListModel::Status status = QQuickFolderListModel::Null;
+ bool sortReversed = false;
+ bool showFiles = true;
+ bool showDirs = true;
+ bool showDirsFirst = false;
+ bool showDotAndDotDot = false;
+ bool showOnlyReadable = false;
+ bool showHidden = false;
+ bool caseSensitive = true;
+ bool sortCaseSensitive = true;
~QQuickFolderListModelPrivate() {}
void init();
@@ -132,14 +125,14 @@ void QQuickFolderListModelPrivate::updateSorting()
case QQuickFolderListModel::Type:
flags |= QDir::Type;
break;
- default:
- break;
}
emit q->layoutAboutToBeChanged();
if (sortReversed)
flags |= QDir::Reversed;
+ if (!sortCaseSensitive)
+ flags |= QDir::IgnoreCase;
fileInfoThread.setSortFlags(flags);
}
@@ -856,6 +849,29 @@ QQuickFolderListModel::Status QQuickFolderListModel::status() const
}
/*!
+ \qmlproperty bool FolderListModel::sortCaseSensitive
+ \since 5.12
+
+ If set to true, the sort is case sensitive. This property is true by default.
+*/
+
+bool QQuickFolderListModel::sortCaseSensitive() const
+{
+ Q_D(const QQuickFolderListModel);
+ return d->sortCaseSensitive;
+}
+
+void QQuickFolderListModel::setSortCaseSensitive(bool on)
+{
+ Q_D(QQuickFolderListModel);
+
+ if (on != d->sortCaseSensitive) {
+ d->sortCaseSensitive = on;
+ d->updateSorting();
+ }
+}
+
+/*!
\qmlmethod var FolderListModel::get(int index, string property)
Get the folder property for the given index. The following properties
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index a449f0dd0f..d93e7daf3f 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -76,11 +76,12 @@ class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus
Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION 2)
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION 11)
+ Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION 12)
//![class props]
//![abslistmodel]
public:
- QQuickFolderListModel(QObject *parent = 0);
+ QQuickFolderListModel(QObject *parent = nullptr);
~QQuickFolderListModel();
enum Roles {
@@ -142,6 +143,8 @@ public:
enum Status { Null, Ready, Loading };
Q_ENUM(Status)
Status status() const;
+ bool sortCaseSensitive() const;
+ void setSortCaseSensitive(bool on);
//![prop funcs]
Q_INVOKABLE bool isFolder(int index) const;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index c2ece459c8..b36b1a91ea 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -1176,6 +1176,8 @@ public:
FunctionIterator objectFunctionsEnd(const Object *object) const { return FunctionIterator(data, object, object->nFunctions); }
// ---
+ bool isESModule() const { return data->flags & Unit::IsESModule; }
+ bool isSharedLibrary() const { return data->flags & Unit::IsSharedLibrary; }
QStringList moduleRequests() const;
Heap::Module *instantiate(ExecutionEngine *engine);
const Value *resolveExport(QV4::String *exportName);
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 9e44a4987d..50fdf56048 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -52,6 +52,7 @@
"section": "QML",
"condition": [
"features.commandlineparser",
+ "features.filesystemwatcher",
"features.qml-network && features.localserver",
"features.process",
"features.qml-debug"
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index a844e3cb3e..a7ae664d72 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -550,6 +550,8 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
void Parser::pushToken(int token)
{
+ Q_ASSERT(last_token);
+ Q_ASSERT(last_token < &token_buffer[TOKEN_BUFFER_SIZE]);
last_token->token = yytoken;
last_token->dval = yylval;
last_token->spell = yytokenspell;
@@ -4386,6 +4388,9 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
token_buffer[1].loc = yylloc = location(lexer);
if (t_action(errorState, yytoken)) {
+#ifdef PARSER_DEBUG
+ qDebug() << "Parse error, trying to recover.";
+#endif
QString msg;
int token = token_buffer[0].token;
if (token < 0 || token >= TERMINAL_COUNT)
@@ -4419,18 +4424,13 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
int a = t_action(errorState, *tk);
if (a > 0 && t_action(a, yytoken)) {
+#ifdef PARSER_DEBUG
+ qDebug() << "Parse error, trying to recover (2).";
+#endif
const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
- yytoken = *tk;
- yylval = 0;
- yylloc = token_buffer[0].loc;
- yylloc.length = 0;
-
- first_token = &token_buffer[0];
- last_token = &token_buffer[2];
-
- action = errorState;
+ pushToken(*tk);
goto _Lcheck_token;
}
}
@@ -4445,12 +4445,7 @@ ExportSpecifier: IdentifierName T_AS IdentifierName;
const QString msg = QCoreApplication::translate("QQmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
- yytoken = tk;
- yylval = 0;
- yylloc = token_buffer[0].loc;
- yylloc.length = 0;
-
- action = errorState;
+ pushToken(tk);
goto _Lcheck_token;
}
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 0b0c6242ba..0047b20346 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2905,6 +2905,55 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
addref();
}
+QQmlContextData *QQmlScriptData::qmlContextDataForContext(QQmlContextData *parentQmlContextData)
+{
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
+
+ if (m_precompiledScript->isESModule())
+ return nullptr;
+
+ auto qmlContextData = new QQmlContextData();
+
+ qmlContextData->isInternal = true;
+ qmlContextData->isJSContext = true;
+ if (m_precompiledScript->isSharedLibrary())
+ qmlContextData->isPragmaLibraryContext = true;
+ else
+ qmlContextData->isPragmaLibraryContext = parentQmlContextData->isPragmaLibraryContext;
+ qmlContextData->baseUrl = url;
+ qmlContextData->baseUrlString = urlString;
+
+ // For backward compatibility, if there are no imports, we need to use the
+ // imports from the parent context. See QTBUG-17518.
+ if (!typeNameCache->isEmpty()) {
+ qmlContextData->imports = typeNameCache;
+ } else if (!m_precompiledScript->isSharedLibrary()) {
+ qmlContextData->imports = parentQmlContextData->imports;
+ qmlContextData->importedScripts = parentQmlContextData->importedScripts;
+ }
+
+ if (!m_precompiledScript->isSharedLibrary()) {
+ qmlContextData->setParent(parentQmlContextData);
+ } else {
+ qmlContextData->engine = parentQmlContextData->engine; // Fix for QTBUG-21620
+ }
+
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ QV4::Scope scope(v4);
+ QV4::ScopedObject scriptsArray(scope);
+ if (qmlContextData->importedScripts.isNullOrUndefined()) {
+ scriptsArray = v4->newArrayObject(scripts.count());
+ qmlContextData->importedScripts.set(v4, scriptsArray);
+ } else {
+ scriptsArray = qmlContextData->importedScripts.valueRef();
+ }
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < scripts.count(); ++ii)
+ scriptsArray->put(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(qmlContextData)));
+
+ return qmlContextData;
+}
+
QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentCtxt)
{
if (m_loaded)
@@ -2913,7 +2962,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
Q_ASSERT(parentCtxt && parentCtxt->engine);
QV4::ExecutionEngine *v4 = parentCtxt->engine->handle();
- if (m_precompiledScript->unitData()->flags & QV4::CompiledData::Unit::IsESModule) {
+ if (m_precompiledScript->isESModule()) {
m_loaded = true;
m_value.set(v4, m_precompiledScript->instantiate(v4));
@@ -2926,54 +2975,14 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
QV4::Scope scope(v4);
- bool shared = m_precompiledScript->unitData()->flags & QV4::CompiledData::Unit::IsSharedLibrary;
-
- QQmlContextData *effectiveCtxt = parentCtxt;
- if (shared)
- effectiveCtxt = nullptr;
-
// Create the script context if required
- QQmlContextDataRef ctxt(new QQmlContextData);
- ctxt->isInternal = true;
- ctxt->isJSContext = true;
- if (shared)
- ctxt->isPragmaLibraryContext = true;
- else
- ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
- ctxt->baseUrl = url;
- ctxt->baseUrlString = urlString;
-
- // For backward compatibility, if there are no imports, we need to use the
- // imports from the parent context. See QTBUG-17518.
- if (!typeNameCache->isEmpty()) {
- ctxt->imports = typeNameCache;
- } else if (effectiveCtxt) {
- ctxt->imports = effectiveCtxt->imports;
- ctxt->importedScripts = effectiveCtxt->importedScripts;
- }
-
- if (effectiveCtxt) {
- ctxt->setParent(effectiveCtxt);
- } else {
- ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620
- }
-
- QV4::ScopedObject scriptsArray(scope);
- if (ctxt->importedScripts.isNullOrUndefined()) {
- scriptsArray = v4->newArrayObject(scripts.count());
- ctxt->importedScripts.set(v4, scriptsArray);
- } else {
- scriptsArray = ctxt->importedScripts.valueRef();
- }
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->put(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)));
+ QQmlContextDataRef ctxt(qmlContextDataForContext(parentCtxt));
if (!hasEngine())
initialize(parentCtxt->engine);
if (!m_program) {
- if (shared)
+ if (m_precompiledScript->isSharedLibrary())
m_loaded = true;
return QV4::Encode::undefined();
}
@@ -2990,7 +2999,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
}
QV4::ScopedValue retval(scope, qmlContext->d()->qml());
- if (shared) {
+ if (m_precompiledScript->isSharedLibrary()) {
m_value.set(scope.engine, retval);
m_loaded = true;
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 031554b330..29c91346de 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -552,6 +552,7 @@ private:
friend class QQmlScriptBlob;
void initialize(QQmlEngine *);
+ QQmlContextData *qmlContextDataForContext(QQmlContextData *parentQmlContextData);
bool m_loaded;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_precompiledScript;
diff --git a/src/qml/types/qqmlinstantiator_p.h b/src/qml/types/qqmlinstantiator_p.h
index 5727c4d1e1..ca371adc23 100644
--- a/src/qml/types/qqmlinstantiator_p.h
+++ b/src/qml/types/qqmlinstantiator_p.h
@@ -53,11 +53,12 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlparserstatus.h>
+#include <QtQml/private/qtqmlglobal_p.h>
QT_BEGIN_NAMESPACE
class QQmlInstantiatorPrivate;
-class Q_AUTOTEST_EXPORT QQmlInstantiator : public QObject, public QQmlParserStatus
+class Q_QML_PRIVATE_EXPORT QQmlInstantiator : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
diff --git a/src/qml/types/qqmlinstantiator_p_p.h b/src/qml/types/qqmlinstantiator_p_p.h
index a5a4d1a32d..4c76d5c689 100644
--- a/src/qml/types/qqmlinstantiator_p_p.h
+++ b/src/qml/types/qqmlinstantiator_p_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
-class QQmlInstantiatorPrivate : public QObjectPrivate
+class Q_QML_PRIVATE_EXPORT QQmlInstantiatorPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQmlInstantiator)
@@ -76,6 +76,9 @@ public:
void _q_modelUpdated(const QQmlChangeSet &, bool);
QObject *modelObject(int index, bool async);
+ static QQmlInstantiatorPrivate *get(QQmlInstantiator *instantiator) { return instantiator->d_func(); }
+ static const QQmlInstantiatorPrivate *get(const QQmlInstantiator *instantiator) { return instantiator->d_func(); }
+
bool componentComplete:1;
bool effectiveReset:1;
bool active:1;
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 2b50a0867c..831663fb7b 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -990,7 +990,7 @@ int QQmlAdaptorModel::rowCount() const
int QQmlAdaptorModel::columnCount() const
{
- return qMax(isValid() ? 1 : 0, accessors->columnCount(*this));
+ return qMax(0, accessors->columnCount(*this));
}
int QQmlAdaptorModel::rowAt(int index) const
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index d49829096f..e4e766a129 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -591,10 +591,18 @@ void QQuickBorderImagePrivate::calculateRects(const QQuickScaleGrid *border,
*innerTargetRect = *targetRect;
if (border) {
- *innerSourceRect = QRectF(border->left() * devicePixelRatio / qreal(sourceSize.width()),
- border->top() * devicePixelRatio / qreal(sourceSize.height()),
- qMax<qreal>(0, sourceSize.width() - (border->right() + border->left()) * devicePixelRatio) / sourceSize.width(),
- qMax<qreal>(0, sourceSize.height() - (border->bottom() + border->top()) * devicePixelRatio) / sourceSize.height());
+ qreal borderLeft = border->left() * devicePixelRatio;
+ qreal borderRight = border->right() * devicePixelRatio;
+ qreal borderTop = border->top() * devicePixelRatio;
+ qreal borderBottom = border->bottom() * devicePixelRatio;
+ if (borderLeft + borderRight > sourceSize.width() && borderLeft < sourceSize.width())
+ borderRight = sourceSize.width() - borderLeft;
+ if (borderTop + borderBottom > sourceSize.height() && borderTop < sourceSize.height())
+ borderBottom = sourceSize.height() - borderTop;
+ *innerSourceRect = QRectF(QPointF(borderLeft / qreal(sourceSize.width()),
+ borderTop * devicePixelRatio / qreal(sourceSize.height())),
+ QPointF((sourceSize.width() - borderRight) / qreal(sourceSize.width()),
+ (sourceSize.height() - borderBottom) / qreal(sourceSize.height()))),
*innerTargetRect = QRectF(border->left(),
border->top(),
qMax<qreal>(0, targetSize.width() - (border->right() + border->left())),
@@ -604,14 +612,16 @@ void QQuickBorderImagePrivate::calculateRects(const QQuickScaleGrid *border,
qreal hTiles = 1;
qreal vTiles = 1;
const QSizeF innerTargetSize = innerTargetRect->size() * devicePixelRatio;
- if (innerSourceRect->width() != 0
- && horizontalTileMode != QQuickBorderImage::Stretch) {
+ if (innerSourceRect->width() <= 0)
+ hTiles = 0;
+ else if (horizontalTileMode != QQuickBorderImage::Stretch) {
hTiles = innerTargetSize.width() / qreal(innerSourceRect->width() * sourceSize.width());
if (horizontalTileMode == QQuickBorderImage::Round)
hTiles = qCeil(hTiles);
}
- if (innerSourceRect->height() != 0
- && verticalTileMode != QQuickBorderImage::Stretch) {
+ if (innerSourceRect->height() <= 0)
+ vTiles = 0;
+ else if (verticalTileMode != QQuickBorderImage::Stretch) {
vTiles = innerTargetSize.height() / qreal(innerSourceRect->height() * sourceSize.height());
if (verticalTileMode == QQuickBorderImage::Round)
vTiles = qCeil(vTiles);
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index a1a71bf3cd..8dafc16cf4 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1185,6 +1185,7 @@ void QQuickItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickItemView);
if (reset) {
+ cancelFlick();
if (d->transitioner)
d->transitioner->setPopulateTransitionEnabled(true);
d->moveReason = QQuickItemViewPrivate::SetIndex;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 540805ac28..908801ce1c 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -515,8 +515,8 @@ QString QQuickListViewPrivate::sectionAt(int modelIndex)
qreal QQuickListViewPrivate::snapPosAt(qreal pos)
{
- if (FxViewItem *snapItem = snapItemAt(pos))
- return snapItem->position();
+ if (FxListItemSG *snapItem = static_cast<FxListItemSG*>(snapItemAt(pos)))
+ return snapItem->itemPosition();
if (visibleItems.count()) {
qreal firstPos = (*visibleItems.constBegin())->position();
qreal endPos = (*(--visibleItems.constEnd()))->position();
@@ -530,22 +530,35 @@ qreal QQuickListViewPrivate::snapPosAt(qreal pos)
FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos)
{
+ const qreal velocity = orient == QQuickListView::Vertical ? vData.velocity : hData.velocity;
FxViewItem *snapItem = nullptr;
+ FxViewItem *prevItem = nullptr;
qreal prevItemSize = 0;
for (FxViewItem *item : qAsConst(visibleItems)) {
if (item->index == -1)
continue;
- qreal itemTop = item->position();
- if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size())
+
+ const FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
+ qreal itemTop = listItem->position();
+ qreal itemSize = listItem->size();
+ if (highlight && itemTop >= pos && listItem->endPosition() <= pos + highlight->size())
return item;
+ if (listItem->section() && velocity > 0) {
+ if (itemTop + listItem->sectionSize() / 2 >= pos && itemTop - prevItemSize / 2 < pos)
+ snapItem = prevItem;
+ itemTop = listItem->itemPosition();
+ itemSize = listItem->itemSize();
+ }
+
// Middle of item and spacing (i.e. the middle of the distance between this item and the next
- qreal halfwayToNextItem = itemTop + (item->size()+spacing) / 2;
+ qreal halfwayToNextItem = itemTop + (itemSize+spacing) / 2;
qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2;
if (halfwayToNextItem >= pos && halfwayToPrevItem < pos)
snapItem = item;
- prevItemSize = item->size();
+ prevItemSize = listItem->itemSize();
+ prevItem = item;
}
return snapItem;
}
@@ -1530,15 +1543,15 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
pos = isContentFlowReversed() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
} else {
if (isContentFlowReversed())
- pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart, -maxExtent), -minExtent);
}
} else if (bottomItem && isInBounds) {
if (isContentFlowReversed())
- pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
+ pos = qMax(qMin(static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd, -maxExtent), -minExtent);
} else {
QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
@@ -1568,7 +1581,10 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
timeline.reset(data.move);
if (viewPos != position()) {
if (fixupMode != Immediate) {
- timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
+ if (fixupMode == ExtentChanged && data.fixingUp)
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::OutQuad), fixupDuration/2);
+ else
+ timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
data.fixingUp = true;
} else {
timeline.set(data.move, -viewPos);
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index d7060cbdea..4b13cde2d5 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1664,6 +1664,7 @@ void QQuickTableViewPrivate::connectToModel()
connect(aim, &QAbstractItemModel::columnsInserted, this, &QQuickTableViewPrivate::columnsInsertedCallback);
connect(aim, &QAbstractItemModel::columnsRemoved, this, &QQuickTableViewPrivate::columnsRemovedCallback);
connect(aim, &QAbstractItemModel::modelReset, this, &QQuickTableViewPrivate::modelResetCallback);
+ connect(aim, &QAbstractItemModel::layoutChanged, this, &QQuickTableViewPrivate::layoutChangedCallback);
} else {
QObjectPrivate::connect(model, &QQmlInstanceModel::modelUpdated, this, &QQuickTableViewPrivate::modelUpdated);
}
@@ -1689,6 +1690,7 @@ void QQuickTableViewPrivate::disconnectFromModel()
disconnect(aim, &QAbstractItemModel::columnsInserted, this, &QQuickTableViewPrivate::columnsInsertedCallback);
disconnect(aim, &QAbstractItemModel::columnsRemoved, this, &QQuickTableViewPrivate::columnsRemovedCallback);
disconnect(aim, &QAbstractItemModel::modelReset, this, &QQuickTableViewPrivate::modelResetCallback);
+ disconnect(aim, &QAbstractItemModel::layoutChanged, this, &QQuickTableViewPrivate::layoutChangedCallback);
} else {
QObjectPrivate::disconnect(model, &QQmlInstanceModel::modelUpdated, this, &QQuickTableViewPrivate::modelUpdated);
}
@@ -1751,6 +1753,14 @@ void QQuickTableViewPrivate::columnsRemovedCallback(const QModelIndex &parent, i
scheduleRebuildTable(RebuildOption::ViewportOnly);
}
+void QQuickTableViewPrivate::layoutChangedCallback(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_UNUSED(parents);
+ Q_UNUSED(hint);
+
+ scheduleRebuildTable(RebuildOption::ViewportOnly);
+}
+
void QQuickTableViewPrivate::modelResetCallback()
{
scheduleRebuildTable(RebuildOption::All);
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index a4f829addd..2ed04f8d29 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -356,6 +356,7 @@ public:
void rowsRemovedCallback(const QModelIndex &parent, int begin, int end);
void columnsInsertedCallback(const QModelIndex &parent, int begin, int end);
void columnsRemovedCallback(const QModelIndex &parent, int begin, int end);
+ void layoutChangedCallback(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
void modelResetCallback();
void _q_componentFinalized();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 059886f41c..d27ee54c89 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -774,6 +774,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve
void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids)
{
+ QQuickPointerEvent *ev = nullptr;
for (int i = 0; i < ids.count(); ++i) {
int id = ids.at(i);
if (Q_UNLIKELY(id < 0)) {
@@ -793,15 +794,26 @@ void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &
qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: mouse grabber changed due to grabTouchPoints:" << touchMouseGrabber << "-> null";
}
+ // optimization to avoid the loop over devices below:
+ // all ids are probably from the same event, so we don't have to search
+ if (ev) {
+ auto point = ev->pointById(id);
+ if (point && point->exclusiveGrabber() != grabber) {
+ point->setExclusiveGrabber(grabber);
+ continue; // next id in the ids loop
+ }
+ }
+ // search all devices for a QQuickPointerEvent instance that is delivering the point with id
const auto touchDevices = QQuickPointerDevice::touchDevices();
for (auto device : touchDevices) {
- auto point = pointerEventInstance(device)->pointById(id);
- if (!point)
- continue;
- QObject *oldGrabber = point->exclusiveGrabber();
- if (oldGrabber == grabber)
- continue;
- point->setExclusiveGrabber(grabber);
+ QQuickPointerEvent *pev = pointerEventInstance(device);
+ auto point = pev->pointById(id);
+ if (point) {
+ ev = pev;
+ if (point->exclusiveGrabber() != grabber)
+ point->setExclusiveGrabber(grabber);
+ break; // out of touchDevices loop
+ }
}
}
}
diff --git a/src/quick/scenegraph/qsgbasicinternalimagenode.cpp b/src/quick/scenegraph/qsgbasicinternalimagenode.cpp
index c8699218ba..53271af9ab 100644
--- a/src/quick/scenegraph/qsgbasicinternalimagenode.cpp
+++ b/src/quick/scenegraph/qsgbasicinternalimagenode.cpp
@@ -484,7 +484,7 @@ void QSGBasicInternalImageNode::updateGeometry()
int hTiles = ceilRight - floorLeft;
int vTiles = ceilBottom - floorTop;
- bool hasTiles = hTiles != 1 || vTiles != 1;
+ bool hasTiles = hTiles > 1 || vTiles > 1;
bool fullTexture = innerSourceRect == QRectF(0, 0, 1, 1);
// An image can be rendered as a single quad if:
diff --git a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp
index 56508af152..94912778f8 100644
--- a/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp
+++ b/src/quick/scenegraph/util/qsgdepthstencilbuffer.cpp
@@ -57,20 +57,34 @@ QSGDepthStencilBuffer::~QSGDepthStencilBuffer()
m_manager->m_buffers.remove(m_format);
}
+#ifndef GL_DEPTH_STENCIL_ATTACHMENT
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#endif
+
void QSGDepthStencilBuffer::attach()
{
+#ifndef Q_OS_WASM
m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, m_depthBuffer);
m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, m_stencilBuffer);
+#else
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, m_stencilBuffer);
+#endif
}
void QSGDepthStencilBuffer::detach()
{
+#ifndef Q_OS_WASM
m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, 0);
m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, 0);
+#else
+ m_functions.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, 0);
+#endif
}
#ifndef GL_DEPTH24_STENCIL8_OES
@@ -81,12 +95,17 @@ void QSGDepthStencilBuffer::detach()
#define GL_DEPTH_COMPONENT24_OES 0x81A6
#endif
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+
QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *context, const Format &format)
: QSGDepthStencilBuffer(context, format)
{
const GLsizei width = format.size.width();
const GLsizei height = format.size.height();
+#ifndef Q_OS_WASM
if (format.attachments == (DepthAttachment | StencilAttachment)
&& m_functions.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
{
@@ -138,6 +157,12 @@ QSGDefaultDepthStencilBuffer::QSGDefaultDepthStencilBuffer(QOpenGLContext *conte
m_functions.glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
}
}
+#else
+ m_functions.glGenRenderbuffers(1, &m_depthBuffer);
+ m_functions.glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
+ m_functions.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+ m_stencilBuffer = m_depthBuffer;
+#endif
}
QSGDefaultDepthStencilBuffer::~QSGDefaultDepthStencilBuffer()
diff --git a/tests/auto/qml/qquickfolderlistmodel/data/sortdir/Uppercase.txt b/tests/auto/qml/qquickfolderlistmodel/data/sortdir/Uppercase.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/qquickfolderlistmodel/data/sortdir/Uppercase.txt
diff --git a/tests/auto/qml/qquickfolderlistmodel/data/sortdir/lowercase.txt b/tests/auto/qml/qquickfolderlistmodel/data/sortdir/lowercase.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/qquickfolderlistmodel/data/sortdir/lowercase.txt
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 77fda3b555..4b2ae45bae 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -73,7 +73,8 @@ private slots:
void showDotAndDotDot_data();
void sortReversed();
void introspectQrc();
-
+ void sortCaseSensitive_data();
+ void sortCaseSensitive();
private:
void checkNoErrors(const QQmlComponent& component);
QQmlEngine engine;
@@ -126,7 +127,7 @@ void tst_qquickfolderlistmodel::basicProperties()
QSignalSpy folderChangedSpy(flm, SIGNAL(folderChanged()));
flm->setProperty("folder", dataDirectoryUrl());
QVERIFY(folderChangedSpy.wait());
- QCOMPARE(flm->property("count").toInt(), 8);
+ QCOMPARE(flm->property("count").toInt(), 9);
QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl());
QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath()));
QCOMPARE(flm->property("sortField").toInt(), int(Name));
@@ -166,12 +167,12 @@ void tst_qquickfolderlistmodel::showFiles()
QVERIFY(flm != nullptr);
flm->setProperty("folder", dataDirectoryUrl());
- QTRY_COMPARE(flm->property("count").toInt(), 8); // wait for refresh
+ QTRY_COMPARE(flm->property("count").toInt(), 9); // wait for refresh
QCOMPARE(flm->property("showFiles").toBool(), true);
flm->setProperty("showFiles", false);
QCOMPARE(flm->property("showFiles").toBool(), false);
- QTRY_COMPARE(flm->property("count").toInt(), 2); // wait for refresh
+ QTRY_COMPARE(flm->property("count").toInt(), 3); // wait for refresh
}
void tst_qquickfolderlistmodel::resetFiltering()
@@ -238,7 +239,7 @@ void tst_qquickfolderlistmodel::refresh()
QVERIFY(flm != nullptr);
flm->setProperty("folder", dataDirectoryUrl());
- QTRY_COMPARE(flm->property("count").toInt(),8); // wait for refresh
+ QTRY_COMPARE(flm->property("count").toInt(), 9); // wait for refresh
int count = flm->rowCount();
@@ -342,7 +343,7 @@ void tst_qquickfolderlistmodel::showDotAndDotDot()
flm->setProperty("rootFolder", rootFolder);
flm->setProperty("showDotAndDotDot", showDotAndDotDot);
- int count = 9;
+ int count = 10;
if (showDot) count++;
if (showDotDot) count++;
QTRY_COMPARE(flm->property("count").toInt(), count); // wait for refresh
@@ -373,7 +374,7 @@ void tst_qquickfolderlistmodel::sortReversed()
QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
QVERIFY(flm != nullptr);
flm->setProperty("folder", dataDirectoryUrl());
- QTRY_COMPARE(flm->property("count").toInt(), 9); // wait for refresh
+ QTRY_COMPARE(flm->property("count").toInt(), 10); // wait for refresh
QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("txtdir"));
}
@@ -387,6 +388,36 @@ void tst_qquickfolderlistmodel::introspectQrc()
QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("hello.txt"));
}
+void tst_qquickfolderlistmodel::sortCaseSensitive_data()
+{
+ QTest::addColumn<bool>("sortCaseSensitive");
+ QTest::addColumn<QStringList>("expectedOrder");
+
+ const QString upperFile = QLatin1String("Uppercase.txt");
+ const QString lowerFile = QLatin1String("lowercase.txt");
+
+ QTest::newRow("caseSensitive") << true << (QStringList() << upperFile << lowerFile);
+ QTest::newRow("caseInsensitive") << false << (QStringList() << lowerFile << upperFile);
+}
+
+void tst_qquickfolderlistmodel::sortCaseSensitive()
+{
+ QFETCH(bool, sortCaseSensitive);
+ QFETCH(QStringList, expectedOrder);
+ QQmlComponent component(&engine);
+ component.setData("import Qt.labs.folderlistmodel 1.0\n"
+ "FolderListModel { }", QUrl());
+ checkNoErrors(component);
+
+ QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
+ QVERIFY(flm != 0);
+ flm->setProperty("folder", QUrl::fromLocalFile(dataDirectoryUrl().path() + QLatin1String("/sortdir")));
+ flm->setProperty("sortCaseSensitive", sortCaseSensitive);
+ QTRY_COMPARE(flm->property("count").toInt(), 2); // wait for refresh
+ for (int i = 0; i < 2; ++i)
+ QTRY_COMPARE(flm->data(flm->index(i),FileNameRole).toString(), expectedOrder.at(i));
+}
+
QTEST_MAIN(tst_qquickfolderlistmodel)
#include "tst_qquickfolderlistmodel.moc"
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index f8e76fdf5c..da7b610978 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -114,6 +114,7 @@ void tst_v4misc::parserMisc_data()
QTest::newRow("for (var f in ++!binaryMathg) ;") << QString("ReferenceError: Prefix ++ operator applied to value that is not a reference.");
QTest::newRow("for (va() in obj) {}") << QString("ReferenceError: Invalid left-hand side expression for 'in' expression");
QTest::newRow("[1]=7[A=8=9]") << QString("ReferenceError: left-hand side of assignment operator is not an lvalue");
+ QTest::newRow("var asmvalsLen = asmvals{{{{{ngth}}}}};") << QString("SyntaxError: Expected token `;'");
}
void tst_v4misc::parserMisc()
diff --git a/tests/auto/quick/qquicklistview/data/sectionSnapping.qml b/tests/auto/quick/qquicklistview/data/sectionSnapping.qml
new file mode 100644
index 0000000000..2583cc0377
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/sectionSnapping.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.0
+
+ListView {
+ width: 400
+ height: 400
+ preferredHighlightBegin: 100
+ preferredHighlightEnd: 100
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ model: ListModel {
+ ListElement { section: "1" }
+ ListElement { section: "1" }
+ ListElement { section: "1" }
+ ListElement { section: "2" }
+ ListElement { section: "2" }
+ ListElement { section: "2" }
+ }
+
+ delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: index % 2 ? "lightsteelblue" : "steelblue"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: model.index
+ }
+ }
+
+ section.property: "section"
+ section.delegate: Rectangle {
+ width: parent.width
+ height: 50
+ color: "green"
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ text: "section"
+ }
+ }
+
+ highlight: Rectangle {
+ y: 100
+ z: 100
+ width: parent.width
+ height: 50
+ color: "#80FF0000"
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 2574eb9c6c..ae02352293 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -132,6 +132,8 @@ private slots:
void sectionPropertyChange();
void sectionDelegateChange();
void sectionsItemInsertion();
+ void sectionsSnap_data();
+ void sectionsSnap();
void cacheBuffer();
void positionViewAtBeginningEnd();
void positionViewAtIndex();
@@ -2667,6 +2669,62 @@ void tst_QQuickListView::sectionsItemInsertion()
}
}
+void tst_QQuickListView::sectionsSnap_data()
+{
+ QTest::addColumn<QQuickListView::SnapMode>("snapMode");
+ QTest::addColumn<QPoint>("point");
+ QTest::addColumn<int>("duration");
+
+ QTest::newRow("drag") << QQuickListView::NoSnap << QPoint(100, 45) << 500;
+ QTest::newRow("flick") << QQuickListView::SnapOneItem << QPoint(100, 75) << 50;
+}
+
+void tst_QQuickListView::sectionsSnap()
+{
+ QFETCH(QQuickListView::SnapMode, snapMode);
+ QFETCH(QPoint, point);
+ QFETCH(int, duration);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("sectionSnapping.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != nullptr);
+ listview->setSnapMode(snapMode);
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QCOMPARE(listview->contentY(), qreal(-50));
+
+ // move down
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(0));
+
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(50));
+
+ flick(window.data(), QPoint(100, 100), point, duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(150));
+
+ // move back up
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(50));
+
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(0));
+
+ flick(window.data(), point, QPoint(100, 100), duration);
+ QTRY_VERIFY(!listview->isMovingVertically());
+ QCOMPARE(listview->contentY(), qreal(-50));
+}
+
void tst_QQuickListView::currentIndex_delayedItemCreation()
{
QFETCH(bool, setCurrentToZero);
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
index 28ea466b82..50f434019e 100644
--- a/tests/auto/quick/qquicktableview/testmodel.h
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -68,14 +68,13 @@ public:
return { {Qt::DisplayRole, "display"} };
}
- Q_INVOKABLE void setModelData(const QPoint &cell, const QSize &span, const QString &prefix)
+ Q_INVOKABLE void setModelData(const QPoint &cell, const QSize &span, const QString &string)
{
for (int c = 0; c < span.width(); ++c) {
for (int r = 0; r < span.height(); ++r) {
const int changedRow = cell.y() + r;
const int changedColumn = cell.x() + c;
const int serializedIndex = changedRow + (changedColumn * m_rows);
- const QString string = prefix + QStringLiteral("%1,%2").arg(changedColumn).arg(changedRow);
modelData.insert(serializedIndex, string);
}
}
@@ -129,10 +128,22 @@ public:
return true;
}
+ void swapRows(int row1, int row2)
+ {
+ layoutAboutToBeChanged();
+ Q_ASSERT(modelData.contains(row1));
+ Q_ASSERT(modelData.contains(row2));
+ const QString tmp = modelData[row1];
+ modelData[row1] = modelData[row2];
+ modelData[row2] = tmp;
+ layoutChanged();
+ }
+
void clear() {
beginResetModel();
m_rows = 0;
m_columns = 0;
+ modelData.clear();
endResetModel();
}
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 60b938d127..d475ef9c4d 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -141,6 +141,7 @@ private slots:
void flickOvershoot();
void checkRowColumnCount();
void modelSignals();
+ void checkModelSignalsUpdateLayout();
void dataChangedSignal();
void checkThatPoolIsDrainedWhenReuseIsFalse();
void checkIfDelegatesAreReused_data();
@@ -1466,9 +1467,48 @@ void tst_QQuickTableView::modelSignals()
QCOMPARE(tableView->columns(), 10);
model.clear();
+ model.setColumnCount(1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->columns(), 1);
+}
+
+void tst_QQuickTableView::checkModelSignalsUpdateLayout()
+{
+ // Check that if the model rearranges rows and emit the
+ // 'layoutChanged' signal, TableView will be updated correctly.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ TestModel model(0, 1);
+ tableView->setModel(QVariant::fromValue(&model));
WAIT_UNTIL_POLISHED;
+
QCOMPARE(tableView->rows(), 0);
QCOMPARE(tableView->columns(), 1);
+
+ QString modelRow1Text = QStringLiteral("firstRow");
+ QString modelRow2Text = QStringLiteral("secondRow");
+ model.insertRow(0);
+ model.insertRow(0);
+ model.setModelData(QPoint(0, 0), QSize(1, 1), modelRow1Text);
+ model.setModelData(QPoint(0, 1), QSize(1, 1), modelRow2Text);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), 2);
+ QCOMPARE(tableView->columns(), 1);
+
+ QString delegate1text = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item->property("modelDataBinding").toString();
+ QString delegate2text = tableViewPrivate->loadedTableItem(QPoint(0, 1))->item->property("modelDataBinding").toString();
+ QCOMPARE(delegate1text, modelRow1Text);
+ QCOMPARE(delegate2text, modelRow2Text);
+
+ model.swapRows(0, 1);
+ WAIT_UNTIL_POLISHED;
+
+ delegate1text = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item->property("modelDataBinding").toString();
+ delegate2text = tableViewPrivate->loadedTableItem(QPoint(0, 1))->item->property("modelDataBinding").toString();
+ QCOMPARE(delegate1text, modelRow2Text);
+ QCOMPARE(delegate2text, modelRow1Text);
}
void tst_QQuickTableView::dataChangedSignal()