You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kkbswitch/kkbswitch/kbconfig.cpp

343 lines
11 KiB

/***************************************************************************
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 <unistd.h>
#include <config.h>
#include <tdeversion.h>
#include <tdelocale.h>
#include <tdeglobal.h>
#if TDE_VERSION_MAJOR >= 3
#include <kstandarddirs.h>
#include <tdeapplication.h>
#else
#include <kstddirs.h>
#include <kapp.h>
#endif
#include <tdeglobalsettings.h>
#include <kdebug.h>
#include <kglobalaccel.h>
#include <ntqnamespace.h>
#include <ntqpainter.h>
#include <ntqimage.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 TDEGlobalAccel(NULL);
m_keys = NULL;
}
KBConfig::~KBConfig()
{
delete m_keys;
}
/** load the KBSwitch configration from the application TDEConfig object */
void KBConfig::load(TDEConfig *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("<Unnamed>");
m_groups.insert(i, new KBGroup(name));
}
TQValueVector<TQPixmap> 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 TDEGlobalAccel(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(TDEConfig *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<TQPixmap> *icons,
TQStringList *iconpaths)
{
TQString path, countryCode, langCode;
TQStringList layouts;
TDEGlobal::dirs()->addResourceDir("appdata", ".");
TDEConfig map("group_names", true, true, "appdata");
TDEConfig *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(){
TDEGlobal::dirs()->addResourceDir("appdata", ".");
TDEConfig 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, TDEConfig *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, TDEConfig *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(TDEGlobalSettings::highlightedTextColor());
pix.fill(TDEGlobalSettings::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, TDEConfig *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 tdebase/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(TDEConfig *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
}