libsax 7.2

keyboard.cpp

00001 /**************
00002 FILE          : keyboard.cpp
00003 ***************
00004 PROJECT       : SaX2 - library interface
00005               :
00006 AUTHOR        : Marcus Schäfer <ms@suse.de>
00007               :
00008 BELONGS TO    : SaX2 - SuSE advanced X11 configuration 
00009               : 
00010               :
00011 DESCRIPTION   : native C++ class library to access SaX2
00012               : functionality. Easy to use interface for
00013               : //.../
00014               : - importing/exporting X11 configurations
00015               : - modifying/creating X11 configurations 
00016               : ---
00017               :
00018               :
00019 STATUS        : Status: Development
00020 **************/
00021 #include "keyboard.h"
00022 #if QT_VERSION > 0x040100
00023 #include <Q3TextStream>
00024 #else
00025 typedef QTextStream Q3TextStream;
00026 #endif
00027 
00028 namespace SaX {
00029 //====================================
00030 // Constructor
00031 //------------------------------------
00032 SaXKeyRules::SaXKeyRules (QString rule): mLayouts(80) {
00033         // .../
00037         // ----
00038         mX11Dir = "/usr/lib/X11/";
00039         if (! access ("/usr/share/X11/xkb",R_OK|X_OK)) {
00040                 mX11Dir = "/usr/share/X11/";
00041         }
00042         loadRules (mX11Dir + QString("xkb/rules/%1").arg(rule));
00043 }
00044 
00045 //====================================
00046 // loadRules
00047 //------------------------------------
00048 void SaXKeyRules::loadRules(QString file) {
00049         // .../
00052         // ----
00053         static struct {
00054                 const char * locale;
00055                 const char * layout;
00056         } fixedLayouts[] = {
00057                 { "ben", "Bengali" },
00058                 { "ar" , "Arabic"  },
00059                 { "ir" , "Farsi"   },
00060                 { 0    , 0 }
00061         };
00062         char* locale = setlocale (LC_ALL,NULL);
00063         XkbRF_RulesPtr rules = XkbRF_Load (
00064                 QFile::encodeName(file).data(),
00065                 locale, true, true
00066         );
00067         if (! rules) {
00068                 excXKBLoadRulesFailed();
00069                 qError (errorString(),EXC_XKBLOADRULESFAILED);
00070                 return;
00071         }
00072         int i;
00073         for (i = 0; i < rules->models.num_desc; ++i) {
00074                 QString* item = new QString (rules->models.desc[i].desc);
00075                 if ( item->length() > 50 ) {
00076                         item->truncate ( 50 ); item->append ("...");
00077                 }
00078                 mModels.replace (
00079                         rules->models.desc[i].name,item
00080                 );
00081         }
00082         for (i = 0; i < rules->layouts.num_desc; ++i) {
00083                 mLayouts.replace (
00084                         rules->layouts.desc[i].name,
00085                         new QString (rules->layouts.desc[i].desc)
00086                 );
00087         }
00088         for (i = 0; i < rules->options.num_desc; ++i) {
00089                 mOptions.replace (
00090                         rules->options.desc[i].name,
00091                         new QString (rules->options.desc[i].desc)
00092                 );
00093         }
00094         XkbRF_Free(rules, true);
00095         // ...
00096         // Knowing which variants we have won't help us
00097         // We want to know which particular variants are available for
00098         // each language
00099         // ---
00100         for(int i=0; fixedLayouts[i].layout != 0; i++ ) {
00101                 mLayouts.replace (
00102                         fixedLayouts[i].locale, new QString (fixedLayouts[i].layout)
00103                 );
00104         }
00105 }
00106 
00107 //====================================
00108 // getVariants
00109 //------------------------------------
00110 QList<QString> SaXKeyRules::getVariants (const QString& layout) {
00111         // .../
00114         // ----
00115         if ( layout.isEmpty() || ! getLayouts().find(layout) ) {
00116                 QList<QString>* nope = new QList<QString>;
00117                 return *nope;
00118         }
00119         QList<QString> result1;
00120         QStringList* r1 = mVarLists[layout];
00121         if ( r1 ) {
00122                 for ( QStringList::Iterator it=r1->begin(); it != r1->end(); ++it ) {
00123                         result1.append (*it);
00124                 }
00125                 return result1;
00126         }
00127         QList<QString> result2;
00128         QStringList* result = new QStringList();
00129         QString file = mX11Dir + "xkb/symbols/" + layout;
00130         QFile f(file);
00131         if (f.open(QIODevice::ReadOnly)) {
00132                 Q3TextStream ts(&f);
00133                 QString line;
00134                 QString prev_line;
00135                 while (!ts.atEnd()) {
00136                         prev_line = line;
00137                         line = ts.readLine().simplifyWhiteSpace();
00138                         if (line[0] == '#' || line.left(2) == "//" || line.isEmpty()) {
00139                                 continue;
00140                         }
00141                         int pos = line.find("xkb_symbols");
00142                         if (pos < 0) {
00143                                 continue;
00144                         }
00145                         if ( prev_line.find("hidden") >=0 ) {
00146                                 continue;
00147                         }
00148                         pos = line.find('"', pos) + 1;
00149                         int pos2 = line.find('"', pos);
00150                         if ( pos < 0 || pos2 < 0 ) {
00151                                 continue;
00152                         }
00153                         result->append (
00154                                 line.mid(pos, pos2-pos)
00155                         );
00156                 }
00157                 f.close();
00158         }
00159         mVarLists.insert(layout, result);
00160         for ( QStringList::Iterator it=result->begin(); it != result->end();++it) {
00161                 result2.append (*it);
00162         }
00163         return result2;
00164 }
00165 
00166 //====================================
00167 // getModels
00168 //------------------------------------
00169 Q3Dict<QString> SaXKeyRules::getModels  (void) {
00170         return mModels;
00171 }
00172 
00173 //====================================
00174 // getLayouts
00175 //------------------------------------
00176 Q3Dict<QString> SaXKeyRules::getLayouts (void) {
00177         return mLayouts;
00178 }
00179 
00180 //====================================
00181 // getOptions
00182 //------------------------------------
00183 Q3Dict<QString> SaXKeyRules::getOptions (void) {
00184         return mOptions;
00185 }
00186 
00187 //====================================
00188 // Constructor...
00189 //------------------------------------
00190 SaXManipulateKeyboard::SaXManipulateKeyboard (
00191         SaXImport* in, int kbd
00192 ) : SaXManipulateKeyboardIF () {
00193         // .../
00198         // ----
00199         if ( ! in ) {
00200                 excNullPointerArgument ();
00201                 qError (errorString(),EXC_NULLPOINTERARGUMENT);
00202                 return;
00203         }
00204         if ( in->getSectionID() != SAX_KEYBOARD ) {
00205                 excKeyboardImportBindFailed ( in->getSectionID() );
00206                 qError (errorString(),EXC_KEYBOARDIMPORTBINDFAILED);
00207                 return;
00208         }
00209         mImport = in;
00210         mKeyboard = kbd;
00211         mImport -> setID ( mKeyboard );
00212 }
00213 
00214 //====================================
00215 // set keyboard ID
00216 //------------------------------------
00217 bool SaXManipulateKeyboard::selectKeyboard (int ptr) {
00218         // .../
00221         // ----
00222         if (! mImport) {
00223                 return false;
00224         }
00225         if (mImport -> setID ( ptr )) {
00226                 mKeyboard = ptr;
00227                 return true;
00228         }
00229         return false;
00230 }
00231 
00232 //====================================
00233 // setXKBModel
00234 //------------------------------------
00235 void SaXManipulateKeyboard::setXKBModel (const QString& model) {
00236         // .../
00239         // ----
00240         if (! mImport) {
00241                 return;
00242         }
00243         mImport -> setItem ( "XkbModel",model );
00244 }
00245 
00246 //====================================
00247 // setXKBLayout
00248 //------------------------------------
00249 void SaXManipulateKeyboard::setXKBLayout (const QString& layout) {
00250         // .../
00253         // ----
00254         if (! mImport) {
00255                 return;
00256         }
00257         mImport -> setItem ( "XkbLayout",layout );
00258 }
00259 
00260 //====================================
00261 // addXKBLayout
00262 //------------------------------------
00263 void SaXManipulateKeyboard::addXKBLayout (const QString& layout) {
00264         // .../
00268         // ----
00269         if (! mImport) {
00270                 return;
00271         }
00272         QString val;
00273         QString key ("XkbLayout");
00274         if (! mImport -> getItem (key).isEmpty()) {
00275                 val = mImport -> getItem (key);
00276         }
00277         QTextOStream (&val) << "," << layout;
00278         mImport -> setItem ( key,val );
00279 }
00280 
00281 //====================================
00282 // removeXKBLayout
00283 //------------------------------------
00284 void SaXManipulateKeyboard::removeXKBLayout (const QString& layout) {
00285         // .../
00288         // ----
00289         if (! mImport) {
00290                 return;
00291         }
00292         QString val (layout);
00293         QString key ("XkbLayout");
00294         if (! mImport -> getItem (key).isEmpty()) {
00295                 mImport -> removeItem (key,val);
00296         }
00297 }
00298 
00299 //====================================
00300 // setXKBOption
00301 //------------------------------------
00302 void SaXManipulateKeyboard::setXKBOption (const QString& option) {
00303         // .../
00306         // ----
00307         if (! mImport) {
00308                 return;
00309         }
00310         mImport -> setItem ( "XkbOptions",option );
00311 }
00312 
00313 //====================================
00314 // addXKBOption
00315 //------------------------------------
00316 void SaXManipulateKeyboard::addXKBOption (const QString& option) {
00317         // .../
00320         // ----
00321         if (! mImport) {
00322                 return;
00323         }
00324         QString val;
00325         QString key ("XkbOptions");
00326         if (! mImport -> getItem (key).isEmpty()) {
00327                 val = mImport -> getItem (key);
00328         }
00329         QTextOStream (&val) << "," << option;
00330         mImport -> setItem ( key,val );
00331 }
00332 
00333 //====================================
00334 // removeXKBOption
00335 //------------------------------------
00336 void SaXManipulateKeyboard::removeXKBOption (const QString& option) {
00337         // .../
00340         // ----
00341         if (! mImport) {
00342                 return;
00343         }
00344         QString val (option);
00345         QString key ("XkbOptions");
00346         if (! mImport -> getItem (key).isEmpty()) {
00347                 mImport -> removeItem (key,val);
00348         }
00349 }
00350 
00351 //====================================
00352 // setXKBVariant
00353 //------------------------------------
00354 void SaXManipulateKeyboard::setXKBVariant (
00355         const QString& layout, const QString& variant
00356 ) {
00357         // .../
00360         // ----
00361         if (! mImport) {
00362                 return;
00363         }
00364         int layoutCount = findLayout (layout);
00365         if (layoutCount < 0) {
00366                 excXKBLayoutUndefined (layout);
00367                 qError (errorString(),EXC_XKBLAYOUTUNDEFINED);
00368                 return;
00369         }
00370         QList<QString> vList = getXKBVariantList();
00371         QList<QString> lList = getXKBLayout();
00372         QStringList result;
00373         QString it;
00374         for (int varCount = 0; varCount < lList.count(); varCount++) {
00375                 QString item;
00376                 if (!vList.value(varCount).isNull()) {
00377                         item = vList.value(varCount);
00378                 }
00379                 if (varCount == layoutCount) {
00380                         item = variant;
00381                 }
00382                 result += item;
00383         }
00384         mImport -> setItem ("XkbVariant",result.join(","));
00385 }
00386 
00387 //====================================
00388 // removeXKBVariant
00389 //------------------------------------
00390 void SaXManipulateKeyboard::removeXKBVariant ( const QString& layout ) {
00391         // .../
00394         // ----
00395         setXKBVariant (layout,"");
00396 }
00397 
00398 //====================================
00399 // setMapping
00400 //------------------------------------
00401 void SaXManipulateKeyboard::setMapping (
00402         const QString& type,const QString& mapping
00403 ) {
00404         // .../
00408         // ----
00409         if (! mImport) {
00410                 return;
00411         }
00412         QString key (type);
00413         QString map (mapping);
00414         if (
00415                 (key != XKB_LEFT_ALT)       &&
00416                 (key != XKB_RIGHT_ALT)      &&
00417                 (key != XKB_SCROLL_LOCK)    &&
00418                 (key != XKB_RIGHT_CTL)
00419         ) {
00420                 excInvalidArgument (type.latin1());
00421                 qError (errorString(),EXC_INVALIDARGUMENT);
00422                 return;
00423         }
00424         if (
00425                 (map != XKB_MAP_META)       &&
00426                 (map != XKB_MAP_COMPOSE)    &&
00427                 (map != XKB_MAP_MODESHIFT)  &&
00428                 (map != XKB_MAP_MODELOCK)   &&
00429                 (map != XKB_MAP_SCROLLLOCK) &&
00430                 (map != XKB_MAP_CONTROL)
00431         ) {
00432                 excInvalidArgument (mapping.latin1());
00433                 qError (errorString(),EXC_INVALIDARGUMENT);
00434                 return;
00435         }
00436         mImport -> setItem ( type,mapping );
00437 }
00438 
00439 //====================================
00440 // getDriver
00441 //------------------------------------
00442 QString SaXManipulateKeyboard::getDriver (void) {
00443         // .../
00445         // ----
00446         if (! mImport) {
00447                 QString* nope = new QString;
00448                 return *nope;
00449         }
00450         return mImport -> getItem ("Driver");
00451 }
00452 
00453 //====================================
00454 // getXKBOptionList
00455 //------------------------------------
00456 QList<QString> SaXManipulateKeyboard::getXKBOptionList (void) {
00457         // .../
00459         // ----
00460         if (! mImport) {
00461                 QList<QString>* nope = new QList<QString>;
00462                 return *nope;
00463         }
00464         QString options = mImport -> getItem ("XkbOptions");
00465         return createList (options);
00466 }
00467 
00468 //====================================
00469 // getXKBLayout
00470 //------------------------------------
00471 QList<QString> SaXManipulateKeyboard::getXKBLayout (void) {
00472         // .../
00475         // ----
00476         if (! mImport) {
00477                 QList<QString>* nope = new QList<QString>;
00478                 return *nope;
00479         }
00480         QString layouts = mImport -> getItem ("XkbLayout");
00481         return createList (layouts);
00482 }
00483 
00484 //====================================
00485 // getXKBVariantList
00486 //------------------------------------
00487 QList<QString> SaXManipulateKeyboard::getXKBVariantList (void) {
00488         // .../
00491         // ----
00492         if (! mImport) {
00493                 QList<QString>* nope = new QList<QString>;
00494                 return *nope;
00495         }
00496         QString variants = mImport -> getItem ("XkbVariant");
00497         return createList (variants);
00498 }
00499 
00500 //====================================
00501 // getXKBVariant for layout X
00502 //------------------------------------
00503 QString SaXManipulateKeyboard::getXKBVariant ( const QString& layout ) {
00504         // .../
00509         // ----
00510         if (! mImport) {
00511                 QString* nope = new QString;
00512                 return *nope;
00513         }
00514         int layoutCount = findLayout (layout);
00515         if (layoutCount < 0) {
00516                 excXKBLayoutUndefined (layout);
00517                 qError (errorString(),EXC_XKBLAYOUTUNDEFINED);
00518                 QString* nope = new QString;
00519                 return *nope;
00520         }
00521         int varCount = 0;
00522         QList<QString> vList = getXKBVariantList();
00523         QString it;
00524         foreach (it,vList) {
00525                 if (varCount == layoutCount) {
00526                         return it;
00527                 }
00528                 varCount++;
00529         }
00530         QString* nope = new QString;
00531         return *nope;
00532 }
00533 
00534 //====================================
00535 // getXKBModel
00536 //------------------------------------
00537 QString SaXManipulateKeyboard::getXKBModel (void) {
00538         // .../
00541         // ----
00542         if (! mImport) {
00543                 QString* nope = new QString;
00544                 return *nope;
00545         }
00546         return mImport -> getItem ("XkbModel");
00547 }
00548 
00549 //====================================
00550 // findLayout
00551 //------------------------------------
00552 int SaXManipulateKeyboard::findLayout (const QString& layout) {
00553         // .../
00557         // ----
00558         int count  = 0;
00559         bool found = false;
00560         QString layoutData = mImport -> getItem ("XkbLayout");
00561         QStringList layouts = QStringList::split ( ",", layoutData );
00562         for (QStringList::Iterator it=layouts.begin(); it!=layouts.end();++ it) {
00563                 QString item (*it);
00564                 if (item == layout) {
00565                         found = true; break;
00566                 }
00567                 count++;
00568         }
00569         if (! found) {
00570                 return -1;
00571         }
00572         return count;
00573 }
00574 
00575 //====================================
00576 // transform string to Qlist
00577 //------------------------------------
00578 QList<QString> SaXManipulateKeyboard::createList ( const QString& data) {
00579         // .../
00582         // ----
00583         if (data.isEmpty()) {
00584                 QList<QString>* nope = new QList<QString>;
00585                 return *nope;
00586         }
00587         QList<QString> result; 
00588         QStringList dataList = QStringList::split ( ",", data, true );
00589         for (QStringList::Iterator it=dataList.begin(); it!=dataList.end();++ it) {
00590                 result.append (*it);
00591         }
00592         return result;
00593 }
00594 } // end namespace