33
33
#define LAYOUTS_DIR "/usr/share/maliit/plugins/com/ubuntu/languages"
35
void managerLoaded(GObject *object,
35
39
LanguagePlugin::LanguagePlugin(QObject *parent) :
37
m_languageLocales(NULL),
38
m_languageNames(NULL),
39
m_languageCodes(NULL),
40
m_indicesByBcp47Name(NULL),
41
m_indicesByLocaleName(NULL),
42
41
m_currentLanguage(-1),
43
42
m_nextCurrentLanguage(-1),
43
m_manager(act_user_manager_get_default()),
46
m_maliitSettings(NULL),
47
m_keyboardLayouts(NULL),
48
m_keyboardLayoutsModel(NULL),
49
m_spellCheckingModel(NULL)
45
m_maliitSettings(g_settings_new(UBUNTU_KEYBOARD_SCHEMA_ID))
47
if (m_manager != NULL) {
48
g_object_ref(m_manager);
51
g_object_get(m_manager, "is-loaded", &loaded, NULL);
56
g_signal_connect(m_manager, "notify::is-loaded", G_CALLBACK(::managerLoaded), this);
59
updateLanguageLocales();
60
updateCurrentLanguage();
61
updateKeyboardLayouts();
62
updateKeyboardLayoutsModel();
63
updateSpellCheckingModel();
53
66
LanguagePlugin::~LanguagePlugin()
55
delete m_languageLocales;
56
delete m_languageNames;
57
delete m_languageCodes;
58
delete m_indicesByBcp47Name;
59
delete m_indicesByLocaleName;
61
if (m_manager != NULL) {
62
g_signal_handlers_disconnect_by_data(m_manager, this);
63
g_object_unref(m_manager);
66
68
if (m_user != NULL) {
67
69
g_signal_handlers_disconnect_by_data(m_user, this);
68
70
g_object_unref(m_user);
71
if (m_maliitSettings != NULL)
73
if (m_manager != NULL) {
74
g_signal_handlers_disconnect_by_data(m_manager, this);
75
g_object_unref(m_manager);
78
if (m_maliitSettings != NULL) {
79
g_signal_handlers_disconnect_by_data(m_maliitSettings, this);
72
80
g_object_unref(m_maliitSettings);
74
for (QList<KeyboardLayout *>::const_iterator i(m_keyboardLayouts->begin()); i != m_keyboardLayouts->end(); ++i)
83
for (QList<KeyboardLayout *>::const_iterator i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i)
77
delete m_keyboardLayouts;
78
delete m_keyboardLayoutsModel;
79
delete m_spellCheckingModel;
82
87
const QStringList &
83
88
LanguagePlugin::languageNames() const
86
return *m_languageNames;
90
return m_languageNames;
89
93
const QStringList &
90
94
LanguagePlugin::languageCodes() const
93
return *m_languageCodes;
96
return m_languageCodes;
97
100
LanguagePlugin::currentLanguage() const
99
if (m_currentLanguage < 0) {
100
ActUserManager *manager(act_user_manager_get_default());
102
if (manager != NULL) {
104
g_object_get(manager, "is-loaded", &loaded, NULL);
107
const char *name(qPrintable(qgetenv("USER")));
109
if (name != NULL && name[0] != '\0') {
110
ActUser *user(act_user_manager_get_user(manager, name));
112
if (user != NULL && act_user_is_loaded(user)) {
113
const char *language(act_user_get_language(user));
114
m_currentLanguage = indexForLanguage(language);
116
if (m_currentLanguage < 0) {
117
QLocale locale(language);
118
m_currentLanguage = indexForLocale(locale);
120
if (m_currentLanguage < 0) {
121
locale = QLocale(locale.language());
122
m_currentLanguage = indexForLocale(locale);
131
if (m_currentLanguage < 0) {
132
QLocale locale(QLocale::system());
133
m_currentLanguage = indexForLocale(locale);
135
if (m_currentLanguage < 0) {
136
locale = QLocale(locale.language());
137
m_currentLanguage = indexForLocale(locale);
141
102
return m_currentLanguage;
145
LanguagePlugin::userSetCurrentLanguage(ActUser *user)
147
if (act_user_is_loaded(user)) {
148
if (m_user != NULL) {
149
g_signal_handlers_disconnect_by_data(m_user, this);
150
g_object_unref(m_user);
154
if (m_nextCurrentLanguage != m_currentLanguage) {
155
QString languageCode(languageCodes()[m_nextCurrentLanguage]);
156
act_user_set_language(user, qPrintable(languageCode.left(languageCode.indexOf('.'))));
157
act_user_set_formats_locale(user, qPrintable(languageCode));
158
m_currentLanguage = m_nextCurrentLanguage;
159
Q_EMIT currentLanguageChanged();
165
userSetCurrentLanguage(GObject *object,
171
LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data));
172
plugin->userSetCurrentLanguage(ACT_USER(object));
176
LanguagePlugin::managerSetCurrentLanguage(ActUserManager *manager)
179
g_object_get(manager, "is-loaded", &loaded, NULL);
182
if (m_manager != NULL) {
183
g_signal_handlers_disconnect_by_data(m_manager, this);
184
g_object_unref(m_manager);
188
const char *name(qPrintable(qgetenv("USER")));
190
if (name != NULL && name[0] != '\0') {
191
ActUser *user(act_user_manager_get_user(manager, name));
194
if (act_user_is_loaded(user))
195
userSetCurrentLanguage(user);
197
m_user = static_cast<ActUser *>(g_object_ref(user));
198
g_signal_connect(user, "notify::is-loaded", G_CALLBACK(::userSetCurrentLanguage), this);
206
managerSetCurrentLanguage(GObject *object,
212
LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data));
213
plugin->managerSetCurrentLanguage(ACT_USER_MANAGER(object));
217
106
LanguagePlugin::setCurrentLanguage(int index)
219
if (index >= 0 && index < languageLocales().length()) {
220
ActUserManager *manager(act_user_manager_get_default());
222
if (manager != NULL) {
223
m_nextCurrentLanguage = index;
226
g_object_get(manager, "is-loaded", &loaded, NULL);
229
managerSetCurrentLanguage(manager);
231
m_manager = static_cast<ActUserManager *>(g_object_ref(manager));
232
g_signal_connect(manager, "notify::is-loaded", G_CALLBACK(::managerSetCurrentLanguage), this);
108
if (index >= 0 && index < m_languageLocales.length()) {
109
m_nextCurrentLanguage = index;
111
updateCurrentLanguage();
239
116
LanguagePlugin::keyboardLayoutsModel()
241
if (m_keyboardLayoutsModel == NULL) {
242
QVariantList superset;
244
for (QList<KeyboardLayout *>::const_iterator i(keyboardLayouts().begin()); i != keyboardLayouts().end(); ++i) {
245
QVariantList element;
247
if (!(*i)->displayName().isEmpty())
248
element += (*i)->displayName();
250
element += (*i)->name();
252
element += (*i)->shortName();
253
superset += QVariant(element);
257
const gchar *language;
260
g_settings_get(maliitSettings(), KEY_ENABLED_LAYOUTS, "as", &iter);
262
while (g_variant_iter_next(iter, "&s", &language)) {
263
for (int i(0); i < keyboardLayouts().length(); i++) {
264
if (keyboardLayouts()[i]->name() == language) {
271
g_variant_iter_free(iter);
273
QStringList customRoles;
274
customRoles += "language";
275
customRoles += "icon";
277
m_keyboardLayoutsModel = new SubsetModel();
278
m_keyboardLayoutsModel->setCustomRoles(customRoles);
279
m_keyboardLayoutsModel->setSuperset(superset);
280
m_keyboardLayoutsModel->setSubset(subset);
281
m_keyboardLayoutsModel->setAllowEmpty(false);
283
connect(m_keyboardLayoutsModel, SIGNAL(subsetChanged()), SLOT(updateKeyboardLayouts()));
286
return m_keyboardLayoutsModel;
118
return &m_keyboardLayoutsModel;
290
LanguagePlugin::updateKeyboardLayouts()
122
LanguagePlugin::keyboardLayoutsModelChanged()
292
124
GVariantBuilder builder;
293
125
GVariant *currentLayouts;
295
127
g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
297
for (QList<int>::const_iterator i(keyboardLayoutsModel()->subset().begin()); i != keyboardLayoutsModel()->subset().end(); ++i)
298
g_variant_builder_add(&builder, "s", qPrintable(keyboardLayouts()[*i]->name()));
129
for (QList<int>::const_iterator i(m_keyboardLayoutsModel.subset().begin()); i != m_keyboardLayoutsModel.subset().end(); ++i)
130
g_variant_builder_add(&builder, "s", qPrintable(m_keyboardLayouts[*i]->name()));
300
132
currentLayouts = g_variant_ref_sink(g_variant_builder_end(&builder));
301
g_settings_set_value(maliitSettings(), KEY_ENABLED_LAYOUTS, currentLayouts);
133
g_settings_set_value(m_maliitSettings, KEY_ENABLED_LAYOUTS, currentLayouts);
302
134
g_variant_unref(currentLayouts);
320
152
LanguagePlugin::spellCheckingModel()
322
if (m_spellCheckingModel == NULL) {
323
// TODO: populate spell checking model
324
QVariantList superset;
326
for (QStringList::const_iterator i(languageNames().begin()); i != languageNames().end(); ++i) {
327
QVariantList element;
329
superset += QVariant(element);
332
m_spellCheckingModel = new SubsetModel();
333
m_spellCheckingModel->setCustomRoles(QStringList("language"));
334
m_spellCheckingModel->setSuperset(superset);
335
m_spellCheckingModel->setSubset(QList<int>());
336
m_spellCheckingModel->setAllowEmpty(false);
338
connect(m_spellCheckingModel, SIGNAL(subsetChanged()), SLOT(updateSpellChecking()));
341
return m_spellCheckingModel;
154
return &m_spellCheckingModel;
345
LanguagePlugin::updateSpellChecking()
158
LanguagePlugin::spellCheckingModelChanged()
347
// TODO: update spell checking
160
// TODO: update spell checking model
351
164
LanguagePlugin::autoCapitalization() const
353
return g_settings_get_boolean(maliitSettings(), KEY_AUTO_CAPITALIZATION);
166
return g_settings_get_boolean(m_maliitSettings, KEY_AUTO_CAPITALIZATION);
357
170
LanguagePlugin::setAutoCapitalization(bool value)
359
172
if (value != autoCapitalization()) {
360
g_settings_set_boolean(maliitSettings(), KEY_AUTO_CAPITALIZATION, value);
173
g_settings_set_boolean(m_maliitSettings, KEY_AUTO_CAPITALIZATION, value);
361
174
Q_EMIT autoCapitalizationChanged();
422
235
return name0 < name1;
425
const QList<QLocale> &
426
LanguagePlugin::languageLocales() const
428
if (m_languageLocales == NULL) {
429
delete m_languageNames;
430
delete m_languageCodes;
431
delete m_indicesByBcp47Name;
432
delete m_indicesByLocaleName;
434
m_languageLocales = new QList<QLocale>;
435
m_languageNames = new QStringList;
436
m_languageCodes = new QStringList;
437
m_indicesByBcp47Name = new QHash<QString, unsigned int>;
438
m_indicesByLocaleName = new QHash<QString, unsigned int>;
440
QProcess localeProcess;
441
localeProcess.start("locale", QStringList("-a"), QIODevice::ReadOnly);
442
localeProcess.waitForFinished();
444
QString localeOutput(localeProcess.readAllStandardOutput());
445
QStringList localeNames(localeOutput.split(QRegExp("\\s+")));
446
QHash<QString, QString> localeNamesByBcp47Name;
447
QHash<QString, unsigned int> countsByLanguage;
449
for (QStringList::const_iterator i(localeNames.begin()); i != localeNames.end(); ++i) {
450
QLocale locale(i->left(i->indexOf('.')));
451
QString bcp47Name(locale.bcp47Name());
452
QString language(locale.nativeLanguageName());
454
if (!language.isEmpty() && !localeNamesByBcp47Name.contains(bcp47Name)) {
455
*m_languageLocales += locale;
456
localeNamesByBcp47Name[bcp47Name] = *i;
457
countsByLanguage[language]++;
461
qSort(m_languageLocales->begin(), m_languageLocales->end(), compareLocales);
463
for (int i(0); i < m_languageLocales->length(); i++) {
464
const QLocale &locale((*m_languageLocales)[i]);
465
QString bcp47Name(locale.bcp47Name());
466
QString language(locale.nativeLanguageName());
467
unsigned int count(countsByLanguage[language]);
470
*m_languageNames += QString("%1 - %2").arg(language).arg(locale.nativeCountryName());
472
*m_languageNames += language;
474
*m_languageCodes += localeNamesByBcp47Name[bcp47Name];
475
(*m_indicesByBcp47Name)[bcp47Name] = i;
476
(*m_indicesByLocaleName)[localeNamesByBcp47Name[bcp47Name]] = i;
480
return *m_languageLocales;
484
LanguagePlugin::indexForLocale(const QLocale &locale) const
487
return m_indicesByBcp47Name->value(locale.bcp47Name(), -1);
491
LanguagePlugin::indexForLanguage(const QString &language) const
494
return m_indicesByLocaleName->value(language, -1);
498
LanguagePlugin::maliitSettings() const
500
if (m_maliitSettings == NULL)
501
m_maliitSettings = g_settings_new(UBUNTU_KEYBOARD_SCHEMA_ID);
503
return m_maliitSettings;
507
239
compareLayouts(const KeyboardLayout *layout0,
508
240
const KeyboardLayout *layout1)
523
255
return name0 < name1;
526
const QList<KeyboardLayout *> &
527
LanguagePlugin::keyboardLayouts() const
529
if (m_keyboardLayouts == NULL) {
530
m_keyboardLayouts = new QList<KeyboardLayout *>;
532
QDir layoutsDir(LAYOUTS_DIR);
533
layoutsDir.setFilter(QDir::Files);
534
layoutsDir.setNameFilters(QStringList("*.xml"));
535
layoutsDir.setSorting(QDir::Name);
537
QFileInfoList fileInfoList(layoutsDir.entryInfoList());
539
for (QFileInfoList::const_iterator i(fileInfoList.begin()); i != fileInfoList.end(); ++i) {
540
KeyboardLayout *layout(new KeyboardLayout(*i));
542
if (!layout->language().isEmpty())
543
*m_keyboardLayouts += layout;
548
qSort(m_keyboardLayouts->begin(), m_keyboardLayouts->end(), compareLayouts);
551
return *m_keyboardLayouts;
259
LanguagePlugin::updateLanguageLocales()
261
m_languageLocales.clear();
262
m_languageNames.clear();
263
m_languageCodes.clear();
264
m_indicesByBcp47Name.clear();
265
m_indicesByLocaleName.clear();
267
QProcess localeProcess;
268
localeProcess.start("locale", QStringList("-a"), QIODevice::ReadOnly);
269
localeProcess.waitForFinished();
271
QString localeOutput(localeProcess.readAllStandardOutput());
272
QStringList localeNames(localeOutput.split(QRegExp("\\s+")));
273
QHash<QString, QString> localeNamesByBcp47Name;
274
QHash<QString, unsigned int> countsByLanguage;
276
for (QStringList::const_iterator i(localeNames.begin()); i != localeNames.end(); ++i) {
277
QLocale locale(i->left(i->indexOf('.')));
278
QString bcp47Name(locale.bcp47Name());
279
QString language(locale.nativeLanguageName());
281
if (!language.isEmpty() && !localeNamesByBcp47Name.contains(bcp47Name)) {
282
m_languageLocales += locale;
283
localeNamesByBcp47Name[bcp47Name] = *i;
284
countsByLanguage[language]++;
288
qSort(m_languageLocales.begin(), m_languageLocales.end(), compareLocales);
290
for (int i(0); i < m_languageLocales.length(); i++) {
291
const QLocale &locale(m_languageLocales[i]);
292
QString bcp47Name(locale.bcp47Name());
293
QString language(locale.nativeLanguageName());
294
unsigned int count(countsByLanguage[language]);
297
m_languageNames += QString("%1 - %2").arg(language).arg(locale.nativeCountryName());
299
m_languageNames += language;
301
m_languageCodes += localeNamesByBcp47Name[bcp47Name];
302
m_indicesByBcp47Name[bcp47Name] = i;
303
m_indicesByLocaleName[localeNamesByBcp47Name[bcp47Name]] = i;
308
LanguagePlugin::updateCurrentLanguage()
310
int previousLanguage(m_currentLanguage);
312
if (m_user != NULL && act_user_is_loaded(m_user)) {
313
if (m_nextCurrentLanguage >= 0) {
314
m_currentLanguage = m_nextCurrentLanguage;
315
m_nextCurrentLanguage = -1;
317
QString languageCode(m_languageCodes[m_currentLanguage]);
318
act_user_set_language(m_user, qPrintable(languageCode.left(languageCode.indexOf('.'))));
319
act_user_set_formats_locale(m_user, qPrintable(languageCode));
321
const char *language(act_user_get_language(m_user));
322
m_currentLanguage = indexForLanguage(language);
324
if (m_currentLanguage < 0) {
325
QLocale locale(language);
326
m_currentLanguage = indexForLocale(locale);
328
if (m_currentLanguage < 0) {
329
locale = QLocale(locale.language());
330
m_currentLanguage = indexForLocale(locale);
336
if (m_currentLanguage < 0) {
337
QLocale locale(QLocale::system());
338
m_currentLanguage = indexForLocale(locale);
340
if (m_currentLanguage < 0) {
341
locale = QLocale(locale.language());
342
m_currentLanguage = indexForLocale(locale);
346
if (m_currentLanguage != previousLanguage)
347
Q_EMIT currentLanguageChanged();
351
LanguagePlugin::updateKeyboardLayouts()
353
m_keyboardLayouts.clear();
355
QDir layoutsDir(LAYOUTS_DIR);
356
layoutsDir.setFilter(QDir::Files);
357
layoutsDir.setNameFilters(QStringList("*.xml"));
358
layoutsDir.setSorting(QDir::Name);
360
QFileInfoList fileInfoList(layoutsDir.entryInfoList());
362
for (QFileInfoList::const_iterator i(fileInfoList.begin()); i != fileInfoList.end(); ++i) {
363
KeyboardLayout *layout(new KeyboardLayout(*i));
365
if (!layout->language().isEmpty())
366
m_keyboardLayouts += layout;
371
qSort(m_keyboardLayouts.begin(), m_keyboardLayouts.end(), compareLayouts);
374
void enabledLayoutsChanged(GSettings *settings,
379
LanguagePlugin::updateKeyboardLayoutsModel()
381
QStringList customRoles;
382
customRoles += "language";
383
customRoles += "icon";
385
m_keyboardLayoutsModel.setCustomRoles(customRoles);
387
QVariantList superset;
389
for (QList<KeyboardLayout *>::const_iterator i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) {
390
QVariantList element;
392
if (!(*i)->displayName().isEmpty())
393
element += (*i)->displayName();
395
element += (*i)->name();
397
element += (*i)->shortName();
398
superset += QVariant(element);
401
m_keyboardLayoutsModel.setSuperset(superset);
403
enabledLayoutsChanged();
405
m_keyboardLayoutsModel.setAllowEmpty(false);
407
connect(&m_keyboardLayoutsModel, SIGNAL(subsetChanged()), SLOT(keyboardLayoutsModelChanged()));
409
g_signal_connect(m_maliitSettings, "changed::" KEY_ENABLED_LAYOUTS, G_CALLBACK(::enabledLayoutsChanged), this);
413
LanguagePlugin::updateSpellCheckingModel()
415
// TODO: populate spell checking model
416
QVariantList superset;
418
for (QStringList::const_iterator i(m_languageNames.begin()); i != m_languageNames.end(); ++i) {
419
QVariantList element;
421
superset += QVariant(element);
424
m_spellCheckingModel.setCustomRoles(QStringList("language"));
425
m_spellCheckingModel.setSuperset(superset);
426
m_spellCheckingModel.setSubset(QList<int>());
427
m_spellCheckingModel.setAllowEmpty(false);
429
connect(&m_spellCheckingModel, SIGNAL(subsetChanged()), SLOT(spellCheckingModelChanged()));
433
LanguagePlugin::indexForLocale(const QLocale &locale) const
435
return m_indicesByBcp47Name.value(locale.bcp47Name(), -1);
439
LanguagePlugin::indexForLanguage(const QString &language) const
441
return m_indicesByLocaleName.value(language, -1);
445
LanguagePlugin::userLoaded()
447
if (act_user_is_loaded(m_user)) {
448
g_signal_handlers_disconnect_by_data(m_user, this);
450
updateCurrentLanguage();
455
userLoaded(GObject *object,
462
LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data));
463
plugin->userLoaded();
467
LanguagePlugin::managerLoaded()
470
g_object_get(m_manager, "is-loaded", &loaded, NULL);
473
g_signal_handlers_disconnect_by_data(m_manager, this);
475
const char *name(qPrintable(qgetenv("USER")));
478
m_user = act_user_manager_get_user(m_manager, name);
480
if (m_user != NULL) {
481
g_object_ref(m_user);
483
if (act_user_is_loaded(m_user))
486
g_signal_connect(m_user, "notify::is-loaded", G_CALLBACK(::userLoaded), this);
493
managerLoaded(GObject *object,
500
LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data));
501
plugin->managerLoaded();
505
LanguagePlugin::enabledLayoutsChanged()
508
const gchar *language;
511
g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter);
513
while (g_variant_iter_next(iter, "&s", &language)) {
514
for (int i(0); i < m_keyboardLayouts.length(); i++) {
515
if (m_keyboardLayouts[i]->name() == language) {
522
g_variant_iter_free(iter);
524
m_keyboardLayoutsModel.setSubset(subset);
528
enabledLayoutsChanged(GSettings *settings,
535
LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data));
536
plugin->enabledLayoutsChanged();