aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r--src/quicktemplates2/qquickabstractbutton.cpp256
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p.h36
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p_p.h16
-rw-r--r--src/quicktemplates2/qquickaction.cpp566
-rw-r--r--src/quicktemplates2/qquickaction_p.h122
-rw-r--r--src/quicktemplates2/qquickaction_p_p.h129
-rw-r--r--src/quicktemplates2/qquickactiongroup.cpp480
-rw-r--r--src/quicktemplates2/qquickactiongroup_p.h130
-rw-r--r--src/quicktemplates2/qquickapplicationwindow.cpp388
-rw-r--r--src/quicktemplates2/qquickapplicationwindow_p.h20
-rw-r--r--src/quicktemplates2/qquickbutton.cpp9
-rw-r--r--src/quicktemplates2/qquickbutton_p.h1
-rw-r--r--src/quicktemplates2/qquickbuttongroup.cpp46
-rw-r--r--src/quicktemplates2/qquickbuttongroup_p.h9
-rw-r--r--src/quicktemplates2/qquickcheckbox.cpp5
-rw-r--r--src/quicktemplates2/qquickcheckbox_p.h1
-rw-r--r--src/quicktemplates2/qquickcombobox.cpp53
-rw-r--r--src/quicktemplates2/qquickcombobox_p.h1
-rw-r--r--src/quicktemplates2/qquickcontainer.cpp104
-rw-r--r--src/quicktemplates2/qquickcontainer_p.h6
-rw-r--r--src/quicktemplates2/qquickcontainer_p_p.h8
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp550
-rw-r--r--src/quicktemplates2/qquickcontrol_p.h14
-rw-r--r--src/quicktemplates2/qquickcontrol_p_p.h38
-rw-r--r--src/quicktemplates2/qquickdelaybutton.cpp5
-rw-r--r--src/quicktemplates2/qquickdelaybutton_p.h1
-rw-r--r--src/quicktemplates2/qquickdialog.cpp141
-rw-r--r--src/quicktemplates2/qquickdialog_p.h23
-rw-r--r--src/quicktemplates2/qquickdialog_p_p.h10
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox.cpp52
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox_p.h5
-rw-r--r--src/quicktemplates2/qquickdrawer.cpp10
-rw-r--r--src/quicktemplates2/qquickdrawer_p_p.h8
-rw-r--r--src/quicktemplates2/qquickgroupbox.cpp5
-rw-r--r--src/quicktemplates2/qquickgroupbox_p.h1
-rw-r--r--src/quicktemplates2/qquickicon.cpp152
-rw-r--r--src/quicktemplates2/qquickicon_p.h104
-rw-r--r--src/quicktemplates2/qquickitemdelegate.cpp9
-rw-r--r--src/quicktemplates2/qquickitemdelegate_p.h1
-rw-r--r--src/quicktemplates2/qquicklabel.cpp138
-rw-r--r--src/quicktemplates2/qquicklabel_p.h10
-rw-r--r--src/quicktemplates2/qquicklabel_p_p.h29
-rw-r--r--src/quicktemplates2/qquickmenu.cpp999
-rw-r--r--src/quicktemplates2/qquickmenu_p.h61
-rw-r--r--src/quicktemplates2/qquickmenu_p_p.h45
-rw-r--r--src/quicktemplates2/qquickmenubar.cpp659
-rw-r--r--src/quicktemplates2/qquickmenubar_p.h126
-rw-r--r--src/quicktemplates2/qquickmenubar_p_p.h107
-rw-r--r--src/quicktemplates2/qquickmenubaritem.cpp185
-rw-r--r--src/quicktemplates2/qquickmenubaritem_p.h102
-rw-r--r--src/quicktemplates2/qquickmenubaritem_p_p.h85
-rw-r--r--src/quicktemplates2/qquickmenuitem.cpp133
-rw-r--r--src/quicktemplates2/qquickmenuitem_p.h17
-rw-r--r--src/quicktemplates2/qquickmenuitem_p_p.h83
-rw-r--r--src/quicktemplates2/qquickmenuseparator.cpp8
-rw-r--r--src/quicktemplates2/qquickmenuseparator_p.h2
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp302
-rw-r--r--src/quicktemplates2/qquickoverlay_p.h35
-rw-r--r--src/quicktemplates2/qquickoverlay_p_p.h9
-rw-r--r--src/quicktemplates2/qquickpalette.cpp326
-rw-r--r--src/quicktemplates2/qquickpalette_p.h163
-rw-r--r--src/quicktemplates2/qquickpopup.cpp250
-rw-r--r--src/quicktemplates2/qquickpopup_p.h32
-rw-r--r--src/quicktemplates2/qquickpopup_p_p.h11
-rw-r--r--src/quicktemplates2/qquickpopupitem.cpp28
-rw-r--r--src/quicktemplates2/qquickpopupitem_p_p.h5
-rw-r--r--src/quicktemplates2/qquickradiobutton.cpp5
-rw-r--r--src/quicktemplates2/qquickradiobutton_p.h1
-rw-r--r--src/quicktemplates2/qquickrangeslider.cpp32
-rw-r--r--src/quicktemplates2/qquickrangeslider_p.h11
-rw-r--r--src/quicktemplates2/qquickscrollbar.cpp32
-rw-r--r--src/quicktemplates2/qquickscrollbar_p.h7
-rw-r--r--src/quicktemplates2/qquickscrollindicator.cpp32
-rw-r--r--src/quicktemplates2/qquickscrollindicator_p.h7
-rw-r--r--src/quicktemplates2/qquickshortcutcontext.cpp9
-rw-r--r--src/quicktemplates2/qquickslider.cpp32
-rw-r--r--src/quicktemplates2/qquickslider_p.h7
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp86
-rw-r--r--src/quicktemplates2/qquickspinbox_p.h9
-rw-r--r--src/quicktemplates2/qquickstackview.cpp53
-rw-r--r--src/quicktemplates2/qquickstackview_p.cpp11
-rw-r--r--src/quicktemplates2/qquickstackview_p.h9
-rw-r--r--src/quicktemplates2/qquickstackview_p_p.h1
-rw-r--r--src/quicktemplates2/qquickswipedelegate_p.h2
-rw-r--r--src/quicktemplates2/qquickswipeview.cpp231
-rw-r--r--src/quicktemplates2/qquickswipeview_p.h10
-rw-r--r--src/quicktemplates2/qquickswitch.cpp6
-rw-r--r--src/quicktemplates2/qquickswitch_p.h2
-rw-r--r--src/quicktemplates2/qquicktabbar.cpp155
-rw-r--r--src/quicktemplates2/qquicktabbar_p.h32
-rw-r--r--src/quicktemplates2/qquicktabbutton.cpp5
-rw-r--r--src/quicktemplates2/qquicktabbutton_p.h1
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp156
-rw-r--r--src/quicktemplates2/qquicktextarea_p.h10
-rw-r--r--src/quicktemplates2/qquicktextarea_p_p.h32
-rw-r--r--src/quicktemplates2/qquicktextfield.cpp150
-rw-r--r--src/quicktemplates2/qquicktextfield_p.h10
-rw-r--r--src/quicktemplates2/qquicktextfield_p_p.h33
-rw-r--r--src/quicktemplates2/qquicktoolbar.cpp5
-rw-r--r--src/quicktemplates2/qquicktoolbar_p.h2
-rw-r--r--src/quicktemplates2/qquicktoolbutton.cpp9
-rw-r--r--src/quicktemplates2/qquicktoolbutton_p.h1
-rw-r--r--src/quicktemplates2/qquicktoolseparator.cpp5
-rw-r--r--src/quicktemplates2/qquicktoolseparator_p.h2
-rw-r--r--src/quicktemplates2/qquicktooltip.cpp7
-rw-r--r--src/quicktemplates2/qquicktooltip_p.h1
-rw-r--r--src/quicktemplates2/qquicktumbler.cpp178
-rw-r--r--src/quicktemplates2/qquicktumbler_p.h10
-rw-r--r--src/quicktemplates2/qquicktumbler_p_p.h37
-rw-r--r--src/quicktemplates2/qtquicktemplates2global_p.h1
-rw-r--r--src/quicktemplates2/quicktemplates2.pri15
111 files changed, 7942 insertions, 975 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index 45ade7bb..a7fe720a 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -37,10 +37,15 @@
#include "qquickabstractbutton_p.h"
#include "qquickabstractbutton_p_p.h"
#include "qquickbuttongroup_p.h"
+#include "qquickaction_p.h"
+#include "qquickaction_p_p.h"
+#include "qquickshortcutcontext_p_p.h"
#include "qquickdeferredexecute_p_p.h"
#include <QtGui/qstylehints.h>
#include <QtGui/qguiapplication.h>
+#include <QtGui/private/qshortcutmap_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQml/qqmllist.h>
@@ -125,9 +130,14 @@ QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate()
holdTimer(0),
delayTimer(0),
repeatTimer(0),
+#if QT_CONFIG(shortcut)
+ shortcutId(0),
+#endif
pressButtons(Qt::NoButton),
indicator(nullptr),
- group(nullptr)
+ group(nullptr),
+ display(QQuickAbstractButton::TextBesideIcon),
+ action(nullptr)
{
}
@@ -174,7 +184,7 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point)
if (wasPressed) {
emit q->released();
if (!wasHeld)
- emit q->clicked();
+ trigger();
} else {
emit q->canceled();
}
@@ -250,6 +260,46 @@ void QQuickAbstractButtonPrivate::stopPressRepeat()
}
}
+#if QT_CONFIG(shortcut)
+void QQuickAbstractButtonPrivate::grabShortcut()
+{
+ Q_Q(QQuickAbstractButton);
+ if (shortcut.isEmpty())
+ return;
+
+ shortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(q, shortcut, Qt::WindowShortcut, QQuickShortcutContext::matcher);
+
+ if (!q->isEnabled())
+ QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(false, shortcutId, q);
+}
+
+void QQuickAbstractButtonPrivate::ungrabShortcut()
+{
+ Q_Q(QQuickAbstractButton);
+ if (!shortcutId)
+ return;
+
+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(shortcutId, q);
+ shortcutId = 0;
+}
+#endif
+
+void QQuickAbstractButtonPrivate::click()
+{
+ Q_Q(QQuickAbstractButton);
+ if (effectiveEnable)
+ emit q->clicked();
+}
+
+void QQuickAbstractButtonPrivate::trigger()
+{
+ Q_Q(QQuickAbstractButton);
+ if (action && action->isEnabled())
+ QQuickActionPrivate::get(action)->trigger(q, false);
+ else if (effectiveEnable)
+ emit q->clicked();
+}
+
void QQuickAbstractButtonPrivate::toggle(bool value)
{
Q_Q(QQuickAbstractButton);
@@ -345,6 +395,7 @@ QQuickAbstractButton::~QQuickAbstractButton()
Q_D(QQuickAbstractButton);
if (d->group)
d->group->removeButton(this);
+ d->ungrabShortcut();
}
/*!
@@ -355,7 +406,7 @@ QQuickAbstractButton::~QQuickAbstractButton()
\note The text is used for accessibility purposes, so it makes sense to
set a textual description even if the content item is an image.
- \sa {Control::contentItem}{contentItem}
+ \sa icon, display, {Control::contentItem}{contentItem}
*/
QString QQuickAbstractButton::text() const
{
@@ -369,8 +420,12 @@ void QQuickAbstractButton::setText(const QString &text)
if (d->text == text)
return;
+#if QT_CONFIG(shortcut)
+ setShortcut(QKeySequence::mnemonic(text));
+#endif
+
d->text = text;
- setAccessibleName(text);
+ setAccessibleName(d->text);
buttonChange(ButtonTextChange);
emit textChanged();
}
@@ -468,6 +523,8 @@ void QQuickAbstractButton::setChecked(bool checked)
setCheckable(true);
d->checked = checked;
+ if (d->action)
+ d->action->setChecked(checked);
setAccessibleProperty("checked", checked);
buttonChange(ButtonCheckedChange);
emit checkedChanged();
@@ -501,6 +558,8 @@ void QQuickAbstractButton::setCheckable(bool checkable)
return;
d->checkable = checkable;
+ if (d->action)
+ d->action->setCheckable(checkable);
setAccessibleProperty("checkable", checkable);
buttonChange(ButtonCheckableChange);
emit checkableChanged();
@@ -584,6 +643,162 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
}
/*!
+ \qmlpropertygroup QtQuick.Controls::AbstractButton::icon
+ \qmlproperty string QtQuick.Controls::AbstractButton::icon.name
+ \qmlproperty url QtQuick.Controls::AbstractButton::icon.source
+ \qmlproperty int QtQuick.Controls::AbstractButton::icon.width
+ \qmlproperty int QtQuick.Controls::AbstractButton::icon.height
+ \qmlproperty color QtQuick.Controls::AbstractButton::icon.color
+
+ This property group was added in QtQuick.Controls 2.3.
+
+ \include qquickicon.qdocinc grouped-properties
+
+ \sa text, display, {Icons in Qt Quick Controls 2}
+*/
+
+QQuickIcon QQuickAbstractButton::icon() const
+{
+ Q_D(const QQuickAbstractButton);
+ return d->icon;
+}
+
+void QQuickAbstractButton::setIcon(const QQuickIcon &icon)
+{
+ Q_D(QQuickAbstractButton);
+ if (d->icon == icon)
+ return;
+
+ d->icon = icon;
+ emit iconChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty enumeration QtQuick.Controls::AbstractButton::display
+
+ This property determines how the \l icon and \l text are displayed within
+ the button.
+
+ \table
+ \header \li Display \li Result
+ \row \li \c AbstractButton.IconOnly \li \image qtquickcontrols2-button-icononly.png
+ \row \li \c AbstractButton.TextOnly \li \image qtquickcontrols2-button-textonly.png
+ \row \li \c AbstractButton.TextBesideIcon \li \image qtquickcontrols2-button-textbesideicon.png
+ \endtable
+
+ \sa {Control::}{spacing}, {Control::}{padding}
+*/
+QQuickAbstractButton::Display QQuickAbstractButton::display() const
+{
+ Q_D(const QQuickAbstractButton);
+ return d->display;
+}
+
+void QQuickAbstractButton::setDisplay(Display display)
+{
+ Q_D(QQuickAbstractButton);
+ if (display == d->display)
+ return;
+
+ d->display = display;
+ emit displayChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Action QtQuick.Controls::AbstractButton::action
+
+ This property holds the button action.
+
+ \sa Action
+*/
+QQuickAction *QQuickAbstractButton::action() const
+{
+ Q_D(const QQuickAbstractButton);
+ return d->action;
+}
+
+void QQuickAbstractButton::setAction(QQuickAction *action)
+{
+ Q_D(QQuickAbstractButton);
+ if (d->action == action)
+ return;
+
+ if (QQuickAction *oldAction = d->action.data()) {
+ QQuickActionPrivate::get(oldAction)->unregisterItem(this);
+ QObjectPrivate::disconnect(oldAction, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
+
+ disconnect(oldAction, &QQuickAction::textChanged, this, &QQuickAbstractButton::setText);
+ disconnect(oldAction, &QQuickAction::iconChanged, this, &QQuickAbstractButton::setIcon);
+ disconnect(oldAction, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
+ disconnect(oldAction, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
+ disconnect(oldAction, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
+ }
+
+ if (action) {
+ QQuickActionPrivate::get(action)->registerItem(this);
+ QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickAbstractButtonPrivate::click);
+
+ connect(action, &QQuickAction::textChanged, this, &QQuickAbstractButton::setText);
+ connect(action, &QQuickAction::iconChanged, this, &QQuickAbstractButton::setIcon);
+ connect(action, &QQuickAction::checkedChanged, this, &QQuickAbstractButton::setChecked);
+ connect(action, &QQuickAction::checkableChanged, this, &QQuickAbstractButton::setCheckable);
+ connect(action, &QQuickAction::enabledChanged, this, &QQuickItem::setEnabled);
+
+ QQuickIcon actionIcon = action->icon();
+
+ QString name = actionIcon.name();
+ if (!name.isEmpty())
+ d->icon.setName(name);
+
+ QUrl source = actionIcon.source();
+ if (!source.isEmpty())
+ d->icon.setSource(source);
+
+ int width = actionIcon.width();
+ if (width > 0)
+ d->icon.setWidth(width);
+
+ int height = actionIcon.height();
+ if (height)
+ d->icon.setHeight(height);
+
+ QColor color = actionIcon.color();
+ if (color != Qt::transparent)
+ d->icon.setColor(color);
+
+ setText(action->text());
+ setChecked(action->isChecked());
+ setCheckable(action->isCheckable());
+ setEnabled(action->isEnabled());
+ }
+
+ d->action = action;
+ emit actionChanged();
+}
+
+#if QT_CONFIG(shortcut)
+QKeySequence QQuickAbstractButton::shortcut() const
+{
+ Q_D(const QQuickAbstractButton);
+ return d->shortcut;
+}
+
+void QQuickAbstractButton::setShortcut(const QKeySequence &shortcut)
+{
+ Q_D(QQuickAbstractButton);
+ if (d->shortcut == shortcut)
+ return;
+
+ d->ungrabShortcut();
+ d->shortcut = shortcut;
+ if (isVisible())
+ d->grabShortcut();
+}
+#endif
+
+/*!
\qmlmethod void QtQuick.Controls::AbstractButton::toggle()
Toggles the checked state of the button.
@@ -601,6 +816,21 @@ void QQuickAbstractButton::componentComplete()
QQuickControl::componentComplete();
}
+bool QQuickAbstractButton::event(QEvent *event)
+{
+ Q_D(QQuickAbstractButton);
+#if QT_CONFIG(shortcut)
+ if (event->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
+ if (se->shortcutId() == d->shortcutId) {
+ d->trigger();
+ return true;
+ }
+ }
+#endif
+ return QQuickControl::event(event);
+}
+
void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
{
Q_D(QQuickAbstractButton);
@@ -634,7 +864,7 @@ void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
nextCheckState();
emit released();
- emit clicked();
+ d->trigger();
if (d->autoRepeat)
d->stopPressRepeat();
@@ -667,11 +897,25 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event)
d->startPressRepeat();
} else if (event->timerId() == d->repeatTimer) {
emit released();
- emit clicked();
+ d->trigger();
emit pressed();
}
}
+void QQuickAbstractButton::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ Q_D(QQuickAbstractButton);
+ QQuickControl::itemChange(change, value);
+#if QT_CONFIG(shortcut)
+ if (change == ItemVisibleHasChanged) {
+ if (value.boolValue)
+ d->grabShortcut();
+ else
+ d->ungrabShortcut();
+ }
+#endif
+}
+
void QQuickAbstractButton::buttonChange(ButtonChange change)
{
Q_D(QQuickAbstractButton);
diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h
index a1210567..cc3cce91 100644
--- a/src/quicktemplates2/qquickabstractbutton_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p.h
@@ -49,9 +49,11 @@
//
#include <QtQuickTemplates2/private/qquickcontrol_p.h>
+#include <QtQuickTemplates2/private/qquickicon_p.h>
QT_BEGIN_NAMESPACE
+class QQuickAction;
class QQuickAbstractButtonPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickControl
@@ -64,6 +66,10 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButton : public QQuickContr
Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL)
Q_PROPERTY(bool autoExclusive READ autoExclusive WRITE setAutoExclusive NOTIFY autoExclusiveChanged FINAL)
Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL REVISION 3)
+ Q_PROPERTY(Display display READ display WRITE setDisplay NOTIFY displayChanged FINAL REVISION 3)
+ Q_PROPERTY(QQuickAction *action READ action WRITE setAction NOTIFY actionChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background,contentItem,indicator")
public:
@@ -95,6 +101,29 @@ public:
QQuickItem *indicator() const;
void setIndicator(QQuickItem *indicator);
+ // 2.3 (Qt 5.10)
+ QQuickIcon icon() const;
+ void setIcon(const QQuickIcon &icon);
+
+ enum Display {
+ IconOnly,
+ TextOnly,
+ TextBesideIcon,
+ TextUnderIcon
+ };
+ Q_ENUM(Display)
+
+ Display display() const;
+ void setDisplay(Display display);
+
+ QQuickAction *action() const;
+ void setAction(QQuickAction *action);
+
+#if QT_CONFIG(shortcut)
+ QKeySequence shortcut() const;
+ void setShortcut(const QKeySequence &shortcut);
+#endif
+
public Q_SLOTS:
void toggle();
@@ -114,12 +143,17 @@ Q_SIGNALS:
void indicatorChanged();
// 2.2 (Qt 5.9)
Q_REVISION(2) void toggled();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void iconChanged();
+ Q_REVISION(3) void displayChanged();
+ Q_REVISION(3) void actionChanged();
protected:
QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent);
void componentComplete() override;
+ bool event(QEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
@@ -127,6 +161,8 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *event) override;
void timerEvent(QTimerEvent *event) override;
+ void itemChange(ItemChange change, const ItemChangeData &value) override;
+
enum ButtonChange {
ButtonAutoRepeatChange,
ButtonCheckedChange,
diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h
index 6634971e..2436d242 100644
--- a/src/quicktemplates2/qquickabstractbutton_p_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p_p.h
@@ -50,9 +50,11 @@
#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtGui/qkeysequence.h>
QT_BEGIN_NAMESPACE
+class QQuickAction;
class QQuickButtonGroup;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAbstractButtonPrivate : public QQuickControlPrivate
@@ -80,9 +82,16 @@ public:
void startPressRepeat();
void stopPressRepeat();
+#if QT_CONFIG(shortcut)
+ void grabShortcut();
+ void ungrabShortcut();
+#endif
+
QQuickAbstractButton *findCheckedButton() const;
QList<QQuickAbstractButton *> findExclusiveButtons() const;
+ void click();
+ void trigger();
void toggle(bool value);
void executeIndicator(bool complete = false);
@@ -100,10 +109,17 @@ public:
int holdTimer;
int delayTimer;
int repeatTimer;
+#if QT_CONFIG(shortcut)
+ int shortcutId;
+ QKeySequence shortcut;
+#endif
+ QQuickIcon icon;
QPointF pressPoint;
Qt::MouseButtons pressButtons;
QQuickDeferredPointer<QQuickItem> indicator;
QQuickButtonGroup *group;
+ QQuickAbstractButton::Display display;
+ QPointer<QQuickAction> action;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickaction.cpp b/src/quicktemplates2/qquickaction.cpp
new file mode 100644
index 00000000..fd899d0b
--- /dev/null
+++ b/src/quicktemplates2/qquickaction.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickaction_p.h"
+#include "qquickaction_p_p.h"
+#include "qquickactiongroup_p.h"
+#include "qquickshortcutcontext_p_p.h"
+
+#include <QtGui/qevent.h>
+#include <QtGui/private/qshortcutmap_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Action
+ \inherits QtObject
+ \instantiates QQuickAction
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \ingroup utilities
+ \brief Abstract user interface action.
+
+ Action represents an abstract user interface action that can have shortcuts
+ and can be assigned to menu items and toolbar buttons.
+
+ Actions may contain \l text, an \l icon, and a \l shortcut. Actions are normally
+ \l triggered by the user via menu items, toolbar buttons, or keyboard shortcuts.
+ A \l checkable Action toggles its \l checked state when triggered.
+
+ \snippet qtquickcontrols2-action.qml action
+
+ Action is commonly used to implement application commands that can be invoked
+ via menu items, toolbar buttons, and keyboard shortcuts. Since the user expects
+ the commands to be performed in the same way, regardless of the user interface
+ used, it is useful to represent the commands as shareable actions.
+
+ Action can be also used to separate the logic and the visual presentation. For
+ example, when declaring buttons and menu items in \c .ui.qml files, actions can
+ be declared elsewhere and assigned from the outside.
+
+ \snippet qtquickcontrols2-action.qml toolbutton
+
+ When an action is paired with buttons and menu items, the \c enabled, \c checkable,
+ and \c checked states are synced automatically. For example, in a word processor,
+ if the user clicks a "Bold" toolbar button, the "Bold" menu item will automatically
+ be checked. Buttons and menu items get their \c text and \c icon from the action by
+ default. An action-specific \c text or \c icon can be overridden for a specific
+ control by specifying \c text or \c icon directly on the control.
+
+ \snippet qtquickcontrols2-action.qml menuitem
+
+ Since Action presents a user interface action, it is intended to be assigned to
+ a \l MenuItem, \l ToolButton, or any other control that inherits \l AbstractButton.
+ For keyboard shortcuts, the simpler \l Shortcut type is more appropriate.
+
+ \sa MenuItem, ToolButton, Shortcut
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::Action::toggled(QtObject source)
+
+ This signal is emitted when the action is toggled. The \a source argument
+ identifies the object that toggled the action.
+
+ For example, if the action is assigned to a menu item and a toolbar button, the
+ action is toggled when the control is toggled, the shortcut is activated, or
+ when \l toggle() is called directly.
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::Action::triggered(QtObject source)
+
+ This signal is emitted when the action is triggered. The \a source argument
+ identifies the object that triggered the action.
+
+ For example, if the action is assigned to a menu item and a toolbar button, the
+ action is triggered when the control is clicked, the shortcut is activated, or
+ when \l trigger() is called directly.
+*/
+
+static QKeySequence variantToKeySequence(const QVariant &var)
+{
+ if (var.type() == QVariant::Int)
+ return QKeySequence(static_cast<QKeySequence::StandardKey>(var.toInt()));
+ return QKeySequence::fromString(var.toString());
+}
+
+QQuickActionPrivate::ShortcutEntry::ShortcutEntry(QObject *target)
+ : m_shortcutId(0),
+ m_target(target)
+{
+}
+
+QQuickActionPrivate::ShortcutEntry::~ShortcutEntry()
+{
+ ungrab();
+}
+
+QObject *QQuickActionPrivate::ShortcutEntry::target() const
+{
+ return m_target;
+}
+
+int QQuickActionPrivate::ShortcutEntry::shortcutId() const
+{
+ return m_shortcutId;
+}
+
+void QQuickActionPrivate::ShortcutEntry::grab(const QKeySequence &shortcut, bool enabled)
+{
+ if (shortcut.isEmpty())
+ return;
+
+ Qt::ShortcutContext context = Qt::WindowShortcut; // TODO
+ m_shortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(m_target, shortcut, context, QQuickShortcutContext::matcher);
+
+ if (!enabled)
+ QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(false, m_shortcutId, m_target);
+}
+
+void QQuickActionPrivate::ShortcutEntry::ungrab()
+{
+ if (!m_shortcutId)
+ return;
+
+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_shortcutId, m_target);
+ m_shortcutId = 0;
+}
+
+void QQuickActionPrivate::ShortcutEntry::setEnabled(bool enabled)
+{
+ if (!m_shortcutId)
+ return;
+
+ QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enabled, m_shortcutId, m_target);
+}
+
+QQuickActionPrivate::QQuickActionPrivate()
+ : explicitEnabled(false),
+ enabled(true),
+ checked(false),
+ checkable(false),
+ defaultShortcutEntry(nullptr),
+ group(nullptr)
+{
+}
+
+QVariant QQuickActionPrivate::shortcut() const
+{
+ return vshortcut;
+}
+
+void QQuickActionPrivate::setShortcut(const QVariant &var)
+{
+ Q_Q(QQuickAction);
+ if (vshortcut == var)
+ return;
+
+ defaultShortcutEntry->ungrab();
+ for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries))
+ entry->ungrab();
+
+ vshortcut = var.toString();
+ keySequence = variantToKeySequence(var);
+
+ defaultShortcutEntry->grab(keySequence, enabled);
+ for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries))
+ entry->grab(keySequence, enabled);
+
+ emit q->shortcutChanged(keySequence);
+}
+
+void QQuickActionPrivate::setEnabled(bool enable)
+{
+ Q_Q(QQuickAction);
+ if (enabled == enable)
+ return;
+
+ enabled = enable;
+
+ defaultShortcutEntry->setEnabled(enable);
+ for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries))
+ entry->setEnabled(enable);
+
+ emit q->enabledChanged(enable);
+}
+
+bool QQuickActionPrivate::watchItem(QQuickItem *item)
+{
+ Q_Q(QQuickAction);
+ if (!item)
+ return false;
+
+ item->installEventFilter(q);
+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed);
+ return true;
+}
+
+bool QQuickActionPrivate::unwatchItem(QQuickItem *item)
+{
+ Q_Q(QQuickAction);
+ if (!item)
+ return false;
+
+ item->removeEventFilter(q);
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed);
+ return true;
+}
+
+void QQuickActionPrivate::registerItem(QQuickItem *item)
+{
+ if (!watchItem(item))
+ return;
+
+ QQuickActionPrivate::ShortcutEntry *entry = new QQuickActionPrivate::ShortcutEntry(item);
+ if (item->isVisible())
+ entry->grab(keySequence, enabled);
+ shortcutEntries += entry;
+
+ updateDefaultShortcutEntry();
+}
+
+void QQuickActionPrivate::unregisterItem(QQuickItem *item)
+{
+ QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(item);
+ if (!entry || !unwatchItem(item))
+ return;
+
+ shortcutEntries.removeOne(entry);
+ delete entry;
+
+ updateDefaultShortcutEntry();
+}
+
+void QQuickActionPrivate::itemVisibilityChanged(QQuickItem *item)
+{
+ QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(item);
+ if (!entry)
+ return;
+
+ if (item->isVisible())
+ entry->grab(keySequence, enabled);
+ else
+ entry->ungrab();
+
+ updateDefaultShortcutEntry();
+}
+
+void QQuickActionPrivate::itemDestroyed(QQuickItem *item)
+{
+ unregisterItem(item);
+}
+
+bool QQuickActionPrivate::handleShortcutEvent(QObject *object, QShortcutEvent *event)
+{
+ Q_Q(QQuickAction);
+ if (event->key() != keySequence)
+ return false;
+
+ QQuickActionPrivate::ShortcutEntry *entry = findShortcutEntry(object);
+ if (!entry || event->shortcutId() != entry->shortcutId())
+ return false;
+
+ q->trigger(entry->target());
+ return true;
+}
+
+QQuickActionPrivate::ShortcutEntry *QQuickActionPrivate::findShortcutEntry(QObject *target) const
+{
+ Q_Q(const QQuickAction);
+ if (target == q)
+ return defaultShortcutEntry;
+ for (QQuickActionPrivate::ShortcutEntry *entry : shortcutEntries) {
+ if (entry->target() == target)
+ return entry;
+ }
+ return nullptr;
+}
+
+void QQuickActionPrivate::updateDefaultShortcutEntry()
+{
+ bool hasActiveShortcutEntries = false;
+ for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(shortcutEntries)) {
+ if (entry->shortcutId()) {
+ hasActiveShortcutEntries = true;
+ break;
+ }
+ }
+
+ if (hasActiveShortcutEntries)
+ defaultShortcutEntry->ungrab();
+ else if (!defaultShortcutEntry->shortcutId())
+ defaultShortcutEntry->grab(keySequence, enabled);
+}
+
+QQuickAction::QQuickAction(QObject *parent)
+ : QObject(*(new QQuickActionPrivate), parent)
+{
+ Q_D(QQuickAction);
+ d->defaultShortcutEntry = new QQuickActionPrivate::ShortcutEntry(this);
+}
+
+QQuickAction::~QQuickAction()
+{
+ Q_D(QQuickAction);
+ if (d->group)
+ d->group->removeAction(this);
+
+ for (QQuickActionPrivate::ShortcutEntry *entry : qAsConst(d->shortcutEntries))
+ d->unwatchItem(qobject_cast<QQuickItem *>(entry->target()));
+
+ qDeleteAll(d->shortcutEntries);
+ delete d->defaultShortcutEntry;
+}
+
+/*!
+ \qmlproperty string QtQuick.Controls::Action::text
+
+ This property holds a textual description of the action.
+*/
+QString QQuickAction::text() const
+{
+ Q_D(const QQuickAction);
+ return d->text;
+}
+
+void QQuickAction::setText(const QString &text)
+{
+ Q_D(QQuickAction);
+ if (d->text == text)
+ return;
+
+ d->text = text;
+ emit textChanged(text);
+}
+
+/*!
+ \qmlpropertygroup QtQuick.Controls::Action::icon
+ \qmlproperty string QtQuick.Controls::Action::icon.name
+ \qmlproperty url QtQuick.Controls::Action::icon.source
+ \qmlproperty int QtQuick.Controls::Action::icon.width
+ \qmlproperty int QtQuick.Controls::Action::icon.height
+ \qmlproperty color QtQuick.Controls::Action::icon.color
+
+ \include qquickicon.qdocinc grouped-properties
+*/
+QQuickIcon QQuickAction::icon() const
+{
+ Q_D(const QQuickAction);
+ return d->icon;
+}
+
+void QQuickAction::setIcon(const QQuickIcon &icon)
+{
+ Q_D(QQuickAction);
+ if (d->icon == icon)
+ return;
+
+ d->icon = icon;
+ emit iconChanged(icon);
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::Action::enabled
+
+ This property holds whether the action is enabled. The default value is \c true.
+*/
+bool QQuickAction::isEnabled() const
+{
+ Q_D(const QQuickAction);
+ return d->enabled && (!d->group || d->group->isEnabled());
+}
+
+void QQuickAction::setEnabled(bool enabled)
+{
+ Q_D(QQuickAction);
+ d->explicitEnabled = true;
+ d->setEnabled(enabled);
+}
+
+void QQuickAction::resetEnabled()
+{
+ Q_D(QQuickAction);
+ if (!d->explicitEnabled)
+ return;
+
+ d->explicitEnabled = false;
+ d->setEnabled(true);
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::Action::checked
+
+ This property holds whether the action is checked.
+
+ \sa checkable
+*/
+bool QQuickAction::isChecked() const
+{
+ Q_D(const QQuickAction);
+ return d->checked;
+}
+
+void QQuickAction::setChecked(bool checked)
+{
+ Q_D(QQuickAction);
+ if (d->checked == checked)
+ return;
+
+ d->checked = checked;
+ emit checkedChanged(checked);
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::Action::checkable
+
+ This property holds whether the action is checkable. The default value is \c false.
+
+ A checkable action toggles between checked (on) and unchecked (off) when triggered.
+
+ \sa checked
+*/
+bool QQuickAction::isCheckable() const
+{
+ Q_D(const QQuickAction);
+ return d->checkable;
+}
+
+void QQuickAction::setCheckable(bool checkable)
+{
+ Q_D(QQuickAction);
+ if (d->checkable == checkable)
+ return;
+
+ d->checkable = checkable;
+ emit checkableChanged(checkable);
+}
+
+/*!
+ \qmlproperty keysequence QtQuick.Controls::Action::shortcut
+
+ This property holds the action's shortcut. The key sequence can be set
+ to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts},
+ or it can be described with a string containing a sequence of up to four
+ key presses that are needed to trigger the shortcut.
+
+ \code
+ Action {
+ sequence: "Ctrl+E,Ctrl+W"
+ onTriggered: edit.wrapMode = TextEdit.Wrap
+ }
+ \endcode
+*/
+QKeySequence QQuickAction::shortcut() const
+{
+ Q_D(const QQuickAction);
+ return d->keySequence;
+}
+
+void QQuickAction::setShortcut(const QKeySequence &shortcut)
+{
+ Q_D(QQuickAction);
+ d->setShortcut(shortcut.toString());
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::Action::toggle(QtObject source = null)
+
+ Toggles the action and emits \l toggled() if enabled, with an optional \a source object defined.
+*/
+void QQuickAction::toggle(QObject *source)
+{
+ Q_D(QQuickAction);
+ if (!d->enabled)
+ return;
+
+ if (d->checkable)
+ setChecked(!d->checked);
+
+ emit toggled(source);
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::Action::trigger(QtObject source = null)
+
+ Triggers the action and emits \l triggered() if enabled, with an optional \a source object defined.
+*/
+void QQuickAction::trigger(QObject *source)
+{
+ Q_D(QQuickAction);
+ d->trigger(source, true);
+}
+
+void QQuickActionPrivate::trigger(QObject* source, bool doToggle)
+{
+ Q_Q(QQuickAction);
+ if (!enabled)
+ return;
+
+ QPointer<QObject> guard = q;
+ // the checked action of an exclusive group cannot be unchecked
+ if (checkable && (!checked || !group || !group->isExclusive() || group->checkedAction() != q)) {
+ if (doToggle)
+ q->toggle(source);
+ else
+ emit q->toggled(source);
+ }
+
+ if (!guard.isNull())
+ emit q->triggered(source);
+}
+
+bool QQuickAction::event(QEvent *event)
+{
+ Q_D(QQuickAction);
+ if (event->type() != QEvent::Shortcut)
+ return QObject::event(event);
+ return d->handleShortcutEvent(this, static_cast<QShortcutEvent *>(event));
+}
+
+bool QQuickAction::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickAction);
+ if (event->type() != QEvent::Shortcut)
+ return false;
+ return d->handleShortcutEvent(object, static_cast<QShortcutEvent *>(event));
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickaction_p.cpp"
diff --git a/src/quicktemplates2/qquickaction_p.h b/src/quicktemplates2/qquickaction_p.h
new file mode 100644
index 00000000..ce989bed
--- /dev/null
+++ b/src/quicktemplates2/qquickaction_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKACTION_P_H
+#define QQUICKACTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+#include <QtQuickTemplates2/private/qquickicon_p.h>
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickIcon;
+class QQuickActionPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickAction : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL)
+ Q_PROPERTY(QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged RESET resetEnabled FINAL)
+ Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged FINAL)
+ Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL)
+ Q_PRIVATE_PROPERTY(QQuickAction::d_func(), QVariant shortcut READ shortcut WRITE setShortcut NOTIFY shortcutChanged FINAL)
+
+public:
+ explicit QQuickAction(QObject *parent = nullptr);
+ ~QQuickAction();
+
+ QString text() const;
+ void setText(const QString &text);
+
+ QQuickIcon icon() const;
+ void setIcon(const QQuickIcon &icon);
+
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+ void resetEnabled();
+
+ bool isChecked() const;
+ void setChecked(bool checked);
+
+ bool isCheckable() const;
+ void setCheckable(bool checkable);
+
+ QKeySequence shortcut() const;
+ void setShortcut(const QKeySequence &shortcut);
+
+public Q_SLOTS:
+ void toggle(QObject *source = nullptr);
+ void trigger(QObject *source = nullptr);
+
+Q_SIGNALS:
+ void textChanged(const QString &text);
+ void iconChanged(const QQuickIcon &icon);
+ void enabledChanged(bool enabled);
+ void checkedChanged(bool checked);
+ void checkableChanged(bool checkable);
+ void shortcutChanged(const QKeySequence &shortcut);
+
+ void toggled(QObject *source = nullptr);
+ void triggered(QObject *source = nullptr);
+
+protected:
+ bool event(QEvent *event) override;
+ bool eventFilter(QObject *object, QEvent *event) override;
+
+private:
+ Q_DISABLE_COPY(QQuickAction)
+ Q_DECLARE_PRIVATE(QQuickAction)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickAction)
+
+#endif // QQUICKACTION_P_H
diff --git a/src/quicktemplates2/qquickaction_p_p.h b/src/quicktemplates2/qquickaction_p_p.h
new file mode 100644
index 00000000..331bcb65
--- /dev/null
+++ b/src/quicktemplates2/qquickaction_p_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKACTION_P_P_H
+#define QQUICKACTION_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qkeysequence.h>
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShortcutEvent;
+class QQuickActionGroup;
+
+class QQuickActionPrivate : public QObjectPrivate, public QQuickItemChangeListener
+{
+ Q_DECLARE_PUBLIC(QQuickAction)
+
+public:
+ QQuickActionPrivate();
+
+ static QQuickActionPrivate *get(QQuickAction *action)
+ {
+ return action->d_func();
+ }
+
+ QVariant shortcut() const;
+ void setShortcut(const QVariant &shortcut);
+
+ void setEnabled(bool enable);
+
+ bool watchItem(QQuickItem *item);
+ bool unwatchItem(QQuickItem *item);
+
+ void registerItem(QQuickItem *item);
+ void unregisterItem(QQuickItem *item);
+
+ void itemVisibilityChanged(QQuickItem *item) override;
+ void itemDestroyed(QQuickItem *item) override;
+
+ bool handleShortcutEvent(QObject *object, QShortcutEvent *event);
+
+ void trigger(QObject*, bool doToggle);
+
+ class ShortcutEntry
+ {
+ public:
+ explicit ShortcutEntry(QObject *target);
+ ~ShortcutEntry();
+
+ QObject *target() const;
+ int shortcutId() const;
+
+ void grab(const QKeySequence &vshortcut, bool enabled);
+ void ungrab();
+
+ void setEnabled(bool enabled);
+
+ private:
+ int m_shortcutId;
+ QObject *m_target;
+ };
+
+ ShortcutEntry *findShortcutEntry(QObject *target) const;
+ void updateDefaultShortcutEntry();
+
+ bool explicitEnabled;
+ bool enabled;
+ bool checked;
+ bool checkable;
+ QString text;
+ QQuickIcon icon;
+ QVariant vshortcut;
+ QKeySequence keySequence;
+ ShortcutEntry *defaultShortcutEntry;
+ QVector<ShortcutEntry *> shortcutEntries;
+ QQuickActionGroup *group;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKACTION_P_P_H
diff --git a/src/quicktemplates2/qquickactiongroup.cpp b/src/quicktemplates2/qquickactiongroup.cpp
new file mode 100644
index 00000000..64895689
--- /dev/null
+++ b/src/quicktemplates2/qquickactiongroup.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickactiongroup_p.h"
+
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvariant.h>
+#include <QtQml/qqmlinfo.h>
+
+#include "qquickaction_p.h"
+#include "qquickaction_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ActionGroup
+ \inherits QtObject
+ \instantiates QQuickActionGroup
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \ingroup utilities
+ \brief Groups actions together.
+
+ ActionGroup is a non-visual group of actions. A mutually \l exclusive
+ action group is used with actions where only one of the options can be
+ selected at a time.
+
+ The most straight-forward way to use ActionGroup is to declare actions
+ as children of the group.
+
+ \code
+ ActionGroup {
+ id: alignmentGroup
+
+ Action {
+ checked: true
+ checkable: true
+ text: qsTr("Left")
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Center")
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Right")
+ }
+ }
+ \endcode
+
+ Alternatively, the \l group attached property allows declaring the actions
+ elsewhere and assigning them to a specific group.
+
+ \code
+ ActionGroup { id: alignmentGroup }
+
+ Action {
+ checked: true
+ checkable: true
+ text: qsTr("Left")
+ ActionGroup.group: alignmentGroup
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Center")
+ ActionGroup.group: alignmentGroup
+ }
+
+ Action {
+ checkable: true
+ text: qsTr("Right")
+ ActionGroup.group: alignmentGroup
+ }
+ \endcode
+
+ More advanced use cases can be handled using the \c addAction() and
+ \c removeAction() methods.
+
+ \sa Action, ButtonGroup
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::ActionGroup::triggered(Action action)
+
+ This signal is emitted when an \a action in the group has been triggered.
+
+ This signal is convenient for implementing a common signal handler for
+ all actions in the same group.
+
+ \code
+ ActionGroup {
+ onTriggered: console.log("triggered:", action.text)
+
+ Action { text: "First" }
+ Action { text: "Second" }
+ Action { text: "Third" }
+ }
+ \endcode
+
+ \sa Action::triggered()
+*/
+
+class QQuickActionGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickActionGroup)
+
+public:
+ QQuickActionGroupPrivate()
+ : enabled(true),
+ exclusive(true),
+ checkedAction(nullptr)
+ {
+ }
+
+ void clear();
+ void actionTriggered();
+ void _q_updateCurrent();
+
+ static bool changeEnabled(QQuickAction *action, bool enabled);
+
+ static void actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj);
+ static int actions_count(QQmlListProperty<QQuickAction> *prop);
+ static QQuickAction *actions_at(QQmlListProperty<QQuickAction> *prop, int index);
+ static void actions_clear(QQmlListProperty<QQuickAction> *prop);
+
+ bool enabled;
+ bool exclusive;
+ QPointer<QQuickAction> checkedAction;
+ QVector<QQuickAction*> actions;
+};
+
+void QQuickActionGroupPrivate::clear()
+{
+ for (QQuickAction *action : qAsConst(actions)) {
+ QQuickActionPrivate::get(action)->group = nullptr;
+ QObjectPrivate::disconnect(action, &QQuickAction::triggered, this, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, this, &QQuickActionGroupPrivate::_q_updateCurrent);
+ }
+ actions.clear();
+}
+
+void QQuickActionGroupPrivate::actionTriggered()
+{
+ Q_Q(QQuickActionGroup);
+ QQuickAction *action = qobject_cast<QQuickAction*>(q->sender());
+ if (action)
+ emit q->triggered(action);
+}
+
+void QQuickActionGroupPrivate::_q_updateCurrent()
+{
+ Q_Q(QQuickActionGroup);
+ if (!exclusive)
+ return;
+ QQuickAction *action = qobject_cast<QQuickAction*>(q->sender());
+ if (action && action->isChecked())
+ q->setCheckedAction(action);
+ else if (!actions.contains(checkedAction))
+ q->setCheckedAction(nullptr);
+}
+
+bool QQuickActionGroupPrivate::changeEnabled(QQuickAction *action, bool enabled)
+{
+ return action->isEnabled() != enabled && (!enabled || !QQuickActionPrivate::get(action)->explicitEnabled);
+}
+
+void QQuickActionGroupPrivate::actions_append(QQmlListProperty<QQuickAction> *prop, QQuickAction *obj)
+{
+ QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object);
+ q->addAction(obj);
+}
+
+int QQuickActionGroupPrivate::actions_count(QQmlListProperty<QQuickAction> *prop)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ return p->actions.count();
+}
+
+QQuickAction *QQuickActionGroupPrivate::actions_at(QQmlListProperty<QQuickAction> *prop, int index)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ return p->actions.value(index);
+}
+
+void QQuickActionGroupPrivate::actions_clear(QQmlListProperty<QQuickAction> *prop)
+{
+ QQuickActionGroupPrivate *p = static_cast<QQuickActionGroupPrivate *>(prop->data);
+ if (!p->actions.isEmpty()) {
+ p->clear();
+ QQuickActionGroup *q = static_cast<QQuickActionGroup *>(prop->object);
+ // QTBUG-52358: don't clear the checked action immediately
+ QMetaObject::invokeMethod(q, "_q_updateCurrent", Qt::QueuedConnection);
+ emit q->actionsChanged();
+ }
+}
+
+QQuickActionGroup::QQuickActionGroup(QObject *parent)
+ : QObject(*(new QQuickActionGroupPrivate), parent)
+{
+}
+
+QQuickActionGroup::~QQuickActionGroup()
+{
+ Q_D(QQuickActionGroup);
+ d->clear();
+}
+
+QQuickActionGroupAttached *QQuickActionGroup::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickActionGroupAttached(object);
+}
+
+/*!
+ \qmlproperty Action QtQuick.Controls::ActionGroup::checkedAction
+
+ This property holds the currently selected action in an exclusive group,
+ or \c null if there is none or the group is non-exclusive.
+
+ By default, it is the first checked action added to an exclusive action group.
+
+ \sa exclusive
+*/
+QQuickAction *QQuickActionGroup::checkedAction() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->checkedAction;
+}
+
+void QQuickActionGroup::setCheckedAction(QQuickAction *checkedAction)
+{
+ Q_D(QQuickActionGroup);
+ if (d->checkedAction == checkedAction)
+ return;
+
+ if (d->checkedAction)
+ d->checkedAction->setChecked(false);
+ d->checkedAction = checkedAction;
+ if (checkedAction)
+ checkedAction->setChecked(true);
+ emit checkedActionChanged();
+}
+
+/*!
+ \qmlproperty list<Action> QtQuick.Controls::ActionGroup::actions
+ \default
+
+ This property holds the list of actions in the group.
+
+ \sa group
+*/
+QQmlListProperty<QQuickAction> QQuickActionGroup::actions()
+{
+ Q_D(QQuickActionGroup);
+ return QQmlListProperty<QQuickAction>(this, d,
+ QQuickActionGroupPrivate::actions_append,
+ QQuickActionGroupPrivate::actions_count,
+ QQuickActionGroupPrivate::actions_at,
+ QQuickActionGroupPrivate::actions_clear);
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::ActionGroup::exclusive
+
+ This property holds whether the action group is exclusive. The default value is \c true.
+
+ If this property is \c true, then only one action in the group can be checked at any given time.
+ The user can trigger any action to check it, and that action will replace the existing one as
+ the checked action in the group.
+
+ In an exclusive group, the user cannot uncheck the currently checked action by triggering it;
+ instead, another action in the group must be triggered to set the new checked action for that
+ group.
+
+ In a non-exclusive group, checking and unchecking actions does not affect the other actions in
+ the group. Furthermore, the value of the \l checkedAction property is \c null.
+*/
+bool QQuickActionGroup::isExclusive() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->exclusive;
+}
+
+void QQuickActionGroup::setExclusive(bool exclusive)
+{
+ Q_D(QQuickActionGroup);
+ if (d->exclusive == exclusive)
+ return;
+
+ d->exclusive = exclusive;
+ emit exclusiveChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::ActionGroup::enabled
+
+ This property holds whether the action group is enabled. The default value is \c true.
+
+ If this property is \c false, then all actions in the group are disabled. If this property
+ is \c true, all actions in the group are enabled, unless explicitly disabled.
+*/
+bool QQuickActionGroup::isEnabled() const
+{
+ Q_D(const QQuickActionGroup);
+ return d->enabled;
+}
+
+void QQuickActionGroup::setEnabled(bool enabled)
+{
+ Q_D(QQuickActionGroup);
+ if (d->enabled == enabled)
+ return;
+
+ for (QQuickAction *action : qAsConst(d->actions)) {
+ if (d->changeEnabled(action, enabled))
+ emit action->enabledChanged(enabled);
+ }
+
+ d->enabled = enabled;
+ emit enabledChanged();
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::ActionGroup::addAction(Action action)
+
+ Adds an \a action to the action group.
+
+ \note Manually adding objects to a action group is typically unnecessary.
+ The \l actions property and the \l group attached property provide a
+ convenient and declarative syntax.
+
+ \sa actions, group
+*/
+void QQuickActionGroup::addAction(QQuickAction *action)
+{
+ Q_D(QQuickActionGroup);
+ if (!action || d->actions.contains(action))
+ return;
+
+ const bool enabledChange = d->changeEnabled(action, d->enabled);
+
+ QQuickActionPrivate::get(action)->group = this;
+ QObjectPrivate::connect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::connect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent);
+
+ if (d->exclusive && action->isChecked())
+ setCheckedAction(action);
+ if (enabledChange)
+ emit action->enabledChanged(action->isEnabled());
+
+ d->actions.append(action);
+ emit actionsChanged();
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::ActionGroup::removeAction(Action action)
+
+ Removes an \a action from the action group.
+
+ \note Manually removing objects from a action group is typically unnecessary.
+ The \l actions property and the \l group attached property provide a
+ convenient and declarative syntax.
+
+ \sa actions, group
+*/
+void QQuickActionGroup::removeAction(QQuickAction *action)
+{
+ Q_D(QQuickActionGroup);
+ if (!action || !d->actions.contains(action))
+ return;
+
+ const bool enabledChange = d->changeEnabled(action, d->enabled);
+
+ QQuickActionPrivate::get(action)->group = nullptr;
+ QObjectPrivate::disconnect(action, &QQuickAction::triggered, d, &QQuickActionGroupPrivate::actionTriggered);
+ QObjectPrivate::disconnect(action, &QQuickAction::checkedChanged, d, &QQuickActionGroupPrivate::_q_updateCurrent);
+
+ if (d->checkedAction == action)
+ setCheckedAction(nullptr);
+ if (enabledChange)
+ emit action->enabledChanged(action->isEnabled());
+
+ d->actions.removeOne(action);
+ emit actionsChanged();
+}
+
+class QQuickActionGroupAttachedPrivate : public QObjectPrivate
+{
+public:
+ QQuickActionGroupAttachedPrivate() : group(nullptr) { }
+
+ QQuickActionGroup *group;
+};
+
+QQuickActionGroupAttached::QQuickActionGroupAttached(QObject *parent)
+ : QObject(*(new QQuickActionGroupAttachedPrivate), parent)
+{
+}
+
+/*!
+ \qmlattachedproperty ActionGroup QtQuick.Controls::ActionGroup::group
+
+ This property attaches an action to an action group.
+
+ \code
+ ActionGroup { id: group }
+
+ Action {
+ checked: true
+ text: qsTr("Option A")
+ ActionGroup.group: group
+ }
+
+ Action {
+ text: qsTr("Option B")
+ ActionGroup.group: group
+ }
+ \endcode
+
+ \sa actions
+*/
+QQuickActionGroup *QQuickActionGroupAttached::group() const
+{
+ Q_D(const QQuickActionGroupAttached);
+ return d->group;
+}
+
+void QQuickActionGroupAttached::setGroup(QQuickActionGroup *group)
+{
+ Q_D(QQuickActionGroupAttached);
+ if (d->group == group)
+ return;
+
+ if (d->group)
+ d->group->removeAction(qobject_cast<QQuickAction*>(parent()));
+ d->group = group;
+ if (group)
+ group->addAction(qobject_cast<QQuickAction*>(parent()));
+ emit groupChanged();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickactiongroup_p.cpp"
diff --git a/src/quicktemplates2/qquickactiongroup_p.h b/src/quicktemplates2/qquickactiongroup_p.h
new file mode 100644
index 00000000..aa04d32e
--- /dev/null
+++ b/src/quicktemplates2/qquickactiongroup_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKACTIONGROUP_P_H
+#define QQUICKACTIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAction;
+class QQuickActionGroupPrivate;
+class QQuickActionGroupAttached;
+class QQuickActionGroupAttachedPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickActionGroup : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickAction *checkedAction READ checkedAction WRITE setCheckedAction NOTIFY checkedActionChanged FINAL)
+ Q_PROPERTY(QQmlListProperty<QQuickAction> actions READ actions NOTIFY actionsChanged FINAL)
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL)
+ Q_CLASSINFO("DefaultProperty", "actions")
+
+public:
+ explicit QQuickActionGroup(QObject *parent = nullptr);
+ ~QQuickActionGroup();
+
+ static QQuickActionGroupAttached *qmlAttachedProperties(QObject *object);
+
+ QQuickAction *checkedAction() const;
+ void setCheckedAction(QQuickAction *checkedAction);
+
+ QQmlListProperty<QQuickAction> actions();
+
+ bool isExclusive() const;
+ void setExclusive(bool exclusive);
+
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
+public Q_SLOTS:
+ void addAction(QQuickAction *action);
+ void removeAction(QQuickAction *action);
+
+Q_SIGNALS:
+ void checkedActionChanged();
+ void actionsChanged();
+ void exclusiveChanged();
+ void enabledChanged();
+ void triggered(QQuickAction *action);
+
+private:
+ Q_DISABLE_COPY(QQuickActionGroup)
+ Q_DECLARE_PRIVATE(QQuickActionGroup)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_updateCurrent())
+};
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickActionGroupAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickActionGroup *group READ group WRITE setGroup NOTIFY groupChanged FINAL)
+
+public:
+ explicit QQuickActionGroupAttached(QObject *parent = nullptr);
+
+ QQuickActionGroup *group() const;
+ void setGroup(QQuickActionGroup *group);
+
+Q_SIGNALS:
+ void groupChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickActionGroupAttached)
+ Q_DECLARE_PRIVATE(QQuickActionGroupAttached)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickActionGroup)
+QML_DECLARE_TYPEINFO(QQuickActionGroup, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // QQUICKACTIONGROUP_P_H
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp
index c1a7f301..94b0de98 100644
--- a/src/quicktemplates2/qquickapplicationwindow.cpp
+++ b/src/quicktemplates2/qquickapplicationwindow.cpp
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
\brief Styled top-level window with support for a header and footer.
ApplicationWindow is a \l Window which makes it convenient to add
- a \l header and \l footer item to the window.
+ a \l {menuBar}{menu bar}, \l header and \l footer item to the window.
You can declare ApplicationWindow as the root item of your application,
and run it by using \l QQmlApplicationEngine. In this way you can control
@@ -71,11 +71,15 @@ QT_BEGIN_NAMESPACE
\image qtquickcontrols2-applicationwindow-wireframe.png
\qml
- import QtQuick.Controls 2.1
+ import QtQuick.Controls 2.3
ApplicationWindow {
visible: true
+ menuBar: MenuBar {
+ // ...
+ }
+
header: ToolBar {
// ...
}
@@ -90,11 +94,6 @@ QT_BEGIN_NAMESPACE
}
\endqml
- ApplicationWindow supports popups via its \l overlay property, which
- ensures that popups are displayed above other content and that the
- background is dimmed when a \l {Popup::}{modal} or \l {Popup::dim}
- {dimmed} popup is visible.
-
\note By default, an ApplicationWindow is not visible.
\section2 Attached ApplicationWindow Properties
@@ -109,31 +108,14 @@ QT_BEGIN_NAMESPACE
to access the window and its building blocks from places where no direct
access to the window is available, without creating a dependency to a
certain window \c id. A QML component that uses the ApplicationWindow
- attached properties works in any window regardless of its \c id. The
- following example uses the attached \c overlay property to position the
- popup to the center of the window, despite the position of the button
- that opens the popup.
-
- \code
- Button {
- onClicked: popup.open()
-
- Popup {
- id: popup
-
- parent: ApplicationWindow.overlay
-
- x: (parent.width - width) / 2
- y: (parent.height - height) / 2
- width: 100
- height: 100
- }
- }
- \endcode
+ attached properties works in any window regardless of its \c id.
- \sa {Customizing ApplicationWindow}, Page, {Container Controls}
+ \sa {Customizing ApplicationWindow}, Overlay, Page, {Container Controls}
*/
+static const QQuickItemPrivate::ChangeTypes ItemChanges = QQuickItemPrivate::Visibility
+ | QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
+
class QQuickApplicationWindowPrivate : public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickApplicationWindow)
@@ -143,6 +125,7 @@ public:
: complete(true),
background(nullptr),
contentItem(nullptr),
+ menuBar(nullptr),
header(nullptr),
footer(nullptr),
overlay(nullptr),
@@ -170,6 +153,14 @@ public:
}
void resolveFont();
+ void updatePalette(const QPalette &p);
+ inline void setPalette_helper(const QPalette &p) {
+ if (palette.resolve() == p.resolve() && palette == p)
+ return;
+ updatePalette(p);
+ }
+ void resolvePalette();
+
void _q_updateActiveFocus();
void setActiveFocusControl(QQuickItem *item);
@@ -180,43 +171,48 @@ public:
bool complete;
QQuickDeferredPointer<QQuickItem> background;
QQuickItem *contentItem;
+ QQuickItem *menuBar;
QQuickItem *header;
QQuickItem *footer;
QQuickOverlay *overlay;
QFont font;
QLocale locale;
+ QPalette palette;
QQuickItem *activeFocusControl;
QQuickApplicationWindow *q_ptr;
};
+static void layoutItem(QQuickItem *item, qreal y, qreal width)
+{
+ if (!item)
+ return;
+
+ item->setY(y);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!p->widthValid) {
+ item->setWidth(width);
+ p->widthValid = false;
+ }
+}
+
void QQuickApplicationWindowPrivate::relayout()
{
Q_Q(QQuickApplicationWindow);
+ if (!complete)
+ return;
+
QQuickItem *content = q->contentItem();
qreal hh = header && header->isVisible() ? header->height() : 0;
qreal fh = footer && footer->isVisible() ? footer->height() : 0;
+ qreal mbh = menuBar && menuBar->isVisible() ? menuBar->height() : 0;
- content->setY(hh);
+ content->setY(mbh + hh);
content->setWidth(q->width());
- content->setHeight(q->height() - hh - fh);
+ content->setHeight(q->height() - mbh - hh - fh);
- if (header) {
- header->setY(-hh);
- QQuickItemPrivate *p = QQuickItemPrivate::get(header);
- if (!p->widthValid) {
- header->setWidth(q->width());
- p->widthValid = false;
- }
- }
-
- if (footer) {
- footer->setY(content->height());
- QQuickItemPrivate *p = QQuickItemPrivate::get(footer);
- if (!p->widthValid) {
- footer->setWidth(q->width());
- p->widthValid = false;
- }
- }
+ layoutItem(menuBar, -mbh - hh, q->width());
+ layoutItem(header, -hh, q->width());
+ layoutItem(footer, content->height(), q->width());
if (background) {
QQuickItemPrivate *p = QQuickItemPrivate::get(background);
@@ -257,28 +253,65 @@ void QQuickApplicationWindowPrivate::itemImplicitHeightChanged(QQuickItem *item)
relayout();
}
-void QQuickApplicationWindowPrivate::_q_updateActiveFocus()
+void QQuickApplicationWindowPrivate::updateFont(const QFont &f)
+{
+ Q_Q(QQuickApplicationWindow);
+ const bool changed = font != f;
+ font = f;
+
+ QQuickControlPrivate::updateFontRecur(q->QQuickWindow::contentItem(), f);
+
+ const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>();
+ for (QQuickPopup *popup : popups)
+ QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(f);
+
+ if (changed)
+ emit q->fontChanged();
+}
+
+void QQuickApplicationWindowPrivate::resolveFont()
+{
+ QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont));
+ setFont_helper(resolvedFont);
+}
+
+void QQuickApplicationWindowPrivate::updatePalette(const QPalette &p)
{
Q_Q(QQuickApplicationWindow);
- QQuickItem *item = q->activeFocusItem();
+ const bool changed = palette != p;
+ palette = p;
+
+ QQuickControlPrivate::updatePaletteRecur(q->QQuickWindow::contentItem(), p);
+
+ const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>();
+ for (QQuickPopup *popup : popups)
+ QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritPalette(p);
+
+ if (changed)
+ emit q->paletteChanged();
+}
+
+void QQuickApplicationWindowPrivate::resolvePalette()
+{
+ QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette));
+ setPalette_helper(resolvedPalette);
+}
+
+static QQuickItem *findActiveFocusControl(QQuickWindow *window)
+{
+ QQuickItem *item = window->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;
- }
+ if (qobject_cast<QQuickControl *>(item) || qobject_cast<QQuickTextField *>(item) || qobject_cast<QQuickTextArea *>(item))
+ return item;
item = item->parentItem();
}
+ return item;
+}
+
+void QQuickApplicationWindowPrivate::_q_updateActiveFocus()
+{
+ Q_Q(QQuickApplicationWindow);
+ setActiveFocusControl(findActiveFocusControl(q));
}
void QQuickApplicationWindowPrivate::setActiveFocusControl(QQuickItem *control)
@@ -325,15 +358,20 @@ QQuickApplicationWindow::~QQuickApplicationWindow()
Q_D(QQuickApplicationWindow);
d->setActiveFocusControl(nullptr);
disconnect(this, SIGNAL(activeFocusItemChanged()), this, SLOT(_q_updateActiveFocus()));
+ if (d->menuBar)
+ QQuickItemPrivate::get(d->menuBar)->removeItemChangeListener(d, ItemChanges);
if (d->header)
- QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, ItemChanges);
if (d->footer)
- QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, ItemChanges);
d_ptr.reset(); // QTBUG-52731
}
+QQuickApplicationWindowAttached *QQuickApplicationWindow::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickApplicationWindowAttached(object);
+}
+
/*!
\qmlproperty Item QtQuick.Controls::ApplicationWindow::background
@@ -350,7 +388,7 @@ QQuickApplicationWindow::~QQuickApplicationWindow()
follows the control's size. In most cases, there is no need to specify
width or height for a background item.
- \sa {Customizing ApplicationWindow}, contentItem, header, footer, overlay
+ \sa {Customizing ApplicationWindow}, contentItem, header, footer
*/
QQuickItem *QQuickApplicationWindow::background() const
{
@@ -382,8 +420,9 @@ void QQuickApplicationWindow::setBackground(QQuickItem *background)
/*!
\qmlproperty Item QtQuick.Controls::ApplicationWindow::header
- This property holds the window header item. The header item is positioned to
- the top, and resized to the width of the window. The default value is \c null.
+ This property holds the window header item. The header item is positioned at the
+ top of the window, below the menu bar, and resized to the width of the window.
+ The default value is \c null.
\code
ApplicationWindow {
@@ -397,7 +436,7 @@ void QQuickApplicationWindow::setBackground(QQuickItem *background)
automatically sets the respective \l ToolBar::position, \l TabBar::position,
or \l DialogButtonBox::position property to \c Header.
- \sa footer, Page::header
+ \sa menuBar, footer, Page::header
*/
QQuickItem *QQuickApplicationWindow::header() const
{
@@ -412,16 +451,14 @@ void QQuickApplicationWindow::setHeader(QQuickItem *header)
return;
if (d->header) {
- QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, ItemChanges);
d->header->setParentItem(nullptr);
}
d->header = header;
if (header) {
header->setParentItem(contentItem());
QQuickItemPrivate *p = QQuickItemPrivate::get(header);
- p->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ p->addItemChangeListener(d, ItemChanges);
if (qFuzzyIsNull(header->z()))
header->setZ(1);
if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(header))
@@ -454,7 +491,7 @@ void QQuickApplicationWindow::setHeader(QQuickItem *header)
automatically sets the respective \l ToolBar::position, \l TabBar::position,
or \l DialogButtonBox::position property to \c Footer.
- \sa header, Page::footer
+ \sa menuBar, header, Page::footer
*/
QQuickItem *QQuickApplicationWindow::footer() const
{
@@ -469,16 +506,14 @@ void QQuickApplicationWindow::setFooter(QQuickItem *footer)
return;
if (d->footer) {
- QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, ItemChanges);
d->footer->setParentItem(nullptr);
}
d->footer = footer;
if (footer) {
footer->setParentItem(contentItem());
QQuickItemPrivate *p = QQuickItemPrivate::get(footer);
- p->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility |
- QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight);
+ p->addItemChangeListener(d, ItemChanges);
if (qFuzzyIsNull(footer->z()))
footer->setZ(1);
if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(footer))
@@ -529,9 +564,9 @@ QQmlListProperty<QObject> QQuickApplicationWindow::contentData()
This property holds the window content item.
The content item is stacked above the \l background item, and under the
- \l header, \l footer, and \l overlay items.
+ \l menuBar, \l header, and \l footer items.
- \sa background, header, footer, overlay
+ \sa background, menuBar, header, footer
*/
QQuickItem *QQuickApplicationWindow::contentItem() const
{
@@ -566,11 +601,14 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const
}
/*!
+ \deprecated
\qmlpropertygroup QtQuick.Controls::ApplicationWindow::overlay
\qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay
\qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modal
\qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modeless
+ Use the \l Overlay attached properties and signals instead.
+
This property holds the window overlay item. Popups are automatically
reparented to the overlay.
@@ -650,28 +688,6 @@ void QQuickApplicationWindow::resetFont()
setFont(QFont());
}
-void QQuickApplicationWindowPrivate::resolveFont()
-{
- QFont resolvedFont = font.resolve(QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont));
- setFont_helper(resolvedFont);
-}
-
-void QQuickApplicationWindowPrivate::updateFont(const QFont &f)
-{
- Q_Q(QQuickApplicationWindow);
- const bool changed = font != f;
- font = f;
-
- QQuickControlPrivate::updateFontRecur(q->QQuickWindow::contentItem(), f);
-
- const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>();
- for (QQuickPopup *popup : popups)
- QQuickControlPrivate::get(static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(f);
-
- if (changed)
- emit q->fontChanged();
-}
-
/*!
\qmlproperty Locale QtQuick.Controls::ApplicationWindow::locale
@@ -714,9 +730,88 @@ void QQuickApplicationWindow::resetLocale()
setLocale(QLocale());
}
-QQuickApplicationWindowAttached *QQuickApplicationWindow::qmlAttachedProperties(QObject *object)
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::ApplicationWindow::palette
+
+ This property holds the palette currently set for the window.
+
+ The default palette depends on the system environment. QGuiApplication maintains a system/theme
+ palette which serves as a default for all application windows. You can also set the default palette
+ for windows by passing a custom palette to QGuiApplication::setPalette(), before loading any QML.
+
+ ApplicationWindow propagates explicit palette properties to child controls. If you change a specific
+ property on the window's palette, that property propagates to all child controls in the window,
+ overriding any system defaults for that property.
+
+ \sa Control::palette, Popup::palette, {qtquickcontrols2-palette}{palette QML Basic Type}
+*/
+QPalette QQuickApplicationWindow::palette() const
{
- return new QQuickApplicationWindowAttached(object);
+ Q_D(const QQuickApplicationWindow);
+ return d->palette;
+}
+
+void QQuickApplicationWindow::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickApplicationWindow);
+ if (d->palette.resolve() == palette.resolve() && d->palette == palette)
+ return;
+
+ QPalette resolvedPalette = palette.resolve(QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette));
+ d->setPalette_helper(resolvedPalette);
+}
+
+void QQuickApplicationWindow::resetPalette()
+{
+ setPalette(QPalette());
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Item QtQuick.Controls::ApplicationWindow::menuBar
+
+ This property holds the window menu bar. The menu bar is positioned at the
+ top of the window, above the header, and resized to the width of the window.
+ The default value is \c null.
+
+ \code
+ ApplicationWindow {
+ menuBar: MenuBar {
+ // ...
+ }
+ }
+ \endcode
+
+ \sa header, footer, MenuBar
+*/
+QQuickItem *QQuickApplicationWindow::menuBar() const
+{
+ Q_D(const QQuickApplicationWindow);
+ return d->menuBar;
+}
+
+void QQuickApplicationWindow::setMenuBar(QQuickItem *menuBar)
+{
+ Q_D(QQuickApplicationWindow);
+ if (d->menuBar == menuBar)
+ return;
+
+ if (d->menuBar) {
+ QQuickItemPrivate::get(d->menuBar)->removeItemChangeListener(d, ItemChanges);
+ d->menuBar->setParentItem(nullptr);
+ }
+ d->menuBar = menuBar;
+ if (menuBar) {
+ menuBar->setParentItem(contentItem());
+ QQuickItemPrivate *p = QQuickItemPrivate::get(menuBar);
+ p->addItemChangeListener(d, ItemChanges);
+ if (qFuzzyIsNull(menuBar->z()))
+ menuBar->setZ(2);
+ }
+ if (isComponentComplete())
+ d->relayout();
+ emit menuBarChanged();
}
bool QQuickApplicationWindow::isComponentComplete() const
@@ -731,6 +826,7 @@ void QQuickApplicationWindow::classBegin()
d->complete = false;
QQuickWindowQmlImpl::classBegin();
d->resolveFont();
+ d->resolvePalette();
}
void QQuickApplicationWindow::componentComplete()
@@ -739,6 +835,7 @@ void QQuickApplicationWindow::componentComplete()
d->complete = true;
d->executeBackground(true);
QQuickWindowQmlImpl::componentComplete();
+ d->relayout();
}
void QQuickApplicationWindow::resizeEvent(QResizeEvent *event)
@@ -753,11 +850,17 @@ class QQuickApplicationWindowAttachedPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQuickApplicationWindowAttached)
public:
- QQuickApplicationWindowAttachedPrivate() : window(nullptr) { }
+ QQuickApplicationWindowAttachedPrivate()
+ : window(nullptr),
+ activeFocusControl(nullptr)
+ {
+ }
void windowChange(QQuickWindow *wnd);
+ void activeFocusChange();
QQuickWindow *window;
+ QQuickItem *activeFocusControl;
};
void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd)
@@ -771,22 +874,32 @@ void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd)
oldWindow = nullptr; // being deleted (QTBUG-52731)
if (oldWindow) {
- QObject::disconnect(oldWindow, &QQuickApplicationWindow::activeFocusControlChanged,
- q, &QQuickApplicationWindowAttached::activeFocusControlChanged);
+ disconnect(oldWindow, &QQuickApplicationWindow::activeFocusControlChanged,
+ this, &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
+ QObject::disconnect(oldWindow, &QQuickApplicationWindow::menuBarChanged,
+ q, &QQuickApplicationWindowAttached::menuBarChanged);
QObject::disconnect(oldWindow, &QQuickApplicationWindow::headerChanged,
q, &QQuickApplicationWindowAttached::headerChanged);
QObject::disconnect(oldWindow, &QQuickApplicationWindow::footerChanged,
q, &QQuickApplicationWindowAttached::footerChanged);
+ } else if (window) {
+ disconnect(window, &QQuickWindow::activeFocusItemChanged,
+ this, &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
}
QQuickApplicationWindow *newWindow = qobject_cast<QQuickApplicationWindow *>(wnd);
if (newWindow) {
- QObject::connect(newWindow, &QQuickApplicationWindow::activeFocusControlChanged,
- q, &QQuickApplicationWindowAttached::activeFocusControlChanged);
+ connect(newWindow, &QQuickApplicationWindow::activeFocusControlChanged,
+ this, &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
+ QObject::connect(newWindow, &QQuickApplicationWindow::menuBarChanged,
+ q, &QQuickApplicationWindowAttached::menuBarChanged);
QObject::connect(newWindow, &QQuickApplicationWindow::headerChanged,
q, &QQuickApplicationWindowAttached::headerChanged);
QObject::connect(newWindow, &QQuickApplicationWindow::footerChanged,
q, &QQuickApplicationWindowAttached::footerChanged);
+ } else if (wnd) {
+ connect(wnd, &QQuickWindow::activeFocusItemChanged,
+ this, &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
}
window = wnd;
@@ -794,14 +907,30 @@ void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd)
emit q->contentItemChanged();
emit q->overlayChanged();
- if ((oldWindow && oldWindow->activeFocusControl()) || (newWindow && newWindow->activeFocusControl()))
- emit q->activeFocusControlChanged();
+ activeFocusChange();
+ if ((oldWindow && oldWindow->menuBar()) || (newWindow && newWindow->menuBar()))
+ emit q->menuBarChanged();
if ((oldWindow && oldWindow->header()) || (newWindow && newWindow->header()))
emit q->headerChanged();
if ((oldWindow && oldWindow->footer()) || (newWindow && newWindow->footer()))
emit q->footerChanged();
}
+void QQuickApplicationWindowAttachedPrivate::activeFocusChange()
+{
+ Q_Q(QQuickApplicationWindowAttached);
+ QQuickItem *control = nullptr;
+ if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(window))
+ control = appWindow->activeFocusControl();
+ else if (window)
+ control = findActiveFocusControl(window);
+ if (activeFocusControl == control)
+ return;
+
+ activeFocusControl = control;
+ emit q->activeFocusControlChanged();
+}
+
QQuickApplicationWindowAttached::QQuickApplicationWindowAttached(QObject *parent)
: QObject(*(new QQuickApplicationWindowAttachedPrivate), parent)
{
@@ -863,17 +992,14 @@ QQuickItem *QQuickApplicationWindowAttached::contentItem() const
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.
+ The value is \c null if the item is not in a window, or the window has no active focus.
\sa Window::activeFocusItem, {Attached ApplicationWindow Properties}
*/
QQuickItem *QQuickApplicationWindowAttached::activeFocusControl() const
{
Q_D(const QQuickApplicationWindowAttached);
- if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(d->window))
- return window->activeFocusControl();
- return nullptr;
+ return d->activeFocusControl;
}
/*!
@@ -913,9 +1039,12 @@ QQuickItem *QQuickApplicationWindowAttached::footer() const
}
/*!
+ \deprecated
\qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::overlay
\readonly
+ Use the \l Overlay::overlay attached property instead.
+
This attached property holds the window overlay item. The property can be attached
to any item. The value is \c null if the item is not in an ApplicationWindow.
@@ -927,6 +1056,25 @@ QQuickOverlay *QQuickApplicationWindowAttached::overlay() const
return QQuickOverlay::overlay(d->window);
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::menuBar
+ \readonly
+
+ This attached property holds the window menu bar. 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 menu bar.
+
+ \sa {Attached ApplicationWindow Properties}
+*/
+QQuickItem *QQuickApplicationWindowAttached::menuBar() const
+{
+ Q_D(const QQuickApplicationWindowAttached);
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(d->window))
+ return window->menuBar();
+ return nullptr;
+}
+
QT_END_NAMESPACE
#include "moc_qquickapplicationwindow_p.cpp"
diff --git a/src/quicktemplates2/qquickapplicationwindow_p.h b/src/quicktemplates2/qquickapplicationwindow_p.h
index c1e7935b..d74d3c9d 100644
--- a/src/quicktemplates2/qquickapplicationwindow_p.h
+++ b/src/quicktemplates2/qquickapplicationwindow_p.h
@@ -51,6 +51,7 @@
#include <QtQuick/private/qquickwindowmodule_p.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
#include <QtGui/qfont.h>
+#include <QtGui/qpalette.h>
#include <QtCore/qlocale.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +73,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindow : public QQuickWi
Q_PROPERTY(QQuickOverlay *overlay READ overlay CONSTANT FINAL)
Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
+ Q_PROPERTY(QQuickItem *menuBar READ menuBar WRITE setMenuBar NOTIFY menuBarChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background")
Q_CLASSINFO("DefaultProperty", "contentData")
@@ -79,6 +83,8 @@ public:
explicit QQuickApplicationWindow(QWindow *parent = nullptr);
~QQuickApplicationWindow();
+ static QQuickApplicationWindowAttached *qmlAttachedProperties(QObject *object);
+
QQuickItem *background() const;
void setBackground(QQuickItem *background);
@@ -103,7 +109,13 @@ public:
void setLocale(const QLocale &locale);
void resetLocale();
- static QQuickApplicationWindowAttached *qmlAttachedProperties(QObject *object);
+ // 2.3 (Qt 5.10)
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
+ QQuickItem *menuBar() const;
+ void setMenuBar(QQuickItem *menuBar);
Q_SIGNALS:
void backgroundChanged();
@@ -112,6 +124,8 @@ Q_SIGNALS:
void footerChanged();
void fontChanged();
void localeChanged();
+ Q_REVISION(3) void paletteChanged();
+ Q_REVISION(3) void menuBarChanged();
protected:
bool isComponentComplete() const;
@@ -135,6 +149,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindowAttached : public
Q_PROPERTY(QQuickItem *header READ header NOTIFY headerChanged FINAL)
Q_PROPERTY(QQuickItem *footer READ footer NOTIFY footerChanged FINAL)
Q_PROPERTY(QQuickOverlay *overlay READ overlay NOTIFY overlayChanged FINAL)
+ Q_PROPERTY(QQuickItem *menuBar READ menuBar NOTIFY menuBarChanged FINAL) // REVISION 3
public:
explicit QQuickApplicationWindowAttached(QObject *parent = nullptr);
@@ -145,6 +160,7 @@ public:
QQuickItem *header() const;
QQuickItem *footer() const;
QQuickOverlay *overlay() const;
+ QQuickItem *menuBar() const;
Q_SIGNALS:
void windowChanged();
@@ -153,6 +169,8 @@ Q_SIGNALS:
void headerChanged();
void footerChanged();
void overlayChanged();
+ // 2.3 (Qt 5.10)
+ /*Q_REVISION(3)*/ void menuBarChanged();
private:
Q_DISABLE_COPY(QQuickApplicationWindowAttached)
diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp
index 1a614754..9cbf8b21 100644
--- a/src/quicktemplates2/qquickbutton.cpp
+++ b/src/quicktemplates2/qquickbutton.cpp
@@ -57,6 +57,10 @@ QT_BEGIN_NAMESPACE
a question. Typical buttons are \e OK, \e Apply, \e Cancel, \e Close,
\e Yes, \e No, and \e Help.
+ Button inherits its API from AbstractButton. For instance, you can set
+ \l {AbstractButton::text}{text}, display an \l {Icons in Qt Quick Controls 2}{icon},
+ and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton API.
+
A button emits the signal \l {AbstractButton::}{clicked()} when it is activated by the user.
Connect to this signal to perform the button's action. Buttons also
provide the signals \l {AbstractButton::}{canceled()}, \l {AbstractButton::}{doubleClicked()}, \l {AbstractButton::}{pressed()},
@@ -119,6 +123,11 @@ QFont QQuickButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont);
}
+QPalette QQuickButton::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette);
+}
+
/*!
\qmlproperty bool QtQuick.Controls::Button::highlighted
diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h
index 93fb3c14..f1a34b10 100644
--- a/src/quicktemplates2/qquickbutton_p.h
+++ b/src/quicktemplates2/qquickbutton_p.h
@@ -81,6 +81,7 @@ protected:
void buttonChange(ButtonChange change) override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
private:
Q_DISABLE_COPY(QQuickButton)
diff --git a/src/quicktemplates2/qquickbuttongroup.cpp b/src/quicktemplates2/qquickbuttongroup.cpp
index 355fcf6a..2a1e354c 100644
--- a/src/quicktemplates2/qquickbuttongroup.cpp
+++ b/src/quicktemplates2/qquickbuttongroup.cpp
@@ -154,6 +154,8 @@ class QQuickButtonGroupPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQuickButtonGroup)
public:
+ QQuickButtonGroupPrivate() : exclusive(true) { }
+
void clear();
void buttonClicked();
void _q_updateCurrent();
@@ -163,6 +165,7 @@ public:
static QQuickAbstractButton *buttons_at(QQmlListProperty<QQuickAbstractButton> *prop, int index);
static void buttons_clear(QQmlListProperty<QQuickAbstractButton> *prop);
+ bool exclusive;
QPointer<QQuickAbstractButton> checkedButton;
QVector<QQuickAbstractButton*> buttons;
};
@@ -188,6 +191,8 @@ void QQuickButtonGroupPrivate::buttonClicked()
void QQuickButtonGroupPrivate::_q_updateCurrent()
{
Q_Q(QQuickButtonGroup);
+ if (!exclusive)
+ return;
QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(q->sender());
if (button && button->isChecked())
q->setCheckedButton(button);
@@ -244,9 +249,12 @@ QQuickButtonGroupAttached *QQuickButtonGroup::qmlAttachedProperties(QObject *obj
/*!
\qmlproperty AbstractButton QtQuick.Controls::ButtonGroup::checkedButton
- This property holds the currently selected button, or \c null if there is none.
+ This property holds the currently selected button in an exclusive group,
+ or \c null if there is none or the group is non-exclusive.
+
+ By default, it is the first checked button added to an exclusive button group.
- By default, it is the first checked button added to the button group.
+ \sa exclusive
*/
QQuickAbstractButton *QQuickButtonGroup::checkedButton() const
{
@@ -306,6 +314,38 @@ QQmlListProperty<QQuickAbstractButton> QQuickButtonGroup::buttons()
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::ButtonGroup::exclusive
+
+ This property holds whether the button group is exclusive. The default value is \c true.
+
+ If this property is \c true, then only one button in the group can be checked at any given time.
+ The user can click on any button to check it, and that button will replace the existing one as
+ the checked button in the group.
+
+ In an exclusive group, the user cannot uncheck the currently checked button by clicking on it;
+ instead, another button in the group must be clicked to set the new checked button for that group.
+
+ In a non-exclusive group, checking and unchecking buttons does not affect the other buttons in
+ the group. Furthermore, the value of the \l checkedButton property is \c null.
+*/
+bool QQuickButtonGroup::isExclusive() const
+{
+ Q_D(const QQuickButtonGroup);
+ return d->exclusive;
+}
+
+void QQuickButtonGroup::setExclusive(bool exclusive)
+{
+ Q_D(QQuickButtonGroup);
+ if (d->exclusive == exclusive)
+ return;
+
+ d->exclusive = exclusive;
+ emit exclusiveChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::ButtonGroup::addButton(AbstractButton button)
Adds a \a button to the button group.
@@ -326,7 +366,7 @@ void QQuickButtonGroup::addButton(QQuickAbstractButton *button)
QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickButtonGroupPrivate::buttonClicked);
QObjectPrivate::connect(button, &QQuickAbstractButton::checkedChanged, d, &QQuickButtonGroupPrivate::_q_updateCurrent);
- if (button->isChecked())
+ if (d->exclusive && button->isChecked())
setCheckedButton(button);
d->buttons.append(button);
diff --git a/src/quicktemplates2/qquickbuttongroup_p.h b/src/quicktemplates2/qquickbuttongroup_p.h
index bb32ed5c..53f8be8c 100644
--- a/src/quicktemplates2/qquickbuttongroup_p.h
+++ b/src/quicktemplates2/qquickbuttongroup_p.h
@@ -62,8 +62,10 @@ class QQuickButtonGroupAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickButtonGroup : public QObject
{
Q_OBJECT
- Q_PROPERTY(QQuickAbstractButton *checkedButton READ checkedButton WRITE setCheckedButton NOTIFY checkedButtonChanged)
+ Q_PROPERTY(QQuickAbstractButton *checkedButton READ checkedButton WRITE setCheckedButton NOTIFY checkedButtonChanged FINAL)
Q_PROPERTY(QQmlListProperty<QQuickAbstractButton> buttons READ buttons NOTIFY buttonsChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL REVISION 3)
public:
explicit QQuickButtonGroup(QObject *parent = nullptr);
@@ -76,6 +78,9 @@ public:
QQmlListProperty<QQuickAbstractButton> buttons();
+ bool isExclusive() const;
+ void setExclusive(bool exclusive);
+
public Q_SLOTS:
void addButton(QQuickAbstractButton *button);
void removeButton(QQuickAbstractButton *button);
@@ -85,6 +90,8 @@ Q_SIGNALS:
void buttonsChanged();
// 2.1 (Qt 5.8)
Q_REVISION(1) void clicked(QQuickAbstractButton *button);
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void exclusiveChanged();
private:
Q_DISABLE_COPY(QQuickButtonGroup)
diff --git a/src/quicktemplates2/qquickcheckbox.cpp b/src/quicktemplates2/qquickcheckbox.cpp
index e0c7faf1..2e0c401a 100644
--- a/src/quicktemplates2/qquickcheckbox.cpp
+++ b/src/quicktemplates2/qquickcheckbox.cpp
@@ -174,6 +174,11 @@ QFont QQuickCheckBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::CheckBoxFont);
}
+QPalette QQuickCheckBox::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette);
+}
+
void QQuickCheckBox::buttonChange(ButtonChange change)
{
if (change == ButtonCheckedChange)
diff --git a/src/quicktemplates2/qquickcheckbox_p.h b/src/quicktemplates2/qquickcheckbox_p.h
index dfd935d3..979f096b 100644
--- a/src/quicktemplates2/qquickcheckbox_p.h
+++ b/src/quicktemplates2/qquickcheckbox_p.h
@@ -75,6 +75,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
void buttonChange(ButtonChange change) override;
void nextCheckState() override;
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp
index d221b9bc..3b37900d 100644
--- a/src/quicktemplates2/qquickcombobox.cpp
+++ b/src/quicktemplates2/qquickcombobox.cpp
@@ -37,6 +37,7 @@
#include "qquickcombobox_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickabstractbutton_p.h"
+#include "qquickabstractbutton_p_p.h"
#include "qquickpopup_p_p.h"
#include "qquickdeferredexecute_p_p.h"
@@ -51,6 +52,7 @@
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
+#include <QtQuick/private/qquickitemview_p.h>
QT_BEGIN_NAMESPACE
@@ -226,6 +228,7 @@ public:
void popupVisibleChanged();
void itemClicked();
+ void itemHovered();
void createdItem(int index, QObject *object);
void modelUpdated();
@@ -261,6 +264,7 @@ public:
bool hasDown;
bool pressed;
bool ownModel;
+ bool keyNavigating;
bool hasDisplayText;
bool hasCurrentIndex;
int highlightedIndex;
@@ -299,6 +303,7 @@ QQuickComboBoxPrivate::QQuickComboBoxPrivate()
hasDown(false),
pressed(false),
ownModel(false),
+ keyNavigating(false),
hasDisplayText(false),
hasCurrentIndex(false),
highlightedIndex(-1),
@@ -349,7 +354,15 @@ void QQuickComboBoxPrivate::popupVisibleChanged()
if (isPopupVisible())
QGuiApplication::inputMethod()->reset();
+ QQuickItemView *itemView = popup->findChild<QQuickItemView *>();
+ if (itemView)
+ itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange);
+
updateHighlightedIndex();
+
+ if (itemView)
+ itemView->positionViewAtIndex(highlightedIndex, QQuickItemView::Beginning);
+
if (!hasDown) {
q->setDown(pressed || isPopupVisible());
hasDown = false;
@@ -366,6 +379,25 @@ void QQuickComboBoxPrivate::itemClicked()
}
}
+void QQuickComboBoxPrivate::itemHovered()
+{
+ Q_Q(QQuickComboBox);
+ if (keyNavigating)
+ return;
+
+ QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
+ if (!button || !button->isHovered() || QQuickAbstractButtonPrivate::get(button)->touchId != -1)
+ return;
+
+ int index = delegateModel->indexOf(button, nullptr);
+ if (index != -1) {
+ setHighlightedIndex(index, Highlight);
+
+ if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>())
+ itemView->positionViewAtIndex(index, QQuickItemView::Contain);
+ }
+}
+
void QQuickComboBoxPrivate::createdItem(int index, QObject *object)
{
Q_Q(QQuickComboBox);
@@ -382,6 +414,7 @@ void QQuickComboBoxPrivate::createdItem(int index, QObject *object)
if (button) {
button->setFocusPolicy(Qt::NoFocus);
connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
+ connect(button, &QQuickAbstractButton::hoveredChanged, this, &QQuickComboBoxPrivate::itemHovered);
}
if (index == currentIndex && !q->isEditable())
@@ -1060,6 +1093,9 @@ void QQuickComboBox::setPopup(QQuickPopup *popup)
QQuickPopupPrivate::get(popup)->allowVerticalFlip = true;
popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent);
QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
+
+ if (QQuickItemView *itemView = popup->findChild<QQuickItemView *>())
+ itemView->setHighlightRangeMode(QQuickItemView::NoHighlightRange);
}
d->popup = popup;
if (!d->popup.isExecuting())
@@ -1428,9 +1464,12 @@ bool QQuickComboBox::eventFilter(QObject *object, QEvent *event)
d->hidePopup(false);
break;
case QEvent::KeyPress: {
- const int key = static_cast<QKeyEvent *>(event)->key();
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ if (d->filterKeyEvent(ke, false))
+ return true;
+ event->accept();
if (d->extra.isAllocated())
- d->extra->allowComplete = key != Qt::Key_Backspace && key != Qt::Key_Delete;
+ d->extra->allowComplete = ke->key() != Qt::Key_Backspace && ke->key() != Qt::Key_Delete;
break;
}
case QEvent::FocusOut:
@@ -1500,14 +1539,17 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event)
event->accept();
break;
case Qt::Key_Up:
+ d->keyNavigating = true;
d->decrementCurrentIndex();
event->accept();
break;
case Qt::Key_Down:
+ d->keyNavigating = true;
d->incrementCurrentIndex();
event->accept();
break;
case Qt::Key_Home:
+ d->keyNavigating = true;
if (d->isPopupVisible())
d->setHighlightedIndex(0, Highlight);
else
@@ -1515,6 +1557,7 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event)
event->accept();
break;
case Qt::Key_End:
+ d->keyNavigating = true;
if (d->isPopupVisible())
d->setHighlightedIndex(count() - 1, Highlight);
else
@@ -1534,6 +1577,7 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event)
{
Q_D(QQuickComboBox);
QQuickControl::keyReleaseEvent(event);
+ d->keyNavigating = false;
if (event->isAutoRepeat())
return;
@@ -1637,6 +1681,11 @@ QFont QQuickComboBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ComboMenuItemFont);
}
+QPalette QQuickComboBox::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ComboBoxPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickComboBox::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h
index 7c27ca99..ee926daf 100644
--- a/src/quicktemplates2/qquickcombobox_p.h
+++ b/src/quicktemplates2/qquickcombobox_p.h
@@ -198,6 +198,7 @@ protected:
void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp
index ffed86b7..048cfdfa 100644
--- a/src/quicktemplates2/qquickcontainer.cpp
+++ b/src/quicktemplates2/qquickcontainer.cpp
@@ -253,13 +253,17 @@ void QQuickContainerPrivate::insertItem(int index, QQuickItem *item)
q->itemAdded(index, item);
- if (contentModel->count() == 1 && currentIndex == -1)
+ int count = contentModel->count();
+ for (int i = index + 1; i < count; ++i)
+ q->itemMoved(i, itemAt(i));
+
+ if (count == 1 && currentIndex == -1)
q->setCurrentIndex(index);
updatingCurrent = false;
}
-void QQuickContainerPrivate::moveItem(int from, int to)
+void QQuickContainerPrivate::moveItem(int from, int to, QQuickItem *item)
{
Q_Q(QQuickContainer);
int oldCurrent = currentIndex;
@@ -267,6 +271,16 @@ void QQuickContainerPrivate::moveItem(int from, int to)
updatingCurrent = true;
+ q->itemMoved(to, item);
+
+ if (from < to) {
+ for (int i = from; i < to; ++i)
+ q->itemMoved(i, itemAt(i));
+ } else {
+ for (int i = from; i > to; --i)
+ q->itemMoved(i, itemAt(i));
+ }
+
if (from == oldCurrent)
q->setCurrentIndex(to);
else if (from < oldCurrent && to >= oldCurrent)
@@ -300,6 +314,10 @@ void QQuickContainerPrivate::removeItem(int index, QQuickItem *item)
q->itemRemoved(index, item);
+ int count = contentModel->count();
+ for (int i = index; i < count; ++i)
+ q->itemMoved(i, itemAt(i));
+
if (currentChanged)
emit q->currentIndexChanged();
@@ -363,8 +381,8 @@ void QQuickContainerPrivate::itemDestroyed(QQuickItem *item)
void QQuickContainerPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ QQuickContainerPrivate *p = QQuickContainerPrivate::get(q);
QQuickItem *item = qobject_cast<QQuickItem *>(obj);
if (item) {
if (QQuickItemPrivate::get(item)->isTransparentForPositioner())
@@ -378,20 +396,20 @@ void QQuickContainerPrivate::contentData_append(QQmlListProperty<QObject> *prop,
int QQuickContainerPrivate::contentData_count(QQmlListProperty<QObject> *prop)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
- return p->contentData.count();
+ QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ return QQuickContainerPrivate::get(q)->contentData.count();
}
QObject *QQuickContainerPrivate::contentData_at(QQmlListProperty<QObject> *prop, int index)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
- return p->contentData.value(index);
+ QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ return QQuickContainerPrivate::get(q)->contentData.value(index);
}
void QQuickContainerPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
- p->contentData.clear();
+ QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ return QQuickContainerPrivate::get(q)->contentData.clear();
}
void QQuickContainerPrivate::contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item)
@@ -402,8 +420,8 @@ void QQuickContainerPrivate::contentChildren_append(QQmlListProperty<QQuickItem>
int QQuickContainerPrivate::contentChildren_count(QQmlListProperty<QQuickItem> *prop)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
- return p->contentModel->count();
+ QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ return QQuickContainerPrivate::get(q)->contentModel->count();
}
QQuickItem *QQuickContainerPrivate::contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
@@ -414,8 +432,8 @@ QQuickItem *QQuickContainerPrivate::contentChildren_at(QQmlListProperty<QQuickIt
void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> *prop)
{
- QQuickContainerPrivate *p = static_cast<QQuickContainerPrivate *>(prop->data);
- p->contentModel->clear();
+ QQuickContainer *q = static_cast<QQuickContainer *>(prop->object);
+ return QQuickContainerPrivate::get(q)->contentModel->clear();
}
QQuickContainer::QQuickContainer(QQuickItem *parent)
@@ -491,7 +509,7 @@ void QQuickContainer::insertItem(int index, QQuickItem *item)
if (oldIndex < index)
--index;
if (oldIndex != index)
- d->moveItem(oldIndex, index);
+ d->moveItem(oldIndex, index, item);
} else {
d->insertItem(index, item);
}
@@ -512,26 +530,65 @@ void QQuickContainer::moveItem(int from, int to)
to = count - 1;
if (from != to)
- d->moveItem(from, to);
+ d->moveItem(from, to, d->itemAt(from));
}
/*!
+ \deprecated
\qmlmethod void QtQuick.Controls::Container::removeItem(int index)
- Removes an item at \a index.
+ Use Container::removeItem(Item) or Container::takeItem(int) instead.
+*/
+void QQuickContainer::removeItem(const QVariant &var)
+{
+ if (var.userType() == QMetaType::Nullptr)
+ return;
+
+ if (QQuickItem *item = var.value<QQuickItem *>())
+ removeItem(item);
+ else
+ takeItem(var.toInt());
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Container::removeItem(Item item)
+
+ Removes and destroys the specified \a item.
+*/
+void QQuickContainer::removeItem(QQuickItem *item)
+{
+ Q_D(QQuickContainer);
+ if (!item)
+ return;
+
+ const int index = d->contentModel->indexOf(item, nullptr);
+ if (index == -1)
+ return;
+
+ d->removeItem(index, item);
+ item->deleteLater();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod Item QtQuick.Controls::Container::takeItem(int index)
+
+ Removes and returns the item at \a index.
\note The ownership of the item is transferred to the caller.
*/
-void QQuickContainer::removeItem(int index)
+QQuickItem *QQuickContainer::takeItem(int index)
{
Q_D(QQuickContainer);
const int count = d->contentModel->count();
if (index < 0 || index >= count)
- return;
+ return nullptr;
QQuickItem *item = itemAt(index);
if (item)
d->removeItem(index, item);
+ return item;
}
/*!
@@ -580,7 +637,7 @@ QQmlListProperty<QObject> QQuickContainer::contentData()
Q_D(QQuickContainer);
if (!d->contentItem)
d->executeContentItem();
- return QQmlListProperty<QObject>(this, d,
+ return QQmlListProperty<QObject>(this, nullptr,
QQuickContainerPrivate::contentData_append,
QQuickContainerPrivate::contentData_count,
QQuickContainerPrivate::contentData_at,
@@ -603,8 +660,7 @@ QQmlListProperty<QObject> QQuickContainer::contentData()
*/
QQmlListProperty<QQuickItem> QQuickContainer::contentChildren()
{
- Q_D(QQuickContainer);
- return QQmlListProperty<QQuickItem>(this, d,
+ return QQmlListProperty<QQuickItem>(this, nullptr,
QQuickContainerPrivate::contentChildren_append,
QQuickContainerPrivate::contentChildren_count,
QQuickContainerPrivate::contentChildren_at,
@@ -759,6 +815,12 @@ void QQuickContainer::itemAdded(int index, QQuickItem *item)
Q_UNUSED(item);
}
+void QQuickContainer::itemMoved(int index, QQuickItem *item)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(item);
+}
+
void QQuickContainer::itemRemoved(int index, QQuickItem *item)
{
Q_UNUSED(index);
diff --git a/src/quicktemplates2/qquickcontainer_p.h b/src/quicktemplates2/qquickcontainer_p.h
index 3aa1f13e..030497cf 100644
--- a/src/quicktemplates2/qquickcontainer_p.h
+++ b/src/quicktemplates2/qquickcontainer_p.h
@@ -75,7 +75,10 @@ public:
Q_INVOKABLE void addItem(QQuickItem *item);
Q_INVOKABLE void insertItem(int index, QQuickItem *item);
Q_INVOKABLE void moveItem(int from, int to);
- Q_INVOKABLE void removeItem(int index);
+ Q_INVOKABLE void removeItem(const QVariant &item); // ### Qt 6: remove
+ void removeItem(QQuickItem *item); // ### Qt 6: Q_INVOKABLE
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) Q_INVOKABLE QQuickItem *takeItem(int index);
QVariant contentModel() const;
QQmlListProperty<QObject> contentData();
@@ -106,6 +109,7 @@ protected:
virtual bool isContent(QQuickItem *item) const;
virtual void itemAdded(int index, QQuickItem *item);
+ virtual void itemMoved(int index, QQuickItem *item);
virtual void itemRemoved(int index, QQuickItem *item);
private:
diff --git a/src/quicktemplates2/qquickcontainer_p_p.h b/src/quicktemplates2/qquickcontainer_p_p.h
index bc892c7d..7791b69c 100644
--- a/src/quicktemplates2/qquickcontainer_p_p.h
+++ b/src/quicktemplates2/qquickcontainer_p_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtQuickTemplates2/private/qquickcontainer_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
@@ -61,12 +62,17 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickContainerPrivate : public QQuickCon
public:
QQuickContainerPrivate();
+ static QQuickContainerPrivate *get(QQuickContainer *container)
+ {
+ return container->d_func();
+ }
+
void init();
void cleanup();
QQuickItem *itemAt(int index) const;
void insertItem(int index, QQuickItem *item);
- void moveItem(int from, int to);
+ void moveItem(int from, int to, QQuickItem *item);
void removeItem(int index, QQuickItem *item);
void reorderItems();
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index cfecc67c..76d6a688 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -131,8 +131,7 @@ QQuickControlPrivate::QQuickControlPrivate()
focusPolicy(Qt::NoFocus),
focusReason(Qt::OtherFocusReason),
background(nullptr),
- contentItem(nullptr),
- accessibleAttached(nullptr)
+ contentItem(nullptr)
{
#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
@@ -320,27 +319,11 @@ QAccessible::Role QQuickControlPrivate::accessibleRole() const
return q->accessibleRole();
}
-QAccessible::Role QQuickControl::accessibleRole() const
+QQuickAccessibleAttached *QQuickControlPrivate::accessibleAttached(const QObject *object)
{
- return QAccessible::NoRole;
-}
-
-void QQuickControl::accessibilityActiveChanged(bool active)
-{
- Q_D(QQuickControl);
- if (d->accessibleAttached || !active)
- return;
-
- d->accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true));
-
- // QQuickControl relies on the existence of a QQuickAccessibleAttached object.
- // However, qmlAttachedPropertiesObject(create=true) creates an instance only
- // for items that have been created by a QML engine. Therefore we create the
- // object by hand for items created in C++ (QQuickPopupItem, for instance).
- if (!d->accessibleAttached)
- d->accessibleAttached = new QQuickAccessibleAttached(this);
-
- d->accessibleAttached->setRole(accessibleRole());
+ if (!QAccessible::isActive())
+ return nullptr;
+ return QQuickAccessibleAttached::attachedProperties(object);
}
#endif
@@ -400,11 +383,11 @@ void QQuickControlPrivate::resolveFont()
inheritFont(parentFont(q));
}
-void QQuickControlPrivate::inheritFont(const QFont &f)
+void QQuickControlPrivate::inheritFont(const QFont &font)
{
Q_Q(QQuickControl);
- QFont parentFont = extra.isAllocated() ? extra->font.resolve(f) : f;
- parentFont.resolve(extra.isAllocated() ? extra->font.resolve() | f.resolve() : f.resolve());
+ QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
+ parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());
const QFont defaultFont = q->defaultFont();
const QFont resolvedFont = parentFont.resolve(defaultFont);
@@ -417,35 +400,192 @@ void QQuickControlPrivate::inheritFont(const QFont &f)
Assign \a font to this control, and propagate it to all children.
*/
-void QQuickControlPrivate::updateFont(const QFont &f)
+void QQuickControlPrivate::updateFont(const QFont &font)
{
Q_Q(QQuickControl);
- QFont old = resolvedFont;
- resolvedFont = f;
+ QFont oldFont = resolvedFont;
+ resolvedFont = font;
- if (old != f)
- q->fontChange(f, old);
+ if (oldFont != font)
+ q->fontChange(font, oldFont);
- QQuickControlPrivate::updateFontRecur(q, f);
+ QQuickControlPrivate::updateFontRecur(q, font);
- if (old != f)
+ if (oldFont != font)
emit q->fontChanged();
}
-void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &f)
+void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &font)
+{
+ const auto childItems = item->childItems();
+ for (QQuickItem *child : childItems) {
+ if (QQuickControl *control = qobject_cast<QQuickControl *>(child))
+ QQuickControlPrivate::get(control)->inheritFont(font);
+ else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(child))
+ QQuickLabelPrivate::get(label)->inheritFont(font);
+ else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(child))
+ QQuickTextAreaPrivate::get(textArea)->inheritFont(font);
+ else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(child))
+ QQuickTextFieldPrivate::get(textField)->inheritFont(font);
+ else
+ QQuickControlPrivate::updateFontRecur(child, font);
+ }
+}
+
+/*!
+ \internal
+
+ Returns the palette that the item inherits from its ancestors and
+ QGuiApplication::palette.
+*/
+QPalette QQuickControlPrivate::parentPalette(const QQuickItem *item)
+{
+ QQuickItem *p = item->parentItem();
+ while (p) {
+ if (QQuickControl *control = qobject_cast<QQuickControl *>(p))
+ return control->palette();
+ else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(p))
+ return label->palette();
+ else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(p))
+ return textField->palette();
+ else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(p))
+ return textArea->palette();
+
+ p = p->parentItem();
+ }
+
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window()))
+ return window->palette();
+
+ return themePalette(QPlatformTheme::SystemPalette);
+}
+
+QPalette QQuickControlPrivate::themePalette(QPlatformTheme::Palette type)
+{
+ if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
+ if (const QPalette *palette = theme->palette(type)) {
+ QPalette p = *palette;
+ if (type == QPlatformTheme::SystemPalette)
+ p.resolve(0);
+ return p;
+ }
+ }
+
+ return QPalette();
+}
+
+/*!
+ \internal
+
+ Determine which palette is implicitly imposed on this control by its ancestors
+ and QGuiApplication::palette, resolve this against its own palette (attributes from
+ the implicit palette are copied over). Then propagate this palette to this
+ control's children.
+*/
+void QQuickControlPrivate::resolvePalette()
+{
+ Q_Q(QQuickControl);
+ inheritPalette(parentPalette(q));
+}
+
+void QQuickControlPrivate::inheritPalette(const QPalette &palette)
+{
+ Q_Q(QQuickControl);
+ QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
+ parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());
+
+ const QPalette defaultPalette = q->defaultPalette();
+ const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);
+
+ setPalette_helper(resolvedPalette);
+}
+
+/*!
+ \internal
+
+ Assign \a palette to this control, and propagate it to all children.
+*/
+void QQuickControlPrivate::updatePalette(const QPalette &palette)
+{
+ Q_Q(QQuickControl);
+ QPalette oldPalette = resolvedPalette;
+ resolvedPalette = palette;
+
+ if (oldPalette != palette)
+ q->paletteChange(palette, oldPalette);
+
+ QQuickControlPrivate::updatePaletteRecur(q, palette);
+
+ if (oldPalette != palette)
+ emit q->paletteChanged();
+}
+
+void QQuickControlPrivate::updatePaletteRecur(QQuickItem *item, const QPalette &palette)
{
const auto childItems = item->childItems();
for (QQuickItem *child : childItems) {
if (QQuickControl *control = qobject_cast<QQuickControl *>(child))
- QQuickControlPrivate::get(control)->inheritFont(f);
+ QQuickControlPrivate::get(control)->inheritPalette(palette);
else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(child))
- QQuickLabelPrivate::get(label)->inheritFont(f);
+ QQuickLabelPrivate::get(label)->inheritPalette(palette);
else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(child))
- QQuickTextAreaPrivate::get(textArea)->inheritFont(f);
+ QQuickTextAreaPrivate::get(textArea)->inheritPalette(palette);
else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(child))
- QQuickTextFieldPrivate::get(textField)->inheritFont(f);
+ QQuickTextFieldPrivate::get(textField)->inheritPalette(palette);
+ else
+ QQuickControlPrivate::updatePaletteRecur(child, palette);
+ }
+}
+
+QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item)
+{
+ const QQuickItem *p = item;
+ while (p) {
+ if (const QQuickControl *control = qobject_cast<const QQuickControl *>(p))
+ return control->locale();
+
+ QVariant v = p->property("locale");
+ if (v.isValid() && v.userType() == QMetaType::QLocale)
+ return v.toLocale();
+
+ p = p->parentItem();
+ }
+
+ if (item) {
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window()))
+ return window->locale();
+ }
+
+ return QLocale();
+}
+
+void QQuickControlPrivate::updateLocale(const QLocale &l, bool e)
+{
+ Q_Q(QQuickControl);
+ if (!e && hasLocale)
+ return;
+
+ QLocale old = q->locale();
+ hasLocale = e;
+ if (old != l) {
+ bool wasMirrored = q->isMirrored();
+ q->localeChange(l, old);
+ locale = l;
+ QQuickControlPrivate::updateLocaleRecur(q, l);
+ emit q->localeChanged();
+ if (wasMirrored != q->isMirrored())
+ q->mirrorChange();
+ }
+}
+
+void QQuickControlPrivate::updateLocaleRecur(QQuickItem *item, const QLocale &l)
+{
+ const auto childItems = item->childItems();
+ for (QQuickItem *child : childItems) {
+ if (QQuickControl *control = qobject_cast<QQuickControl *>(child))
+ QQuickControlPrivate::get(control)->updateLocale(l, false);
else
- QQuickControlPrivate::updateFontRecur(child, f);
+ updateLocaleRecur(child, l);
}
}
@@ -507,48 +647,54 @@ bool QQuickControlPrivate::calcHoverEnabled(const QQuickItem *item)
}
#endif
-QString QQuickControl::accessibleName() const
+static inline QString contentItemName() { return QStringLiteral("contentItem"); }
+
+void QQuickControlPrivate::executeContentItem(bool complete)
{
-#if QT_CONFIG(accessibility)
- Q_D(const QQuickControl);
- if (d->accessibleAttached)
- return d->accessibleAttached->name();
-#endif
- return QString();
+ Q_Q(QQuickControl);
+ if (contentItem.wasExecuted())
+ return;
+
+ if (!contentItem)
+ quickBeginDeferred(q, contentItemName(), contentItem);
+ if (complete)
+ quickCompleteDeferred(q, contentItemName(), contentItem);
}
-void QQuickControl::setAccessibleName(const QString &name)
+static inline QString backgroundName() { return QStringLiteral("background"); }
+
+void QQuickControlPrivate::executeBackground(bool complete)
{
-#if QT_CONFIG(accessibility)
- Q_D(QQuickControl);
- if (d->accessibleAttached)
- d->accessibleAttached->setName(name);
-#else
- Q_UNUSED(name)
-#endif
+ Q_Q(QQuickControl);
+ if (background.wasExecuted())
+ return;
+
+ if (!background)
+ quickBeginDeferred(q, backgroundName(), background);
+ if (complete)
+ quickCompleteDeferred(q, backgroundName(), background);
}
-QVariant QQuickControl::accessibleProperty(const char *propertyName)
+/*
+ Cancels incubation recursively to avoid "Object destroyed during incubation" (QTBUG-50992)
+*/
+static void cancelIncubation(QObject *object, QQmlContext *context)
{
-#if QT_CONFIG(accessibility)
- Q_D(QQuickControl);
- if (d->accessibleAttached)
- return QQuickAccessibleAttached::property(this, propertyName);
-#endif
- Q_UNUSED(propertyName)
- return QVariant();
+ const auto children = object->children();
+ for (QObject *child : children)
+ cancelIncubation(child, context);
+ QQmlIncubatorPrivate::cancel(object, context);
}
-bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value)
+void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent)
{
-#if QT_CONFIG(accessibility)
- Q_D(QQuickControl);
- if (d->accessibleAttached)
- return QQuickAccessibleAttached::setProperty(this, propertyName, value);
-#endif
- Q_UNUSED(propertyName)
- Q_UNUSED(value)
- return false;
+ if (!delegate)
+ return;
+
+ QQmlContext *context = parent ? qmlContext(parent) : nullptr;
+ if (context)
+ cancelIncubation(delegate, context);
+ delete delegate;
}
QQuickControl::QQuickControl(QQuickItem *parent)
@@ -566,6 +712,9 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::
Q_D(QQuickControl);
QQuickItem::itemChange(change, value);
switch (change) {
+ case ItemEnabledHasChanged:
+ emit paletteChanged();
+ break;
case ItemVisibleHasChanged:
#if QT_CONFIG(quicktemplates2_hover)
if (!value.boolValue)
@@ -576,6 +725,7 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::
case ItemParentHasChanged:
if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
d->resolveFont();
+ d->resolvePalette();
if (!d->hasLocale)
d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false
#if QT_CONFIG(quicktemplates2_hover)
@@ -605,9 +755,14 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::
The default font depends on the system environment. ApplicationWindow maintains a system/theme
font which serves as a default for all controls. There may also be special font defaults for
- certain types of controls. You can also set the default font for controls by passing a custom
- font to QGuiApplication::setFont(), before loading the QML. Finally, the font is matched
- against Qt's font database to find the best match.
+ certain types of controls. You can also set the default font for controls by either:
+
+ \list
+ \li passing a custom font to QGuiApplication::setFont(), before loading the QML; or
+ \li specifying the fonts in the \l {Qt Quick Controls 2 Configuration File}{qtquickcontrols2.conf file}.
+ \endlist
+
+ Finally, the font is matched against Qt's font database to find the best match.
Control propagates explicit font properties from parent to children. If you change a specific
property on a control's font, that property propagates to all of the control's children,
@@ -628,6 +783,9 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::
}
}
\endcode
+
+ For the full list of available font properties, see the
+ \l [QtQuick]{font}{font QML Basic Type} documentation.
*/
QFont QQuickControl::font() const
{
@@ -638,10 +796,10 @@ QFont QQuickControl::font() const
void QQuickControl::setFont(const QFont &font)
{
Q_D(QQuickControl);
- if (d->extra.value().font.resolve() == font.resolve() && d->extra.value().font == font)
+ if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
return;
- d->extra.value().font = font;
+ d->extra.value().requestedFont = font;
d->resolveFont();
}
@@ -914,108 +1072,6 @@ void QQuickControl::resetLocale()
d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false
}
-QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item)
-{
- const QQuickItem *p = item;
- while (p) {
- if (const QQuickControl *control = qobject_cast<const QQuickControl *>(p))
- return control->locale();
-
- QVariant v = p->property("locale");
- if (v.isValid() && v.userType() == QMetaType::QLocale)
- return v.toLocale();
-
- p = p->parentItem();
- }
-
- if (item) {
- if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(item->window()))
- return window->locale();
- }
-
- return QLocale();
-}
-
-static inline QString contentItemName() { return QStringLiteral("contentItem"); }
-
-void QQuickControlPrivate::executeContentItem(bool complete)
-{
- Q_Q(QQuickControl);
- if (contentItem.wasExecuted())
- return;
-
- if (!contentItem)
- quickBeginDeferred(q, contentItemName(), contentItem);
- if (complete)
- quickCompleteDeferred(q, contentItemName(), contentItem);
-}
-
-static inline QString backgroundName() { return QStringLiteral("background"); }
-
-void QQuickControlPrivate::executeBackground(bool complete)
-{
- Q_Q(QQuickControl);
- if (background.wasExecuted())
- return;
-
- if (!background)
- quickBeginDeferred(q, backgroundName(), background);
- if (complete)
- quickCompleteDeferred(q, backgroundName(), background);
-}
-
-/*
- Cancels incubation recursively to avoid "Object destroyed during incubation" (QTBUG-50992)
-*/
-static void cancelIncubation(QObject *object, QQmlContext *context)
-{
- const auto children = object->children();
- for (QObject *child : children)
- cancelIncubation(child, context);
- QQmlIncubatorPrivate::cancel(object, context);
-}
-
-void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent)
-{
- if (!delegate)
- return;
-
- QQmlContext *context = parent ? qmlContext(parent) : nullptr;
- if (context)
- cancelIncubation(delegate, context);
- delete delegate;
-}
-
-void QQuickControlPrivate::updateLocale(const QLocale &l, bool e)
-{
- Q_Q(QQuickControl);
- if (!e && hasLocale)
- return;
-
- QLocale old = q->locale();
- hasLocale = e;
- if (old != l) {
- bool wasMirrored = q->isMirrored();
- q->localeChange(l, old);
- locale = l;
- QQuickControlPrivate::updateLocaleRecur(q, l);
- emit q->localeChanged();
- if (wasMirrored != q->isMirrored())
- q->mirrorChange();
- }
-}
-
-void QQuickControlPrivate::updateLocaleRecur(QQuickItem *item, const QLocale &l)
-{
- const auto childItems = item->childItems();
- for (QQuickItem *child : childItems) {
- if (QQuickControl *control = qobject_cast<QQuickControl *>(child))
- QQuickControlPrivate::get(control)->updateLocale(l, false);
- else
- updateLocaleRecur(child, l);
- }
-}
-
/*!
\qmlproperty bool QtQuick.Controls::Control::mirrored
\readonly
@@ -1312,11 +1368,81 @@ void QQuickControl::setContentItem(QQuickItem *item)
d->setContentItem_helper(item, true);
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::Control::palette
+
+ This property holds the palette currently set for the control.
+
+ This property describes the control's requested palette. The palette is used by the control's
+ style when rendering standard components, and is available as a means to ensure that custom
+ controls can maintain consistency with the native platform's native look and feel. It's common
+ that different platforms, or different styles, define different palettes for an application.
+
+ The default palette depends on the system environment. ApplicationWindow maintains a system/theme
+ palette which serves as a default for all controls. There may also be special palette defaults for
+ certain types of controls. You can also set the default palette for controls by either:
+
+ \list
+ \li passing a custom palette to QGuiApplication::setPalette(), before loading any QML; or
+ \li specifying the colors in the \l {Qt Quick Controls 2 Configuration File}{qtquickcontrols2.conf file}.
+ \endlist
+
+ Control propagates explicit palette properties from parent to children. If you change a specific
+ property on a control's palette, that property propagates to all of the control's children,
+ overriding any system defaults for that property.
+
+ \code
+ Page {
+ palette.text: "red"
+
+ Column {
+ Label {
+ text: qsTr("This will use red color...")
+ }
+
+ Switch {
+ text: qsTr("... and so will this")
+ }
+ }
+ }
+ \endcode
+
+ For the full list of available palette colors, see the
+ \l {qtquickcontrols2-palette}{palette QML Basic Type} documentation.
+
+ \sa ApplicationWindow::palette, Popup::palette
+*/
+QPalette QQuickControl::palette() const
+{
+ Q_D(const QQuickControl);
+ QPalette palette = d->resolvedPalette;
+ if (!isEnabled())
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ return palette;
+}
+
+void QQuickControl::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickControl);
+ if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
+ return;
+
+ d->extra.value().requestedPalette = palette;
+ d->resolvePalette();
+}
+
+void QQuickControl::resetPalette()
+{
+ setPalette(QPalette());
+}
+
void QQuickControl::classBegin()
{
Q_D(QQuickControl);
QQuickItem::classBegin();
d->resolveFont();
+ d->resolvePalette();
}
void QQuickControl::componentComplete()
@@ -1333,7 +1459,7 @@ void QQuickControl::componentComplete()
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
#endif
#if QT_CONFIG(accessibility)
- if (!d->accessibleAttached && QAccessible::isActive())
+ if (QAccessible::isActive())
accessibilityActiveChanged(true);
#endif
}
@@ -1343,6 +1469,11 @@ QFont QQuickControl::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont);
}
+QPalette QQuickControl::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette);
+}
+
void QQuickControl::focusInEvent(QFocusEvent *event)
{
QQuickItem::focusInEvent(event);
@@ -1516,4 +1647,67 @@ void QQuickControl::localeChange(const QLocale &newLocale, const QLocale &oldLoc
Q_UNUSED(oldLocale);
}
+void QQuickControl::paletteChange(const QPalette &newPalette, const QPalette &oldPalette)
+{
+ Q_UNUSED(newPalette);
+ Q_UNUSED(oldPalette);
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickControl::accessibleRole() const
+{
+ return QAccessible::NoRole;
+}
+
+void QQuickControl::accessibilityActiveChanged(bool active)
+{
+ if (!active)
+ return;
+
+ QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, true));
+ Q_ASSERT(accessibleAttached);
+ accessibleAttached->setRole(accessibleRole());
+}
+#endif
+
+QString QQuickControl::accessibleName() const
+{
+#if QT_CONFIG(accessibility)
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
+ return accessibleAttached->name();
+#endif
+ return QString();
+}
+
+void QQuickControl::setAccessibleName(const QString &name)
+{
+#if QT_CONFIG(accessibility)
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
+ accessibleAttached->setName(name);
+#else
+ Q_UNUSED(name)
+#endif
+}
+
+QVariant QQuickControl::accessibleProperty(const char *propertyName)
+{
+#if QT_CONFIG(accessibility)
+ if (QAccessible::isActive())
+ return QQuickAccessibleAttached::property(this, propertyName);
+#endif
+ Q_UNUSED(propertyName)
+ return QVariant();
+}
+
+bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value)
+{
+#if QT_CONFIG(accessibility)
+ if (QAccessible::isActive())
+ return QQuickAccessibleAttached::setProperty(this, propertyName, value);
+#endif
+ Q_UNUSED(propertyName)
+ Q_UNUSED(value)
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h
index 6ccc5b71..6b2d48d6 100644
--- a/src/quicktemplates2/qquickcontrol_p.h
+++ b/src/quicktemplates2/qquickcontrol_p.h
@@ -49,6 +49,7 @@
//
#include <QtCore/qlocale.h>
+#include <QtGui/qpalette.h>
#include <QtQuick/qquickitem.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
@@ -78,6 +79,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControl : public QQuickItem
Q_PROPERTY(bool wheelEnabled READ isWheelEnabled WRITE setWheelEnabled NOTIFY wheelEnabledChanged FINAL)
Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background,contentItem")
public:
@@ -144,6 +147,11 @@ public:
QQuickItem *contentItem() const;
void setContentItem(QQuickItem *item);
+ // 2.3 (Qt 5.10)
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
Q_SIGNALS:
void fontChanged();
void availableWidthChanged();
@@ -164,9 +172,12 @@ Q_SIGNALS:
void wheelEnabledChanged();
void backgroundChanged();
void contentItemChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void paletteChanged();
protected:
virtual QFont defaultFont() const;
+ virtual QPalette defaultPalette() const;
QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent);
@@ -205,10 +216,11 @@ protected:
virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding);
virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem);
virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale);
+ virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette);
#if QT_CONFIG(accessibility)
- virtual void accessibilityActiveChanged(bool active);
virtual QAccessible::Role accessibleRole() const;
+ virtual void accessibilityActiveChanged(bool active);
#endif
// helper functions which avoid to check QT_CONFIG(accessibility)
diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h
index d8b1dd40..f159c96d 100644
--- a/src/quicktemplates2/qquickcontrol_p_p.h
+++ b/src/quicktemplates2/qquickcontrol_p_p.h
@@ -48,8 +48,8 @@
// We mean it.
//
-#include "qquickcontrol_p.h"
-#include "qquickdeferredpointer_p_p.h"
+#include <QtQuickTemplates2/private/qquickcontrol_p.h>
+#include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQml/private/qlazilyallocated_p.h>
@@ -103,20 +103,33 @@ public:
#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
+ static QQuickAccessibleAttached *accessibleAttached(const QObject *object);
#endif
- void updateFont(const QFont &f);
- static void updateFontRecur(QQuickItem *item, const QFont &f);
- inline void setFont_helper(const QFont &f) {
- if (resolvedFont.resolve() == f.resolve() && resolvedFont == f)
+ virtual void resolveFont();
+ void inheritFont(const QFont &font);
+ void updateFont(const QFont &font);
+ static void updateFontRecur(QQuickItem *item, const QFont &font);
+ inline void setFont_helper(const QFont &font) {
+ if (resolvedFont.resolve() == font.resolve() && resolvedFont == font)
return;
- updateFont(f);
+ updateFont(font);
}
- virtual void resolveFont();
- void inheritFont(const QFont &f);
static QFont parentFont(const QQuickItem *item);
static QFont themeFont(QPlatformTheme::Font type);
+ virtual void resolvePalette();
+ void inheritPalette(const QPalette &palette);
+ void updatePalette(const QPalette &palette);
+ static void updatePaletteRecur(QQuickItem *item, const QPalette &palette);
+ inline void setPalette_helper(const QPalette &palette) {
+ if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette)
+ return;
+ updatePalette(palette);
+ }
+ static QPalette parentPalette(const QQuickItem *item);
+ static QPalette themePalette(QPlatformTheme::Palette type);
+
void updateLocale(const QLocale &l, bool e);
static void updateLocaleRecur(QQuickItem *item, const QLocale &l);
static QLocale calcLocale(const QQuickItem *item);
@@ -134,11 +147,11 @@ public:
struct ExtraData {
ExtraData();
- QFont font;
+ QFont requestedFont;
+ QPalette requestedPalette;
};
QLazilyAllocated<ExtraData> extra;
- QFont resolvedFont;
bool hasTopPadding;
bool hasLeftPadding;
bool hasRightPadding;
@@ -157,11 +170,12 @@ public:
qreal bottomPadding;
qreal spacing;
QLocale locale;
+ QFont resolvedFont;
+ QPalette resolvedPalette;
Qt::FocusPolicy focusPolicy;
Qt::FocusReason focusReason;
QQuickDeferredPointer<QQuickItem> background;
QQuickDeferredPointer<QQuickItem> contentItem;
- QQuickAccessibleAttached *accessibleAttached;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickdelaybutton.cpp b/src/quicktemplates2/qquickdelaybutton.cpp
index 842713e0..128f0c78 100644
--- a/src/quicktemplates2/qquickdelaybutton.cpp
+++ b/src/quicktemplates2/qquickdelaybutton.cpp
@@ -268,4 +268,9 @@ QFont QQuickDelayButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont);
}
+QPalette QQuickDelayButton::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ButtonPalette);
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickdelaybutton_p.h b/src/quicktemplates2/qquickdelaybutton_p.h
index 5ac0885d..0927eb4a 100644
--- a/src/quicktemplates2/qquickdelaybutton_p.h
+++ b/src/quicktemplates2/qquickdelaybutton_p.h
@@ -85,6 +85,7 @@ protected:
void nextCheckState() override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
private:
Q_DISABLE_COPY(QQuickDelayButton)
diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp
index 3ac99caa..cce1ae47 100644
--- a/src/quicktemplates2/qquickdialog.cpp
+++ b/src/quicktemplates2/qquickdialog.cpp
@@ -37,6 +37,7 @@
#include "qquickdialog_p.h"
#include "qquickdialog_p_p.h"
#include "qquickdialogbuttonbox_p.h"
+#include "qquickabstractbutton_p.h"
#include "qquickpopupitem_p_p.h"
QT_BEGIN_NAMESPACE
@@ -115,6 +116,69 @@ QT_BEGIN_NAMESPACE
\sa accepted()
*/
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::Dialog::applied()
+
+ This signal is emitted when the \c Dialog.Apply standard button is clicked.
+
+ \sa discarded(), reset()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::Dialog::reset()
+
+ This signal is emitted when the \c Dialog.Reset standard button is clicked.
+
+ \sa discarded(), applied()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::Dialog::discarded()
+
+ This signal is emitted when the \c Dialog.Discard standard button is clicked.
+
+ \sa reset(), applied()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::Dialog::helpRequested()
+
+ This signal is emitted when the \c Dialog.Help standard button is clicked.
+
+ \sa accepted(), rejected()
+*/
+
+QPlatformDialogHelper::ButtonRole QQuickDialogPrivate::buttonRole(QQuickAbstractButton *button)
+{
+ const QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false));
+ return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole;
+}
+
+void QQuickDialogPrivate::handleClick(QQuickAbstractButton *button)
+{
+ Q_Q(QQuickDialog);
+ switch (buttonRole(button)) {
+ case QPlatformDialogHelper::ApplyRole:
+ emit q->applied();
+ break;
+ case QPlatformDialogHelper::ResetRole:
+ emit q->reset();
+ break;
+ case QPlatformDialogHelper::DestructiveRole:
+ emit q->discarded();
+ break;
+ case QPlatformDialogHelper::HelpRole:
+ emit q->helpRequested();
+ break;
+ default:
+ break;
+ }
+}
+
QQuickDialog::QQuickDialog(QObject *parent)
: QQuickPopup(*(new QQuickDialogPrivate), parent)
{
@@ -188,12 +252,14 @@ void QQuickDialog::setHeader(QQuickItem *header)
if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldHeader)) {
disconnect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept);
disconnect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject);
+ QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
if (d->buttonBox == buttonBox)
d->buttonBox = nullptr;
}
if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(header)) {
connect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept);
connect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject);
+ QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
d->buttonBox = buttonBox;
buttonBox->setStandardButtons(d->standardButtons);
}
@@ -235,12 +301,14 @@ void QQuickDialog::setFooter(QQuickItem *footer)
if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(oldFooter)) {
disconnect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept);
disconnect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject);
+ QObjectPrivate::disconnect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
if (d->buttonBox == buttonBox)
d->buttonBox = nullptr;
}
if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(footer)) {
connect(buttonBox, &QQuickDialogButtonBox::accepted, this, &QQuickDialog::accept);
connect(buttonBox, &QQuickDialogButtonBox::rejected, this, &QQuickDialog::reject);
+ QObjectPrivate::connect(buttonBox, &QQuickDialogButtonBox::clicked, d, &QQuickDialogPrivate::handleClick);
d->buttonBox = buttonBox;
buttonBox->setStandardButtons(d->standardButtons);
}
@@ -301,16 +369,59 @@ void QQuickDialog::setStandardButtons(QPlatformDialogHelper::StandardButtons but
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod AbstractButton QtQuick.Controls::Dialog::standardButton(StandardButton button)
+
+ Returns the specified standard \a button, or \c null if it does not exist.
+
+ \sa standardButtons
+*/
+QQuickAbstractButton *QQuickDialog::standardButton(QPlatformDialogHelper::StandardButton button) const
+{
+ Q_D(const QQuickDialog);
+ if (!d->buttonBox)
+ return nullptr;
+ return d->buttonBox->standardButton(button);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty int QtQuick.Controls::Dialog::result
+
+ This property holds the result code.
+
+ Standard result codes:
+ \value Dialog.Accepted The dialog was accepted.
+ \value Dialog.Rejected The dialog was rejected.
+
+ \sa accept(), reject(), done()
+*/
+int QQuickDialog::result() const
+{
+ Q_D(const QQuickDialog);
+ return d->result;
+}
+
+void QQuickDialog::setResult(int result)
+{
+ Q_D(QQuickDialog);
+ if (d->result == result)
+ return;
+
+ d->result = result;
+ emit resultChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::Dialog::accept()
Closes the dialog and emits the \l accepted() signal.
- \sa reject()
+ \sa reject(), done()
*/
void QQuickDialog::accept()
{
- close();
- emit accepted();
+ done(Accepted);
}
/*!
@@ -318,12 +429,32 @@ void QQuickDialog::accept()
Closes the dialog and emits the \l rejected() signal.
- \sa accept()
+ \sa accept(), done()
*/
void QQuickDialog::reject()
{
+ done(Rejected);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Dialog::done(int result)
+
+ Closes the dialog, sets the \a result, and emits \l accepted() or
+ \l rejected() depending on whether the result is \c Dialog.Accepted
+ or \c Dialog.Rejected, respectively.
+
+ \sa accept(), reject(), result
+*/
+void QQuickDialog::done(int result)
+{
close();
- emit rejected();
+ setResult(result);
+
+ if (result == Accepted)
+ emit accepted();
+ else if (result == Rejected)
+ emit rejected();
}
void QQuickDialog::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
diff --git a/src/quicktemplates2/qquickdialog_p.h b/src/quicktemplates2/qquickdialog_p.h
index 97c90a59..d22685b6 100644
--- a/src/quicktemplates2/qquickdialog_p.h
+++ b/src/quicktemplates2/qquickdialog_p.h
@@ -54,6 +54,7 @@
QT_BEGIN_NAMESPACE
class QQuickDialogPrivate;
+class QQuickAbstractButton;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialog : public QQuickPopup
{
@@ -62,6 +63,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDialog : public QQuickPopup
Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL)
Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL)
Q_PROPERTY(QPlatformDialogHelper::StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(int result READ result WRITE setResult NOTIFY resultChanged FINAL REVISION 3)
Q_FLAGS(QPlatformDialogHelper::StandardButtons)
public:
@@ -78,19 +81,33 @@ public:
QPlatformDialogHelper::StandardButtons standardButtons() const;
void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons);
+ Q_REVISION(3) Q_INVOKABLE QQuickAbstractButton *standardButton(QPlatformDialogHelper::StandardButton button) const;
+
+ // 2.3 (Qt 5.10)
+ enum StandardCode { Rejected, Accepted };
+ Q_ENUM(StandardCode)
+
+ int result() const;
+ void setResult(int result);
public Q_SLOTS:
- void accept();
- void reject();
+ virtual void accept();
+ virtual void reject();
+ virtual void done(int result);
Q_SIGNALS:
void accepted();
void rejected();
-
void titleChanged();
void headerChanged();
void footerChanged();
void standardButtonsChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void applied();
+ Q_REVISION(3) void reset();
+ Q_REVISION(3) void discarded();
+ Q_REVISION(3) void helpRequested();
+ Q_REVISION(3) void resultChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
diff --git a/src/quicktemplates2/qquickdialog_p_p.h b/src/quicktemplates2/qquickdialog_p_p.h
index 13885ca9..e26182ac 100644
--- a/src/quicktemplates2/qquickdialog_p_p.h
+++ b/src/quicktemplates2/qquickdialog_p_p.h
@@ -48,11 +48,14 @@
// We mean it.
//
+#include <QtQuickTemplates2/private/qquickdialog_p.h>
#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
#include <QtQuickTemplates2/private/qquickpagelayout_p_p.h>
+#include <QtGui/qpa/qplatformdialoghelper.h>
QT_BEGIN_NAMESPACE
+class QQuickAbstractButton;
class QQuickDialogButtonBox;
class QQuickDialogPrivate : public QQuickPopupPrivate
@@ -60,13 +63,18 @@ class QQuickDialogPrivate : public QQuickPopupPrivate
Q_DECLARE_PUBLIC(QQuickDialog)
public:
- QQuickDialogPrivate() : buttonBox(nullptr) { }
+ QQuickDialogPrivate() : result(0), buttonBox(nullptr) { }
static QQuickDialogPrivate *get(QQuickDialog *dialog)
{
return dialog->d_func();
}
+ static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button);
+
+ void handleClick(QQuickAbstractButton *button);
+
+ int result;
QString title;
QQuickDialogButtonBox *buttonBox;
QScopedPointer<QQuickPageLayout> layout;
diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp
index 5f7f488e..cd971139 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox.cpp
+++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -38,6 +38,7 @@
#include "qquickdialogbuttonbox_p_p.h"
#include "qquickabstractbutton_p.h"
#include "qquickbutton_p.h"
+#include "qquickdialog_p_p.h"
#include <QtCore/qpointer.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -122,6 +123,36 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::DialogButtonBox::applied()
+
+ This signal is emitted when a button defined with the \c ApplyRole is
+ clicked.
+
+ \sa discarded(), reset()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::DialogButtonBox::reset()
+
+ This signal is emitted when a button defined with the \c ResetRole is
+ clicked.
+
+ \sa discarded(), applied()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlsignal QtQuick.Controls::DialogButtonBox::discarded()
+
+ This signal is emitted when a button defined with the \c DiscardRole is
+ clicked.
+
+ \sa reset(), applied()
+*/
+
+/*!
\qmlsignal QtQuick.Controls::DialogButtonBox::helpRequested()
This signal is emitted when a button defined with the \c HelpRole is clicked.
@@ -137,12 +168,6 @@ QT_BEGIN_NAMESPACE
\sa accepted(), rejected(), helpRequested()
*/
-static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button)
-{
- const QQuickDialogButtonBoxAttached *attached = qobject_cast<QQuickDialogButtonBoxAttached *>(qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, false));
- return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole;
-}
-
QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate()
: alignment(0),
position(QQuickDialogButtonBox::Footer),
@@ -235,8 +260,8 @@ void QQuickDialogButtonBoxPrivate::updateLayout()
struct ButtonLayout {
bool operator()(QQuickAbstractButton *first, QQuickAbstractButton *second)
{
- const QPlatformDialogHelper::ButtonRole firstRole = buttonRole(first);
- const QPlatformDialogHelper::ButtonRole secondRole = buttonRole(second);
+ const QPlatformDialogHelper::ButtonRole firstRole = QQuickDialogPrivate::buttonRole(first);
+ const QPlatformDialogHelper::ButtonRole secondRole = QQuickDialogPrivate::buttonRole(second);
if (firstRole != secondRole && firstRole != QPlatformDialogHelper::InvalidRole && secondRole != QPlatformDialogHelper::InvalidRole) {
const int *l = m_layout;
@@ -280,7 +305,7 @@ void QQuickDialogButtonBoxPrivate::handleClick()
// or change its role. Now changing the role is not possible yet, but arguably
// both clicked and accepted/rejected/etc. should be emitted "atomically"
// depending on whatever role the button had at the time of the click.
- const QPlatformDialogHelper::ButtonRole role = buttonRole(button);
+ const QPlatformDialogHelper::ButtonRole role = QQuickDialogPrivate::buttonRole(button);
QPointer<QQuickDialogButtonBox> guard(q);
emit q->clicked(button);
@@ -297,6 +322,15 @@ void QQuickDialogButtonBoxPrivate::handleClick()
case QPlatformDialogHelper::NoRole:
emit q->rejected();
break;
+ case QPlatformDialogHelper::ApplyRole:
+ emit q->applied();
+ break;
+ case QPlatformDialogHelper::ResetRole:
+ emit q->reset();
+ break;
+ case QPlatformDialogHelper::DestructiveRole:
+ emit q->discarded();
+ break;
case QPlatformDialogHelper::HelpRole:
emit q->helpRequested();
break;
diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p.h
index 9bd92c79..1e3cdeef 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox_p.h
+++ b/src/quicktemplates2/qquickdialogbuttonbox_p.h
@@ -99,11 +99,14 @@ Q_SIGNALS:
void rejected();
void helpRequested();
void clicked(QQuickAbstractButton *button);
-
void positionChanged();
void alignmentChanged();
void standardButtonsChanged();
void delegateChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void applied();
+ Q_REVISION(3) void reset();
+ Q_REVISION(3) void discarded();
protected:
void updatePolish() override;
diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp
index f5df8015..022c9dbf 100644
--- a/src/quicktemplates2/qquickdrawer.cpp
+++ b/src/quicktemplates2/qquickdrawer.cpp
@@ -232,6 +232,16 @@ void QQuickDrawerPrivate::reposition()
QQuickPopupPrivate::reposition();
}
+void QQuickDrawerPrivate::showOverlay()
+{
+ // managed in setPosition()
+}
+
+void QQuickDrawerPrivate::hideOverlay()
+{
+ // managed in setPosition()
+}
+
void QQuickDrawerPrivate::resizeOverlay()
{
if (!dimmer || !window)
diff --git a/src/quicktemplates2/qquickdrawer_p_p.h b/src/quicktemplates2/qquickdrawer_p_p.h
index aff6e81e..0ceaf2e7 100644
--- a/src/quicktemplates2/qquickdrawer_p_p.h
+++ b/src/quicktemplates2/qquickdrawer_p_p.h
@@ -48,9 +48,9 @@
// We mean it.
//
-#include "qquickdrawer_p.h"
-#include "qquickpopup_p_p.h"
-#include "qquickvelocitycalculator_p_p.h"
+#include <QtQuickTemplates2/private/qquickdrawer_p.h>
+#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
+#include <QtQuickTemplates2/private/qquickvelocitycalculator_p_p.h>
QT_BEGIN_NAMESPACE
@@ -70,6 +70,8 @@ public:
qreal positionAt(const QPointF &point) const;
void reposition() override;
+ void showOverlay() override;
+ void hideOverlay() override;
void resizeOverlay() override;
bool startDrag(QEvent *event);
diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp
index 674f5b18..c127192c 100644
--- a/src/quicktemplates2/qquickgroupbox.cpp
+++ b/src/quicktemplates2/qquickgroupbox.cpp
@@ -182,6 +182,11 @@ QFont QQuickGroupBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::GroupBoxTitleFont);
}
+QPalette QQuickGroupBox::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::GroupBoxPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickGroupBox::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickgroupbox_p.h b/src/quicktemplates2/qquickgroupbox_p.h
index 0468462e..b46d91fd 100644
--- a/src/quicktemplates2/qquickgroupbox_p.h
+++ b/src/quicktemplates2/qquickgroupbox_p.h
@@ -78,6 +78,7 @@ protected:
void componentComplete() override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickicon.cpp b/src/quicktemplates2/qquickicon.cpp
new file mode 100644
index 00000000..0b0127d3
--- /dev/null
+++ b/src/quicktemplates2/qquickicon.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickicon_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickIconPrivate : public QSharedData
+{
+public:
+ QQuickIconPrivate()
+ : width(0),
+ height(0),
+ color(Qt::transparent)
+ {
+ }
+
+ QString name;
+ QUrl source;
+ int width;
+ int height;
+ QColor color;
+};
+
+QQuickIcon::QQuickIcon()
+ : d(new QQuickIconPrivate)
+{
+}
+
+QQuickIcon::QQuickIcon(const QQuickIcon &other)
+ : d(other.d)
+{
+}
+
+QQuickIcon::~QQuickIcon()
+{
+}
+
+QQuickIcon &QQuickIcon::operator=(const QQuickIcon &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool QQuickIcon::operator==(const QQuickIcon &other) const
+{
+ return d == other.d || (d->name == other.d->name
+ && d->source == other.d->source
+ && d->width == other.d->width
+ && d->height == other.d->height
+ && d->color == other.d->color);
+}
+
+bool QQuickIcon::operator!=(const QQuickIcon &other) const
+{
+ return !(*this == other);
+}
+
+bool QQuickIcon::isEmpty() const
+{
+ return d->name.isEmpty() && d->source.isEmpty();
+}
+
+QString QQuickIcon::name() const
+{
+ return d->name;
+}
+
+void QQuickIcon::setName(const QString &name)
+{
+ d->name = name;
+}
+
+QUrl QQuickIcon::source() const
+{
+ return d->source;
+}
+
+void QQuickIcon::setSource(const QUrl &source)
+{
+ d->source = source;
+}
+
+int QQuickIcon::width() const
+{
+ return d->width;
+}
+
+void QQuickIcon::setWidth(int width)
+{
+ d->width = width;
+}
+
+int QQuickIcon::height() const
+{
+ return d->height;
+}
+
+void QQuickIcon::setHeight(int height)
+{
+ d->height = height;
+}
+
+QColor QQuickIcon::color() const
+{
+ return d->color;
+}
+
+void QQuickIcon::setColor(const QColor &color)
+{
+ d->color = color;
+}
+
+void QQuickIcon::resetColor()
+{
+ d->color = Qt::transparent;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickicon_p.h b/src/quicktemplates2/qquickicon_p.h
new file mode 100644
index 00000000..6e28f2a9
--- /dev/null
+++ b/src/quicktemplates2/qquickicon_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKICON_P_H
+#define QQUICKICON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qshareddata.h>
+#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickIconPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickIcon
+{
+ Q_GADGET
+ Q_PROPERTY(QString name READ name WRITE setName FINAL)
+ Q_PROPERTY(QUrl source READ source WRITE setSource FINAL)
+ Q_PROPERTY(int width READ width WRITE setWidth FINAL)
+ Q_PROPERTY(int height READ height WRITE setHeight FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor RESET resetColor FINAL)
+
+public:
+ QQuickIcon();
+ QQuickIcon(const QQuickIcon &other);
+ ~QQuickIcon();
+
+ QQuickIcon& operator=(const QQuickIcon &other);
+ bool operator==(const QQuickIcon &other) const;
+ bool operator!=(const QQuickIcon &other) const;
+
+ bool isEmpty() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QUrl source() const;
+ void setSource(const QUrl &source);
+
+ int width() const;
+ void setWidth(int width);
+
+ int height() const;
+ void setHeight(int height);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+ void resetColor();
+
+private:
+ QSharedDataPointer<QQuickIconPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKICON_P_H
diff --git a/src/quicktemplates2/qquickitemdelegate.cpp b/src/quicktemplates2/qquickitemdelegate.cpp
index 1b93c145..044141f2 100644
--- a/src/quicktemplates2/qquickitemdelegate.cpp
+++ b/src/quicktemplates2/qquickitemdelegate.cpp
@@ -56,8 +56,8 @@ QT_BEGIN_NAMESPACE
in various views and controls, such as \l ListView and \l ComboBox.
ItemDelegate inherits its API from AbstractButton. For instance, you can set
- \l {AbstractButton::text}{text}, and react to \l {AbstractButton::clicked}{clicks}
- using the AbstractButton API.
+ \l {AbstractButton::text}{text}, display an \l {Icons in Qt Quick Controls 2}{icon},
+ and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton API.
\snippet qtquickcontrols2-itemdelegate.qml 1
@@ -125,6 +125,11 @@ QFont QQuickItemDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont);
}
+QPalette QQuickItemDelegate::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ItemViewPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickItemDelegate::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickitemdelegate_p.h b/src/quicktemplates2/qquickitemdelegate_p.h
index a162ddee..5d52f764 100644
--- a/src/quicktemplates2/qquickitemdelegate_p.h
+++ b/src/quicktemplates2/qquickitemdelegate_p.h
@@ -70,6 +70,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp
index 418a7834..d27393ae 100644
--- a/src/quicktemplates2/qquicklabel.cpp
+++ b/src/quicktemplates2/qquicklabel.cpp
@@ -80,8 +80,7 @@ QT_BEGIN_NAMESPACE
*/
QQuickLabelPrivate::QQuickLabelPrivate()
- : background(nullptr),
- accessibleAttached(nullptr)
+ : background(nullptr)
{
#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
@@ -109,25 +108,76 @@ void QQuickLabelPrivate::resolveFont()
inheritFont(QQuickControlPrivate::parentFont(q));
}
-void QQuickLabelPrivate::inheritFont(const QFont &f)
+void QQuickLabelPrivate::inheritFont(const QFont &font)
{
- Q_Q(QQuickLabel);
- QFont parentFont = font.resolve(f);
- parentFont.resolve(font.resolve() | f.resolve());
+ QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
+ parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());
const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::LabelFont);
const QFont resolvedFont = parentFont.resolve(defaultFont);
- const bool changed = resolvedFont != sourceFont;
- q->QQuickText::setFont(resolvedFont);
- if (changed)
+ setFont_helper(resolvedFont);
+}
+
+/*!
+ \internal
+
+ Assign \a font to this control, and propagate it to all children.
+*/
+void QQuickLabelPrivate::updateFont(const QFont &font)
+{
+ Q_Q(QQuickLabel);
+ QFont oldFont = sourceFont;
+ q->QQuickText::setFont(font);
+
+ QQuickControlPrivate::updateFontRecur(q, font);
+
+ if (oldFont != font)
emit q->fontChanged();
}
+/*!
+ \internal
+
+ Determine which palette is implicitly imposed on this control by its ancestors
+ and QGuiApplication::palette, resolve this against its own palette (attributes from
+ the implicit palette are copied over). Then propagate this palette to this
+ control's children.
+*/
+void QQuickLabelPrivate::resolvePalette()
+{
+ Q_Q(QQuickLabel);
+ inheritPalette(QQuickControlPrivate::parentPalette(q));
+}
+
+void QQuickLabelPrivate::inheritPalette(const QPalette &palette)
+{
+ QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
+ parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());
+
+ const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::LabelPalette);
+ const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);
+
+ setPalette_helper(resolvedPalette);
+}
+
+void QQuickLabelPrivate::updatePalette(const QPalette &palette)
+{
+ Q_Q(QQuickLabel);
+ QPalette oldPalette = resolvedPalette;
+ resolvedPalette = palette;
+
+ QQuickControlPrivate::updatePaletteRecur(q, palette);
+
+ if (oldPalette != palette)
+ emit q->paletteChanged();
+}
+
void QQuickLabelPrivate::textChanged(const QString &text)
{
#if QT_CONFIG(accessibility)
- if (accessibleAttached)
+ Q_Q(QQuickLabel);
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q))
accessibleAttached->setName(text);
#else
Q_UNUSED(text)
@@ -137,17 +187,14 @@ void QQuickLabelPrivate::textChanged(const QString &text)
#if QT_CONFIG(accessibility)
void QQuickLabelPrivate::accessibilityActiveChanged(bool active)
{
- if (accessibleAttached || !active)
+ if (!active)
return;
Q_Q(QQuickLabel);
- accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
- if (accessibleAttached) {
- accessibleAttached->setRole(accessibleRole());
- accessibleAttached->setName(text);
- } else {
- qWarning() << "QQuickLabel: " << q << " QQuickAccessibleAttached object creation failed!";
- }
+ QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
+ Q_ASSERT(accessibleAttached);
+ accessibleAttached->setRole(accessibleRole());
+ accessibleAttached->setName(text);
}
QAccessible::Role QQuickLabelPrivate::accessibleRole() const
@@ -185,10 +232,10 @@ QFont QQuickLabel::font() const
void QQuickLabel::setFont(const QFont &font)
{
Q_D(QQuickLabel);
- if (d->font.resolve() == font.resolve() && d->font == font)
+ if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
return;
- d->font = font;
+ d->extra.value().requestedFont = font;
d->resolveFont();
}
@@ -228,11 +275,44 @@ void QQuickLabel::setBackground(QQuickItem *background)
emit backgroundChanged();
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::Label::palette
+
+ This property holds the palette currently set for the label.
+
+ \sa Control::palette
+*/
+QPalette QQuickLabel::palette() const
+{
+ Q_D(const QQuickLabel);
+ QPalette palette = d->resolvedPalette;
+ if (!isEnabled())
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ return palette;
+}
+
+void QQuickLabel::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickLabel);
+ if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
+ return;
+
+ d->extra.value().requestedPalette = palette;
+ d->resolvePalette();
+}
+
+void QQuickLabel::resetPalette()
+{
+ setPalette(QPalette());
+}
+
void QQuickLabel::classBegin()
{
Q_D(QQuickLabel);
QQuickText::classBegin();
d->resolveFont();
+ d->resolvePalette();
}
void QQuickLabel::componentComplete()
@@ -241,7 +321,7 @@ void QQuickLabel::componentComplete()
d->executeBackground(true);
QQuickText::componentComplete();
#if QT_CONFIG(accessibility)
- if (!d->accessibleAttached && QAccessible::isActive())
+ if (QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
}
@@ -250,8 +330,20 @@ void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::It
{
Q_D(QQuickLabel);
QQuickText::itemChange(change, value);
- if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window))
- d->resolveFont();
+ switch (change) {
+ case ItemEnabledHasChanged:
+ emit paletteChanged();
+ break;
+ case ItemSceneChange:
+ case ItemParentHasChanged:
+ if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
+ d->resolveFont();
+ d->resolvePalette();
+ }
+ break;
+ default:
+ break;
+ }
}
void QQuickLabel::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
diff --git a/src/quicktemplates2/qquicklabel_p.h b/src/quicktemplates2/qquicklabel_p.h
index c31e173b..5486d311 100644
--- a/src/quicktemplates2/qquicklabel_p.h
+++ b/src/quicktemplates2/qquicklabel_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtGui/qpalette.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
@@ -60,6 +61,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickLabel : public QQuickText
Q_OBJECT
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) // override
Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background")
public:
@@ -71,9 +74,16 @@ public:
QQuickItem *background() const;
void setBackground(QQuickItem *background);
+ // 2.3 (Qt 5.10)
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
Q_SIGNALS:
void fontChanged();
void backgroundChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void paletteChanged();
protected:
void classBegin() override;
diff --git a/src/quicktemplates2/qquicklabel_p_p.h b/src/quicktemplates2/qquicklabel_p_p.h
index b8ad2ae7..5f432a22 100644
--- a/src/quicktemplates2/qquicklabel_p_p.h
+++ b/src/quicktemplates2/qquicklabel_p_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtQml/private/qlazilyallocated_p.h>
#include <QtQuick/private/qquicktext_p_p.h>
#include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h>
@@ -57,8 +58,6 @@
QT_BEGIN_NAMESPACE
-class QQuickAccessibleAttached;
-
class QQuickLabelPrivate : public QQuickTextPrivate
#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
@@ -76,7 +75,22 @@ public:
}
void resolveFont();
- void inheritFont(const QFont &f);
+ void inheritFont(const QFont &font);
+ void updateFont(const QFont &font);
+ inline void setFont_helper(const QFont &font) {
+ if (sourceFont.resolve() == font.resolve() && sourceFont == font)
+ return;
+ updateFont(font);
+ }
+
+ void resolvePalette();
+ void inheritPalette(const QPalette &palette);
+ void updatePalette(const QPalette &palette);
+ inline void setPalette_helper(const QPalette &palette) {
+ if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette)
+ return;
+ updatePalette(palette);
+ }
void textChanged(const QString &text);
@@ -87,9 +101,14 @@ public:
void executeBackground(bool complete = false);
- QFont font;
+ struct ExtraData {
+ QFont requestedFont;
+ QPalette requestedPalette;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
+ QPalette resolvedPalette;
QQuickDeferredPointer<QQuickItem> background;
- QQuickAccessibleAttached *accessibleAttached;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp
index 52c048a6..7ebeb344 100644
--- a/src/quicktemplates2/qquickmenu.cpp
+++ b/src/quicktemplates2/qquickmenu.cpp
@@ -36,10 +36,22 @@
#include "qquickmenu_p.h"
#include "qquickmenu_p_p.h"
-#include "qquickmenuitem_p.h"
-#include "qquickcontrol_p_p.h"
+#include "qquickmenuitem_p_p.h"
+#include "qquickmenubaritem_p.h"
+#include "qquickmenubar_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickaction_p.h"
#include <QtGui/qevent.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+#include <QtQml/private/qv4variantobject_p.h>
+#include <QtQml/private/qv4qobjectwrapper_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
@@ -49,6 +61,9 @@
QT_BEGIN_NAMESPACE
+// copied from qfusionstyle.cpp
+static const int SUBMENU_DELAY = 225;
+
/*!
\qmltype Menu
\inherits Popup
@@ -67,6 +82,37 @@ QT_BEGIN_NAMESPACE
\li Popup menus; for example, a menu that is shown after clicking a button
\endlist
+ When used as a context menu, the recommended way of opening the menu is to call
+ \l popup(). Unless a position is explicitly specified, the menu is positioned at
+ the mouse cursor on desktop platforms that have a mouse cursor available, and
+ otherwise centered over its parent item.
+
+ \code
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: {
+ if (mouse.button === Qt.RightButton)
+ contextMenu.popup()
+ }
+ onPressAndHold: {
+ if (mouse.source === Qt.MouseEventNotSynthesized)
+ contextMenu.popup()
+ }
+
+ Menu {
+ id: contextMenu
+ MenuItem { text: "Cut" }
+ MenuItem { text: "Copy" }
+ MenuItem { text: "Paste" }
+ }
+ }
+ \endcode
+
+ When used as a popup menu, it is easiest to specify the position by specifying
+ the desired \l {Popup::}{x} and \l {Popup::}{y} coordinates using the respective
+ properties, and call \l {Popup::}{open()} to open the menu.
+
\code
Button {
id: fileButton
@@ -90,6 +136,30 @@ QT_BEGIN_NAMESPACE
}
\endcode
+ Since QtQuick.Controls 2.3 (Qt 5.10), it is also possible to create sub-menus
+ and declare Action objects inside Menu:
+
+ \code
+ Menu {
+ Action { text: "Cut" }
+ Action { text: "Copy" }
+ Action { text: "Paste" }
+
+ MenuSeparator { }
+
+ Menu {
+ title: "Find/Replace"
+ Action { text: "Find Next" }
+ Action { text: "Find Previous" }
+ Action { text: "Replace" }
+ }
+ }
+ \endcode
+
+ Sub-menus are \l {cascade}{cascading} by default on desktop platforms
+ that have a mouse cursor available. Non-cascading menus are shown one
+ menu at a time, and centered over the parent menu.
+
Typically, menu items are statically declared as children of the menu, but
Menu also provides API to \l {addItem}{add}, \l {insertItem}{insert},
\l {moveItem}{move} and \l {removeItem}{remove} items dynamically. The
@@ -99,12 +169,28 @@ QT_BEGIN_NAMESPACE
Although \l {MenuItem}{MenuItems} are most commonly used with Menu, it can
contain any type of item.
- \sa {Customizing Menu}, {Menu Controls}, {Popup Controls}
+ \sa {Customizing Menu}, MenuItem, {Menu Controls}, {Popup Controls}
*/
+static const QQuickPopup::ClosePolicy cascadingSubMenuClosePolicy = QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent;
+
+static bool shouldCascade()
+{
+#if QT_CONFIG(cursor)
+ return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
+#else
+ return false;
+#endif
+}
+
QQuickMenuPrivate::QQuickMenuPrivate()
- : contentItem(nullptr),
- contentModel(nullptr)
+ : cascade(shouldCascade()),
+ hoverTimer(0),
+ currentIndex(-1),
+ overlap(0),
+ contentItem(nullptr),
+ contentModel(nullptr),
+ delegate(nullptr)
{
Q_Q(QQuickMenu);
contentModel = new QQmlObjectModel(q);
@@ -129,9 +215,12 @@ void QQuickMenuPrivate::insertItem(int index, QQuickItem *item)
QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
if (menuItem) {
Q_Q(QQuickMenu);
- QObjectPrivate::connect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed);
- QObject::connect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close);
+ QQuickMenuItemPrivate::get(menuItem)->setMenu(q);
+ if (QQuickMenu *subMenu = menuItem->subMenu())
+ QQuickMenuPrivate::get(subMenu)->setParentMenu(q);
+ QObjectPrivate::connect(menuItem, &QQuickMenuItem::triggered, this, &QQuickMenuPrivate::onItemTriggered);
QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged);
+ QObjectPrivate::connect(menuItem, &QQuickControl::hoveredChanged, this, &QQuickMenuPrivate::onItemHovered);
}
}
@@ -150,13 +239,63 @@ void QQuickMenuPrivate::removeItem(int index, QQuickItem *item)
QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
if (menuItem) {
- Q_Q(QQuickMenu);
- QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed);
- QObject::disconnect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close);
+ QQuickMenuItemPrivate::get(menuItem)->setMenu(nullptr);
+ if (QQuickMenu *subMenu = menuItem->subMenu())
+ QQuickMenuPrivate::get(subMenu)->setParentMenu(nullptr);
+ QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::triggered, this, &QQuickMenuPrivate::onItemTriggered);
QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged);
+ QObjectPrivate::disconnect(menuItem, &QQuickControl::hoveredChanged, this, &QQuickMenuPrivate::onItemHovered);
}
}
+QQuickItem *QQuickMenuPrivate::beginCreateItem()
+{
+ Q_Q(QQuickMenu);
+ if (!delegate)
+ return nullptr;
+
+ QQmlContext *creationContext = delegate->creationContext();
+ if (!creationContext)
+ creationContext = qmlContext(q);
+ QQmlContext *context = new QQmlContext(creationContext, q);
+ context->setContextObject(q);
+
+ QObject *object = delegate->beginCreate(context);
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (!item)
+ delete object;
+
+ QQml_setParent_noEvent(item, q);
+
+ return item;
+}
+
+void QQuickMenuPrivate::completeCreateItem()
+{
+ if (!delegate)
+ return;
+
+ delegate->completeCreate();
+}
+
+QQuickItem *QQuickMenuPrivate::createItem(QQuickMenu *menu)
+{
+ QQuickItem *item = beginCreateItem();
+ if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item))
+ QQuickMenuItemPrivate::get(menuItem)->setSubMenu(menu);
+ completeCreateItem();
+ return item;
+}
+
+QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action)
+{
+ QQuickItem *item = beginCreateItem();
+ if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
+ button->setAction(action);
+ completeCreateItem();
+ return item;
+}
+
void QQuickMenuPrivate::resizeItem(QQuickItem *item)
{
if (!item || !contentItem)
@@ -222,12 +361,105 @@ void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange,
resizeItems();
}
-void QQuickMenuPrivate::onItemPressed()
+void QQuickMenuPrivate::reposition()
{
Q_Q(QQuickMenu);
- QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
- if (item)
- item->forceActiveFocus();
+ if (parentMenu) {
+ if (cascade) {
+ if (popupItem->isMirrored())
+ q->setPosition(QPointF(-q->width() - parentMenu->leftPadding() + q->overlap(), -q->topPadding()));
+ else if (parentItem)
+ q->setPosition(QPointF(parentItem->width() + parentMenu->rightPadding() - q->overlap(), -q->topPadding()));
+ } else {
+ q->setPosition(QPointF(parentMenu->x() + (parentMenu->width() - q->width()) / 2,
+ parentMenu->y() + (parentMenu->height() - q->height()) / 2));
+ }
+ }
+ QQuickPopupPrivate::reposition();
+}
+
+bool QQuickMenuPrivate::prepareEnterTransition()
+{
+ Q_Q(QQuickMenu);
+ if (parentMenu && !cascade)
+ parentMenu->close();
+
+ // If a cascading sub-menu doesn't have enough space to open on
+ // the right, it flips on the other side of the parent menu.
+ allowHorizontalFlip = cascade && parentMenu;
+
+ if (!QQuickPopupPrivate::prepareEnterTransition())
+ return false;
+
+ if (!hasClosePolicy) {
+ if (cascade && parentMenu)
+ closePolicy = cascadingSubMenuClosePolicy;
+ else
+ q->resetClosePolicy();
+ }
+ return true;
+}
+
+bool QQuickMenuPrivate::prepareExitTransition()
+{
+ if (!QQuickPopupPrivate::prepareExitTransition())
+ return false;
+
+ stopHoverTimer();
+
+ QQuickMenu *subMenu = currentSubMenu();
+ while (subMenu) {
+ QPointer<QQuickMenuItem> currentSubMenuItem = QQuickMenuPrivate::get(subMenu)->currentItem;
+ subMenu->close();
+ subMenu = currentSubMenuItem ? currentSubMenuItem->subMenu() : nullptr;
+ }
+ return true;
+}
+
+bool QQuickMenuPrivate::blockInput(QQuickItem *item, const QPointF &point) const
+{
+ // keep the parent menu open when a cascading sub-menu (this menu) is interacted with
+ return (cascade && parentMenu && contains(point)) || QQuickPopupPrivate::blockInput(item, point);
+}
+
+void QQuickMenuPrivate::onItemHovered()
+{
+ Q_Q(QQuickMenu);
+ QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
+ if (!button || !button->isHovered() || QQuickAbstractButtonPrivate::get(button)->touchId != -1)
+ return;
+
+ QQuickMenuItem *oldCurrentItem = currentItem;
+
+ int index = contentModel->indexOf(button, nullptr);
+ if (index != -1) {
+ setCurrentIndex(index, Qt::OtherFocusReason);
+ if (oldCurrentItem != currentItem) {
+ if (oldCurrentItem) {
+ QQuickMenu *subMenu = oldCurrentItem->subMenu();
+ if (subMenu)
+ subMenu->close();
+ }
+ if (currentItem) {
+ QQuickMenu *subMenu = currentItem->menu();
+ if (subMenu && subMenu->cascade())
+ startHoverTimer();
+ }
+ }
+ }
+}
+
+void QQuickMenuPrivate::onItemTriggered()
+{
+ Q_Q(QQuickMenu);
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(q->sender());
+ if (!item)
+ return;
+
+ if (QQuickMenu *subMenu = item->subMenu())
+ subMenu->popup(subMenu->itemAt(0));
+ else
+ q->dismiss();
}
void QQuickMenuPrivate::onItemActiveFocusChanged()
@@ -238,52 +470,158 @@ void QQuickMenuPrivate::onItemActiveFocusChanged()
return;
int indexOfItem = contentModel->indexOf(item, nullptr);
- setCurrentIndex(indexOfItem);
+ QQuickControl *control = qobject_cast<QQuickControl *>(item);
+ setCurrentIndex(indexOfItem, control ? control->focusReason() : Qt::OtherFocusReason);
}
-int QQuickMenuPrivate::currentIndex() const
+QQuickMenu *QQuickMenuPrivate::currentSubMenu() const
{
- QVariant index = contentItem->property("currentIndex");
- if (!index.isValid())
- return -1;
- return index.toInt();
+ if (!currentItem)
+ return nullptr;
+
+ return currentItem->subMenu();
}
-void QQuickMenuPrivate::setCurrentIndex(int index)
+void QQuickMenuPrivate::setParentMenu(QQuickMenu *parent)
{
- contentItem->setProperty("currentIndex", index);
+ Q_Q(QQuickMenu);
+ if (parentMenu == parent)
+ return;
+
+ if (parentMenu) {
+ QObject::disconnect(parentMenu.data(), &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
+ disconnect(parentMenu.data(), &QQuickMenu::parentChanged, this, &QQuickMenuPrivate::resolveParentItem);
+ }
+ if (parent) {
+ QObject::connect(parent, &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
+ connect(parent, &QQuickMenu::parentChanged, this, &QQuickMenuPrivate::resolveParentItem);
+ }
+
+ parentMenu = parent;
+ q->resetCascade();
+ resolveParentItem();
+}
+
+static QQuickItem *findParentMenuItem(QQuickMenu *subMenu)
+{
+ QQuickMenu *menu = QQuickMenuPrivate::get(subMenu)->parentMenu;
+ for (int i = 0; i < QQuickMenuPrivate::get(menu)->contentModel->count(); ++i) {
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(menu->itemAt(i));
+ if (item && item->subMenu() == subMenu)
+ return item;
+ }
+ return nullptr;
+}
+
+void QQuickMenuPrivate::resolveParentItem()
+{
+ Q_Q(QQuickMenu);
+ if (!parentMenu)
+ q->resetParentItem();
+ else if (!cascade)
+ q->setParentItem(parentMenu->parentItem());
+ else
+ q->setParentItem(findParentMenuItem(q));
}
-void QQuickMenuPrivate::activateNextItem()
+void QQuickMenuPrivate::propagateKeyEvent(QKeyEvent *event)
{
- int index = currentIndex();
+ if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(parentItem)) {
+ if (QQuickMenu *menu = menuItem->menu())
+ QQuickMenuPrivate::get(menu)->propagateKeyEvent(event);
+ } else if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(parentItem)) {
+ if (QQuickMenuBar *menuBar = menuBarItem->menuBar()) {
+ event->accept();
+ QCoreApplication::sendEvent(menuBar, event);
+ }
+ }
+}
+
+void QQuickMenuPrivate::startHoverTimer()
+{
+ Q_Q(QQuickMenu);
+ stopHoverTimer();
+ hoverTimer = q->startTimer(SUBMENU_DELAY);
+}
+
+void QQuickMenuPrivate::stopHoverTimer()
+{
+ Q_Q(QQuickMenu);
+ if (!hoverTimer)
+ return;
+
+ q->killTimer(hoverTimer);
+ hoverTimer = 0;
+}
+
+void QQuickMenuPrivate::setCurrentIndex(int index, Qt::FocusReason reason)
+{
+ Q_Q(QQuickMenu);
+ if (currentIndex == index)
+ return;
+
+ QQuickMenuItem *newCurrentItem = qobject_cast<QQuickMenuItem *>(itemAt(index));
+ if (currentItem != newCurrentItem) {
+ stopHoverTimer();
+ if (currentItem) {
+ currentItem->setHighlighted(false);
+ if (!newCurrentItem && window) {
+ QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem;
+ if (focusItem)
+ QQuickWindowPrivate::get(window)->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
+ }
+ }
+ if (newCurrentItem) {
+ newCurrentItem->setHighlighted(true);
+ newCurrentItem->forceActiveFocus(reason);
+ }
+ currentItem = newCurrentItem;
+ }
+
+ currentIndex = index;
+ emit q->currentIndexChanged();
+}
+
+bool QQuickMenuPrivate::activateNextItem()
+{
+ int index = currentIndex;
int count = contentModel->count();
while (++index < count) {
QQuickItem *item = itemAt(index);
if (!item || !item->activeFocusOnTab())
continue;
- item->forceActiveFocus(Qt::TabFocusReason);
- break;
+ setCurrentIndex(index, Qt::TabFocusReason);
+ return true;
}
+ return false;
}
-void QQuickMenuPrivate::activatePreviousItem()
+bool QQuickMenuPrivate::activatePreviousItem()
{
- int index = currentIndex();
+ int index = currentIndex;
while (--index >= 0) {
QQuickItem *item = itemAt(index);
if (!item || !item->activeFocusOnTab())
continue;
- item->forceActiveFocus(Qt::BacktabFocusReason);
- break;
+ setCurrentIndex(index, Qt::BacktabFocusReason);
+ return true;
}
+ return false;
}
void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
{
- QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data);
- QQuickMenu *q = static_cast<QQuickMenu *>(prop->object);
+ QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object);
+ QQuickMenuPrivate *p = QQuickMenuPrivate::get(q);
+
QQuickItem *item = qobject_cast<QQuickItem *>(obj);
+ if (!item) {
+ if (QQuickAction *action = qobject_cast<QQuickAction *>(obj))
+ item = p->createItem(action);
+ else if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj))
+ item = p->createItem(menu);
+ }
+
if (item) {
if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) {
QQuickItemPrivate::get(item)->addItemChangeListener(p, QQuickItemPrivate::SiblingOrder);
@@ -298,26 +636,28 @@ void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObj
int QQuickMenuPrivate::contentData_count(QQmlListProperty<QObject> *prop)
{
- QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data);
- return p->contentData.count();
+ QQuickMenu *q = static_cast<QQuickMenu *>(prop->object);
+ return QQuickMenuPrivate::get(q)->contentData.count();
}
QObject *QQuickMenuPrivate::contentData_at(QQmlListProperty<QObject> *prop, int index)
{
- QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data);
- return p->contentData.value(index);
+ QQuickMenu *q = static_cast<QQuickMenu *>(prop->object);
+ return QQuickMenuPrivate::get(q)->contentData.value(index);
}
void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
{
- QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data);
- p->contentData.clear();
+ QQuickMenu *q = static_cast<QQuickMenu *>(prop->object);
+ QQuickMenuPrivate::get(q)->contentData.clear();
}
QQuickMenu::QQuickMenu(QObject *parent)
: QQuickPopup(*(new QQuickMenuPrivate), parent)
{
+ Q_D(QQuickMenu);
setFocus(true);
+ connect(d->contentModel, &QQmlObjectModel::countChanged, this, &QQuickMenu::countChanged);
}
/*!
@@ -386,22 +726,247 @@ void QQuickMenu::moveItem(int from, int to)
}
/*!
+ \deprecated
\qmlmethod void QtQuick.Controls::Menu::removeItem(int index)
- Removes the item at \a index.
+ Use Menu::removeItem(Item) or Menu::takeItem(int) instead.
+*/
+void QQuickMenu::removeItem(const QVariant &var)
+{
+ if (var.userType() == QMetaType::Nullptr)
+ return;
+
+ if (QQuickItem *item = var.value<QQuickItem *>())
+ removeItem(item);
+ else
+ takeItem(var.toInt());
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::removeItem(Item item)
+
+ Removes and destroys the specified \a item.
+*/
+void QQuickMenu::removeItem(QQuickItem *item)
+{
+ Q_D(QQuickMenu);
+ if (!item)
+ return;
+
+ const int index = d->contentModel->indexOf(item, nullptr);
+ if (index == -1)
+ return;
+
+ d->removeItem(index, item);
+ item->deleteLater();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod MenuItem QtQuick.Controls::Menu::takeItem(int index)
+
+ Removes and returns the item at \a index.
\note The ownership of the item is transferred to the caller.
*/
-void QQuickMenu::removeItem(int index)
+QQuickItem *QQuickMenu::takeItem(int index)
{
Q_D(QQuickMenu);
const int count = d->contentModel->count();
if (index < 0 || index >= count)
- return;
+ return nullptr;
QQuickItem *item = itemAt(index);
if (item)
d->removeItem(index, item);
+ return item;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod Menu QtQuick.Controls::Menu::menuAt(int index)
+
+ Returns the sub-menu at \a index, or \c null if the index is not valid or
+ there is no sub-menu at the specified index.
+*/
+QQuickMenu *QQuickMenu::menuAt(int index) const
+{
+ Q_D(const QQuickMenu);
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
+ if (!item)
+ return nullptr;
+
+ return item->subMenu();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::addMenu(Menu menu)
+
+ Adds \a menu as a sub-menu to the end of this menu.
+*/
+void QQuickMenu::addMenu(QQuickMenu *menu)
+{
+ Q_D(QQuickMenu);
+ insertMenu(d->contentModel->count(), menu);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::insertMenu(int index, Menu menu)
+
+ Inserts \a menu as a sub-menu at \a index. The index is within all items in the menu.
+*/
+void QQuickMenu::insertMenu(int index, QQuickMenu *menu)
+{
+ Q_D(QQuickMenu);
+ if (!menu)
+ return;
+
+ insertItem(index, d->createItem(menu));
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::removeMenu(Menu menu)
+
+ Removes and destroys the specified \a menu.
+*/
+void QQuickMenu::removeMenu(QQuickMenu *menu)
+{
+ Q_D(QQuickMenu);
+ if (!menu)
+ return;
+
+ const int count = d->contentModel->count();
+ for (int i = 0; i < count; ++i) {
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
+ if (!item || item->subMenu() != menu)
+ continue;
+
+ removeItem(item);
+ break;
+ }
+
+ menu->deleteLater();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod Menu QtQuick.Controls::Menu::takeMenu(int index)
+
+ Removes and returns the menu at \a index. The index is within all items in the menu.
+
+ \note The ownership of the menu is transferred to the caller.
+*/
+QQuickMenu *QQuickMenu::takeMenu(int index)
+{
+ Q_D(QQuickMenu);
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
+ if (!item)
+ return nullptr;
+
+ QQuickMenu *subMenu = item->subMenu();
+ if (!subMenu)
+ return nullptr;
+
+ d->removeItem(index, item);
+ item->deleteLater();
+ return subMenu;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod Action QtQuick.Controls::Menu::actionAt(int index)
+
+ Returns the action at \a index, or \c null if the index is not valid or
+ there is no action at the specified index.
+*/
+QQuickAction *QQuickMenu::actionAt(int index) const
+{
+ Q_D(const QQuickMenu);
+ QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
+ if (!item)
+ return nullptr;
+
+ return item->action();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::addAction(Action action)
+
+ Adds \a action to the end of this menu.
+*/
+void QQuickMenu::addAction(QQuickAction *action)
+{
+ Q_D(QQuickMenu);
+ insertAction(d->contentModel->count(), action);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::insertAction(int index, Action action)
+
+ Inserts \a action at \a index. The index is within all items in the menu.
+*/
+void QQuickMenu::insertAction(int index, QQuickAction *action)
+{
+ Q_D(QQuickMenu);
+ if (!action)
+ return;
+
+ insertItem(index, d->createItem(action));
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::removeAction(Action action)
+
+ Removes and destroys the specified \a action.
+*/
+void QQuickMenu::removeAction(QQuickAction *action)
+{
+ Q_D(QQuickMenu);
+ if (!action)
+ return;
+
+ const int count = d->contentModel->count();
+ for (int i = 0; i < count; ++i) {
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
+ if (!item || item->action() != action)
+ continue;
+
+ removeItem(item);
+ break;
+ }
+
+ action->deleteLater();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod Action QtQuick.Controls::Menu::takeAction(int index)
+
+ Removes and returns the action at \a index. The index is within all items in the menu.
+
+ \note The ownership of the action is transferred to the caller.
+*/
+QQuickAction *QQuickMenu::takeAction(int index)
+{
+ Q_D(QQuickMenu);
+ QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
+ if (!item)
+ return nullptr;
+
+ QQuickAction *action = item->action();
+ if (!action)
+ return nullptr;
+
+ d->removeItem(index, item);
+ item->deleteLater();
+ return action;
}
/*!
@@ -448,8 +1013,7 @@ QVariant QQuickMenu::contentModel() const
*/
QQmlListProperty<QObject> QQuickMenu::contentData()
{
- Q_D(QQuickMenu);
- return QQmlListProperty<QObject>(this, d,
+ return QQmlListProperty<QObject>(this, nullptr,
QQuickMenuPrivate::contentData_append,
QQuickMenuPrivate::contentData_count,
QQuickMenuPrivate::contentData_at,
@@ -477,7 +1041,300 @@ void QQuickMenu::setTitle(QString &title)
if (title == d->title)
return;
d->title = title;
- emit titleChanged();
+ emit titleChanged(title);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Menu::cascade
+
+ This property holds whether the menu cascades its sub-menus.
+
+ The default value is platform-specific. Menus are cascading by default on
+ desktop platforms that have a mouse cursor available. Non-cascading menus
+ are shown one menu at a time, and centered over the parent menu.
+
+ \note Changing the value of the property has no effect while the menu is open.
+
+ \sa overlap
+*/
+bool QQuickMenu::cascade() const
+{
+ Q_D(const QQuickMenu);
+ return d->cascade;
+}
+
+void QQuickMenu::setCascade(bool cascade)
+{
+ Q_D(QQuickMenu);
+ if (d->cascade == cascade)
+ return;
+ d->cascade = cascade;
+ if (d->parentMenu)
+ d->resolveParentItem();
+ emit cascadeChanged(cascade);
+}
+
+void QQuickMenu::resetCascade()
+{
+ Q_D(QQuickMenu);
+ if (d->parentMenu)
+ setCascade(d->parentMenu->cascade());
+ else
+ setCascade(shouldCascade());
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty real QtQuick.Controls::Menu::overlap
+
+ This property holds the amount of pixels by which the menu horizontally overlaps its parent menu.
+
+ The property only has effect when the menu is used as a cascading sub-menu.
+
+ The default value is style-specific.
+
+ \note Changing the value of the property has no effect while the menu is open.
+
+ \sa cascade
+*/
+qreal QQuickMenu::overlap() const
+{
+ Q_D(const QQuickMenu);
+ return d->overlap;
+}
+
+void QQuickMenu::setOverlap(qreal overlap)
+{
+ Q_D(QQuickMenu);
+ if (d->overlap == overlap)
+ return;
+ d->overlap = overlap;
+ emit overlapChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Component QtQuick.Controls::Menu::delegate
+
+ This property holds the component that is used to create items
+ to present actions.
+
+ \code
+ Menu {
+ Action { text: "Cut" }
+ Action { text: "Copy" }
+ Action { text: "Paste" }
+ }
+ \endcode
+
+ \sa Action
+*/
+QQmlComponent *QQuickMenu::delegate() const
+{
+ Q_D(const QQuickMenu);
+ return d->delegate;
+}
+
+void QQuickMenu::setDelegate(QQmlComponent *delegate)
+{
+ Q_D(QQuickMenu);
+ if (d->delegate == delegate)
+ return;
+
+ d->delegate = delegate;
+ emit delegateChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty int QtQuick.Controls::Menu::currentIndex
+
+ This property holds the index of the currently highlighted item.
+
+ Menu items can be highlighted by mouse hover or keyboard navigation.
+
+ \sa MenuItem::highlighted
+*/
+int QQuickMenu::currentIndex() const
+{
+ Q_D(const QQuickMenu);
+ return d->currentIndex;
+}
+
+void QQuickMenu::setCurrentIndex(int index)
+{
+ Q_D(QQuickMenu);
+ d->setCurrentIndex(index, Qt::OtherFocusReason);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty int QtQuick.Controls::Menu::count
+ \readonly
+
+ This property holds the number of items.
+*/
+int QQuickMenu::count() const
+{
+ Q_D(const QQuickMenu);
+ return d->contentModel->count();
+}
+
+void QQuickMenu::popup(QQuickItem *menuItem)
+{
+ Q_D(QQuickMenu);
+ // No position has been explicitly specified, so position the menu at the mouse cursor
+ // on desktop platforms that have a mouse cursor available and support multiple windows.
+ QQmlNullableValue<QPointF> pos;
+#if QT_CONFIG(cursor)
+ if (d->parentItem && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows))
+ pos = d->parentItem->mapFromGlobal(QCursor::pos());
+#endif
+
+ // As a fallback, center the menu over its parent item.
+ if (pos.isNull && d->parentItem)
+ pos = QPointF((d->parentItem->width() - width()) / 2, (d->parentItem->height() - height()) / 2);
+
+ popup(pos.isNull ? QPointF() : pos.value, menuItem);
+}
+
+void QQuickMenu::popup(const QPointF &pos, QQuickItem *menuItem)
+{
+ Q_D(QQuickMenu);
+ qreal offset = 0;
+#if QT_CONFIG(cursor)
+ if (menuItem)
+ offset = d->popupItem->mapFromItem(menuItem, QPointF(0, 0)).y();
+#endif
+ setPosition(pos - QPointF(0, offset));
+
+ if (menuItem)
+ d->setCurrentIndex(d->contentModel->indexOf(menuItem, nullptr), Qt::PopupFocusReason);
+ open();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::popup(MenuItem item = null)
+ \qmlmethod void QtQuick.Controls::Menu::popup(Item parent, MenuItem item = null)
+
+ Opens the menu at the mouse cursor on desktop platforms that have a mouse cursor
+ available, and otherwise centers the menu over its \a parent item.
+
+ The menu can be optionally aligned to a specific menu \a item.
+
+ \sa Popup::open()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::popup(point pos, MenuItem item = null)
+ \qmlmethod void QtQuick.Controls::Menu::popup(Item parent, point pos, MenuItem item = null)
+
+ Opens the menu at the specified position \a pos in the popups coordinate system,
+ that is, a coordinate relative to its \a parent item.
+
+ The menu can be optionally aligned to a specific menu \a item.
+
+ \sa Popup::open()
+*/
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::popup(real x, real y, MenuItem item = null)
+ \qmlmethod void QtQuick.Controls::Menu::popup(Item parent, real x, real y, MenuItem item = null)
+
+ Opens the menu at the specified position \a x, \a y in the popups coordinate system,
+ that is, a coordinate relative to its \a parent item.
+
+ The menu can be optionally aligned to a specific menu \a item.
+
+ \sa dismiss(), Popup::open()
+*/
+void QQuickMenu::popup(QQmlV4Function *args)
+{
+ Q_D(QQuickMenu);
+ const int len = args->length();
+ if (len > 4) {
+ args->v4engine()->throwTypeError();
+ return;
+ }
+
+ QV4::ExecutionEngine *v4 = args->v4engine();
+ QV4::Scope scope(v4);
+
+ QQmlNullableValue<QPointF> pos;
+ QQuickItem *menuItem = nullptr;
+ QQuickItem *parentItem = nullptr;
+
+ if (len > 0) {
+ // Item parent
+ QV4::ScopedValue firstArg(scope, (*args)[0]);
+ if (const QV4::QObjectWrapper *obj = firstArg->as<QV4::QObjectWrapper>()) {
+ QQuickItem *item = qobject_cast<QQuickItem *>(obj->object());
+ if (item && !d->popupItem->isAncestorOf(item))
+ parentItem = item;
+ } else if (firstArg->isUndefined()) {
+ resetParentItem();
+ parentItem = d->parentItem;
+ }
+
+ // MenuItem item
+ QV4::ScopedValue lastArg(scope, (*args)[len - 1]);
+ if (const QV4::QObjectWrapper *obj = lastArg->as<QV4::QObjectWrapper>()) {
+ QQuickItem *item = qobject_cast<QQuickItem *>(obj->object());
+ if (item && d->popupItem->isAncestorOf(item))
+ menuItem = item;
+ }
+ }
+
+ if (len >= 3 || (!parentItem && len >= 2)) {
+ // real x, real y
+ QV4::ScopedValue xArg(scope, (*args)[parentItem ? 1 : 0]);
+ QV4::ScopedValue yArg(scope, (*args)[parentItem ? 2 : 1]);
+ if (xArg->isNumber() && yArg->isNumber())
+ pos = QPointF(xArg->asDouble(), yArg->asDouble());
+ }
+
+ if (pos.isNull && (len >= 2 || (!parentItem && len >= 1))) {
+ // point pos
+ QV4::ScopedValue posArg(scope, (*args)[parentItem ? 1 : 0]);
+ const QVariant var = v4->toVariant(posArg, -1);
+ if (var.userType() == QMetaType::QPointF)
+ pos = var.toPointF();
+ }
+
+ if (parentItem)
+ setParentItem(parentItem);
+
+ if (pos.isNull)
+ popup(menuItem);
+ else
+ popup(pos, menuItem);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlmethod void QtQuick.Controls::Menu::dismiss()
+
+ Closes all menus in the hierarchy that this menu belongs to.
+
+ \note Unlike \l {Popup::}{close()} that only closes a menu and its sub-menus,
+ \c dismiss() closes the whole hierarchy of menus, including the parent menus.
+ In practice, \c close() is suitable e.g. for implementing navigation in a
+ hierarchy of menus, and \c dismiss() is the appropriate method for closing
+ the whole hierarchy of menus.
+
+ \sa popup(), Popup::close()
+*/
+void QQuickMenu::dismiss()
+{
+ QQuickMenu *menu = this;
+ while (menu) {
+ menu->close();
+ menu = QQuickMenuPrivate::get(menu)->parentMenu;
+ }
}
void QQuickMenu::componentComplete()
@@ -506,26 +1363,18 @@ void QQuickMenu::itemChange(QQuickItem::ItemChange change, const QQuickItem::Ite
QQuickPopup::itemChange(change, data);
if (change == QQuickItem::ItemVisibleHasChanged) {
- if (!data.boolValue) {
+ if (!data.boolValue && d->cascade) {
// Ensure that when the menu isn't visible, there's no current item
// the next time it's opened.
- QQuickItem *focusItem = QQuickItemPrivate::get(d->contentItem)->subFocusItem;
- if (focusItem) {
- QQuickWindow *window = QQuickPopup::window();
- if (window)
- QQuickWindowPrivate::get(window)->clearFocusInScope(d->contentItem, focusItem, Qt::OtherFocusReason);
- }
- d->setCurrentIndex(-1);
+ d->setCurrentIndex(-1, Qt::OtherFocusReason);
}
}
}
-void QQuickMenu::keyReleaseEvent(QKeyEvent *event)
+void QQuickMenu::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickMenu);
- QQuickPopup::keyReleaseEvent(event);
- if (d->contentModel->count() == 0)
- return;
+ QQuickPopup::keyPressEvent(event);
// QTBUG-17051
// Work around the fact that ListView has no way of distinguishing between
@@ -535,23 +1384,59 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event)
// shown at once.
switch (event->key()) {
case Qt::Key_Up:
- d->activatePreviousItem();
+ if (!d->activatePreviousItem())
+ d->propagateKeyEvent(event);
break;
case Qt::Key_Down:
d->activateNextItem();
break;
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ event->ignore();
+ if (d->popupItem->isMirrored() == (event->key() == Qt::Key_Right)) {
+ if (d->parentMenu && d->currentItem) {
+ if (!d->cascade)
+ d->parentMenu->open();
+ close();
+ event->accept();
+ }
+ } else {
+ if (QQuickMenu *subMenu = d->currentSubMenu()) {
+ subMenu->popup(subMenu->itemAt(0));
+ event->accept();
+ }
+ }
+ if (!event->isAccepted())
+ d->propagateKeyEvent(event);
+ break;
+
default:
break;
}
}
+void QQuickMenu::timerEvent(QTimerEvent *event)
+{
+ Q_D(QQuickMenu);
+ if (event->timerId() == d->hoverTimer) {
+ if (QQuickMenu *subMenu = d->currentSubMenu())
+ subMenu->open();
+ d->stopHoverTimer();
+ }
+}
+
QFont QQuickMenu::defaultFont() const
{
return QQuickControlPrivate::themeFont(QPlatformTheme::MenuFont);
}
+QPalette QQuickMenu::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenu::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickmenu_p.h b/src/quicktemplates2/qquickmenu_p.h
index 6d1a4985..01b970f8 100644
--- a/src/quicktemplates2/qquickmenu_p.h
+++ b/src/quicktemplates2/qquickmenu_p.h
@@ -55,6 +55,8 @@
QT_BEGIN_NAMESPACE
+class QQuickAction;
+class QQmlComponent;
class QQuickMenuItem;
class QQuickMenuPrivate;
@@ -63,7 +65,13 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenu : public QQuickPopup
Q_OBJECT
Q_PROPERTY(QVariant contentModel READ contentModel CONSTANT FINAL)
Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
- Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
+ Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(int count READ count NOTIFY countChanged FINAL REVISION 3)
+ Q_PROPERTY(bool cascade READ cascade WRITE setCascade RESET resetCascade NOTIFY cascadeChanged FINAL REVISION 3)
+ Q_PROPERTY(qreal overlap READ overlap WRITE setOverlap NOTIFY overlapChanged FINAL REVISION 3)
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL REVISION 3)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL REVISION 3)
Q_CLASSINFO("DefaultProperty", "contentData")
public:
@@ -73,7 +81,8 @@ public:
Q_INVOKABLE void addItem(QQuickItem *item);
Q_INVOKABLE void insertItem(int index, QQuickItem *item);
Q_INVOKABLE void moveItem(int from, int to);
- Q_INVOKABLE void removeItem(int index);
+ Q_INVOKABLE void removeItem(const QVariant &item); // ### Qt 6: remove
+ void removeItem(QQuickItem *item); // ### Qt 6: Q_INVOKABLE
QVariant contentModel() const;
QQmlListProperty<QObject> contentData();
@@ -81,17 +90,61 @@ public:
QString title() const;
void setTitle(QString &title);
+ bool cascade() const;
+ void setCascade(bool cascade);
+ void resetCascade();
+
+ qreal overlap() const;
+ void setOverlap(qreal overlap);
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *delegate);
+
+ int currentIndex() const;
+ void setCurrentIndex(int index);
+
+ // 2.3 (Qt 5.10)
+ int count() const;
+ Q_REVISION(3) Q_INVOKABLE QQuickItem *takeItem(int index);
+
+ Q_REVISION(3) Q_INVOKABLE QQuickMenu *menuAt(int index) const;
+ Q_REVISION(3) Q_INVOKABLE void addMenu(QQuickMenu *menu);
+ Q_REVISION(3) Q_INVOKABLE void insertMenu(int index, QQuickMenu *menu);
+ Q_REVISION(3) Q_INVOKABLE void removeMenu(QQuickMenu *menu);
+ Q_REVISION(3) Q_INVOKABLE QQuickMenu *takeMenu(int index);
+
+ Q_REVISION(3) Q_INVOKABLE QQuickAction *actionAt(int index) const;
+ Q_REVISION(3) Q_INVOKABLE void addAction(QQuickAction *action);
+ Q_REVISION(3) Q_INVOKABLE void insertAction(int index, QQuickAction *action);
+ Q_REVISION(3) Q_INVOKABLE void removeAction(QQuickAction *action);
+ Q_REVISION(3) Q_INVOKABLE QQuickAction *takeAction(int index);
+
+ void popup(QQuickItem *menuItem = nullptr);
+ void popup(const QPointF &pos, QQuickItem *menuItem = nullptr);
+
+ Q_REVISION(3) Q_INVOKABLE void popup(QQmlV4Function *args);
+ Q_REVISION(3) Q_INVOKABLE void dismiss();
+
protected:
void componentComplete() override;
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override;
- void keyReleaseEvent(QKeyEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
Q_SIGNALS:
- void titleChanged();
+ void titleChanged(const QString &title);
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void countChanged();
+ Q_REVISION(3) void cascadeChanged(bool cascade);
+ Q_REVISION(3) void overlapChanged();
+ Q_REVISION(3) void delegateChanged();
+ Q_REVISION(3) void currentIndexChanged();
protected:
+ void timerEvent(QTimerEvent *event) override;
+
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h
index 583bb41d..0c8ffb4d 100644
--- a/src/quicktemplates2/qquickmenu_p_p.h
+++ b/src/quicktemplates2/qquickmenu_p_p.h
@@ -51,11 +51,15 @@
#include <QtCore/qvector.h>
#include <QtCore/qpointer.h>
+#include <QtQuickTemplates2/private/qquickmenu_p.h>
#include <QtQuickTemplates2/private/qquickpopup_p_p.h>
QT_BEGIN_NAMESPACE
+class QQuickAction;
+class QQmlComponent;
class QQmlObjectModel;
+class QQuickMenuItem;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuPrivate : public QQuickPopupPrivate
{
@@ -64,11 +68,22 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuPrivate : public QQuickPopupPri
public:
QQuickMenuPrivate();
+ static QQuickMenuPrivate *get(QQuickMenu *menu)
+ {
+ return menu->d_func();
+ }
+
QQuickItem *itemAt(int index) const;
void insertItem(int index, QQuickItem *item);
void moveItem(int from, int to);
void removeItem(int index, QQuickItem *item);
+ QQuickItem *beginCreateItem();
+ void completeCreateItem();
+
+ QQuickItem *createItem(QQuickMenu *menu);
+ QQuickItem *createItem(QQuickAction *action);
+
void resizeItem(QQuickItem *item);
void resizeItems();
@@ -78,23 +93,43 @@ public:
void itemDestroyed(QQuickItem *item) override;
void itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &diff) override;
- void onItemPressed();
+ void reposition() override;
+ bool prepareEnterTransition() override;
+ bool prepareExitTransition() override;
+ bool blockInput(QQuickItem *item, const QPointF &point) const override;
+
+ void onItemHovered();
+ void onItemTriggered();
void onItemActiveFocusChanged();
- int currentIndex() const;
- void setCurrentIndex(int index);
+ QQuickMenu *currentSubMenu() const;
+ void setParentMenu(QQuickMenu *parent);
+ void resolveParentItem();
+
+ void propagateKeyEvent(QKeyEvent *event);
+
+ void startHoverTimer();
+ void stopHoverTimer();
- void activateNextItem();
- void activatePreviousItem();
+ void setCurrentIndex(int index, Qt::FocusReason reason);
+ bool activateNextItem();
+ bool activatePreviousItem();
static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
static int contentData_count(QQmlListProperty<QObject> *prop);
static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index);
static void contentData_clear(QQmlListProperty<QObject> *prop);
+ bool cascade;
+ int hoverTimer;
+ int currentIndex;
+ qreal overlap;
+ QPointer<QQuickMenu> parentMenu;
+ QPointer<QQuickMenuItem> currentItem;
QQuickItem *contentItem; // TODO: cleanup
QVector<QObject *> contentData;
QQmlObjectModel *contentModel;
+ QQmlComponent *delegate;
QString title;
};
diff --git a/src/quicktemplates2/qquickmenubar.cpp b/src/quicktemplates2/qquickmenubar.cpp
new file mode 100644
index 00000000..de3cc9a7
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubar.cpp
@@ -0,0 +1,659 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmenubar_p.h"
+#include "qquickmenubar_p_p.h"
+#include "qquickmenubaritem_p_p.h"
+#include "qquickmenu_p.h"
+#include "qquickmenu_p_p.h"
+
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype MenuBar
+ \inherits Container
+ \instantiates QQuickMenuBar
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \ingroup qtquickcontrols2-menus
+ \brief Provides a window menu bar.
+
+ \image qtquickcontrols2-menubar.png
+
+ MenuBar consists of drop-down menus, and is normally located at the top
+ edge of the window.
+
+ \quotefromfile qtquickcontrols2-menubar.qml
+ \skipuntil begin
+ \printto skipfrom
+ \skipuntil skipto
+ \printto end
+
+ Typically, menus are statically declared as children of the menu bar, but
+ MenuBar also provides API to \l {addMenu}{add}, \l {insertMenu}{insert},
+ \l {removeMenu}{remove}, and \l {takeMenu}{take} menus dynamically. The
+ menus in a menu bar can be accessed using \l menuAt().
+
+ \sa {Customizing MenuBar}, Menu, MenuBarItem, {Menu Controls}
+*/
+
+QQuickMenuBarPrivate::QQuickMenuBarPrivate()
+ : popupMode(false),
+ triggering(false),
+ hasContentWidth(false),
+ hasContentHeight(false),
+ contentWidth(0),
+ contentHeight(0),
+ delegate(nullptr)
+{
+ changeTypes |= Geometry;
+}
+
+QQuickItem *QQuickMenuBarPrivate::beginCreateItem()
+{
+ Q_Q(QQuickMenuBar);
+ if (!delegate)
+ return nullptr;
+
+ QQmlContext *creationContext = delegate->creationContext();
+ if (!creationContext)
+ creationContext = qmlContext(q);
+ QQmlContext *context = new QQmlContext(creationContext, q);
+ context->setContextObject(q);
+
+ QObject *object = delegate->beginCreate(context);
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (!item) {
+ delete object;
+ delete context;
+ return nullptr;
+ }
+
+ item->setParentItem(q);
+ QQml_setParent_noEvent(item, q);
+
+ return item;
+}
+
+void QQuickMenuBarPrivate::completeCreateItem()
+{
+ if (!delegate)
+ return;
+
+ delegate->completeCreate();
+}
+
+QQuickItem *QQuickMenuBarPrivate::createItem(QQuickMenu *menu)
+{
+ QQuickItem *item = beginCreateItem();
+ if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(item))
+ menuBarItem->setMenu(menu);
+ completeCreateItem();
+ return item;
+}
+
+void QQuickMenuBarPrivate::toggleCurrentMenu(bool visible, bool activate)
+{
+ if (!currentItem || visible == popupMode)
+ return;
+
+ QQuickMenu *menu = currentItem->menu();
+
+ triggering = true;
+ popupMode = visible;
+ if (menu)
+ menu->setVisible(visible);
+ if (!visible)
+ currentItem->forceActiveFocus();
+ else if (menu && activate)
+ menu->setCurrentIndex(0);
+ triggering = false;
+}
+
+void QQuickMenuBarPrivate::activateItem(QQuickMenuBarItem *item)
+{
+ if (currentItem == item)
+ return;
+
+ if (currentItem) {
+ currentItem->setHighlighted(false);
+ if (popupMode) {
+ if (QQuickMenu *menu = currentItem->menu())
+ menu->dismiss();
+ }
+ }
+
+ if (item) {
+ item->setHighlighted(true);
+ if (popupMode) {
+ if (QQuickMenu *menu = item->menu())
+ menu->open();
+ }
+ }
+
+ currentItem = item;
+}
+
+void QQuickMenuBarPrivate::activateNextItem()
+{
+ int index = currentItem ? contentModel->indexOf(currentItem, nullptr) : -1;
+ if (index >= contentModel->count() - 1)
+ index = -1;
+ activateItem(qobject_cast<QQuickMenuBarItem *>(itemAt(++index)));
+}
+
+void QQuickMenuBarPrivate::activatePreviousItem()
+{
+ int index = currentItem ? contentModel->indexOf(currentItem, nullptr) : contentModel->count();
+ if (index <= 0)
+ index = contentModel->count();
+ activateItem(qobject_cast<QQuickMenuBarItem *>(itemAt(--index)));
+}
+
+void QQuickMenuBarPrivate::onItemHovered()
+{
+ Q_Q(QQuickMenuBar);
+ QQuickMenuBarItem *item = qobject_cast<QQuickMenuBarItem *>(q->sender());
+ if (!item || item == currentItem || !item->isHovered() || QQuickMenuBarItemPrivate::get(item)->touchId != -1)
+ return;
+
+ activateItem(item);
+}
+
+void QQuickMenuBarPrivate::onItemTriggered()
+{
+ Q_Q(QQuickMenuBar);
+ QQuickMenuBarItem *item = qobject_cast<QQuickMenuBarItem *>(q->sender());
+ if (!item)
+ return;
+
+ if (item == currentItem) {
+ toggleCurrentMenu(!popupMode, false);
+ } else {
+ popupMode = true;
+ activateItem(item);
+ }
+}
+
+void QQuickMenuBarPrivate::onMenuAboutToHide()
+{
+ if (triggering || !currentItem || currentItem->isHovered() || !currentItem->isHighlighted())
+ return;
+
+ popupMode = false;
+ activateItem(nullptr);
+}
+
+void QQuickMenuBarPrivate::updateContentSize()
+{
+ Q_Q(QQuickMenuBar);
+ if (hasContentWidth && hasContentHeight)
+ return;
+
+ const int count = contentModel->count();
+ if (count <= 0 || !contentItem)
+ return;
+
+ qreal maxHeight = 0;
+ qreal totalWidth = qMax(0, count - 1) * spacing;
+
+ for (int i = 0; i < count; ++i) {
+ QQuickItem *item = q->itemAt(i);
+ if (item) {
+ totalWidth += item->width();
+ maxHeight = qMax(maxHeight, item->implicitHeight());
+ }
+ }
+
+ bool contentWidthChange = false;
+ if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) {
+ contentWidth = totalWidth;
+ contentWidthChange = true;
+ }
+
+ bool contentHeightChange = false;
+ if (!hasContentHeight && !qFuzzyCompare(contentHeight, maxHeight)) {
+ contentHeight = maxHeight;
+ contentHeightChange = true;
+ }
+
+ if (contentWidthChange)
+ emit q->contentWidthChanged();
+ if (contentHeightChange)
+ emit q->contentHeightChanged();
+}
+
+void QQuickMenuBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &)
+{
+ if ((change.widthChange() && !hasContentWidth) || (change.heightChange() && !hasContentHeight))
+ updateContentSize();
+}
+
+void QQuickMenuBarPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
+{
+ QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object);
+ if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj))
+ obj = QQuickMenuBarPrivate::get(menuBar)->createItem(menu);
+ QQuickContainerPrivate::contentData_append(prop, obj);
+}
+
+void QQuickMenuBarPrivate::menus_append(QQmlListProperty<QQuickMenu> *prop, QQuickMenu *obj)
+{
+ QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object);
+ menuBar->addMenu(obj);
+}
+
+int QQuickMenuBarPrivate::menus_count(QQmlListProperty<QQuickMenu> *prop)
+{
+ QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object);
+ return menuBar->count();
+}
+
+QQuickMenu *QQuickMenuBarPrivate::menus_at(QQmlListProperty<QQuickMenu> *prop, int index)
+{
+ QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object);
+ return menuBar->menuAt(index);
+}
+
+void QQuickMenuBarPrivate::menus_clear(QQmlListProperty<QQuickMenu> *prop)
+{
+ QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object);
+ QQuickMenuBarPrivate::get(menuBar)->contentModel->clear();
+}
+
+QQuickMenuBar::QQuickMenuBar(QQuickItem *parent)
+ : QQuickContainer(*(new QQuickMenuBarPrivate), parent)
+{
+ setFlag(ItemIsFocusScope);
+ setFocusPolicy(Qt::ClickFocus);
+}
+
+/*!
+ \qmlproperty Component QtQuick.Controls::MenuBar::delegate
+
+ This property holds the component that is used to create menu bar
+ items to present menus in the menu bar.
+
+ \sa MenuBarItem
+*/
+QQmlComponent *QQuickMenuBar::delegate() const
+{
+ Q_D(const QQuickMenuBar);
+ return d->delegate;
+}
+
+void QQuickMenuBar::setDelegate(QQmlComponent *delegate)
+{
+ Q_D(QQuickMenuBar);
+ if (d->delegate == delegate)
+ return;
+
+ d->delegate = delegate;
+ emit delegateChanged();
+}
+
+/*!
+ \qmlmethod Menu QtQuick.Controls::MenuBar::menuAt(int index)
+
+ Returns the menu at \a index, or \c null if it does not exist.
+*/
+QQuickMenu *QQuickMenuBar::menuAt(int index) const
+{
+ Q_D(const QQuickMenuBar);
+ QQuickMenuBarItem *item = qobject_cast<QQuickMenuBarItem *>(d->itemAt(index));
+ if (!item)
+ return nullptr;
+ return item->menu();
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::MenuBar::addMenu(Menu menu)
+
+ Adds \a menu to the end of the list of menus.
+*/
+void QQuickMenuBar::addMenu(QQuickMenu *menu)
+{
+ Q_D(QQuickMenuBar);
+ addItem(d->createItem(menu));
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::MenuBar::insertMenu(int index, Menu menu)
+
+ Inserts \a menu at \a index.
+*/
+void QQuickMenuBar::insertMenu(int index, QQuickMenu *menu)
+{
+ Q_D(QQuickMenuBar);
+ insertItem(index, d->createItem(menu));
+}
+
+/*!
+ \qmlmethod void QtQuick.Controls::MenuBar::removeMenu(Menu menu)
+
+ Removes and destroys the specified \a menu.
+*/
+void QQuickMenuBar::removeMenu(QQuickMenu *menu)
+{
+ Q_D(QQuickMenuBar);
+ if (!menu)
+ return;
+
+ const int count = d->contentModel->count();
+ for (int i = 0; i < count; ++i) {
+ QQuickMenuBarItem *item = qobject_cast<QQuickMenuBarItem *>(itemAt(i));
+ if (!item || item->menu() != menu)
+ continue;
+
+ removeItem(item);
+ break;
+ }
+
+ menu->deleteLater();
+}
+
+/*!
+ \qmlmethod Menu QtQuick.Controls::MenuBar::takeMenu(int index)
+
+ Removes and returns the menu at \a index.
+
+ \note The ownership of the item is transferred to the caller.
+*/
+QQuickMenu *QQuickMenuBar::takeMenu(int index)
+{
+ Q_D(QQuickMenuBar);
+ QQuickMenuBarItem *item = qobject_cast<QQuickMenuBarItem *>(itemAt(index));
+ if (!item)
+ return nullptr;
+
+ QQuickMenu *menu = item->menu();
+ if (!menu)
+ return nullptr;
+
+ d->removeItem(index, item);
+ item->deleteLater();
+ return menu;
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::MenuBar::contentWidth
+
+ This property holds the content width. It is used for calculating the total
+ implicit width of the menu bar.
+
+ Unless explicitly overridden, the content width is automatically calculated
+ based on the total implicit width of the items and the \l {Control::}{spacing}
+ of the menu bar.
+
+ \sa contentHeight
+*/
+qreal QQuickMenuBar::contentWidth() const
+{
+ Q_D(const QQuickMenuBar);
+ return d->contentWidth;
+}
+
+void QQuickMenuBar::setContentWidth(qreal width)
+{
+ Q_D(QQuickMenuBar);
+ d->hasContentWidth = true;
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ d->contentWidth = width;
+ emit contentWidthChanged();
+}
+
+void QQuickMenuBar::resetContentWidth()
+{
+ Q_D(QQuickMenuBar);
+ if (!d->hasContentWidth)
+ return;
+
+ d->hasContentWidth = false;
+ if (isComponentComplete())
+ d->updateContentSize();
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::MenuBar::contentHeight
+
+ This property holds the content height. It is used for calculating the total
+ implicit height of the menu bar.
+
+ Unless explicitly overridden, the content height is automatically calculated
+ based on the maximum implicit height of the items.
+
+ \sa contentWidth
+*/
+qreal QQuickMenuBar::contentHeight() const
+{
+ Q_D(const QQuickMenuBar);
+ return d->contentHeight;
+}
+
+void QQuickMenuBar::setContentHeight(qreal height)
+{
+ Q_D(QQuickMenuBar);
+ d->hasContentHeight = true;
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ d->contentHeight = height;
+ emit contentHeightChanged();
+}
+
+void QQuickMenuBar::resetContentHeight()
+{
+ Q_D(QQuickMenuBar);
+ if (!d->hasContentHeight)
+ return;
+
+ d->hasContentHeight = false;
+ if (isComponentComplete())
+ d->updateContentSize();
+}
+
+/*!
+ \qmlproperty list<Menu> QtQuick.Controls::MenuBar::menus
+
+ This property holds the list of menus.
+
+ The list contains all menus that have been declared in QML as children
+ of the menu bar, and also menus that have been dynamically added or
+ inserted using the \l addMenu() and \l insertMenu() methods, respectively.
+*/
+QQmlListProperty<QQuickMenu> QQuickMenuBar::menus()
+{
+ return QQmlListProperty<QQuickMenu>(this, nullptr,
+ QQuickMenuBarPrivate::menus_append,
+ QQuickMenuBarPrivate::menus_count,
+ QQuickMenuBarPrivate::menus_at,
+ QQuickMenuBarPrivate::menus_clear);
+}
+
+QQmlListProperty<QObject> QQuickMenuBar::contentData()
+{
+ return QQmlListProperty<QObject>(this, nullptr,
+ QQuickMenuBarPrivate::contentData_append,
+ QQuickContainerPrivate::contentData_count,
+ QQuickContainerPrivate::contentData_at,
+ QQuickContainerPrivate::contentData_clear);
+}
+
+void QQuickMenuBar::updatePolish()
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::updatePolish();
+ d->updateContentSize();
+}
+
+void QQuickMenuBar::componentComplete()
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::componentComplete();
+ d->updateContentSize();
+}
+
+bool QQuickMenuBar::eventFilter(QObject *object, QEvent *event)
+{
+ return QObject::eventFilter(object, event);
+}
+
+void QQuickMenuBar::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::keyReleaseEvent(event);
+
+ switch (event->key()) {
+ case Qt::Key_Up:
+ d->toggleCurrentMenu(false, false);
+ break;
+
+ case Qt::Key_Down:
+ d->toggleCurrentMenu(true, true);
+ break;
+
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ if (isMirrored() == (event->key() == Qt::Key_Left))
+ d->activateNextItem();
+ else
+ d->activatePreviousItem();
+ break;
+ case Qt::Key_Escape:
+ if (d->currentItem) {
+ d->activateItem(nullptr);
+ setFocus(false);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void QQuickMenuBar::keyReleaseEvent(QKeyEvent *event)
+{
+ QQuickContainer::keyReleaseEvent(event);
+
+ switch (event->key()) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Escape:
+ event->accept();
+ break;
+
+ default:
+ event->ignore();
+ break;
+ }
+}
+
+void QQuickMenuBar::hoverLeaveEvent(QHoverEvent *event)
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::hoverLeaveEvent(event);
+ if (!d->popupMode && d->currentItem)
+ d->activateItem(nullptr);
+}
+
+bool QQuickMenuBar::isContent(QQuickItem *item) const
+{
+ return qobject_cast<QQuickMenuBarItem *>(item);
+}
+
+void QQuickMenuBar::itemAdded(int index, QQuickItem *item)
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::itemAdded(index, item);
+ if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(item)) {
+ QQuickMenuBarItemPrivate::get(menuBarItem)->setMenuBar(this);
+ QObjectPrivate::connect(menuBarItem, &QQuickControl::hoveredChanged, d, &QQuickMenuBarPrivate::onItemHovered);
+ QObjectPrivate::connect(menuBarItem, &QQuickMenuBarItem::triggered, d, &QQuickMenuBarPrivate::onItemTriggered);
+ if (QQuickMenu *menu = menuBarItem->menu())
+ QObjectPrivate::connect(menu, &QQuickPopup::aboutToHide, d, &QQuickMenuBarPrivate::onMenuAboutToHide);
+ }
+ if (isComponentComplete())
+ polish();
+ if (isComponentComplete())
+ polish();
+ emit menusChanged();
+}
+
+void QQuickMenuBar::itemMoved(int index, QQuickItem *item)
+{
+ QQuickContainer::itemMoved(index, item);
+ emit menusChanged();
+}
+
+void QQuickMenuBar::itemRemoved(int index, QQuickItem *item)
+{
+ Q_D(QQuickMenuBar);
+ QQuickContainer::itemRemoved(index, item);
+ if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(item)) {
+ QQuickMenuBarItemPrivate::get(menuBarItem)->setMenuBar(nullptr);
+ QObjectPrivate::disconnect(menuBarItem, &QQuickControl::hoveredChanged, d, &QQuickMenuBarPrivate::onItemHovered);
+ QObjectPrivate::disconnect(menuBarItem, &QQuickMenuBarItem::triggered, d, &QQuickMenuBarPrivate::onItemTriggered);
+ if (QQuickMenu *menu = menuBarItem->menu())
+ QObjectPrivate::disconnect(menu, &QQuickPopup::aboutToHide, d, &QQuickMenuBarPrivate::onMenuAboutToHide);
+ }
+ emit menusChanged();
+}
+
+QFont QQuickMenuBar::defaultFont() const
+{
+ return QQuickControlPrivate::themeFont(QPlatformTheme::MenuBarFont);
+}
+
+QPalette QQuickMenuBar::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::MenuBarPalette);
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickMenuBar::accessibleRole() const
+{
+ return QAccessible::MenuBar;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickmenubar_p.h b/src/quicktemplates2/qquickmenubar_p.h
new file mode 100644
index 00000000..8c703f25
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubar_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMENUBAR_P_H
+#define QQUICKMENUBAR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickcontainer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMenu;
+class QQuickMenuBarPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuBar : public QQuickContainer
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL)
+ Q_PROPERTY(QQmlListProperty<QQuickMenu> menus READ menus NOTIFY menusChanged FINAL)
+ Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
+
+public:
+ explicit QQuickMenuBar(QQuickItem *parent = nullptr);
+
+ QQmlComponent *delegate() const;
+ void setDelegate(QQmlComponent *delegate);
+
+ Q_INVOKABLE QQuickMenu *menuAt(int index) const;
+ Q_INVOKABLE void addMenu(QQuickMenu *menu);
+ Q_INVOKABLE void insertMenu(int index, QQuickMenu *menu);
+ Q_INVOKABLE void removeMenu(QQuickMenu *menu);
+ Q_INVOKABLE QQuickMenu *takeMenu(int index);
+
+ qreal contentWidth() const;
+ void setContentWidth(qreal width);
+ void resetContentWidth();
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal height);
+ void resetContentHeight();
+
+ QQmlListProperty<QQuickMenu> menus();
+ QQmlListProperty<QObject> contentData();
+
+Q_SIGNALS:
+ void delegateChanged();
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void menusChanged();
+
+protected:
+ void updatePolish() override;
+ void componentComplete() override;
+
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+ void hoverLeaveEvent(QHoverEvent *event) override;
+
+ bool isContent(QQuickItem *item) const override;
+ void itemAdded(int index, QQuickItem *item) override;
+ void itemMoved(int index, QQuickItem *item) override;
+ void itemRemoved(int index, QQuickItem *item) override;
+
+ QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
+
+#if QT_CONFIG(accessibility)
+ QAccessible::Role accessibleRole() const override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickMenuBar)
+ Q_DECLARE_PRIVATE(QQuickMenuBar)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickMenuBar)
+
+#endif // QQUICKMENUBAR_P_H
diff --git a/src/quicktemplates2/qquickmenubar_p_p.h b/src/quicktemplates2/qquickmenubar_p_p.h
new file mode 100644
index 00000000..161806fb
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubar_p_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMENUBAR_P_P_H
+#define QQUICKMENUBAR_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickmenubar_p.h>
+#include <QtQuickTemplates2/private/qquickcontainer_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlComponent;
+class QQuickMenuBarItem;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuBarPrivate : public QQuickContainerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickMenuBar)
+
+public:
+ QQuickMenuBarPrivate();
+
+ static QQuickMenuBarPrivate *get(QQuickMenuBar *menuBar)
+ {
+ return menuBar->d_func();
+ }
+
+ QQuickItem *beginCreateItem();
+ void completeCreateItem();
+
+ QQuickItem *createItem(QQuickMenu *menu);
+
+ void toggleCurrentMenu(bool visible, bool activate);
+ void activateItem(QQuickMenuBarItem *item);
+ void activateNextItem();
+ void activatePreviousItem();
+
+ void onItemHovered();
+ void onItemTriggered();
+ void onMenuAboutToHide();
+
+ void updateContentSize();
+ void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
+
+ static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
+
+ static void menus_append(QQmlListProperty<QQuickMenu> *prop, QQuickMenu *obj);
+ static int menus_count(QQmlListProperty<QQuickMenu> *prop);
+ static QQuickMenu *menus_at(QQmlListProperty<QQuickMenu> *prop, int index);
+ static void menus_clear(QQmlListProperty<QQuickMenu> *prop);
+
+ bool popupMode;
+ bool triggering;
+ bool hasContentWidth;
+ bool hasContentHeight;
+ qreal contentWidth;
+ qreal contentHeight;
+ QQmlComponent *delegate;
+ QPointer<QQuickMenuBarItem> currentItem;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKMENUBAR_P_P_H
diff --git a/src/quicktemplates2/qquickmenubaritem.cpp b/src/quicktemplates2/qquickmenubaritem.cpp
new file mode 100644
index 00000000..cbf490b8
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubaritem.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmenubaritem_p.h"
+#include "qquickmenubaritem_p_p.h"
+#include "qquickmenubar_p.h"
+#include "qquickmenu_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype MenuBarItem
+ \inherits AbstractButton
+ \instantiates QQuickMenuBarItem
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \ingroup qtquickcontrols2-menus
+ \brief Presents a drop-down menu within a MenuBar.
+
+ MenuBarItem presents a Menu within a MenuBar. The respective drop-down menu
+ is shown when a MenuBarItem is \l triggered via keyboard, mouse, or touch.
+
+ \image qtquickcontrols2-menubar.png
+
+ MenuBarItem is used as a default \l {MenuBar::}{delegate} type for MenuBar.
+ Notice that it is not necessary to declare MenuBarItem instances by hand when
+ using MenuBar. It is sufficient to declare Menu instances as children of the
+ MenuBar and the respective items are created automatically.
+
+ \sa {Customizing MenuBar}, MenuBar, {Menu Controls}
+*/
+
+/*!
+ \qmlsignal void QtQuick.Controls::MenuBarItem::triggered()
+
+ This signal is emitted when the menu bar item is triggered by the user.
+*/
+
+void QQuickMenuBarItemPrivate::setMenuBar(QQuickMenuBar *newMenuBar)
+{
+ Q_Q(QQuickMenuBarItem);
+ if (menuBar == newMenuBar)
+ return;
+
+ menuBar = newMenuBar;
+ emit q->menuBarChanged();
+}
+
+QQuickMenuBarItem::QQuickMenuBarItem(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickMenuBarItemPrivate), parent)
+{
+ setFocusPolicy(Qt::NoFocus);
+ connect(this, &QQuickAbstractButton::clicked, this, &QQuickMenuBarItem::triggered);
+}
+
+/*!
+ \qmlproperty Menu QtQuick.Controls::MenuBarItem::menuBar
+ \readonly
+
+ This property holds the menu bar that contains this item,
+ or \c null if the item is not in a menu bar.
+*/
+QQuickMenuBar *QQuickMenuBarItem::menuBar() const
+{
+ Q_D(const QQuickMenuBarItem);
+ return d->menuBar;
+}
+
+/*!
+ \qmlproperty Menu QtQuick.Controls::MenuBarItem::menu
+
+ This property holds the menu that this item presents in a
+ menu bar, or \c null if this item does not have a menu.
+*/
+QQuickMenu *QQuickMenuBarItem::menu() const
+{
+ Q_D(const QQuickMenuBarItem);
+ return d->menu;
+}
+
+void QQuickMenuBarItem::setMenu(QQuickMenu *menu)
+{
+ Q_D(QQuickMenuBarItem);
+ if (d->menu == menu)
+ return;
+
+ if (d->menu)
+ disconnect(d->menu, &QQuickMenu::titleChanged, this, &QQuickAbstractButton::setText);
+
+ if (menu) {
+ setText(menu->title());
+ menu->setY(height());
+ menu->setParentItem(this);
+ menu->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent);
+ connect(menu, &QQuickMenu::titleChanged, this, &QQuickAbstractButton::setText);
+ }
+
+ d->menu = menu;
+ emit menuChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick.Controls::MenuBarItem::highlighted
+
+ This property holds whether the menu bar item is highlighted by the user.
+
+ A menu bar item can be highlighted by mouse hover or keyboard navigation.
+
+ The default value is \c false.
+*/
+bool QQuickMenuBarItem::isHighlighted() const
+{
+ Q_D(const QQuickMenuBarItem);
+ return d->highlighted;
+}
+
+void QQuickMenuBarItem::setHighlighted(bool highlighted)
+{
+ Q_D(QQuickMenuBarItem);
+ if (highlighted == d->highlighted)
+ return;
+
+ d->highlighted = highlighted;
+ emit highlightedChanged();
+}
+
+void QQuickMenuBarItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickMenuBarItem);
+ QQuickAbstractButton::geometryChanged(newGeometry, oldGeometry);
+ if (d->menu)
+ d->menu->setY(newGeometry.height());
+}
+
+QFont QQuickMenuBarItem::defaultFont() const
+{
+ return QQuickControlPrivate::themeFont(QPlatformTheme::MenuBarFont);
+}
+
+QPalette QQuickMenuBarItem::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::MenuBarPalette);
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickMenuBarItem::accessibleRole() const
+{
+ return QAccessible::MenuBar;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickmenubaritem_p.h b/src/quicktemplates2/qquickmenubaritem_p.h
new file mode 100644
index 00000000..86cd6a6a
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubaritem_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMENUBARITEM_P_H
+#define QQUICKMENUBARITEM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMenu;
+class QQuickMenuBar;
+class QQuickMenuBarItemPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuBarItem : public QQuickAbstractButton
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickMenuBar *menuBar READ menuBar NOTIFY menuBarChanged FINAL)
+ Q_PROPERTY(QQuickMenu *menu READ menu WRITE setMenu NOTIFY menuChanged FINAL)
+ Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL)
+
+public:
+ explicit QQuickMenuBarItem(QQuickItem *parent = nullptr);
+
+ QQuickMenuBar *menuBar() const;
+
+ QQuickMenu *menu() const;
+ void setMenu(QQuickMenu *menu);
+
+ bool isHighlighted() const;
+ void setHighlighted(bool highlighted);
+
+Q_SIGNALS:
+ void triggered();
+ void menuBarChanged();
+ void menuChanged();
+ void highlightedChanged();
+
+protected:
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+
+ QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
+
+#if QT_CONFIG(accessibility)
+ QAccessible::Role accessibleRole() const override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickMenuBarItem)
+ Q_DECLARE_PRIVATE(QQuickMenuBarItem)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickMenuBarItem)
+
+#endif // QQUICKMENUBARITEM_P_H
diff --git a/src/quicktemplates2/qquickmenubaritem_p_p.h b/src/quicktemplates2/qquickmenubaritem_p_p.h
new file mode 100644
index 00000000..bd4c3a43
--- /dev/null
+++ b/src/quicktemplates2/qquickmenubaritem_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMENUBARITEM_P_P_H
+#define QQUICKMENUBARITEM_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickmenubaritem_p.h>
+#include <QtQuickTemplates2/private/qquickabstractbutton_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMenu;
+class QQuickMenuBar;
+
+class QQuickMenuBarItemPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickMenuBarItem)
+
+public:
+ QQuickMenuBarItemPrivate()
+ : highlighted(false),
+ menu(nullptr),
+ menuBar(nullptr)
+ {
+ }
+
+ static QQuickMenuBarItemPrivate *get(QQuickMenuBarItem *item)
+ {
+ return item->d_func();
+ }
+
+ void setMenuBar(QQuickMenuBar *menuBar);
+
+ bool highlighted;
+ QQuickMenu *menu;
+ QQuickMenuBar *menuBar;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKMENUBARITEM_P_P_H
diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp
index e15640fb..f71b9c35 100644
--- a/src/quicktemplates2/qquickmenuitem.cpp
+++ b/src/quicktemplates2/qquickmenuitem.cpp
@@ -35,7 +35,8 @@
****************************************************************************/
#include "qquickmenuitem_p.h"
-#include "qquickabstractbutton_p_p.h"
+#include "qquickmenuitem_p_p.h"
+#include "qquickmenu_p.h"
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQuick/private/qquickevents_p_p.h>
@@ -55,6 +56,10 @@ QT_BEGIN_NAMESPACE
providing a familiar way to respond to menu items being \l triggered, for
example.
+ MenuItem inherits its API from AbstractButton. For instance, you can set
+ \l {AbstractButton::text}{text} and \l {Icons in Qt Quick Controls 2}{icon}
+ using the AbstractButton API.
+
\code
Button {
id: fileButton
@@ -80,22 +85,53 @@ QT_BEGIN_NAMESPACE
}
\endcode
- \sa {Customizing MenuItem}, {Menu Controls}
+ \sa {Customizing Menu}, Menu, {Menu Controls}
*/
-class QQuickMenuItemPrivate : public QQuickAbstractButtonPrivate
+QQuickMenuItemPrivate::QQuickMenuItemPrivate()
+ : highlighted(false),
+ arrow(nullptr),
+ menu(nullptr),
+ subMenu(nullptr)
{
- Q_DECLARE_PUBLIC(QQuickMenuItem)
+}
-public:
- QQuickMenuItemPrivate();
+void QQuickMenuItemPrivate::setMenu(QQuickMenu *newMenu)
+{
+ Q_Q(QQuickMenuItem);
+ if (menu == newMenu)
+ return;
- bool highlighted;
-};
+ menu = newMenu;
+ emit q->menuChanged();
+}
-QQuickMenuItemPrivate::QQuickMenuItemPrivate()
- : highlighted(false)
+void QQuickMenuItemPrivate::setSubMenu(QQuickMenu *newSubMenu)
{
+ Q_Q(QQuickMenuItem);
+ if (subMenu == newSubMenu)
+ return;
+
+ if (subMenu) {
+ QObject::disconnect(subMenu, &QQuickMenu::titleChanged, q, &QQuickAbstractButton::setText);
+ QObjectPrivate::disconnect(subMenu, &QQuickPopup::enabledChanged, this, &QQuickMenuItemPrivate::updateEnabled);
+ }
+
+ if (newSubMenu) {
+ QObject::connect(newSubMenu, &QQuickMenu::titleChanged, q, &QQuickAbstractButton::setText);
+ QObjectPrivate::connect(newSubMenu, &QQuickPopup::enabledChanged, this, &QQuickMenuItemPrivate::updateEnabled);
+ q->setText(newSubMenu->title());
+ }
+
+ subMenu = newSubMenu;
+ updateEnabled();
+ emit q->subMenuChanged();
+}
+
+void QQuickMenuItemPrivate::updateEnabled()
+{
+ Q_Q(QQuickMenuItem);
+ q->setEnabled(subMenu && subMenu->isEnabled());
}
/*!
@@ -110,20 +146,16 @@ QQuickMenuItem::QQuickMenuItem(QQuickItem *parent)
connect(this, &QQuickAbstractButton::clicked, this, &QQuickMenuItem::triggered);
}
-QFont QQuickMenuItem::defaultFont() const
-{
- return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont);
-}
-
/*!
\qmlproperty bool QtQuick.Controls::MenuItem::highlighted
- This property holds whether the menu item is highlighted.
+ This property holds whether the menu item is highlighted by the user.
- A menu item can be highlighted in order to draw the user's attention
- towards it. It has no effect on keyboard interaction.
+ A menu item can be highlighted by mouse hover or keyboard navigation.
The default value is \c false.
+
+ \sa Menu::currentIndex
*/
bool QQuickMenuItem::isHighlighted() const
{
@@ -141,6 +173,71 @@ void QQuickMenuItem::setHighlighted(bool highlighted)
emit highlightedChanged();
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Item QtQuick.Controls::MenuItem::arrow
+
+ This property holds the sub-menu arrow item.
+
+ \sa {Customizing Menu}
+*/
+QQuickItem *QQuickMenuItem::arrow() const
+{
+ Q_D(const QQuickMenuItem);
+ return d->arrow;
+}
+
+void QQuickMenuItem::setArrow(QQuickItem *arrow)
+{
+ Q_D(QQuickMenuItem);
+ if (d->arrow == arrow)
+ return;
+
+ QQuickControlPrivate::destroyDelegate(d->arrow, this);
+ d->arrow = arrow;
+ if (arrow && !arrow->parentItem())
+ arrow->setParentItem(this);
+ emit arrowChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Menu QtQuick.Controls::MenuItem::menu
+ \readonly
+
+ This property holds the menu that contains this menu item,
+ or \c null if the item is not in a menu.
+*/
+QQuickMenu *QQuickMenuItem::menu() const
+{
+ Q_D(const QQuickMenuItem);
+ return d->menu;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty Menu QtQuick.Controls::MenuItem::subMenu
+ \readonly
+
+ This property holds the sub-menu that this item presents in
+ the parent menu, or \c null if this item is not a sub-menu item.
+*/
+QQuickMenu *QQuickMenuItem::subMenu() const
+{
+ Q_D(const QQuickMenuItem);
+ return d->subMenu;
+}
+
+QFont QQuickMenuItem::defaultFont() const
+{
+ return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont);
+}
+
+QPalette QQuickMenuItem::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenuItem::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickmenuitem_p.h b/src/quicktemplates2/qquickmenuitem_p.h
index 76f41f9d..8af3cbd1 100644
--- a/src/quicktemplates2/qquickmenuitem_p.h
+++ b/src/quicktemplates2/qquickmenuitem_p.h
@@ -52,12 +52,17 @@
QT_BEGIN_NAMESPACE
+class QQuickMenu;
class QQuickMenuItemPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuItem : public QQuickAbstractButton
{
Q_OBJECT
Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QQuickItem *arrow READ arrow WRITE setArrow NOTIFY arrowChanged FINAL REVISION 3)
+ Q_PROPERTY(QQuickMenu *menu READ menu NOTIFY menuChanged FINAL REVISION 3)
+ Q_PROPERTY(QQuickMenu *subMenu READ subMenu NOTIFY subMenuChanged FINAL REVISION 3)
public:
explicit QQuickMenuItem(QQuickItem *parent = nullptr);
@@ -65,12 +70,24 @@ public:
bool isHighlighted() const;
void setHighlighted(bool highlighted);
+ // 2.3 (Qt 5.10)
+ QQuickItem *arrow() const;
+ void setArrow(QQuickItem *arrow);
+
+ QQuickMenu *menu() const;
+ QQuickMenu *subMenu() const;
+
Q_SIGNALS:
void triggered();
void highlightedChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void arrowChanged();
+ Q_REVISION(3) void menuChanged();
+ Q_REVISION(3) void subMenuChanged();
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickmenuitem_p_p.h b/src/quicktemplates2/qquickmenuitem_p_p.h
new file mode 100644
index 00000000..e0e90ff1
--- /dev/null
+++ b/src/quicktemplates2/qquickmenuitem_p_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKMENUITEM_P_P_H
+#define QQUICKMENUITEM_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTemplates2/private/qquickmenuitem_p.h>
+#include <QtQuickTemplates2/private/qquickabstractbutton_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMenu;
+
+class QQuickMenuItemPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickMenuItem)
+
+public:
+ QQuickMenuItemPrivate();
+
+ static QQuickMenuItemPrivate *get(QQuickMenuItem *item)
+ {
+ return item->d_func();
+ }
+
+ void setMenu(QQuickMenu *menu);
+ void setSubMenu(QQuickMenu *subMenu);
+
+ void updateEnabled();
+
+ bool highlighted;
+ QQuickItem *arrow;
+ QQuickMenu *menu;
+ QQuickMenu *subMenu;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKMENUITEM_P_P_H
diff --git a/src/quicktemplates2/qquickmenuseparator.cpp b/src/quicktemplates2/qquickmenuseparator.cpp
index 366f0a27..dee5287a 100644
--- a/src/quicktemplates2/qquickmenuseparator.cpp
+++ b/src/quicktemplates2/qquickmenuseparator.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qquickmenuseparator_p.h"
+#include "qquickcontrol_p_p.h"
QT_BEGIN_NAMESPACE
@@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE
\printuntil }
\printuntil }
- \sa {Customizing MenuSeparator}, {Separator Controls}
+ \sa {Customizing Menu}, Menu, {Separator Controls}
*/
QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent)
@@ -70,6 +71,11 @@ QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent)
{
}
+QPalette QQuickMenuSeparator::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::MenuPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenuSeparator::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickmenuseparator_p.h b/src/quicktemplates2/qquickmenuseparator_p.h
index 42147f77..002b68ba 100644
--- a/src/quicktemplates2/qquickmenuseparator_p.h
+++ b/src/quicktemplates2/qquickmenuseparator_p.h
@@ -60,6 +60,8 @@ public:
explicit QQuickMenuSeparator(QQuickItem *parent = nullptr);
protected:
+ QPalette defaultPalette() const override;
+
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index f30f6a5e..38f7949e 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -47,102 +47,42 @@
QT_BEGIN_NAMESPACE
-void QQuickOverlayPrivate::popupAboutToShow()
-{
- Q_Q(QQuickOverlay);
- QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender());
- if (!popup || !popup->dim())
- return;
-
- // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
- QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
- if (p->dimmer)
- QQmlProperty::write(p->dimmer, QStringLiteral("opacity"), 1.0);
-}
-
-void QQuickOverlayPrivate::popupAboutToHide()
-{
- Q_Q(QQuickOverlay);
- QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender());
- if (!popup || !popup->dim())
- return;
-
- // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
- QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
- if (p->dimmer)
- QQmlProperty::write(p->dimmer, QStringLiteral("opacity"), 0.0);
-}
-
-static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent)
-{
- QQuickItem *item = nullptr;
- if (component) {
- QQmlContext *creationContext = component->creationContext();
- if (!creationContext)
- creationContext = qmlContext(popup);
- QQmlContext *context = new QQmlContext(creationContext, popup);
- context->setContextObject(popup);
- item = qobject_cast<QQuickItem*>(component->beginCreate(context));
- }
-
- // when there is no overlay component available (with plain QQuickWindow),
- // use a plain QQuickItem as a fallback to block hover events
- if (!item && popup->isModal())
- item = new QQuickItem;
-
- if (item) {
- item->setOpacity(popup->isVisible() ? 1.0 : 0.0);
- item->setParentItem(parent);
- item->stackBefore(popup->popupItem());
- item->setZ(popup->z());
- if (popup->isModal()) {
- item->setAcceptedMouseButtons(Qt::AllButtons);
-#if QT_CONFIG(cursor)
- item->setCursor(Qt::ArrowCursor);
-#endif
-#if QT_CONFIG(quicktemplates2_hover)
- // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
- item->setAcceptHoverEvents(true);
- // item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
- // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
-#endif
+/*!
+ \qmltype Overlay
+ \inherits Item
+ \instantiates QQuickOverlay
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \brief A window overlay for popups.
+
+ Overlay provides a layer for popups, ensuring that popups are displayed above
+ other content and that the background is dimmed when a \l {Popup::}{modal} or
+ \l {Popup::dim}{dimmed} popup is visible.
+
+ The overlay is an ordinary Item that covers the entire window. It can be used
+ as a visual parent to position a popup in scene coordinates. The following
+ example uses the attached \c overlay property to position a popup to the center
+ of the window, despite the position of the button that opens the popup.
+
+ \code
+ Button {
+ onClicked: popup.open()
+
+ Popup {
+ id: popup
+
+ parent: Overlay.overlay
+
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: 100
+ height: 100
}
- if (component)
- component->completeCreate();
}
- return item;
-}
+ \endcode
-void QQuickOverlayPrivate::createOverlay(QQuickPopup *popup)
-{
- Q_Q(QQuickOverlay);
- QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
- if (!p->dimmer)
- p->dimmer = createDimmer(popup->isModal() ? modal : modeless, popup, q);
- p->resizeOverlay();
-}
-
-void QQuickOverlayPrivate::destroyOverlay(QQuickPopup *popup)
-{
- QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
- if (p->dimmer) {
- p->dimmer->setParentItem(nullptr);
- p->dimmer->deleteLater();
- p->dimmer = nullptr;
- }
-}
-
-void QQuickOverlayPrivate::toggleOverlay()
-{
- Q_Q(QQuickOverlay);
- QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender());
- if (!popup)
- return;
-
- destroyOverlay(popup);
- if (popup->dim())
- createOverlay(popup);
-}
+ \sa ApplicationWindow
+*/
QVector<QQuickPopup *> QQuickOverlayPrivate::stackingOrderPopups() const
{
@@ -461,37 +401,18 @@ QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window)
return overlay;
}
+QQuickOverlayAttached *QQuickOverlay::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickOverlayAttached(object);
+}
+
void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
{
Q_D(QQuickOverlay);
QQuickItem::itemChange(change, data);
- QQuickPopup *popup = nullptr;
- if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
- popup = qobject_cast<QQuickPopup *>(data.item->parent());
+ if (change == ItemChildAddedChange || change == ItemChildRemovedChange)
setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
- }
- if (!popup)
- return;
-
- if (change == ItemChildAddedChange) {
- if (popup->dim())
- d->createOverlay(popup);
- QObjectPrivate::connect(popup, &QQuickPopup::dimChanged, d, &QQuickOverlayPrivate::toggleOverlay);
- QObjectPrivate::connect(popup, &QQuickPopup::modalChanged, d, &QQuickOverlayPrivate::toggleOverlay);
- if (!qobject_cast<QQuickDrawer *>(popup)) {
- QObjectPrivate::connect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow);
- QObjectPrivate::connect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide);
- }
- } else if (change == ItemChildRemovedChange) {
- d->destroyOverlay(popup);
- QObjectPrivate::disconnect(popup, &QQuickPopup::dimChanged, d, &QQuickOverlayPrivate::toggleOverlay);
- QObjectPrivate::disconnect(popup, &QQuickPopup::modalChanged, d, &QQuickOverlayPrivate::toggleOverlay);
- if (!qobject_cast<QQuickDrawer *>(popup)) {
- QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow);
- QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide);
- }
- }
}
void QQuickOverlay::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
@@ -654,4 +575,149 @@ bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
return false;
}
+class QQuickOverlayAttachedPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickOverlayAttached)
+
+public:
+ QQuickOverlayAttachedPrivate()
+ : window(nullptr),
+ modal(nullptr),
+ modeless(nullptr)
+ {
+ }
+
+ void setWindow(QQuickWindow *newWindow);
+
+ QQuickWindow *window;
+ QQmlComponent *modal;
+ QQmlComponent *modeless;
+};
+
+void QQuickOverlayAttachedPrivate::setWindow(QQuickWindow *newWindow)
+{
+ Q_Q(QQuickOverlayAttached);
+ if (window == newWindow)
+ return;
+
+ if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) {
+ QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
+ QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
+ }
+
+ if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow)) {
+ QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
+ QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
+ }
+
+ window = newWindow;
+ emit q->overlayChanged();
+}
+
+/*!
+ \qmlattachedsignal QtQuick.Controls::Overlay::pressed()
+
+ This attached signal is emitted when the overlay is pressed by the user while
+ a popup is visible.
+
+ The signal can be attached to any item, popup, or window. When attached to an
+ item or a popup, the signal is only emitted if the item or popup is in a window.
+*/
+
+/*!
+ \qmlattachedsignal QtQuick.Controls::Overlay::released()
+
+ This attached signal is emitted when the overlay is released by the user while
+ a popup is visible.
+
+ The signal can be attached to any item, popup, or window. When attached to an
+ item or a popup, the signal is only emitted if the item or popup is in a window.
+*/
+
+QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
+ : QObject(*(new QQuickOverlayAttachedPrivate), parent)
+{
+ Q_D(QQuickOverlayAttached);
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
+ d->setWindow(item->window());
+ QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
+ } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
+ d->setWindow(popup->window());
+ QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
+ } else {
+ d->setWindow(qobject_cast<QQuickWindow *>(parent));
+ }
+}
+
+/*!
+ \qmlattachedproperty Overlay QtQuick.Controls::Overlay::overlay
+ \readonly
+
+ This attached property holds the window overlay item.
+
+ The property can be attached to any item, popup, or window. When attached to an
+ item or a popup, the value is \c null if the item or popup is not in a window.
+*/
+QQuickOverlay *QQuickOverlayAttached::overlay() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return QQuickOverlay::overlay(d->window);
+}
+
+/*!
+ \qmlattachedproperty Component QtQuick.Controls::Overlay::modal
+
+ This attached property holds a component to use as a visual item that implements
+ background dimming for modal popups. It is created for and stacked below visible
+ modal popups.
+
+ The property can be attached to any popup.
+
+ \sa Popup::modal
+*/
+QQmlComponent *QQuickOverlayAttached::modal() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return d->modal;
+}
+
+void QQuickOverlayAttached::setModal(QQmlComponent *modal)
+{
+ Q_D(QQuickOverlayAttached);
+ if (d->modal == modal)
+ return;
+
+ delete d->modal;
+ d->modal = modal;
+ emit modalChanged();
+}
+
+/*!
+ \qmlattachedproperty Component QtQuick.Controls::Overlay::modeless
+
+ This attached property holds a component to use as a visual item that implements
+ background dimming for modeless popups. It is created for and stacked below visible
+ dimming popups.
+
+ The property can be attached to any popup.
+
+ \sa Popup::dim
+*/
+QQmlComponent *QQuickOverlayAttached::modeless() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return d->modeless;
+}
+
+void QQuickOverlayAttached::setModeless(QQmlComponent *modeless)
+{
+ Q_D(QQuickOverlayAttached);
+ if (d->modeless == modeless)
+ return;
+
+ delete d->modeless;
+ d->modeless = modeless;
+ emit modelessChanged();
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h
index ba61c9c9..0d8bccf5 100644
--- a/src/quicktemplates2/qquickoverlay_p.h
+++ b/src/quicktemplates2/qquickoverlay_p.h
@@ -55,6 +55,8 @@ QT_BEGIN_NAMESPACE
class QQmlComponent;
class QQuickOverlayPrivate;
+class QQuickOverlayAttached;
+class QQuickOverlayAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickOverlay : public QQuickItem
{
@@ -74,6 +76,8 @@ public:
static QQuickOverlay *overlay(QQuickWindow *window);
+ static QQuickOverlayAttached *qmlAttachedProperties(QObject *object);
+
Q_SIGNALS:
void modalChanged();
void modelessChanged();
@@ -101,8 +105,39 @@ private:
Q_DECLARE_PRIVATE(QQuickOverlay)
};
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickOverlayAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickOverlay *overlay READ overlay NOTIFY overlayChanged FINAL)
+ Q_PROPERTY(QQmlComponent *modal READ modal WRITE setModal NOTIFY modalChanged FINAL)
+ Q_PROPERTY(QQmlComponent *modeless READ modeless WRITE setModeless NOTIFY modelessChanged FINAL)
+
+public:
+ explicit QQuickOverlayAttached(QObject *parent = nullptr);
+
+ QQuickOverlay *overlay() const;
+
+ QQmlComponent *modal() const;
+ void setModal(QQmlComponent *modal);
+
+ QQmlComponent *modeless() const;
+ void setModeless(QQmlComponent *modeless);
+
+Q_SIGNALS:
+ void overlayChanged();
+ void modalChanged();
+ void modelessChanged();
+ void pressed();
+ void released();
+
+private:
+ Q_DISABLE_COPY(QQuickOverlayAttached)
+ Q_DECLARE_PRIVATE(QQuickOverlayAttached)
+};
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickOverlay)
+QML_DECLARE_TYPEINFO(QQuickOverlay, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKOVERLAY_P_H
diff --git a/src/quicktemplates2/qquickoverlay_p_p.h b/src/quicktemplates2/qquickoverlay_p_p.h
index dfedf7c0..a290ecc2 100644
--- a/src/quicktemplates2/qquickoverlay_p_p.h
+++ b/src/quicktemplates2/qquickoverlay_p_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include "qquickoverlay_p.h"
+#include <QtQuickTemplates2/private/qquickoverlay_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
@@ -84,13 +84,6 @@ public:
void removePopup(QQuickPopup *popup);
void setMouseGrabberPopup(QQuickPopup *popup);
- void popupAboutToShow();
- void popupAboutToHide();
-
- void createOverlay(QQuickPopup *popup);
- void destroyOverlay(QQuickPopup *popup);
- void toggleOverlay();
-
QVector<QQuickPopup *> stackingOrderPopups() const;
QVector<QQuickDrawer *> stackingOrderDrawers() const;
diff --git a/src/quicktemplates2/qquickpalette.cpp b/src/quicktemplates2/qquickpalette.cpp
new file mode 100644
index 00000000..018d6fdc
--- /dev/null
+++ b/src/quicktemplates2/qquickpalette.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickpalette_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QColor QQuickPalette::alternateBase() const
+{
+ return v.color(QPalette::AlternateBase);
+}
+
+void QQuickPalette::setAlternateBase(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::AlternateBase, color);
+}
+
+void QQuickPalette::resetAlternateBase()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::AlternateBase));
+}
+
+QColor QQuickPalette::base() const
+{
+ return v.color(QPalette::Base);
+}
+
+void QQuickPalette::setBase(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Base, color);
+}
+
+void QQuickPalette::resetBase()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Base));
+}
+
+QColor QQuickPalette::brightText() const
+{
+ return v.color(QPalette::BrightText);
+}
+
+void QQuickPalette::setBrightText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::BrightText, color);
+}
+
+void QQuickPalette::resetBrightText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::BrightText));
+}
+
+QColor QQuickPalette::button() const
+{
+ return v.color(QPalette::Button);
+}
+
+void QQuickPalette::setButton(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Button, color);
+}
+
+void QQuickPalette::resetButton()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Button));
+}
+
+QColor QQuickPalette::buttonText() const
+{
+ return v.color(QPalette::ButtonText);
+}
+
+void QQuickPalette::setButtonText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::ButtonText, color);
+}
+
+void QQuickPalette::resetButtonText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::ButtonText));
+}
+
+QColor QQuickPalette::dark() const
+{
+ return v.color(QPalette::Dark);
+}
+
+void QQuickPalette::setDark(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Dark, color);
+}
+
+void QQuickPalette::resetDark()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Dark));
+}
+
+QColor QQuickPalette::highlight() const
+{
+ return v.color(QPalette::Highlight);
+}
+
+void QQuickPalette::setHighlight(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Highlight, color);
+}
+
+void QQuickPalette::resetHighlight()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Highlight));
+}
+
+QColor QQuickPalette::highlightedText() const
+{
+ return v.color(QPalette::HighlightedText);
+}
+
+void QQuickPalette::setHighlightedText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::HighlightedText, color);
+}
+
+void QQuickPalette::resetHighlightedText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::HighlightedText));
+}
+
+QColor QQuickPalette::light() const
+{
+ return v.color(QPalette::Light);
+}
+
+void QQuickPalette::setLight(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Light, color);
+}
+
+void QQuickPalette::resetLight()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Light));
+}
+
+QColor QQuickPalette::link() const
+{
+ return v.color(QPalette::Link);
+}
+
+void QQuickPalette::setLink(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Link, color);
+}
+
+void QQuickPalette::resetLink()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Link));
+}
+
+QColor QQuickPalette::linkVisited() const
+{
+ return v.color(QPalette::LinkVisited);
+}
+
+void QQuickPalette::setLinkVisited(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::LinkVisited, color);
+}
+
+void QQuickPalette::resetLinkVisited()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::LinkVisited));
+}
+
+QColor QQuickPalette::mid() const
+{
+ return v.color(QPalette::Mid);
+}
+
+void QQuickPalette::setMid(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Mid, color);
+}
+
+void QQuickPalette::resetMid()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Mid));
+}
+
+QColor QQuickPalette::midlight() const
+{
+ return v.color(QPalette::Midlight);
+}
+
+void QQuickPalette::setMidlight(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Midlight, color);
+}
+
+void QQuickPalette::resetMidlight()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Midlight));
+}
+
+QColor QQuickPalette::shadow() const
+{
+ return v.color(QPalette::Shadow);
+}
+
+void QQuickPalette::setShadow(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Shadow, color);
+}
+
+void QQuickPalette::resetShadow()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Shadow));
+}
+
+QColor QQuickPalette::text() const
+{
+ return v.color(QPalette::Text);
+}
+
+void QQuickPalette::setText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Text, color);
+}
+
+void QQuickPalette::resetText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Text));
+}
+
+QColor QQuickPalette::toolTipBase() const
+{
+ return v.color(QPalette::ToolTipBase);
+}
+
+void QQuickPalette::setToolTipBase(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::ToolTipBase, color);
+}
+
+void QQuickPalette::resetToolTipBase()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::ToolTipBase));
+}
+
+QColor QQuickPalette::toolTipText() const
+{
+ return v.color(QPalette::ToolTipText);
+}
+
+void QQuickPalette::setToolTipText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::ToolTipText, color);
+}
+
+void QQuickPalette::resetToolTipText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::ToolTipText));
+}
+
+QColor QQuickPalette::window() const
+{
+ return v.color(QPalette::Window);
+}
+
+void QQuickPalette::setWindow(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::Window, color);
+}
+
+void QQuickPalette::resetWindow()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::Window));
+}
+
+QColor QQuickPalette::windowText() const
+{
+ return v.color(QPalette::WindowText);
+}
+
+void QQuickPalette::setWindowText(const QColor &color)
+{
+ v.setColor(QPalette::All, QPalette::WindowText, color);
+}
+
+void QQuickPalette::resetWindowText()
+{
+ v.resolve(v.resolve() & ~(1 << QPalette::WindowText));
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickpalette_p.h b/src/quicktemplates2/qquickpalette_p.h
new file mode 100644
index 00000000..d43e78a6
--- /dev/null
+++ b/src/quicktemplates2/qquickpalette_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPALETTE_P_H
+#define QQUICKPALETTE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qpalette.h>
+#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPalette
+{
+ Q_GADGET
+ Q_PROPERTY(QColor alternateBase READ alternateBase WRITE setAlternateBase RESET resetAlternateBase FINAL)
+ Q_PROPERTY(QColor base READ base WRITE setBase RESET resetBase FINAL)
+ Q_PROPERTY(QColor brightText READ brightText WRITE setBrightText RESET resetBrightText FINAL)
+ Q_PROPERTY(QColor button READ button WRITE setButton RESET resetButton FINAL)
+ Q_PROPERTY(QColor buttonText READ buttonText WRITE setButtonText RESET resetButtonText FINAL)
+ Q_PROPERTY(QColor dark READ dark WRITE setDark RESET resetDark FINAL)
+ Q_PROPERTY(QColor highlight READ highlight WRITE setHighlight RESET resetHighlight FINAL)
+ Q_PROPERTY(QColor highlightedText READ highlightedText WRITE setHighlightedText RESET resetHighlightedText FINAL)
+ Q_PROPERTY(QColor light READ light WRITE setLight RESET resetLight FINAL)
+ Q_PROPERTY(QColor link READ link WRITE setLink RESET resetLink FINAL)
+ Q_PROPERTY(QColor linkVisited READ linkVisited WRITE setLinkVisited RESET resetLinkVisited FINAL)
+ Q_PROPERTY(QColor mid READ mid WRITE setMid RESET resetMid FINAL)
+ Q_PROPERTY(QColor midlight READ midlight WRITE setMidlight RESET resetMidlight FINAL)
+ Q_PROPERTY(QColor shadow READ shadow WRITE setShadow RESET resetShadow FINAL)
+ Q_PROPERTY(QColor text READ text WRITE setText RESET resetText FINAL)
+ Q_PROPERTY(QColor toolTipBase READ toolTipBase WRITE setToolTipBase RESET resetToolTipBase FINAL)
+ Q_PROPERTY(QColor toolTipText READ toolTipText WRITE setToolTipText RESET resetToolTipText FINAL)
+ Q_PROPERTY(QColor window READ window WRITE setWindow RESET resetWindow FINAL)
+ Q_PROPERTY(QColor windowText READ windowText WRITE setWindowText RESET resetWindowText FINAL)
+
+public:
+ QColor alternateBase() const;
+ void setAlternateBase(const QColor &color);
+ void resetAlternateBase();
+
+ QColor base() const;
+ void setBase(const QColor &color);
+ void resetBase();
+
+ QColor brightText() const;
+ void setBrightText(const QColor &color);
+ void resetBrightText();
+
+ QColor button() const;
+ void setButton(const QColor &color);
+ void resetButton();
+
+ QColor buttonText() const;
+ void setButtonText(const QColor &color);
+ void resetButtonText();
+
+ QColor dark() const;
+ void setDark(const QColor &color);
+ void resetDark();
+
+ QColor highlight() const;
+ void setHighlight(const QColor &color);
+ void resetHighlight();
+
+ QColor highlightedText() const;
+ void setHighlightedText(const QColor &color);
+ void resetHighlightedText();
+
+ QColor light() const;
+ void setLight(const QColor &color);
+ void resetLight();
+
+ QColor link() const;
+ void setLink(const QColor &color);
+ void resetLink();
+
+ QColor linkVisited() const;
+ void setLinkVisited(const QColor &color);
+ void resetLinkVisited();
+
+ QColor mid() const;
+ void setMid(const QColor &color);
+ void resetMid();
+
+ QColor midlight() const;
+ void setMidlight(const QColor &color);
+ void resetMidlight();
+
+ QColor shadow() const;
+ void setShadow(const QColor &color);
+ void resetShadow();
+
+ QColor text() const;
+ void setText(const QColor &color);
+ void resetText();
+
+ QColor toolTipBase() const;
+ void setToolTipBase(const QColor &color);
+ void resetToolTipBase();
+
+ QColor toolTipText() const;
+ void setToolTipText(const QColor &color);
+ void resetToolTipText();
+
+ QColor window() const;
+ void setWindow(const QColor &color);
+ void resetWindow();
+
+ QColor windowText() const;
+ void setWindowText(const QColor &color);
+ void resetWindowText();
+
+private:
+ QPalette v;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPALETTE_P_H
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index ce4072e5..472d2124 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -203,6 +203,8 @@ QT_BEGIN_NAMESPACE
\sa closed()
*/
+static const QQuickPopup::ClosePolicy DefaultClosePolicy = QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside;
+
QQuickPopupPrivate::QQuickPopupPrivate()
: focus(false),
modal(false),
@@ -225,6 +227,7 @@ QQuickPopupPrivate::QQuickPopupPrivate()
allowHorizontalResize(true),
hadActiveFocusBeforeExitTransition(false),
interactive(true),
+ hasClosePolicy(false),
touchId(-1),
x(0),
y(0),
@@ -238,7 +241,7 @@ QQuickPopupPrivate::QQuickPopupPrivate()
contentWidth(0),
contentHeight(0),
transitionState(QQuickPopupPrivate::NoTransition),
- closePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside),
+ closePolicy(DefaultClosePolicy),
parentItem(nullptr),
dimmer(nullptr),
window(nullptr),
@@ -260,6 +263,7 @@ void QQuickPopupPrivate::init()
popupItem = new QQuickPopupItem(q);
popupItem->setVisible(false);
q->setParentItem(qobject_cast<QQuickItem *>(parent));
+ QObject::connect(popupItem, &QQuickItem::enabledChanged, q, &QQuickPopup::enabledChanged);
QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
QObject::connect(popupItem, &QQuickControl::contentItemChanged, q, &QQuickPopup::contentItemChanged);
positioner = new QQuickPopupPositioner(q);
@@ -425,6 +429,9 @@ bool QQuickPopupPrivate::prepareEnterTransition()
if (transitionState != EnterTransition) {
popupItem->setParentItem(QQuickOverlay::overlay(window));
+ if (dim)
+ createOverlay();
+ showOverlay();
emit q->aboutToShow();
visible = true;
transitionState = EnterTransition;
@@ -449,7 +456,9 @@ bool QQuickPopupPrivate::prepareExitTransition()
popupItem->setFocus(false);
}
transitionState = ExitTransition;
+ hideOverlay();
emit q->aboutToHide();
+ emit q->openedChanged();
}
return true;
}
@@ -460,6 +469,7 @@ void QQuickPopupPrivate::finalizeEnterTransition()
if (focus)
popupItem->setFocus(true);
transitionState = NoTransition;
+ emit q->openedChanged();
emit q->opened();
}
@@ -469,6 +479,7 @@ void QQuickPopupPrivate::finalizeExitTransition()
positioner->setParentItem(nullptr);
popupItem->setParentItem(nullptr);
popupItem->setVisible(false);
+ destroyOverlay();
if (hadActiveFocusBeforeExitTransition && window) {
// restore focus to the next popup in chain, or to the window content if there are no other popups open
@@ -572,6 +583,7 @@ void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem);
p->resolveFont();
+ p->resolvePalette();
if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(newWindow))
p->updateLocale(appWindow->locale(), false); // explicit=false
}
@@ -594,6 +606,96 @@ void QQuickPopupPrivate::reposition()
positioner->reposition();
}
+static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent)
+{
+ QQuickItem *item = nullptr;
+ if (component) {
+ QQmlContext *creationContext = component->creationContext();
+ if (!creationContext)
+ creationContext = qmlContext(popup);
+ QQmlContext *context = new QQmlContext(creationContext, popup);
+ context->setContextObject(popup);
+ item = qobject_cast<QQuickItem*>(component->beginCreate(context));
+ }
+
+ // when there is no overlay component available (with plain QQuickWindow),
+ // use a plain QQuickItem as a fallback to block hover events
+ if (!item && popup->isModal())
+ item = new QQuickItem;
+
+ if (item) {
+ item->setOpacity(popup->isVisible() ? 1.0 : 0.0);
+ item->setParentItem(parent);
+ item->stackBefore(popup->popupItem());
+ item->setZ(popup->z());
+ if (popup->isModal()) {
+ item->setAcceptedMouseButtons(Qt::AllButtons);
+#if QT_CONFIG(cursor)
+ item->setCursor(Qt::ArrowCursor);
+#endif
+#if QT_CONFIG(quicktemplates2_hover)
+ // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
+ item->setAcceptHoverEvents(true);
+ // item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
+ // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
+#endif
+ }
+ if (component)
+ component->completeCreate();
+ }
+ return item;
+}
+
+void QQuickPopupPrivate::createOverlay()
+{
+ Q_Q(QQuickPopup);
+ QQuickOverlay *overlay = QQuickOverlay::overlay(window);
+ if (!overlay)
+ return;
+
+ QQmlComponent *component = nullptr;
+ QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(qmlAttachedPropertiesObject<QQuickOverlay>(q, false));
+ if (overlayAttached)
+ component = modal ? overlayAttached->modal() : overlayAttached->modeless();
+
+ if (!component)
+ component = modal ? overlay->modal() : overlay->modeless();
+
+ if (!dimmer)
+ dimmer = createDimmer(component, q, overlay);
+ resizeOverlay();
+}
+
+void QQuickPopupPrivate::destroyOverlay()
+{
+ if (dimmer) {
+ dimmer->setParentItem(nullptr);
+ dimmer->deleteLater();
+ dimmer = nullptr;
+ }
+}
+
+void QQuickPopupPrivate::toggleOverlay()
+{
+ destroyOverlay();
+ if (dim)
+ createOverlay();
+}
+
+void QQuickPopupPrivate::showOverlay()
+{
+ // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
+ if (dim && dimmer)
+ QQmlProperty::write(dimmer, QStringLiteral("opacity"), 1.0);
+}
+
+void QQuickPopupPrivate::hideOverlay()
+{
+ // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
+ if (dim && dimmer)
+ QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0);
+}
+
void QQuickPopupPrivate::resizeOverlay()
{
if (!dimmer)
@@ -662,6 +764,7 @@ QQuickPopup::~QQuickPopup()
setParentItem(nullptr);
d->popupItem->ungrabShortcut();
delete d->popupItem;
+ d->popupItem = nullptr;
}
/*!
@@ -1291,7 +1394,7 @@ void QQuickPopup::resetBottomPadding()
This property holds the locale of the popup.
- \sa {LayoutMirroring}{LayoutMirroring}
+ \sa mirrored, {LayoutMirroring}{LayoutMirroring}
*/
QLocale QQuickPopup::locale() const
{
@@ -1312,6 +1415,25 @@ void QQuickPopup::resetLocale()
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Popup::mirrored
+ \readonly
+
+ This property holds whether the popup is mirrored.
+
+ This property is provided for convenience. A popup is considered mirrored
+ when its visual layout direction is right-to-left; that is, when using a
+ right-to-left locale.
+
+ \sa locale, {Right-to-left User Interfaces}
+*/
+bool QQuickPopup::isMirrored() const
+{
+ Q_D(const QQuickPopup);
+ return d->popupItem->isMirrored();
+}
+
+/*!
\qmlproperty font QtQuick.Controls::Popup::font
This property holds the font currently set for the popup.
@@ -1356,6 +1478,53 @@ void QQuickPopup::resetFont()
d->popupItem->resetFont();
}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::Popup::palette
+
+ This property holds the palette currently set for the popup.
+
+ Popup propagates explicit palette properties to its children. If you change a specific
+ property on a popup's palette, that property propagates to all of the popup's children,
+ overriding any system defaults for that property.
+
+ \code
+ Popup {
+ palette.text: "red"
+
+ Column {
+ Label {
+ text: qsTr("This will use red color...")
+ }
+
+ Switch {
+ text: qsTr("... and so will this")
+ }
+ }
+ }
+ \endcode
+
+ \sa Control::palette, ApplicationWindow::palette, {qtquickcontrols2-palette}{palette QML Basic Type}
+*/
+QPalette QQuickPopup::palette() const
+{
+ Q_D(const QQuickPopup);
+ return d->popupItem->palette();
+}
+
+void QQuickPopup::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickPopup);
+ d->popupItem->setPalette(palette);
+}
+
+void QQuickPopup::resetPalette()
+{
+ Q_D(QQuickPopup);
+ d->popupItem->resetPalette();
+}
+
QQuickWindow *QQuickPopup::window() const
{
Q_D(const QQuickPopup);
@@ -1402,6 +1571,14 @@ void QQuickPopup::setParentItem(QQuickItem *parent)
emit parentChanged();
}
+void QQuickPopup::resetParentItem()
+{
+ if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
+ setParentItem(window->contentItem());
+ else
+ setParentItem(qobject_cast<QQuickItem *>(parent()));
+}
+
/*!
\qmlproperty Item QtQuick.Controls::Popup::background
@@ -1603,6 +1780,8 @@ void QQuickPopup::setModal(bool modal)
if (d->modal == modal)
return;
d->modal = modal;
+ if (d->complete && d->visible)
+ d->toggleOverlay();
emit modalChanged();
if (!d->hasDim) {
@@ -1636,6 +1815,8 @@ void QQuickPopup::setDim(bool dim)
return;
d->dim = dim;
+ if (d->complete && d->visible)
+ d->toggleOverlay();
emit dimChanged();
}
@@ -1654,7 +1835,7 @@ void QQuickPopup::resetDim()
This property holds whether the popup is visible. The default value is \c false.
- \sa open(), close()
+ \sa open(), close(), opened
*/
bool QQuickPopup::isVisible() const
{
@@ -1679,6 +1860,41 @@ void QQuickPopup::setVisible(bool visible)
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Popup::enabled
+
+ This property holds whether the popup is enabled. The default value is \c true.
+
+ \sa visible, Item::enabled
+*/
+bool QQuickPopup::isEnabled() const
+{
+ Q_D(const QQuickPopup);
+ return d->popupItem->isEnabled();
+}
+
+void QQuickPopup::setEnabled(bool enabled)
+{
+ Q_D(QQuickPopup);
+ d->popupItem->setEnabled(enabled);
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Popup::opened
+
+ This property holds whether the popup is fully open. The popup is considered opened
+ when it's visible and neither the \l enter nor \l exit transitions are running.
+
+ \sa open(), close(), visible
+*/
+bool QQuickPopup::isOpened() const
+{
+ Q_D(const QQuickPopup);
+ return d->transitionState == QQuickPopupPrivate::NoTransition && isVisible();
+}
+
+/*!
\qmlproperty real QtQuick.Controls::Popup::opacity
This property holds the opacity of the popup. Opacity is specified as a number between
@@ -1752,6 +1968,7 @@ QQuickPopup::ClosePolicy QQuickPopup::closePolicy() const
void QQuickPopup::setClosePolicy(ClosePolicy policy)
{
Q_D(QQuickPopup);
+ d->hasClosePolicy = true;
if (d->closePolicy == policy)
return;
d->closePolicy = policy;
@@ -1764,6 +1981,13 @@ void QQuickPopup::setClosePolicy(ClosePolicy policy)
emit closePolicyChanged();
}
+void QQuickPopup::resetClosePolicy()
+{
+ Q_D(QQuickPopup);
+ setClosePolicy(DefaultClosePolicy);
+ d->hasClosePolicy = false;
+}
+
/*!
\qmlproperty enumeration QtQuick.Controls::Popup::transformOrigin
@@ -1892,12 +2116,8 @@ void QQuickPopup::classBegin()
void QQuickPopup::componentComplete()
{
Q_D(QQuickPopup);
- if (!parentItem()) {
- if (QQuickItem *item = qobject_cast<QQuickItem *>(parent()))
- setParentItem(item);
- else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
- setParentItem(window->contentItem());
- }
+ if (!parentItem())
+ resetParentItem();
if (d->visible && d->window)
d->transitionManager.transitionEnter();
@@ -2111,6 +2331,13 @@ void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &ol
emit availableHeightChanged();
}
+void QQuickPopup::paletteChange(const QPalette &newPalette, const QPalette &oldPalette)
+{
+ Q_UNUSED(newPalette);
+ Q_UNUSED(oldPalette);
+ emit paletteChanged();
+}
+
void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing)
{
Q_UNUSED(newSpacing);
@@ -2123,6 +2350,11 @@ QFont QQuickPopup::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont);
}
+QPalette QQuickPopup::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::SystemPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPopup::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h
index 199f7e4c..ada4b649 100644
--- a/src/quicktemplates2/qquickpopup_p.h
+++ b/src/quicktemplates2/qquickpopup_p.h
@@ -53,6 +53,7 @@
#include <QtGui/qevent.h>
#include <QtCore/qlocale.h>
#include <QtGui/qfont.h>
+#include <QtGui/qpalette.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmllist.h>
@@ -96,7 +97,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged FINAL)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL)
Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL)
- Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem NOTIFY parentChanged FINAL)
+ Q_PROPERTY(QQuickItem *parent READ parentItem WRITE setParentItem RESET resetParentItem NOTIFY parentChanged FINAL)
Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem NOTIFY contentItemChanged FINAL)
Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
@@ -109,12 +110,17 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopup : public QObject, public QQml
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged FINAL)
- Q_PROPERTY(ClosePolicy closePolicy READ closePolicy WRITE setClosePolicy NOTIFY closePolicyChanged FINAL)
- Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin)
+ Q_PROPERTY(ClosePolicy closePolicy READ closePolicy WRITE setClosePolicy RESET resetClosePolicy NOTIFY closePolicyChanged FINAL)
+ Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin FINAL)
Q_PROPERTY(QQuickTransition *enter READ enter WRITE setEnter NOTIFY enterChanged FINAL)
Q_PROPERTY(QQuickTransition *exit READ exit WRITE setExit NOTIFY exitChanged FINAL)
// 2.1 (Qt 5.8)
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing RESET resetSpacing NOTIFY spacingChanged FINAL REVISION 1)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool opened READ isOpened NOTIFY openedChanged FINAL REVISION 3)
+ Q_PROPERTY(bool mirrored READ isMirrored NOTIFY mirroredChanged FINAL REVISION 3)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL REVISION 3)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
Q_CLASSINFO("DefaultProperty", "contentData")
public:
@@ -209,6 +215,7 @@ public:
QQuickItem *parentItem() const;
void setParentItem(QQuickItem *parent);
+ void resetParentItem();
QQuickItem *background() const;
void setBackground(QQuickItem *background);
@@ -256,6 +263,7 @@ public:
ClosePolicy closePolicy() const;
void setClosePolicy(ClosePolicy policy);
+ void resetClosePolicy();
// keep in sync with Item.TransformOrigin
enum TransformOrigin {
@@ -284,6 +292,17 @@ public:
void setSpacing(qreal spacing);
void resetSpacing();
+ // 2.3 (Qt 5.10)
+ bool isOpened() const;
+ bool isMirrored() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
public Q_SLOTS:
void open();
void close();
@@ -334,6 +353,11 @@ Q_SIGNALS:
void windowChanged(QQuickWindow *window);
// 2.1 (Qt 5.8)
Q_REVISION(1) void spacingChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void openedChanged();
+ Q_REVISION(3) void mirroredChanged();
+ Q_REVISION(3) void enabledChanged();
+ Q_REVISION(3) void paletteChanged();
protected:
QQuickPopup(QQuickPopupPrivate &dd, QObject *parent);
@@ -368,9 +392,11 @@ protected:
virtual void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data);
virtual void marginsChange(const QMarginsF &newMargins, const QMarginsF &oldMargins);
virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding);
+ virtual void paletteChange(const QPalette &newPalette, const QPalette &oldPalette);
virtual void spacingChange(qreal newSpacing, qreal oldSpacing);
virtual QFont defaultFont() const;
+ virtual QPalette defaultPalette() const;
#if QT_CONFIG(accessibility)
virtual QAccessible::Role accessibleRole() const;
diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h
index ce64d49e..6890fdac 100644
--- a/src/quicktemplates2/qquickpopup_p_p.h
+++ b/src/quicktemplates2/qquickpopup_p_p.h
@@ -48,8 +48,8 @@
// We mean it.
//
-#include "qquickpopup_p.h"
-#include "qquickcontrol_p.h"
+#include <QtQuickTemplates2/private/qquickpopup_p.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p.h>
#include <QtCore/private/qobject_p.h>
#include <QtQuick/qquickitem.h>
@@ -115,6 +115,12 @@ public:
#endif
virtual void reposition();
+
+ void createOverlay();
+ void destroyOverlay();
+ void toggleOverlay();
+ virtual void showOverlay();
+ virtual void hideOverlay();
virtual void resizeOverlay();
virtual bool prepareEnterTransition();
@@ -157,6 +163,7 @@ public:
bool allowHorizontalResize;
bool hadActiveFocusBeforeExitTransition;
bool interactive;
+ bool hasClosePolicy;
int touchId;
qreal x;
qreal y;
diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp
index bd667835..af4d03a4 100644
--- a/src/quicktemplates2/qquickpopupitem.cpp
+++ b/src/quicktemplates2/qquickpopupitem.cpp
@@ -56,6 +56,7 @@ public:
void implicitHeightChanged() override;
void resolveFont() override;
+ void resolvePalette() override;
QQuickItem *getContentItem() override;
@@ -92,6 +93,14 @@ void QQuickPopupItemPrivate::resolveFont()
inheritFont(themeFont(QPlatformTheme::SystemFont));
}
+void QQuickPopupItemPrivate::resolvePalette()
+{
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
+ inheritPalette(window->palette());
+ else
+ inheritPalette(themePalette(QPlatformTheme::SystemPalette));
+}
+
QQuickItem *QQuickPopupItemPrivate::getContentItem()
{
Q_Q(QQuickPopupItem);
@@ -280,6 +289,12 @@ void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldL
d->popup->localeChange(newLocale, oldLocale);
}
+void QQuickPopupItem::mirrorChange()
+{
+ Q_D(QQuickPopupItem);
+ emit d->popup->mirroredChanged();
+}
+
void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
{
Q_D(QQuickPopupItem);
@@ -294,12 +309,25 @@ void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF
d->popup->paddingChange(newPadding, oldPadding);
}
+void QQuickPopupItem::paletteChange(const QPalette &newPalette, const QPalette &oldPalette)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::paletteChange(newPalette, oldPalette);
+ d->popup->paletteChange(newPalette, oldPalette);
+}
+
QFont QQuickPopupItem::defaultFont() const
{
Q_D(const QQuickPopupItem);
return d->popup->defaultFont();
}
+QPalette QQuickPopupItem::defaultPalette() const
+{
+ Q_D(const QQuickPopupItem);
+ return d->popup->defaultPalette();
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPopupItem::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h
index d5447383..0187b77a 100644
--- a/src/quicktemplates2/qquickpopupitem_p_p.h
+++ b/src/quicktemplates2/qquickpopupitem_p_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include "qquickcontrol_p.h"
+#include <QtQuickTemplates2/private/qquickcontrol_p.h>
QT_BEGIN_NAMESPACE
@@ -91,10 +91,13 @@ protected:
void fontChange(const QFont &newFont, const QFont &oldFont) override;
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
+ void mirrorChange() override;
void itemChange(ItemChange change, const ItemChangeData &data) override;
void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
+ void paletteChange(const QPalette &newPalette, const QPalette &oldPalette) override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickradiobutton.cpp b/src/quicktemplates2/qquickradiobutton.cpp
index c923fbbf..86be3ed6 100644
--- a/src/quicktemplates2/qquickradiobutton.cpp
+++ b/src/quicktemplates2/qquickradiobutton.cpp
@@ -102,6 +102,11 @@ QFont QQuickRadioButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::RadioButtonFont);
}
+QPalette QQuickRadioButton::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::RadioButtonPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickRadioButton::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickradiobutton_p.h b/src/quicktemplates2/qquickradiobutton_p.h
index 0fe4eb70..ea372687 100644
--- a/src/quicktemplates2/qquickradiobutton_p.h
+++ b/src/quicktemplates2/qquickradiobutton_p.h
@@ -61,6 +61,7 @@ public:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp
index 51b646ce..937de9c9 100644
--- a/src/quicktemplates2/qquickrangeslider.cpp
+++ b/src/quicktemplates2/qquickrangeslider.cpp
@@ -810,6 +810,8 @@ void QQuickRangeSlider::setSnapMode(SnapMode mode)
Possible values:
\value Qt.Horizontal Horizontal (default)
\value Qt.Vertical Vertical
+
+ \sa horizontal, vertical
*/
Qt::Orientation QQuickRangeSlider::orientation() const
{
@@ -911,6 +913,36 @@ void QQuickRangeSlider::setLive(bool live)
emit liveChanged();
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::RangeSlider::horizontal
+ \readonly
+
+ This property holds whether the slider is horizontal.
+
+ \sa orientation
+*/
+bool QQuickRangeSlider::isHorizontal() const
+{
+ Q_D(const QQuickRangeSlider);
+ return d->orientation == Qt::Horizontal;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::RangeSlider::vertical
+ \readonly
+
+ This property holds whether the slider is vertical.
+
+ \sa orientation
+*/
+bool QQuickRangeSlider::isVertical() const
+{
+ Q_D(const QQuickRangeSlider);
+ return d->orientation == Qt::Vertical;
+}
+
void QQuickRangeSlider::focusInEvent(QFocusEvent *event)
{
Q_D(QQuickRangeSlider);
diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h
index b8182768..a6326441 100644
--- a/src/quicktemplates2/qquickrangeslider_p.h
+++ b/src/quicktemplates2/qquickrangeslider_p.h
@@ -60,13 +60,16 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl
Q_OBJECT
Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged FINAL)
Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged FINAL)
- Q_PROPERTY(QQuickRangeSliderNode *first READ first CONSTANT)
- Q_PROPERTY(QQuickRangeSliderNode *second READ second CONSTANT)
+ Q_PROPERTY(QQuickRangeSliderNode *first READ first CONSTANT FINAL)
+ Q_PROPERTY(QQuickRangeSliderNode *second READ second CONSTANT FINAL)
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
// 2.2 (Qt 5.9)
Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
+ Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
public:
explicit QQuickRangeSlider(QQuickItem *parent = nullptr);
@@ -102,6 +105,10 @@ public:
bool live() const;
void setLive(bool live);
+ // 2.3 (Qt 5.10)
+ bool isHorizontal() const;
+ bool isVertical() const;
+
Q_SIGNALS:
void fromChanged();
void toChanged();
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp
index 87ff4b0a..e75fed5a 100644
--- a/src/quicktemplates2/qquickscrollbar.cpp
+++ b/src/quicktemplates2/qquickscrollbar.cpp
@@ -438,6 +438,8 @@ void QQuickScrollBar::setPressed(bool pressed)
This property is automatically set when the scroll bar is
\l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
+
+ \sa horizontal, vertical
*/
Qt::Orientation QQuickScrollBar::orientation() const
{
@@ -559,6 +561,36 @@ void QQuickScrollBar::setPolicy(Policy policy)
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::ScrollBar::horizontal
+ \readonly
+
+ This property holds whether the scroll bar is horizontal.
+
+ \sa orientation
+*/
+bool QQuickScrollBar::isHorizontal() const
+{
+ Q_D(const QQuickScrollBar);
+ return d->orientation == Qt::Horizontal;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::ScrollBar::vertical
+ \readonly
+
+ This property holds whether the scroll bar is vertical.
+
+ \sa orientation
+*/
+bool QQuickScrollBar::isVertical() const
+{
+ Q_D(const QQuickScrollBar);
+ return d->orientation == Qt::Vertical;
+}
+
+/*!
\qmlmethod void QtQuick.Controls::ScrollBar::increase()
Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h
index 892ef2e4..6dda6f2e 100644
--- a/src/quicktemplates2/qquickscrollbar_p.h
+++ b/src/quicktemplates2/qquickscrollbar_p.h
@@ -68,6 +68,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBar : public QQuickControl
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL REVISION 2)
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive RESET resetInteractive NOTIFY interactiveChanged FINAL REVISION 2)
Q_PROPERTY(Policy policy READ policy WRITE setPolicy NOTIFY policyChanged FINAL REVISION 2)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
+ Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
public:
explicit QQuickScrollBar(QQuickItem *parent = nullptr);
@@ -114,6 +117,10 @@ public:
Policy policy() const;
void setPolicy(Policy policy);
+ // 2.3 (Qt 5.10)
+ bool isHorizontal() const;
+ bool isVertical() const;
+
public Q_SLOTS:
void increase();
void decrease();
diff --git a/src/quicktemplates2/qquickscrollindicator.cpp b/src/quicktemplates2/qquickscrollindicator.cpp
index 780eff1e..ee1078e4 100644
--- a/src/quicktemplates2/qquickscrollindicator.cpp
+++ b/src/quicktemplates2/qquickscrollindicator.cpp
@@ -276,6 +276,8 @@ void QQuickScrollIndicator::setActive(bool active)
This property is automatically set when the scroll indicator is
\l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
+
+ \sa horizontal, vertical
*/
Qt::Orientation QQuickScrollIndicator::orientation() const
{
@@ -295,6 +297,36 @@ void QQuickScrollIndicator::setOrientation(Qt::Orientation orientation)
emit orientationChanged();
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::ScrollIndicator::horizontal
+ \readonly
+
+ This property holds whether the scroll indicator is horizontal.
+
+ \sa orientation
+*/
+bool QQuickScrollIndicator::isHorizontal() const
+{
+ Q_D(const QQuickScrollIndicator);
+ return d->orientation == Qt::Horizontal;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::ScrollIndicator::vertical
+ \readonly
+
+ This property holds whether the scroll indicator is vertical.
+
+ \sa orientation
+*/
+bool QQuickScrollIndicator::isVertical() const
+{
+ Q_D(const QQuickScrollIndicator);
+ return d->orientation == Qt::Vertical;
+}
+
class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
public:
diff --git a/src/quicktemplates2/qquickscrollindicator_p.h b/src/quicktemplates2/qquickscrollindicator_p.h
index 476a7859..d679cf74 100644
--- a/src/quicktemplates2/qquickscrollindicator_p.h
+++ b/src/quicktemplates2/qquickscrollindicator_p.h
@@ -63,6 +63,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollIndicator : public QQuickCont
Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
+ Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
public:
explicit QQuickScrollIndicator(QQuickItem *parent = nullptr);
@@ -78,6 +81,10 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ // 2.3 (Qt 5.10)
+ bool isHorizontal() const;
+ bool isVertical() const;
+
public Q_SLOTS:
void setSize(qreal size);
void setPosition(qreal position);
diff --git a/src/quicktemplates2/qquickshortcutcontext.cpp b/src/quicktemplates2/qquickshortcutcontext.cpp
index 92e4c04a..b491cab2 100644
--- a/src/quicktemplates2/qquickshortcutcontext.cpp
+++ b/src/quicktemplates2/qquickshortcutcontext.cpp
@@ -38,6 +38,8 @@
#include "qquickoverlay_p_p.h"
#include "qquicktooltip_p.h"
#include "qquickpopup_p.h"
+#include "qquickmenu_p.h"
+#include "qquickmenubaritem_p.h"
#include <QtGui/qguiapplication.h>
#include <QtQuick/qquickrendercontrol.h>
@@ -54,8 +56,13 @@ static bool isBlockedByPopup(QQuickItem *item)
for (QQuickPopup *popup : popups) {
if (qobject_cast<QQuickToolTip *>(popup))
continue; // ignore tooltips (QTBUG-60492)
- if (popup->isModal() || popup->closePolicy() & QQuickPopup::CloseOnEscape)
+ if (popup->isModal() || popup->closePolicy() & QQuickPopup::CloseOnEscape) {
+ if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(popup)) {
+ if (qobject_cast<QQuickMenuBarItem *>(menu->parentItem()))
+ continue;
+ }
return item != popup->popupItem() && !popup->popupItem()->isAncestorOf(item);
+ }
}
return false;
diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp
index 73fa2725..21aeda39 100644
--- a/src/quicktemplates2/qquickslider.cpp
+++ b/src/quicktemplates2/qquickslider.cpp
@@ -469,6 +469,36 @@ void QQuickSlider::setPressed(bool pressed)
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Slider::horizontal
+ \readonly
+
+ This property holds whether the slider is horizontal.
+
+ \sa orientation
+*/
+bool QQuickSlider::isHorizontal() const
+{
+ Q_D(const QQuickSlider);
+ return d->orientation == Qt::Horizontal;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::Slider::vertical
+ \readonly
+
+ This property holds whether the slider is vertical.
+
+ \sa orientation
+*/
+bool QQuickSlider::isVertical() const
+{
+ Q_D(const QQuickSlider);
+ return d->orientation == Qt::Vertical;
+}
+
+/*!
\qmlproperty enumeration QtQuick.Controls::Slider::orientation
This property holds the orientation.
@@ -476,6 +506,8 @@ void QQuickSlider::setPressed(bool pressed)
Possible values:
\value Qt.Horizontal Horizontal (default)
\value Qt.Vertical Vertical
+
+ \sa horizontal, vertical
*/
Qt::Orientation QQuickSlider::orientation() const
{
diff --git a/src/quicktemplates2/qquickslider_p.h b/src/quicktemplates2/qquickslider_p.h
index 377e853a..95545462 100644
--- a/src/quicktemplates2/qquickslider_p.h
+++ b/src/quicktemplates2/qquickslider_p.h
@@ -68,6 +68,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSlider : public QQuickControl
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
+ Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background,handle")
public:
@@ -114,6 +117,10 @@ public:
bool live() const;
void setLive(bool live);
+ // 2.3 (Qt 5.10)
+ bool isHorizontal() const;
+ bool isVertical() const;
+
public Q_SLOTS:
void increase();
void decrease();
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index 80bef2db..27dd0d5e 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -109,6 +109,7 @@ class QQuickSpinBoxPrivate : public QQuickControlPrivate
public:
QQuickSpinBoxPrivate()
: editable(false),
+ wrap(false),
from(0),
to(99),
value(0),
@@ -122,9 +123,10 @@ public:
{
}
- int boundValue(int value) const;
+ int boundValue(int value, bool wrap) const;
void updateValue();
- bool setValue(int value, bool modified);
+ bool setValue(int value, bool wrap, bool modified);
+ bool stepBy(int steps, bool modified);
void increase(bool modified);
void decrease(bool modified);
@@ -146,6 +148,7 @@ public:
void handleUngrab() override;
bool editable;
+ bool wrap;
int from;
int to;
int value;
@@ -184,9 +187,20 @@ public:
QQuickDeferredPointer<QQuickItem> indicator;
};
-int QQuickSpinBoxPrivate::boundValue(int value) const
+int QQuickSpinBoxPrivate::boundValue(int value, bool wrap) const
{
- return from > to ? qBound(to, value, from) : qBound(from, value, to);
+ bool inverted = from > to;
+ if (!wrap)
+ return inverted ? qBound(to, value, from) : qBound(from, value, to);
+
+ int f = inverted ? to : from;
+ int t = inverted ? from : to;
+ if (value < f)
+ value = t;
+ else if (value > t)
+ value = f;
+
+ return value;
}
void QQuickSpinBoxPrivate::updateValue()
@@ -200,17 +214,17 @@ void QQuickSpinBoxPrivate::updateValue()
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
QJSValue loc(v4, QQmlLocale::wrap(v4, locale));
QJSValue val = q->valueFromText().call(QJSValueList() << text.toString() << loc);
- setValue(val.toInt(), true);
+ setValue(val.toInt(), /* allowWrap = */ false, /* modified = */ true);
}
}
}
}
-bool QQuickSpinBoxPrivate::setValue(int newValue, bool modified)
+bool QQuickSpinBoxPrivate::setValue(int newValue, bool allowWrap, bool modified)
{
Q_Q(QQuickSpinBox);
if (q->isComponentComplete())
- newValue = boundValue(newValue);
+ newValue = boundValue(newValue, allowWrap);
if (value == newValue)
return false;
@@ -226,14 +240,19 @@ bool QQuickSpinBoxPrivate::setValue(int newValue, bool modified)
return true;
}
+bool QQuickSpinBoxPrivate::stepBy(int steps, bool modified)
+{
+ return setValue(value + steps, wrap, modified);
+}
+
void QQuickSpinBoxPrivate::increase(bool modified)
{
- setValue(value + effectiveStepSize(), modified);
+ setValue(value + effectiveStepSize(), wrap, modified);
}
void QQuickSpinBoxPrivate::decrease(bool modified)
{
- setValue(value - effectiveStepSize(), modified);
+ setValue(value - effectiveStepSize(), wrap, modified);
}
int QQuickSpinBoxPrivate::effectiveStepSize() const
@@ -253,7 +272,7 @@ void QQuickSpinBoxPrivate::updateUpEnabled()
if (!upIndicator)
return;
- upIndicator->setEnabled(from < to ? value < to : value > to);
+ upIndicator->setEnabled(wrap || (from < to ? value < to : value > to));
}
bool QQuickSpinBoxPrivate::downEnabled() const
@@ -268,7 +287,7 @@ void QQuickSpinBoxPrivate::updateDownEnabled()
if (!downIndicator)
return;
- downIndicator->setEnabled(from < to ? value > from : value < from);
+ downIndicator->setEnabled(wrap || (from < to ? value > from : value < from));
}
void QQuickSpinBoxPrivate::updateHover(const QPointF &pos)
@@ -409,7 +428,7 @@ void QQuickSpinBox::setFrom(int from)
d->from = from;
emit fromChanged();
if (isComponentComplete()) {
- if (!d->setValue(d->value, false)) {
+ if (!d->setValue(d->value, /* allowWrap = */ false, /* modified = */ false)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
@@ -438,7 +457,7 @@ void QQuickSpinBox::setTo(int to)
d->to = to;
emit toChanged();
if (isComponentComplete()) {
- if (!d->setValue(d->value, false)) {
+ if (!d->setValue(d->value, /* allowWrap = */false, /* modified = */ false)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
@@ -459,7 +478,7 @@ int QQuickSpinBox::value() const
void QQuickSpinBox::setValue(int value)
{
Q_D(QQuickSpinBox);
- d->setValue(value, false);
+ d->setValue(value, /* allowWrap = */ false, /* modified = */ false);
}
/*!
@@ -731,6 +750,34 @@ bool QQuickSpinBox::isInputMethodComposing() const
}
/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::SpinBox::wrap
+
+ This property holds whether the spinbox wraps. The default value is \c false.
+
+ If wrap is \c true, stepping past \l to changes the value to \l from and vice versa.
+*/
+bool QQuickSpinBox::wrap() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->wrap;
+}
+
+void QQuickSpinBox::setWrap(bool wrap)
+{
+ Q_D(QQuickSpinBox);
+ if (d->wrap == wrap)
+ return;
+
+ d->wrap = wrap;
+ if (d->value == d->from || d->value == d->to) {
+ d->updateUpEnabled();
+ d->updateDownEnabled();
+ }
+ emit wrapChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::SpinBox::increase()
Increases the value by \l stepSize, or \c 1 if stepSize is not defined.
@@ -852,8 +899,8 @@ void QQuickSpinBox::wheelEvent(QWheelEvent *event)
if (d->wheelEnabled) {
const QPointF angle = event->angleDelta();
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : angle.y()) / QWheelEvent::DefaultDeltasPerStep;
- if (!d->setValue(d->value + qRound(d->effectiveStepSize() * delta), true))
- event->ignore();
+ if (!d->stepBy(qRound(d->effectiveStepSize() * delta), true))
+ event->ignore();
}
}
#endif
@@ -877,7 +924,7 @@ void QQuickSpinBox::componentComplete()
QQuickSpinButtonPrivate::get(d->down)->executeIndicator(true);
QQuickControl::componentComplete();
- if (!d->setValue(d->value, false)) {
+ if (!d->setValue(d->value, /* allowWrap = */ false, /* modified = */ false)) {
d->updateUpEnabled();
d->updateDownEnabled();
}
@@ -916,6 +963,11 @@ QFont QQuickSpinBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
}
+QPalette QQuickSpinBox::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickSpinBox::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h
index 1ba21386..524930a2 100644
--- a/src/quicktemplates2/qquickspinbox_p.h
+++ b/src/quicktemplates2/qquickspinbox_p.h
@@ -74,6 +74,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl
// 2.2 (Qt 5.9)
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL REVISION 3)
public:
explicit QQuickSpinBox(QQuickItem *parent = nullptr);
@@ -111,6 +113,10 @@ public:
bool isInputMethodComposing() const;
+ // 2.3 (Qt 5.10)
+ bool wrap() const;
+ void setWrap(bool wrap);
+
public Q_SLOTS:
void increase();
void decrease();
@@ -128,6 +134,8 @@ Q_SIGNALS:
Q_REVISION(2) void valueModified();
Q_REVISION(2) void inputMethodHintsChanged();
Q_REVISION(2) void inputMethodComposingChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void wrapChanged();
protected:
void focusInEvent(QFocusEvent *event) override;
@@ -147,6 +155,7 @@ protected:
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp
index 20e3c817..2f13b1a1 100644
--- a/src/quicktemplates2/qquickstackview.cpp
+++ b/src/quicktemplates2/qquickstackview.cpp
@@ -516,8 +516,9 @@ void QQuickStackView::push(QQmlV4Function *args)
if (!d->elements.isEmpty())
exit = d->elements.top();
+ int oldDepth = d->elements.count();
if (d->pushElements(elements)) {
- emit depthChanged();
+ d->depthChange(d->elements.count(), oldDepth);
QQuickStackElement *enter = d->elements.top();
d->startTransition(QQuickStackTransition::pushEnter(operation, enter, this),
QQuickStackTransition::pushExit(operation, exit, this),
@@ -574,6 +575,7 @@ void QQuickStackView::pop(QQmlV4Function *args)
return;
}
+ int oldDepth = d->elements.count();
QQuickStackElement *exit = d->elements.pop();
QQuickStackElement *enter = d->elements.top();
@@ -612,7 +614,7 @@ void QQuickStackView::pop(QQmlV4Function *args)
d->removing.insert(exit);
previousItem = exit->item;
}
- emit depthChanged();
+ d->depthChange(d->elements.count(), oldDepth);
d->startTransition(QQuickStackTransition::popExit(operation, exit, this),
QQuickStackTransition::popEnter(operation, enter, this),
operation == Immediate);
@@ -752,14 +754,13 @@ void QQuickStackView::replace(QQmlV4Function *args)
return;
}
- int depth = d->elements.count();
+ int oldDepth = d->elements.count();
QQuickStackElement* exit = nullptr;
if (!d->elements.isEmpty())
exit = d->elements.pop();
if (exit != target ? d->replaceElements(target, elements) : d->pushElements(elements)) {
- if (depth != d->elements.count())
- emit depthChanged();
+ d->depthChange(d->elements.count(), oldDepth);
if (exit) {
exit->removal = true;
d->removing.insert(exit);
@@ -780,20 +781,51 @@ void QQuickStackView::replace(QQmlV4Function *args)
}
/*!
- \qmlmethod void QtQuick.Controls::StackView::clear()
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::StackView::empty
+ \readonly
+
+ This property holds whether the stack is empty.
+
+ \sa depth
+*/
+bool QQuickStackView::isEmpty() const
+{
+ Q_D(const QQuickStackView);
+ return d->elements.isEmpty();
+}
- Removes all items from the stack. No animations are applied.
+/*!
+ \qmlmethod void QtQuick.Controls::StackView::clear(transition)
+
+ Removes all items from the stack.
+
+ Since QtQuick.Controls 2.3, a \a transition can be optionally specified. Supported transitions:
+
+ \value StackView.Immediate Clear the stack immediately without any transition (default).
+ \value StackView.PushTransition Clear the stack with a push transition.
+ \value StackView.ReplaceTransition Clear the stack with a replace transition.
+ \value StackView.PopTransition Clear the stack with a pop transition.
*/
-void QQuickStackView::clear()
+void QQuickStackView::clear(Operation operation)
{
Q_D(QQuickStackView);
if (d->elements.isEmpty())
return;
+ if (operation != Immediate) {
+ QQuickStackElement *exit = d->elements.pop();
+ exit->removal = true;
+ d->removing.insert(exit);
+ d->startTransition(QQuickStackTransition::popExit(operation, exit, this),
+ QQuickStackTransition::popEnter(operation, nullptr, this), false);
+ }
+
+ int oldDepth = d->elements.count();
d->setCurrentItem(nullptr);
qDeleteAll(d->elements);
d->elements.clear();
- emit depthChanged();
+ d->depthChange(0, oldDepth);
}
/*!
@@ -990,6 +1022,7 @@ void QQuickStackView::componentComplete()
QScopedValueRollback<QString> rollback(d->operation, QStringLiteral("initialItem"));
QQuickStackElement *element = nullptr;
QString error;
+ int oldDepth = d->elements.count();
if (QObject *o = d->initialItem.value<QObject *>())
element = QQuickStackElement::fromObject(o, this, &error);
else if (d->initialItem.canConvert<QString>())
@@ -998,7 +1031,7 @@ void QQuickStackView::componentComplete()
d->warn(error);
delete element;
} else if (d->pushElement(element)) {
- emit depthChanged();
+ d->depthChange(d->elements.count(), oldDepth);
d->setCurrentItem(element);
element->setStatus(QQuickStackView::Active);
}
diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp
index 0b0f5ef5..0167ad97 100644
--- a/src/quicktemplates2/qquickstackview_p.cpp
+++ b/src/quicktemplates2/qquickstackview_p.cpp
@@ -301,4 +301,15 @@ void QQuickStackViewPrivate::setBusy(bool b)
emit q->busyChanged();
}
+void QQuickStackViewPrivate::depthChange(int newDepth, int oldDepth)
+{
+ Q_Q(QQuickStackView);
+ if (newDepth == oldDepth)
+ return;
+
+ emit q->depthChanged();
+ if (newDepth == 0 || oldDepth == 0)
+ emit q->emptyChanged();
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackview_p.h b/src/quicktemplates2/qquickstackview_p.h
index ff115416..2cddb800 100644
--- a/src/quicktemplates2/qquickstackview_p.h
+++ b/src/quicktemplates2/qquickstackview_p.h
@@ -72,6 +72,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackView : public QQuickControl
Q_PROPERTY(QQuickTransition *pushExit READ pushExit WRITE setPushExit NOTIFY pushExitChanged FINAL)
Q_PROPERTY(QQuickTransition *replaceEnter READ replaceEnter WRITE setReplaceEnter NOTIFY replaceEnterChanged FINAL)
Q_PROPERTY(QQuickTransition *replaceExit READ replaceExit WRITE setReplaceExit NOTIFY replaceExitChanged FINAL)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged FINAL REVISION 3)
public:
explicit QQuickStackView(QQuickItem *parent = nullptr);
@@ -134,8 +136,11 @@ public:
Q_INVOKABLE void pop(QQmlV4Function *args);
Q_INVOKABLE void replace(QQmlV4Function *args);
+ // 2.3 (Qt 5.10)
+ bool isEmpty() const;
+
public Q_SLOTS:
- void clear();
+ void clear(Operation operation = Immediate);
Q_SIGNALS:
void busyChanged();
@@ -147,6 +152,8 @@ Q_SIGNALS:
void pushExitChanged();
void replaceEnterChanged();
void replaceExitChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void emptyChanged();
protected:
void componentComplete() override;
diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h
index 81ca9164..d86f35cd 100644
--- a/src/quicktemplates2/qquickstackview_p_p.h
+++ b/src/quicktemplates2/qquickstackview_p_p.h
@@ -92,6 +92,7 @@ public:
void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) override;
void setBusy(bool busy);
+ void depthChange(int newDepth, int oldDepth);
bool busy;
QString operation;
diff --git a/src/quicktemplates2/qquickswipedelegate_p.h b/src/quicktemplates2/qquickswipedelegate_p.h
index 5ba0604d..a9900eb8 100644
--- a/src/quicktemplates2/qquickswipedelegate_p.h
+++ b/src/quicktemplates2/qquickswipedelegate_p.h
@@ -60,7 +60,7 @@ class QQuickSwipeDelegateAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeDelegate : public QQuickItemDelegate
{
Q_OBJECT
- Q_PROPERTY(QQuickSwipe *swipe READ swipe CONSTANT)
+ Q_PROPERTY(QQuickSwipe *swipe READ swipe CONSTANT FINAL)
public:
explicit QQuickSwipeDelegate(QQuickItem *parent = nullptr);
diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp
index 72754b0f..5f84f93e 100644
--- a/src/quicktemplates2/qquickswipeview.cpp
+++ b/src/quicktemplates2/qquickswipeview.cpp
@@ -121,6 +121,32 @@ public:
Qt::Orientation orientation;
};
+class QQuickSwipeViewAttachedPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickSwipeViewAttached)
+
+public:
+ QQuickSwipeViewAttachedPrivate()
+ : swipeView(nullptr),
+ index(-1),
+ currentIndex(-1)
+ {
+ }
+
+ static QQuickSwipeViewAttachedPrivate *get(QQuickSwipeViewAttached *attached)
+ {
+ return attached->d_func();
+ }
+
+ void update(QQuickSwipeView *newView, int newIndex);
+ void updateCurrentIndex();
+ void setCurrentIndex(int i);
+
+ QQuickSwipeView *swipeView;
+ int index;
+ int currentIndex;
+};
+
void QQuickSwipeViewPrivate::resizeItems()
{
Q_Q(QQuickSwipeView);
@@ -190,6 +216,8 @@ void QQuickSwipeView::setInteractive(bool interactive)
Possible values:
\value Qt.Horizontal Horizontal (default)
\value Qt.Vertical Vertical
+
+ \sa horizontal, vertical
*/
Qt::Orientation QQuickSwipeView::orientation() const
{
@@ -209,6 +237,36 @@ void QQuickSwipeView::setOrientation(Qt::Orientation orientation)
emit orientationChanged();
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::SwipeView::horizontal
+ \readonly
+
+ This property holds whether the swipe view is horizontal.
+
+ \sa orientation
+*/
+bool QQuickSwipeView::isHorizontal() const
+{
+ Q_D(const QQuickSwipeView);
+ return d->orientation == Qt::Horizontal;
+}
+
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty bool QtQuick.Controls::SwipeView::vertical
+ \readonly
+
+ This property holds whether the swipe view is vertical.
+
+ \sa orientation
+*/
+bool QQuickSwipeView::isVertical() const
+{
+ Q_D(const QQuickSwipeView);
+ return d->orientation == Qt::Vertical;
+}
+
QQuickSwipeViewAttached *QQuickSwipeView::qmlAttachedProperties(QObject *object)
{
return new QQuickSwipeViewAttached(object);
@@ -221,12 +279,29 @@ void QQuickSwipeView::geometryChanged(const QRectF &newGeometry, const QRectF &o
d->resizeItems();
}
-void QQuickSwipeView::itemAdded(int, QQuickItem *item)
+void QQuickSwipeView::itemAdded(int index, QQuickItem *item)
{
Q_D(QQuickSwipeView);
QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-51078, QTBUG-51669
if (isComponentComplete())
item->setSize(QSizeF(d->contentItem->width(), d->contentItem->height()));
+ QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item));
+ if (attached)
+ QQuickSwipeViewAttachedPrivate::get(attached)->update(this, index);
+}
+
+void QQuickSwipeView::itemMoved(int index, QQuickItem *item)
+{
+ QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item));
+ if (attached)
+ QQuickSwipeViewAttachedPrivate::get(attached)->update(this, index);
+}
+
+void QQuickSwipeView::itemRemoved(int, QQuickItem *item)
+{
+ QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item));
+ if (attached)
+ QQuickSwipeViewAttachedPrivate::get(attached)->update(nullptr, -1);
}
#if QT_CONFIG(accessibility)
@@ -283,85 +358,11 @@ QAccessible::Role QQuickSwipeView::accessibleRole() const
It is attached to each child item of the SwipeView.
*/
-class QQuickSwipeViewAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
-{
- Q_DECLARE_PUBLIC(QQuickSwipeViewAttached)
-public:
- QQuickSwipeViewAttachedPrivate()
- : item(nullptr),
- swipeView(nullptr),
- index(-1),
- currentIndex(-1)
- {
- }
-
- ~QQuickSwipeViewAttachedPrivate() {
- }
-
- void updateView(QQuickItem *parent);
-
- void itemChildAdded(QQuickItem *, QQuickItem *) override;
- void itemChildRemoved(QQuickItem *, QQuickItem *) override;
- void itemParentChanged(QQuickItem *, QQuickItem *) override;
- void itemDestroyed(QQuickItem *) override;
-
- void updateIndex();
- void updateCurrentIndex();
-
- void setView(QQuickSwipeView *view);
- void setIndex(int i);
- void setCurrentIndex(int i);
-
- QQuickItem *item;
- QQuickSwipeView *swipeView;
- int index;
- int currentIndex;
-};
-
-void QQuickSwipeViewAttachedPrivate::updateIndex()
-{
- setIndex(swipeView ? QQuickSwipeViewPrivate::get(swipeView)->contentModel->indexOf(item, nullptr) : -1);
-}
-
void QQuickSwipeViewAttachedPrivate::updateCurrentIndex()
{
setCurrentIndex(swipeView ? swipeView->currentIndex() : -1);
}
-void QQuickSwipeViewAttachedPrivate::setView(QQuickSwipeView *view)
-{
- if (view == swipeView)
- return;
-
- if (swipeView) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView);
- p->removeItemChangeListener(this, QQuickItemPrivate::Children);
-
- disconnect(swipeView, &QQuickSwipeView::currentIndexChanged,
- this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex);
- disconnect(swipeView, &QQuickSwipeView::contentChildrenChanged,
- this, &QQuickSwipeViewAttachedPrivate::updateIndex);
- }
-
- swipeView = view;
-
- if (swipeView) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(swipeView);
- p->addItemChangeListener(this, QQuickItemPrivate::Children);
-
- connect(swipeView, &QQuickSwipeView::currentIndexChanged,
- this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex);
- connect(swipeView, &QQuickSwipeView::contentChildrenChanged,
- this, &QQuickSwipeViewAttachedPrivate::updateIndex);
- }
-
- Q_Q(QQuickSwipeViewAttached);
- emit q->viewChanged();
-
- updateIndex();
- updateCurrentIndex();
-}
-
void QQuickSwipeViewAttachedPrivate::setCurrentIndex(int i)
{
if (i == currentIndex)
@@ -381,79 +382,37 @@ void QQuickSwipeViewAttachedPrivate::setCurrentIndex(int i)
emit q->isPreviousItemChanged();
}
-void QQuickSwipeViewAttachedPrivate::setIndex(int i)
+void QQuickSwipeViewAttachedPrivate::update(QQuickSwipeView *newView, int newIndex)
{
- if (i == index)
- return;
-
- index = i;
Q_Q(QQuickSwipeViewAttached);
- emit q->indexChanged();
-}
+ int oldIndex = index;
+ QQuickSwipeView *oldView = swipeView;
-void QQuickSwipeViewAttachedPrivate::updateView(QQuickItem *parent)
-{
- // parent can be, e.g.:
- // - The contentItem of a ListView (typically the case)
- // - A non-visual or weird type like TestCase, when child items are created from components
- // wherein the attached properties are used
- // - null, when the item was removed with removeItem()
- QQuickSwipeView *view = nullptr;
- if (parent) {
- view = qobject_cast<QQuickSwipeView*>(parent);
- if (!view) {
- if (parent->parentItem() && parent->parentItem()->property("contentItem").isValid()) {
- // The parent is the contentItem of some kind of view.
- view = qobject_cast<QQuickSwipeView*>(parent->parentItem()->parentItem());
- }
+ index = newIndex;
+ swipeView = newView;
+
+ if (oldView != newView) {
+ if (oldView) {
+ disconnect(oldView, &QQuickSwipeView::currentIndexChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex);
}
+ if (newView) {
+ connect(newView, &QQuickSwipeView::currentIndexChanged,
+ this, &QQuickSwipeViewAttachedPrivate::updateCurrentIndex);
+ }
+ emit q->viewChanged();
}
+ if (oldIndex != newIndex)
+ emit q->indexChanged();
- setView(view);
-}
-
-void QQuickSwipeViewAttachedPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
-{
- updateIndex();
-}
-
-void QQuickSwipeViewAttachedPrivate::itemChildRemoved(QQuickItem *, QQuickItem *)
-{
- updateIndex();
-}
-
-void QQuickSwipeViewAttachedPrivate::itemParentChanged(QQuickItem *, QQuickItem *parent)
-{
- updateView(parent);
-}
-
-void QQuickSwipeViewAttachedPrivate::itemDestroyed(QQuickItem *item)
-{
- QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed);
+ updateCurrentIndex();
}
QQuickSwipeViewAttached::QQuickSwipeViewAttached(QObject *parent)
: QObject(*(new QQuickSwipeViewAttachedPrivate), parent)
{
- Q_D(QQuickSwipeViewAttached);
- d->item = qobject_cast<QQuickItem *>(parent);
- if (d->item) {
- if (d->item->parentItem())
- d->updateView(d->item->parentItem());
-
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->addItemChangeListener(d, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed);
- } else if (parent) {
+ if (!qobject_cast<QQuickItem *>(parent))
qmlWarning(parent) << "SwipeView: attached properties must be accessed from within a child item";
- }
-}
-
-QQuickSwipeViewAttached::~QQuickSwipeViewAttached()
-{
- Q_D(QQuickSwipeViewAttached);
- QQuickItem *item = qobject_cast<QQuickItem *>(parent());
- if (item)
- QQuickItemPrivate::get(item)->removeItemChangeListener(d, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed);
}
int QQuickSwipeViewAttached::index() const
diff --git a/src/quicktemplates2/qquickswipeview_p.h b/src/quicktemplates2/qquickswipeview_p.h
index 98594bd3..03f6cefa 100644
--- a/src/quicktemplates2/qquickswipeview_p.h
+++ b/src/quicktemplates2/qquickswipeview_p.h
@@ -62,6 +62,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeView : public QQuickContainer
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 1)
// 2.2 (Qt 5.9)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL REVISION 2)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(bool horizontal READ isHorizontal NOTIFY orientationChanged FINAL REVISION 3)
+ Q_PROPERTY(bool vertical READ isVertical NOTIFY orientationChanged FINAL REVISION 3)
public:
explicit QQuickSwipeView(QQuickItem *parent = nullptr);
@@ -76,6 +79,10 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ // 2.3 (Qt 5.10)
+ bool isHorizontal() const;
+ bool isVertical() const;
+
Q_SIGNALS:
// 2.1 (Qt 5.8)
Q_REVISION(1) void interactiveChanged();
@@ -85,6 +92,8 @@ Q_SIGNALS:
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void itemAdded(int index, QQuickItem *item) override;
+ void itemMoved(int index, QQuickItem *item) override;
+ void itemRemoved(int index, QQuickItem *item) override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
@@ -109,7 +118,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeViewAttached : public QObject
public:
explicit QQuickSwipeViewAttached(QObject *parent = nullptr);
- ~QQuickSwipeViewAttached();
int index() const;
bool isCurrentItem() const;
diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp
index f9bbff25..da1f0408 100644
--- a/src/quicktemplates2/qquickswitch.cpp
+++ b/src/quicktemplates2/qquickswitch.cpp
@@ -231,4 +231,10 @@ void QQuickSwitch::buttonChange(ButtonChange change)
QQuickAbstractButton::buttonChange(change);
}
+QPalette QQuickSwitch::defaultPalette() const
+{
+ // ### TODO: add QPlatformTheme::SwitchPalette
+ return QQuickControlPrivate::themePalette(QPlatformTheme::CheckBoxPalette);
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h
index 12e20bde..0faaf114 100644
--- a/src/quicktemplates2/qquickswitch_p.h
+++ b/src/quicktemplates2/qquickswitch_p.h
@@ -83,6 +83,8 @@ protected:
void nextCheckState() override;
void buttonChange(ButtonChange change) override;
+ QPalette defaultPalette() const override;
+
private:
Q_DISABLE_COPY(QQuickSwitch)
Q_DECLARE_PRIVATE(QQuickSwitch)
diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp
index 65a4a863..814d14ea 100644
--- a/src/quicktemplates2/qquicktabbar.cpp
+++ b/src/quicktemplates2/qquicktabbar.cpp
@@ -116,6 +116,28 @@ public:
QQuickTabBar::Position position;
};
+class QQuickTabBarAttachedPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickTabBarAttached)
+
+public:
+ QQuickTabBarAttachedPrivate()
+ : index(-1),
+ tabBar(nullptr)
+ {
+ }
+
+ static QQuickTabBarAttachedPrivate *get(QQuickTabBarAttached *attached)
+ {
+ return attached->d_func();
+ }
+
+ void update(QQuickTabBar *tabBar, int index);
+
+ int index;
+ QQuickTabBar *tabBar;
+};
+
QQuickTabBarPrivate::QQuickTabBarPrivate()
: updatingLayout(false),
hasContentWidth(false),
@@ -152,38 +174,47 @@ void QQuickTabBarPrivate::updateLayout()
qreal maxHeight = 0;
qreal totalWidth = 0;
qreal reservedWidth = 0;
+ int resizableCount = 0;
- QVector<QQuickItem *> resizableItems;
- resizableItems.reserve(count);
+ QVector<QQuickItem *> allItems;
+ allItems.reserve(count);
for (int i = 0; i < count; ++i) {
QQuickItem *item = q->itemAt(i);
if (item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
if (!p->widthValid) {
- resizableItems += item;
+ ++resizableCount;
totalWidth += item->implicitWidth();
} else {
reservedWidth += item->width();
totalWidth += item->width();
}
maxHeight = qMax(maxHeight, item->implicitHeight());
+ allItems += item;
}
}
const qreal totalSpacing = qMax(0, count - 1) * spacing;
totalWidth += totalSpacing;
- if (!resizableItems.isEmpty()) {
- const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count();
+ const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / qMax(1, resizableCount);
- updatingLayout = true;
- for (QQuickItem *item : qAsConst(resizableItems)) {
+ updatingLayout = true;
+ for (QQuickItem *item : qAsConst(allItems)) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!p->widthValid) {
item->setWidth(itemWidth);
- QQuickItemPrivate::get(item)->widthValid = false;
+ p->widthValid = false;
+ }
+ if (!p->heightValid) {
+ item->setHeight(hasContentHeight ? contentHeight : maxHeight);
+ p->heightValid = false;
+ } else {
+ item->setY((maxHeight - item->height()) / 2);
}
- updatingLayout = false;
}
+ updatingLayout = false;
bool contentWidthChange = false;
if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) {
@@ -342,6 +373,11 @@ void QQuickTabBar::resetContentHeight()
d->updateLayout();
}
+QQuickTabBarAttached *QQuickTabBar::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickTabBarAttached(object);
+}
+
void QQuickTabBar::updatePolish()
{
Q_D(QQuickTabBar);
@@ -376,20 +412,38 @@ void QQuickTabBar::itemAdded(int index, QQuickItem *item)
QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-55129
if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item))
QObjectPrivate::connect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex);
+ QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item));
+ if (attached)
+ QQuickTabBarAttachedPrivate::get(attached)->update(this, index);
if (isComponentComplete())
polish();
}
+void QQuickTabBar::itemMoved(int index, QQuickItem *item)
+{
+ QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item));
+ if (attached)
+ QQuickTabBarAttachedPrivate::get(attached)->update(this, index);
+}
+
void QQuickTabBar::itemRemoved(int index, QQuickItem *item)
{
Q_D(QQuickTabBar);
Q_UNUSED(index);
if (QQuickTabButton *button = qobject_cast<QQuickTabButton *>(item))
QObjectPrivate::disconnect(button, &QQuickTabButton::checkedChanged, d, &QQuickTabBarPrivate::updateCurrentIndex);
+ QQuickTabBarAttached *attached = qobject_cast<QQuickTabBarAttached *>(qmlAttachedPropertiesObject<QQuickTabBar>(item));
+ if (attached)
+ QQuickTabBarAttachedPrivate::get(attached)->update(nullptr, -1);
if (isComponentComplete())
polish();
}
+QPalette QQuickTabBar::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickTabBar::accessibleRole() const
{
@@ -397,4 +451,87 @@ QAccessible::Role QQuickTabBar::accessibleRole() const
}
#endif
+/*!
+ \qmlattachedproperty int QtQuick.Controls::TabBar::index
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \readonly
+
+ This attached property holds the index of each tab button in the TabBar.
+
+ It is attached to each tab button of the TabBar.
+*/
+
+/*!
+ \qmlattachedproperty TabBar QtQuick.Controls::TabBar::tabBar
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \readonly
+
+ This attached property holds the tab bar that manages this tab button.
+
+ It is attached to each tab button of the TabBar.
+*/
+
+/*!
+ \qmlattachedproperty enumeration QtQuick.Controls::TabBar::position
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \readonly
+
+ This attached property holds the position of the tab bar.
+
+ It is attached to each tab button of the TabBar.
+
+ Possible values:
+ \value TabBar.Header The tab bar is at the top, as a window or page header.
+ \value TabBar.Footer The tab bar is at the bottom, as a window or page footer.
+*/
+
+void QQuickTabBarAttachedPrivate::update(QQuickTabBar *newTabBar, int newIndex)
+{
+ Q_Q(QQuickTabBarAttached);
+ const int oldIndex = index;
+ const QQuickTabBar *oldTabBar = tabBar;
+ const QQuickTabBar::Position oldPos = q->position();
+
+ index = newIndex;
+ tabBar = newTabBar;
+
+ if (oldTabBar != newTabBar) {
+ if (oldTabBar)
+ QObject::disconnect(oldTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged);
+ if (newTabBar)
+ QObject::connect(newTabBar, &QQuickTabBar::positionChanged, q, &QQuickTabBarAttached::positionChanged);
+ emit q->tabBarChanged();
+ }
+
+ if (oldIndex != newIndex)
+ emit q->indexChanged();
+ if (oldPos != q->position())
+ emit q->positionChanged();
+}
+
+QQuickTabBarAttached::QQuickTabBarAttached(QObject *parent)
+ : QObject(*(new QQuickTabBarAttachedPrivate), parent)
+{
+}
+
+int QQuickTabBarAttached::index() const
+{
+ Q_D(const QQuickTabBarAttached);
+ return d->index;
+}
+
+QQuickTabBar *QQuickTabBarAttached::tabBar() const
+{
+ Q_D(const QQuickTabBarAttached);
+ return d->tabBar;
+}
+
+QQuickTabBar::Position QQuickTabBarAttached::position() const
+{
+ Q_D(const QQuickTabBarAttached);
+ if (!d->tabBar)
+ return QQuickTabBar::Header;
+ return d->tabBar->position();
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h
index 5780197b..f0299bd5 100644
--- a/src/quicktemplates2/qquicktabbar_p.h
+++ b/src/quicktemplates2/qquicktabbar_p.h
@@ -53,6 +53,8 @@
QT_BEGIN_NAMESPACE
class QQuickTabBarPrivate;
+class QQuickTabBarAttached;
+class QQuickTabBarAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer
{
@@ -83,6 +85,8 @@ public:
void setContentHeight(qreal height);
void resetContentHeight();
+ static QQuickTabBarAttached *qmlAttachedProperties(QObject *object);
+
Q_SIGNALS:
void positionChanged();
// 2.2 (Qt 5.9)
@@ -95,8 +99,11 @@ protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
bool isContent(QQuickItem *item) const override;
void itemAdded(int index, QQuickItem *item) override;
+ void itemMoved(int index, QQuickItem *item) override;
void itemRemoved(int index, QQuickItem *item) override;
+ QPalette defaultPalette() const override;
+
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
@@ -106,8 +113,33 @@ private:
Q_DECLARE_PRIVATE(QQuickTabBar)
};
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBarAttached : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL)
+ Q_PROPERTY(QQuickTabBar *tabBar READ tabBar NOTIFY tabBarChanged FINAL)
+ Q_PROPERTY(QQuickTabBar::Position position READ position NOTIFY positionChanged FINAL)
+
+public:
+ explicit QQuickTabBarAttached(QObject *parent = nullptr);
+
+ int index() const;
+ QQuickTabBar *tabBar() const;
+ QQuickTabBar::Position position() const;
+
+Q_SIGNALS:
+ void indexChanged();
+ void tabBarChanged();
+ void positionChanged();
+
+private:
+ Q_DISABLE_COPY(QQuickTabBarAttached)
+ Q_DECLARE_PRIVATE(QQuickTabBarAttached)
+};
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickTabBar)
+QML_DECLARE_TYPEINFO(QQuickTabBar, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKTABBAR_P_H
diff --git a/src/quicktemplates2/qquicktabbutton.cpp b/src/quicktemplates2/qquicktabbutton.cpp
index 9afe5363..617d4aea 100644
--- a/src/quicktemplates2/qquicktabbutton.cpp
+++ b/src/quicktemplates2/qquicktabbutton.cpp
@@ -75,6 +75,11 @@ QFont QQuickTabButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::TabButtonFont);
}
+QPalette QQuickTabButton::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::TabBarPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickTabButton::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquicktabbutton_p.h b/src/quicktemplates2/qquicktabbutton_p.h
index 49ecee50..9ca9df9f 100644
--- a/src/quicktemplates2/qquicktabbutton_p.h
+++ b/src/quicktemplates2/qquicktabbutton_p.h
@@ -61,6 +61,7 @@ public:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index 06867742..d2458c24 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -139,7 +139,6 @@ QQuickTextAreaPrivate::QQuickTextAreaPrivate()
#endif
background(nullptr),
focusReason(Qt::OtherFocusReason),
- accessibleAttached(nullptr),
flickable(nullptr)
{
#if QT_CONFIG(accessibility)
@@ -190,21 +189,71 @@ void QQuickTextAreaPrivate::resolveFont()
inheritFont(QQuickControlPrivate::parentFont(q));
}
-void QQuickTextAreaPrivate::inheritFont(const QFont &f)
+void QQuickTextAreaPrivate::inheritFont(const QFont &font)
{
- Q_Q(QQuickTextArea);
- QFont parentFont = font.resolve(f);
- parentFont.resolve(font.resolve() | f.resolve());
+ QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
+ parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());
const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
const QFont resolvedFont = parentFont.resolve(defaultFont);
- const bool changed = resolvedFont != sourceFont;
- q->QQuickTextEdit::setFont(resolvedFont);
- if (changed)
+ setFont_helper(resolvedFont);
+}
+
+/*!
+ \internal
+
+ Assign \a font to this control, and propagate it to all children.
+*/
+void QQuickTextAreaPrivate::updateFont(const QFont &font)
+{
+ Q_Q(QQuickTextArea);
+ QFont oldFont = sourceFont;
+ q->QQuickTextEdit::setFont(font);
+
+ QQuickControlPrivate::updateFontRecur(q, font);
+
+ if (oldFont != font)
emit q->fontChanged();
}
+/*!
+ \internal
+
+ Determine which palette is implicitly imposed on this control by its ancestors
+ and QGuiApplication::palette, resolve this against its own palette (attributes from
+ the implicit palette are copied over). Then propagate this palette to this
+ control's children.
+*/
+void QQuickTextAreaPrivate::resolvePalette()
+{
+ Q_Q(QQuickTextArea);
+ inheritPalette(QQuickControlPrivate::parentPalette(q));
+}
+
+void QQuickTextAreaPrivate::inheritPalette(const QPalette &palette)
+{
+ QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
+ parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());
+
+ const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextEditPalette);
+ const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);
+
+ setPalette_helper(resolvedPalette);
+}
+
+void QQuickTextAreaPrivate::updatePalette(const QPalette &palette)
+{
+ Q_Q(QQuickTextArea);
+ QPalette oldPalette = resolvedPalette;
+ resolvedPalette = palette;
+
+ QQuickControlPrivate::updatePaletteRecur(q, palette);
+
+ if (oldPalette != palette)
+ emit q->paletteChanged();
+}
+
#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit)
{
@@ -361,7 +410,7 @@ void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
{
Q_UNUSED(isReadOnly);
#if QT_CONFIG(accessibility)
- if (accessibleAttached)
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
accessibleAttached->set_readOnly(isReadOnly);
#endif
#if QT_CONFIG(cursor)
@@ -372,18 +421,15 @@ void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
#if QT_CONFIG(accessibility)
void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
{
- if (accessibleAttached || !active)
+ if (!active)
return;
Q_Q(QQuickTextArea);
- accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
- if (accessibleAttached) {
- accessibleAttached->setRole(accessibleRole());
- accessibleAttached->set_readOnly(q->isReadOnly());
- accessibleAttached->setDescription(placeholder);
- } else {
- qWarning() << "QQuickTextArea: " << q << " QQuickAccessibleAttached object creation failed!";
- }
+ QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
+ Q_ASSERT(accessibleAttached);
+ accessibleAttached->setRole(accessibleRole());
+ accessibleAttached->set_readOnly(q->isReadOnly());
+ accessibleAttached->setDescription(placeholder);
}
QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const
@@ -441,10 +487,10 @@ QFont QQuickTextArea::font() const
void QQuickTextArea::setFont(const QFont &font)
{
Q_D(QQuickTextArea);
- if (d->font.resolve() == font.resolve() && d->font == font)
+ if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
return;
- d->font = font;
+ d->extra.value().requestedFont = font;
d->resolveFont();
}
@@ -504,8 +550,8 @@ void QQuickTextArea::setPlaceholderText(const QString &text)
d->placeholder = text;
#if QT_CONFIG(accessibility)
- if (d->accessibleAttached)
- d->accessibleAttached->setDescription(text);
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
+ accessibleAttached->setDescription(text);
#endif
emit placeholderTextChanged();
}
@@ -615,11 +661,44 @@ void QQuickTextArea::resetHoverEnabled()
#endif
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::TextArea::palette
+
+ This property holds the palette currently set for the text area.
+
+ \sa Control::palette
+*/
+QPalette QQuickTextArea::palette() const
+{
+ Q_D(const QQuickTextArea);
+ QPalette palette = d->resolvedPalette;
+ if (!isEnabled())
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ return palette;
+}
+
+void QQuickTextArea::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickTextArea);
+ if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
+ return;
+
+ d->extra.value().requestedPalette = palette;
+ d->resolvePalette();
+}
+
+void QQuickTextArea::resetPalette()
+{
+ setPalette(QPalette());
+}
+
void QQuickTextArea::classBegin()
{
Q_D(QQuickTextArea);
QQuickTextEdit::classBegin();
d->resolveFont();
+ d->resolvePalette();
}
void QQuickTextArea::componentComplete()
@@ -632,7 +711,7 @@ void QQuickTextArea::componentComplete()
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
#endif
#if QT_CONFIG(accessibility)
- if (!d->accessibleAttached && QAccessible::isActive())
+ if (QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
}
@@ -641,20 +720,31 @@ void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem:
{
Q_D(QQuickTextArea);
QQuickTextEdit::itemChange(change, value);
- if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
- d->resolveFont();
+ switch (change) {
+ case ItemEnabledHasChanged:
+ emit paletteChanged();
+ break;
+ case ItemSceneChange:
+ case ItemParentHasChanged:
+ if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
+ d->resolveFont();
+ d->resolvePalette();
#if QT_CONFIG(quicktemplates2_hover)
- if (!d->explicitHoverEnabled)
- d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+ if (!d->explicitHoverEnabled)
+ d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
#endif
- if (change == ItemParentHasChanged) {
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
- if (flickable) {
- QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
- if (scrollView)
- d->attachFlickable(flickable);
+ if (change == ItemParentHasChanged) {
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
+ if (flickable) {
+ QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
+ if (scrollView)
+ d->attachFlickable(flickable);
+ }
}
}
+ break;
+ default:
+ break;
}
}
diff --git a/src/quicktemplates2/qquicktextarea_p.h b/src/quicktemplates2/qquicktextarea_p.h
index 86d91346..5482ceae 100644
--- a/src/quicktemplates2/qquicktextarea_p.h
+++ b/src/quicktemplates2/qquicktextarea_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtGui/qpalette.h>
#include <QtQuick/private/qquicktextedit_p.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
@@ -70,6 +71,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextArea : public QQuickTextEdit
// 2.1 (Qt 5.8)
Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL REVISION 1)
Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background")
public:
@@ -100,6 +103,11 @@ public:
void setHoverEnabled(bool enabled);
void resetHoverEnabled();
+ // 2.3 (Qt 5.10)
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
Q_SIGNALS:
void fontChanged();
void implicitWidthChanged3();
@@ -113,6 +121,8 @@ Q_SIGNALS:
Q_REVISION(1) void released(QQuickMouseEvent *event);
Q_REVISION(1) void hoveredChanged();
Q_REVISION(1) void hoverEnabledChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void paletteChanged();
protected:
void classBegin() override;
diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h
index ede9d97f..d27af8f6 100644
--- a/src/quicktemplates2/qquicktextarea_p_p.h
+++ b/src/quicktemplates2/qquicktextarea_p_p.h
@@ -48,12 +48,13 @@
// We mean it.
//
+#include <QtQml/private/qlazilyallocated_p.h>
#include <QtQuick/private/qquicktextedit_p_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
#include <QtQuickTemplates2/private/qquickpresshandler_p_p.h>
#include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h>
-#include "qquicktextarea_p.h"
+#include <QtQuickTemplates2/private/qquicktextarea_p.h>
#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
@@ -62,7 +63,6 @@
QT_BEGIN_NAMESPACE
class QQuickFlickable;
-class QQuickAccessibleAttached;
class QQuickTextAreaPrivate : public QQuickTextEditPrivate, public QQuickItemChangeListener
#if QT_CONFIG(accessibility)
@@ -81,8 +81,24 @@ public:
}
void resizeBackground();
+
void resolveFont();
- void inheritFont(const QFont &f);
+ void inheritFont(const QFont &font);
+ void updateFont(const QFont &font);
+ inline void setFont_helper(const QFont &font) {
+ if (sourceFont.resolve() == font.resolve() && sourceFont == font)
+ return;
+ updateFont(font);
+ }
+
+ void resolvePalette();
+ void inheritPalette(const QPalette &palette);
+ void updatePalette(const QPalette &palette);
+ inline void setPalette_helper(const QPalette &palette) {
+ if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette)
+ return;
+ updatePalette(palette);
+ }
#if QT_CONFIG(quicktemplates2_hover)
void updateHoverEnabled(bool h, bool e);
@@ -115,12 +131,18 @@ public:
bool hovered;
bool explicitHoverEnabled;
#endif
- QFont font;
+
+ struct ExtraData {
+ QFont requestedFont;
+ QPalette requestedPalette;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
+ QPalette resolvedPalette;
QQuickDeferredPointer<QQuickItem> background;
QString placeholder;
Qt::FocusReason focusReason;
QQuickPressHandler pressHandler;
- QQuickAccessibleAttached *accessibleAttached;
QQuickFlickable *flickable;
};
diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp
index 2d432ec0..03da9323 100644
--- a/src/quicktemplates2/qquicktextfield.cpp
+++ b/src/quicktemplates2/qquicktextfield.cpp
@@ -119,8 +119,7 @@ QQuickTextFieldPrivate::QQuickTextFieldPrivate()
explicitHoverEnabled(false),
#endif
background(nullptr),
- focusReason(Qt::OtherFocusReason),
- accessibleAttached(nullptr)
+ focusReason(Qt::OtherFocusReason)
{
#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
@@ -164,21 +163,71 @@ void QQuickTextFieldPrivate::resolveFont()
inheritFont(QQuickControlPrivate::parentFont(q));
}
-void QQuickTextFieldPrivate::inheritFont(const QFont &f)
+void QQuickTextFieldPrivate::inheritFont(const QFont &font)
{
- Q_Q(QQuickTextField);
- QFont parentFont = font.resolve(f);
- parentFont.resolve(font.resolve() | f.resolve());
+ QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
+ parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());
const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
const QFont resolvedFont = parentFont.resolve(defaultFont);
- const bool changed = resolvedFont != sourceFont;
- q->QQuickTextInput::setFont(resolvedFont);
- if (changed)
+ setFont_helper(resolvedFont);
+}
+
+/*!
+ \internal
+
+ Assign \a font to this control, and propagate it to all children.
+*/
+void QQuickTextFieldPrivate::updateFont(const QFont &font)
+{
+ Q_Q(QQuickTextField);
+ QFont oldFont = sourceFont;
+ q->QQuickTextInput::setFont(font);
+
+ QQuickControlPrivate::updateFontRecur(q, font);
+
+ if (oldFont != font)
emit q->fontChanged();
}
+/*!
+ \internal
+
+ Determine which palette is implicitly imposed on this control by its ancestors
+ and QGuiApplication::palette, resolve this against its own palette (attributes from
+ the implicit palette are copied over). Then propagate this palette to this
+ control's children.
+*/
+void QQuickTextFieldPrivate::resolvePalette()
+{
+ Q_Q(QQuickTextField);
+ inheritPalette(QQuickControlPrivate::parentPalette(q));
+}
+
+void QQuickTextFieldPrivate::inheritPalette(const QPalette &palette)
+{
+ QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
+ parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());
+
+ const QPalette defaultPalette = QQuickControlPrivate::themePalette(QPlatformTheme::TextLineEditPalette);
+ const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);
+
+ setPalette_helper(resolvedPalette);
+}
+
+void QQuickTextFieldPrivate::updatePalette(const QPalette &palette)
+{
+ Q_Q(QQuickTextField);
+ QPalette oldPalette = resolvedPalette;
+ resolvedPalette = palette;
+
+ QQuickControlPrivate::updatePaletteRecur(q, palette);
+
+ if (oldPalette != palette)
+ emit q->paletteChanged();
+}
+
#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextFieldPrivate::updateHoverEnabled(bool enabled, bool xplicit)
{
@@ -224,7 +273,7 @@ void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly)
{
Q_UNUSED(isReadOnly);
#if QT_CONFIG(accessibility)
- if (accessibleAttached)
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
accessibleAttached->set_readOnly(isReadOnly);
#endif
#if QT_CONFIG(cursor)
@@ -235,7 +284,7 @@ void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly)
void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode)
{
#if QT_CONFIG(accessibility)
- if (accessibleAttached)
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
accessibleAttached->set_passwordEdit((echoMode == QQuickTextField::Password || echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
#else
Q_UNUSED(echoMode)
@@ -245,19 +294,16 @@ void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode)
#if QT_CONFIG(accessibility)
void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active)
{
- if (accessibleAttached || !active)
+ if (!active)
return;
Q_Q(QQuickTextField);
- accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
- if (accessibleAttached) {
- accessibleAttached->setRole(accessibleRole());
- accessibleAttached->set_readOnly(m_readOnly);
- accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
- accessibleAttached->setDescription(placeholder);
- } else {
- qWarning() << "QQuickTextField: " << q << " QQuickAccessibleAttached object creation failed!";
- }
+ QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
+ Q_ASSERT(accessibleAttached);
+ accessibleAttached->setRole(accessibleRole());
+ accessibleAttached->set_readOnly(m_readOnly);
+ accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
+ accessibleAttached->setDescription(placeholder);
}
QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const
@@ -303,10 +349,10 @@ QFont QQuickTextField::font() const
void QQuickTextField::setFont(const QFont &font)
{
Q_D(QQuickTextField);
- if (d->font.resolve() == font.resolve() && d->font == font)
+ if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
return;
- d->font = font;
+ d->extra.value().requestedFont = font;
d->resolveFont();
}
@@ -366,8 +412,8 @@ void QQuickTextField::setPlaceholderText(const QString &text)
d->placeholder = text;
#if QT_CONFIG(accessibility)
- if (d->accessibleAttached)
- d->accessibleAttached->setDescription(text);
+ if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
+ accessibleAttached->setDescription(text);
#endif
emit placeholderTextChanged();
}
@@ -469,11 +515,44 @@ void QQuickTextField::resetHoverEnabled()
#endif
}
+/*!
+ \since QtQuick.Controls 2.3 (Qt 5.10)
+ \qmlproperty palette QtQuick.Controls::TextField::palette
+
+ This property holds the palette currently set for the text field.
+
+ \sa Control::palette
+*/
+QPalette QQuickTextField::palette() const
+{
+ Q_D(const QQuickTextField);
+ QPalette palette = d->resolvedPalette;
+ if (!isEnabled())
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ return palette;
+}
+
+void QQuickTextField::setPalette(const QPalette &palette)
+{
+ Q_D(QQuickTextField);
+ if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
+ return;
+
+ d->extra.value().requestedPalette = palette;
+ d->resolvePalette();
+}
+
+void QQuickTextField::resetPalette()
+{
+ setPalette(QPalette());
+}
+
void QQuickTextField::classBegin()
{
Q_D(QQuickTextField);
QQuickTextInput::classBegin();
d->resolveFont();
+ d->resolvePalette();
}
void QQuickTextField::componentComplete()
@@ -486,7 +565,7 @@ void QQuickTextField::componentComplete()
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
#endif
#if QT_CONFIG(accessibility)
- if (!d->accessibleAttached && QAccessible::isActive())
+ if (QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
}
@@ -495,12 +574,23 @@ void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem
{
Q_D(QQuickTextField);
QQuickTextInput::itemChange(change, value);
- if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
- d->resolveFont();
+ switch (change) {
+ case ItemEnabledHasChanged:
+ emit paletteChanged();
+ break;
+ case ItemSceneChange:
+ case ItemParentHasChanged:
+ if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
+ d->resolveFont();
+ d->resolvePalette();
#if QT_CONFIG(quicktemplates2_hover)
- if (!d->explicitHoverEnabled)
- d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+ if (!d->explicitHoverEnabled)
+ d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
#endif
+ }
+ break;
+ default:
+ break;
}
}
diff --git a/src/quicktemplates2/qquicktextfield_p.h b/src/quicktemplates2/qquicktextfield_p.h
index eb84fe62..4757bd2d 100644
--- a/src/quicktemplates2/qquicktextfield_p.h
+++ b/src/quicktemplates2/qquicktextfield_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtGui/qpalette.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
@@ -69,6 +70,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextField : public QQuickTextInput
// 2.1 (Qt 5.8)
Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL REVISION 1)
Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled RESET resetHoverEnabled NOTIFY hoverEnabledChanged FINAL REVISION 1)
+ // 2.3 (Qt 5.10)
+ Q_PROPERTY(QPalette palette READ palette WRITE setPalette RESET resetPalette NOTIFY paletteChanged FINAL REVISION 3)
Q_CLASSINFO("DeferredPropertyNames", "background")
public:
@@ -94,6 +97,11 @@ public:
void setHoverEnabled(bool enabled);
void resetHoverEnabled();
+ // 2.3 (Qt 5.10)
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void resetPalette();
+
Q_SIGNALS:
void fontChanged();
void implicitWidthChanged3();
@@ -107,6 +115,8 @@ Q_SIGNALS:
Q_REVISION(1) void released(QQuickMouseEvent *event);
Q_REVISION(1) void hoveredChanged();
Q_REVISION(1) void hoverEnabledChanged();
+ // 2.3 (Qt 5.10)
+ Q_REVISION(3) void paletteChanged();
protected:
void classBegin() override;
diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h
index 037c6a21..5ae79b7f 100644
--- a/src/quicktemplates2/qquicktextfield_p_p.h
+++ b/src/quicktemplates2/qquicktextfield_p_p.h
@@ -48,11 +48,12 @@
// We mean it.
//
+#include <QtQml/private/qlazilyallocated_p.h>
#include <QtQuick/private/qquicktextinput_p_p.h>
#include <QtQuickTemplates2/private/qquickpresshandler_p_p.h>
#include <QtQuickTemplates2/private/qquickdeferredpointer_p_p.h>
-#include "qquicktextfield_p.h"
+#include <QtQuickTemplates2/private/qquicktextfield_p.h>
#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
@@ -60,8 +61,6 @@
QT_BEGIN_NAMESPACE
-class QQuickAccessibleAttached;
-
class QQuickTextFieldPrivate : public QQuickTextInputPrivate
#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
@@ -77,8 +76,24 @@ public:
return static_cast<QQuickTextFieldPrivate *>(QObjectPrivate::get(item)); }
void resizeBackground();
+
void resolveFont();
- void inheritFont(const QFont &f);
+ void inheritFont(const QFont &font);
+ void updateFont(const QFont &font);
+ inline void setFont_helper(const QFont &font) {
+ if (sourceFont.resolve() == font.resolve() && sourceFont == font)
+ return;
+ updateFont(font);
+ }
+
+ void resolvePalette();
+ void inheritPalette(const QPalette &palette);
+ void updatePalette(const QPalette &palette);
+ inline void setPalette_helper(const QPalette &palette) {
+ if (resolvedPalette.resolve() == palette.resolve() && resolvedPalette == palette)
+ return;
+ updatePalette(palette);
+ }
#if QT_CONFIG(quicktemplates2_hover)
void updateHoverEnabled(bool h, bool e);
@@ -104,12 +119,18 @@ public:
bool hovered;
bool explicitHoverEnabled;
#endif
- QFont font;
+
+ struct ExtraData {
+ QFont requestedFont;
+ QPalette requestedPalette;
+ };
+ QLazilyAllocated<ExtraData> extra;
+
+ QPalette resolvedPalette;
QQuickDeferredPointer<QQuickItem> background;
QString placeholder;
Qt::FocusReason focusReason;
QQuickPressHandler pressHandler;
- QQuickAccessibleAttached *accessibleAttached;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktoolbar.cpp b/src/quicktemplates2/qquicktoolbar.cpp
index 9f5f210e..99775c6a 100644
--- a/src/quicktemplates2/qquicktoolbar.cpp
+++ b/src/quicktemplates2/qquicktoolbar.cpp
@@ -141,6 +141,11 @@ void QQuickToolBar::setPosition(Position position)
emit positionChanged();
}
+QPalette QQuickToolBar::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickToolBar::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquicktoolbar_p.h b/src/quicktemplates2/qquicktoolbar_p.h
index 58192ff9..b919c615 100644
--- a/src/quicktemplates2/qquicktoolbar_p.h
+++ b/src/quicktemplates2/qquicktoolbar_p.h
@@ -75,6 +75,8 @@ Q_SIGNALS:
void positionChanged();
protected:
+ QPalette defaultPalette() const override;
+
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicktoolbutton.cpp b/src/quicktemplates2/qquicktoolbutton.cpp
index 5ef25e3e..f87a58b2 100644
--- a/src/quicktemplates2/qquicktoolbutton.cpp
+++ b/src/quicktemplates2/qquicktoolbutton.cpp
@@ -58,8 +58,8 @@ QT_BEGIN_NAMESPACE
\snippet qtquickcontrols2-toolbar.qml 1
ToolButton inherits its API from AbstractButton. For instance, you can set
- \l {AbstractButton::text}{text}, and react to \l {AbstractButton::clicked}{clicks}
- using the AbstractButton API.
+ \l {AbstractButton::text}{text}, display an \l {Icons in Qt Quick Controls 2}{icon},
+ and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton API.
\sa ToolBar, {Customizing ToolButton}, {Button Controls}
*/
@@ -74,4 +74,9 @@ QFont QQuickToolButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ToolButtonFont);
}
+QPalette QQuickToolButton::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette);
+}
+
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktoolbutton_p.h b/src/quicktemplates2/qquicktoolbutton_p.h
index 06745cd9..0e376f7b 100644
--- a/src/quicktemplates2/qquicktoolbutton_p.h
+++ b/src/quicktemplates2/qquicktoolbutton_p.h
@@ -61,6 +61,7 @@ public:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktoolseparator.cpp b/src/quicktemplates2/qquicktoolseparator.cpp
index 4da63907..2ec7799f 100644
--- a/src/quicktemplates2/qquicktoolseparator.cpp
+++ b/src/quicktemplates2/qquicktoolseparator.cpp
@@ -133,6 +133,11 @@ bool QQuickToolSeparator::isVertical() const
return d->orientation == Qt::Vertical;
}
+QPalette QQuickToolSeparator::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ToolButtonPalette);
+}
+
#if QT_CONFIG(accessibility)
QAccessible::Role QQuickToolSeparator::accessibleRole() const
{
diff --git a/src/quicktemplates2/qquicktoolseparator_p.h b/src/quicktemplates2/qquicktoolseparator_p.h
index 055f475c..2108cc5b 100644
--- a/src/quicktemplates2/qquicktoolseparator_p.h
+++ b/src/quicktemplates2/qquicktoolseparator_p.h
@@ -74,6 +74,8 @@ Q_SIGNALS:
void orientationChanged();
protected:
+ QPalette defaultPalette() const override;
+
#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp
index 25fb74ab..f0bc6ffc 100644
--- a/src/quicktemplates2/qquicktooltip.cpp
+++ b/src/quicktemplates2/qquicktooltip.cpp
@@ -281,6 +281,11 @@ QFont QQuickToolTip::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::TipLabelFont);
}
+QPalette QQuickToolTip::defaultPalette() const
+{
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ToolTipPalette);
+}
+
void QQuickToolTip::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
{
Q_D(QQuickToolTip);
@@ -355,7 +360,7 @@ QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
if (!tip && create) {
// TODO: a cleaner way to create the instance? QQml(Meta)Type?
QQmlComponent component(engine);
- component.setData("import QtQuick.Controls 2.2; ToolTip { }", QUrl());
+ component.setData("import QtQuick.Controls 2.3; ToolTip { }", QUrl());
QObject *object = component.create();
if (object)
diff --git a/src/quicktemplates2/qquicktooltip_p.h b/src/quicktemplates2/qquicktooltip_p.h
index bdfbe362..60b02502 100644
--- a/src/quicktemplates2/qquicktooltip_p.h
+++ b/src/quicktemplates2/qquicktooltip_p.h
@@ -86,6 +86,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override;
void timerEvent(QTimerEvent *event) override;
diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp
index 3429f1f4..bed3e400 100644
--- a/src/quicktemplates2/qquicktumbler.cpp
+++ b/src/quicktemplates2/qquicktumbler.cpp
@@ -36,6 +36,7 @@
#include "qquicktumbler_p.h"
+#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
@@ -123,11 +124,13 @@ QQuickItem *QQuickTumblerPrivate::determineViewType(QQuickItem *contentItem)
view = contentItem;
viewContentItem = contentItem;
viewContentItemType = PathViewContentItem;
+ viewOffset = 0;
return contentItem;
} else if (contentItem->inherits("QQuickListView")) {
view = contentItem;
viewContentItem = qobject_cast<QQuickFlickable*>(contentItem)->contentItem();
viewContentItemType = ListViewContentItem;
+ viewContentY = 0;
return contentItem;
} else {
const auto childItems = contentItem->childItems();
@@ -146,6 +149,10 @@ void QQuickTumblerPrivate::resetViewData()
{
view = nullptr;
viewContentItem = nullptr;
+ if (viewContentItemType == PathViewContentItem)
+ viewOffset = 0;
+ else if (viewContentItemType == ListViewContentItem)
+ viewContentY = 0;
viewContentItemType = UnsupportedContentItemType;
}
@@ -228,16 +235,52 @@ void QQuickTumblerPrivate::_q_onViewCountChanged()
}
}
-void QQuickTumblerPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
+void QQuickTumblerPrivate::_q_onViewOffsetChanged()
+{
+ viewOffset = view->property("offset").toReal();
+ calculateDisplacements();
+}
+
+void QQuickTumblerPrivate::_q_onViewContentYChanged()
+{
+ viewContentY = view->property("contentY").toReal();
+ calculateDisplacements();
+}
+
+void QQuickTumblerPrivate::calculateDisplacements()
+{
+ const auto items = viewContentItemChildItems();
+ for (QQuickItem *childItem : items) {
+ QQuickTumblerAttached *attached = qobject_cast<QQuickTumblerAttached *>(qmlAttachedPropertiesObject<QQuickTumbler>(childItem, false));
+ if (attached)
+ QQuickTumblerAttachedPrivate::get(attached)->calculateDisplacement();
+ }
+}
+
+void QQuickTumblerPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
{
_q_updateItemWidths();
_q_updateItemHeights();
+
+ QQuickTumblerAttached *attached = qobject_cast<QQuickTumblerAttached *>(qmlAttachedPropertiesObject<QQuickTumbler>(child, false));
+ if (attached)
+ QQuickTumblerAttachedPrivate::get(attached)->calculateDisplacement();
}
-void QQuickTumblerPrivate::itemChildRemoved(QQuickItem *, QQuickItem *)
+void QQuickTumblerPrivate::itemChildRemoved(QQuickItem *, QQuickItem *child)
{
_q_updateItemWidths();
_q_updateItemHeights();
+
+ QQuickTumblerAttached *attached = qobject_cast<QQuickTumblerAttached *>(qmlAttachedPropertiesObject<QQuickTumbler>(child, false));
+ if (attached)
+ QQuickTumblerAttachedPrivate::get(attached)->calculateDisplacement();
+}
+
+void QQuickTumblerPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &)
+{
+ if (change.sizeChange())
+ calculateDisplacements();
}
QQuickTumbler::QQuickTumbler(QQuickItem *parent)
@@ -531,8 +574,13 @@ void QQuickTumblerPrivate::disconnectFromView()
QObject::disconnect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
QObject::disconnect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
+ if (viewContentItemType == PathViewContentItem)
+ QObject::disconnect(view, SIGNAL(offsetChanged()), q, SLOT(_q_onViewOffsetChanged()));
+ else
+ QObject::disconnect(view, SIGNAL(contentYChanged()), q, SLOT(_q_onViewContentYChanged()));
+
QQuickItemPrivate *oldViewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
- oldViewContentItemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Children);
+ oldViewContentItemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Children | QQuickItemPrivate::Geometry);
resetViewData();
}
@@ -556,8 +604,16 @@ void QQuickTumblerPrivate::setupViewData(QQuickItem *newControlContentItem)
QObject::connect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
QObject::connect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
+ if (viewContentItemType == PathViewContentItem) {
+ QObject::connect(view, SIGNAL(offsetChanged()), q, SLOT(_q_onViewOffsetChanged()));
+ _q_onViewOffsetChanged();
+ } else {
+ QObject::connect(view, SIGNAL(contentYChanged()), q, SLOT(_q_onViewContentYChanged()));
+ _q_onViewContentYChanged();
+ }
+
QQuickItemPrivate *viewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
- viewContentItemPrivate->addItemChangeListener(this, QQuickItemPrivate::Children);
+ viewContentItemPrivate->addItemChangeListener(this, QQuickItemPrivate::Children | QQuickItemPrivate::Geometry);
// Sync the view's currentIndex with ours.
syncCurrentIndex();
@@ -689,81 +745,46 @@ void QQuickTumbler::updatePolish()
}
}
-class QQuickTumblerAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+QFont QQuickTumbler::defaultFont() const
{
- Q_DECLARE_PUBLIC(QQuickTumblerAttached)
-public:
- QQuickTumblerAttachedPrivate()
- : tumbler(nullptr),
- index(-1),
- displacement(0)
- {
- }
-
- void init(QQuickItem *delegateItem)
- {
- if (!delegateItem->parentItem()) {
- qWarning() << "Tumbler: attached properties must be accessed through a delegate item that has a parent";
- return;
- }
-
- QVariant indexContextProperty = qmlContext(delegateItem)->contextProperty(QStringLiteral("index"));
- if (!indexContextProperty.isValid()) {
- qWarning() << "Tumbler: attempting to access attached property on item without an \"index\" property";
- return;
- }
-
- index = indexContextProperty.toInt();
-
- QQuickItem *parentItem = delegateItem;
- while ((parentItem = parentItem->parentItem())) {
- if ((tumbler = qobject_cast<QQuickTumbler*>(parentItem)))
- break;
- }
- }
-
- void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
- void itemChildAdded(QQuickItem *, QQuickItem *) override;
- void itemChildRemoved(QQuickItem *, QQuickItem *) override;
-
- void _q_calculateDisplacement();
- void emitIfDisplacementChanged(qreal oldDisplacement, qreal newDisplacement);
-
- // The Tumbler that contains the delegate. Required to calculated the displacement.
- QPointer<QQuickTumbler> tumbler;
- // The index of the delegate. Used to calculate the displacement.
- int index;
- // The displacement for our delegate.
- qreal displacement;
-};
+ return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont);
+}
-void QQuickTumblerAttachedPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
+QPalette QQuickTumbler::defaultPalette() const
{
- _q_calculateDisplacement();
+ return QQuickControlPrivate::themePalette(QPlatformTheme::ItemViewPalette);
}
-void QQuickTumblerAttachedPrivate::itemChildAdded(QQuickItem *, QQuickItem *)
+QQuickTumblerAttachedPrivate::QQuickTumblerAttachedPrivate()
+ : tumbler(nullptr),
+ index(-1),
+ displacement(0)
{
- _q_calculateDisplacement();
}
-void QQuickTumblerAttachedPrivate::itemChildRemoved(QQuickItem *item, QQuickItem *child)
+void QQuickTumblerAttachedPrivate::init(QQuickItem *delegateItem)
{
- _q_calculateDisplacement();
+ if (!delegateItem->parentItem()) {
+ qWarning() << "Tumbler: attached properties must be accessed through a delegate item that has a parent";
+ return;
+ }
- if (parent == child) {
- // The child that was removed from the contentItem was the delegate
- // that our properties are attached to. If we don't remove the change
- // listener, the contentItem will attempt to notify a destroyed
- // listener, causing a crash.
+ QVariant indexContextProperty = qmlContext(delegateItem)->contextProperty(QStringLiteral("index"));
+ if (!indexContextProperty.isValid()) {
+ qWarning() << "Tumbler: attempting to access attached property on item without an \"index\" property";
+ return;
+ }
- // item is the "actual content item" of Tumbler's contentItem, i.e. a PathView or ListView.contentItem
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- p->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Children);
+ index = indexContextProperty.toInt();
+
+ QQuickItem *parentItem = delegateItem;
+ while ((parentItem = parentItem->parentItem())) {
+ if ((tumbler = qobject_cast<QQuickTumbler*>(parentItem)))
+ break;
}
}
-void QQuickTumblerAttachedPrivate::_q_calculateDisplacement()
+void QQuickTumblerAttachedPrivate::calculateDisplacement()
{
const int previousDisplacement = displacement;
displacement = 0;
@@ -791,7 +812,7 @@ void QQuickTumblerAttachedPrivate::_q_calculateDisplacement()
}
if (tumblerPrivate->viewContentItemType == QQuickTumblerPrivate::PathViewContentItem) {
- const qreal offset = tumblerPrivate->view->property("offset").toReal();
+ const qreal offset = tumblerPrivate->viewOffset;
displacement = count > 1 ? count - index - offset : 0;
// Don't add 1 if count <= visibleItemCount
@@ -802,7 +823,7 @@ void QQuickTumblerAttachedPrivate::_q_calculateDisplacement()
else if (displacement < -halfVisibleItems)
displacement += count;
} else {
- const qreal contentY = tumblerPrivate->view->property("contentY").toReal();
+ const qreal contentY = tumblerPrivate->viewContentY;
const qreal delegateH = delegateHeight(tumbler);
const qreal preferredHighlightBegin = tumblerPrivate->view->property("preferredHighlightBegin").toReal();
// Tumbler's displacement goes from negative at the top to positive towards the bottom, so we must switch this around.
@@ -842,31 +863,10 @@ QQuickTumblerAttached::QQuickTumblerAttached(QObject *parent)
if (!tumblerPrivate->viewContentItem)
return;
- QQuickItemPrivate *p = QQuickItemPrivate::get(tumblerPrivate->viewContentItem);
- p->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Children);
-
- const char *contentItemSignal = tumblerPrivate->viewContentItemType == QQuickTumblerPrivate::PathViewContentItem
- ? SIGNAL(offsetChanged()) : SIGNAL(contentYChanged());
- connect(tumblerPrivate->view, contentItemSignal, this, SLOT(_q_calculateDisplacement()));
-
- d->_q_calculateDisplacement();
+ d->calculateDisplacement();
}
}
-QQuickTumblerAttached::~QQuickTumblerAttached()
-{
- Q_D(QQuickTumblerAttached);
- if (!d->tumbler)
- return;
-
- QQuickTumblerPrivate *tumblerPrivate = QQuickTumblerPrivate::get(d->tumbler);
- if (!tumblerPrivate->viewContentItem)
- return;
-
- QQuickItemPrivate *viewContentItemPrivate = QQuickItemPrivate::get(tumblerPrivate->viewContentItem);
- viewContentItemPrivate->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Children);
-}
-
/*!
\qmlattachedproperty Tumbler QtQuick.Controls::Tumbler::tumbler
\readonly
diff --git a/src/quicktemplates2/qquicktumbler_p.h b/src/quicktemplates2/qquicktumbler_p.h
index 480ebb23..c388c28d 100644
--- a/src/quicktemplates2/qquicktumbler_p.h
+++ b/src/quicktemplates2/qquicktumbler_p.h
@@ -120,6 +120,9 @@ protected:
void keyPressEvent(QKeyEvent *event) override;
void updatePolish() override;
+ QFont defaultFont() const override;
+ QPalette defaultPalette() const override;
+
private:
Q_DISABLE_COPY(QQuickTumbler)
Q_DECLARE_PRIVATE(QQuickTumbler)
@@ -128,6 +131,8 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_updateItemHeights())
Q_PRIVATE_SLOT(d_func(), void _q_onViewCurrentIndexChanged())
Q_PRIVATE_SLOT(d_func(), void _q_onViewCountChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_onViewOffsetChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_onViewContentYChanged())
};
class QQuickTumblerAttachedPrivate;
@@ -135,12 +140,11 @@ class QQuickTumblerAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumblerAttached : public QObject
{
Q_OBJECT
- Q_PROPERTY(QQuickTumbler *tumbler READ tumbler CONSTANT)
+ Q_PROPERTY(QQuickTumbler *tumbler READ tumbler CONSTANT FINAL)
Q_PROPERTY(qreal displacement READ displacement NOTIFY displacementChanged FINAL)
public:
explicit QQuickTumblerAttached(QObject *parent = nullptr);
- ~QQuickTumblerAttached();
QQuickTumbler *tumbler() const;
qreal displacement() const;
@@ -151,8 +155,6 @@ Q_SIGNALS:
private:
Q_DISABLE_COPY(QQuickTumblerAttached)
Q_DECLARE_PRIVATE(QQuickTumblerAttached)
-
- Q_PRIVATE_SLOT(d_func(), void _q_calculateDisplacement())
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktumbler_p_p.h b/src/quicktemplates2/qquicktumbler_p_p.h
index 0dcae762..fe8a4ad2 100644
--- a/src/quicktemplates2/qquicktumbler_p_p.h
+++ b/src/quicktemplates2/qquicktumbler_p_p.h
@@ -50,11 +50,10 @@
#include <QtQuick/private/qquickitemchangelistener_p.h>
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtQuickTemplates2/private/qquicktumbler_p.h>
QT_BEGIN_NAMESPACE
-class QQuickTumbler;
-
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumblerPrivate : public QQuickControlPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickTumbler)
@@ -84,6 +83,10 @@ public:
QQuickItem *view;
QQuickItem *viewContentItem;
ContentItemType viewContentItemType;
+ union {
+ qreal viewOffset; // PathView
+ qreal viewContentY; // ListView
+ };
int currentIndex;
int pendingCurrentIndex;
bool ignoreCurrentIndexChanges;
@@ -94,6 +97,10 @@ public:
void _q_updateItemWidths();
void _q_onViewCurrentIndexChanged();
void _q_onViewCountChanged();
+ void _q_onViewOffsetChanged();
+ void _q_onViewContentYChanged();
+
+ void calculateDisplacements();
void disconnectFromView();
void setupViewData(QQuickItem *newControlContentItem);
@@ -107,6 +114,32 @@ public:
void itemChildAdded(QQuickItem *, QQuickItem *) override;
void itemChildRemoved(QQuickItem *, QQuickItem *) override;
+ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange , const QRectF &) override;
+};
+
+class QQuickTumblerAttachedPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickTumblerAttached)
+
+public:
+ QQuickTumblerAttachedPrivate();
+
+ static QQuickTumblerAttachedPrivate *get(QQuickTumblerAttached *attached)
+ {
+ return attached->d_func();
+ }
+
+ void init(QQuickItem *delegateItem);
+
+ void calculateDisplacement();
+ void emitIfDisplacementChanged(qreal oldDisplacement, qreal newDisplacement);
+
+ // The Tumbler that contains the delegate. Required to calculated the displacement.
+ QPointer<QQuickTumbler> tumbler;
+ // The index of the delegate. Used to calculate the displacement.
+ int index;
+ // The displacement for our delegate.
+ qreal displacement;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qtquicktemplates2global_p.h b/src/quicktemplates2/qtquicktemplates2global_p.h
index b7f54bb6..e5ee3f2e 100644
--- a/src/quicktemplates2/qtquicktemplates2global_p.h
+++ b/src/quicktemplates2/qtquicktemplates2global_p.h
@@ -49,6 +49,7 @@
//
#include <QtCore/qglobal.h>
+#include <QtQml/private/qqmlglobal_p.h>
#include <QtQuickTemplates2/private/qtquicktemplates2-config_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri
index 95039681..ee51f995 100644
--- a/src/quicktemplates2/quicktemplates2.pri
+++ b/src/quicktemplates2/quicktemplates2.pri
@@ -3,6 +3,8 @@ INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/qquickabstractbutton_p.h \
$$PWD/qquickabstractbutton_p_p.h \
+ $$PWD/qquickaction_p.h \
+ $$PWD/qquickactiongroup_p.h \
$$PWD/qquickapplicationwindow_p.h \
$$PWD/qquickbusyindicator_p.h \
$$PWD/qquickbutton_p.h \
@@ -28,19 +30,26 @@ HEADERS += \
$$PWD/qquickframe_p.h \
$$PWD/qquickframe_p_p.h \
$$PWD/qquickgroupbox_p.h \
+ $$PWD/qquickicon_p.h \
$$PWD/qquickitemdelegate_p.h \
$$PWD/qquickitemdelegate_p_p.h \
$$PWD/qquicklabel_p.h \
$$PWD/qquicklabel_p_p.h \
$$PWD/qquickmenu_p.h \
$$PWD/qquickmenu_p_p.h \
+ $$PWD/qquickmenubar_p.h \
+ $$PWD/qquickmenubar_p_p.h \
+ $$PWD/qquickmenubaritem_p.h \
+ $$PWD/qquickmenubaritem_p_p.h \
$$PWD/qquickmenuitem_p.h \
+ $$PWD/qquickmenuitem_p_p.h \
$$PWD/qquickmenuseparator_p.h \
$$PWD/qquickoverlay_p.h \
$$PWD/qquickoverlay_p_p.h \
$$PWD/qquickpage_p.h \
$$PWD/qquickpageindicator_p.h \
$$PWD/qquickpagelayout_p_p.h \
+ $$PWD/qquickpalette_p.h \
$$PWD/qquickpane_p.h \
$$PWD/qquickpane_p_p.h \
$$PWD/qquickpopup_p.h \
@@ -84,6 +93,8 @@ HEADERS += \
SOURCES += \
$$PWD/qquickabstractbutton.cpp \
+ $$PWD/qquickaction.cpp \
+ $$PWD/qquickactiongroup.cpp \
$$PWD/qquickapplicationwindow.cpp \
$$PWD/qquickbusyindicator.cpp \
$$PWD/qquickbutton.cpp \
@@ -101,15 +112,19 @@ SOURCES += \
$$PWD/qquickdrawer.cpp \
$$PWD/qquickframe.cpp \
$$PWD/qquickgroupbox.cpp \
+ $$PWD/qquickicon.cpp \
$$PWD/qquickitemdelegate.cpp \
$$PWD/qquicklabel.cpp \
$$PWD/qquickmenu.cpp \
+ $$PWD/qquickmenubar.cpp \
+ $$PWD/qquickmenubaritem.cpp \
$$PWD/qquickmenuitem.cpp \
$$PWD/qquickmenuseparator.cpp \
$$PWD/qquickoverlay.cpp \
$$PWD/qquickpage.cpp \
$$PWD/qquickpageindicator.cpp \
$$PWD/qquickpagelayout.cpp \
+ $$PWD/qquickpalette.cpp \
$$PWD/qquickpane.cpp \
$$PWD/qquickpopup.cpp \
$$PWD/qquickpopupitem.cpp \