Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdbusmenutypes.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
6
7#include <QDBusConnection>
8#include <QDBusMetaType>
9#include <QImage>
10#include <QIcon>
11#include <QImage>
12#include <QPixmap>
13#include <QDebug>
14#include <QtEndian>
15#include <QBuffer>
16#if QT_CONFIG(shortcut)
17# include <private/qkeysequence_p.h>
18#endif
19#include <qpa/qplatformmenu.h>
21
23
24using namespace Qt::StringLiterals;
25
26QT_IMPL_METATYPE_EXTERN(QDBusMenuItem)
27QT_IMPL_METATYPE_EXTERN(QDBusMenuItemList)
28QT_IMPL_METATYPE_EXTERN(QDBusMenuItemKeys)
29QT_IMPL_METATYPE_EXTERN(QDBusMenuItemKeysList)
30QT_IMPL_METATYPE_EXTERN(QDBusMenuLayoutItem)
31QT_IMPL_METATYPE_EXTERN(QDBusMenuLayoutItemList)
32QT_IMPL_METATYPE_EXTERN(QDBusMenuEvent)
33QT_IMPL_METATYPE_EXTERN(QDBusMenuEventList)
34QT_IMPL_METATYPE_EXTERN(QDBusMenuShortcut)
35
36const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItem &item)
37{
38 arg.beginStructure();
39 arg << item.m_id << item.m_properties;
40 arg.endStructure();
41 return arg;
42}
43
44const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItem &item)
45{
46 arg.beginStructure();
47 arg >> item.m_id >> item.m_properties;
48 arg.endStructure();
49 return arg;
50}
51
52const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItemKeys &keys)
53{
54 arg.beginStructure();
55 arg << keys.id << keys.properties;
56 arg.endStructure();
57 return arg;
58}
59
60const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItemKeys &keys)
61{
62 arg.beginStructure();
63 arg >> keys.id >> keys.properties;
64 arg.endStructure();
65 return arg;
66}
67
68uint QDBusMenuLayoutItem::populate(int id, int depth, const QStringList &propertyNames, const QDBusPlatformMenu *topLevelMenu)
69{
70 qCDebug(qLcMenu) << id << "depth" << depth << propertyNames;
71 m_id = id;
72 if (id == 0) {
73 m_properties.insert("children-display"_L1, "submenu"_L1);
74 if (topLevelMenu)
75 populate(topLevelMenu, depth, propertyNames);
76 return 1; // revision
77 }
78
80 if (item) {
81 const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
82
83 if (menu) {
84 if (depth != 0)
85 populate(menu, depth, propertyNames);
86 return menu->revision();
87 }
88 }
89
90 return 1; // revision
91}
92
93void QDBusMenuLayoutItem::populate(const QDBusPlatformMenu *menu, int depth, const QStringList &propertyNames)
94{
95 const auto items = menu->items();
96 for (QDBusPlatformMenuItem *item : items) {
97 QDBusMenuLayoutItem child;
98 child.populate(item, depth - 1, propertyNames);
99 m_children << child;
100 }
101}
102
103void QDBusMenuLayoutItem::populate(const QDBusPlatformMenuItem *item, int depth, const QStringList &propertyNames)
104{
105 m_id = item->dbusID();
106 QDBusMenuItem proxy(item);
107 m_properties = proxy.m_properties;
108
109 const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
110 if (depth != 0 && menu)
111 populate(menu, depth, propertyNames);
112}
113
114const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuLayoutItem &item)
115{
116 arg.beginStructure();
117 arg << item.m_id << item.m_properties;
118 arg.beginArray(qMetaTypeId<QDBusVariant>());
119 for (const QDBusMenuLayoutItem &child : item.m_children)
120 arg << QDBusVariant(QVariant::fromValue<QDBusMenuLayoutItem>(child));
121 arg.endArray();
122 arg.endStructure();
123 return arg;
124}
125
126const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuLayoutItem &item)
127{
128 arg.beginStructure();
129 arg >> item.m_id >> item.m_properties;
130 arg.beginArray();
131 while (!arg.atEnd()) {
132 QDBusVariant dbusVariant;
133 arg >> dbusVariant;
134 QDBusArgument childArgument = qvariant_cast<QDBusArgument>(dbusVariant.variant());
135
137 childArgument >> child;
138 item.m_children.append(child);
139 }
140 arg.endArray();
141 arg.endStructure();
142 return arg;
143}
144
146{
147 qDBusRegisterMetaType<QDBusMenuItem>();
148 qDBusRegisterMetaType<QDBusMenuItemList>();
149 qDBusRegisterMetaType<QDBusMenuItemKeys>();
150 qDBusRegisterMetaType<QDBusMenuItemKeysList>();
151 qDBusRegisterMetaType<QDBusMenuLayoutItem>();
152 qDBusRegisterMetaType<QDBusMenuLayoutItemList>();
153 qDBusRegisterMetaType<QDBusMenuEvent>();
154 qDBusRegisterMetaType<QDBusMenuEventList>();
155 qDBusRegisterMetaType<QDBusMenuShortcut>();
156}
157
159 : m_id(item->dbusID())
160{
161 if (item->isSeparator()) {
162 m_properties.insert("type"_L1, "separator"_L1);
163 } else {
164 m_properties.insert("label"_L1, convertMnemonic(item->text()));
165 if (item->menu())
166 m_properties.insert("children-display"_L1, "submenu"_L1);
167 m_properties.insert("enabled"_L1, item->isEnabled());
168 if (item->isCheckable()) {
169 QString toggleType = item->hasExclusiveGroup() ? "radio"_L1 : "checkmark"_L1;
170 m_properties.insert("toggle-type"_L1, toggleType);
171 m_properties.insert("toggle-state"_L1, item->isChecked() ? 1 : 0);
172 }
173#ifndef QT_NO_SHORTCUT
174 const QKeySequence &scut = item->shortcut();
175 if (!scut.isEmpty()) {
176 QDBusMenuShortcut shortcut = convertKeySequence(scut);
177 m_properties.insert("shortcut"_L1, QVariant::fromValue(shortcut));
178 }
179#endif
180 const QIcon &icon = item->icon();
181 if (!icon.name().isEmpty()) {
182 m_properties.insert("icon-name"_L1, icon.name());
183 } else if (!icon.isNull()) {
184 QBuffer buf;
185 icon.pixmap(16).save(&buf, "PNG");
186 m_properties.insert("icon-data"_L1, buf.data());
187 }
188 }
189 m_properties.insert("visible"_L1, item->isVisible());
190}
191
192QDBusMenuItemList QDBusMenuItem::items(const QList<int> &ids, const QStringList &propertyNames)
193{
194 Q_UNUSED(propertyNames);
196 const QList<const QDBusPlatformMenuItem *> items = QDBusPlatformMenuItem::byIds(ids);
197 ret.reserve(items.size());
198 for (const QDBusPlatformMenuItem *item : items)
199 ret << QDBusMenuItem(item);
200 return ret;
201}
202
203QString QDBusMenuItem::convertMnemonic(const QString &label)
204{
205 // convert only the first occurrence of ampersand which is not at the end
206 // dbusmenu uses underscore instead of ampersand
207 int idx = label.indexOf(u'&');
208 if (idx < 0 || idx == label.size() - 1)
209 return label;
210 QString ret(label);
211 ret[idx] = u'_';
212 return ret;
213}
214
215#ifndef QT_NO_SHORTCUT
216QDBusMenuShortcut QDBusMenuItem::convertKeySequence(const QKeySequence &sequence)
217{
218 QDBusMenuShortcut shortcut;
219 for (int i = 0; i < sequence.count(); ++i) {
220 QStringList tokens;
221 auto modifiers = sequence[i].keyboardModifiers();
222 if (modifiers & Qt::MetaModifier)
223 tokens << QStringLiteral("Super");
224 if (modifiers & Qt::ControlModifier)
225 tokens << QStringLiteral("Control");
226 if (modifiers & Qt::AltModifier)
227 tokens << QStringLiteral("Alt");
228 if (modifiers & Qt::ShiftModifier)
229 tokens << QStringLiteral("Shift");
230 if (modifiers & Qt::KeypadModifier)
231 tokens << QStringLiteral("Num");
232
233 QString keyName = QKeySequencePrivate::keyName(sequence[i].key(), QKeySequence::PortableText);
234 if (keyName == "+"_L1)
235 tokens << QStringLiteral("plus");
236 else if (keyName == "-"_L1)
237 tokens << QStringLiteral("minus");
238 else
239 tokens << keyName;
240 shortcut << tokens;
241 }
242 return shortcut;
243}
244#endif
245
246const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuEvent &ev)
247{
248 arg.beginStructure();
249 arg << ev.m_id << ev.m_eventId << ev.m_data << ev.m_timestamp;
250 arg.endStructure();
251 return arg;
252}
253
254const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuEvent &ev)
255{
256 arg.beginStructure();
257 arg >> ev.m_id >> ev.m_eventId >> ev.m_data >> ev.m_timestamp;
258 arg.endStructure();
259 return arg;
260}
261
262#ifndef QT_NO_DEBUG_STREAM
263QDebug operator<<(QDebug d, const QDBusMenuItem &item)
264{
265 QDebugStateSaver saver(d);
266 d.nospace();
267 d << "QDBusMenuItem(id=" << item.m_id << ", properties=" << item.m_properties << ')';
268 return d;
269}
270
271QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item)
272{
273 QDebugStateSaver saver(d);
274 d.nospace();
275 d << "QDBusMenuLayoutItem(id=" << item.m_id << ", properties=" << item.m_properties << ", " << item.m_children.size() << " children)";
276 return d;
277}
278#endif
279
280QT_END_NAMESPACE
QDBusMenuItem(const QDBusPlatformMenuItem *item)
static void registerDBusTypes()
uint populate(int id, int depth, const QStringList &propertyNames, const QDBusPlatformMenu *topLevelMenu)
void populate(const QDBusPlatformMenuItem *item, int depth, const QStringList &propertyNames)
void populate(const QDBusPlatformMenu *menu, int depth, const QStringList &propertyNames)
static QDBusPlatformMenuItem * byId(int id)
const QDBusArgument & operator>>(const QDBusArgument &arg, QDBusMenuEvent &ev)
QDebug operator<<(QDebug d, const QDBusMenuItem &item)
const QDBusArgument & operator<<(QDBusArgument &arg, const QDBusMenuEvent &ev)
const QDBusArgument & operator>>(const QDBusArgument &arg, QDBusMenuItem &item)
const QDBusArgument & operator<<(QDBusArgument &arg, const QDBusMenuItemKeys &keys)
QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item)
const QDBusArgument & operator>>(const QDBusArgument &arg, QDBusMenuLayoutItem &item)
const QDBusArgument & operator<<(QDBusArgument &arg, const QDBusMenuLayoutItem &item)
const QDBusArgument & operator>>(const QDBusArgument &arg, QDBusMenuItemKeys &keys)
QList< QStringList > QDBusMenuShortcut
QList< QDBusMenuItemKeys > QDBusMenuItemKeysList
QList< QDBusMenuItem > QDBusMenuItemList
QList< QDBusMenuLayoutItem > QDBusMenuLayoutItemList
QList< QDBusMenuEvent > QDBusMenuEventList