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 Templates 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 "qquickplatformmenuitemgroup_p.h" |
38 | #include "qquickplatformmenuitem_p.h" |
39 | |
40 | QT_BEGIN_NAMESPACE |
41 | |
42 | /*! |
43 | \qmltype MenuItemGroup |
44 | \inherits QtObject |
45 | //! \instantiates QQuickPlatformMenuItemGroup |
46 | \inqmlmodule Qt.labs.platform |
47 | \since 5.8 |
48 | \brief A group for managing native menu items. |
49 | |
50 | The MenuItemGroup groups native menu items together. |
51 | |
52 | MenuItemGroup is exclusive by default. In an exclusive menu item |
53 | group, only one item can be checked at any time; checking another |
54 | item automatically unchecks the previously checked one. MenuItemGroup |
55 | can be configured as non-exclusive, which is particularly useful for |
56 | showing, hiding, enabling and disabling items together as a group. |
57 | |
58 | The most straight-forward way to use MenuItemGroup is to assign |
59 | a list of items. |
60 | |
61 | \code |
62 | Menu { |
63 | id: verticalMenu |
64 | title: qsTr("Vertical") |
65 | |
66 | MenuItemGroup { |
67 | id: verticalGroup |
68 | items: verticalMenu.items |
69 | } |
70 | |
71 | MenuItem { text: qsTr("Top"); checkable: true } |
72 | MenuItem { text: qsTr("Center"); checked: true } |
73 | MenuItem { text: qsTr("Bottom"); checkable: true } |
74 | } |
75 | \endcode |
76 | |
77 | The same menu may sometimes contain items that should not be included |
78 | in the same exclusive group. Such cases are best handled using the |
79 | \l {MenuItem::group}{group} property. |
80 | |
81 | \code |
82 | Menu { |
83 | id: horizontalMenu |
84 | title: qsTr("Horizontal") |
85 | |
86 | MenuItemGroup { |
87 | id: horizontalGroup |
88 | } |
89 | |
90 | MenuItem { |
91 | checked: true |
92 | text: qsTr("Left") |
93 | group: horizontalGroup |
94 | } |
95 | MenuItem { |
96 | checkable: true |
97 | text: qsTr("Center") |
98 | group: horizontalGroup |
99 | } |
100 | MenuItem { |
101 | text: qsTr("Right") |
102 | checkable: true |
103 | group: horizontalGroup |
104 | } |
105 | |
106 | MenuItem { separator: true } |
107 | MenuItem { text: qsTr("Justify"); checkable: true } |
108 | MenuItem { text: qsTr("Absolute"); checkable: true } |
109 | } |
110 | \endcode |
111 | |
112 | More advanced use cases can be handled using the addItem() and |
113 | removeItem() methods. |
114 | |
115 | \labs |
116 | |
117 | \sa MenuItem |
118 | */ |
119 | |
120 | /*! |
121 | \qmlsignal Qt.labs.platform::MenuItemGroup::triggered(MenuItem item) |
122 | |
123 | This signal is emitted when an \a item in the group is triggered by the user. |
124 | |
125 | \sa MenuItem::triggered() |
126 | */ |
127 | |
128 | /*! |
129 | \qmlsignal Qt.labs.platform::MenuItemGroup::hovered(MenuItem item) |
130 | |
131 | This signal is emitted when an \a item in the group is hovered by the user. |
132 | |
133 | \sa MenuItem::hovered() |
134 | */ |
135 | |
136 | QQuickPlatformMenuItemGroup::(QObject *parent) |
137 | : QObject(parent), m_enabled(true), m_visible(true), m_exclusive(true), m_checkedItem(nullptr) |
138 | { |
139 | } |
140 | |
141 | QQuickPlatformMenuItemGroup::() |
142 | { |
143 | clear(); |
144 | } |
145 | |
146 | /*! |
147 | \qmlproperty bool Qt.labs.platform::MenuItemGroup::enabled |
148 | |
149 | This property holds whether the group is enabled. The default value is \c true. |
150 | |
151 | The enabled state of the group affects the enabled state of each item in the group, |
152 | except that explicitly disabled items are not enabled even if the group is enabled. |
153 | */ |
154 | bool QQuickPlatformMenuItemGroup::() const |
155 | { |
156 | return m_enabled; |
157 | } |
158 | |
159 | void QQuickPlatformMenuItemGroup::(bool enabled) |
160 | { |
161 | if (m_enabled == enabled) |
162 | return; |
163 | |
164 | m_enabled = enabled; |
165 | emit enabledChanged(); |
166 | |
167 | for (QQuickPlatformMenuItem *item : qAsConst(t&: m_items)) { |
168 | if (item->m_enabled) { |
169 | item->sync(); |
170 | emit item->enabledChanged(); |
171 | } |
172 | } |
173 | } |
174 | |
175 | /*! |
176 | \qmlproperty bool Qt.labs.platform::MenuItemGroup::visible |
177 | |
178 | This property holds whether the group is visible. The default value is \c true. |
179 | |
180 | The visibility of the group affects the visibility of each item in the group, |
181 | except that explicitly hidden items are not visible even if the group is visible. |
182 | */ |
183 | bool QQuickPlatformMenuItemGroup::() const |
184 | { |
185 | return m_visible; |
186 | } |
187 | |
188 | void QQuickPlatformMenuItemGroup::(bool visible) |
189 | { |
190 | if (m_visible == visible) |
191 | return; |
192 | |
193 | m_visible = visible; |
194 | emit visibleChanged(); |
195 | |
196 | for (QQuickPlatformMenuItem *item : qAsConst(t&: m_items)) { |
197 | if (item->m_visible) { |
198 | item->sync(); |
199 | emit item->visibleChanged(); |
200 | } |
201 | } |
202 | } |
203 | |
204 | /*! |
205 | \qmlproperty bool Qt.labs.platform::MenuItemGroup::exclusive |
206 | |
207 | This property holds whether the group is exclusive. The default value is \c true. |
208 | |
209 | In an exclusive menu item group, only one item can be checked at any time; |
210 | checking another item automatically unchecks the previously checked one. |
211 | */ |
212 | bool QQuickPlatformMenuItemGroup::() const |
213 | { |
214 | return m_exclusive; |
215 | } |
216 | |
217 | void QQuickPlatformMenuItemGroup::(bool exclusive) |
218 | { |
219 | if (m_exclusive == exclusive) |
220 | return; |
221 | |
222 | m_exclusive = exclusive; |
223 | emit exclusiveChanged(); |
224 | |
225 | for (QQuickPlatformMenuItem *item : qAsConst(t&: m_items)) |
226 | item->sync(); |
227 | } |
228 | |
229 | /*! |
230 | \qmlproperty MenuItem Qt.labs.platform::MenuItemGroup::checkedItem |
231 | |
232 | This property holds the currently checked item in the group, or \c null if no item is checked. |
233 | */ |
234 | QQuickPlatformMenuItem *QQuickPlatformMenuItemGroup::() const |
235 | { |
236 | return m_checkedItem; |
237 | } |
238 | |
239 | void QQuickPlatformMenuItemGroup::(QQuickPlatformMenuItem *item) |
240 | { |
241 | if (m_checkedItem == item) |
242 | return; |
243 | |
244 | if (m_checkedItem) |
245 | m_checkedItem->setChecked(false); |
246 | |
247 | m_checkedItem = item; |
248 | emit checkedItemChanged(); |
249 | |
250 | if (item) |
251 | item->setChecked(true); |
252 | } |
253 | |
254 | /*! |
255 | \qmlproperty list<MenuItem> Qt.labs.platform::MenuItemGroup::items |
256 | |
257 | This property holds the list of items in the group. |
258 | */ |
259 | QQmlListProperty<QQuickPlatformMenuItem> QQuickPlatformMenuItemGroup::() |
260 | { |
261 | return QQmlListProperty<QQuickPlatformMenuItem>(this, nullptr, items_append, items_count, items_at, items_clear); |
262 | } |
263 | |
264 | /*! |
265 | \qmlmethod void Qt.labs.platform::MenuItemGroup::addItem(MenuItem item) |
266 | |
267 | Adds an \a item to the group. |
268 | */ |
269 | void QQuickPlatformMenuItemGroup::(QQuickPlatformMenuItem *item) |
270 | { |
271 | if (!item || m_items.contains(t: item)) |
272 | return; |
273 | |
274 | m_items.append(t: item); |
275 | item->setGroup(this); |
276 | |
277 | connect(sender: item, signal: &QQuickPlatformMenuItem::checkedChanged, receiver: this, slot: &QQuickPlatformMenuItemGroup::updateCurrent); |
278 | connect(sender: item, signal: &QQuickPlatformMenuItem::triggered, receiver: this, slot: &QQuickPlatformMenuItemGroup::activateItem); |
279 | connect(sender: item, signal: &QQuickPlatformMenuItem::hovered, receiver: this, slot: &QQuickPlatformMenuItemGroup::hoverItem); |
280 | |
281 | if (m_exclusive && item->isChecked()) |
282 | setCheckedItem(item); |
283 | |
284 | emit itemsChanged(); |
285 | } |
286 | |
287 | /*! |
288 | \qmlmethod void Qt.labs.platform::MenuItemGroup::removeItem(MenuItem item) |
289 | |
290 | Removes an \a item from the group. |
291 | */ |
292 | void QQuickPlatformMenuItemGroup::(QQuickPlatformMenuItem *item) |
293 | { |
294 | if (!item || !m_items.contains(t: item)) |
295 | return; |
296 | |
297 | m_items.removeOne(t: item); |
298 | item->setGroup(nullptr); |
299 | |
300 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::checkedChanged, receiver: this, slot: &QQuickPlatformMenuItemGroup::updateCurrent); |
301 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::triggered, receiver: this, slot: &QQuickPlatformMenuItemGroup::activateItem); |
302 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::hovered, receiver: this, slot: &QQuickPlatformMenuItemGroup::hoverItem); |
303 | |
304 | if (m_checkedItem == item) |
305 | setCheckedItem(nullptr); |
306 | |
307 | emit itemsChanged(); |
308 | } |
309 | |
310 | /*! |
311 | \qmlmethod void Qt.labs.platform::MenuItemGroup::clear() |
312 | |
313 | Removes all items from the group. |
314 | */ |
315 | void QQuickPlatformMenuItemGroup::() |
316 | { |
317 | if (m_items.isEmpty()) |
318 | return; |
319 | |
320 | for (QQuickPlatformMenuItem *item : qAsConst(t&: m_items)) { |
321 | item->setGroup(nullptr); |
322 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::checkedChanged, receiver: this, slot: &QQuickPlatformMenuItemGroup::updateCurrent); |
323 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::triggered, receiver: this, slot: &QQuickPlatformMenuItemGroup::activateItem); |
324 | disconnect(sender: item, signal: &QQuickPlatformMenuItem::hovered, receiver: this, slot: &QQuickPlatformMenuItemGroup::hoverItem); |
325 | } |
326 | |
327 | setCheckedItem(nullptr); |
328 | |
329 | m_items.clear(); |
330 | emit itemsChanged(); |
331 | } |
332 | |
333 | QQuickPlatformMenuItem *QQuickPlatformMenuItemGroup::() const |
334 | { |
335 | for (QQuickPlatformMenuItem *item : m_items) { |
336 | if (item->isChecked()) |
337 | return item; |
338 | } |
339 | return nullptr; |
340 | } |
341 | |
342 | void QQuickPlatformMenuItemGroup::() |
343 | { |
344 | if (!m_exclusive) |
345 | return; |
346 | |
347 | QQuickPlatformMenuItem *item = qobject_cast<QQuickPlatformMenuItem*>(object: sender()); |
348 | if (item && item->isChecked()) |
349 | setCheckedItem(item); |
350 | } |
351 | |
352 | void QQuickPlatformMenuItemGroup::() |
353 | { |
354 | QQuickPlatformMenuItem *item = qobject_cast<QQuickPlatformMenuItem*>(object: sender()); |
355 | if (item) |
356 | emit triggered(item); |
357 | } |
358 | |
359 | void QQuickPlatformMenuItemGroup::() |
360 | { |
361 | QQuickPlatformMenuItem *item = qobject_cast<QQuickPlatformMenuItem*>(object: sender()); |
362 | if (item) |
363 | emit hovered(item); |
364 | } |
365 | |
366 | void QQuickPlatformMenuItemGroup::(QQmlListProperty<QQuickPlatformMenuItem> *prop, QQuickPlatformMenuItem *item) |
367 | { |
368 | QQuickPlatformMenuItemGroup *group = static_cast<QQuickPlatformMenuItemGroup *>(prop->object); |
369 | group->addItem(item); |
370 | } |
371 | |
372 | int QQuickPlatformMenuItemGroup::(QQmlListProperty<QQuickPlatformMenuItem> *prop) |
373 | { |
374 | QQuickPlatformMenuItemGroup *group = static_cast<QQuickPlatformMenuItemGroup *>(prop->object); |
375 | return group->m_items.count(); |
376 | } |
377 | |
378 | QQuickPlatformMenuItem *QQuickPlatformMenuItemGroup::(QQmlListProperty<QQuickPlatformMenuItem> *prop, int index) |
379 | { |
380 | QQuickPlatformMenuItemGroup *group = static_cast<QQuickPlatformMenuItemGroup *>(prop->object); |
381 | return group->m_items.value(i: index); |
382 | } |
383 | |
384 | void QQuickPlatformMenuItemGroup::(QQmlListProperty<QQuickPlatformMenuItem> *prop) |
385 | { |
386 | QQuickPlatformMenuItemGroup *group = static_cast<QQuickPlatformMenuItemGroup *>(prop->object); |
387 | group->clear(); |
388 | } |
389 | |
390 | QT_END_NAMESPACE |
391 | |