aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-03-10 10:56:21 +0100
committerJ-P Nurmi <jpnurmi@qt.io>2017-03-10 10:57:04 +0100
commit8be6bac83ddf958e9658465630b86afcb0728800 (patch)
tree6576e0ee428d7dfe0cd85222d56d939ef1047e63
parentabc657ada6377d12e919113699da6e6960633516 (diff)
parente91c9feab8a0cf4cff71cc68ab0f001b1531504f (diff)
Merge remote-tracking branch 'origin/5.8' into 5.9
Conflicts: src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp src/quicktemplates2/qquicktextarea.cpp src/quicktemplates2/qquicktextfield.cpp Change-Id: Ie80a2d3bcbb961a38e3dffa247547d3d860c231a
-rw-r--r--src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp1
-rw-r--r--src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp2
-rw-r--r--src/quicktemplates2/qquickapplicationwindow.cpp2
-rw-r--r--src/quicktemplates2/qquickpopup.cpp9
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp6
-rw-r--r--src/quicktemplates2/qquicktextfield.cpp6
-rw-r--r--tests/auto/applicationwindow/data/clearfocusondestruction.qml74
-rw-r--r--tests/auto/applicationwindow/tst_applicationwindow.cpp42
-rw-r--r--tests/auto/snippets/tst_snippets.cpp13
9 files changed, 146 insertions, 9 deletions
diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
index 0deb429c..3f3a66b0 100644
--- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
+++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
@@ -99,6 +99,7 @@ void QtQuickControls2MaterialStylePlugin::initializeEngine(QQmlEngine *engine, c
qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 0, "CheckIndicator");
qmlRegisterType(typeUrl(QStringLiteral("CursorDelegate.qml")), import, 2, 0, "CursorDelegate");
qmlRegisterType(typeUrl(QStringLiteral("ElevationEffect.qml")), import, 2, 0, "ElevationEffect");
+ qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 0, "RadioIndicator");
qmlRegisterType(typeUrl(QStringLiteral("RectangularGlow.qml")), import, 2, 0, "RectangularGlow");
qmlRegisterType(typeUrl(QStringLiteral("SliderHandle.qml")), import, 2, 0, "SliderHandle");
qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 0, "SwitchIndicator");
diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
index 29f2b7cc..017a1aad 100644
--- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
+++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
@@ -92,6 +92,8 @@ void QtQuickControls2UniversalStylePlugin::initializeEngine(QQmlEngine *engine,
qmlRegisterType<QQuickUniversalFocusRectangle>(import, 2, 0, "FocusRectangle");
qmlRegisterType<QQuickUniversalBusyIndicator>(import, 2, 0, "BusyIndicatorImpl");
qmlRegisterType<QQuickUniversalProgressBar>(import, 2, 0, "ProgressBarImpl");
+
+ qmlRegisterType(typeUrl(QStringLiteral("CheckIndicator.qml")), import, 2, 0, "CheckIndicator");
qmlRegisterType(typeUrl(QStringLiteral("RadioIndicator.qml")), import, 2, 0, "RadioIndicator");
qmlRegisterType(typeUrl(QStringLiteral("SwitchIndicator.qml")), import, 2, 0, "SwitchIndicator");
}
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp
index c094d454..dcf1b5f0 100644
--- a/src/quicktemplates2/qquickapplicationwindow.cpp
+++ b/src/quicktemplates2/qquickapplicationwindow.cpp
@@ -294,6 +294,8 @@ QQuickApplicationWindow::QQuickApplicationWindow(QWindow *parent)
QQuickApplicationWindow::~QQuickApplicationWindow()
{
Q_D(QQuickApplicationWindow);
+ d->setActiveFocusControl(nullptr);
+ disconnect(this, SIGNAL(activeFocusItemChanged()), this, SLOT(_q_updateActiveFocus()));
if (d->header)
QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index ace82553..9cdb194e 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -427,6 +427,9 @@ void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
window = newWindow;
emit q->windowChanged(newWindow);
+
+ if (complete && visible && window)
+ transitionManager.transitionEnter();
}
void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
@@ -1728,15 +1731,17 @@ void QQuickPopup::classBegin()
void QQuickPopup::componentComplete()
{
Q_D(QQuickPopup);
- d->complete = true;
if (!parentItem()) {
if (QQuickItem *item = qobject_cast<QQuickItem *>(parent()))
setParentItem(item);
else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
setParentItem(window->contentItem());
}
- if (d->visible)
+
+ if (d->visible && d->window)
d->transitionManager.transitionEnter();
+
+ d->complete = true;
d->popupItem->componentComplete();
}
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index 9fbf9764..21d74dd8 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -358,11 +358,13 @@ void QQuickTextAreaPrivate::implicitHeightChanged()
void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
{
+ Q_UNUSED(isReadOnly);
#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->set_readOnly(isReadOnly);
-#else
- Q_UNUSED(isReadOnly)
+#endif
+#if QT_CONFIG(cursor)
+ q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
}
diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp
index a15f923f..e6ca2496 100644
--- a/src/quicktemplates2/qquicktextfield.cpp
+++ b/src/quicktemplates2/qquicktextfield.cpp
@@ -221,11 +221,13 @@ void QQuickTextFieldPrivate::implicitHeightChanged()
void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly)
{
+ Q_UNUSED(isReadOnly);
#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->set_readOnly(isReadOnly);
-#else
- Q_UNUSED(isReadOnly)
+#endif
+#if QT_CONFIG(cursor)
+ q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
}
diff --git a/tests/auto/applicationwindow/data/clearfocusondestruction.qml b/tests/auto/applicationwindow/data/clearfocusondestruction.qml
new file mode 100644
index 00000000..3589439e
--- /dev/null
+++ b/tests/auto/applicationwindow/data/clearfocusondestruction.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.1
+import QtQuick.Layouts 1.3
+import QtGraphicalEffects 1.0
+
+ApplicationWindow {
+ width: 200
+ height: 200
+ visible: true
+
+ property alias textfield: textfield
+
+ /*
+ * The code below is the simplest way we can trigger that the signal
+ * activeFocusItemChanged() is emitted during destruction of the
+ * ApplicationWindow. This caused a crash in QQuickApplicationWindow.
+ */
+ FastBlur {
+ id: fastBlur
+ anchors.fill: parent
+ radius: 30
+ source: ShaderEffectSource {
+ id: effectsource
+ sourceItem: textfield
+ sourceRect: Qt.rect( 0, 0, fastBlur.width, fastBlur.height )
+ }
+ }
+
+ TextField {
+ id: textfield
+ anchors.bottom: parent.bottom
+ focus: true
+ }
+}
diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp
index 2a3f849c..b72bb8f2 100644
--- a/tests/auto/applicationwindow/tst_applicationwindow.cpp
+++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp
@@ -72,6 +72,7 @@ private slots:
void activeFocusControl_data();
void activeFocusControl();
void focusAfterPopupClosed();
+ void clearFocusOnDestruction();
void layout();
};
@@ -685,6 +686,47 @@ void tst_applicationwindow::focusAfterPopupClosed()
QCOMPARE(spy.count(), 2);
}
+void tst_applicationwindow::clearFocusOnDestruction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("clearfocusondestruction.qml"));
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow*>(component.create()));
+ QVERIFY(window);
+
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(QGuiApplication::focusWindow() == window.data());
+
+ QQuickItem* contentItem = window->contentItem();
+ QVERIFY(contentItem);
+ QVERIFY(contentItem->hasActiveFocus());
+
+ QQuickItem* focusScope = window->property("textfield").value<QQuickItem*>();
+ QVERIFY(focusScope);
+ QVERIFY(focusScope->hasActiveFocus());
+
+ QSignalSpy spy(window.data(), SIGNAL(activeFocusControlChanged()));
+ // destroy the window, do not crash
+ window.reset();
+
+ /*
+ QQuickWindow::activeFocusItemChanged() is emitted inconsistently and
+ only for certain use cases. Ideally it should be emitted whenever a
+ QQuickWindow with a focus item is destroyed, but it doesn't... It might
+ also be favorable to not emit it for performance reason.
+
+ However, activeFocusControlChanged() is emitted more consistently, which
+ of course makes it inconsistent with the emission of
+ activeFocusItemChanged()....
+
+ Therefore, if you have good reasons to change the behavior (and not emit
+ it) take the test below with a grain of salt.
+ */
+ QCOMPARE(spy.count(), 1);
+}
+
void tst_applicationwindow::layout()
{
QQmlEngine engine;
diff --git a/tests/auto/snippets/tst_snippets.cpp b/tests/auto/snippets/tst_snippets.cpp
index e5e3ab9e..f870ec7d 100644
--- a/tests/auto/snippets/tst_snippets.cpp
+++ b/tests/auto/snippets/tst_snippets.cpp
@@ -53,6 +53,7 @@ private slots:
void screenshots_data();
private:
+ QQuickView view;
QMap<QString, QStringPair> snippetPaths;
QMap<QString, QStringPair> screenshotSnippetPaths;
};
@@ -97,7 +98,15 @@ static void loadAndShow(QQuickView *view, const QString &source)
QSignalSpy warnings(view->engine(), SIGNAL(warnings(QList<QQmlError>)));
QVERIFY(warnings.isValid());
- view->setSource(QUrl::fromLocalFile(source));
+ QUrl url = QUrl::fromLocalFile(source);
+ QQmlComponent *component = new QQmlComponent(view->engine(), view);
+ component->loadUrl(url);
+
+ QObject *root = component->beginCreate(view->rootContext());
+ QVERIFY(root);
+ view->setContent(url, component, root);
+ component->completeCreate();
+
QCOMPARE(view->status(), QQuickView::Ready);
QVERIFY(view->errors().isEmpty());
QVERIFY(view->rootObject());
@@ -113,7 +122,6 @@ void tst_Snippets::verify()
{
QFETCH(QString, input);
- QQuickView view;
loadAndShow(&view, input);
QGuiApplication::processEvents();
}
@@ -132,7 +140,6 @@ void tst_Snippets::screenshots()
QFETCH(QString, input);
QFETCH(QString, output);
- QQuickView view;
loadAndShow(&view, input);
QSharedPointer<QQuickItemGrabResult> result = view.contentItem()->grabToImage();