diff options
Diffstat (limited to 'kkbswitch/kbconfig.cpp')
-rw-r--r-- | kkbswitch/kbconfig.cpp | 340 |
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 +} |