/*************************************************************************** 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 #include #include #include #if KDE_VERSION_MAJOR >= 3 #include #include #else #include #include #endif #include #include #include #include #include #include #include "kbconfig.h" #include "xkeyboard.h" #ifdef HAVE_X11_EXTENSIONS_XKBRULES_H #include #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(); TQStringList list; xkb->getGroupNames(list); unsigned int i = 0; m_groups.clear(); m_groups.resize(xkb->getNumKbdGroups()); TQString name; for (TQStringList::Iterator iter = list.begin(); iter != list.end(); iter++, i++) { name = *iter; if (name == TQString::null) name = i18n(""); m_groups.insert(i, new KBGroup(name)); } TQValueVector pixlist; TQStringList 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(TQString::fromLatin1("SetGroup %1").arg(i), i18n("Activate %1 keyboard layout").arg(m_groups[i]->getName()), TQString::null, TQt::ALT+TQt::CTRL+TQt::Key_1 + i, KKey::QtWIN+TQt::CTRL+TQt::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, TQValueVector *icons, TQStringList *iconpaths) { TQString path, countryCode, langCode; TQStringList 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; TQPixmap &pix = (*icons)[i]; pix.resize(0, 0); path = TQString::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"); TQString path, countryCode, langCode; TQPixmap 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(TQImage &img, TQString &path, const TQString &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", TQString("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 = TQString("/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(TQPixmap &pix, TQString &path, const TQString &code, int group, KConfig *config) { TQImage img; if (getGroupImage(img, path, code, group, config)) pix.convertFromImage(img); } void KBConfig::drawCodePixmap(TQPixmap &pix, const TQString &code) { pix.resize(19, 16); TQPainter painter(&pix); TQFont font("helvetica", 9, TQFont::Bold); font.setPixelSize(10); painter.setFont(font); painter.setPen(KGlobalSettings::highlightedTextColor()); pix.fill(KGlobalSettings::highlightColor()); painter.drawText(1, 0, pix.width(), pix.height(), TQt::AlignHCenter | TQt::AlignVCenter, code.upper()); /*TQSize size = painter.fontMetrics().size(0, code.upper()); kdDebug() << size.width() << " x " << size.height() << endl;*/ } void KBConfig::drawCodeAndFlagPixmap(TQPixmap &pix, TQString &path, const TQString &countryCode, const TQString &langCode, int group, KConfig *config) { TQImage 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++) { TQRgb rgb = img.pixel(x, y); img.setPixel(x, y, tqRgb(tqRed(rgb)*3/4, tqGreen(rgb)*3/4, tqBlue(rgb)*3/4)); } pix.convertFromImage(img); TQPainter painter(&pix); painter.setPen(TQt::black); painter.setFont(TQFont("helvetica", 10, TQFont::Bold)); painter.drawText(1, 1, pix.width(), pix.height()-2, TQt::AlignCenter, langCode); painter.setPen(TQt::white); painter.drawText(0, 0, pix.width(), pix.height()-2, TQt::AlignCenter, langCode); } void KBConfig::drawDefaultPixmap(TQPixmap &pix, int group) { pix.resize(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT); TQPainter painter(&pix); pix.fill(); painter.drawText(0, 0, pix.width(), pix.height(), TQt::AlignHCenter | TQt::AlignVCenter, TQString::number(group+1)); } void KBConfig::checkKeysEnabled() { m_keys->setEnabled(m_use_shortcuts); m_keys->updateConnections(); } /** No descriptions */ /*void KBConfig::drawDefaultPixmaps(){ TQPixmap pix(16, 16); TQPainter 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(), TQt::AlignHCenter | TQt::AlignVCenter, TQString::number(i+1)); m_groups[i]->setPixmap(pix); } } }*/ /** No descriptions */ /*void KBConfig::loadConfiguredPixmaps(KConfig *config){ TQString path; TQPixmap 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 TQStringList &layouts) */ void KBConfig::getXkbLayouts(TQStringList &layouts) { #if HAVE_X11_EXTENSIONS_XKBRULES_H && HAVE_LIBXKBFILE XkbRF_VarDefsRec vardefs; int i; usleep(10000); if (XkbRF_GetNamesProp(tqt_xdisplay(), NULL, &vardefs)) { layouts = TQStringList::split(',', vardefs.layout, true); for (TQStringList::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 }