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