1
/***************************************************************************
2
kbconfig.cpp - description
5
copyright : (C) 2001 by Leonid Zeitlin
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
19
#include <kdeversion.h>
22
#if KDE_VERSION_MAJOR >= 3
23
#include <kstandarddirs.h>
24
#include <kapplication.h>
29
#include <kglobalsettings.h>
31
#include <kglobalaccel.h>
33
#include <qnamespace.h>
38
#include "xkeyboard.h"
40
#ifdef HAVE_X11_EXTENSIONS_XKBRULES_H
41
#include <X11/extensions/XKBrules.h>
44
#define TOGGLE_MODE_ENTRY "toggle_mode"
45
#define DEFAULT_GROUP_ENTRY "default_group"
46
//#define PERWINDOW_GROUP_ENTRY "perwindow_group"
47
#define ICON_TYPE_ENTRY "icon_type"
48
#define AUTOSTART_ENTRY "autostart"
49
#define USE_SHORTCUTS_ENTRY "use_shorcuts"
50
#define GROUP_SCOPE_ENTRY "group_scope"
54
m_toggle_mode = false;
55
m_groups.setAutoDelete(true);
56
m_default_groupno = 0;
57
//m_perwindow_group = false;
58
m_group_scope = SCOPE_GLOBAL;
60
m_icon_style = ICON_CODE_AND_FLAG;
61
//m_keys = new KGlobalAccel(NULL);
70
/** load the KBSwitch configration from the application KConfig object */
71
void KBConfig::load(KConfig *config){
72
config->setGroup(OPTIONS_SECTION);
73
m_toggle_mode = config->readBoolEntry(TOGGLE_MODE_ENTRY);
74
m_default_groupno = config->readNumEntry(DEFAULT_GROUP_ENTRY);
75
//m_perwindow_group = config->readBoolEntry(PERWINDOW_GROUP_ENTRY);
76
m_group_scope = GroupScope(config->readNumEntry(GROUP_SCOPE_ENTRY, SCOPE_GLOBAL));
77
m_autostart = config->readBoolEntry(AUTOSTART_ENTRY, true);
78
m_icon_style = IconStyle(config->readNumEntry(ICON_TYPE_ENTRY, ICON_FLAG));
79
m_use_shortcuts = config->readBoolEntry(USE_SHORTCUTS_ENTRY, false);
81
XKeyboard *xkb = XKeyboard::self();
83
xkb->getGroupNames(list);
86
m_groups.resize(xkb->getNumKbdGroups());
88
for (QStringList::Iterator iter = list.begin(); iter != list.end(); iter++, i++) {
90
if (name == QString::null) name = i18n("<Unnamed>");
91
m_groups.insert(i, new KBGroup(name));
94
QValueVector<QPixmap> pixlist;
95
QStringList iconpaths;
96
drawIcons(m_icon_style, &pixlist, &iconpaths);
97
for (i = 0; i < m_groups.count(); i++) {
98
m_groups[i]->setPixmap(pixlist[i]);
99
m_groups[i]->setIconPath(iconpaths[i]);
102
if (m_keys) delete m_keys;
103
m_keys = new KGlobalAccel(NULL);
104
for (int i = 0; i < groupCount(); i++) {
105
m_keys->insert(QString::fromLatin1("SetGroup %1").arg(i),
106
i18n("Activate %1 keyboard layout").arg(m_groups[i]->getName()),
107
QString::null, Qt::ALT+Qt::CTRL+Qt::Key_1 + i, KKey::QtWIN+Qt::CTRL+Qt::Key_1 + i,
108
kapp, SLOT(slotGroupSelected(int)));
110
m_keys->readSettings(config);
114
void KBConfig::save(KConfig *config)
116
config->setGroup(OPTIONS_SECTION);
117
config->writeEntry(TOGGLE_MODE_ENTRY, m_toggle_mode);
118
config->writeEntry(DEFAULT_GROUP_ENTRY, m_default_groupno);
119
//config->writeEntry(PERWINDOW_GROUP_ENTRY, m_perwindow_group);
120
config->writeEntry(GROUP_SCOPE_ENTRY, m_group_scope);
121
config->writeEntry(ICON_TYPE_ENTRY, m_icon_style);
122
config->writeEntry(AUTOSTART_ENTRY, m_autostart);
123
config->writeEntry(USE_SHORTCUTS_ENTRY, m_use_shortcuts);
124
m_keys->writeSettings(config);
127
void KBConfig::drawIcons(IconStyle icon_style, QValueVector<QPixmap> *icons,
128
QStringList *iconpaths)
130
QString path, countryCode, langCode;
133
KGlobal::dirs()->addResourceDir("appdata", ".");
134
KConfig map("group_names", true, true, "appdata");
135
KConfig *config = kapp->config();
136
config->setGroup(ICONS_SECTION);
137
getXkbLayouts(layouts);
140
icons->resize(m_groups.count());
142
for (unsigned int i = 0; i < m_groups.count(); i++) {
143
map.setGroup("Mapping");
144
countryCode = map.readEntry(m_groups[i]->getName());
145
// if the country code can't be guessed from group name, try XKB layout name
146
if (countryCode.isEmpty() && i < layouts.count()) countryCode = layouts[i];
147
map.setGroup("Languages");
148
langCode = map.readEntry(m_groups[i]->getName());
149
if (langCode.isEmpty()) langCode = countryCode;
150
QPixmap &pix = (*icons)[i];
152
path = QString::null;
153
if (icon_style == ICON_FLAG /*&& !countryCode.isEmpty()*/)
154
drawFlagPixmap(pix, path, countryCode, i, config);
155
else if (icon_style == ICON_CODE_AND_FLAG /*&& !countryCode.isEmpty()*/)
156
drawCodeAndFlagPixmap(pix, path, countryCode, langCode, i, config);
157
if (pix.isNull() && !langCode.isEmpty())
158
drawCodePixmap(pix, langCode);
159
if (pix.isNull()) drawDefaultPixmap(pix, i);
160
iconpaths->append(path);
164
/** No descriptions */
165
/*void KBConfig::guessGroupPixmaps(){
166
KGlobal::dirs()->addResourceDir("appdata", ".");
167
KConfig map("group_names", true, true, "appdata");
168
QString path, countryCode, langCode;
171
for (unsigned int i = 0; i < m_groups.count(); i++) {
172
if (m_groups[i]->getPixmap().isNull()) {
173
map.setGroup("Mapping");
174
countryCode = map.readEntry(m_groups[i]->getName());
175
map.setGroup("Languages");
176
langCode = map.readEntry(m_groups[i]->getName());
177
if (langCode.isEmpty()) langCode = countryCode;
179
if (m_icon_type == ICON_FLAG && !countryCode.isEmpty())
180
drawFlagPixmap(pix, countryCode);
181
else if (m_icon_type == ICON_CODE_AND_FLAG && !countryCode.isEmpty())
182
drawCodeAndFlagPixmap(pix, countryCode, langCode);
183
if (pix.isNull() && !langCode.isEmpty())
184
drawCodePixmap(pix, langCode);
185
if (!pix.isNull()) m_groups[i]->setPixmap(pix);
190
bool KBConfig::getGroupImage(QImage &img, QString &path, const QString &code,
191
int group, KConfig *config)
194
bool need_to_scale = false;
196
path = config->readEntry(m_groups[group]->getName()/*entryForGroup(group)*/);
197
if (path.isEmpty() || !img.load(path)) {
198
if (code.isEmpty()) ret = false;
200
path = locate("locale", QString("l10n/%1/flag.png").arg(code));
201
if (!path.isEmpty()) ret = img.load(path);
203
// I am told in Red Hat 9 standard KDE flag pixmaps are missing.
204
// Workaround: we have to simulate them by rescaling GKB's pixmaps
205
path = QString("/usr/share/pixmaps/gkb/%1.png").arg(code);
206
ret = img.load(path) && !img.isNull();
207
need_to_scale = true;
212
// if need_to_scale is not already set, set it if image is too wide
213
if (!need_to_scale) need_to_scale = img.width() > 24;
214
if (need_to_scale) img = img.smoothScale(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
219
void KBConfig::drawFlagPixmap(QPixmap &pix, QString &path, const QString &code,
220
int group, KConfig *config)
223
if (getGroupImage(img, path, code, group, config))
224
pix.convertFromImage(img);
227
void KBConfig::drawCodePixmap(QPixmap &pix, const QString &code)
231
QPainter painter(&pix);
232
QFont font("helvetica", 9, QFont::Bold);
233
font.setPixelSize(10);
234
painter.setFont(font);
235
painter.setPen(KGlobalSettings::highlightedTextColor());
237
pix.fill(KGlobalSettings::highlightColor());
238
painter.drawText(1, 0, pix.width(), pix.height(),
239
Qt::AlignHCenter | Qt::AlignVCenter, code.upper());
241
/*QSize size = painter.fontMetrics().size(0, code.upper());
242
kdDebug() << size.width() << " x " << size.height() << endl;*/
245
void KBConfig::drawCodeAndFlagPixmap(QPixmap &pix, QString &path,
246
const QString &countryCode, const QString &langCode, int group, KConfig *config)
249
if (!getGroupImage(img, path, countryCode, group, config)) return; // could not find flag
250
if (img.depth() <= 8) img = img.convertDepth(32);
252
// the following code is taken from kdebase/kxkb/pixmap.cpp
253
for (int y = 0; y < img.height(); y++)
254
for(int x = 0; x < img.width(); x++) {
255
QRgb rgb = img.pixel(x, y);
256
img.setPixel(x, y, qRgb(qRed(rgb)*3/4, qGreen(rgb)*3/4, qBlue(rgb)*3/4));
258
pix.convertFromImage(img);
260
QPainter painter(&pix);
261
painter.setPen(Qt::black);
262
painter.setFont(QFont("helvetica", 10, QFont::Bold));
263
painter.drawText(1, 1, pix.width(), pix.height()-2, Qt::AlignCenter, langCode);
264
painter.setPen(Qt::white);
265
painter.drawText(0, 0, pix.width(), pix.height()-2, Qt::AlignCenter, langCode);
268
void KBConfig::drawDefaultPixmap(QPixmap &pix, int group)
270
pix.resize(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
271
QPainter painter(&pix);
273
painter.drawText(0, 0, pix.width(), pix.height(),
274
Qt::AlignHCenter | Qt::AlignVCenter, QString::number(group+1));
277
void KBConfig::checkKeysEnabled()
279
m_keys->setEnabled(m_use_shortcuts);
280
m_keys->updateConnections();
284
/** No descriptions */
285
/*void KBConfig::drawDefaultPixmaps(){
287
QPainter painter(&pix);
289
for (unsigned int i = 0; i < m_groups.count(); i++) {
290
if (m_groups[i]->getPixmap().isNull()) {
292
painter.drawText(0, 0, pix.width(), pix.height(),
293
Qt::AlignHCenter | Qt::AlignVCenter, QString::number(i+1));
294
m_groups[i]->setPixmap(pix);
299
/** No descriptions */
300
/*void KBConfig::loadConfiguredPixmaps(KConfig *config){
303
config->setGroup(ICONS_SECTION);
304
for (unsigned int i = 0; i < m_groups.count(); i++) {
305
path = config->readEntry(entryForGroup(i));
306
if (!path.isEmpty() && pix.load(path))
307
m_groups[i]->setPixmap(pix);
311
/** No descriptions */
312
/*void KBConfig::notifyChanged(){
318
\fn KBConfig::getXkbLayouts(const QStringList &layouts)
320
void KBConfig::getXkbLayouts(QStringList &layouts)
322
#if HAVE_X11_EXTENSIONS_XKBRULES_H && HAVE_LIBXKBFILE
323
XkbRF_VarDefsRec vardefs;
327
if (XkbRF_GetNamesProp(qt_xdisplay(), NULL, &vardefs)) {
328
layouts = QStringList::split(',', vardefs.layout, true);
329
for (QStringList::Iterator it = layouts.begin(); it != layouts.end(); ++it) {
331
while ((*it)[i] >= 'a' && (*it)[i] <= 'z') i++;
334
if (vardefs.layout) XFree(vardefs.layout);
335
if (vardefs.model) XFree(vardefs.model);
336
if (vardefs.variant) XFree(vardefs.variant);
337
if (vardefs.options) XFree(vardefs.options);