1 /*
2 SPDX-FileCopyrightText: 2009 Wang Hoi <zealot.hoi@gmail.com>
3 SPDX-FileCopyrightText: 2011 Weng Xuetian <wengxt@gmail.com>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "kimpanelagent.h"
9 #include "impaneladaptor.h"
10
11 // Qt
12 #include <QByteArray>
13 #include <QDBusServiceWatcher>
14 #include <QList>
15 #include <QMap>
16 #include <QString>
17 #include <QVariant>
18
19 int PanelAgent::m_connectionIndex = 0;
20
PanelAgent(QObject * parent)21 PanelAgent::PanelAgent(QObject *parent)
22 : QObject(parent)
23 , m_adaptor(new ImpanelAdaptor(this))
24 , m_adaptor2(new Impanel2Adaptor(this))
25 , m_watcher(new QDBusServiceWatcher(this))
26 , m_connection(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("kimpanel_bus_%0").arg(++m_connectionIndex)))
27 {
28 m_watcher->setConnection(QDBusConnection::sessionBus());
29 m_watcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
30 m_connection.registerObject(QStringLiteral("/org/kde/impanel"), this);
31 m_connection.registerService(QStringLiteral("org.kde.impanel"));
32
33 // directly connect to corresponding signal
34 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("Enable"), this, SIGNAL(enable(bool)));
35 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("ShowPreedit"), this, SIGNAL(showPreedit(bool)));
36 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("ShowAux"), this, SIGNAL(showAux(bool)));
37 m_connection
38 .connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("ShowLookupTable"), this, SIGNAL(showLookupTable(bool)));
39 m_connection.connect(QString(),
40 QString(),
41 QStringLiteral("org.kde.kimpanel.inputmethod"),
42 QStringLiteral("UpdateLookupTableCursor"),
43 this,
44 SIGNAL(updateLookupTableCursor(int)));
45
46 // do some serialization
47 m_connection.connect(QString(),
48 QString(),
49 QStringLiteral("org.kde.kimpanel.inputmethod"),
50 QStringLiteral("UpdateLookupTable"),
51 this,
52 SLOT(UpdateLookupTable(QStringList, QStringList, QStringList, bool, bool)));
53 m_connection.connect(QString(),
54 QString(),
55 QStringLiteral("org.kde.kimpanel.inputmethod"),
56 QStringLiteral("UpdatePreeditCaret"),
57 this,
58 SIGNAL(updatePreeditCaret(int)));
59 m_connection.connect(QString(),
60 QString(),
61 QStringLiteral("org.kde.kimpanel.inputmethod"),
62 QStringLiteral("UpdatePreeditText"),
63 this,
64 SLOT(UpdatePreeditText(QString, QString)));
65 m_connection
66 .connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("UpdateAux"), this, SLOT(UpdateAux(QString, QString)));
67 m_connection.connect(QString(),
68 QString(),
69 QStringLiteral("org.kde.kimpanel.inputmethod"),
70 QStringLiteral("UpdateSpotLocation"),
71 this,
72 SIGNAL(updateSpotLocation(int, int)));
73 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("UpdateScreen"), this, SLOT(UpdateScreen(int)));
74 m_connection
75 .connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("UpdateProperty"), this, SLOT(UpdateProperty(QString)));
76 m_connection.connect(QString(),
77 QString(),
78 QStringLiteral("org.kde.kimpanel.inputmethod"),
79 QStringLiteral("RegisterProperties"),
80 this,
81 SLOT(RegisterProperties(QStringList)));
82 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("ExecDialog"), this, SLOT(ExecDialog(QString)));
83 m_connection.connect(QString(), QString(), QStringLiteral("org.kde.kimpanel.inputmethod"), QStringLiteral("ExecMenu"), this, SLOT(ExecMenu(QStringList)));
84
85 connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &PanelAgent::serviceUnregistered);
86 }
87
~PanelAgent()88 PanelAgent::~PanelAgent()
89 {
90 // destructor
91 QDBusConnection::disconnectFromBus(m_connection.name());
92 }
93
serviceUnregistered(const QString & service)94 void PanelAgent::serviceUnregistered(const QString &service)
95 {
96 if (service == m_currentService) {
97 m_watcher->setWatchedServices(QStringList());
98 m_cachedProps.clear();
99 m_currentService = QString();
100 Q_EMIT showAux(false);
101 Q_EMIT showPreedit(false);
102 Q_EMIT showLookupTable(false);
103 Q_EMIT registerProperties(QList<KimpanelProperty>());
104 }
105 }
106
configure()107 void PanelAgent::configure()
108 {
109 Q_EMIT Configure();
110 }
111
lookupTablePageDown()112 void PanelAgent::lookupTablePageDown()
113 {
114 Q_EMIT LookupTablePageDown();
115 }
116
lookupTablePageUp()117 void PanelAgent::lookupTablePageUp()
118 {
119 Q_EMIT LookupTablePageUp();
120 }
121
movePreeditCaret(int pos)122 void PanelAgent::movePreeditCaret(int pos)
123 {
124 Q_EMIT MovePreeditCaret(pos);
125 }
126
triggerProperty(const QString & key)127 void PanelAgent::triggerProperty(const QString &key)
128 {
129 Q_EMIT TriggerProperty(key);
130 }
131
selectCandidate(int idx)132 void PanelAgent::selectCandidate(int idx)
133 {
134 Q_EMIT SelectCandidate(idx);
135 }
136
String2AttrList(const QString & str)137 static QList<TextAttribute> String2AttrList(const QString &str)
138 {
139 QList<TextAttribute> result;
140 if (str.isEmpty()) {
141 return result;
142 }
143 foreach (const QString &s, str.split(QLatin1Char(';'))) {
144 TextAttribute attr;
145 QStringList list = s.split(QLatin1Char(':'));
146 if (list.size() < 4)
147 continue;
148 switch (list.at(0).toInt()) {
149 case 0:
150 attr.type = TextAttribute::None;
151 break;
152 case 1:
153 attr.type = TextAttribute::Decorate;
154 break;
155 case 2:
156 attr.type = TextAttribute::Foreground;
157 break;
158 case 3:
159 attr.type = TextAttribute::Background;
160 break;
161 default:
162 attr.type = TextAttribute::None;
163 }
164 attr.start = list.at(1).toInt();
165 attr.length = list.at(2).toInt();
166 attr.value = list.at(3).toInt();
167 result << attr;
168 }
169 return result;
170 }
171
String2Property(const QString & str)172 static KimpanelProperty String2Property(const QString &str)
173 {
174 KimpanelProperty result;
175
176 QStringList list = str.split(QLatin1Char(':'));
177
178 if (list.size() < 4)
179 return result;
180
181 result.key = list.at(0);
182 result.label = list.at(1);
183 result.icon = list.at(2);
184 result.tip = list.at(3);
185 result.hint = list.size() > 4 ? list.at(4) : QString();
186
187 return result;
188 }
189
Args2LookupTable(const QStringList & labels,const QStringList & candis,const QStringList & attrs,bool has_prev,bool has_next)190 static KimpanelLookupTable Args2LookupTable(const QStringList &labels, const QStringList &candis, const QStringList &attrs, bool has_prev, bool has_next)
191 {
192 Q_ASSERT(labels.size() == candis.size());
193 Q_ASSERT(labels.size() == attrs.size());
194
195 KimpanelLookupTable result;
196
197 for (int i = 0; i < labels.size(); i++) {
198 KimpanelLookupTable::Entry entry;
199
200 entry.label = labels.at(i);
201 entry.text = candis.at(i);
202 entry.attr = String2AttrList(attrs.at(i));
203
204 result.entries << entry;
205 }
206
207 result.has_prev = has_prev;
208 result.has_next = has_next;
209 return result;
210 }
211
created()212 void PanelAgent::created()
213 {
214 Q_EMIT PanelCreated();
215 Q_EMIT PanelCreated2();
216 }
217
exit()218 void PanelAgent::exit()
219 {
220 Q_EMIT Exit();
221 }
222
reloadConfig()223 void PanelAgent::reloadConfig()
224 {
225 Q_EMIT ReloadConfig();
226 }
227
UpdateLookupTable(const QStringList & labels,const QStringList & candis,const QStringList & attrlists,bool has_prev,bool has_next)228 void PanelAgent::UpdateLookupTable(const QStringList &labels, const QStringList &candis, const QStringList &attrlists, bool has_prev, bool has_next)
229 {
230 Q_EMIT updateLookupTable(Args2LookupTable(labels, candis, attrlists, has_prev, has_next));
231 }
232
UpdatePreeditText(const QString & text,const QString & attr)233 void PanelAgent::UpdatePreeditText(const QString &text, const QString &attr)
234 {
235 Q_EMIT updatePreeditText(text, String2AttrList(attr));
236 }
237
UpdateAux(const QString & text,const QString & attr)238 void PanelAgent::UpdateAux(const QString &text, const QString &attr)
239 {
240 Q_EMIT updateAux(text, String2AttrList(attr));
241 }
242
UpdateScreen(int screen_id)243 void PanelAgent::UpdateScreen(int screen_id)
244 {
245 Q_UNUSED(screen_id);
246 }
247
UpdateProperty(const QString & prop)248 void PanelAgent::UpdateProperty(const QString &prop)
249 {
250 Q_EMIT updateProperty(String2Property(prop));
251 }
252
RegisterProperties(const QStringList & props)253 void PanelAgent::RegisterProperties(const QStringList &props)
254 {
255 const QDBusMessage &msg = message();
256 if (msg.service() != m_currentService) {
257 m_watcher->removeWatchedService(m_currentService);
258 if (m_currentService.isEmpty()) {
259 Q_EMIT PanelRegistered();
260 }
261 m_currentService = msg.service();
262 m_watcher->addWatchedService(m_currentService);
263 }
264 if (m_cachedProps != props) {
265 m_cachedProps = props;
266 QList<KimpanelProperty> list;
267 foreach (const QString &prop, props) {
268 list << String2Property(prop);
269 }
270
271 Q_EMIT registerProperties(list);
272 }
273 }
274
ExecDialog(const QString & prop)275 void PanelAgent::ExecDialog(const QString &prop)
276 {
277 Q_EMIT execDialog(String2Property(prop));
278 }
279
ExecMenu(const QStringList & entries)280 void PanelAgent::ExecMenu(const QStringList &entries)
281 {
282 QList<KimpanelProperty> list;
283 foreach (const QString &entry, entries) {
284 list << String2Property(entry);
285 }
286
287 Q_EMIT execMenu(list);
288 }
289
SetSpotRect(int x,int y,int w,int h)290 void PanelAgent::SetSpotRect(int x, int y, int w, int h)
291 {
292 Q_EMIT updateSpotRect(x, y, w, h);
293 }
294
SetLookupTable(const QStringList & labels,const QStringList & candis,const QStringList & attrlists,bool hasPrev,bool hasNext,int cursor,int layout)295 void PanelAgent::SetLookupTable(const QStringList &labels,
296 const QStringList &candis,
297 const QStringList &attrlists,
298 bool hasPrev,
299 bool hasNext,
300 int cursor,
301 int layout)
302 {
303 Q_EMIT updateLookupTableFull(Args2LookupTable(labels, candis, attrlists, hasPrev, hasNext), cursor, layout);
304 }
305