1// Copyright (C) 2020 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 "qquicklabsplatformmenubar_p.h"
5#include "qquicklabsplatformmenu_p.h"
6
7#include <QtCore/qloggingcategory.h>
8#include <QtGui/qpa/qplatformmenu.h>
9#include <QtGui/qpa/qplatformtheme.h>
10#include <QtGui/private/qguiapplication_p.h>
11#include <QtQuick/qquickwindow.h>
12#include <QtQuick/qquickitem.h>
13
14QT_BEGIN_NAMESPACE
15
16/*!
17 \qmltype MenuBar
18 \inherits QtObject
19//! \instantiates QQuickLabsPlatformMenuBar
20 \inqmlmodule Qt.labs.platform
21 \since 5.8
22 \brief A native menubar.
23
24 The MenuBar type provides a QML API for native platform menubars.
25
26 \image qtlabsplatform-menubar.png
27
28 A menubar consists of a list of drop-down menus.
29
30 \code
31 MenuBar {
32 id: menuBar
33
34 Menu {
35 id: fileMenu
36 title: qsTr("File")
37 // ...
38 }
39
40 Menu {
41 id: editMenu
42 title: qsTr("&Edit")
43 // ...
44 }
45
46 Menu {
47 id: viewMenu
48 title: qsTr("&View")
49 // ...
50 }
51
52 Menu {
53 id: helpMenu
54 title: qsTr("&Help")
55 // ...
56 }
57 }
58 \endcode
59
60 MenuBar is currently available on the following platforms:
61
62 \list
63 \li macOS
64 \li Android
65 \li Linux (only available on desktop environments that provide a global D-Bus menu bar)
66 \li Windows
67 \endlist
68
69 \labs
70
71 \sa Menu
72*/
73
74Q_DECLARE_LOGGING_CATEGORY(qtLabsPlatformMenus)
75
76QQuickLabsPlatformMenuBar::QQuickLabsPlatformMenuBar(QObject *parent)
77 : QObject(parent),
78 m_complete(false),
79 m_window(nullptr),
80 m_handle(nullptr)
81{
82 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
83 qCDebug(qtLabsPlatformMenus) << "MenuBar ->" << m_handle;
84}
85
86QQuickLabsPlatformMenuBar::~QQuickLabsPlatformMenuBar()
87{
88 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus))
89 menu->setMenuBar(nullptr);
90 delete m_handle;
91 m_handle = nullptr;
92}
93
94QPlatformMenuBar *QQuickLabsPlatformMenuBar::handle() const
95{
96 return m_handle;
97}
98
99/*!
100 \qmldefault
101 \qmlproperty list<QtObject> Qt.labs.platform::MenuBar::data
102
103 This default property holds the list of all objects declared as children of
104 the menubar. The data property includes objects that are not \l Menu instances,
105 such as \l Timer and \l QtObject.
106
107 \sa menus
108*/
109QQmlListProperty<QObject> QQuickLabsPlatformMenuBar::data()
110{
111 return QQmlListProperty<QObject>(this, nullptr, data_append, data_count, data_at, data_clear);
112}
113
114/*!
115 \qmlproperty list<Menu> Qt.labs.platform::MenuBar::menus
116
117 This property holds the list of menus in the menubar.
118*/
119QQmlListProperty<QQuickLabsPlatformMenu> QQuickLabsPlatformMenuBar::menus()
120{
121 return QQmlListProperty<QQuickLabsPlatformMenu>(this, nullptr, menus_append, menus_count, menus_at, menus_clear);
122}
123
124/*!
125 \qmlproperty Window Qt.labs.platform::MenuBar::window
126
127 This property holds the menubar's window.
128
129 Unless explicitly set, the window is automatically resolved by iterating
130 the QML parent objects until a \l Window or an \l Item that has a window
131 is found.
132*/
133QWindow *QQuickLabsPlatformMenuBar::window() const
134{
135 return m_window;
136}
137
138void QQuickLabsPlatformMenuBar::setWindow(QWindow *window)
139{
140 if (m_window == window)
141 return;
142
143 if (m_handle)
144 m_handle->handleReparent(newParentWindow: window);
145
146 m_window = window;
147 emit windowChanged();
148}
149
150/*!
151 \qmlmethod void Qt.labs.platform::MenuBar::addMenu(Menu menu)
152
153 Adds a \a menu to end of the menubar.
154*/
155void QQuickLabsPlatformMenuBar::addMenu(QQuickLabsPlatformMenu *menu)
156{
157 insertMenu(index: m_menus.size(), menu);
158}
159
160/*!
161 \qmlmethod void Qt.labs.platform::MenuBar::insertMenu(int index, Menu menu)
162
163 Inserts a \a menu at the specified \a index in the menubar.
164*/
165void QQuickLabsPlatformMenuBar::insertMenu(int index, QQuickLabsPlatformMenu *menu)
166{
167 if (!menu || m_menus.contains(t: menu))
168 return;
169
170 QQuickLabsPlatformMenu *before = m_menus.value(i: index);
171 m_menus.insert(i: index, t: menu);
172 m_data.append(t: menu);
173 menu->setMenuBar(this);
174 if (m_handle)
175 m_handle->insertMenu(menu: menu->create(), before: before ? before->handle() : nullptr);
176 menu->sync();
177 emit menusChanged();
178}
179
180/*!
181 \qmlmethod void Qt.labs.platform::MenuBar::removeMenu(Menu menu)
182
183 Removes a \a menu from the menubar.
184*/
185void QQuickLabsPlatformMenuBar::removeMenu(QQuickLabsPlatformMenu *menu)
186{
187 if (!menu || !m_menus.removeOne(t: menu))
188 return;
189
190 m_data.removeOne(t: menu);
191 if (m_handle)
192 m_handle->removeMenu(menu: menu->handle());
193 menu->setMenuBar(nullptr);
194 emit menusChanged();
195}
196
197/*!
198 \qmlmethod void Qt.labs.platform::MenuBar::clear()
199
200 Removes all menus from the menubar.
201*/
202void QQuickLabsPlatformMenuBar::clear()
203{
204 if (m_menus.isEmpty())
205 return;
206
207 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus)) {
208 m_data.removeOne(t: menu);
209 if (m_handle)
210 m_handle->removeMenu(menu: menu->handle());
211 menu->setMenuBar(nullptr);
212 delete menu;
213 }
214
215 m_menus.clear();
216 emit menusChanged();
217}
218
219void QQuickLabsPlatformMenuBar::classBegin()
220{
221}
222
223void QQuickLabsPlatformMenuBar::componentComplete()
224{
225 m_complete = true;
226 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus))
227 menu->sync();
228 if (!m_window)
229 setWindow(findWindow());
230}
231
232QWindow *QQuickLabsPlatformMenuBar::findWindow() const
233{
234 QObject *obj = parent();
235 while (obj) {
236 QWindow *window = qobject_cast<QWindow *>(o: obj);
237 if (window)
238 return window;
239 QQuickItem *item = qobject_cast<QQuickItem *>(o: obj);
240 if (item && item->window())
241 return item->window();
242 obj = obj->parent();
243 }
244 return nullptr;
245}
246
247void QQuickLabsPlatformMenuBar::data_append(QQmlListProperty<QObject> *property, QObject *object)
248{
249 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
250 QQuickLabsPlatformMenu *menu = qobject_cast<QQuickLabsPlatformMenu *>(object);
251 if (menu)
252 menuBar->addMenu(menu);
253 else
254 menuBar->m_data.append(t: object);
255}
256
257qsizetype QQuickLabsPlatformMenuBar::data_count(QQmlListProperty<QObject> *property)
258{
259 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
260 return menuBar->m_data.size();
261}
262
263QObject *QQuickLabsPlatformMenuBar::data_at(QQmlListProperty<QObject> *property, qsizetype index)
264{
265 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
266 return menuBar->m_data.value(i: index);
267}
268
269void QQuickLabsPlatformMenuBar::data_clear(QQmlListProperty<QObject> *property)
270{
271 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
272 menuBar->m_data.clear();
273}
274
275void QQuickLabsPlatformMenuBar::menus_append(QQmlListProperty<QQuickLabsPlatformMenu> *property, QQuickLabsPlatformMenu *menu)
276{
277 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
278 menuBar->addMenu(menu);
279}
280
281qsizetype QQuickLabsPlatformMenuBar::menus_count(QQmlListProperty<QQuickLabsPlatformMenu> *property)
282{
283 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
284 return menuBar->m_menus.size();
285}
286
287QQuickLabsPlatformMenu *QQuickLabsPlatformMenuBar::menus_at(QQmlListProperty<QQuickLabsPlatformMenu> *property, qsizetype index)
288{
289 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
290 return menuBar->m_menus.value(i: index);
291}
292
293void QQuickLabsPlatformMenuBar::menus_clear(QQmlListProperty<QQuickLabsPlatformMenu> *property)
294{
295 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
296 menuBar->clear();
297}
298
299QT_END_NAMESPACE
300
301#include "moc_qquicklabsplatformmenubar_p.cpp"
302

source code of qtdeclarative/src/labs/platform/qquicklabsplatformmenubar.cpp