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 
44 QT_BEGIN_NAMESPACE
45 
46 Q_LOGGING_CATEGORY(qtQpaInputMethods, "qt.qpa.input.methods")
47 Q_LOGGING_CATEGORY(qtQpaInputMethodsSerialize, "qt.qpa.input.methods.serialize")
48 
QIBusSerializable()49 QIBusSerializable::QIBusSerializable()
50 {
51 }
52 
deserializeFrom(const QDBusArgument & argument)53 void 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 
serializeTo(QDBusArgument & argument) const70 void 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 
QIBusAttribute()88 QIBusAttribute::QIBusAttribute()
89     : type(Invalid),
90       value(0),
91       start(0),
92       end(0)
93 {
94     name = "IBusAttribute";
95 }
96 
serializeTo(QDBusArgument & argument) const97 void 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 
deserializeFrom(const QDBusArgument & argument)112 void 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 
format() const128 QTextCharFormat 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 
QIBusAttributeList()168 QIBusAttributeList::QIBusAttributeList()
169 {
170     name = "IBusAttrList";
171 }
172 
serializeTo(QDBusArgument & argument) const173 void 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 
deserializeFrom(const QDBusArgument & arg)190 void 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 
imAttributes() const212 QList<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 
QIBusText()245 QIBusText::QIBusText()
246 {
247     name = "IBusText";
248 }
249 
serializeTo(QDBusArgument & argument) const250 void QIBusText::serializeTo(QDBusArgument &argument) const
251 {
252     argument.beginStructure();
253 
254     QIBusSerializable::serializeTo(argument);
255 
256     argument << text << attributes;
257     argument.endStructure();
258 }
259 
deserializeFrom(const QDBusArgument & argument)260 void 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 
QIBusEngineDesc()276 QIBusEngineDesc::QIBusEngineDesc()
277     : rank(0)
278 {
279     name = "IBusEngineDesc";
280 }
281 
serializeTo(QDBusArgument & argument) const282 void 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 
deserializeFrom(const QDBusArgument & argument)309 void 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;
347 olderThanV2:
348     layout_variant.clear();
349     layout_option.clear();
350 olderThanV3:
351     version.clear();
352 olderThanV4:
353     textdomain.clear();
354 olderThanV5:
355     iconpropkey.clear();
356     // <-- insert new members here (2/2)
357 newest:
358     argument.endStructure();
359 }
360 
361 QT_END_NAMESPACE
362