1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qquickmenuitem_p.h" |
5 | #include "qquickmenuitem_p_p.h" |
6 | #include "qquickmenu_p.h" |
7 | #include "qquickdeferredexecute_p_p.h" |
8 | |
9 | #include <QtGui/qpa/qplatformtheme.h> |
10 | #include <QtQuick/private/qquickevents_p_p.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | /*! |
15 | \qmltype MenuItem |
16 | \inherits AbstractButton |
17 | //! \instantiates QQuickMenuItem |
18 | \inqmlmodule QtQuick.Controls |
19 | \since 5.7 |
20 | \ingroup qtquickcontrols-menus |
21 | \brief Presents an item within a Menu. |
22 | |
23 | MenuItem is a convenience type that implements the AbstractButton API, |
24 | providing a familiar way to respond to menu items being \l triggered, for |
25 | example. |
26 | |
27 | MenuItem inherits its API from AbstractButton. For instance, you can set |
28 | \l {AbstractButton::text}{text} and \l {Icons in Qt Quick Controls}{icon} |
29 | using the AbstractButton API. |
30 | |
31 | \code |
32 | Button { |
33 | id: fileButton |
34 | text: "File" |
35 | onClicked: menu.open() |
36 | |
37 | Menu { |
38 | id: menu |
39 | |
40 | MenuItem { |
41 | text: "New..." |
42 | onTriggered: document.reset() |
43 | } |
44 | MenuItem { |
45 | text: "Open..." |
46 | onTriggered: openDialog.open() |
47 | } |
48 | MenuItem { |
49 | text: "Save" |
50 | onTriggered: saveDialog.open() |
51 | } |
52 | } |
53 | } |
54 | \endcode |
55 | |
56 | \sa {Customizing Menu}, Menu, {Menu Controls} |
57 | */ |
58 | |
59 | void QQuickMenuItemPrivate::(QQuickMenu *) |
60 | { |
61 | Q_Q(QQuickMenuItem); |
62 | if (menu == newMenu) |
63 | return; |
64 | |
65 | menu = newMenu; |
66 | emit q->menuChanged(); |
67 | } |
68 | |
69 | void QQuickMenuItemPrivate::(QQuickMenu *) |
70 | { |
71 | Q_Q(QQuickMenuItem); |
72 | if (subMenu == newSubMenu) |
73 | return; |
74 | |
75 | if (subMenu) { |
76 | QObject::disconnect(sender: subMenu, signal: &QQuickMenu::titleChanged, receiver: q, slot: &QQuickAbstractButton::setText); |
77 | QObject::disconnect(sender: subMenu, signal: &QQuickMenu::iconChanged, receiver: q, slot: &QQuickAbstractButton::setIcon); |
78 | QObjectPrivate::disconnect(sender: subMenu, signal: &QQuickPopup::enabledChanged, receiverPrivate: this, slot: &QQuickMenuItemPrivate::updateEnabled); |
79 | } |
80 | |
81 | if (newSubMenu) { |
82 | QObject::connect(sender: newSubMenu, signal: &QQuickMenu::titleChanged, context: q, slot: &QQuickAbstractButton::setText); |
83 | QObject::connect(sender: newSubMenu, signal: &QQuickMenu::iconChanged, context: q, slot: &QQuickAbstractButton::setIcon); |
84 | QObjectPrivate::connect(sender: newSubMenu, signal: &QQuickPopup::enabledChanged, receiverPrivate: this, slot: &QQuickMenuItemPrivate::updateEnabled); |
85 | q->setText(newSubMenu->title()); |
86 | q->setIcon(newSubMenu->icon()); |
87 | } |
88 | |
89 | subMenu = newSubMenu; |
90 | updateEnabled(); |
91 | emit q->subMenuChanged(); |
92 | } |
93 | |
94 | void QQuickMenuItemPrivate::() |
95 | { |
96 | Q_Q(QQuickMenuItem); |
97 | q->setEnabled(subMenu && subMenu->isEnabled()); |
98 | } |
99 | |
100 | static inline QString arrowName() { return QStringLiteral("arrow" ); } |
101 | |
102 | void QQuickMenuItemPrivate::() |
103 | { |
104 | Q_Q(QQuickAbstractButton); |
105 | quickCancelDeferred(object: q, property: arrowName()); |
106 | } |
107 | |
108 | void QQuickMenuItemPrivate::(bool complete) |
109 | { |
110 | Q_Q(QQuickMenuItem); |
111 | if (arrow.wasExecuted()) |
112 | return; |
113 | |
114 | if (!arrow || complete) |
115 | quickBeginDeferred(object: q, property: arrowName(), delegate&: arrow); |
116 | if (complete) |
117 | quickCompleteDeferred(object: q, property: arrowName(), delegate&: arrow); |
118 | } |
119 | |
120 | bool QQuickMenuItemPrivate::(Qt::Key key) const |
121 | { |
122 | return key == Qt::Key_Return || key == Qt::Key_Enter |
123 | || QQuickAbstractButtonPrivate::acceptKeyClick(key); |
124 | } |
125 | |
126 | QPalette QQuickMenuItemPrivate::() const |
127 | { |
128 | return QQuickTheme::palette(scope: QQuickTheme::Menu); |
129 | } |
130 | |
131 | /*! |
132 | \qmlsignal void QtQuick.Controls::MenuItem::triggered() |
133 | |
134 | This signal is emitted when the menu item is triggered by the user. |
135 | */ |
136 | |
137 | QQuickMenuItem::(QQuickItem *parent) |
138 | : QQuickAbstractButton(*(new QQuickMenuItemPrivate), parent) |
139 | { |
140 | connect(sender: this, signal: &QQuickAbstractButton::clicked, context: this, slot: &QQuickMenuItem::triggered); |
141 | } |
142 | |
143 | /*! |
144 | \qmlproperty bool QtQuick.Controls::MenuItem::highlighted |
145 | |
146 | This property holds whether the menu item is highlighted by the user. |
147 | |
148 | A menu item can be highlighted by mouse hover or keyboard navigation. |
149 | |
150 | The default value is \c false. |
151 | |
152 | \sa Menu::currentIndex |
153 | */ |
154 | bool QQuickMenuItem::() const |
155 | { |
156 | Q_D(const QQuickMenuItem); |
157 | return d->highlighted; |
158 | } |
159 | |
160 | void QQuickMenuItem::(bool highlighted) |
161 | { |
162 | Q_D(QQuickMenuItem); |
163 | if (highlighted == d->highlighted) |
164 | return; |
165 | |
166 | d->highlighted = highlighted; |
167 | emit highlightedChanged(); |
168 | } |
169 | |
170 | /*! |
171 | \since QtQuick.Controls 2.3 (Qt 5.10) |
172 | \qmlproperty Item QtQuick.Controls::MenuItem::arrow |
173 | |
174 | This property holds the sub-menu arrow item. |
175 | |
176 | \sa {Customizing Menu} |
177 | */ |
178 | QQuickItem *QQuickMenuItem::() const |
179 | { |
180 | QQuickMenuItemPrivate *d = const_cast<QQuickMenuItemPrivate *>(d_func()); |
181 | if (!d->arrow) |
182 | d->executeArrow(); |
183 | return d->arrow; |
184 | } |
185 | |
186 | void QQuickMenuItem::(QQuickItem *arrow) |
187 | { |
188 | Q_D(QQuickMenuItem); |
189 | if (d->arrow == arrow) |
190 | return; |
191 | |
192 | if (!d->arrow.isExecuting()) |
193 | d->cancelArrow(); |
194 | |
195 | QQuickControlPrivate::hideOldItem(item: d->arrow); |
196 | d->arrow = arrow; |
197 | if (arrow && !arrow->parentItem()) |
198 | arrow->setParentItem(this); |
199 | if (!d->arrow.isExecuting()) |
200 | emit arrowChanged(); |
201 | } |
202 | |
203 | /*! |
204 | \since QtQuick.Controls 2.3 (Qt 5.10) |
205 | \qmlproperty Menu QtQuick.Controls::MenuItem::menu |
206 | \readonly |
207 | |
208 | This property holds the menu that contains this menu item, |
209 | or \c null if the item is not in a menu. |
210 | */ |
211 | QQuickMenu *QQuickMenuItem::() const |
212 | { |
213 | Q_D(const QQuickMenuItem); |
214 | return d->menu; |
215 | } |
216 | |
217 | /*! |
218 | \since QtQuick.Controls 2.3 (Qt 5.10) |
219 | \qmlproperty Menu QtQuick.Controls::MenuItem::subMenu |
220 | \readonly |
221 | |
222 | This property holds the sub-menu that this item presents in |
223 | the parent menu, or \c null if this item is not a sub-menu item. |
224 | */ |
225 | QQuickMenu *QQuickMenuItem::() const |
226 | { |
227 | Q_D(const QQuickMenuItem); |
228 | return d->subMenu; |
229 | } |
230 | |
231 | void QQuickMenuItem::() |
232 | { |
233 | Q_D(QQuickMenuItem); |
234 | d->executeArrow(complete: true); |
235 | QQuickAbstractButton::componentComplete(); |
236 | } |
237 | |
238 | QFont QQuickMenuItem::() const |
239 | { |
240 | return QQuickTheme::font(scope: QQuickTheme::Menu); |
241 | } |
242 | |
243 | #if QT_CONFIG(accessibility) |
244 | QAccessible::Role QQuickMenuItem::() const |
245 | { |
246 | return QAccessible::MenuItem; |
247 | } |
248 | #endif |
249 | |
250 | QT_END_NAMESPACE |
251 | |
252 | #include "moc_qquickmenuitem_p.cpp" |
253 | |