1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Labs Platform module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickplatformmenubar_p.h"
38#include "qquickplatformmenu_p.h"
39
40#include <QtCore/qloggingcategory.h>
41#include <QtGui/qpa/qplatformmenu.h>
42#include <QtGui/qpa/qplatformtheme.h>
43#include <QtGui/private/qguiapplication_p.h>
44#include <QtQuick/qquickwindow.h>
45#include <QtQuick/qquickitem.h>
46
47QT_BEGIN_NAMESPACE
48
49/*!
50 \qmltype MenuBar
51 \inherits QtObject
52//! \instantiates QQuickPlatformMenuBar
53 \inqmlmodule Qt.labs.platform
54 \since 5.8
55 \brief A native menubar.
56
57 The MenuBar type provides a QML API for native platform menubars.
58
59 \image qtlabsplatform-menubar.png
60
61 A menubar consists of a list of drop-down menus.
62
63 \code
64 MenuBar {
65 id: menuBar
66
67 Menu {
68 id: fileMenu
69 title: qsTr("File")
70 // ...
71 }
72
73 Menu {
74 id: editMenu
75 title: qsTr("&Edit")
76 // ...
77 }
78
79 Menu {
80 id: viewMenu
81 title: qsTr("&View")
82 // ...
83 }
84
85 Menu {
86 id: helpMenu
87 title: qsTr("&Help")
88 // ...
89 }
90 }
91 \endcode
92
93 MenuBar is currently available on the following platforms:
94
95 \list
96 \li macOS
97 \li Android
98 \li Linux (only available on desktop environments that provide a global D-Bus menu bar)
99 \endlist
100
101 \labs
102
103 \sa Menu
104*/
105
106Q_DECLARE_LOGGING_CATEGORY(qtLabsPlatformMenus)
107
108QQuickPlatformMenuBar::QQuickPlatformMenuBar(QObject *parent)
109 : QObject(parent),
110 m_complete(false),
111 m_window(nullptr),
112 m_handle(nullptr)
113{
114 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenuBar();
115 qCDebug(qtLabsPlatformMenus) << "MenuBar ->" << m_handle;
116}
117
118QQuickPlatformMenuBar::~QQuickPlatformMenuBar()
119{
120 for (QQuickPlatformMenu *menu : qAsConst(t&: m_menus))
121 menu->setMenuBar(nullptr);
122 delete m_handle;
123 m_handle = nullptr;
124}
125
126QPlatformMenuBar *QQuickPlatformMenuBar::handle() const
127{
128 return m_handle;
129}
130
131/*!
132 \default
133 \qmlproperty list<Object> Qt.labs.platform::MenuBar::data
134
135 This default property holds the list of all objects declared as children of
136 the menubar. The data property includes objects that are not \l Menu instances,
137 such as \l Timer and \l QtObject.
138
139 \sa menus
140*/
141QQmlListProperty<QObject> QQuickPlatformMenuBar::data()
142{
143 return QQmlListProperty<QObject>(this, nullptr, data_append, data_count, data_at, data_clear);
144}
145
146/*!
147 \qmlproperty list<Menu> Qt.labs.platform::MenuBar::menus
148
149 This property holds the list of menus in the menubar.
150*/
151QQmlListProperty<QQuickPlatformMenu> QQuickPlatformMenuBar::menus()
152{
153 return QQmlListProperty<QQuickPlatformMenu>(this, nullptr, menus_append, menus_count, menus_at, menus_clear);
154}
155
156/*!
157 \qmlproperty Window Qt.labs.platform::MenuBar::window
158
159 This property holds the menubar's window.
160
161 Unless explicitly set, the window is automatically resolved by iterating
162 the QML parent objects until a \l Window or an \l Item that has a window
163 is found.
164*/
165QWindow *QQuickPlatformMenuBar::window() const
166{
167 return m_window;
168}
169
170void QQuickPlatformMenuBar::setWindow(QWindow *window)
171{
172 if (m_window == window)
173 return;
174
175 if (m_handle)
176 m_handle->handleReparent(newParentWindow: window);
177
178 m_window = window;
179 emit windowChanged();
180}
181
182/*!
183 \qmlmethod void Qt.labs.platform::MenuBar::addMenu(Menu menu)
184
185 Adds a \a menu to end of the menubar.
186*/
187void QQuickPlatformMenuBar::addMenu(QQuickPlatformMenu *menu)
188{
189 insertMenu(index: m_menus.count(), menu);
190}
191
192/*!
193 \qmlmethod void Qt.labs.platform::MenuBar::insertMenu(int index, Menu menu)
194
195 Inserts a \a menu at the specified \a index in the menubar.
196*/
197void QQuickPlatformMenuBar::insertMenu(int index, QQuickPlatformMenu *menu)
198{
199 if (!menu || m_menus.contains(t: menu))
200 return;
201
202 QQuickPlatformMenu *before = m_menus.value(i: index);
203 m_menus.insert(i: index, t: menu);
204 m_data.append(t: menu);
205 menu->setMenuBar(this);
206 if (m_handle)
207 m_handle->insertMenu(menu: menu->create(), before: before ? before->handle() : nullptr);
208 menu->sync();
209 emit menusChanged();
210}
211
212/*!
213 \qmlmethod void Qt.labs.platform::MenuBar::removeMenu(Menu menu)
214
215 Removes a \a menu from the menubar.
216*/
217void QQuickPlatformMenuBar::removeMenu(QQuickPlatformMenu *menu)
218{
219 if (!menu || !m_menus.removeOne(t: menu))
220 return;
221
222 m_data.removeOne(t: menu);
223 if (m_handle)
224 m_handle->removeMenu(menu: menu->handle());
225 menu->setMenuBar(nullptr);
226 emit menusChanged();
227}
228
229/*!
230 \qmlmethod void Qt.labs.platform::MenuBar::clear()
231
232 Removes all menus from the menubar.
233*/
234void QQuickPlatformMenuBar::clear()
235{
236 if (m_menus.isEmpty())
237 return;
238
239 for (QQuickPlatformMenu *menu : qAsConst(t&: m_menus)) {
240 m_data.removeOne(t: menu);
241 if (m_handle)
242 m_handle->removeMenu(menu: menu->handle());
243 menu->setMenuBar(nullptr);
244 delete menu;
245 }
246
247 m_menus.clear();
248 emit menusChanged();
249}
250
251void QQuickPlatformMenuBar::classBegin()
252{
253}
254
255void QQuickPlatformMenuBar::componentComplete()
256{
257 m_complete = true;
258 for (QQuickPlatformMenu *menu : qAsConst(t&: m_menus))
259 menu->sync();
260 if (!m_window)
261 setWindow(findWindow());
262}
263
264QWindow *QQuickPlatformMenuBar::findWindow() const
265{
266 QObject *obj = parent();
267 while (obj) {
268 QWindow *window = qobject_cast<QWindow *>(o: obj);
269 if (window)
270 return window;
271 QQuickItem *item = qobject_cast<QQuickItem *>(object: obj);
272 if (item && item->window())
273 return item->window();
274 obj = obj->parent();
275 }
276 return nullptr;
277}
278
279void QQuickPlatformMenuBar::data_append(QQmlListProperty<QObject> *property, QObject *object)
280{
281 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
282 QQuickPlatformMenu *menu = qobject_cast<QQuickPlatformMenu *>(object);
283 if (menu)
284 menuBar->addMenu(menu);
285 else
286 menuBar->m_data.append(t: object);
287}
288
289int QQuickPlatformMenuBar::data_count(QQmlListProperty<QObject> *property)
290{
291 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
292 return menuBar->m_data.count();
293}
294
295QObject *QQuickPlatformMenuBar::data_at(QQmlListProperty<QObject> *property, int index)
296{
297 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
298 return menuBar->m_data.value(i: index);
299}
300
301void QQuickPlatformMenuBar::data_clear(QQmlListProperty<QObject> *property)
302{
303 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
304 menuBar->m_data.clear();
305}
306
307void QQuickPlatformMenuBar::menus_append(QQmlListProperty<QQuickPlatformMenu> *property, QQuickPlatformMenu *menu)
308{
309 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
310 menuBar->addMenu(menu);
311}
312
313int QQuickPlatformMenuBar::menus_count(QQmlListProperty<QQuickPlatformMenu> *property)
314{
315 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
316 return menuBar->m_menus.count();
317}
318
319QQuickPlatformMenu *QQuickPlatformMenuBar::menus_at(QQmlListProperty<QQuickPlatformMenu> *property, int index)
320{
321 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
322 return menuBar->m_menus.value(i: index);
323}
324
325void QQuickPlatformMenuBar::menus_clear(QQmlListProperty<QQuickPlatformMenu> *property)
326{
327 QQuickPlatformMenuBar *menuBar = static_cast<QQuickPlatformMenuBar *>(property->object);
328 menuBar->clear();
329}
330
331QT_END_NAMESPACE
332

source code of qtquickcontrols2/src/imports/platform/qquickplatformmenubar.cpp