-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathmattributeextensionmanager.cpp
More file actions
295 lines (253 loc) · 10.8 KB
/
mattributeextensionmanager.cpp
File metadata and controls
295 lines (253 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/* * This file is part of Maliit framework *
*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* and appearing in the file LICENSE.LGPL included in the packaging
* of this file.
*/
#include "mattributeextensionmanager.h"
#include "logging.h"
#include <maliit/plugins/keyoverridedata.h>
#include <maliit/plugins/keyoverride.h>
#include <QVariant>
#include <QFileInfo>
#include <QFile>
#include <QDebug>
namespace {
const QString DefaultConfigurationPath = QString::fromLatin1(MALIIT_EXTENSIONS_DIR);
const char * const PreferredDomainSettingName(MALIIT_CONFIG_ROOT"preferred_domain");
const char * const DomainItemName("_domain");
const char * const KeysExtensionString("/keys");
const char * const ToolbarExtensionString("/toolbar");
const char * const GlobalExtensionString("/");
const char * const ToolbarIdAttribute = "toolbarId";
const char * const ToolbarAttribute = "toolbar";
const char * const FocusStateAttribute = "focusState";
}
MAttributeExtensionManager::MAttributeExtensionManager()
: copyPasteStatus(Maliit::InputMethodNoCopyPaste)
{
}
MAttributeExtensionManager::~MAttributeExtensionManager()
{
}
QList<MAttributeExtensionId> MAttributeExtensionManager::attributeExtensionIdList() const
{
return attributeExtensions.keys();
}
QSharedPointer<MAttributeExtension> MAttributeExtensionManager::attributeExtension(const MAttributeExtensionId &id) const
{
AttributeExtensionContainer::const_iterator iterator(attributeExtensions.find(id));
if (iterator != attributeExtensions.end())
return iterator.value();
return QSharedPointer<MAttributeExtension>();
}
bool MAttributeExtensionManager::contains(const MAttributeExtensionId &id) const
{
return attributeExtensions.contains(id);
}
void MAttributeExtensionManager::setCopyPasteState(bool copyAvailable, bool pasteAvailable)
{
Maliit::CopyPasteState newStatus = Maliit::InputMethodNoCopyPaste;
if (copyAvailable) {
newStatus = Maliit::InputMethodCopy;
} else if (pasteAvailable) {
newStatus = Maliit::InputMethodPaste;
}
if (copyPasteStatus == newStatus)
return;
copyPasteStatus = newStatus;
switch (newStatus) {
case Maliit::InputMethodNoCopyPaste:
break;
case Maliit::InputMethodCopy:
break;
case Maliit::InputMethodPaste:
break;
}
}
void MAttributeExtensionManager::registerAttributeExtension(const MAttributeExtensionId &id, const QString &fileName)
{
if (!id.isValid() || attributeExtensions.contains(id))
return;
// Only register default extension in the case of empty string.
// Don't register extension if user makes a typo in the file name.
if (!fileName.isEmpty()) {
QString absoluteFileName = fileName;
QFileInfo info(absoluteFileName);
if (info.isRelative())
absoluteFileName = DefaultConfigurationPath + info.fileName();
if (!QFile::exists(absoluteFileName))
return;
}
QSharedPointer<MAttributeExtension> attributeExtension(new MAttributeExtension(id, fileName));
if (attributeExtension) {
attributeExtensions.insert(id, attributeExtension);
}
}
void MAttributeExtensionManager::unregisterAttributeExtension(const MAttributeExtensionId &id)
{
AttributeExtensionContainer::iterator iterator(attributeExtensions.find(id));
if (iterator == attributeExtensions.end()) {
return;
}
attributeExtensions.remove(id);
}
void MAttributeExtensionManager::setToolbarItemAttribute(const MAttributeExtensionId &id,
const QString &itemName,
const QString &attribute,
const QVariant &value)
{
setExtendedAttribute(id, ToolbarExtensionString, itemName,
attribute, value);
}
QMap<QString, QSharedPointer<MKeyOverride> > MAttributeExtensionManager::keyOverrides(
const MAttributeExtensionId &id) const
{
QList<QSharedPointer<MKeyOverride> > overrides;
QSharedPointer<MAttributeExtension> extension = attributeExtension(id);
if (extension) {
overrides = extension->keyOverrideData()->keyOverrides();
}
QMap<QString, QSharedPointer<MKeyOverride> > overridesMap;
Q_FOREACH (const QSharedPointer<MKeyOverride> &override, overrides) {
overridesMap.insert(override->keyId(), override);
}
return overridesMap;
}
void MAttributeExtensionManager::setExtendedAttribute(const MAttributeExtensionId &id,
const QString &target,
const QString &targetItem,
const QString &attribute,
const QVariant &value)
{
if (target == GlobalExtensionString) {
Q_EMIT globalAttributeChanged(id, targetItem, attribute, value);
return;
}
if (!id.isValid() || attribute.isEmpty() || targetItem.isEmpty() || !value.isValid())
return;
QSharedPointer<MAttributeExtension> extension = attributeExtension(id);
if (!extension) {
qCWarning(lcMaliitFw) << "Extended attribute change with invalid id";
return;
}
if (target == KeysExtensionString) {
// create key override if not exist.
bool newKeyOverrideCreated = extension->keyOverrideData()->createKeyOverride(targetItem);
QSharedPointer<MKeyOverride> keyOverride = extension->keyOverrideData()->keyOverride(targetItem);
Q_ASSERT(keyOverride);
const QByteArray byteArray = attribute.toLatin1();
const char * const c_str = byteArray.data();
// Ignore l10n lengthvariants in QStrings for labels, always pick longest variant (first)
if (attribute == "label") {
QString label = value.toString();
label = label.split(QChar(0x9c)).first();
const QVariant newValue(label);
keyOverride->setProperty(c_str, newValue);
} else {
keyOverride->setProperty(c_str, value);
}
// Q_EMIT signal to notify the new key override is created.
if (newKeyOverrideCreated) {
Q_EMIT keyOverrideCreated();
}
} else {
qCWarning(lcMaliitFw) << "Invalid or incompatible attribute extension target:" << target;
}
}
void MAttributeExtensionManager::handleClientDisconnect(unsigned int clientId)
{
// unregister toolbars registered by the lost connection
const QString service(QString::number(clientId));
QSet<MAttributeExtensionId>::iterator i(attributeExtensionIds.begin());
while (i != attributeExtensionIds.end()) {
if ((*i).service() == service) {
unregisterAttributeExtension(*i);
i = attributeExtensionIds.erase(i);
} else {
++i;
}
}
}
void MAttributeExtensionManager::handleExtendedAttributeUpdate(unsigned int clientId, int id,
const QString &target, const QString &targetName,
const QString &attribute, const QVariant &value)
{
MAttributeExtensionId globalId(id, QString::number(clientId));
if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
setExtendedAttribute(globalId, target, targetName, attribute, value);
}
}
void MAttributeExtensionManager::handleAttributeExtensionRegistered(unsigned int clientId,
int id, const QString &attributeExtension)
{
MAttributeExtensionId globalId(id, QString::number(clientId));
if (globalId.isValid() && !attributeExtensionIds.contains(globalId)) {
registerAttributeExtension(globalId, attributeExtension);
attributeExtensionIds.insert(globalId);
}
}
void MAttributeExtensionManager::handleAttributeExtensionUnregistered(unsigned int clientId, int id)
{
MAttributeExtensionId globalId(id, QString::number(clientId));
if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
unregisterAttributeExtension(globalId);
attributeExtensionIds.remove(globalId);
}
}
void MAttributeExtensionManager::handleWidgetStateChanged(unsigned int clientId,
const QMap<QString, QVariant> &newState,
const QMap<QString, QVariant> &oldState,
bool focusChanged)
{
Q_UNUSED(oldState);
// toolbar change
MAttributeExtensionId oldAttributeExtensionId;
MAttributeExtensionId newAttributeExtensionId;
oldAttributeExtensionId = attributeExtensionId;
QVariant variant = newState[ToolbarIdAttribute];
if (variant.isValid()) {
// map toolbar id from local to global
newAttributeExtensionId = MAttributeExtensionId(variant.toInt(), QString::number(clientId));
}
if (!newAttributeExtensionId.isValid()) {
newAttributeExtensionId = MAttributeExtensionId::standardAttributeExtensionId();
}
variant = newState[FocusStateAttribute];
if (not variant.isValid()) {
qCCritical(lcMaliitFw) << Q_FUNC_INFO << "Invalid focus state";
}
bool widgetFocusState = variant.toBool();
// compare the toolbar id (global)
if (oldAttributeExtensionId != newAttributeExtensionId) {
QString toolbarFile = newState[ToolbarAttribute].toString();
if (!contains(newAttributeExtensionId) && !toolbarFile.isEmpty()) {
// register toolbar if toolbar manager does not contain it but
// toolbar file is not empty. This can reload the toolbar data
// if im-uiserver crashes.
// XXX: should not happen, the input context is reponsible for registering
// and resending the toolbar information on server reconnect
qCWarning(lcMaliitFw) << "Unregistered toolbar found in widget information";
variant = newState[ToolbarIdAttribute];
if (variant.isValid()) {
const int toolbarLocalId = variant.toInt();
// FIXME: brittle to call the signal handler directly like this
handleAttributeExtensionRegistered(clientId, toolbarLocalId, toolbarFile);
}
}
Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
// store the new used toolbar id(global).
attributeExtensionId = newAttributeExtensionId;
}
// this happens when we focus on a text widget with no attribute extensions.
else if (focusChanged && widgetFocusState)
{
Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
}
}