summaryrefslogtreecommitdiffstats
path: root/kkbswitch/kbconfig.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kkbswitch/kbconfig.cpp')
-rw-r--r--kkbswitch/kbconfig.cpp340
1 files changed, 340 insertions, 0 deletions
diff --git a/kkbswitch/kbconfig.cpp b/kkbswitch/kbconfig.cpp
new file mode 100644
index 0000000..b7c5cac
--- /dev/null
+++ b/kkbswitch/kbconfig.cpp
@@ -0,0 +1,340 @@
+/***************************************************************************
+ kbconfig.cpp - description
+ -------------------
+ begin : Sun Jul 8 2001
+ copyright : (C) 2001 by Leonid Zeitlin
+ email : lz@europe.com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <config.h>
+#include <kdeversion.h>
+#include <klocale.h>
+#include <kglobal.h>
+#if KDE_VERSION_MAJOR >= 3
+ #include <kstandarddirs.h>
+ #include <kapplication.h>
+#else
+ #include <kstddirs.h>
+ #include <kapp.h>
+#endif
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kglobalaccel.h>
+
+#include <qnamespace.h>
+#include <qpainter.h>
+#include <qimage.h>
+
+#include "kbconfig.h"
+#include "xkeyboard.h"
+
+#ifdef HAVE_X11_EXTENSIONS_XKBRULES_H
+ #include <X11/extensions/XKBrules.h>
+#endif
+
+#define TOGGLE_MODE_ENTRY "toggle_mode"
+#define DEFAULT_GROUP_ENTRY "default_group"
+//#define PERWINDOW_GROUP_ENTRY "perwindow_group"
+#define ICON_TYPE_ENTRY "icon_type"
+#define AUTOSTART_ENTRY "autostart"
+#define USE_SHORTCUTS_ENTRY "use_shorcuts"
+#define GROUP_SCOPE_ENTRY "group_scope"
+
+KBConfig::KBConfig()
+{
+ m_toggle_mode = false;
+ m_groups.setAutoDelete(true);
+ m_default_groupno = 0;
+ //m_perwindow_group = false;
+ m_group_scope = SCOPE_GLOBAL;
+ m_autostart = true;
+ m_icon_style = ICON_CODE_AND_FLAG;
+ //m_keys = new KGlobalAccel(NULL);
+ m_keys = NULL;
+}
+
+KBConfig::~KBConfig()
+{
+ delete m_keys;
+}
+
+/** load the KBSwitch configration from the application KConfig object */
+void KBConfig::load(KConfig *config){
+ config->setGroup(OPTIONS_SECTION);
+ m_toggle_mode = config->readBoolEntry(TOGGLE_MODE_ENTRY);
+ m_default_groupno = config->readNumEntry(DEFAULT_GROUP_ENTRY);
+ //m_perwindow_group = config->readBoolEntry(PERWINDOW_GROUP_ENTRY);
+ m_group_scope = GroupScope(config->readNumEntry(GROUP_SCOPE_ENTRY, SCOPE_GLOBAL));
+ m_autostart = config->readBoolEntry(AUTOSTART_ENTRY, true);
+ m_icon_style = IconStyle(config->readNumEntry(ICON_TYPE_ENTRY, ICON_FLAG));
+ m_use_shortcuts = config->readBoolEntry(USE_SHORTCUTS_ENTRY, false);
+
+ XKeyboard *xkb = XKeyboard::self();
+ QStringList list;
+ xkb->getGroupNames(list);
+ unsigned int i = 0;
+ m_groups.clear();
+ m_groups.resize(xkb->getNumKbdGroups());
+ QString name;
+ for (QStringList::Iterator iter = list.begin(); iter != list.end(); iter++, i++) {
+ name = *iter;
+ if (name == QString::null) name = i18n("<Unnamed>");
+ m_groups.insert(i, new KBGroup(name));
+ }
+
+ QValueVector<QPixmap> pixlist;
+ QStringList iconpaths;
+ drawIcons(m_icon_style, &pixlist, &iconpaths);
+ for (i = 0; i < m_groups.count(); i++) {
+ m_groups[i]->setPixmap(pixlist[i]);
+ m_groups[i]->setIconPath(iconpaths[i]);
+ }
+
+ if (m_keys) delete m_keys;
+ m_keys = new KGlobalAccel(NULL);
+ for (int i = 0; i < groupCount(); i++) {
+ m_keys->insert(QString::fromLatin1("SetGroup %1").arg(i),
+ i18n("Activate %1 keyboard layout").arg(m_groups[i]->getName()),
+ QString::null, Qt::ALT+Qt::CTRL+Qt::Key_1 + i, KKey::QtWIN+Qt::CTRL+Qt::Key_1 + i,
+ kapp, SLOT(slotGroupSelected(int)));
+ }
+ m_keys->readSettings(config);
+ checkKeysEnabled();
+}
+
+void KBConfig::save(KConfig *config)
+{
+ config->setGroup(OPTIONS_SECTION);
+ config->writeEntry(TOGGLE_MODE_ENTRY, m_toggle_mode);
+ config->writeEntry(DEFAULT_GROUP_ENTRY, m_default_groupno);
+ //config->writeEntry(PERWINDOW_GROUP_ENTRY, m_perwindow_group);
+ config->writeEntry(GROUP_SCOPE_ENTRY, m_group_scope);
+ config->writeEntry(ICON_TYPE_ENTRY, m_icon_style);
+ config->writeEntry(AUTOSTART_ENTRY, m_autostart);
+ config->writeEntry(USE_SHORTCUTS_ENTRY, m_use_shortcuts);
+ m_keys->writeSettings(config);
+}
+
+void KBConfig::drawIcons(IconStyle icon_style, QValueVector<QPixmap> *icons,
+ QStringList *iconpaths)
+{
+ QString path, countryCode, langCode;
+ QStringList layouts;
+
+ KGlobal::dirs()->addResourceDir("appdata", ".");
+ KConfig map("group_names", true, true, "appdata");
+ KConfig *config = kapp->config();
+ config->setGroup(ICONS_SECTION);
+ getXkbLayouts(layouts);
+
+ icons->clear();
+ icons->resize(m_groups.count());
+ iconpaths->clear();
+ for (unsigned int i = 0; i < m_groups.count(); i++) {
+ map.setGroup("Mapping");
+ countryCode = map.readEntry(m_groups[i]->getName());
+ // if the country code can't be guessed from group name, try XKB layout name
+ if (countryCode.isEmpty() && i < layouts.count()) countryCode = layouts[i];
+ map.setGroup("Languages");
+ langCode = map.readEntry(m_groups[i]->getName());
+ if (langCode.isEmpty()) langCode = countryCode;
+ QPixmap &pix = (*icons)[i];
+ pix.resize(0, 0);
+ path = QString::null;
+ if (icon_style == ICON_FLAG /*&& !countryCode.isEmpty()*/)
+ drawFlagPixmap(pix, path, countryCode, i, config);
+ else if (icon_style == ICON_CODE_AND_FLAG /*&& !countryCode.isEmpty()*/)
+ drawCodeAndFlagPixmap(pix, path, countryCode, langCode, i, config);
+ if (pix.isNull() && !langCode.isEmpty())
+ drawCodePixmap(pix, langCode);
+ if (pix.isNull()) drawDefaultPixmap(pix, i);
+ iconpaths->append(path);
+ }
+}
+
+/** No descriptions */
+/*void KBConfig::guessGroupPixmaps(){
+ KGlobal::dirs()->addResourceDir("appdata", ".");
+ KConfig map("group_names", true, true, "appdata");
+ QString path, countryCode, langCode;
+ QPixmap pix;
+
+ for (unsigned int i = 0; i < m_groups.count(); i++) {
+ if (m_groups[i]->getPixmap().isNull()) {
+ map.setGroup("Mapping");
+ countryCode = map.readEntry(m_groups[i]->getName());
+ map.setGroup("Languages");
+ langCode = map.readEntry(m_groups[i]->getName());
+ if (langCode.isEmpty()) langCode = countryCode;
+ pix.resize(0, 0);
+ if (m_icon_type == ICON_FLAG && !countryCode.isEmpty())
+ drawFlagPixmap(pix, countryCode);
+ else if (m_icon_type == ICON_CODE_AND_FLAG && !countryCode.isEmpty())
+ drawCodeAndFlagPixmap(pix, countryCode, langCode);
+ if (pix.isNull() && !langCode.isEmpty())
+ drawCodePixmap(pix, langCode);
+ if (!pix.isNull()) m_groups[i]->setPixmap(pix);
+ }
+ }
+}*/
+
+bool KBConfig::getGroupImage(QImage &img, QString &path, const QString &code,
+ int group, KConfig *config)
+{
+ bool ret = true;
+ bool need_to_scale = false;
+
+ path = config->readEntry(m_groups[group]->getName()/*entryForGroup(group)*/);
+ if (path.isEmpty() || !img.load(path)) {
+ if (code.isEmpty()) ret = false;
+ else {
+ path = locate("locale", QString("l10n/%1/flag.png").arg(code));
+ if (!path.isEmpty()) ret = img.load(path);
+ else {
+ // I am told in Red Hat 9 standard KDE flag pixmaps are missing.
+ // Workaround: we have to simulate them by rescaling GKB's pixmaps
+ path = QString("/usr/share/pixmaps/gkb/%1.png").arg(code);
+ ret = img.load(path) && !img.isNull();
+ need_to_scale = true;
+ }
+ }
+ }
+ if (ret) {
+ // if need_to_scale is not already set, set it if image is too wide
+ if (!need_to_scale) need_to_scale = img.width() > 24;
+ if (need_to_scale) img = img.smoothScale(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
+ }
+ return ret;
+}
+
+void KBConfig::drawFlagPixmap(QPixmap &pix, QString &path, const QString &code,
+ int group, KConfig *config)
+{
+ QImage img;
+ if (getGroupImage(img, path, code, group, config))
+ pix.convertFromImage(img);
+}
+
+void KBConfig::drawCodePixmap(QPixmap &pix, const QString &code)
+{
+ pix.resize(19, 16);
+
+ QPainter painter(&pix);
+ QFont font("helvetica", 9, QFont::Bold);
+ font.setPixelSize(10);
+ painter.setFont(font);
+ painter.setPen(KGlobalSettings::highlightedTextColor());
+
+ pix.fill(KGlobalSettings::highlightColor());
+ painter.drawText(1, 0, pix.width(), pix.height(),
+ Qt::AlignHCenter | Qt::AlignVCenter, code.upper());
+
+ /*QSize size = painter.fontMetrics().size(0, code.upper());
+ kdDebug() << size.width() << " x " << size.height() << endl;*/
+}
+
+void KBConfig::drawCodeAndFlagPixmap(QPixmap &pix, QString &path,
+ const QString &countryCode, const QString &langCode, int group, KConfig *config)
+{
+ QImage img;
+ if (!getGroupImage(img, path, countryCode, group, config)) return; // could not find flag
+ if (img.depth() <= 8) img = img.convertDepth(32);
+
+ // the following code is taken from kdebase/kxkb/pixmap.cpp
+ for (int y = 0; y < img.height(); y++)
+ for(int x = 0; x < img.width(); x++) {
+ QRgb rgb = img.pixel(x, y);
+ img.setPixel(x, y, qRgb(qRed(rgb)*3/4, qGreen(rgb)*3/4, qBlue(rgb)*3/4));
+ }
+ pix.convertFromImage(img);
+
+ QPainter painter(&pix);
+ painter.setPen(Qt::black);
+ painter.setFont(QFont("helvetica", 10, QFont::Bold));
+ painter.drawText(1, 1, pix.width(), pix.height()-2, Qt::AlignCenter, langCode);
+ painter.setPen(Qt::white);
+ painter.drawText(0, 0, pix.width(), pix.height()-2, Qt::AlignCenter, langCode);
+}
+
+void KBConfig::drawDefaultPixmap(QPixmap &pix, int group)
+{
+ pix.resize(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
+ QPainter painter(&pix);
+ pix.fill();
+ painter.drawText(0, 0, pix.width(), pix.height(),
+ Qt::AlignHCenter | Qt::AlignVCenter, QString::number(group+1));
+}
+
+void KBConfig::checkKeysEnabled()
+{
+ m_keys->setEnabled(m_use_shortcuts);
+ m_keys->updateConnections();
+}
+
+
+/** No descriptions */
+/*void KBConfig::drawDefaultPixmaps(){
+ QPixmap pix(16, 16);
+ QPainter painter(&pix);
+
+ for (unsigned int i = 0; i < m_groups.count(); i++) {
+ if (m_groups[i]->getPixmap().isNull()) {
+ pix.fill();
+ painter.drawText(0, 0, pix.width(), pix.height(),
+ Qt::AlignHCenter | Qt::AlignVCenter, QString::number(i+1));
+ m_groups[i]->setPixmap(pix);
+ }
+ }
+}*/
+
+/** No descriptions */
+/*void KBConfig::loadConfiguredPixmaps(KConfig *config){
+ QString path;
+ QPixmap pix;
+ config->setGroup(ICONS_SECTION);
+ for (unsigned int i = 0; i < m_groups.count(); i++) {
+ path = config->readEntry(entryForGroup(i));
+ if (!path.isEmpty() && pix.load(path))
+ m_groups[i]->setPixmap(pix);
+ }
+}*/
+
+/** No descriptions */
+/*void KBConfig::notifyChanged(){
+ emit changed();
+}*/
+
+
+/*!
+ \fn KBConfig::getXkbLayouts(const QStringList &layouts)
+ */
+void KBConfig::getXkbLayouts(QStringList &layouts)
+{
+#if HAVE_X11_EXTENSIONS_XKBRULES_H && HAVE_LIBXKBFILE
+ XkbRF_VarDefsRec vardefs;
+ int i;
+
+ usleep(10000);
+ if (XkbRF_GetNamesProp(qt_xdisplay(), NULL, &vardefs)) {
+ layouts = QStringList::split(',', vardefs.layout, true);
+ for (QStringList::Iterator it = layouts.begin(); it != layouts.end(); ++it) {
+ i = 0;
+ while ((*it)[i] >= 'a' && (*it)[i] <= 'z') i++;
+ *it = (*it).left(i);
+ }
+ if (vardefs.layout) XFree(vardefs.layout);
+ if (vardefs.model) XFree(vardefs.model);
+ if (vardefs.variant) XFree(vardefs.variant);
+ if (vardefs.options) XFree(vardefs.options);
+ }
+#endif
+}