Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquicklabsplatformmenuitem.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
9
10#include <QtGui/qicon.h>
11#if QT_CONFIG(shortcut)
12#include <QtGui/qkeysequence.h>
13#endif
14#include <QtGui/qpa/qplatformtheme.h>
15#include <QtGui/private/qguiapplication_p.h>
16#include <QtQuickTemplates2/private/qquickshortcutcontext_p_p.h>
17
18#include "widgets/qwidgetplatform_p.h"
19
21
22/*!
23 \qmltype MenuItem
24 \inherits QtObject
25//! \nativetype QQuickLabsPlatformMenuItem
26 \inqmlmodule Qt.labs.platform
27 \since 5.8
28 \brief A native menu item.
29
30 The MenuItem type provides a QML API for native platform menu items.
31
32 \image qtlabsplatform-menu.png
33
34 A menu item consists of an \l icon, \l text, and \l shortcut.
35
36 \code
37 Menu {
38 id: zoomMenu
39
40 MenuItem {
41 text: qsTr("Zoom In")
42 shortcut: StandardKey.ZoomIn
43 onTriggered: zoomIn()
44 }
45
46 MenuItem {
47 text: qsTr("Zoom Out")
48 shortcut: StandardKey.ZoomOut
49 onTriggered: zoomOut()
50 }
51 }
52 \endcode
53
54 \labs
55
56 \sa Menu, MenuItemGroup
57*/
58
59/*!
60 \qmlsignal Qt.labs.platform::MenuItem::triggered()
61
62 This signal is emitted when the menu item is triggered by the user.
63*/
64
65/*!
66 \qmlsignal Qt.labs.platform::MenuItem::hovered()
67
68 This signal is emitted when the menu item is hovered by the user.
69*/
70
72 : QObject(parent),
73 m_complete(false),
74 m_enabled(true),
75 m_visible(true),
76 m_separator(false),
77 m_checkable(false),
78 m_checked(false),
79 m_role(QPlatformMenuItem::TextHeuristicRole),
80 m_menu(nullptr),
81 m_subMenu(nullptr),
82 m_group(nullptr),
83 m_iconLoader(nullptr),
84 m_handle(nullptr)
85{
86}
87
89{
90 if (m_menu)
91 m_menu->removeItem(this);
92 if (m_group)
93 m_group->removeItem(this);
94 removeShortcut();
95 delete m_iconLoader;
96 m_iconLoader = nullptr;
97 delete m_handle;
98 m_handle = nullptr;
99}
100
101QPlatformMenuItem *QQuickLabsPlatformMenuItem::handle() const
102{
103 return m_handle;
104}
105
107{
108 if (!m_handle && m_menu && m_menu->handle()) {
109 m_handle = m_menu->handle()->createMenuItem();
110
111 // TODO: implement QCocoaMenu::createMenuItem()
112 if (!m_handle)
113 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
114
115 if (!m_handle)
116 m_handle = QWidgetPlatform::createMenuItem();
117
118 if (m_handle) {
119 connect(m_handle, &QPlatformMenuItem::activated, this, &QQuickLabsPlatformMenuItem::activate);
120 connect(m_handle, &QPlatformMenuItem::hovered, this, &QQuickLabsPlatformMenuItem::hovered);
121 }
122 }
123 return m_handle;
124}
125
127{
128 if (!m_complete || !create())
129 return;
130
131 m_handle->setEnabled(isEnabled());
132 m_handle->setVisible(isVisible());
133 m_handle->setIsSeparator(m_separator);
134 m_handle->setCheckable(m_checkable);
135 m_handle->setChecked(m_checked);
136 m_handle->setRole(m_role);
137 m_handle->setText(m_text);
138 m_handle->setFont(m_font);
139 m_handle->setHasExclusiveGroup(m_group && m_group->isExclusive());
140
141 if (m_iconLoader)
142 m_handle->setIcon(m_iconLoader->toQIcon());
143
144 if (m_subMenu) {
145 // Sync first as dynamically created menus may need to get the
146 // handle recreated
147 m_subMenu->sync();
148 if (m_subMenu->handle())
149 m_handle->setMenu(m_subMenu->handle());
150 }
151
152#if QT_CONFIG(shortcut)
153 QKeySequence sequence;
154 if (m_shortcut.metaType().id() == QMetaType::Int)
155 sequence = QKeySequence(static_cast<QKeySequence::StandardKey>(m_shortcut.toInt()));
156 else if (m_shortcut.metaType().id() == QMetaType::QKeySequence)
157 sequence = m_shortcut.value<QKeySequence>();
158 else
159 sequence = QKeySequence::fromString(m_shortcut.toString());
160 m_handle->setShortcut(sequence.toString());
161#endif
162
163 if (m_menu && m_menu->handle())
164 m_menu->handle()->syncMenuItem(m_handle);
165}
166
167/*!
168 \readonly
169 \qmlproperty Menu Qt.labs.platform::MenuItem::menu
170
171 This property holds the menu that the item belongs to, or \c null if the
172 item is not in a menu.
173*/
175{
176 return m_menu;
177}
178
180{
181 if (m_menu == menu)
182 return;
183
184 m_menu = menu;
185 emit menuChanged();
186}
187
188/*!
189 \readonly
190 \qmlproperty Menu Qt.labs.platform::MenuItem::subMenu
191
192 This property holds the sub-menu that the item contains, or \c null if
193 the item is not a sub-menu item.
194*/
196{
197 return m_subMenu;
198}
199
201{
202 if (m_subMenu == menu)
203 return;
204
205 m_subMenu = menu;
206 sync();
207 emit subMenuChanged();
208}
209
210/*!
211 \qmlproperty MenuItemGroup Qt.labs.platform::MenuItem::group
212
213 This property holds the group that the item belongs to, or \c null if the
214 item is not in a group.
215*/
220
222{
223 if (m_group == group)
224 return;
225
226 bool wasEnabled = isEnabled();
227 bool wasVisible = isVisible();
228
229 if (group)
230 group->addItem(this);
231
232 m_group = group;
233 sync();
234 emit groupChanged();
235
236 if (isEnabled() != wasEnabled)
237 emit enabledChanged();
238 if (isVisible() != wasVisible)
239 emit visibleChanged();
240}
241
242/*!
243 \qmlproperty bool Qt.labs.platform::MenuItem::enabled
244
245 This property holds whether the item is enabled. The default value is \c true.
246
247 Disabled items cannot be triggered by the user. They do not disappear from menus,
248 but they are displayed in a way which indicates that they are unavailable. For
249 example, they might be displayed using only shades of gray.
250
251 When an item is disabled, it is not possible to trigger it through its \l shortcut.
252*/
254{
255 return m_enabled && (!m_group || m_group->isEnabled());
256}
257
259{
260 if (m_enabled == enabled)
261 return;
262
263 if (!enabled)
264 removeShortcut();
265
266 bool wasEnabled = isEnabled();
267 m_enabled = enabled;
268
269 if (enabled)
270 addShortcut();
271
272 sync();
273 if (isEnabled() != wasEnabled)
274 emit enabledChanged();
275}
276
277/*!
278 \qmlproperty bool Qt.labs.platform::MenuItem::visible
279
280 This property holds whether the item is visible. The default value is \c true.
281*/
283{
284 return m_visible && (!m_group || m_group->isVisible());
285}
286
288{
289 if (m_visible == visible)
290 return;
291
292 bool wasVisible = isVisible();
293 m_visible = visible;
294 sync();
295 if (isVisible() != wasVisible)
296 emit visibleChanged();
297}
298
299/*!
300 \qmlproperty bool Qt.labs.platform::MenuItem::separator
301
302 This property holds whether the item is a separator line. The default value
303 is \c false.
304
305 \sa MenuSeparator
306*/
308{
309 return m_separator;
310}
311
313{
314 if (m_separator == separator)
315 return;
316
317 m_separator = separator;
318 sync();
319 emit separatorChanged();
320}
321
322/*!
323 \qmlproperty bool Qt.labs.platform::MenuItem::checkable
324
325 This property holds whether the item is checkable.
326
327 A checkable menu item has an on/off state. For example, in a word processor,
328 a "Bold" menu item may be either on or off. A menu item that is not checkable
329 is a command item that is simply executed, e.g. file save.
330
331 The default value is \c false.
332
333 \sa checked, MenuItemGroup
334*/
336{
337 return m_checkable;
338}
339
341{
342 if (m_checkable == checkable)
343 return;
344
345 m_checkable = checkable;
346 sync();
347 emit checkableChanged();
348}
349
350/*!
351 \qmlproperty bool Qt.labs.platform::MenuItem::checked
352
353 This property holds whether the item is checked (on) or unchecked (off).
354 The default value is \c false.
355
356 \sa checkable, MenuItemGroup
357*/
359{
360 return m_checked;
361}
362
364{
365 if (m_checked == checked)
366 return;
367
368 if (checked && !m_checkable)
369 setCheckable(true);
370
371 m_checked = checked;
372 sync();
373 emit checkedChanged();
374}
375
376/*!
377 \qmlproperty enumeration Qt.labs.platform::MenuItem::role
378
379 This property holds the role of the item. The role determines whether
380 the item should be placed into the application menu on macOS.
381
382 Available values:
383 \value MenuItem.NoRole The item should not be put into the application menu
384 \value MenuItem.TextHeuristicRole The item should be put in the application menu based on the action's text (default)
385 \value MenuItem.ApplicationSpecificRole The item should be put in the application menu with an application-specific role
386 \value MenuItem.AboutQtRole The item handles the "About Qt" menu item.
387 \value MenuItem.AboutRole The item should be placed where the "About" menu item is in the application menu. The text of
388 the menu item will be set to "About <application name>". The application name is fetched from the
389 \c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}).
390 \value MenuItem.PreferencesRole The item should be placed where the "Preferences..." menu item is in the application menu.
391 \value MenuItem.QuitRole The item should be placed where the Quit menu item is in the application menu.
392
393 Specifying the role only has effect on items that are in the immediate
394 menus of a menubar, not in the submenus of those menus. For example, if
395 you have a "File" menu in your menubar and the "File" menu has a submenu,
396 specifying a role for the items in that submenu has no effect. They will
397 never be moved to the application menu.
398*/
400{
401 return m_role;
402}
403
404void QQuickLabsPlatformMenuItem::setRole(QPlatformMenuItem::MenuRole role)
405{
406 if (m_role == role)
407 return;
408
409 m_role = role;
410 sync();
411 emit roleChanged();
412}
413
414/*!
415 \qmlproperty string Qt.labs.platform::MenuItem::text
416
417 This property holds the menu item's text.
418*/
420{
421 return m_text;
422}
423
424void QQuickLabsPlatformMenuItem::setText(const QString &text)
425{
426 if (m_text == text)
427 return;
428
429 m_text = text;
430 sync();
431 emit textChanged();
432}
433
434/*!
435 \qmlproperty keysequence Qt.labs.platform::MenuItem::shortcut
436
437 This property holds the menu item's shortcut.
438
439 The shortcut key sequence can be set to one of the
440 \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, or it can be
441 specified by a string containing a sequence of up to four key presses
442 that are needed to \l{triggered}{trigger} the shortcut.
443
444 The default value is an empty key sequence.
445
446 \code
447 MenuItem {
448 shortcut: "Ctrl+E,Ctrl+W"
449 onTriggered: edit.wrapMode = TextEdit.Wrap
450 }
451 \endcode
452*/
454{
455 return m_shortcut;
456}
457
459{
460#if QT_CONFIG(shortcut)
461 if (e->type() == QEvent::Shortcut) {
462 QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
463 if (se->shortcutId() == m_shortcutId) {
464 activate();
465 return true;
466 }
467 }
468#endif
469 return QObject::event(e);
470}
471
472void QQuickLabsPlatformMenuItem::setShortcut(const QVariant& shortcut)
473{
474 if (m_shortcut == shortcut)
475 return;
476
477 removeShortcut();
478 m_shortcut = shortcut;
479 sync();
480 addShortcut();
481 emit shortcutChanged();
482}
483
484/*!
485 \qmlproperty font Qt.labs.platform::MenuItem::font
486
487 This property holds the menu item's font.
488
489 \sa text
490*/
492{
493 return m_font;
494}
495
496void QQuickLabsPlatformMenuItem::setFont(const QFont& font)
497{
498 if (m_font == font)
499 return;
500
501 m_font = font;
502 sync();
503 emit fontChanged();
504}
505
506/*!
507 \since Qt.labs.platform 1.1 (Qt 5.12)
508 \qmlproperty url Qt.labs.platform::MenuItem::icon.source
509 \qmlproperty string Qt.labs.platform::MenuItem::icon.name
510 \qmlproperty bool Qt.labs.platform::MenuItem::icon.mask
511
512 This property holds the menu item's icon.
513
514 \code
515 MenuItem {
516 icon.mask: true
517 icon.name: "edit-undo"
518 icon.source: "qrc:/images/undo.png"
519 }
520 \endcode
521
522 \sa QIcon::fromTheme()
523*/
525{
526 if (!m_iconLoader)
527 return QQuickLabsPlatformIcon();
528
529 return m_iconLoader->icon();
530}
531
533{
534 if (iconLoader()->icon() == icon)
535 return;
536
538 emit iconChanged();
539}
540
541/*!
542 \qmlmethod void Qt.labs.platform::MenuItem::toggle()
543
544 Toggles the \l checked state to its opposite state.
545*/
547{
548 if (m_checkable)
549 setChecked(!m_checked);
550}
551
555
557{
558 if (m_iconLoader)
559 m_iconLoader->setEnabled(true);
560 m_complete = true;
561 sync();
562}
563
565{
566 if (!m_iconLoader) {
567 QQuickLabsPlatformMenuItem *that = const_cast<QQuickLabsPlatformMenuItem *>(this);
568 static int slot = staticMetaObject.indexOfSlot("updateIcon()");
569 m_iconLoader = new QQuickLabsPlatformIconLoader(slot, that);
570 m_iconLoader->setEnabled(m_complete);
571 }
572 return m_iconLoader;
573}
574
575void QQuickLabsPlatformMenuItem::activate()
576{
577 toggle();
578 emit triggered();
579}
580
581void QQuickLabsPlatformMenuItem::updateIcon()
582{
583 sync();
584}
585
586void QQuickLabsPlatformMenuItem::addShortcut()
587{
588#if QT_CONFIG(shortcut)
589 QKeySequence sequence;
590 if (m_shortcut.metaType().id() == QMetaType::Int)
591 sequence = QKeySequence(static_cast<QKeySequence::StandardKey>(m_shortcut.toInt()));
592 else if (m_shortcut.metaType().id() == QMetaType::QKeySequence)
593 sequence = m_shortcut.value<QKeySequence>();
594 else
595 sequence = QKeySequence::fromString(m_shortcut.toString());
596 if (!sequence.isEmpty() && m_enabled) {
597 m_shortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, sequence,
598 Qt::WindowShortcut, QQuickShortcutContext::matcher);
599 } else {
600 m_shortcutId = -1;
601 }
602#endif
603}
604
605void QQuickLabsPlatformMenuItem::removeShortcut()
606{
607#if QT_CONFIG(shortcut)
608 if (m_shortcutId == -1)
609 return;
610
611 QKeySequence sequence;
612 if (m_shortcut.metaType().id() == QMetaType::Int)
613 sequence = QKeySequence(static_cast<QKeySequence::StandardKey>(m_shortcut.toInt()));
614 else if (m_shortcut.metaType().id() == QMetaType::QKeySequence)
615 sequence = m_shortcut.value<QKeySequence>();
616 else
617 sequence = QKeySequence::fromString(m_shortcut.toString());
618 QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(m_shortcutId, this, sequence);
619#endif
620}
621
622QT_END_NAMESPACE
623
624#include "moc_qquicklabsplatformmenuitem_p.cpp"
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:105
void setIcon(const QQuickLabsPlatformIcon &icon)
QQuickLabsPlatformIcon icon() const
bool operator==(const QQuickLabsPlatformIcon &other) const
bool isEnabled() const
\qmlproperty bool Qt.labs.platform::MenuItemGroup::enabled
bool isVisible() const
\qmlproperty bool Qt.labs.platform::MenuItemGroup::visible
bool isExclusive() const
\qmlproperty bool Qt.labs.platform::MenuItemGroup::exclusive
QQuickLabsPlatformMenuItemGroup * group() const
\qmlproperty MenuItemGroup Qt.labs.platform::MenuItem::group
QFont font() const
\qmlproperty font Qt.labs.platform::MenuItem::font
QString text() const
\qmlproperty string Qt.labs.platform::MenuItem::text
QQuickLabsPlatformIconLoader * iconLoader() const
QQuickLabsPlatformMenu * subMenu() const
\readonly \qmlproperty Menu Qt.labs.platform::MenuItem::subMenu
QQuickLabsPlatformMenu * menu() const
\readonly \qmlproperty Menu Qt.labs.platform::MenuItem::menu
bool isChecked() const
\qmlproperty bool Qt.labs.platform::MenuItem::checked
void setIcon(const QQuickLabsPlatformIcon &icon)
bool isCheckable() const
\qmlproperty bool Qt.labs.platform::MenuItem::checkable
bool isEnabled() const
\qmlproperty bool Qt.labs.platform::MenuItem::enabled
void setMenu(QQuickLabsPlatformMenu *menu)
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void setSubMenu(QQuickLabsPlatformMenu *menu)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
bool isVisible() const
\qmlproperty bool Qt.labs.platform::MenuItem::visible
QPlatformMenuItem::MenuRole role() const
\qmlproperty enumeration Qt.labs.platform::MenuItem::role
void setGroup(QQuickLabsPlatformMenuItemGroup *group)
bool isSeparator() const
\qmlproperty bool Qt.labs.platform::MenuItem::separator
QQuickLabsPlatformIcon icon() const
void classBegin() override
Invoked after class creation, but before any properties have been set.
QVariant shortcut() const
\qmlproperty keysequence Qt.labs.platform::MenuItem::shortcut
void setShortcut(const QVariant &shortcut)
QPlatformMenu * handle() const