1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qibustypes.h"
41#include <QtDBus>
42#include <QHash>
43
44QT_BEGIN_NAMESPACE
45
46Q_LOGGING_CATEGORY(qtQpaInputMethods, "qt.qpa.input.methods")
47Q_LOGGING_CATEGORY(qtQpaInputMethodsSerialize, "qt.qpa.input.methods.serialize")
48
49QIBusSerializable::QIBusSerializable()
50{
51}
52
53void QIBusSerializable::deserializeFrom(const QDBusArgument &argument)
54{
55 argument >> name;
56
57 argument.beginMap();
58 while (!argument.atEnd()) {
59 argument.beginMapEntry();
60 QString key;
61 QDBusVariant value;
62 argument >> key;
63 argument >> value;
64 argument.endMapEntry();
65 attachments[key] = qvariant_cast<QDBusArgument>(value.variant());
66 }
67 argument.endMap();
68}
69
70void QIBusSerializable::serializeTo(QDBusArgument &argument) const
71{
72 argument << name;
73
74 argument.beginMap(qMetaTypeId<QString>(), qMetaTypeId<QDBusVariant>());
75
76 for (auto i = attachments.begin(), end = attachments.end(); i != end; ++i) {
77 argument.beginMapEntry();
78 argument << i.key();
79
80 QDBusVariant variant(i.value().asVariant());
81
82 argument << variant;
83 argument.endMapEntry();
84 }
85 argument.endMap();
86}
87
88QIBusAttribute::QIBusAttribute()
89 : type(Invalid),
90 value(0),
91 start(0),
92 end(0)
93{
94 name = "IBusAttribute";
95}
96
97void QIBusAttribute::serializeTo(QDBusArgument &argument) const
98{
99 argument.beginStructure();
100
101 QIBusSerializable::serializeTo(argument);
102
103 quint32 t = (quint32) type;
104 argument << t;
105 argument << value;
106 argument << start;
107 argument << end;
108
109 argument.endStructure();
110}
111
112void QIBusAttribute::deserializeFrom(const QDBusArgument &argument)
113{
114 argument.beginStructure();
115
116 QIBusSerializable::deserializeFrom(argument);
117
118 quint32 t;
119 argument >> t;
120 type = (QIBusAttribute::Type) t;
121 argument >> value;
122 argument >> start;
123 argument >> end;
124
125 argument.endStructure();
126}
127
128QTextCharFormat QIBusAttribute::format() const
129{
130 QTextCharFormat fmt;
131 switch (type) {
132 case Invalid:
133 break;
134 case Underline: {
135 QTextCharFormat::UnderlineStyle style = QTextCharFormat::NoUnderline;
136
137 switch (value) {
138 case UnderlineNone:
139 break;
140 case UnderlineSingle:
141 style = QTextCharFormat::SingleUnderline;
142 break;
143 case UnderlineDouble:
144 style = QTextCharFormat::DashUnderline;
145 break;
146 case UnderlineLow:
147 style = QTextCharFormat::DashDotLine;
148 break;
149 case UnderlineError:
150 style = QTextCharFormat::WaveUnderline;
151 fmt.setUnderlineColor(Qt::red);
152 break;
153 }
154
155 fmt.setUnderlineStyle(style);
156 break;
157 }
158 case Foreground:
159 fmt.setForeground(QColor(value));
160 break;
161 case Background:
162 fmt.setBackground(QColor(value));
163 break;
164 }
165 return fmt;
166}
167
168QIBusAttributeList::QIBusAttributeList()
169{
170 name = "IBusAttrList";
171}
172
173void QIBusAttributeList::serializeTo(QDBusArgument &argument) const
174{
175 argument.beginStructure();
176
177 QIBusSerializable::serializeTo(argument);
178
179 argument.beginArray(qMetaTypeId<QDBusVariant>());
180 for (int i = 0; i < attributes.size(); ++i) {
181 QVariant variant;
182 variant.setValue(attributes.at(i));
183 argument << QDBusVariant (variant);
184 }
185 argument.endArray();
186
187 argument.endStructure();
188}
189
190void QIBusAttributeList::deserializeFrom(const QDBusArgument &arg)
191{
192 qCDebug(qtQpaInputMethodsSerialize) << "QIBusAttributeList::fromDBusArgument()" << arg.currentSignature();
193
194 arg.beginStructure();
195
196 QIBusSerializable::deserializeFrom(arg);
197
198 arg.beginArray();
199 while (!arg.atEnd()) {
200 QDBusVariant var;
201 arg >> var;
202
203 QIBusAttribute attr;
204 qvariant_cast<QDBusArgument>(var.variant()) >> attr;
205 attributes.append(std::move(attr));
206 }
207 arg.endArray();
208
209 arg.endStructure();
210}
211
212QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
213{
214 QHash<QPair<int, int>, QTextCharFormat> rangeAttrs;
215 const int numAttributes = attributes.size();
216
217 // Merge text fomats for identical ranges into a single QTextFormat.
218 for (int i = 0; i < numAttributes; ++i) {
219 const QIBusAttribute &attr = attributes.at(i);
220 const QTextCharFormat &format = attr.format();
221
222 if (format.isValid()) {
223 const QPair<int, int> range(attr.start, attr.end);
224 rangeAttrs[range].merge(format);
225 }
226 }
227
228 // Assemble list in original attribute order.
229 QList<QInputMethodEvent::Attribute> imAttrs;
230 imAttrs.reserve(numAttributes);
231
232 for (int i = 0; i < numAttributes; ++i) {
233 const QIBusAttribute &attr = attributes.at(i);
234 const QTextFormat &format = attr.format();
235
236 imAttrs += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
237 attr.start,
238 attr.end - attr.start,
239 format.isValid() ? rangeAttrs[QPair<int, int>(attr.start, attr.end)] : format);
240 }
241
242 return imAttrs;
243}
244
245QIBusText::QIBusText()
246{
247 name = "IBusText";
248}
249
250void QIBusText::serializeTo(QDBusArgument &argument) const
251{
252 argument.beginStructure();
253
254 QIBusSerializable::serializeTo(argument);
255
256 argument << text << attributes;
257 argument.endStructure();
258}
259
260void QIBusText::deserializeFrom(const QDBusArgument &argument)
261{
262 qCDebug(qtQpaInputMethodsSerialize) << "QIBusText::fromDBusArgument()" << argument.currentSignature();
263
264 argument.beginStructure();
265
266 QIBusSerializable::deserializeFrom(argument);
267
268 argument >> text;
269 QDBusVariant variant;
270 argument >> variant;
271 qvariant_cast<QDBusArgument>(variant.variant()) >> attributes;
272
273 argument.endStructure();
274}
275
276QIBusEngineDesc::QIBusEngineDesc()
277 : rank(0)
278{
279 name = "IBusEngineDesc";
280}
281
282void QIBusEngineDesc::serializeTo(QDBusArgument &argument) const
283{
284 argument.beginStructure();
285
286 QIBusSerializable::serializeTo(argument);
287
288 argument << engine_name;
289 argument << longname;
290 argument << description;
291 argument << language;
292 argument << license;
293 argument << author;
294 argument << icon;
295 argument << layout;
296 argument << rank;
297 argument << hotkeys;
298 argument << symbol;
299 argument << setup;
300 argument << layout_variant;
301 argument << layout_option;
302 argument << version;
303 argument << textdomain;
304 argument << iconpropkey;
305
306 argument.endStructure();
307}
308
309void QIBusEngineDesc::deserializeFrom(const QDBusArgument &argument)
310{
311 qCDebug(qtQpaInputMethodsSerialize) << "QIBusEngineDesc::fromDBusArgument()" << argument.currentSignature();
312 argument.beginStructure();
313
314 QIBusSerializable::deserializeFrom(argument);
315
316 argument >> engine_name;
317 argument >> longname;
318 argument >> description;
319 argument >> language;
320 argument >> license;
321 argument >> author;
322 argument >> icon;
323 argument >> layout;
324 argument >> rank;
325 argument >> hotkeys;
326 argument >> symbol;
327 argument >> setup;
328 // Previous IBusEngineDesc supports the arguments between engine_name
329 // and setup.
330 if (argument.currentSignature() == "")
331 goto olderThanV2;
332 argument >> layout_variant;
333 argument >> layout_option;
334 // Previous IBusEngineDesc supports the arguments between engine_name
335 // and layout_option.
336 if (argument.currentSignature() == "")
337 goto olderThanV3;
338 argument >> version;
339 if (argument.currentSignature() == "")
340 goto olderThanV4;
341 argument >> textdomain;
342 if (argument.currentSignature() == "")
343 goto olderThanV5;
344 argument >> iconpropkey;
345 // <-- insert new member streaming here (1/2)
346 goto newest;
347olderThanV2:
348 layout_variant.clear();
349 layout_option.clear();
350olderThanV3:
351 version.clear();
352olderThanV4:
353 textdomain.clear();
354olderThanV5:
355 iconpropkey.clear();
356 // <-- insert new members here (2/2)
357newest:
358 argument.endStructure();
359}
360
361QT_END_NAMESPACE
362