diff options
author | J-P Nurmi <jpnurmi@theqtcompany.com> | 2015-11-29 21:56:36 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@theqtcompany.com> | 2015-12-10 21:03:43 +0000 |
commit | eba39a3ba543c04747aa837b064a35ea6b32ed89 (patch) | |
tree | 4e13f4f31b560cac3ffeb2c587016dbebad788e2 | |
parent | c47aa91ed7e0e120d810dc81863758715b928d1b (diff) |
Add ApplicationWindow::activeFocusControl
This makes it possible for ApplicationWindow to visualize key focus
navigation with a single focus rectangle that follows the currently
active focus control.
Change-Id: Ief92bcdc64891b7baa3503216137665a8badcd17
Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com>
-rw-r--r-- | src/templates/qquickapplicationwindow.cpp | 95 | ||||
-rw-r--r-- | src/templates/qquickapplicationwindow_p.h | 11 | ||||
-rw-r--r-- | tests/auto/applicationwindow/data/activeFocusControl.qml | 105 | ||||
-rw-r--r-- | tests/auto/applicationwindow/data/attachedProperties.qml | 58 | ||||
-rw-r--r-- | tests/auto/applicationwindow/tst_applicationwindow.cpp | 150 |
5 files changed, 371 insertions, 48 deletions
diff --git a/src/templates/qquickapplicationwindow.cpp b/src/templates/qquickapplicationwindow.cpp index 32e53a6e..cdc4086e 100644 --- a/src/templates/qquickapplicationwindow.cpp +++ b/src/templates/qquickapplicationwindow.cpp @@ -37,6 +37,8 @@ #include "qquickapplicationwindow_p.h" #include "qquickoverlay_p.h" #include "qquickcontrol_p_p.h" +#include "qquicktextarea_p.h" +#include "qquicktextfield_p.h" #include <QtCore/private/qobject_p.h> #include <QtQuick/private/qquickitem_p.h> @@ -93,6 +95,7 @@ public: , header(Q_NULLPTR) , footer(Q_NULLPTR) , overlay(Q_NULLPTR) + , activeFocusControl(Q_NULLPTR) { } void relayout(); @@ -108,12 +111,16 @@ public: } void resolveFont(); + void _q_updateActiveFocus(); + void setActiveFocusControl(QQuickItem *item); + bool complete; QQuickItem *contentItem; QQuickItem *header; QQuickItem *footer; QQuickOverlay *overlay; QFont font; + QQuickItem *activeFocusControl; QQuickApplicationWindow *q_ptr; }; @@ -165,10 +172,44 @@ void QQuickApplicationWindowPrivate::itemImplicitHeightChanged(QQuickItem *item) relayout(); } +void QQuickApplicationWindowPrivate::_q_updateActiveFocus() +{ + Q_Q(QQuickApplicationWindow); + QQuickItem *item = q->activeFocusItem(); + while (item) { + QQuickControl *control = qobject_cast<QQuickControl *>(item); + if (control) { + setActiveFocusControl(control); + break; + } + QQuickTextField *textField = qobject_cast<QQuickTextField *>(item); + if (textField) { + setActiveFocusControl(textField); + break; + } + QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(item); + if (textArea) { + setActiveFocusControl(textArea); + break; + } + item = item->parentItem(); + } +} + +void QQuickApplicationWindowPrivate::setActiveFocusControl(QQuickItem *control) +{ + Q_Q(QQuickApplicationWindow); + if (activeFocusControl != control) { + activeFocusControl = control; + emit q->activeFocusControlChanged(); + } +} + QQuickApplicationWindow::QQuickApplicationWindow(QWindow *parent) : QQuickWindowQmlImpl(parent), d_ptr(new QQuickApplicationWindowPrivate) { d_ptr->q_ptr = this; + connect(this, SIGNAL(activeFocusItemChanged()), this, SLOT(_q_updateActiveFocus())); } QQuickApplicationWindow::~QQuickApplicationWindow() @@ -277,6 +318,25 @@ QQuickItem *QQuickApplicationWindow::contentItem() const } /*! + \qmlproperty Control Qt.labs.controls::ApplicationWindow::activeFocusControl + + This property holds the control that currently has active focus, or \c null if there is + no control with active focus. + + The difference between \L Window::activeFocusItem and ApplicationWindow::activeFocusControl + is that the former may point to a building block of a control, whereas the latter points + to the enclosing control. For example, when SpinBox has focus, activeFocusItem points to + the editor and acticeFocusControl to the SpinBox itself. + + \sa Window::activeFocusItem +*/ +QQuickItem *QQuickApplicationWindow::activeFocusControl() const +{ + Q_D(const QQuickApplicationWindow); + return d->activeFocusControl; +} + +/*! \qmlproperty Item Qt.labs.controls::ApplicationWindow::overlay \readonly @@ -392,16 +452,16 @@ void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd) if (window != newWindow) { QQuickApplicationWindow *oldWindow = window; if (oldWindow) { - QObject::disconnect(oldWindow, &QQuickApplicationWindow::activeFocusItemChanged, - q, &QQuickApplicationWindowAttached::activeFocusItemChanged); + QObject::disconnect(oldWindow, &QQuickApplicationWindow::activeFocusControlChanged, + q, &QQuickApplicationWindowAttached::activeFocusControlChanged); QObject::disconnect(oldWindow, &QQuickApplicationWindow::headerChanged, q, &QQuickApplicationWindowAttached::headerChanged); QObject::disconnect(oldWindow, &QQuickApplicationWindow::footerChanged, q, &QQuickApplicationWindowAttached::footerChanged); } if (newWindow) { - QObject::connect(newWindow, &QQuickApplicationWindow::activeFocusItemChanged, - q, &QQuickApplicationWindowAttached::activeFocusItemChanged); + QObject::connect(newWindow, &QQuickApplicationWindow::activeFocusControlChanged, + q, &QQuickApplicationWindowAttached::activeFocusControlChanged); QObject::connect(newWindow, &QQuickApplicationWindow::headerChanged, q, &QQuickApplicationWindowAttached::headerChanged); QObject::connect(newWindow, &QQuickApplicationWindow::footerChanged, @@ -413,8 +473,8 @@ void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd) emit q->contentItemChanged(); emit q->overlayChanged(); - if ((oldWindow && oldWindow->activeFocusItem()) || (newWindow && newWindow->activeFocusItem())) - emit q->activeFocusItemChanged(); + if ((oldWindow && oldWindow->activeFocusControl()) || (newWindow && newWindow->activeFocusControl())) + emit q->activeFocusControlChanged(); if ((oldWindow && oldWindow->header()) || (newWindow && newWindow->header())) emit q->headerChanged(); if ((oldWindow && oldWindow->footer()) || (newWindow && newWindow->footer())) @@ -458,18 +518,27 @@ QQuickItem *QQuickApplicationWindowAttached::contentItem() const } /*! - \qmlattachedproperty Item Qt.labs.controls::ApplicationWindow::activeFocusItem + \qmlattachedproperty Control Qt.labs.controls::ApplicationWindow::activeFocusControl - This attached property holds the active focus item. The property can be attached - to any item. The value is \c null if the item is not in an ApplicationWindow, or - the window has no active focus. + This attached property holds the control that currently has active focus, or \c null + if there is no control with active focus. The property can be attached to any item. + The value is \c null if the item is not in an ApplicationWindow, or the window has + no active focus. \sa Window::activeFocusItem */ -QQuickItem *QQuickApplicationWindowAttached::activeFocusItem() const + +/*! + \qmlattachedproperty Control Qt.labs.controls::ApplicationWindow::activeFocusControl + + This attached property holds the active focus control. The property can be attached + to any item. The value is \c null if the item is not in an ApplicationWindow, or + the window has no active focus. +*/ +QQuickItem *QQuickApplicationWindowAttached::activeFocusControl() const { Q_D(const QQuickApplicationWindowAttached); - return d->window ? d->window->activeFocusItem() : Q_NULLPTR; + return d->window ? d->window->activeFocusControl() : Q_NULLPTR; } /*! @@ -511,3 +580,5 @@ QQuickItem *QQuickApplicationWindowAttached::overlay() const } QT_END_NAMESPACE + +#include "moc_qquickapplicationwindow_p.cpp" diff --git a/src/templates/qquickapplicationwindow_p.h b/src/templates/qquickapplicationwindow_p.h index a4c64e19..4d207a08 100644 --- a/src/templates/qquickapplicationwindow_p.h +++ b/src/templates/qquickapplicationwindow_p.h @@ -63,6 +63,7 @@ class Q_LABSTEMPLATES_EXPORT QQuickApplicationWindow : public QQuickWindowQmlImp Q_OBJECT Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT FINAL) Q_PROPERTY(QQmlListProperty<QObject> data READ contentData FINAL) + Q_PROPERTY(QQuickItem *activeFocusControl READ activeFocusControl NOTIFY activeFocusControlChanged FINAL) Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL) Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL) Q_PROPERTY(QQuickItem *overlay READ overlay CONSTANT FINAL) @@ -76,6 +77,8 @@ public: QQuickItem *contentItem() const; QQmlListProperty<QObject> contentData(); + QQuickItem *activeFocusControl() const; + QQuickItem *header() const; void setHeader(QQuickItem *header); @@ -91,6 +94,7 @@ public: static QQuickApplicationWindowAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: + void activeFocusControlChanged(); void headerChanged(); void footerChanged(); void fontChanged(); @@ -103,6 +107,7 @@ protected: private: Q_DISABLE_COPY(QQuickApplicationWindow) Q_DECLARE_PRIVATE(QQuickApplicationWindow) + Q_PRIVATE_SLOT(d_func(), void _q_updateActiveFocus()) QScopedPointer<QQuickApplicationWindowPrivate> d_ptr; }; @@ -111,7 +116,7 @@ class Q_LABSTEMPLATES_EXPORT QQuickApplicationWindowAttached : public QObject Q_OBJECT Q_PROPERTY(QQuickApplicationWindow *window READ window NOTIFY windowChanged FINAL) Q_PROPERTY(QQuickItem *contentItem READ contentItem NOTIFY contentItemChanged FINAL) - Q_PROPERTY(QQuickItem *activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged FINAL) + Q_PROPERTY(QQuickItem *activeFocusControl READ activeFocusControl NOTIFY activeFocusControlChanged FINAL) Q_PROPERTY(QQuickItem *header READ header NOTIFY headerChanged FINAL) Q_PROPERTY(QQuickItem *footer READ footer NOTIFY footerChanged FINAL) Q_PROPERTY(QQuickItem *overlay READ overlay NOTIFY overlayChanged FINAL) @@ -121,7 +126,7 @@ public: QQuickApplicationWindow *window() const; QQuickItem *contentItem() const; - QQuickItem *activeFocusItem() const; + QQuickItem *activeFocusControl() const; QQuickItem *header() const; QQuickItem *footer() const; QQuickItem *overlay() const; @@ -129,7 +134,7 @@ public: Q_SIGNALS: void windowChanged(); void contentItemChanged(); - void activeFocusItemChanged(); + void activeFocusControlChanged(); void headerChanged(); void footerChanged(); void overlayChanged(); diff --git a/tests/auto/applicationwindow/data/activeFocusControl.qml b/tests/auto/applicationwindow/data/activeFocusControl.qml new file mode 100644 index 00000000..51b3241f --- /dev/null +++ b/tests/auto/applicationwindow/data/activeFocusControl.qml @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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.6 +import Qt.labs.controls 1.0 + +ApplicationWindow { + width: 400 + height: 400 + + property alias container_column: column + property alias textInput_column: ti_column + property alias textEdit_column: te_column + property alias textField_column: tf_column + property alias textArea_column: ta_column + property alias spinBox_column: sp_column + property alias spinContent_column: sp_column.contentItem + + property alias container_frame: frame + property alias textInput_frame: ti_frame + property alias textEdit_frame: te_frame + property alias textField_frame: tf_frame + property alias textArea_frame: ta_frame + property alias spinBox_frame: sp_frame + property alias spinContent_frame: sp_frame.contentItem + + Column { + id: column + + TextInput { + id: ti_column + } + TextEdit { + id: te_column + } + TextField { + id: tf_column + } + TextArea { + id: ta_column + } + SpinBox { + id: sp_column + } + } + + Frame { + id: frame + + Column { + TextInput { + id: ti_frame + } + TextEdit { + id: te_frame + } + TextField { + id: tf_frame + } + TextArea { + id: ta_frame + } + SpinBox { + id: sp_frame + } + } + } +} diff --git a/tests/auto/applicationwindow/data/attachedProperties.qml b/tests/auto/applicationwindow/data/attachedProperties.qml index 060a3093..72707537 100644 --- a/tests/auto/applicationwindow/data/attachedProperties.qml +++ b/tests/auto/applicationwindow/data/attachedProperties.qml @@ -43,15 +43,27 @@ import QtQuick.Window 2.2 import Qt.labs.controls 1.0 ApplicationWindow { + property alias childControl: childControl property alias childItem: childItem property alias childObject: childObject - Item { + Control { + id: childControl + + property ApplicationWindow attached_window: ApplicationWindow.window + property Item attached_contentItem: ApplicationWindow.contentItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl + property Item attached_header: ApplicationWindow.header + property Item attached_footer: ApplicationWindow.footer + property Item attached_overlay: ApplicationWindow.overlay + } + + Control { id: childItem property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay @@ -62,13 +74,14 @@ ApplicationWindow { property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay } property alias childWindow: childWindow + property alias childWindowControl: childWindowControl property alias childWindowItem: childWindowItem property alias childWindowObject: childWindowObject @@ -77,17 +90,28 @@ ApplicationWindow { property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay - Item { + Control { + id: childWindowControl + + property ApplicationWindow attached_window: ApplicationWindow.window + property Item attached_contentItem: ApplicationWindow.contentItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl + property Item attached_header: ApplicationWindow.header + property Item attached_footer: ApplicationWindow.footer + property Item attached_overlay: ApplicationWindow.overlay + } + + Control { id: childWindowItem property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay @@ -98,7 +122,7 @@ ApplicationWindow { property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay @@ -106,6 +130,7 @@ ApplicationWindow { } property alias childAppWindow: childAppWindow + property alias childAppWindowControl: childAppWindowControl property alias childAppWindowItem: childAppWindowItem property alias childAppWindowObject: childAppWindowObject @@ -114,17 +139,28 @@ ApplicationWindow { property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay - Item { + Control { + id: childAppWindowControl + + property ApplicationWindow attached_window: ApplicationWindow.window + property Item attached_contentItem: ApplicationWindow.contentItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl + property Item attached_header: ApplicationWindow.header + property Item attached_footer: ApplicationWindow.footer + property Item attached_overlay: ApplicationWindow.overlay + } + + Control { id: childAppWindowItem property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay @@ -135,7 +171,7 @@ ApplicationWindow { property ApplicationWindow attached_window: ApplicationWindow.window property Item attached_contentItem: ApplicationWindow.contentItem - property Item attached_activeFocusItem: ApplicationWindow.activeFocusItem + property Item attached_activeFocusControl: ApplicationWindow.activeFocusControl property Item attached_header: ApplicationWindow.header property Item attached_footer: ApplicationWindow.footer property Item attached_overlay: ApplicationWindow.overlay diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp index 6deb49d2..10360c4f 100644 --- a/tests/auto/applicationwindow/tst_applicationwindow.cpp +++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp @@ -64,6 +64,8 @@ private slots: void implicitFill(); void attachedProperties(); void font(); + void activeFocusControl_data(); + void activeFocusControl(); }; void tst_applicationwindow::qmlCreation() @@ -266,11 +268,20 @@ void tst_applicationwindow::attachedProperties() QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object.data()); QVERIFY(window); + QQuickItem *childControl = object->property("childControl").value<QQuickItem *>(); + QVERIFY(childControl); + QCOMPARE(childControl->property("attached_window").value<QQuickApplicationWindow *>(), window); + QCOMPARE(childControl->property("attached_contentItem").value<QQuickItem *>(), window->contentItem()); + QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), window->activeFocusControl()); + QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), window->header()); + QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), window->footer()); + QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), window->overlay()); + QQuickItem *childItem = object->property("childItem").value<QQuickItem *>(); QVERIFY(childItem); QCOMPARE(childItem->property("attached_window").value<QQuickApplicationWindow *>(), window); QCOMPARE(childItem->property("attached_contentItem").value<QQuickItem *>(), window->contentItem()); - QCOMPARE(childItem->property("attached_activeFocusItem").value<QQuickItem *>(), window->activeFocusItem()); + QCOMPARE(childItem->property("attached_activeFocusControl").value<QQuickItem *>(), window->activeFocusControl()); QCOMPARE(childItem->property("attached_header").value<QQuickItem *>(), window->header()); QCOMPARE(childItem->property("attached_footer").value<QQuickItem *>(), window->footer()); QCOMPARE(childItem->property("attached_overlay").value<QQuickItem *>(), window->overlay()); @@ -279,7 +290,7 @@ void tst_applicationwindow::attachedProperties() QVERIFY(childObject); QVERIFY(!childObject->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childObject->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childObject->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childObject->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childObject->property("attached_header").value<QQuickItem *>()); QVERIFY(!childObject->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childObject->property("attached_overlay").value<QQuickItem *>()); @@ -288,16 +299,25 @@ void tst_applicationwindow::attachedProperties() QVERIFY(childWindow); QVERIFY(!childWindow->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childWindow->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childWindow->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childWindow->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childWindow->property("attached_header").value<QQuickItem *>()); QVERIFY(!childWindow->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childWindow->property("attached_overlay").value<QQuickItem *>()); + QQuickItem *childWindowControl = object->property("childWindowControl").value<QQuickItem *>(); + QVERIFY(childWindowControl); + QVERIFY(!childWindowControl->property("attached_window").value<QQuickApplicationWindow *>()); + QVERIFY(!childWindowControl->property("attached_contentItem").value<QQuickItem *>()); + QVERIFY(!childWindowControl->property("attached_activeFocusControl").value<QQuickItem *>()); + QVERIFY(!childWindowControl->property("attached_header").value<QQuickItem *>()); + QVERIFY(!childWindowControl->property("attached_footer").value<QQuickItem *>()); + QVERIFY(!childWindowControl->property("attached_overlay").value<QQuickItem *>()); + QQuickItem *childWindowItem = object->property("childWindowItem").value<QQuickItem *>(); QVERIFY(childWindowItem); QVERIFY(!childWindowItem->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childWindowItem->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childWindowItem->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childWindowItem->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childWindowItem->property("attached_header").value<QQuickItem *>()); QVERIFY(!childWindowItem->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childWindowItem->property("attached_overlay").value<QQuickItem *>()); @@ -306,7 +326,7 @@ void tst_applicationwindow::attachedProperties() QVERIFY(childWindowObject); QVERIFY(!childWindowObject->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childWindowObject->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childWindowObject->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childWindowObject->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childWindowObject->property("attached_header").value<QQuickItem *>()); QVERIFY(!childWindowObject->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childWindowObject->property("attached_overlay").value<QQuickItem *>()); @@ -315,16 +335,25 @@ void tst_applicationwindow::attachedProperties() QVERIFY(childAppWindow); QVERIFY(!childAppWindow->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childAppWindow->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childAppWindow->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childAppWindow->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childAppWindow->property("attached_header").value<QQuickItem *>()); QVERIFY(!childAppWindow->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childAppWindow->property("attached_overlay").value<QQuickItem *>()); + QQuickItem *childAppWindowControl = object->property("childAppWindowControl").value<QQuickItem *>(); + QVERIFY(childAppWindowControl); + QCOMPARE(childAppWindowControl->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow); + QCOMPARE(childAppWindowControl->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem()); + QCOMPARE(childAppWindowControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl()); + QCOMPARE(childAppWindowControl->property("attached_header").value<QQuickItem *>(), childAppWindow->header()); + QCOMPARE(childAppWindowControl->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer()); + QCOMPARE(childAppWindowControl->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay()); + QQuickItem *childAppWindowItem = object->property("childAppWindowItem").value<QQuickItem *>(); QVERIFY(childAppWindowItem); QCOMPARE(childAppWindowItem->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow); QCOMPARE(childAppWindowItem->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem()); - QCOMPARE(childAppWindowItem->property("attached_activeFocusItem").value<QQuickItem *>(), childAppWindow->activeFocusItem()); + QCOMPARE(childAppWindowItem->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl()); QCOMPARE(childAppWindowItem->property("attached_header").value<QQuickItem *>(), childAppWindow->header()); QCOMPARE(childAppWindowItem->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer()); QCOMPARE(childAppWindowItem->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay()); @@ -333,7 +362,7 @@ void tst_applicationwindow::attachedProperties() QVERIFY(childAppWindowObject); QVERIFY(!childAppWindowObject->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childAppWindowObject->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childAppWindowObject->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childAppWindowObject->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childAppWindowObject->property("attached_header").value<QQuickItem *>()); QVERIFY(!childAppWindowObject->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childAppWindowObject->property("attached_overlay").value<QQuickItem *>()); @@ -342,46 +371,64 @@ void tst_applicationwindow::attachedProperties() window->requestActivate(); QVERIFY(QTest::qWaitForWindowActive(window)); - QVERIFY(!childItem->hasActiveFocus()); - childItem->forceActiveFocus(); - QTRY_VERIFY(childItem->hasActiveFocus()); - QCOMPARE(window->activeFocusItem(), childItem); - QCOMPARE(childItem->property("attached_activeFocusItem").value<QQuickItem *>(), childItem); + QVERIFY(!childControl->hasActiveFocus()); + childControl->forceActiveFocus(); + QTRY_VERIFY(childControl->hasActiveFocus()); + QCOMPARE(window->activeFocusItem(), childControl); + QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childControl); QQuickItem *header = new QQuickItem; window->setHeader(header); QCOMPARE(window->header(), header); - QCOMPARE(childItem->property("attached_header").value<QQuickItem *>(), header); + QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), header); QQuickItem *footer = new QQuickItem; window->setFooter(footer); QCOMPARE(window->footer(), footer); - QCOMPARE(childItem->property("attached_footer").value<QQuickItem *>(), footer); + QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), footer); childAppWindow->show(); childAppWindow->requestActivate(); QVERIFY(QTest::qWaitForWindowActive(childAppWindow)); - QVERIFY(!childAppWindowItem->hasActiveFocus()); - childAppWindowItem->forceActiveFocus(); - QTRY_VERIFY(childAppWindowItem->hasActiveFocus()); - QCOMPARE(childAppWindow->activeFocusItem(), childAppWindowItem); - QCOMPARE(childAppWindowItem->property("attached_activeFocusItem").value<QQuickItem *>(), childAppWindowItem); + QVERIFY(!childAppWindowControl->hasActiveFocus()); + childAppWindowControl->forceActiveFocus(); + QTRY_VERIFY(childAppWindowControl->hasActiveFocus()); + QCOMPARE(childAppWindow->activeFocusItem(), childAppWindowControl); + QCOMPARE(childAppWindowControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindowControl); + + childControl->setParentItem(childAppWindow->contentItem()); + QCOMPARE(childControl->window(), childAppWindow); + QCOMPARE(childControl->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow); + QCOMPARE(childControl->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem()); + QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl()); + QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), childAppWindow->header()); + QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer()); + QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay()); childItem->setParentItem(childAppWindow->contentItem()); QCOMPARE(childItem->window(), childAppWindow); QCOMPARE(childItem->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow); QCOMPARE(childItem->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem()); - QCOMPARE(childItem->property("attached_activeFocusItem").value<QQuickItem *>(), childAppWindow->activeFocusItem()); + QCOMPARE(childItem->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl()); QCOMPARE(childItem->property("attached_header").value<QQuickItem *>(), childAppWindow->header()); QCOMPARE(childItem->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer()); QCOMPARE(childItem->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay()); + childControl->setParentItem(Q_NULLPTR); + QVERIFY(!childControl->window()); + QVERIFY(!childControl->property("attached_window").value<QQuickApplicationWindow *>()); + QVERIFY(!childControl->property("attached_contentItem").value<QQuickItem *>()); + QVERIFY(!childControl->property("attached_activeFocusControl").value<QQuickItem *>()); + QVERIFY(!childControl->property("attached_header").value<QQuickItem *>()); + QVERIFY(!childControl->property("attached_footer").value<QQuickItem *>()); + QVERIFY(!childControl->property("attached_overlay").value<QQuickItem *>()); + childItem->setParentItem(Q_NULLPTR); QVERIFY(!childItem->window()); QVERIFY(!childItem->property("attached_window").value<QQuickApplicationWindow *>()); QVERIFY(!childItem->property("attached_contentItem").value<QQuickItem *>()); - QVERIFY(!childItem->property("attached_activeFocusItem").value<QQuickItem *>()); + QVERIFY(!childItem->property("attached_activeFocusControl").value<QQuickItem *>()); QVERIFY(!childItem->property("attached_header").value<QQuickItem *>()); QVERIFY(!childItem->property("attached_footer").value<QQuickItem *>()); QVERIFY(!childItem->property("attached_overlay").value<QQuickItem *>()); @@ -443,6 +490,65 @@ void tst_applicationwindow::font() QCOMPARE(item6->font(), font); } +void tst_applicationwindow::activeFocusControl_data() +{ + QTest::addColumn<QByteArray>("containerName"); + QTest::addColumn<QByteArray>("activeFocusItemName"); + QTest::addColumn<QByteArray>("activeFocusControlName"); + + QTest::newRow("Column:TextInput") << QByteArray("container_column") << QByteArray("textInput_column") << QByteArray(); + QTest::newRow("Column:TextEdit") << QByteArray("container_column") << QByteArray("textEdit_column") << QByteArray(); + QTest::newRow("Column:TextField") << QByteArray("container_column") << QByteArray("textField_column") << QByteArray("textField_column"); + QTest::newRow("Column:TextArea") << QByteArray("container_column") << QByteArray("textArea_column") << QByteArray("textArea_column"); + QTest::newRow("Column:SpinBox") << QByteArray("container_column") << QByteArray("spinContent_column") << QByteArray("spinBox_column"); + + QTest::newRow("Frame:TextInput") << QByteArray("container_frame") << QByteArray("textInput_frame") << QByteArray("container_frame"); + QTest::newRow("Frame:TextEdit") << QByteArray("container_frame") << QByteArray("textEdit_frame") << QByteArray("container_frame"); + QTest::newRow("Frame:TextField") << QByteArray("container_frame") << QByteArray("textField_frame") << QByteArray("textField_frame"); + QTest::newRow("Frame:TextArea") << QByteArray("container_frame") << QByteArray("textArea_frame") << QByteArray("textArea_frame"); + QTest::newRow("Frame:SpinBox") << QByteArray("container_frame") << QByteArray("spinContent_frame") << QByteArray("spinBox_frame"); +} + +void tst_applicationwindow::activeFocusControl() +{ + QFETCH(QByteArray, containerName); + QFETCH(QByteArray, activeFocusItemName); + QFETCH(QByteArray, activeFocusControlName); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("activeFocusControl.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object.data()); + QVERIFY(window); + QVERIFY(!window->isVisible()); + QCOMPARE(window->width(), 400); + QCOMPARE(window->height(), 400); + + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + QQuickItem *container = window->property(containerName).value<QQuickItem*>(); + QVERIFY(container); + + QQuickItem *activeFocusItem = window->property(activeFocusItemName).value<QQuickItem*>(); + QVERIFY(activeFocusItem); + activeFocusItem->forceActiveFocus(); + QVERIFY(activeFocusItem->hasActiveFocus()); + QCOMPARE(window->activeFocusItem(), activeFocusItem); + + QQuickItem *activeFocusControl = window->property(activeFocusControlName).value<QQuickItem*>(); + if (activeFocusControlName.isEmpty()) { + QVERIFY(!activeFocusControl); + } else { + QVERIFY(activeFocusControl); + QVERIFY(activeFocusControl->hasActiveFocus()); + } + QCOMPARE(window->activeFocusControl(), activeFocusControl); +} + QTEST_MAIN(tst_applicationwindow) #include "tst_applicationwindow.moc" |