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//! \nativetype 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} {A native menubar}
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
74QQuickLabsPlatformMenuBar::QQuickLabsPlatformMenuBar(QObject *parent)
75 : QObject(parent),
76 m_complete(false),
77 m_window(nullptr),
78 m_handle(nullptr)
79{
80 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
81 qCDebug(qtLabsPlatformMenus) << "MenuBar ->" << m_handle;
82}
83
84QQuickLabsPlatformMenuBar::~QQuickLabsPlatformMenuBar()
85{
86 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus))
87 menu->setMenuBar(nullptr);
88 delete m_handle;
89 m_handle = nullptr;
90}
91
92QPlatformMenuBar *QQuickLabsPlatformMenuBar::handle() const
93{
94 return m_handle;
95}
96
97/*!
98 \qmldefault
99 \qmlproperty list<QtObject> Qt.labs.platform::MenuBar::data
100
101 This default property holds the list of all objects declared as children of
102 the menubar. The data property includes objects that are not \l Menu instances,
103 such as \l Timer and \l QtObject.
104
105 \sa menus
106*/
107QQmlListProperty<QObject> QQuickLabsPlatformMenuBar::data()
108{
109 return QQmlListProperty<QObject>(this, nullptr, data_append, data_count, data_at, data_clear);
110}
111
112/*!
113 \qmlproperty list<Menu> Qt.labs.platform::MenuBar::menus
114
115 This property holds the list of menus in the menubar.
116*/
117QQmlListProperty<QQuickLabsPlatformMenu> QQuickLabsPlatformMenuBar::menus()
118{
119 return QQmlListProperty<QQuickLabsPlatformMenu>(this, nullptr, menus_append, menus_count, menus_at, menus_clear);
120}
121
122/*!
123 \qmlproperty Window Qt.labs.platform::MenuBar::window
124
125 This property holds the menubar's window.
126
127 Unless explicitly set, the window is automatically resolved by iterating
128 the QML parent objects until a \l Window or an \l Item that has a window
129 is found.
130*/
131QWindow *QQuickLabsPlatformMenuBar::window() const
132{
133 return m_window;
134}
135
136void QQuickLabsPlatformMenuBar::setWindow(QWindow *window)
137{
138 if (m_window == window)
139 return;
140
141 if (m_handle)
142 m_handle->handleReparent(newParentWindow: window);
143
144 m_window = window;
145 emit windowChanged();
146}
147
148/*!
149 \qmlmethod void Qt.labs.platform::MenuBar::addMenu(Menu menu)
150
151 Adds a \a menu to end of the menubar.
152*/
153void QQuickLabsPlatformMenuBar::addMenu(QQuickLabsPlatformMenu *menu)
154{
155 insertMenu(index: m_menus.size(), menu);
156}
157
158/*!
159 \qmlmethod void Qt.labs.platform::MenuBar::insertMenu(int index, Menu menu)
160
161 Inserts a \a menu at the specified \a index in the menubar.
162*/
163void QQuickLabsPlatformMenuBar::insertMenu(int index, QQuickLabsPlatformMenu *menu)
164{
165 if (!menu || m_menus.contains(t: menu))
166 return;
167
168 QQuickLabsPlatformMenu *before = m_menus.value(i: index);
169 m_menus.insert(i: index, t: menu);
170 m_data.append(t: menu);
171 menu->setMenuBar(this);
172 if (m_handle)
173 m_handle->insertMenu(menu: menu->create(), before: before ? before->handle() : nullptr);
174 menu->sync();
175 emit menusChanged();
176}
177
178/*!
179 \qmlmethod void Qt.labs.platform::MenuBar::removeMenu(Menu menu)
180
181 Removes a \a menu from the menubar.
182*/
183void QQuickLabsPlatformMenuBar::removeMenu(QQuickLabsPlatformMenu *menu)
184{
185 if (!menu || !m_menus.removeOne(t: menu))
186 return;
187
188 m_data.removeOne(t: menu);
189 if (m_handle)
190 m_handle->removeMenu(menu: menu->handle());
191 menu->setMenuBar(nullptr);
192 emit menusChanged();
193}
194
195/*!
196 \qmlmethod void Qt.labs.platform::MenuBar::clear()
197
198 Removes all menus from the menubar.
199*/
200void QQuickLabsPlatformMenuBar::clear()
201{
202 if (m_menus.isEmpty())
203 return;
204
205 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus)) {
206 m_data.removeOne(t: menu);
207 if (m_handle)
208 m_handle->removeMenu(menu: menu->handle());
209 menu->setMenuBar(nullptr);
210 delete menu;
211 }
212
213 m_menus.clear();
214 emit menusChanged();
215}
216
217void QQuickLabsPlatformMenuBar::classBegin()
218{
219}
220
221void QQuickLabsPlatformMenuBar::componentComplete()
222{
223 m_complete = true;
224 for (QQuickLabsPlatformMenu *menu : std::as_const(t&: m_menus))
225 menu->sync();
226 if (!m_window)
227 setWindow(findWindow());
228}
229
230QWindow *QQuickLabsPlatformMenuBar::findWindow() const
231{
232 QObject *obj = parent();
233 while (obj) {
234 QWindow *window = qobject_cast<QWindow *>(o: obj);
235 if (window)
236 return window;
237 QQuickItem *item = qobject_cast<QQuickItem *>(o: obj);
238 if (item && item->window())
239 return item->window();
240 obj = obj->parent();
241 }
242 return nullptr;
243}
244
245void QQuickLabsPlatformMenuBar::data_append(QQmlListProperty<QObject> *property, QObject *object)
246{
247 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
248 QQuickLabsPlatformMenu *menu = qobject_cast<QQuickLabsPlatformMenu *>(object);
249 if (menu)
250 menuBar->addMenu(menu);
251 else
252 menuBar->m_data.append(t: object);
253}
254
255qsizetype QQuickLabsPlatformMenuBar::data_count(QQmlListProperty<QObject> *property)
256{
257 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
258 return menuBar->m_data.size();
259}
260
261QObject *QQuickLabsPlatformMenuBar::data_at(QQmlListProperty<QObject> *property, qsizetype index)
262{
263 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
264 return menuBar->m_data.value(i: index);
265}
266
267void QQuickLabsPlatformMenuBar::data_clear(QQmlListProperty<QObject> *property)
268{
269 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
270 menuBar->m_data.clear();
271}
272
273void QQuickLabsPlatformMenuBar::menus_append(QQmlListProperty<QQuickLabsPlatformMenu> *property, QQuickLabsPlatformMenu *menu)
274{
275 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
276 menuBar->addMenu(menu);
277}
278
279qsizetype QQuickLabsPlatformMenuBar::menus_count(QQmlListProperty<QQuickLabsPlatformMenu> *property)
280{
281 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
282 return menuBar->m_menus.size();
283}
284
285QQuickLabsPlatformMenu *QQuickLabsPlatformMenuBar::menus_at(QQmlListProperty<QQuickLabsPlatformMenu> *property, qsizetype index)
286{
287 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
288 return menuBar->m_menus.value(i: index);
289}
290
291void QQuickLabsPlatformMenuBar::menus_clear(QQmlListProperty<QQuickLabsPlatformMenu> *property)
292{
293 QQuickLabsPlatformMenuBar *menuBar = static_cast<QQuickLabsPlatformMenuBar *>(property->object);
294 menuBar->clear();
295}
296
297QT_END_NAMESPACE
298
299#include "moc_qquicklabsplatformmenubar_p.cpp"
300

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