aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/quickcontrols2/contactlist/ContactView.ui.qml6
-rw-r--r--src/imports/controls/ComboBox.qml11
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-combobox-custom.qml2
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-delaybutton-custom.qml2
-rw-r--r--src/imports/controls/doc/src/includes/customize-button-background.qdocinc25
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc120
-rw-r--r--src/imports/controls/fusion/ComboBox.qml15
-rw-r--r--src/imports/controls/imagine/ComboBox.qml13
-rw-r--r--src/imports/controls/material/ComboBox.qml15
-rw-r--r--src/imports/controls/material/CursorDelegate.qml2
-rw-r--r--src/imports/controls/universal/ComboBox.qml13
-rw-r--r--src/imports/platform/qquickplatformfiledialog.cpp2
-rw-r--r--src/imports/platform/qquickplatformfolderdialog.cpp2
-rw-r--r--src/imports/templates/qtquicktemplates2plugin.cpp3
-rw-r--r--src/quicktemplates2/qquickabstractbutton.cpp10
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p_p.h4
-rw-r--r--src/quicktemplates2/qquickaction.cpp17
-rw-r--r--src/quicktemplates2/qquickaction_p_p.h6
-rw-r--r--src/quicktemplates2/qquickapplicationwindow.cpp2
-rw-r--r--src/quicktemplates2/qquickcombobox.cpp135
-rw-r--r--src/quicktemplates2/qquickcombobox_p.h11
-rw-r--r--src/quicktemplates2/qquickcontainer.cpp2
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp22
-rw-r--r--src/quicktemplates2/qquickcontrol_p_p.h6
-rw-r--r--src/quicktemplates2/qquickdeferredexecute.cpp10
-rw-r--r--src/quicktemplates2/qquickdial.cpp2
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox.cpp2
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox_p_p.h2
-rw-r--r--src/quicktemplates2/qquickgroupbox.cpp2
-rw-r--r--src/quicktemplates2/qquicklabel.cpp2
-rw-r--r--src/quicktemplates2/qquickmenuitem.cpp2
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp8
-rw-r--r--src/quicktemplates2/qquickpopup.cpp2
-rw-r--r--src/quicktemplates2/qquickpopupitem.cpp4
-rw-r--r--src/quicktemplates2/qquickrangeslider.cpp2
-rw-r--r--src/quicktemplates2/qquickslider.cpp2
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp2
-rw-r--r--src/quicktemplates2/qquickstackelement.cpp6
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp2
-rw-r--r--src/quicktemplates2/qquicktextfield.cpp2
-rw-r--r--tests/auto/controls/data/tst_combobox.qml16
-rw-r--r--tests/auto/controls/data/tst_spinbox.qml16
-rw-r--r--tests/auto/customization/data/styles/identified/AbstractButton.qml3
-rw-r--r--tests/auto/customization/tst_customization.cpp36
-rw-r--r--tests/auto/qquickpopup/data/tabFence.qml97
-rw-r--r--tests/auto/qquickpopup/tst_qquickpopup.cpp61
47 files changed, 546 insertions, 183 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 32d4d650..31431340 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -5,4 +5,4 @@ DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST
QQC2_SOURCE_TREE = $$PWD
-MODULE_VERSION = 5.14.1
+MODULE_VERSION = 5.15.0
diff --git a/examples/quickcontrols2/contactlist/ContactView.ui.qml b/examples/quickcontrols2/contactlist/ContactView.ui.qml
index 747f3042..984fc787 100644
--- a/examples/quickcontrols2/contactlist/ContactView.ui.qml
+++ b/examples/quickcontrols2/contactlist/ContactView.ui.qml
@@ -72,11 +72,7 @@ ListView {
delegate: ContactDelegate {
id: delegate
width: listView.width
-
- Connections {
- target: delegate
- onPressAndHold: listView.pressAndHold(index)
- }
+ onPressAndHold: listView.pressAndHold(index)
}
model: ContactModel {
diff --git a/src/imports/controls/ComboBox.qml b/src/imports/controls/ComboBox.qml
index 8eefc686..b30293f5 100644
--- a/src/imports/controls/ComboBox.qml
+++ b/src/imports/controls/ComboBox.qml
@@ -34,11 +34,11 @@
**
****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Controls 2.14
-import QtQuick.Controls.impl 2.14
-import QtQuick.Templates 2.14 as T
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Controls.impl 2.15
+import QtQuick.Templates 2.15 as T
T.ComboBox {
id: control
@@ -84,6 +84,7 @@ T.ComboBox {
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
+ selectByMouse: control.selectTextByMouse
font: control.font
color: control.editable ? control.palette.text : control.palette.buttonText
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-combobox-custom.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-combobox-custom.qml
index 1bb68bdf..b902dab1 100644
--- a/src/imports/controls/doc/snippets/qtquickcontrols2-combobox-custom.qml
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-combobox-custom.qml
@@ -55,7 +55,7 @@ ComboBox {
Connections {
target: control
- onPressedChanged: canvas.requestPaint()
+ function onPressedChanged() { canvas.requestPaint(); }
}
onPaint: {
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-delaybutton-custom.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-delaybutton-custom.qml
index 86c6a0b7..4bcbaa67 100644
--- a/src/imports/controls/doc/snippets/qtquickcontrols2-delaybutton-custom.qml
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-delaybutton-custom.qml
@@ -62,7 +62,7 @@ DelayButton {
Connections {
target: control
- onProgressChanged: canvas.requestPaint()
+ function onProgressChanged() { canvas.requestPaint(); }
}
onPaint: {
diff --git a/src/imports/controls/doc/src/includes/customize-button-background.qdocinc b/src/imports/controls/doc/src/includes/customize-button-background.qdocinc
new file mode 100644
index 00000000..59df7d8e
--- /dev/null
+++ b/src/imports/controls/doc/src/includes/customize-button-background.qdocinc
@@ -0,0 +1,25 @@
+//! [file]
+\qml \QtMinorVersion
+import QtQuick 2.\1
+import QtQuick.Controls 2.\1
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ visible: true
+
+ Button {
+ id: button
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: button.down ? "#d6d6d6" : "#f6f6f6"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+}
+\endqml
+//! [file]
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index ca1ecf48..5901663a 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -48,29 +48,7 @@
can override the \l {Control::}{background} item and set the radius
property of Rectangle:
- \qml \QtMinorVersion
- import QtQuick 2.\1
- import QtQuick.Controls 2.\1
-
- ApplicationWindow {
- width: 400
- height: 400
- visible: true
-
- Button {
- id: button
- text: "A Special Button"
- background: Rectangle {
- implicitWidth: 100
- implicitHeight: 40
- color: button.down ? "#d6d6d6" : "#f6f6f6"
- border.color: "#26282a"
- border.width: 1
- radius: 4
- }
- }
- }
- \endqml
+ \include customize-button-background.qdocinc file
The second way to create the button is good if you plan to use your rounded
button in several places. It involves moving the code into its own QML file
@@ -214,6 +192,102 @@
files.
\endlist
+ \section3 Considerations for custom styles
+
+ When implementing your own style and customizing controls, there are some
+ points to keep in mind to ensure that your application is as performant as
+ possible.
+
+ \section4 Avoid assigning an id to styles' implementations of item delegates
+
+ As explained in \l {Definition of a Style}, when you implement your
+ own style for a control, you start off with the relevant template for
+ that control. For example, a style's \c Button.qml will be structured
+ similarly to this:
+
+ \qml
+ T.Button {
+ // ...
+
+ background: Rectangle {
+ // ...
+ }
+
+ contentItem: Text {
+ // ...
+ }
+
+ // ...
+ }
+ \endqml
+
+ When you use a Button in your application, the \c background and
+ \c contentItem items will be created and parented to the root \c Button
+ item:
+
+ \qml
+ // Creates the Button root item, the Rectangle background,
+ // and the Text contentItem.
+ Button {
+ text: qsTr("Confirm")
+ }
+ \endqml
+
+ Suppose you then needed to do a one-off customization of the Button (as
+ explained in \l {Customizing a Control}):
+
+ \include customize-button-background.qdocinc file
+
+ In QML, this would normally result in both the default \c background
+ implementation and the one-off, custom \c background items being created.
+ Qt Quick Controls uses a technique that avoids creating both items, and
+ instead only creates the custom \c background, greatly improving the
+ creation performance of controls.
+
+ This technique relies on the absence of an \l {The id Attribute}{id} in the
+ style's implementation of that item. If an id is assigned, the technique
+ cannot work, and both items will be created. For example, it can be
+ tempting to assign an id to the \c background or \c contentItem so that
+ other objects within the file can refer to those items:
+
+ \qml
+ T.Button {
+ // ...
+
+ background: Rectangle {
+ id: backgroundRect
+ // ...
+ }
+
+ contentItem: Text {
+ // Use backgroundRect in some way...
+ }
+
+ // ...
+ }
+ \endqml
+
+ With this code, every time a Button instance with a customized background
+ is created, both backgrounds will be created, resulting in sub-optimal
+ creation performance.
+
+ Prior to Qt 5.15, the old, unused background would be deleted to release
+ the resources associated with it. However, as the control does not own the
+ items, it should not delete them. As of Qt 5.15, old items are no longer
+ deleted, and so the \c backgroundRect item will live longer than it needs
+ to—typically until the application exits. Although the old item will be
+ hidden, visually unparented from the control, and removed from the
+ accessibility tree, it is important to keep the creation time and memory
+ usage of these unused items in mind when assigning an id in this context.
+
+ \section4 Avoid imperative assignments of custom items
+
+ The technique mentioned in the section above only works when an item is
+ \l {Prefer Declarative Bindings Over Imperative Assignments}{declaratively}
+ assigned for the first time, and so imperative assignments will result in
+ orphaned items. Always use declarative bindings to assign custom items
+ when possible.
+
\section3 Attached properties
It is common for a style to have certain properties or attributes that
diff --git a/src/imports/controls/fusion/ComboBox.qml b/src/imports/controls/fusion/ComboBox.qml
index e9b836ef..d8ef1888 100644
--- a/src/imports/controls/fusion/ComboBox.qml
+++ b/src/imports/controls/fusion/ComboBox.qml
@@ -34,13 +34,13 @@
**
****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Templates 2.14 as T
-import QtQuick.Controls 2.14
-import QtQuick.Controls.impl 2.14
-import QtQuick.Controls.Fusion 2.14
-import QtQuick.Controls.Fusion.impl 2.14
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Templates 2.15 as T
+import QtQuick.Controls 2.15
+import QtQuick.Controls.impl 2.15
+import QtQuick.Controls.Fusion 2.15
+import QtQuick.Controls.Fusion.impl 2.15
T.ComboBox {
id: control
@@ -84,6 +84,7 @@ T.ComboBox {
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
+ selectByMouse: control.selectTextByMouse
font: control.font
color: control.editable ? control.palette.text : control.palette.buttonText
diff --git a/src/imports/controls/imagine/ComboBox.qml b/src/imports/controls/imagine/ComboBox.qml
index 2d582e98..92937826 100644
--- a/src/imports/controls/imagine/ComboBox.qml
+++ b/src/imports/controls/imagine/ComboBox.qml
@@ -34,12 +34,12 @@
**
****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Templates 2.14 as T
-import QtQuick.Controls 2.14
-import QtQuick.Controls.Imagine 2.14
-import QtQuick.Controls.Imagine.impl 2.14
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Templates 2.15 as T
+import QtQuick.Controls 2.15
+import QtQuick.Controls.Imagine 2.15
+import QtQuick.Controls.Imagine.impl 2.15
T.ComboBox {
id: control
@@ -98,6 +98,7 @@ T.ComboBox {
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
+ selectByMouse: control.selectTextByMouse
font: control.font
color: control.flat ? control.palette.windowText : control.editable ? control.palette.text : control.palette.buttonText
diff --git a/src/imports/controls/material/ComboBox.qml b/src/imports/controls/material/ComboBox.qml
index 7d635902..e4ee332b 100644
--- a/src/imports/controls/material/ComboBox.qml
+++ b/src/imports/controls/material/ComboBox.qml
@@ -34,13 +34,13 @@
**
****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Controls 2.14
-import QtQuick.Controls.impl 2.14
-import QtQuick.Templates 2.14 as T
-import QtQuick.Controls.Material 2.14
-import QtQuick.Controls.Material.impl 2.14
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Controls.impl 2.15
+import QtQuick.Templates 2.15 as T
+import QtQuick.Controls.Material 2.15
+import QtQuick.Controls.Material.impl 2.15
T.ComboBox {
id: control
@@ -89,6 +89,7 @@ T.ComboBox {
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
+ selectByMouse: control.selectTextByMouse
font: control.font
color: control.enabled ? control.Material.foreground : control.Material.hintTextColor
diff --git a/src/imports/controls/material/CursorDelegate.qml b/src/imports/controls/material/CursorDelegate.qml
index 1626a6fb..fe2d25c6 100644
--- a/src/imports/controls/material/CursorDelegate.qml
+++ b/src/imports/controls/material/CursorDelegate.qml
@@ -46,7 +46,7 @@ Rectangle {
Connections {
target: cursor.parent
- onCursorPositionChanged: {
+ function onCursorPositionChanged() {
// keep a moving cursor visible
cursor.opacity = 1
timer.restart()
diff --git a/src/imports/controls/universal/ComboBox.qml b/src/imports/controls/universal/ComboBox.qml
index 9a4e119b..fd2d8935 100644
--- a/src/imports/controls/universal/ComboBox.qml
+++ b/src/imports/controls/universal/ComboBox.qml
@@ -34,12 +34,12 @@
**
****************************************************************************/
-import QtQuick 2.14
-import QtQuick.Window 2.14
-import QtQuick.Controls 2.14
-import QtQuick.Controls.impl 2.14
-import QtQuick.Templates 2.14 as T
-import QtQuick.Controls.Universal 2.14
+import QtQuick 2.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Controls.impl 2.15
+import QtQuick.Templates 2.15 as T
+import QtQuick.Controls.Universal 2.15
T.ComboBox {
id: control
@@ -94,6 +94,7 @@ T.ComboBox {
readOnly: control.down
inputMethodHints: control.inputMethodHints
validator: control.validator
+ selectByMouse: control.selectTextByMouse
font: control.font
color: !control.enabled ? control.Universal.chromeDisabledLowColor :
diff --git a/src/imports/platform/qquickplatformfiledialog.cpp b/src/imports/platform/qquickplatformfiledialog.cpp
index 6f212bef..4c8a0192 100644
--- a/src/imports/platform/qquickplatformfiledialog.cpp
+++ b/src/imports/platform/qquickplatformfiledialog.cpp
@@ -303,7 +303,7 @@ void QQuickPlatformFileDialog::setOptions(QFileDialogOptions::FileDialogOptions
void QQuickPlatformFileDialog::resetOptions()
{
- setOptions(0);
+ setOptions({});
}
/*!
diff --git a/src/imports/platform/qquickplatformfolderdialog.cpp b/src/imports/platform/qquickplatformfolderdialog.cpp
index b9ea0184..4ae6341e 100644
--- a/src/imports/platform/qquickplatformfolderdialog.cpp
+++ b/src/imports/platform/qquickplatformfolderdialog.cpp
@@ -186,7 +186,7 @@ void QQuickPlatformFolderDialog::setOptions(QFileDialogOptions::FileDialogOption
void QQuickPlatformFolderDialog::resetOptions()
{
- setOptions(0);
+ setOptions({});
}
/*!
diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp
index e84db606..9645e4ce 100644
--- a/src/imports/templates/qtquicktemplates2plugin.cpp
+++ b/src/imports/templates/qtquicktemplates2plugin.cpp
@@ -358,6 +358,9 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri)
// QtQuick.Templates 2.14 (new types and revisions in Qt 5.14)
qmlRegisterType<QQuickComboBox, 14>(uri, 2, 14, "ComboBox");
+
+ // QtQuick.Templates 2.15 (new types and revisions in Qt 5.15)
+ qmlRegisterType<QQuickComboBox, 15>(uri, 2, 15, "ComboBox");
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index 969ab173..8ce4d0e5 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -44,7 +44,9 @@
#include <QtGui/qstylehints.h>
#include <QtGui/qguiapplication.h>
-#include <QtGui/private/qshortcutmap_p.h>
+#if QT_CONFIG(shortcut)
+# include <QtGui/private/qshortcutmap_p.h>
+#endif
#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQml/qqmllist.h>
@@ -710,7 +712,7 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight();
d->removeImplicitSizeListener(d->indicator);
- delete d->indicator;
+ QQuickControlPrivate::hideOldItem(d->indicator);
d->indicator = indicator;
if (indicator) {
@@ -1015,8 +1017,8 @@ void QQuickAbstractButton::componentComplete()
bool QQuickAbstractButton::event(QEvent *event)
{
- Q_D(QQuickAbstractButton);
#if QT_CONFIG(shortcut)
+ Q_D(QQuickAbstractButton);
if (event->type() == QEvent::Shortcut) {
QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
if (se->shortcutId() == d->shortcutId) {
@@ -1101,9 +1103,9 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event)
void QQuickAbstractButton::itemChange(ItemChange change, const ItemChangeData &value)
{
- Q_D(QQuickAbstractButton);
QQuickControl::itemChange(change, value);
#if QT_CONFIG(shortcut)
+ Q_D(QQuickAbstractButton);
if (change == ItemVisibleHasChanged) {
if (value.boolValue)
d->grabShortcut();
diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h
index 7394f115..8ad479e2 100644
--- a/src/quicktemplates2/qquickabstractbutton_p_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p_p.h
@@ -50,7 +50,9 @@
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
-#include <QtGui/qkeysequence.h>
+#if QT_CONFIG(shortcut)
+# include <QtGui/qkeysequence.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/quicktemplates2/qquickaction.cpp b/src/quicktemplates2/qquickaction.cpp
index 6cb63238..0b083339 100644
--- a/src/quicktemplates2/qquickaction.cpp
+++ b/src/quicktemplates2/qquickaction.cpp
@@ -40,7 +40,9 @@
#include "qquickshortcutcontext_p_p.h"
#include <QtGui/qevent.h>
-#include <QtGui/private/qshortcutmap_p.h>
+#if QT_CONFIG(shortcut)
+# include <QtGui/private/qshortcutmap_p.h>
+#endif
#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/private/qquickitem_p.h>
@@ -261,6 +263,8 @@ void QQuickActionPrivate::unregisterItem(QQuickItem *item)
delete entry;
updateDefaultShortcutEntry();
+#else
+ Q_UNUSED(item);
#endif
}
@@ -277,6 +281,8 @@ void QQuickActionPrivate::itemVisibilityChanged(QQuickItem *item)
entry->ungrab();
updateDefaultShortcutEntry();
+#else
+ Q_UNUSED(item);
#endif
}
@@ -332,8 +338,8 @@ void QQuickActionPrivate::updateDefaultShortcutEntry()
QQuickAction::QQuickAction(QObject *parent)
: QObject(*(new QQuickActionPrivate), parent)
{
- Q_D(QQuickAction);
#if QT_CONFIG(shortcut)
+ Q_D(QQuickAction);
d->defaultShortcutEntry = new QQuickActionPrivate::ShortcutEntry(this);
#endif
}
@@ -554,8 +560,8 @@ void QQuickActionPrivate::trigger(QObject* source, bool doToggle)
bool QQuickAction::event(QEvent *event)
{
- Q_D(QQuickAction);
#if QT_CONFIG(shortcut)
+ Q_D(QQuickAction);
if (event->type() == QEvent::Shortcut)
return d->handleShortcutEvent(this, static_cast<QShortcutEvent *>(event));
#endif
@@ -564,10 +570,13 @@ bool QQuickAction::event(QEvent *event)
bool QQuickAction::eventFilter(QObject *object, QEvent *event)
{
- Q_D(QQuickAction);
#if QT_CONFIG(shortcut)
+ Q_D(QQuickAction);
if (event->type() == QEvent::Shortcut)
return d->handleShortcutEvent(object, static_cast<QShortcutEvent *>(event));
+#else
+ Q_UNUSED(object);
+ Q_UNUSED(event);
#endif
return false;
}
diff --git a/src/quicktemplates2/qquickaction_p_p.h b/src/quicktemplates2/qquickaction_p_p.h
index 7c70bab1..252b0075 100644
--- a/src/quicktemplates2/qquickaction_p_p.h
+++ b/src/quicktemplates2/qquickaction_p_p.h
@@ -51,7 +51,9 @@
#include <QtCore/private/qobject_p.h>
#include <QtCore/qvariant.h>
#include <QtCore/qstring.h>
-#include <QtGui/qkeysequence.h>
+#if QT_CONFIG(shortcut)
+# include <QtGui/qkeysequence.h>
+#endif
#include <QtQuick/private/qquickitemchangelistener_p.h>
QT_BEGIN_NAMESPACE
@@ -119,8 +121,8 @@ public:
bool checkable = false;
QString text;
QQuickIcon icon;
- QKeySequence keySequence;
#if QT_CONFIG(shortcut)
+ QKeySequence keySequence;
QVariant vshortcut;
ShortcutEntry *defaultShortcutEntry = nullptr;
QVector<ShortcutEntry *> shortcutEntries;
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp
index 92d19a37..903de676 100644
--- a/src/quicktemplates2/qquickapplicationwindow.cpp
+++ b/src/quicktemplates2/qquickapplicationwindow.cpp
@@ -407,7 +407,7 @@ void QQuickApplicationWindow::setBackground(QQuickItem *background)
if (!d->background.isExecuting())
d->cancelBackground();
- delete d->background;
+ QQuickControlPrivate::hideOldItem(d->background);
d->background = background;
if (background) {
background->setParentItem(QQuickWindow::contentItem());
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp
index 7833b39b..5f3f1cfc 100644
--- a/src/quicktemplates2/qquickcombobox.cpp
+++ b/src/quicktemplates2/qquickcombobox.cpp
@@ -51,6 +51,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/private/qlazilyallocated_p.h>
#include <private/qqmldelegatemodel_p.h>
+#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuick/private/qquickitemview_p.h>
@@ -232,13 +233,9 @@ public:
void updateEditText();
void updateCurrentText();
void updateCurrentValue();
- void updateCurrentText(bool hasDelegateModelObject);
- void updateCurrentValue(bool hasDelegateModelObject);
void updateCurrentTextAndValue();
bool isValidIndex(int index) const;
- QString fastTextAt(int index) const;
- QVariant fastValueAt(int index) const;
void acceptInput();
QString tryComplete(const QString &inputText);
@@ -268,6 +265,8 @@ public:
void itemImplicitWidthChanged(QQuickItem *item) override;
void itemImplicitHeightChanged(QQuickItem *item) override;
+ static void hideOldPopup(QQuickPopup *popup);
+
bool flat = false;
bool down = false;
bool hasDown = false;
@@ -294,6 +293,7 @@ public:
bool editable = false;
bool accepting = false;
bool allowComplete = false;
+ bool selectTextByMouse = false;
Qt::InputMethodHints inputMethodHints = Qt::ImhNone;
QString editText;
QValidator *validator = nullptr;
@@ -441,34 +441,10 @@ void QQuickComboBoxPrivate::updateEditText()
q->setEditText(text);
}
-// We have these two rather than just using default arguments
-// because QObjectPrivate::connect() doesn't accept lambdas.
void QQuickComboBoxPrivate::updateCurrentText()
{
- updateCurrentText(false);
-}
-
-void QQuickComboBoxPrivate::updateCurrentValue()
-{
- updateCurrentValue(false);
-}
-
-void QQuickComboBoxPrivate::updateCurrentText(bool hasDelegateModelObject)
-{
Q_Q(QQuickComboBox);
- QString text;
- // If a delegate model object was passed in, it means the calling code
- // has decided to reuse it for several function calls to speed things up.
- // So, use the faster (private) version in that case.
- // For other cases, we use the version that creates the delegate model object
- // itself in order to have neater, more convenient calling code.
- if (isValidIndex(currentIndex)) {
- if (hasDelegateModelObject)
- text = fastTextAt(currentIndex);
- else
- text = q->textAt(currentIndex);
- }
-
+ const QString text = q->textAt(currentIndex);
if (currentText != text) {
currentText = text;
if (!hasDisplayText)
@@ -483,19 +459,10 @@ void QQuickComboBoxPrivate::updateCurrentText(bool hasDelegateModelObject)
q->setEditText(currentText);
}
-void QQuickComboBoxPrivate::updateCurrentValue(bool hasDelegateModelObject)
+void QQuickComboBoxPrivate::updateCurrentValue()
{
Q_Q(QQuickComboBox);
- QVariant value;
- // If a delegate model object was passed in, it means the calling code
- // has decided to reuse it for several function calls to speed things up.
- // So, use the faster (private) version in that case.
- if (isValidIndex(currentIndex)) {
- if (hasDelegateModelObject)
- value = fastValueAt(currentIndex);
- else
- value = q->valueAt(currentIndex);
- }
+ const QVariant value = q->valueAt(currentIndex);
if (currentValue == value)
return;
@@ -505,15 +472,8 @@ void QQuickComboBoxPrivate::updateCurrentValue(bool hasDelegateModelObject)
void QQuickComboBoxPrivate::updateCurrentTextAndValue()
{
- QObject *object = nullptr;
- // For performance reasons, we reuse the same delegate model object: QTBUG-76029.
- if (isValidIndex(currentIndex))
- object = delegateModel->object(currentIndex);
- const bool hasDelegateModelObject = object != nullptr;
- updateCurrentText(hasDelegateModelObject);
- updateCurrentValue(hasDelegateModelObject);
- if (object)
- delegateModel->release(object);
+ updateCurrentText();
+ updateCurrentValue();
}
bool QQuickComboBoxPrivate::isValidIndex(int index) const
@@ -521,20 +481,6 @@ bool QQuickComboBoxPrivate::isValidIndex(int index) const
return delegateModel && index >= 0 && index < delegateModel->count();
}
-// For performance reasons (QTBUG-76029), both this and valueAt assume that
-// the index is valid and delegateModel->object(index) has been called.
-QString QQuickComboBoxPrivate::fastTextAt(int index) const
-{
- const QString effectiveTextRole = textRole.isEmpty() ? QStringLiteral("modelData") : textRole;
- return delegateModel->stringValue(index, effectiveTextRole);
-}
-
-QVariant QQuickComboBoxPrivate::fastValueAt(int index) const
-{
- const QString effectiveValueRole = valueRole.isEmpty() ? QStringLiteral("modelData") : valueRole;
- return delegateModel->variantValue(index, effectiveValueRole);
-}
-
void QQuickComboBoxPrivate::acceptInput()
{
Q_Q(QQuickComboBox);
@@ -832,6 +778,21 @@ void QQuickComboBoxPrivate::itemImplicitHeightChanged(QQuickItem *item)
emit q->implicitIndicatorHeightChanged();
}
+void QQuickComboBoxPrivate::hideOldPopup(QQuickPopup *popup)
+{
+ if (!popup)
+ return;
+
+ qCDebug(lcItemManagement) << "hiding old popup" << popup;
+
+ popup->setVisible(false);
+ popup->setParentItem(nullptr);
+ // Remove the item from the accessibility tree.
+ QQuickAccessibleAttached *accessible = accessibleAttached(popup);
+ if (accessible)
+ accessible->setIgnored(true);
+}
+
QQuickComboBox::QQuickComboBox(QQuickItem *parent)
: QQuickControl(*(new QQuickComboBoxPrivate), parent)
{
@@ -852,7 +813,7 @@ QQuickComboBox::~QQuickComboBox()
// Disconnect visibleChanged() to avoid a spurious highlightedIndexChanged() signal
// emission during the destruction of the (visible) popup. (QTBUG-57650)
QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
- delete d->popup;
+ QQuickComboBoxPrivate::hideOldPopup(d->popup);
d->popup = nullptr;
}
}
@@ -1194,7 +1155,7 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator)
const qreal oldImplicitIndicatorHeight = implicitIndicatorHeight();
d->removeImplicitSizeListener(d->indicator);
- delete d->indicator;
+ QQuickControlPrivate::hideOldItem(d->indicator);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
@@ -1242,7 +1203,7 @@ void QQuickComboBox::setPopup(QQuickPopup *popup)
if (d->popup) {
QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
- delete d->popup;
+ QQuickComboBoxPrivate::hideOldPopup(d->popup);
}
if (popup) {
QQuickPopupPrivate::get(popup)->allowVerticalFlip = true;
@@ -1583,13 +1544,8 @@ QVariant QQuickComboBox::valueAt(int index) const
if (!d->isValidIndex(index))
return QVariant();
- QObject *object = d->delegateModel->object(index);
- QVariant value;
- if (object) {
- value = d->fastValueAt(index);
- d->delegateModel->release(object);
- }
- return value;
+ const QString effectiveValueRole = d->valueRole.isEmpty() ? QStringLiteral("modelData") : d->valueRole;
+ return d->delegateModel->variantValue(index, effectiveValueRole);
}
/*!
@@ -1613,6 +1569,30 @@ int QQuickComboBox::indexOfValue(const QVariant &value) const
}
/*!
+ \since QtQuick.Controls 2.15 (Qt 5.15)
+ \qmlproperty bool QtQuick.Controls::ComboBox::selectTextByMouse
+
+ This property holds whether the text field for an editable ComboBox
+ can be selected with the mouse.
+
+ The default value is \c false.
+*/
+bool QQuickComboBox::selectTextByMouse() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->selectTextByMouse : false;
+}
+
+void QQuickComboBox::setSelectTextByMouse(bool canSelect)
+{
+ Q_D(QQuickComboBox);
+ if (canSelect == selectTextByMouse())
+ return;
+
+ d->extra.value().selectTextByMouse = canSelect;
+ emit selectTextByMouseChanged();
+}
+/*!
\qmlmethod string QtQuick.Controls::ComboBox::textAt(int index)
Returns the text for the specified \a index, or an empty string
@@ -1626,13 +1606,8 @@ QString QQuickComboBox::textAt(int index) const
if (!d->isValidIndex(index))
return QString();
- QObject *object = d->delegateModel->object(index);
- QString text;
- if (object) {
- text = d->fastTextAt(index);
- d->delegateModel->release(object);
- }
- return text;
+ const QString effectiveTextRole = d->textRole.isEmpty() ? QStringLiteral("modelData") : d->textRole;
+ return d->delegateModel->stringValue(index, effectiveTextRole);
}
/*!
diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h
index c9063d6a..b52d7545 100644
--- a/src/quicktemplates2/qquickcombobox_p.h
+++ b/src/quicktemplates2/qquickcombobox_p.h
@@ -48,10 +48,13 @@
// We mean it.
//
+#include <QtCore/qloggingcategory.h>
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcItemManagement)
+
class QValidator;
class QQuickPopup;
class QQmlInstanceModel;
@@ -89,6 +92,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickComboBox : public QQuickControl
// 2.14 (Qt 5.14)
Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged FINAL REVISION 14)
Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole NOTIFY valueRoleChanged FINAL REVISION 14)
+ // 2.15 (Qt 5.15)
+ Q_PROPERTY(bool selectTextByMouse READ selectTextByMouse WRITE setSelectTextByMouse NOTIFY selectTextByMouseChanged FINAL REVISION 15)
public:
explicit QQuickComboBox(QQuickItem *parent = nullptr);
@@ -166,6 +171,10 @@ public:
Q_REVISION(14) Q_INVOKABLE QVariant valueAt(int index) const;
Q_REVISION(14) Q_INVOKABLE int indexOfValue(const QVariant &value) const;
+ // 2.15 (Qt 5.15)
+ bool selectTextByMouse() const;
+ void setSelectTextByMouse(bool canSelect);
+
public Q_SLOTS:
void incrementCurrentIndex();
void decrementCurrentIndex();
@@ -203,6 +212,8 @@ Q_SIGNALS:
// 2.14 (Qt 5.14)
Q_REVISION(14) void valueRoleChanged();
Q_REVISION(14) void currentValueChanged();
+ // 2.15 (Qt 5.15)
+ Q_REVISION(15) void selectTextByMouseChanged();
protected:
bool eventFilter(QObject *object, QEvent *event) override;
diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp
index 19b59e33..f38c2b09 100644
--- a/src/quicktemplates2/qquickcontainer.cpp
+++ b/src/quicktemplates2/qquickcontainer.cpp
@@ -219,7 +219,7 @@ void QQuickContainerPrivate::cleanup()
QQuickWindowPrivate::get(window)->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
q->contentItemChange(nullptr, contentItem);
- delete contentItem;
+ QQuickControlPrivate::hideOldItem(contentItem);
}
QObject::disconnect(contentModel, &QQmlObjectModel::countChanged, q, &QQuickContainer::countChanged);
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index 7e249dae..6b845ae6 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -56,6 +56,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcItemManagement, "qt.quick.controls.control.itemmanagement")
+
/*!
\qmltype Control
\inherits Item
@@ -420,7 +422,7 @@ void QQuickControlPrivate::setContentItem_helper(QQuickItem *item, bool notify)
contentItem = item;
q->contentItemChange(item, oldContentItem);
- delete oldContentItem;
+ QQuickControlPrivate::hideOldItem(oldContentItem);
if (item) {
connect(contentItem.data(), &QQuickItem::baselineOffsetChanged, this, &QQuickControlPrivate::updateBaselineOffset);
@@ -838,6 +840,22 @@ void QQuickControlPrivate::executeBackground(bool complete)
quickCompleteDeferred(q, backgroundName(), background);
}
+void QQuickControlPrivate::hideOldItem(QQuickItem *item)
+{
+ if (!item)
+ return;
+
+ qCDebug(lcItemManagement) << "hiding old item" << item;
+
+ item->setVisible(false);
+ item->setParentItem(nullptr);
+
+ // Remove the item from the accessibility tree.
+ QQuickAccessibleAttached *accessible = accessibleAttached(item);
+ if (accessible)
+ accessible->setIgnored(true);
+}
+
void QQuickControlPrivate::updateBaselineOffset()
{
Q_Q(QQuickControl);
@@ -1590,7 +1608,7 @@ void QQuickControl::setBackground(QQuickItem *background)
}
d->removeImplicitSizeListener(d->background, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
- delete d->background;
+ QQuickControlPrivate::hideOldItem(d->background);
d->background = background;
if (background) {
diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h
index a657307b..b649db0a 100644
--- a/src/quicktemplates2/qquickcontrol_p_p.h
+++ b/src/quicktemplates2/qquickcontrol_p_p.h
@@ -60,8 +60,12 @@
#include <QtGui/qaccessible.h>
#endif
+#include <QtCore/qloggingcategory.h>
+
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcItemManagement)
+
class QQuickAccessibleAttached;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControlPrivate : public QQuickItemPrivate, public QQuickItemChangeListener
@@ -168,6 +172,8 @@ public:
virtual void cancelBackground();
virtual void executeBackground(bool complete = false);
+ static void hideOldItem(QQuickItem *item);
+
void updateBaselineOffset();
static const ChangeTypes ImplicitSizeChanges;
diff --git a/src/quicktemplates2/qquickdeferredexecute.cpp b/src/quicktemplates2/qquickdeferredexecute.cpp
index 800dcedb..d56131e4 100644
--- a/src/quicktemplates2/qquickdeferredexecute.cpp
+++ b/src/quicktemplates2/qquickdeferredexecute.cpp
@@ -92,11 +92,21 @@ static bool beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &pro
typedef QMultiHash<int, const QV4::CompiledData::Binding *> QV4PropertyBindingHash;
auto it = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.second);
auto last = std::reverse_iterator<QV4PropertyBindingHash::iterator>(range.first);
+#if Q_QML_PRIVATE_API_VERSION < 7
while (it != last) {
if (!state->creator->populateDeferredBinding(property, deferData, *it))
state->errors << state->creator->errors;
++it;
}
+#else
+ state->creator->beginPopulateDeferred(deferData->context);
+ while (it != last) {
+ state->creator->populateDeferredBinding(property, deferData->deferredIdx, *it);
+ ++it;
+ }
+ state->creator->finalizePopulateDeferred();
+ state->errors << state->creator->errors;
+#endif
deferredState->constructionStates += state;
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp
index b07628ff..99bd0e98 100644
--- a/src/quicktemplates2/qquickdial.cpp
+++ b/src/quicktemplates2/qquickdial.cpp
@@ -620,7 +620,7 @@ void QQuickDial::setHandle(QQuickItem *handle)
if (!d->handle.isExecuting())
d->cancelHandle();
- delete d->handle;
+ QQuickControlPrivate::hideOldItem(d->handle);
d->handle = handle;
if (d->handle && !d->handle->parentItem())
d->handle->setParentItem(this);
diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp
index 33b720ed..2c09cd11 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox.cpp
+++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -542,7 +542,7 @@ void QQuickDialogButtonBox::setAlignment(Qt::Alignment alignment)
void QQuickDialogButtonBox::resetAlignment()
{
- setAlignment(0);
+ setAlignment({});
}
/*!
diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
index 6f9c9033..22da9e6d 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
+++ b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
@@ -80,7 +80,7 @@ public:
void updateLanguage();
- Qt::Alignment alignment = 0;
+ Qt::Alignment alignment;
QQuickDialogButtonBox::Position position = QQuickDialogButtonBox::Footer;
QPlatformDialogHelper::StandardButtons standardButtons = QPlatformDialogHelper::NoButton;
QPlatformDialogHelper::ButtonLayout buttonLayout = QPlatformDialogHelper::UnknownLayout;
diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp
index 3dbf3174..70ec30dc 100644
--- a/src/quicktemplates2/qquickgroupbox.cpp
+++ b/src/quicktemplates2/qquickgroupbox.cpp
@@ -199,7 +199,7 @@ void QQuickGroupBox::setLabel(QQuickItem *label)
const qreal oldImplicitLabelHeight = implicitLabelHeight();
d->removeImplicitSizeListener(d->label);
- delete d->label;
+ QQuickControlPrivate::hideOldItem(d->label);
d->label = label;
if (label) {
diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp
index 9937436c..71b60a2b 100644
--- a/src/quicktemplates2/qquicklabel.cpp
+++ b/src/quicktemplates2/qquicklabel.cpp
@@ -405,7 +405,7 @@ void QQuickLabel::setBackground(QQuickItem *background)
}
QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
- delete d->background;
+ QQuickControlPrivate::hideOldItem(d->background);
d->background = background;
if (background) {
diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp
index 0fbfb90b..ec1ea621 100644
--- a/src/quicktemplates2/qquickmenuitem.cpp
+++ b/src/quicktemplates2/qquickmenuitem.cpp
@@ -216,7 +216,7 @@ void QQuickMenuItem::setArrow(QQuickItem *arrow)
if (!d->arrow.isExecuting())
d->cancelArrow();
- delete d->arrow;
+ QQuickControlPrivate::hideOldItem(d->arrow);
d->arrow = arrow;
if (arrow && !arrow->parentItem())
arrow->setParentItem(this);
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index ea72072b..e9f8801d 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -34,10 +34,12 @@
**
****************************************************************************/
+#include "qquickcontrol_p_p.h"
#include "qquickoverlay_p.h"
#include "qquickoverlay_p_p.h"
#include "qquickpopupitem_p_p.h"
#include "qquickpopup_p_p.h"
+#include "qquickdrawer_p.h"
#include "qquickdrawer_p_p.h"
#include "qquickapplicationwindow_p.h"
#include <QtQml/qqmlinfo.h>
@@ -255,7 +257,7 @@ void QQuickOverlayPrivate::removePopup(QQuickPopup *popup)
{
Q_Q(QQuickOverlay);
allPopups.removeOne(popup);
- if (allDrawers.removeOne(static_cast<QQuickDrawer *>(popup)))
+ if (allDrawers.removeOne(qobject_cast<QQuickDrawer *>(popup)))
q->setVisible(!allDrawers.isEmpty() || !q->childItems().isEmpty());
}
@@ -341,7 +343,6 @@ void QQuickOverlay::setModal(QQmlComponent *modal)
if (d->modal == modal)
return;
- delete d->modal;
d->modal = modal;
emit modalChanged();
}
@@ -358,7 +359,6 @@ void QQuickOverlay::setModeless(QQmlComponent *modeless)
if (d->modeless == modeless)
return;
- delete d->modeless;
d->modeless = modeless;
emit modelessChanged();
}
@@ -670,7 +670,6 @@ void QQuickOverlayAttached::setModal(QQmlComponent *modal)
if (d->modal == modal)
return;
- delete d->modal;
d->modal = modal;
emit modalChanged();
}
@@ -703,7 +702,6 @@ void QQuickOverlayAttached::setModeless(QQmlComponent *modeless)
if (d->modeless == modeless)
return;
- delete d->modeless;
d->modeless = modeless;
emit modelessChanged();
}
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index ecb2568e..7a7e00b1 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -1843,6 +1843,8 @@ void QQuickPopup::setModal(bool modal)
d->toggleOverlay();
emit modalChanged();
+ QQuickItemPrivate::get(d->popupItem)->isTabFence = modal;
+
if (!d->hasDim) {
setDim(modal);
d->hasDim = false;
diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp
index fcf23db5..8e169b0b 100644
--- a/src/quicktemplates2/qquickpopupitem.cpp
+++ b/src/quicktemplates2/qquickpopupitem.cpp
@@ -42,7 +42,9 @@
#include "qquickpopup_p_p.h"
#include "qquickdeferredexecute_p_p.h"
-#include <QtGui/private/qshortcutmap_p.h>
+#if QT_CONFIG(shortcut)
+# include <QtGui/private/qshortcutmap_p.h>
+#endif
#include <QtGui/private/qguiapplication_p.h>
#if QT_CONFIG(accessibility)
diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp
index bd53963d..9ad12102 100644
--- a/src/quicktemplates2/qquickrangeslider.cpp
+++ b/src/quicktemplates2/qquickrangeslider.cpp
@@ -267,7 +267,7 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle)
const qreal oldImplicitHandleHeight = implicitHandleHeight();
QQuickControlPrivate::get(d->slider)->removeImplicitSizeListener(d->handle);
- delete d->handle;
+ QQuickControlPrivate::hideOldItem(d->handle);
d->handle = handle;
if (handle) {
diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp
index 1fb674b6..f4a459fa 100644
--- a/src/quicktemplates2/qquickslider.cpp
+++ b/src/quicktemplates2/qquickslider.cpp
@@ -579,7 +579,7 @@ void QQuickSlider::setHandle(QQuickItem *handle)
const qreal oldImplicitHandleHeight = implicitHandleHeight();
d->removeImplicitSizeListener(d->handle);
- delete d->handle;
+ QQuickControlPrivate::hideOldItem(d->handle);
d->handle = handle;
if (handle) {
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index 8b81e4e5..3482af8c 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -1126,7 +1126,7 @@ void QQuickSpinButton::setIndicator(QQuickItem *indicator)
QQuickSpinBox *spinBox = static_cast<QQuickSpinBox *>(parent());
QQuickSpinBoxPrivate::get(spinBox)->removeImplicitSizeListener(d->indicator);
- delete d->indicator;
+ QQuickControlPrivate::hideOldItem(d->indicator);
d->indicator = indicator;
if (indicator) {
diff --git a/src/quicktemplates2/qquickstackelement.cpp b/src/quicktemplates2/qquickstackelement.cpp
index 7ae5c495..4c14022a 100644
--- a/src/quicktemplates2/qquickstackelement.cpp
+++ b/src/quicktemplates2/qquickstackelement.cpp
@@ -44,6 +44,7 @@
#include <QtQml/private/qv4qobjectwrapper_p.h>
#include <QtQml/private/qqmlcomponent_p.h>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qqmlapiversion_p.h>
QT_BEGIN_NAMESPACE
@@ -210,7 +211,12 @@ void QQuickStackElement::initialize()
QV4::ScopedValue ipv(scope, properties.value());
QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item));
+#if Q_QML_PRIVATE_API_VERSION >= 6
+ RequiredProperties requiredPropertiesCurrentlyNotSupported;
+ QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv, requiredPropertiesCurrentlyNotSupported, item);
+#else
QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv);
+#endif
properties.clear();
}
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index 75dfba4e..56dc946d 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -634,7 +634,7 @@ void QQuickTextArea::setBackground(QQuickItem *background)
}
QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
- delete d->background;
+ QQuickControlPrivate::hideOldItem(d->background);
d->background = background;
if (background) {
diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp
index 025139f8..8fa04bd3 100644
--- a/src/quicktemplates2/qquicktextfield.cpp
+++ b/src/quicktemplates2/qquicktextfield.cpp
@@ -503,7 +503,7 @@ void QQuickTextField::setBackground(QQuickItem *background)
}
QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
- delete d->background;
+ QQuickControlPrivate::hideOldItem(d->background);
d->background = background;
if (background) {
diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml
index 634d70a8..2d5069b3 100644
--- a/tests/auto/controls/data/tst_combobox.qml
+++ b/tests/auto/controls/data/tst_combobox.qml
@@ -1854,6 +1854,22 @@ TestCase {
compare(closedSpy.count, 1)
}
+ function test_comboBoxSelectTextByMouse() {
+ let control = createTemporaryObject(comboBox, testCase,
+ { editable: true, selectTextByMouse: true, model: [ "Some text" ], width: parent.width })
+ verify(control)
+ waitForRendering(control)
+ control.forceActiveFocus()
+
+ // Position the text cursor at the beginning of the text.
+ mouseClick(control, control.leftPadding, control.height / 2)
+ // Select all of the text.
+ mousePress(control, control.leftPadding, control.height / 2)
+ mouseMove(control, control.leftPadding + control.contentItem.width, control.height / 2)
+ mouseRelease(control, control.leftPadding + control.contentItem.width, control.height / 2)
+ compare(control.contentItem.selectedText, "Some text")
+ }
+
// QTBUG-78885: When the edit text is changed on an editable ComboBox,
// and then that ComboBox loses focus, its currentIndex should change
// to the index of the edit text (assuming a match is found).
diff --git a/tests/auto/controls/data/tst_spinbox.qml b/tests/auto/controls/data/tst_spinbox.qml
index d3a0d8bb..22dbb352 100644
--- a/tests/auto/controls/data/tst_spinbox.qml
+++ b/tests/auto/controls/data/tst_spinbox.qml
@@ -658,4 +658,20 @@ TestCase {
compare(control.displayText, data.displayTexts[i])
}
}
+
+ Component {
+ id: overriddenSpinBox
+ SpinBox {
+ value: 50
+ up.indicator: Rectangle {
+ property string s: "this is the one"
+ }
+ }
+ }
+
+ function test_indicatorOverridden() {
+ var control = createTemporaryObject(overriddenSpinBox, testCase)
+ verify(control)
+ compare(control.up.indicator.s, "this is the one");
+ }
}
diff --git a/tests/auto/customization/data/styles/identified/AbstractButton.qml b/tests/auto/customization/data/styles/identified/AbstractButton.qml
index b9656f7a..cd2b5bdc 100644
--- a/tests/auto/customization/data/styles/identified/AbstractButton.qml
+++ b/tests/auto/customization/data/styles/identified/AbstractButton.qml
@@ -58,15 +58,18 @@ T.AbstractButton {
indicator: Item {
id: indicator
objectName: "abstractbutton-indicator-identified"
+ Accessible.name: objectName
}
contentItem: Item {
id: contentItem
objectName: "abstractbutton-contentItem-identified"
+ Accessible.name: objectName
}
background: Item {
id: background
objectName: "abstractbutton-background-identified"
+ Accessible.name: objectName
}
}
diff --git a/tests/auto/customization/tst_customization.cpp b/tests/auto/customization/tst_customization.cpp
index 41efc2a6..cce74b41 100644
--- a/tests/auto/customization/tst_customization.cpp
+++ b/tests/auto/customization/tst_customization.cpp
@@ -42,6 +42,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include "../shared/visualtestutil.h"
using namespace QQuickVisualTestUtil;
@@ -439,11 +440,36 @@ void tst_customization::override()
QVERIFY2(qt_createdQObjects()->isEmpty(), qPrintable("unexpectedly created: " + qt_createdQObjects->join(", ")));
if (!nonDeferred.isEmpty()) {
- for (QString delegate : qAsConst(delegates)) {
- if (!delegate.contains("-"))
- delegate.append("-" + nonDeferred);
- delegate.prepend(type.toLower() + "-");
- QVERIFY2(qt_destroyedQObjects()->removeOne(delegate), qPrintable(delegate + " was not destroyed as expected"));
+ // There were items for which deferred execution was not possible.
+ for (QString delegateName : qAsConst(delegates)) {
+ if (!delegateName.contains("-"))
+ delegateName.append("-" + nonDeferred);
+ delegateName.prepend(type.toLower() + "-");
+
+ const int delegateIndex = qt_destroyedQObjects()->indexOf(delegateName);
+ QVERIFY2(delegateIndex == -1, qPrintable(delegateName + " was unexpectedly destroyed"));
+
+ const auto controlChildren = control->children();
+ const auto childIt = std::find_if(controlChildren.constBegin(), controlChildren.constEnd(), [delegateName](const QObject *child) {
+ return child->objectName() == delegateName;
+ });
+ // We test other delegates (like the background) here, so make sure we don't end up with XPASSes by using the wrong delegate.
+ if (delegateName.contains(QLatin1String("handle"))) {
+ QEXPECT_FAIL("identified:RangeSlider", "For some reason, items that are belong to grouped properties fail here", Abort);
+ QEXPECT_FAIL("overidentified:RangeSlider", "For some reason, items that are belong to grouped properties fail here", Abort);
+ }
+ if (delegateName.contains(QLatin1String("indicator"))) {
+ QEXPECT_FAIL("identified:SpinBox", "For some reason, items that are belong to grouped properties fail here", Abort);
+ QEXPECT_FAIL("overidentified:SpinBox", "For some reason, items that are belong to grouped properties fail here", Abort);
+ }
+ QVERIFY2(childIt != controlChildren.constEnd(), qPrintable(QString::fromLatin1(
+ "Expected delegate \"%1\" to still be a QObject child of \"%2\"").arg(delegateName).arg(controlName)));
+
+ const auto *delegate = qobject_cast<QQuickItem*>(*childIt);
+ // Ensure that the item is hidden, etc.
+ QVERIFY(delegate);
+ QCOMPARE(delegate->isVisible(), false);
+ QCOMPARE(delegate->parentItem(), nullptr);
}
}
diff --git a/tests/auto/qquickpopup/data/tabFence.qml b/tests/auto/qquickpopup/data/tabFence.qml
new file mode 100644
index 00000000..2cf408e9
--- /dev/null
+++ b/tests/auto/qquickpopup/data/tabFence.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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.15
+import QtQuick.Layouts 1.15
+import QtQuick.Window 2.15
+import QtQuick.Controls 2.15
+
+ApplicationWindow {
+ width: 400
+ height: 400
+ objectName: "Rectangle"
+
+ property alias dialog: dialog
+ property alias outsideButton1: outsideButton1
+ property alias outsideButton2: outsideButton2
+ property alias dialogButton1: dialogButton1
+ property alias dialogButton2: dialogButton2
+
+ ColumnLayout {
+ Button {
+ id: outsideButton1
+ text: "Button1"
+ }
+ Button {
+ id: outsideButton2
+ text: "Button2"
+ }
+ }
+
+ Dialog {
+ id: dialog
+ objectName: "Dialog"
+ width: 200
+ height: 200
+ anchors.centerIn: parent
+ visible: true
+
+ ColumnLayout {
+ Button {
+ id: dialogButton1
+ text: "Button3"
+ }
+ Button {
+ id: dialogButton2
+ text: "Button4"
+ }
+ }
+ }
+}
diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp
index e852a61e..a3683d6c 100644
--- a/tests/auto/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp
@@ -93,6 +93,7 @@ private slots:
void countChanged();
void toolTipCrashOnClose();
void setOverlayParentToNull();
+ void tabFence();
};
void tst_QQuickPopup::initTestCase()
@@ -793,7 +794,9 @@ void tst_QQuickPopup::wheel_data()
static bool sendWheelEvent(QQuickItem *item, const QPoint &localPos, int degrees)
{
QQuickWindow *window = item->window();
- QWheelEvent wheelEvent(localPos, item->window()->mapToGlobal(localPos), QPoint(0, 0), QPoint(0, 8 * degrees), 0, Qt::Vertical, Qt::NoButton, 0);
+ QWheelEvent wheelEvent(localPos, item->window()->mapToGlobal(localPos),
+ QPoint(0, 0), QPoint(0, 8 * degrees),
+ 0, Qt::Vertical, Qt::NoButton, {});
QSpontaneKeyEvent::setSpontaneous(&wheelEvent);
return qGuiApp->notify(window, &wheelEvent);
}
@@ -1299,6 +1302,62 @@ void tst_QQuickPopup::setOverlayParentToNull()
// While nullifying the overlay parent doesn't make much sense, it shouldn't crash.
}
+void tst_QQuickPopup::tabFence()
+{
+ if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
+ QSKIP("This platform only allows tab focus for text controls");
+
+ QQuickApplicationHelper helper(this, "tabFence.qml");
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickPopup *popup = window->property("dialog").value<QQuickPopup*>();
+ QVERIFY(popup);
+ popup->open();
+ popup->setModal(true);
+
+ QQuickButton *outsideButton1 = window->property("outsideButton1").value<QQuickButton*>();
+ QVERIFY(outsideButton1);
+ QQuickButton *outsideButton2 = window->property("outsideButton2").value<QQuickButton*>();
+ QVERIFY(outsideButton2);
+ QQuickButton *dialogButton1 = window->property("dialogButton1").value<QQuickButton*>();
+ QVERIFY(dialogButton1);
+ QQuickButton *dialogButton2 = window->property("dialogButton2").value<QQuickButton*>();
+ QVERIFY(dialogButton2);
+
+ // When modal, focus loops between the two external buttons
+ outsideButton1->forceActiveFocus();
+ QVERIFY(outsideButton1->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(outsideButton2->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(outsideButton1->hasActiveFocus());
+
+ // Same thing for dialog's buttons
+ dialogButton1->forceActiveFocus();
+ QVERIFY(dialogButton1->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(dialogButton2->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(dialogButton1->hasActiveFocus());
+
+ popup->setModal(false);
+
+ // When not modal, focus goes in and out of the dialog
+ outsideButton1->forceActiveFocus();
+ QVERIFY(outsideButton1->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(outsideButton2->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(dialogButton1->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(dialogButton2->hasActiveFocus());
+ QTest::keyClick(window, Qt::Key_Tab);
+ QVERIFY(outsideButton1->hasActiveFocus());
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup)
#include "tst_qquickpopup.moc"