KKBSwitch – keyboard layout indicator
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.

kbconfig.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /***************************************************************************
  2. kbconfig.cpp - description
  3. -------------------
  4. begin : Sun Jul 8 2001
  5. copyright : (C) 2001 by Leonid Zeitlin
  6. email : lz@europe.com
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************/
  16. #include <unistd.h>
  17. #include <config.h>
  18. #include <tdeversion.h>
  19. #include <tdelocale.h>
  20. #include <tdeglobal.h>
  21. #if TDE_VERSION_MAJOR >= 3
  22. #include <kstandarddirs.h>
  23. #include <tdeapplication.h>
  24. #else
  25. #include <kstddirs.h>
  26. #include <kapp.h>
  27. #endif
  28. #include <tdeglobalsettings.h>
  29. #include <kdebug.h>
  30. #include <kglobalaccel.h>
  31. #include <ntqnamespace.h>
  32. #include <ntqpainter.h>
  33. #include <ntqimage.h>
  34. #include "kbconfig.h"
  35. #include "xkeyboard.h"
  36. #ifdef HAVE_X11_EXTENSIONS_XKBRULES_H
  37. #include <X11/extensions/XKBrules.h>
  38. #endif
  39. #define TOGGLE_MODE_ENTRY "toggle_mode"
  40. #define DEFAULT_GROUP_ENTRY "default_group"
  41. //#define PERWINDOW_GROUP_ENTRY "perwindow_group"
  42. #define ICON_TYPE_ENTRY "icon_type"
  43. #define AUTOSTART_ENTRY "autostart"
  44. #define USE_SHORTCUTS_ENTRY "use_shorcuts"
  45. #define GROUP_SCOPE_ENTRY "group_scope"
  46. KBConfig::KBConfig()
  47. {
  48. m_toggle_mode = false;
  49. m_groups.setAutoDelete(true);
  50. m_default_groupno = 0;
  51. //m_perwindow_group = false;
  52. m_group_scope = SCOPE_GLOBAL;
  53. m_autostart = true;
  54. m_icon_style = ICON_CODE_AND_FLAG;
  55. //m_keys = new TDEGlobalAccel(NULL);
  56. m_keys = NULL;
  57. }
  58. KBConfig::~KBConfig()
  59. {
  60. delete m_keys;
  61. }
  62. /** load the KBSwitch configration from the application TDEConfig object */
  63. void KBConfig::load(TDEConfig *config){
  64. config->setGroup(OPTIONS_SECTION);
  65. m_toggle_mode = config->readBoolEntry(TOGGLE_MODE_ENTRY);
  66. m_default_groupno = config->readNumEntry(DEFAULT_GROUP_ENTRY);
  67. //m_perwindow_group = config->readBoolEntry(PERWINDOW_GROUP_ENTRY);
  68. m_group_scope = GroupScope(config->readNumEntry(GROUP_SCOPE_ENTRY, SCOPE_GLOBAL));
  69. m_autostart = config->readBoolEntry(AUTOSTART_ENTRY, true);
  70. m_icon_style = IconStyle(config->readNumEntry(ICON_TYPE_ENTRY, ICON_FLAG));
  71. m_use_shortcuts = config->readBoolEntry(USE_SHORTCUTS_ENTRY, false);
  72. XKeyboard *xkb = XKeyboard::self();
  73. TQStringList list;
  74. xkb->getGroupNames(list);
  75. unsigned int i = 0;
  76. m_groups.clear();
  77. m_groups.resize(xkb->getNumKbdGroups());
  78. TQString name;
  79. for (TQStringList::Iterator iter = list.begin(); iter != list.end(); iter++, i++) {
  80. name = *iter;
  81. if (name == TQString::null) name = i18n("<Unnamed>");
  82. m_groups.insert(i, new KBGroup(name));
  83. }
  84. TQValueVector<TQPixmap> pixlist;
  85. TQStringList iconpaths;
  86. drawIcons(m_icon_style, &pixlist, &iconpaths);
  87. for (i = 0; i < m_groups.count(); i++) {
  88. m_groups[i]->setPixmap(pixlist[i]);
  89. m_groups[i]->setIconPath(iconpaths[i]);
  90. }
  91. if (m_keys) delete m_keys;
  92. m_keys = new TDEGlobalAccel(NULL);
  93. for (int i = 0; i < groupCount(); i++) {
  94. m_keys->insert(TQString::fromLatin1("SetGroup %1").arg(i),
  95. i18n("Activate %1 keyboard layout").arg(m_groups[i]->getName()),
  96. TQString::null, TQt::ALT+TQt::CTRL+TQt::Key_1 + i, KKey::QtWIN+TQt::CTRL+TQt::Key_1 + i,
  97. kapp, SLOT(slotGroupSelected(int)));
  98. }
  99. m_keys->readSettings(config);
  100. checkKeysEnabled();
  101. }
  102. void KBConfig::save(TDEConfig *config)
  103. {
  104. config->setGroup(OPTIONS_SECTION);
  105. config->writeEntry(TOGGLE_MODE_ENTRY, m_toggle_mode);
  106. config->writeEntry(DEFAULT_GROUP_ENTRY, m_default_groupno);
  107. //config->writeEntry(PERWINDOW_GROUP_ENTRY, m_perwindow_group);
  108. config->writeEntry(GROUP_SCOPE_ENTRY, m_group_scope);
  109. config->writeEntry(ICON_TYPE_ENTRY, m_icon_style);
  110. config->writeEntry(AUTOSTART_ENTRY, m_autostart);
  111. config->writeEntry(USE_SHORTCUTS_ENTRY, m_use_shortcuts);
  112. m_keys->writeSettings(config);
  113. }
  114. void KBConfig::drawIcons(IconStyle icon_style, TQValueVector<TQPixmap> *icons,
  115. TQStringList *iconpaths)
  116. {
  117. TQString path, countryCode, langCode;
  118. TQStringList layouts;
  119. TDEGlobal::dirs()->addResourceDir("appdata", ".");
  120. TDEConfig map("group_names", true, true, "appdata");
  121. TDEConfig *config = kapp->config();
  122. config->setGroup(ICONS_SECTION);
  123. getXkbLayouts(layouts);
  124. icons->clear();
  125. icons->resize(m_groups.count());
  126. iconpaths->clear();
  127. for (unsigned int i = 0; i < m_groups.count(); i++) {
  128. map.setGroup("Mapping");
  129. countryCode = map.readEntry(m_groups[i]->getName());
  130. // if the country code can't be guessed from group name, try XKB layout name
  131. if (countryCode.isEmpty() && i < layouts.count()) countryCode = layouts[i];
  132. map.setGroup("Languages");
  133. langCode = map.readEntry(m_groups[i]->getName());
  134. if (langCode.isEmpty()) langCode = countryCode;
  135. TQPixmap &pix = (*icons)[i];
  136. pix.resize(0, 0);
  137. path = TQString::null;
  138. if (icon_style == ICON_FLAG /*&& !countryCode.isEmpty()*/)
  139. drawFlagPixmap(pix, path, countryCode, i, config);
  140. else if (icon_style == ICON_CODE_AND_FLAG /*&& !countryCode.isEmpty()*/)
  141. drawCodeAndFlagPixmap(pix, path, countryCode, langCode, i, config);
  142. if (pix.isNull() && !langCode.isEmpty())
  143. drawCodePixmap(pix, langCode);
  144. if (pix.isNull()) drawDefaultPixmap(pix, i);
  145. iconpaths->append(path);
  146. }
  147. }
  148. /** No descriptions */
  149. /*void KBConfig::guessGroupPixmaps(){
  150. TDEGlobal::dirs()->addResourceDir("appdata", ".");
  151. TDEConfig map("group_names", true, true, "appdata");
  152. TQString path, countryCode, langCode;
  153. TQPixmap pix;
  154. for (unsigned int i = 0; i < m_groups.count(); i++) {
  155. if (m_groups[i]->getPixmap().isNull()) {
  156. map.setGroup("Mapping");
  157. countryCode = map.readEntry(m_groups[i]->getName());
  158. map.setGroup("Languages");
  159. langCode = map.readEntry(m_groups[i]->getName());
  160. if (langCode.isEmpty()) langCode = countryCode;
  161. pix.resize(0, 0);
  162. if (m_icon_type == ICON_FLAG && !countryCode.isEmpty())
  163. drawFlagPixmap(pix, countryCode);
  164. else if (m_icon_type == ICON_CODE_AND_FLAG && !countryCode.isEmpty())
  165. drawCodeAndFlagPixmap(pix, countryCode, langCode);
  166. if (pix.isNull() && !langCode.isEmpty())
  167. drawCodePixmap(pix, langCode);
  168. if (!pix.isNull()) m_groups[i]->setPixmap(pix);
  169. }
  170. }
  171. }*/
  172. bool KBConfig::getGroupImage(TQImage &img, TQString &path, const TQString &code,
  173. int group, TDEConfig *config)
  174. {
  175. bool ret = true;
  176. bool need_to_scale = false;
  177. path = config->readEntry(m_groups[group]->getName()/*entryForGroup(group)*/);
  178. if (path.isEmpty() || !img.load(path)) {
  179. if (code.isEmpty()) ret = false;
  180. else {
  181. path = locate("locale", TQString("l10n/%1/flag.png").arg(code));
  182. if (!path.isEmpty()) ret = img.load(path);
  183. else {
  184. // I am told in Red Hat 9 standard KDE flag pixmaps are missing.
  185. // Workaround: we have to simulate them by rescaling GKB's pixmaps
  186. path = TQString("/usr/share/pixmaps/gkb/%1.png").arg(code);
  187. ret = img.load(path) && !img.isNull();
  188. need_to_scale = true;
  189. }
  190. }
  191. }
  192. if (ret) {
  193. // if need_to_scale is not already set, set it if image is too wide
  194. if (!need_to_scale) need_to_scale = img.width() > 24;
  195. if (need_to_scale) img = img.smoothScale(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
  196. }
  197. return ret;
  198. }
  199. void KBConfig::drawFlagPixmap(TQPixmap &pix, TQString &path, const TQString &code,
  200. int group, TDEConfig *config)
  201. {
  202. TQImage img;
  203. if (getGroupImage(img, path, code, group, config))
  204. pix.convertFromImage(img);
  205. }
  206. void KBConfig::drawCodePixmap(TQPixmap &pix, const TQString &code)
  207. {
  208. pix.resize(19, 16);
  209. TQPainter painter(&pix);
  210. TQFont font("helvetica", 9, TQFont::Bold);
  211. font.setPixelSize(10);
  212. painter.setFont(font);
  213. painter.setPen(TDEGlobalSettings::highlightedTextColor());
  214. pix.fill(TDEGlobalSettings::highlightColor());
  215. painter.drawText(1, 0, pix.width(), pix.height(),
  216. TQt::AlignHCenter | TQt::AlignVCenter, code.upper());
  217. /*TQSize size = painter.fontMetrics().size(0, code.upper());
  218. kdDebug() << size.width() << " x " << size.height() << endl;*/
  219. }
  220. void KBConfig::drawCodeAndFlagPixmap(TQPixmap &pix, TQString &path,
  221. const TQString &countryCode, const TQString &langCode, int group, TDEConfig *config)
  222. {
  223. TQImage img;
  224. if (!getGroupImage(img, path, countryCode, group, config)) return; // could not find flag
  225. if (img.depth() <= 8) img = img.convertDepth(32);
  226. // the following code is taken from tdebase/kxkb/pixmap.cpp
  227. for (int y = 0; y < img.height(); y++)
  228. for(int x = 0; x < img.width(); x++) {
  229. TQRgb rgb = img.pixel(x, y);
  230. img.setPixel(x, y, tqRgb(tqRed(rgb)*3/4, tqGreen(rgb)*3/4, tqBlue(rgb)*3/4));
  231. }
  232. pix.convertFromImage(img);
  233. TQPainter painter(&pix);
  234. painter.setPen(TQt::black);
  235. painter.setFont(TQFont("helvetica", 10, TQFont::Bold));
  236. painter.drawText(1, 1, pix.width(), pix.height()-2, TQt::AlignCenter, langCode);
  237. painter.setPen(TQt::white);
  238. painter.drawText(0, 0, pix.width(), pix.height()-2, TQt::AlignCenter, langCode);
  239. }
  240. void KBConfig::drawDefaultPixmap(TQPixmap &pix, int group)
  241. {
  242. pix.resize(FLAG_ICON_WIDTH, FLAG_ICON_HEIGHT);
  243. TQPainter painter(&pix);
  244. pix.fill();
  245. painter.drawText(0, 0, pix.width(), pix.height(),
  246. TQt::AlignHCenter | TQt::AlignVCenter, TQString::number(group+1));
  247. }
  248. void KBConfig::checkKeysEnabled()
  249. {
  250. m_keys->setEnabled(m_use_shortcuts);
  251. m_keys->updateConnections();
  252. }
  253. /** No descriptions */
  254. /*void KBConfig::drawDefaultPixmaps(){
  255. TQPixmap pix(16, 16);
  256. TQPainter painter(&pix);
  257. for (unsigned int i = 0; i < m_groups.count(); i++) {
  258. if (m_groups[i]->getPixmap().isNull()) {
  259. pix.fill();
  260. painter.drawText(0, 0, pix.width(), pix.height(),
  261. TQt::AlignHCenter | TQt::AlignVCenter, TQString::number(i+1));
  262. m_groups[i]->setPixmap(pix);
  263. }
  264. }
  265. }*/
  266. /** No descriptions */
  267. /*void KBConfig::loadConfiguredPixmaps(TDEConfig *config){
  268. TQString path;
  269. TQPixmap pix;
  270. config->setGroup(ICONS_SECTION);
  271. for (unsigned int i = 0; i < m_groups.count(); i++) {
  272. path = config->readEntry(entryForGroup(i));
  273. if (!path.isEmpty() && pix.load(path))
  274. m_groups[i]->setPixmap(pix);
  275. }
  276. }*/
  277. /** No descriptions */
  278. /*void KBConfig::notifyChanged(){
  279. emit changed();
  280. }*/
  281. /*!
  282. \fn KBConfig::getXkbLayouts(const TQStringList &layouts)
  283. */
  284. void KBConfig::getXkbLayouts(TQStringList &layouts)
  285. {
  286. #if HAVE_X11_EXTENSIONS_XKBRULES_H && HAVE_LIBXKBFILE
  287. XkbRF_VarDefsRec vardefs;
  288. int i;
  289. usleep(10000);
  290. if (XkbRF_GetNamesProp(tqt_xdisplay(), NULL, &vardefs)) {
  291. layouts = TQStringList::split(',', vardefs.layout, true);
  292. for (TQStringList::Iterator it = layouts.begin(); it != layouts.end(); ++it) {
  293. i = 0;
  294. while ((*it)[i] >= 'a' && (*it)[i] <= 'z') i++;
  295. *it = (*it).left(i);
  296. }
  297. if (vardefs.layout) XFree(vardefs.layout);
  298. if (vardefs.model) XFree(vardefs.model);
  299. if (vardefs.variant) XFree(vardefs.variant);
  300. if (vardefs.options) XFree(vardefs.options);
  301. }
  302. #endif
  303. }