From c0e16b469f1bce8fc96d751656a43d7396ce4276 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Jan 2019 17:57:46 +0100 Subject: Fix build error when building with -no-feature-translation Change-Id: Ie97ae901283cf431fc38d238ddbc88a18bd630c8 Fixes: QTBUG-72352 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4compileddata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index e68a563a45..d205d8be8b 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -754,7 +754,7 @@ QString Binding::valueAsString(const CompilationUnit *unit) const #if !QT_CONFIG(translation) case Type_TranslationById: case Type_Translation: - return unit->stringAt(unit->unitData->translations()[value.translationDataIndex].stringIndex); + return unit->stringAt(unit->unitData()->translations()[value.translationDataIndex].stringIndex); #else case Type_TranslationById: { const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex]; -- cgit v1.2.3 From 0924e03e245c1d628bc7f864d6b194b137116b6e Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Mon, 14 Jan 2019 09:13:30 +0200 Subject: Bump version Change-Id: Ibc48d8afabaf0ec83a61cf1c51f27d737b01379e --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 34660b3c4d..b0541fe720 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,4 +1,4 @@ load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.12.1 +MODULE_VERSION = 5.12.2 -- cgit v1.2.3 From cfdb483613494d982a574c9334f2b21621024b1b Mon Sep 17 00:00:00 2001 From: Nils Jeisecke Date: Mon, 14 Jan 2019 10:44:34 +0100 Subject: Fix crash with qt.qml.binding.removal.info=true For some bindings (qsTr) no actual javascript function exists and the debug output causes a null pointer access. Fixes: QTBUG-73009 Change-Id: I896fd2afd680dc5dee544a0c46ade6746f6727d8 Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlbinding.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index e38f379eb0..eea3670191 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -517,11 +517,14 @@ QVariant QQmlBinding::evaluate() QString QQmlBinding::expressionIdentifier() const { - auto f = function(); - QString url = f->sourceFile(); - quint16 lineNumber = f->compiledFunction->location.line; - quint16 columnNumber = f->compiledFunction->location.column; - return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber)); + if (auto f = function()) { + QString url = f->sourceFile(); + quint16 lineNumber = f->compiledFunction->location.line; + quint16 columnNumber = f->compiledFunction->location.column; + return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber)); + } + + return QStringLiteral("[native code]"); } void QQmlBinding::expressionChanged() -- cgit v1.2.3 From 4aa7fe666be35b5699b0e201c3a963777f874e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 14 Jan 2019 12:20:33 +0100 Subject: tst_qquickapplication: Don't assume app activation is tied to window activation Follows same approach as 47f6d256ed in tst_qquickapplication::state(). Change-Id: Ibecdab3f874fc9e75b38ba2ccaf3776bd46c77e8 Fixes: QTBUG-72953 Reviewed-by: Liang Qi Reviewed-by: Richard Moe Gustavsen --- .../qquickapplication/tst_qquickapplication.cpp | 56 ++++++++++++---------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index 62027f59f4..3526eb98be 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -88,31 +88,37 @@ void tst_qquickapplication::active() QQuickWindow window; item->setParentItem(window.contentItem()); - // not active - QVERIFY(!item->property("active").toBool()); - QVERIFY(!item->property("active2").toBool()); - - // active - window.show(); - window.requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(&window)); - QCOMPARE(QGuiApplication::focusWindow(), &window); - QVERIFY(item->property("active").toBool()); - QVERIFY(item->property("active2").toBool()); - - QWindowSystemInterface::handleWindowActivated(nullptr); - -#ifdef Q_OS_OSX - // OS X has the concept of "reactivation" - QTRY_VERIFY(QGuiApplication::focusWindow() != &window); - QVERIFY(item->property("active").toBool()); - QVERIFY(item->property("active2").toBool()); -#else - // not active again - QTRY_VERIFY(QGuiApplication::focusWindow() != &window); - QVERIFY(!item->property("active").toBool()); - QVERIFY(!item->property("active2").toBool()); -#endif + // If the platform plugin has the ApplicationState capability, app activation originate from it + // as a result of a system event. We therefore have to simulate these events here. + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) { + + // Flush pending events, in case the platform have already queued real application state events + QWindowSystemInterface::flushWindowSystemEvents(); + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + QWindowSystemInterface::flushWindowSystemEvents(); + QVERIFY(item->property("active").toBool()); + QVERIFY(item->property("active2").toBool()); + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + QWindowSystemInterface::flushWindowSystemEvents(); + QVERIFY(!item->property("active").toBool()); + QVERIFY(!item->property("active2").toBool()); + } else { + // Otherwise, app activation is triggered by window activation. + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QCOMPARE(QGuiApplication::focusWindow(), &window); + QVERIFY(item->property("active").toBool()); + QVERIFY(item->property("active2").toBool()); + + // not active again + QWindowSystemInterface::handleWindowActivated(nullptr); + QTRY_VERIFY(QGuiApplication::focusWindow() != &window); + QVERIFY(!item->property("active").toBool()); + QVERIFY(!item->property("active2").toBool()); + } } void tst_qquickapplication::state() -- cgit v1.2.3 From f0a9c1efe36b952dfe3e802f3ceeee6ed10a65f5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 14 Jan 2019 11:37:39 +0100 Subject: Stabilize tst_QQuickPathView::package() Add QQUICK_VERIFY_POLISH. Fixes: QTBUG-73007 Change-Id: I08d90058770ef496469b917892104c751b5cf9c1 Reviewed-by: Mitch Curtis --- tests/auto/quick/qquickpathview/tst_qquickpathview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index aceb61bde4..6267a3771e 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -1371,6 +1371,7 @@ void tst_QQuickPathView::package() QSKIP("QTBUG-27170 view does not reliably receive polish without a running animation"); #endif + QQUICK_VERIFY_POLISH(pathView); QQuickItem *item = findItem(pathView, "pathItem"); QVERIFY(item); QVERIFY(item->scale() != 1.0); -- cgit v1.2.3 From aca0351c7ce933503b042fd8d745d220c7dd331d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 14 Jan 2019 14:20:57 +0100 Subject: QQmlMetaType: Erase attached properties in dtor Also, make it more obvious that the attachedPropertyIds are a static member of QQmlTypePrivate. Fixes: QTBUG-72972 Change-Id: If0a28e034dd46d7127993ed15aed11c7641d580e Reviewed-by: Harald Hvaal Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlmetatype.cpp | 16 +++++++--- tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp | 39 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 11806a89a0..708859be00 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -497,9 +497,9 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction; d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject; if (d->extraData.cd->attachedPropertiesType) { - QHash::Iterator iter = d->attachedPropertyIds.find(d->baseMetaObject); - if (iter == d->attachedPropertyIds.end()) - iter = d->attachedPropertyIds.insert(d->baseMetaObject, d->index); + auto iter = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject); + if (iter == QQmlTypePrivate::attachedPropertyIds.end()) + iter = QQmlTypePrivate::attachedPropertyIds.insert(d->baseMetaObject, d->index); d->extraData.cd->attachedPropertiesId = *iter; } else { d->extraData.cd->attachedPropertiesId = -1; @@ -569,8 +569,16 @@ QQmlType::QQmlType(QQmlTypePrivate *priv) QQmlType::~QQmlType() { - if (d && !d->refCount.deref()) + if (d && !d->refCount.deref()) { + // If attached properties were successfully registered, deregister them. + // (They may not have been registered if some other type used the same baseMetaObject) + if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) { + auto it = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject); + if (it != QQmlTypePrivate::attachedPropertyIds.end() && *it == d->index) + QQmlTypePrivate::attachedPropertyIds.erase(it); + } delete d; + } } QHashedString QQmlType::module() const diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index e83dac48fb..7139a1c952 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include "../../shared/util.h" @@ -64,6 +65,7 @@ private slots: void unregisterCustomSingletonType(); void normalizeUrls(); + void unregisterAttachedProperties(); }; class TestType : public QObject @@ -533,6 +535,43 @@ void tst_qqmlmetatype::normalizeUrls() QVERIFY(!QQmlMetaType::qmlType(url, /*includeNonFileImports=*/true).isValid()); } +void tst_qqmlmetatype::unregisterAttachedProperties() +{ + qmlClearTypeRegistrations(); + + const QUrl dummy("qrc:///doesnotexist.qml"); + { + QQmlEngine e; + QQmlComponent c(&e); + c.setData("import QtQuick 2.2\n Item { }", dummy); + + const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2); + QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)), + attachedType.index()); + + QVERIFY(c.create()); + } + + qmlClearTypeRegistrations(); + { + QQmlEngine e; + QQmlComponent c(&e); + + // The extra import shuffles the type IDs around, so that we + // get a different ID for the attached properties. If the attached + // properties aren't properly cleared, this will crash. + c.setData("import QtQml.StateMachine 1.0 \n" + "import QtQuick 2.2 \n" + "Item { KeyNavigation.up: null }", dummy); + + const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2); + QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)), + attachedType.index()); + + QVERIFY(c.create()); + } +} + QTEST_MAIN(tst_qqmlmetatype) #include "tst_qqmlmetatype.moc" -- cgit v1.2.3 From 8396dc86f28e89a920d85f59518fac79da8480eb Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 10 Aug 2018 12:00:45 +0200 Subject: StorageModel manual test: use DelegateChoices to show data graphically This demonstrates that DelegateChooser and DelegateChoice are working with TableView. In this use case, DelegateChooser uses a role from the model to decide which delegate type to instantiate. So we need the model to provide a type role that it can switch on. Conveniently, by using the Q_ENUM registration of the Type enum, it automatically becomes possible to match against the stringified versions of those enum values in the DelegateChoice.roleValue property. To demonstrate a set of roles which would work for almost any kind of numeric data, we choose to have a Value role for the current value, corresponding to the width of the bar or the numerator of the ratio; and ValueMax for the maximum possible value, corresponding to the total width of the bar graph, or the denominator of the ratio. ValueDisplay and ValueMaxDisplay are roles which provide string-formatted versions of those for labeling purposes. Maybe in the future we could consider adding those (plus ValueMin and ValueMinDisplay) to the ItemDataRole enum; because almost any kind of data model could need to provide numeric data, but for some reason we have only made it easy to provide strings (DisplayRole) and booleans (CheckStateRole). Likewise some sort of type role could be standardized at the same time. Free / used space is graphically shown as a bar graph. QStorageInfo provides bytesFree() but not bytesUsed(), but it's more conventional to show a bar which grows wider as more space is used, so we reverse it visually by showing a red background with the bytesFree bar anchored to the right. Thus the width of the red part showing through is proportional to bytes used. The three flags isReady, isReadOnly and isValid are shown with simulated checkboxes. This manual test is now on its way to becoming an example of how to use row, column and role effectively together. It's not enough to say that TableView is only for spreadsheet-like views, displaying only text in each cell. To display more than text, we can do the same thing that we have done in the past with models designed for display with ListView: use the role, so that data(index, role) gets called multiple times for each cell, to get the values that each delegate type needs to use to render itself. Change-Id: I1060eacc2b7d25f420411828258e7d94ee0bdd0b Reviewed-by: Richard Moe Gustavsen --- tests/manual/tableview/storagemodel/main.qml | 74 +++++++++++++++---- .../manual/tableview/storagemodel/storagemodel.cpp | 82 ++++++++++++++++++---- tests/manual/tableview/storagemodel/storagemodel.h | 25 ++++++- 3 files changed, 149 insertions(+), 32 deletions(-) diff --git a/tests/manual/tableview/storagemodel/main.qml b/tests/manual/tableview/storagemodel/main.qml index 2603fba0e2..725d7da7b0 100644 --- a/tests/manual/tableview/storagemodel/main.qml +++ b/tests/manual/tableview/storagemodel/main.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -38,13 +38,14 @@ ****************************************************************************/ import QtQuick 2.12 -import QtQuick.Window 2.3 +import QtQuick.Window 2.12 +import Qt.labs.qmlmodels 1.0 import StorageModel 0.1 Window { id: window - width: 640 - height: 480 + width: 480 + height: 300 visible: true color: "darkgray" title: "Storage Volumes" @@ -57,17 +58,62 @@ Window { model: StorageModel { } columnSpacing: 1 rowSpacing: 1 - delegate: Rectangle { - id: tableDelegate - implicitWidth: displayText.implicitWidth + 8 - implicitHeight: displayText.implicitHeight + 14 + delegate: DelegateChooser { + role: "type" + DelegateChoice { + roleValue: "Value" + delegate: Rectangle { + color: "tomato" + implicitWidth: Math.max(100, label.implicitWidth + 8) + implicitHeight: label.implicitHeight + 4 - Text { - id: displayText - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.leftMargin: 4 - text: display + Rectangle { + x: parent.width - width + width: value * parent.width / valueMax + height: parent.height + color: "white" + } + + Text { + id: label + anchors.baseline: parent.bottom + anchors.baselineOffset: -4 + anchors.left: parent.left + anchors.leftMargin: 4 + text: valueDisplay + " of " + valueMaxDisplay + " " + heading + } + } + } + DelegateChoice { + roleValue: "Flag" + // We could use a checkbox here but that would be another component (e.g. from Controls) + delegate: Rectangle { + implicitWidth: checkBox.implicitWidth + 8 + implicitHeight: checkBox.implicitHeight + 4 + Text { + id: checkBox + anchors.baseline: parent.bottom + anchors.baselineOffset: -4 + anchors.left: parent.left + anchors.leftMargin: 4 + text: (checkState ? "☑ " : "☐ ") + heading + } + } + } + DelegateChoice { + // roleValue: "String" // default delegate + delegate: Rectangle { + implicitWidth: stringLabel.implicitWidth + 8 + implicitHeight: stringLabel.implicitHeight + 4 + Text { + id: stringLabel + anchors.baseline: parent.bottom + anchors.baselineOffset: -4 + anchors.left: parent.left + anchors.leftMargin: 4 + text: display + } + } } } } diff --git a/tests/manual/tableview/storagemodel/storagemodel.cpp b/tests/manual/tableview/storagemodel/storagemodel.cpp index b6b861a1a8..b43454b249 100644 --- a/tests/manual/tableview/storagemodel/storagemodel.cpp +++ b/tests/manual/tableview/storagemodel/storagemodel.cpp @@ -63,6 +63,20 @@ StorageModel::StorageModel(QObject *parent) : refresh(); } +QHash StorageModel::roleNames() const { + static auto roles = QHash { + { int(Role::Type), "type" }, + { int(Role::Heading), "heading" }, + { int(Role::Value), "value" }, + { int(Role::ValueMax), "valueMax" }, + { int(Role::ValueDisplay), "valueDisplay" }, + { int(Role::ValueMaxDisplay), "valueMaxDisplay" }, + { Qt::CheckStateRole, "checkState" }, + }; + static auto ret = roles.unite(QAbstractTableModel::roleNames());; + return ret; +} + void StorageModel::refresh() { beginResetModel(); @@ -92,7 +106,6 @@ Qt::ItemFlags StorageModel::flags(const QModelIndex &index) const { Qt::ItemFlags result = QAbstractTableModel::flags(index); switch (Column(index.column())) { - case Column::Available: case Column::IsReady: case Column::IsReadOnly: case Column::IsValid: @@ -109,7 +122,9 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const if (!index.isValid()) return QVariant(); - if (role == Qt::DisplayRole) { + switch (role) { + case Qt::DisplayRole: + case int(Role::ValueDisplay): { const QStorageInfo &volume = m_volumes.at(index.row()); switch (Column(index.column())) { case Column::RootPath: @@ -120,12 +135,8 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const return volume.device(); case Column::FileSystemName: return volume.fileSystemType(); - case Column::Total: - return QLocale().formattedDataSize(volume.bytesTotal()); case Column::Free: return QLocale().formattedDataSize(volume.bytesFree()); - case Column::Available: - return QLocale().formattedDataSize(volume.bytesAvailable()); case Column::IsReady: return volume.isReady(); case Column::IsReadOnly: @@ -135,7 +146,8 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const default: break; } - } else if (role == Qt::CheckStateRole) { + } break; + case Qt::CheckStateRole: { const QStorageInfo &volume = m_volumes.at(index.row()); switch (Column(index.column())) { case Column::IsReady: @@ -147,17 +159,16 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const default: break; } - } else if (role == Qt::TextAlignmentRole) { + } break; + case Qt::TextAlignmentRole: switch (Column(index.column())) { - case Column::Total: case Column::Free: - case Column::Available: return Qt::AlignTrailing; default: break; } return Qt::AlignLeading; - } else if (role == Qt::ToolTipRole) { + case Qt::ToolTipRole: { QLocale locale; const QStorageInfo &volume = m_volumes.at(index.row()); return tr("Root path : %1\n" @@ -186,6 +197,51 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const arg(volume.isValid() ? tr("true") : tr("false")). arg(volume.isRoot() ? tr("true") : tr("false")); } + case int(Role::Type): + switch (Column(index.column())) { + case Column::RootPath: + case Column::Name: + case Column::Device: + case Column::FileSystemName: + return QVariant::fromValue(Type::String); + break; + case Column::Free: + return QVariant::fromValue(Type::Value); + case Column::IsReady: + case Column::IsReadOnly: + case Column::IsValid: + return QVariant::fromValue(Type::Flag); + default: + break; + } + break; + case int(Role::Heading): + return headerData(index.column()); + case int(Role::Value): + switch (Column(index.column())) { + case Column::Free: + return m_volumes.at(index.row()).bytesFree(); + default: + break; + } + break; + case int(Role::ValueMax): + switch (Column(index.column())) { + case Column::Free: + return m_volumes.at(index.row()).bytesTotal(); + default: + break; + } + break; + case int(Role::ValueMaxDisplay): + switch (Column(index.column())) { + case Column::Free: + return QLocale().formattedDataSize(m_volumes.at(index.row()).bytesTotal()); + default: + break; + } + break; + } // switch (role) return QVariant(); } @@ -206,12 +262,8 @@ QVariant StorageModel::headerData(int section, Qt::Orientation orientation, int return tr("Device"); case Column::FileSystemName: return tr("File System"); - case Column::Total: - return tr("Total"); case Column::Free: return tr("Free"); - case Column::Available: - return tr("Available"); case Column::IsReady: return tr("Ready"); case Column::IsReadOnly: diff --git a/tests/manual/tableview/storagemodel/storagemodel.h b/tests/manual/tableview/storagemodel/storagemodel.h index 1f6f6f8b1f..6cbab3d850 100644 --- a/tests/manual/tableview/storagemodel/storagemodel.h +++ b/tests/manual/tableview/storagemodel/storagemodel.h @@ -65,23 +65,42 @@ public: Name, Device, FileSystemName, - Total, Free, - Available, IsReady, IsReadOnly, IsValid, Count }; + Q_ENUM(Column) + + enum class Role : int { + Type = Qt::UserRole + 1, + Heading, + Value, + ValueMax, // If we had ValueMin, it would always be zero in this example + ValueDisplay, + ValueMaxDisplay, + Count + }; + Q_ENUM(Role) + + enum class Type : int { + String, // use Qt::DisplayRole + Value, // use Role::Value and Role::ValueMax + Flag, // use Qt::CheckStateRole + Count + }; + Q_ENUM(Type) explicit StorageModel(QObject *parent = nullptr); int columnCount(const QModelIndex &parent) const override; int rowCount(const QModelIndex &parent) const override; + QHash roleNames() const override; QVariant data(const QModelIndex &index, int role) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation = Qt::Horizontal, int role = Qt::DisplayRole) const override; public slots: void refresh(); -- cgit v1.2.3 From 8fd3cfe7d0f39a731c585334299f5160ad952df9 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 14 Jan 2019 14:21:21 +0100 Subject: Annotate stack traces when frames are elided through tail calls Task-number: QTBUG-72407 Change-Id: I98b96852309fc783a945797185f666196513d24b Reviewed-by: Ulf Hermann --- src/qml/jsruntime/qv4engine.cpp | 5 +++++ src/qml/jsruntime/qv4functionobject.cpp | 1 + src/qml/jsruntime/qv4stackframe_p.h | 2 ++ tests/auto/qml/qjsengine/tst_qjsengine.cpp | 16 ++++++++++++++++ 4 files changed, 24 insertions(+) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 57a364b205..f00578aa70 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1011,6 +1011,11 @@ StackTrace ExecutionEngine::stackTrace(int frameLimit) const frame.line = qAbs(f->lineNumber()); frame.column = -1; stack.append(frame); + if (f->isTailCalling) { + QV4::StackFrame frame; + frame.function = QStringLiteral("[elided tail calls]"); + stack.append(frame); + } --frameLimit; f = f->parent; } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index dfe9d35194..41a21ba379 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -518,6 +518,7 @@ ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value * do { frame.pendingTailCall = false; result = Moth::VME::exec(&frame, engine); + frame.isTailCalling = true; } while (frame.pendingTailCall); frame.pop(); diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h index a97ae0e7c9..44cfef9173 100644 --- a/src/qml/jsruntime/qv4stackframe_p.h +++ b/src/qml/jsruntime/qv4stackframe_p.h @@ -125,6 +125,7 @@ struct Q_QML_EXPORT CppStackFrame { bool yieldIsIterator; bool callerCanHandleTailCall; bool pendingTailCall; + bool isTailCalling; void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) { this->engine = engine; @@ -140,6 +141,7 @@ struct Q_QML_EXPORT CppStackFrame { yieldIsIterator = false; this->callerCanHandleTailCall = callerCanHandleTailCall; pendingTailCall = false; + isTailCalling = false; } void push() { diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 00c631141b..cf7b9c7224 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -1759,6 +1759,22 @@ void tst_QJSEngine::stacktrace() QJSValue result2 = eng.evaluate(script2, fileName); QVERIFY(!result2.isError()); QVERIFY(result2.isString()); + + { + QString script3 = QString::fromLatin1( + "'use strict'\n" + "function throwUp() { throw new Error('up') }\n" + "function indirectlyThrow() { return throwUp() }\n" + "indirectlyThrow()\n" + ); + QJSValue result3 = eng.evaluate(script3); + QVERIFY(result3.isError()); + QJSValue stack = result3.property("stack"); + QVERIFY(stack.isString()); + QString stackTrace = stack.toString(); + QVERIFY(!stackTrace.contains(QStringLiteral("indirectlyThrow"))); + QVERIFY(stackTrace.contains(QStringLiteral("elide"))); + } } void tst_QJSEngine::numberParsing_data() -- cgit v1.2.3 From 9e3c46961a5f48c3a704b0147e1f073f7516da9c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 3 Jan 2019 08:09:55 +0100 Subject: Remove reference to OpenGL from distance field cache superclass QSGDefaultDistanceFieldGlyphCache is the OpenGL-specific implementation, but for some reason the core profile flag was stored in the superclass. It is ever only used from QSGDefaultDistanceFieldGlyphCache and the rest of the superclass has no OpenGL-dependency, so we just move it. This is needed to be able to share the generic QSGDistanceFieldGlyphCache with Qt 3D Runtime, where there is no current OpenGL context when the scene graph is built and resources have to be allocated through an abstraction layer in Qt 3D. Task-number: QT3DS-1419 Change-Id: I7f4e26eecc21635ff81030b32ecc89c6dc4fcfbe Reviewed-by: Laszlo Agocs --- src/particles/qquickcustomparticle.cpp | 1 + src/quick/scenegraph/qsgadaptationlayer.cpp | 7 +------ src/quick/scenegraph/qsgadaptationlayer_p.h | 9 +-------- src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp | 4 +++- src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h | 2 ++ 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index 8528a6f750..85056dffa9 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -39,6 +39,7 @@ #include "qquickcustomparticle_p.h" #include +#include #include #include #include diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index c99e149aa5..252e5a9c55 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -56,7 +56,7 @@ static QElapsedTimer qsg_render_timer; QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture; -QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font) +QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(const QRawFont &font) : m_pendingGlyphs(64) { Q_ASSERT(font.isValid()); @@ -71,11 +71,6 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QOpenGLContext *c, const // this allows us to call pathForGlyph once and reuse the result. m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution) * QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution)); Q_ASSERT(m_referenceFont.isValid()); -#if QT_CONFIG(opengl) - m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile); -#else - Q_UNUSED(c) -#endif } QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache() diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index ba5c4353b2..58ecae94e7 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -75,7 +74,6 @@ class QSGNode; class QImage; class TextureReference; class QSGDistanceFieldGlyphNode; -class QOpenGLContext; class QSGInternalImageNode; class QSGPainterNode; class QSGInternalRectangleNode; @@ -413,7 +411,7 @@ typedef QIntrusiveList m_textures; QHash m_glyphsData; QDataBuffer m_pendingGlyphs; diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index ccc57b0b86..8121b4559e 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -67,7 +67,7 @@ DEFINE_BOOL_CONFIG_OPTION(qsgPreferFullSizeGlyphCacheTextures, QSG_PREFER_FULLSI QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font) - : QSGDistanceFieldGlyphCache(c, font) + : QSGDistanceFieldGlyphCache(font) , m_maxTextureSize(0) , m_maxTextureCount(3) , m_areaAllocator(nullptr) @@ -89,6 +89,8 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLCont qWarning("Buffer creation failed"); } + m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile); + // Load a pregenerated cache if the font contains one loadPregeneratedCache(font); } diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index a0e4387af9..c64adddd91 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -88,6 +88,7 @@ public: private: bool loadPregeneratedCache(const QRawFont &font); + inline bool isCoreProfile() const { return m_coreProfile; } struct TextureInfo { GLuint texture; @@ -137,6 +138,7 @@ private: mutable int m_maxTextureSize; int m_maxTextureCount; + bool m_coreProfile; QList m_textures; QHash m_glyphsTexture; -- cgit v1.2.3 From 84e15a609b37a64baf82ed20f8d4f79474989226 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Jan 2019 11:15:49 +0100 Subject: Documentation: Start using the \nullptr macro Task-number: PYSIDE-903 Change-Id: I0c4640eb20157673eabb131e8834e79cbbf95d5c Reviewed-by: Paul Wicking --- src/qml/jsapi/qjsvalue.cpp | 6 +++--- src/qml/qml/qqmlcomponent.cpp | 8 ++++---- src/qml/qml/qqmlengine.cpp | 4 +--- src/qml/qml/qqmllist.cpp | 6 +++--- src/quick/items/qquickitem.cpp | 6 +++--- src/quick/scenegraph/util/qsgtexture.cpp | 2 +- src/quick/util/qquickimageprovider.cpp | 2 +- 7 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 225a4443d9..f6fb93eab3 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -1343,11 +1343,11 @@ bool QJSValue::hasOwnProperty(const QString &name) const /*! * If this QJSValue is a QObject, returns the QObject pointer - * that the QJSValue represents; otherwise, returns 0. + * that the QJSValue represents; otherwise, returns \nullptr. * * If the QObject that this QJSValue wraps has been deleted, - * this function returns 0 (i.e. it is possible for toQObject() - * to return 0 even when isQObject() returns true). + * this function returns \nullptr (i.e. it is possible for toQObject() + * to return \nullptr even when isQObject() returns true). * * \sa isQObject() */ diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5ed3cc5d6a..57ea685a5d 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -756,12 +756,12 @@ QQmlComponent::QQmlComponent(QQmlComponentPrivate &dd, QObject *parent) } /*! - Create an object instance from this component. Returns 0 if creation + Create an object instance from this component. Returns \nullptr if creation failed. \a context specifies the context within which to create the object instance. - If \a context is 0 (the default), it will create the instance in the - engine' s \l {QQmlEngine::rootContext()}{root context}. + If \a context is \nullptr (the default), it will create the instance in the + \l {QQmlEngine::rootContext()}{root context} of the engine. The ownership of the returned object instance is transferred to the caller. @@ -791,7 +791,7 @@ QObject *QQmlComponent::create(QQmlContext *context) In general, programmers should use QQmlComponent::create() to create object instances. - Create an object instance from this component. Returns 0 if creation + Create an object instance from this component. Returns \nullptr if creation failed. \a publicContext specifies the context within which to create the object instance. diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 6db43a50eb..5841a480fc 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1304,9 +1304,7 @@ void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBa } /*! - Returns the image provider set for \a providerId. - - Returns the provider if it was found; otherwise returns 0. + Returns the image provider set for \a providerId if found; otherwise returns \nullptr. \sa QQuickImageProvider */ diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 656a8a470b..5425bf498c 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -184,7 +184,7 @@ bool QQmlListReference::isValid() const } /*! -Returns the list property's object. Returns 0 if the reference is invalid. +Returns the list property's object. Returns \nullptr if the reference is invalid. */ QObject *QQmlListReference::object() const { @@ -193,8 +193,8 @@ QObject *QQmlListReference::object() const } /*! -Returns the QMetaObject for the elements stored in the list property. Returns 0 if the reference -is invalid. +Returns the QMetaObject for the elements stored in the list property, +or \nullptr if the reference is invalid. The QMetaObject can be used ahead of time to determine whether a given instance can be added to a list. diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index fabd3ef03b..9e32ccfee9 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4798,7 +4798,7 @@ QQuickItem *QQuickItem::nextItemInFocusChain(bool forward) Returns the first visible child item found at point (\a x, \a y) within the coordinate system of this item. - Returns 0 if there is no such item. + Returns \nullptr if there is no such item. */ QQuickItem *QQuickItem::childAt(qreal x, qreal y) const { @@ -7222,7 +7222,7 @@ bool QQuickItem::isFocusScope() const If this item is a focus scope, this returns the item in its focus chain that currently has focus. - Returns 0 if this item is not a focus scope. + Returns \nullptr if this item is not a focus scope. */ QQuickItem *QQuickItem::scopedFocusItem() const { @@ -8158,7 +8158,7 @@ bool QQuickItem::isTextureProvider() const \fn QSGTextureProvider *QQuickItem::textureProvider() const Returns the texture provider for an item. The default implementation - returns 0. + returns \nullptr. This function may only be called on the rendering thread. */ diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index 982d05691d..d33bdffe74 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -388,7 +388,7 @@ QSGTexture::~QSGTexture() it to a shader that operates on the texture coordinates 0-1 instead of the texture subrect inside the atlas. - If the texture is not part of a texture atlas, this function returns 0. + If the texture is not part of a texture atlas, this function returns \nullptr. Implementations of this function are recommended to return the same instance for multiple calls to limit memory usage. diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp index ced981de3e..ebcca77f17 100644 --- a/src/quick/util/qquickimageprovider.cpp +++ b/src/quick/util/qquickimageprovider.cpp @@ -436,7 +436,7 @@ QPixmap QQuickImageProvider::requestPixmap(const QString &id, QSize *size, const /*! Implement this method to return the texture with \a id. The default - implementation returns 0. + implementation returns \nullptr. The \a id is the requested image source, with the "image:" scheme and provider identifier removed. For example, if the image \l{Image::}{source} -- cgit v1.2.3