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 "qquickmenubaritem_p.h"
5#include "qquickmenubaritem_p_p.h"
6#include "qquickmenubar_p.h"
7#include "qquickmenu_p.h"
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \qmltype MenuBarItem
13 \inherits AbstractButton
14//! \instantiates QQuickMenuBarItem
15 \inqmlmodule QtQuick.Controls
16 \since 5.10
17 \ingroup qtquickcontrols-menus
18 \brief Presents a drop-down menu within a MenuBar.
19
20 MenuBarItem presents a Menu within a MenuBar. The respective drop-down menu
21 is shown when a MenuBarItem is \l triggered via keyboard, mouse, or touch.
22
23 \image qtquickcontrols-menubar.png
24
25 MenuBarItem is used as a default \l {MenuBar::}{delegate} type for MenuBar.
26 Notice that it is not necessary to declare MenuBarItem instances by hand when
27 using MenuBar. It is sufficient to declare Menu instances as children of the
28 MenuBar and the respective items are created automatically.
29
30 \sa {Customizing MenuBar}, MenuBar, {Menu Controls}
31*/
32
33/*!
34 \qmlsignal void QtQuick.Controls::MenuBarItem::triggered()
35
36 This signal is emitted when the menu bar item is triggered by the user.
37*/
38
39void QQuickMenuBarItemPrivate::setMenuBar(QQuickMenuBar *newMenuBar)
40{
41 Q_Q(QQuickMenuBarItem);
42 if (menuBar == newMenuBar)
43 return;
44
45 menuBar = newMenuBar;
46 emit q->menuBarChanged();
47}
48
49bool QQuickMenuBarItemPrivate::handlePress(const QPointF &point, ulong timestamp)
50{
51 Q_Q(QQuickMenuBarItem);
52 const bool handled = QQuickAbstractButtonPrivate::handlePress(point, timestamp);
53 if (!handled)
54 return false;
55
56 const bool wasTouchPress = touchId != -1;
57 if (!wasTouchPress) {
58 // Open the menu when it's a mouse press.
59 emit q->triggered();
60 }
61
62 return true;
63}
64
65bool QQuickMenuBarItemPrivate::handleRelease(const QPointF &point, ulong timestamp)
66{
67 Q_Q(QQuickMenuBarItem);
68 const bool wasTouchPress = touchId != -1;
69 const bool handled = QQuickAbstractButtonPrivate::handleRelease(point, timestamp);
70 if (!handled)
71 return false;
72
73 if (wasDoubleClick || !wasTouchPress) {
74 // Don't open the menu on mouse release, as it should be done on press.
75 return handled;
76 }
77
78 if (wasTouchPress) {
79 // Open the menu.
80 emit q->triggered();
81 }
82
83 return true;
84}
85
86QPalette QQuickMenuBarItemPrivate::defaultPalette() const
87{
88 return QQuickTheme::palette(scope: QQuickTheme::MenuBar);
89}
90
91QQuickMenuBarItem::QQuickMenuBarItem(QQuickItem *parent)
92 : QQuickAbstractButton(*(new QQuickMenuBarItemPrivate), parent)
93{
94 setFocusPolicy(Qt::NoFocus);
95}
96
97/*!
98 \qmlproperty Menu QtQuick.Controls::MenuBarItem::menuBar
99 \readonly
100
101 This property holds the menu bar that contains this item,
102 or \c null if the item is not in a menu bar.
103*/
104QQuickMenuBar *QQuickMenuBarItem::menuBar() const
105{
106 Q_D(const QQuickMenuBarItem);
107 return d->menuBar;
108}
109
110/*!
111 \qmlproperty Menu QtQuick.Controls::MenuBarItem::menu
112
113 This property holds the menu that this item presents in a
114 menu bar, or \c null if this item does not have a menu.
115*/
116QQuickMenu *QQuickMenuBarItem::menu() const
117{
118 Q_D(const QQuickMenuBarItem);
119 return d->menu;
120}
121
122void QQuickMenuBarItem::setMenu(QQuickMenu *menu)
123{
124 Q_D(QQuickMenuBarItem);
125 if (d->menu == menu)
126 return;
127
128 if (d->menu)
129 disconnect(sender: d->menu, signal: &QQuickMenu::titleChanged, receiver: this, slot: &QQuickAbstractButton::setText);
130
131 if (menu) {
132 setText(menu->title());
133 menu->setY(height());
134 menu->setParentItem(this);
135 menu->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent);
136 connect(sender: menu, signal: &QQuickMenu::titleChanged, context: this, slot: &QQuickAbstractButton::setText);
137 }
138
139 d->menu = menu;
140 emit menuChanged();
141}
142
143/*!
144 \qmlproperty bool QtQuick.Controls::MenuBarItem::highlighted
145
146 This property holds whether the menu bar item is highlighted by the user.
147
148 A menu bar item can be highlighted by mouse hover or keyboard navigation.
149
150 The default value is \c false.
151*/
152bool QQuickMenuBarItem::isHighlighted() const
153{
154 Q_D(const QQuickMenuBarItem);
155 return d->highlighted;
156}
157
158void QQuickMenuBarItem::setHighlighted(bool highlighted)
159{
160 Q_D(QQuickMenuBarItem);
161 if (highlighted == d->highlighted)
162 return;
163
164 d->highlighted = highlighted;
165 emit highlightedChanged();
166}
167
168bool QQuickMenuBarItem::event(QEvent *event)
169{
170#if QT_CONFIG(shortcut)
171 Q_D(QQuickMenuBarItem);
172 if (event->type() == QEvent::Shortcut) {
173 auto *shortcutEvent = static_cast<QShortcutEvent *>(event);
174 if (shortcutEvent->shortcutId() == d->shortcutId) {
175 d->trigger();
176 emit triggered();
177 return true;
178 }
179 }
180#endif
181 return QQuickControl::event(event);
182}
183
184void QQuickMenuBarItem::keyPressEvent(QKeyEvent *event)
185{
186 Q_D(QQuickMenuBarItem);
187 QQuickControl::keyPressEvent(event);
188 if (d->acceptKeyClick(key: static_cast<Qt::Key>(event->key()))) {
189 d->setPressPoint(d->centerPressPoint());
190 setPressed(true);
191 emit pressed();
192 event->accept();
193 }
194}
195
196void QQuickMenuBarItem::keyReleaseEvent(QKeyEvent *event)
197{
198 Q_D(QQuickMenuBarItem);
199 QQuickControl::keyReleaseEvent(event);
200 if (d->pressed && d->acceptKeyClick(key: static_cast<Qt::Key>(event->key()))) {
201 setPressed(false);
202 emit released();
203 d->trigger();
204 // We override these event functions so that we can emit triggered here.
205 // We can't just connect clicked to triggered, because that would cause mouse clicks
206 // to open the menu, when only presses should.
207 emit triggered();
208 event->accept();
209 }
210}
211
212void QQuickMenuBarItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
213{
214 Q_D(QQuickMenuBarItem);
215 QQuickAbstractButton::geometryChange(newGeometry, oldGeometry);
216 if (d->menu)
217 d->menu->setY(newGeometry.height());
218}
219
220QFont QQuickMenuBarItem::defaultFont() const
221{
222 return QQuickTheme::font(scope: QQuickTheme::MenuBar);
223}
224
225#if QT_CONFIG(accessibility)
226QAccessible::Role QQuickMenuBarItem::accessibleRole() const
227{
228 return QAccessible::MenuBar;
229}
230#endif
231
232QT_END_NAMESPACE
233
234#include "moc_qquickmenubaritem_p.cpp"
235

source code of qtdeclarative/src/quicktemplates/qquickmenubaritem.cpp