1 ////////////////////////////////////////
2 // File : xkbconf.cpp //
3 // Written by: disels@gmail.com //
5 ////////////////////////////////////////
9 QXKBconf::QXKBconf (QWidget
*parent
) : QDialog(parent
) {
10 xkb_conf
.setupUi(this);
11 // initialize the binding between list and stackedWidget
12 xkb_conf
.listWidget
->setCurrentRow(0);
13 QSettings
qxkb(QDir::homePath()+"/.config/qxkb.cfg", QSettings::IniFormat
, this);
14 qxkb
.beginGroup("Style");
15 theme
=qxkb
.value("path").toString();
16 ico_path
= theme
+"/language/";
17 qxkb
.endGroup(); //Style
18 qDebug() << "Theme " << theme
;
19 qDebug() << "Icons " << ico_path
;
20 xkbConf
= X11tools::loadXKBconf();
22 connect(xkb_conf
.buttonBox
, SIGNAL(rejected()), this, SLOT(close()));
23 connect(xkb_conf
.buttonBox
, SIGNAL(accepted()), SLOT(apply()));
24 connect(xkb_conf
.radioButton
, SIGNAL(clicked(bool)), SLOT(statSelect(bool)));
25 connect(xkb_conf
.radioButton_2
, SIGNAL(clicked(bool)), SLOT(statSelect(bool)));
26 connect(xkb_conf
.radioButton_3
, SIGNAL(clicked(bool)), SLOT(statSelect(bool)));
28 xkb_conf
.btnAdd
->setEnabled(false);
29 xkb_conf
.btnAdd
->setIcon(QIcon::fromTheme(QString("arrow-right"), QIcon(theme
+"/add.png")));
31 xkb_conf
.btnRemove
->setEnabled(false);
32 xkb_conf
.btnRemove
->setIcon(QIcon::fromTheme(QString("arrow-left"), QIcon(theme
+"/rem.png")));
34 xkb_conf
.btnUp
->setEnabled(false);
35 xkb_conf
.btnUp
->setIcon(QIcon::fromTheme(QString("arrow-up"), QIcon(theme
+"/up.png")));
37 xkb_conf
.btnDown
->setEnabled(false);
38 xkb_conf
.btnDown
->setIcon(QIcon::fromTheme(QString("arrow-down"), QIcon(theme
+"/down.png")));
40 if (!setStat()) return;
42 xkbConf
->lockKeys
= true;
46 QXKBconf::~QXKBconf () {
51 void QXKBconf::apply () {
52 X11tools::saveXKBconf(xkbConf
);
54 if (xkb_conf
.stackedWidget
->currentIndex() == 0) {
55 QStringList parm
= xkb_conf
.editCmdLine
->text().split(" ");
59 qDebug() << "parm:" << parm
;
60 qpres
= 0;//QProcess::execute("setxkbmap", parm);
61 qDebug() << "Set XKB result" << qpres
;
62 } else if (xkb_conf
.stackedWidget
->currentIndex() == 2) {
63 QStringList parm
= xkb_conf
.editCmdLineOpt
->text().split(" ");
67 qDebug() << "parm:" << parm
;
68 qpres
= 0;//QProcess::execute("setxkbmap", parm);
69 qDebug() << "Set XKB result" << qpres
;
77 void QXKBconf::statSelect (bool check
) {
80 if (xkb_conf
.radioButton
->isChecked()) xkbConf
->status
= 2;
81 if (xkb_conf
.radioButton_2
->isChecked()) xkbConf
->status
= 1;
82 if (xkb_conf
.radioButton_3
->isChecked()) xkbConf
->status
= 0;
83 if (!setStat()) return;
88 void QXKBconf::initXKBTab () {
89 connect(xkb_conf
.btnAdd
, SIGNAL(clicked()), SLOT(addLayout()));
90 connect(xkb_conf
.btnRemove
, SIGNAL(clicked()), SLOT(delLayout()));
93 QHashIterator
<QString
, QString
> i(curRule
->models
);
94 while (i
.hasNext()) { i
.next(); listModels
<< i
.value(); }
95 // set avaleble language
96 srcLayoutModel
= new SrcLayoutModel(curRule
, ico_path
, this);
98 dstLayoutModel
= new DstLayoutModel(curRule
, xkbConf
, ico_path
, this);
99 xkbOptionsModel
= new XkbOptionsModel(curRule
, xkbConf
, this);
100 xkb_conf
.comboModel
->addItems(listModels
);
101 xkb_conf
.comboModel
->setCurrentIndex(listModels
.indexOf(curRule
->models
.value(xkbConf
->model
)));
102 xkb_conf
.srcTableView
->setModel(srcLayoutModel
);
103 xkb_conf
.srcTableView
->resizeColumnToContents(0);
104 xkb_conf
.dstTableView
->setModel(dstLayoutModel
);
105 xkb_conf
.dstTableView
->resizeColumnToContents(0);
106 xkb_conf
.xkbOptionsTreeView
->setModel(xkbOptionsModel
);
107 xkb_conf
.xkbOptionsTreeView
->header()->hide();
108 xkb_conf
.xkbOptionsTreeView
->expandAll();
110 for (int f
= 0; f
< xkbConf
->options
.count(); ++f
) {
111 if (xkbConf
->options
[f
].contains("grp:")) xkb_conf
.btnXkbShortcut
->setText(tr("Defined"));
112 if (xkbConf
->options
[f
].contains("lv3:")) xkb_conf
.btnXkbShortcut3d
->setText(tr("Defined"));
115 switch (xkbConf
->switching
) {
116 case GLOBAL_LAYOUT
: xkb_conf
.rdBtnSwitchGlobal
->setChecked(true); break;
117 case APP_LAYOUT
: xkb_conf
.rdBtnSwitchPerApp
->setChecked(true); break;
118 case WIN_LAYOUT
: xkb_conf
.rdBtnSwitchPerWin
->setChecked(true); break;
121 connect(xkb_conf
.srcTableView
, SIGNAL(clicked (const QModelIndex
&)), SLOT(srcClick(QModelIndex
)));
122 connect(xkb_conf
.dstTableView
->selectionModel(), SIGNAL(selectionChanged(const QItemSelection
&, const QItemSelection
&)), SLOT(dstClick()));
123 connect(xkb_conf
.comboModel
, SIGNAL(currentIndexChanged (int)) , SLOT(comboModelCh(int)));
124 connect(xkb_conf
.comboVariant
, SIGNAL(currentIndexChanged (int)), SLOT(comboVariantCh(int)));
125 connect(xkb_conf
.btnUp
, SIGNAL(clicked()), SLOT(layoutUp()));
126 connect(xkb_conf
.btnDown
, SIGNAL(clicked()), SLOT(layoutDown()));
127 connect(xkbOptionsModel
, SIGNAL(dataChanged(const QModelIndex
&, const QModelIndex
&)), SLOT(xkbOptionsChanged(const QModelIndex
&, const QModelIndex
&)));
128 connect( xkb_conf
.btnXkbShortcut
, SIGNAL(clicked()), SLOT(xkbShortcutPressed()));
129 connect(xkb_conf
.btnXkbShortcut3d
, SIGNAL(clicked()), SLOT(xkbShortcut3dPressed()));
132 updateOptionsCommand();
136 bool QXKBconf::setStat () {
137 switch (xkbConf
->status
) {
139 xkb_conf
.grpIndicatorOptions
->setEnabled(false);
140 xkb_conf
.grpLayouts
->setEnabled(false);
141 xkb_conf
.page_2
->setEnabled(false);
142 xkb_conf
.page_3
->setEnabled(false);
143 xkb_conf
.radioButton
->setChecked(false);
144 xkb_conf
.radioButton_2
->setChecked(false);
145 xkb_conf
.radioButton_3
->setChecked(true);
147 case ONLY_INDICATION
:
148 xkb_conf
.grpIndicatorOptions
->setEnabled(true);
149 xkb_conf
.grpLayouts
->setEnabled(false);
150 xkb_conf
.page_2
->setEnabled(false);
151 xkb_conf
.page_3
->setEnabled(false);
152 xkb_conf
.radioButton
->setChecked(false);
153 xkb_conf
.radioButton_2
->setChecked(true);
154 xkb_conf
.radioButton_3
->setChecked(false);
155 xkb_conf
.chkShowFlag
->setChecked(xkbConf
->showFlag
);
156 xkb_conf
.chkShowSingle
->setChecked(xkbConf
->showSingle
);
157 connect(xkb_conf
.chkShowFlag
, SIGNAL(clicked()), SLOT(setFlagUse()));
158 connect(xkb_conf
.chkShowSingle
, SIGNAL(clicked()), SLOT(setSinglShow()));
161 xkb_conf
.grpIndicatorOptions
->setEnabled(true);
162 xkb_conf
.grpLayouts
->setEnabled(true);
163 xkb_conf
.page_2
->setEnabled(true);//not work yet
164 xkb_conf
.page_3
->setEnabled(true);
165 xkb_conf
.radioButton
->setChecked(true);
166 xkb_conf
.radioButton_2
->setChecked(false);
167 xkb_conf
.radioButton_3
->setChecked(false);
168 xkb_conf
.chkShowFlag
->setChecked(xkbConf
->showFlag
);
169 xkb_conf
.chkShowSingle
->setChecked(xkbConf
->showSingle
);
170 connect(xkb_conf
.chkShowFlag
, SIGNAL(clicked()), SLOT(setFlagUse()));
171 connect(xkb_conf
.chkShowSingle
, SIGNAL(clicked()), SLOT(setSinglShow()));
178 void QXKBconf::setCmdLine () {
179 QString cmdLine
= "setxkbmap -model "+xkbConf
->model
;
181 cmdLine
+= " -layout ";
182 for (int f
= 0;f
< xkbConf
->layouts
.size(); ++f
) {
183 cmdLine
+= xkbConf
->layouts
[f
].layout
;
184 if (f
< xkbConf
->layouts
.size()-1) cmdLine
+= ',';
187 cmdLine
+= " -variant ";
188 for (int f
= 0; f
< xkbConf
->layouts
.size(); ++f
) {
189 cmdLine
+= xkbConf
->layouts
[f
].variant
;
190 if (f
< xkbConf
->layouts
.size()-1) cmdLine
+= ',';
192 xkb_conf
.editCmdLine
->setText(cmdLine
);
196 void QXKBconf::addLayout () {
198 QItemSelectionModel
*selectionModel
= xkb_conf
.srcTableView
->selectionModel();
200 if (selectionModel
== NULL
|| !selectionModel
->hasSelection() || xkbConf
->layouts
.size() >= 4) return;
201 QModelIndexList selected
= selectionModel
->selectedRows();
202 qDebug() << "selected : " << selected
;
203 QString layout
= srcLayoutModel
->getLayoutAt(selected
[0].row());
204 if (layout
.isEmpty() || xkbConf
->layouts
.contains(layout
)) return;
206 xkbConf
->layouts
.append(lu
);
207 dstLayoutModel
->reset();
208 xkb_conf
.dstTableView
->update();
213 void QXKBconf::delLayout () {
214 QItemSelectionModel
*selectionModel
= xkb_conf
.dstTableView
->selectionModel();
215 if (selectionModel
== NULL
|| !selectionModel
->hasSelection()|| xkbConf
->layouts
.size() == 0) return;
216 QModelIndexList selected
= selectionModel
->selectedRows();
217 xkbConf
->layouts
.removeAt(selected
[0].row());
218 dstLayoutModel
->reset();
219 xkb_conf
.dstTableView
->update();
224 void QXKBconf::srcClick (QModelIndex index
) {
226 xkb_conf
.btnAdd
->setEnabled(true);
230 void QXKBconf::dstClick () {
231 int row
= getSelectedDstLayout();
232 xkb_conf
.btnRemove
->setEnabled(row
!=-1);
233 int el_count
= xkb_conf
.comboVariant
->count();
234 for (int f
= el_count
; f
> 0; --f
) xkb_conf
.comboVariant
->removeItem(f
);
235 //xkb_conf.comboVariant->clear(); some sheet seg fail in use
236 xkb_conf
.comboVariant
->setEnabled(row
!=-1);
237 xkb_conf
.btnUp
->setEnabled(row
!=-1);
238 xkb_conf
.btnDown
->setEnabled(row
!=-1);
239 if (row
== -1) return;
240 QString layout
= xkbConf
->layouts
[row
].layout
;
242 variants
= X11tools::getVariants(layout
, X11tools::findX11Dir());
243 qDebug() << "QXKBconf:addItem";
244 if (xkb_conf
.comboVariant
->count() == 0) {
245 xkb_conf
.comboVariant
->addItem(tr("Default"), "Default");
246 xkb_conf
.comboVariant
->setItemData(0, tr("Default"), Qt::ToolTipRole
);
247 xkb_conf
.comboVariant
->setItemText(0, tr("Default"));
249 if (variants
.count() > 0) {
250 for (int f
= 0; f
< variants
.count(); ++f
) {
251 xkb_conf
.comboVariant
->addItem(variants
[f
].description
, variants
[f
].name
);
252 xkb_conf
.comboVariant
->setItemData(xkb_conf
.comboVariant
->count()-1, variants
[f
].description
, Qt::ToolTipRole
);
254 QString variant
= xkbConf
->layouts
[row
].variant
;
255 if (variant
!= NULL
&& !variant
.isEmpty()) {
256 int idx
= xkb_conf
.comboVariant
->findData(variant
);
257 xkb_conf
.comboVariant
->setCurrentIndex(idx
);
259 xkb_conf
.comboVariant
->setCurrentIndex(0);
265 bool QXKBconf::load_rules () {
266 QString x11dir
= X11tools::findX11Dir();
267 if (x11dir
.isNull() || x11dir
.isEmpty()) return false;
268 QString rulesFile
= X11tools::findXkbRulesFile(x11dir
, QX11Info::display());
269 if (rulesFile
.isNull() || rulesFile
.isEmpty()) return false;
270 curRule
= X11tools::loadRules(rulesFile
, false);
271 if (curRule
== NULL
) return false;
276 void QXKBconf::comboModelCh (int index
) {
277 xkbConf
->model
= curRule
->models
.key(xkb_conf
.comboModel
->itemText(index
));
282 void QXKBconf::comboVariantCh (int index
) {
283 if (index
== 0) xkbConf
->layouts
[getSelectedDstLayout()].variant
= "";
284 else if (index
< variants
.count()) xkbConf
->layouts
[getSelectedDstLayout()].variant
= variants
.at(index
-1).name
; // it sometimes crashed here with "index out of bounds"
289 int QXKBconf::getSelectedDstLayout () {
290 QItemSelectionModel
*selectionModel
= xkb_conf
.dstTableView
->selectionModel();
291 if (selectionModel
== NULL
|| !selectionModel
->hasSelection()) return -1;
292 QModelIndexList selected
= selectionModel
->selectedRows();
293 int row
= selected
.count() > 0 ? selected
[0].row() : -1;
298 void QXKBconf::setFlagUse () {
299 xkbConf
->showFlag
= xkb_conf
.chkShowFlag
->isChecked();
303 void QXKBconf::setSinglShow () {
304 xkbConf
->showSingle
= xkb_conf
.chkShowSingle
->isChecked();
308 void QXKBconf::layoutUp () {
309 int row
= getSelectedDstLayout();
311 LayoutUnit lu
= xkbConf
->layouts
[row
-1];
312 xkbConf
->layouts
[row
-1] = xkbConf
->layouts
[row
];
313 xkbConf
->layouts
[row
] = lu
;
314 dstLayoutModel
->reset();
315 xkb_conf
.dstTableView
->update();
321 void QXKBconf::layoutDown () {
322 int row
= getSelectedDstLayout();
323 if (row
< xkbConf
->layouts
.count()-1 && row
> -1) {
324 LayoutUnit lu
= xkbConf
->layouts
[row
+1];
325 xkbConf
->layouts
[row
+1]=xkbConf
->layouts
[row
];
326 xkbConf
->layouts
[row
]=lu
;
327 dstLayoutModel
->reset();
333 void QXKBconf::updateOptionsCommand () {
334 QString cmd
= "setxkbmap";
335 if (xkb_conf
.checkResetOld
->isChecked()) cmd
+= " -option";
336 if (!xkbConf
->options
.empty()) {
338 cmd
+= xkbConf
->options
.join(",");
340 xkb_conf
.editCmdLineOpt
->setText(cmd
);
344 void QXKBconf::xkbOptionsChanged (const QModelIndex
&topLeft
, const QModelIndex
&bottomRight
) {
346 Q_UNUSED(bottomRight
)
347 updateOptionsCommand();
351 void QXKBconf::closeEvent (QCloseEvent
*event
) {
352 xkbConf
->lockKeys
= false;
358 void QXKBconf::xkbShortcutPressed () {
359 xkb_conf
.stackedWidget
->setCurrentIndex(2);
360 xkbOptionsModel
->gotoGroup("grp", xkb_conf
.xkbOptionsTreeView
);
364 void QXKBconf::xkbShortcut3dPressed () {
365 xkb_conf
.stackedWidget
->setCurrentIndex(2);
366 xkbOptionsModel
->gotoGroup("lv3", xkb_conf
.xkbOptionsTreeView
);
370 void QXKBconf::statSwitching (bool check
) {
372 if (xkb_conf
.rdBtnSwitchGlobal
->isChecked()) xkbConf
->switching
= 2;
373 if (xkb_conf
.rdBtnSwitchPerApp
->isChecked()) xkbConf
->switching
= 1;
374 if (xkb_conf
.rdBtnSwitchPerWin
->isChecked()) xkbConf
->switching
= 0;
378 void QXKBconf::getHotKeys (XEvent
*event
) {
379 XKeyEvent
*keys
= (XKeyEvent
*)event
;
381 switch (XKeycodeToKeysym(QX11Info::display(), keys
->keycode
, 0)) {
398 key
= QString(XKeysymToString(XKeycodeToKeysym(QX11Info::display(), keys
->keycode
, 0)));
399 if (key
.count() < 2) key
= key
.toUpper();
401 if (!mods
.isEmpty()) hot_keys
=mods
+"+"+key
;
402 else if (key
.count() > 1) hot_keys
= key
;
406 void QXKBconf::clearHotKeys () {
407 qDebug() << "QXKBconf:: Kurrent mods " << mods
;
408 if (mods
.isEmpty()) return;
409 qDebug() << "QXKBconf:: Kurrent key " << key
;
410 if (!key
.isEmpty()) return;