00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "tabkeyboardshortcutswidget.h"
00027
00028 #include <QComboBox>
00029 #include <QDataStream>
00030 #include <QDir>
00031 #include <QDomDocument>
00032 #include <QFile>
00033 #include <QFileInfo>
00034 #include <QFileDialog>
00035 #include <QInputDialog>
00036 #include <QKeySequence>
00037 #include <QLabel>
00038 #include <QListWidget>
00039 #include <QMessageBox>
00040 #include <QPushButton>
00041 #include <QRadioButton>
00042 #include <QTextStream>
00043 #include <QList>
00044 #include <QEvent>
00045
00046 #include "actionmanager.h"
00047 #include "commonstrings.h"
00048 #include "pluginmanager.h"
00049 #include "prefsmanager.h"
00050 #include "prefsfile.h"
00051 #include "prefscontext.h"
00052 #include "scpaths.h"
00053 #include "scplugin.h"
00054 #include "scraction.h"
00055 #include "util.h"
00056 #include "util_icon.h"
00057
00058 TabKeyboardShortcutsWidget::TabKeyboardShortcutsWidget(QMap<QString, Keys> oldKeyMap, QWidget *parent, const char *name)
00059 :QWidget(parent)
00060 {
00061 setupUi(this);
00062 setObjectName(name);
00063 ActionManager::createDefaultMenus();
00064 ActionManager::createDefaultNonMenuActions();
00065 defMenus=ActionManager::defaultMenus();
00066 defNonMenuActions=ActionManager::defaultNonMenuActions();
00067
00068 QVector< QPair<QString, QStringList> >::Iterator itnmenua = defNonMenuActions->begin();
00069 PluginManager& pluginManager(PluginManager::instance());
00070 QStringList pluginNames(pluginManager.pluginNames(false));
00071 ScPlugin* plugin;
00072 ScActionPlugin* ixplug;
00073 QString pName;
00074 for (int i = 0; i < pluginNames.count(); ++i)
00075 {
00076 pName = pluginNames.at(i);
00077 plugin = pluginManager.getPlugin(pName, true);
00078 Q_ASSERT(plugin);
00079 if (plugin->inherits("ScActionPlugin"))
00080 {
00081 ixplug = dynamic_cast<ScActionPlugin*>(plugin);
00082 Q_ASSERT(ixplug);
00083 ScActionPlugin::ActionInfo ai(ixplug->actionInfo());
00084 itnmenua->second << ai.name;
00085 }
00086 }
00087
00088 Q_CHECK_PTR(defMenus);
00089 lviToActionMap.clear();
00090 lviToMenuMap.clear();
00091 keyTable->clear();
00092 keyMap.clear();
00093 keyMap = oldKeyMap;
00094 Part0 = "";
00095 Part1 = "";
00096 Part2 = "";
00097 Part3 = "";
00098 Part4 = "";
00099 keyCode = 0;
00100 keyDisplay->setMinimumWidth(fontMetrics().width("CTRL+ALT+SHIFT+W"));
00101 keyDisplay->setText("");
00102
00103 clearSearchButton->setIcon(loadIcon("clear_right.png"));
00104
00105 connect( keyTable, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
00106 this, SLOT(dispKey(QTreeWidgetItem *, QTreeWidgetItem *)));
00107 connect( noKey, SIGNAL(clicked()), this, SLOT(setNoKey()));
00108 connect( setKeyButton, SIGNAL(clicked()), this, SLOT(setKeyText()));
00109 connect( loadSetButton, SIGNAL(clicked()), this, SLOT(loadKeySetFile()));
00110 connect( importSetButton, SIGNAL(clicked()), this, SLOT(importKeySetFile()));
00111 connect( exportSetButton, SIGNAL(clicked()), this, SLOT(exportKeySetFile()));
00112 connect( resetSetButton, SIGNAL(clicked()), this, SLOT(resetKeySet()));
00113 connect( clearSearchButton, SIGNAL(clicked()), this, SLOT(clearSearchString()));
00114 connect( searchTextLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(applySearch(const QString&)));
00115 }
00116
00117 void TabKeyboardShortcutsWidget::restoreDefaults()
00118 {
00119 loadableSets->clear();
00120 loadableSets->addItems(scanForSets());
00121 insertActions();
00122 dispKey(0);
00123 }
00124
00125 const QMap<QString, Keys> TabKeyboardShortcutsWidget::getNewKeyMap()
00126 {
00127 return keyMap;
00128 }
00129
00130 void TabKeyboardShortcutsWidget::setNoKey()
00131 {
00132 if (noKey->isChecked())
00133 {
00134 if (selectedLVI!=0)
00135 {
00136 selectedLVI->setText(1,"");
00137 keyMap[lviToActionMap[selectedLVI]].keySequence=QKeySequence();
00138 }
00139 keyDisplay->setText("");
00140 noKey->setChecked(true);
00141 }
00142 }
00143
00144 void TabKeyboardShortcutsWidget::loadKeySetFile()
00145 {
00146 if (keySetList.contains(loadableSets->currentText()))
00147 importKeySet(keySetList[loadableSets->currentText()]);
00148 }
00149
00150 void TabKeyboardShortcutsWidget::importKeySetFile()
00151 {
00152 PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
00153 QString currentPath = dirs->get("keymapprefs_import", ScPaths::instance().shareDir() + "keysets/");
00154 QString s = QFileDialog::getOpenFileName(this, tr("Select a Key set file to read"), currentPath, tr("Key Set XML Files (*.xml)"));
00155 if (!s.isEmpty())
00156 importKeySet(s);
00157 }
00158 void TabKeyboardShortcutsWidget::exportKeySetFile()
00159 {
00160 PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
00161 QString currentPath= dirs->get("keymapprefs_export", ".");
00162 QString s = QFileDialog::getSaveFileName(this, tr("Select a Key set file to save to"), currentPath, tr("Key Set XML Files (*.xml)") );
00163 if (!s.isEmpty())
00164 exportKeySet(s);
00165 }
00166
00167 void TabKeyboardShortcutsWidget::importKeySet(QString filename)
00168 {
00169 searchTextLineEdit->clear();
00170 QFileInfo fi = QFileInfo(filename);
00171 if (fi.exists())
00172 {
00173
00174 QDomDocument doc( "keymapentries" );
00175 QFile file1( filename );
00176 if ( !file1.open( QIODevice::ReadOnly ) )
00177 return;
00178 QTextStream ts(&file1);
00179 ts.setCodec("UTF-8");
00180 QString errorMsg;
00181 int eline;
00182 int ecol;
00183 if ( !doc.setContent( ts.readAll(), &errorMsg, &eline, &ecol ))
00184 {
00185 qDebug("%s", QString("Could not open key set file: %1\nError:%2 at line: %3, row: %4").arg(filename).arg(errorMsg).arg(eline).arg(ecol).toAscii().constData());
00186 file1.close();
00187 return;
00188 }
00189 file1.close();
00190
00191 QDomElement docElem = doc.documentElement();
00192 if (docElem.tagName()=="shortcutset" && docElem.hasAttribute("name"))
00193 {
00194 QDomAttr keysetAttr = docElem.attributeNode( "name" );
00195
00196
00197 for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=keyMap.end(); ++it)
00198 it.value().keySequence = QKeySequence();
00199
00200
00201 QDomNode n = docElem.firstChild();
00202 while( !n.isNull() )
00203 {
00204 QDomElement e = n.toElement();
00205 if( !e.isNull() )
00206 {
00207 if (e.hasAttribute("name") && e.hasAttribute( "shortcut" ))
00208 {
00209 QDomAttr nameAttr = e.attributeNode( "name" );
00210 QDomAttr shortcutAttr = e.attributeNode( "shortcut" );
00211 if (keyMap.contains(nameAttr.value()))
00212 keyMap[nameAttr.value()].keySequence=QKeySequence(shortcutAttr.value());
00213 }
00214 }
00215 n = n.nextSibling();
00216 }
00217 }
00218 }
00219 insertActions();
00220 }
00221
00222 bool TabKeyboardShortcutsWidget::exportKeySet(QString filename)
00223 {
00224 QFileInfo fi = QFileInfo(filename);
00225 QString exportFileName;
00226 if (filename.endsWith(".xml"))
00227 exportFileName = filename;
00228 else
00229 exportFileName = filename+".xml";
00230 if (overwrite(this, exportFileName))
00231 {
00232 bool ok;
00233 QString setName = QInputDialog::getText(this, tr("Export Keyboard Shortcuts to File"), tr("Enter the name of the shortcut set:"), QLineEdit::Normal, QString::null, &ok);
00234 if (!( ok && !setName.isEmpty()) )
00235 return false;
00236
00237 QDomDocument doc( "keymapentries" );
00238 QString keyset=QString("<shortcutset name=\"%1\"></shortcutset>").arg(setName);
00239 doc.setContent(keyset);
00240 QDomElement keySetElement=doc.documentElement();
00241 QMap<QString,Keys>::Iterator itEnd=keyMap.end();
00242 for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=itEnd; ++it)
00243 {
00244 if (it.value().keySequence.isEmpty() && it.key().isEmpty())
00245 continue;
00246 QDomElement function_shortcut=doc.createElement("function");
00247 function_shortcut.setAttribute("name",it.key());
00248 function_shortcut.setAttribute("shortcut",getKeyText(it.value().keySequence));
00249 keySetElement.appendChild(function_shortcut);
00250 }
00251 QFile f(filename);
00252 if(!f.open(QIODevice::WriteOnly))
00253 return false;
00254 QDataStream s(&f);
00255 QByteArray xmltag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00256 s.writeRawData(xmltag.data(), xmltag.length());
00257 QByteArray xmldoc = doc.toByteArray(4);
00258 s.writeRawData(xmldoc, xmldoc.length());
00259 f.close();
00260 }
00261 return true;
00262 }
00263
00264 void TabKeyboardShortcutsWidget::resetKeySet()
00265 {
00266 QString location=ScPaths::instance().shareDir();
00267 QString defaultKeySetFileName=QDir::convertSeparators(location+"keysets/scribus13.xml");
00268 importKeySet(defaultKeySetFileName);
00269 }
00270
00271 QStringList TabKeyboardShortcutsWidget::scanForSets()
00272 {
00273 keySetList.clear();
00274 QString location=ScPaths::instance().shareDir();
00275 QString keySetLocation=QDir::convertSeparators(location+"keysets/");
00276 QDir keySetsDir(keySetLocation, "*.xml", QDir::Name, QDir::Files | QDir::NoSymLinks);
00277 if ((keySetsDir.exists()) && (keySetsDir.count() != 0))
00278 {
00279 QStringList appNames;
00280 for (uint fileCounter = 0; fileCounter < keySetsDir.count(); ++fileCounter)
00281 {
00282 QString filename=QDir::convertSeparators(location+"keysets/"+keySetsDir[fileCounter]);
00283
00284 QDomDocument doc( "keymapentries" );
00285 QFile file( filename );
00286 if ( !file.open( QIODevice::ReadOnly ) )
00287 continue;
00288 QString errorMsg;
00289 int eline;
00290 int ecol;
00291
00292 if ( !doc.setContent( &file, &errorMsg, &eline, &ecol ))
00293 {
00294 qDebug("%s", QString("Could not open key set file: %1\nError:%2 at line: %3, row: %4").arg(keySetsDir[fileCounter]).arg(errorMsg).arg(eline).arg(ecol).toAscii().constData());
00295 file.close();
00296 continue;
00297 }
00298 file.close();
00299
00300 QDomElement docElem = doc.documentElement();
00301 if (docElem.tagName()=="shortcutset" && docElem.hasAttribute("name"))
00302 {
00303 QDomAttr nameAttr = docElem.attributeNode( "name" );
00304 appNames.append(nameAttr.value());
00305 keySetList.insert(nameAttr.value(), filename);
00306 }
00307 }
00308 return QStringList(appNames);
00309 }
00310 return QStringList();
00311 }
00312
00313 QString TabKeyboardShortcutsWidget::getKeyText(int KeyC)
00314 {
00315 if ((KeyC & ~(Qt::META | Qt::CTRL | Qt::ALT | Qt::SHIFT)) == 0)
00316 return "";
00317
00318
00319 QString res;
00320 if ((KeyC & Qt::META) != 0)
00321 res += "Meta+";
00322 if ((KeyC & Qt::CTRL) != 0)
00323 res += "Ctrl+";
00324 if ((KeyC & Qt::ALT) != 0)
00325 res += "Alt+";
00326 if ((KeyC & Qt::SHIFT) != 0)
00327 res += "Shift+";
00328 return res + QString(QKeySequence(KeyC & ~(Qt::META | Qt::CTRL | Qt::ALT | Qt::SHIFT)));
00329 }
00330
00331 void TabKeyboardShortcutsWidget::setKeyText()
00332 {
00333 if (keyTable->currentItem()==0)
00334 {
00335 setKeyButton->setChecked(false);
00336 return;
00337 }
00338 if (setKeyButton->isChecked())
00339 {
00340 keyCode = 0;
00341 Part0 = "";
00342 Part1 = "";
00343 Part2 = "";
00344 Part3 = "";
00345 Part4 = "";
00346 grabKeyboard();
00347 }
00348 else
00349 releaseKeyboard();
00350 }
00351
00352 void TabKeyboardShortcutsWidget::insertActions()
00353 {
00354 lviToActionMap.clear();
00355 lviToMenuMap.clear();
00356 keyTable->clear();
00357 bool first, firstMenu=true;
00358 QTreeWidgetItem *currLVI = NULL;
00359 QTreeWidgetItem *currMenuLVI = NULL;
00360 QTreeWidgetItem *prevLVI = NULL;
00361 QTreeWidgetItem *prevMenuLVI = NULL;
00362 for (QVector< QPair<QString, QStringList> >::Iterator itmenu = defMenus->begin(); itmenu != defMenus->end(); ++itmenu )
00363 {
00364 if (firstMenu)
00365 {
00366 currMenuLVI = new QTreeWidgetItem(keyTable);
00367 firstMenu = false;
00368 }
00369 else
00370 currMenuLVI = new QTreeWidgetItem(keyTable, prevMenuLVI);
00371 Q_CHECK_PTR(currMenuLVI);
00372 lviToMenuMap.append(currMenuLVI);
00373 currMenuLVI->setText(0, itmenu->first);
00374 currMenuLVI->setExpanded(true);
00375 prevMenuLVI=currMenuLVI;
00376 first=true;
00377 currLVI=0;
00378 prevLVI=0;
00379 for ( QStringList::Iterator it = itmenu->second.begin(); it != itmenu->second.end(); ++it )
00380 {
00381 if (first)
00382 {
00383 currLVI = new QTreeWidgetItem(currMenuLVI);
00384 first = false;
00385 }
00386 else
00387 currLVI = new QTreeWidgetItem(currMenuLVI, prevLVI);
00388 Q_CHECK_PTR(currLVI);
00389 lviToActionMap.insert(currLVI, *it);
00390 currLVI->setText(0, keyMap[*it].cleanMenuText);
00391 currLVI->setText(1, keyMap[*it].keySequence);
00392 prevLVI=currLVI;
00393 }
00394 }
00395
00396 for (QVector< QPair<QString, QStringList> >::Iterator itmenu = defNonMenuActions->begin(); itmenu != defNonMenuActions->end(); ++itmenu )
00397 {
00398 if (firstMenu)
00399 {
00400 currMenuLVI = new QTreeWidgetItem(keyTable);
00401 firstMenu = false;
00402 }
00403 else
00404 currMenuLVI = new QTreeWidgetItem(keyTable, prevMenuLVI);
00405 Q_CHECK_PTR(currMenuLVI);
00406 lviToMenuMap.append(currMenuLVI);
00407 currMenuLVI->setText(0, itmenu->first);
00408 currMenuLVI->setExpanded(true);
00409 prevMenuLVI=currMenuLVI;
00410 first=true;
00411 currLVI=0;
00412 prevLVI=0;
00413 for ( QStringList::Iterator it = itmenu->second.begin(); it != itmenu->second.end(); ++it )
00414 {
00415 if (first)
00416 {
00417 currLVI=new QTreeWidgetItem(currMenuLVI);
00418 first=false;
00419 }
00420 else
00421 currLVI=new QTreeWidgetItem(currMenuLVI, prevLVI);
00422 Q_CHECK_PTR(currLVI);
00423 lviToActionMap.insert(currLVI, *it);
00424 currLVI->setText(0, keyMap[*it].cleanMenuText);
00425 currLVI->setText(1, keyMap[*it].keySequence);
00426 prevLVI=currLVI;
00427 }
00428 }
00429 }
00430
00431 void TabKeyboardShortcutsWidget::applySearch( const QString & newss )
00432 {
00433
00434 for (QList<QTreeWidgetItem*>::iterator it=lviToMenuMap.begin(); it!=lviToMenuMap.end(); ++it)
00435 (*it)->setHidden(false);
00436 if (newss.isEmpty())
00437 {
00438 for (QMap<QTreeWidgetItem*, QString>::iterator it=lviToActionMap.begin(); it!=lviToActionMap.end(); ++it)
00439 it.key()->setHidden(false);
00440 return;
00441 }
00442
00443 for (QMap<QTreeWidgetItem*, QString>::iterator it=lviToActionMap.begin(); it!=lviToActionMap.end(); ++it)
00444 {
00445 if (it.key()->text(0).contains(newss, Qt::CaseInsensitive))
00446 it.key()->setHidden(false);
00447 else
00448 it.key()->setHidden(true);
00449 }
00450 }
00451
00452 void TabKeyboardShortcutsWidget::dispKey(QTreeWidgetItem* qlvi, QTreeWidgetItem*)
00453 {
00454 if (qlvi!=0 && lviToActionMap.contains(qlvi))
00455 {
00456 selectedLVI=qlvi;
00457 QString actionName=lviToActionMap[qlvi];
00458 if (actionName.isEmpty())
00459 return;
00460 keyDisplay->setText(keyMap[actionName].keySequence);
00461 if (keyMap[actionName].keySequence.isEmpty())
00462 noKey->setChecked(true);
00463 else
00464 userDef->setChecked(true);
00465 }
00466 else
00467 {
00468 noKey->setChecked(true);
00469 keyDisplay->setText("");
00470 selectedLVI=0;
00471 }
00472 }
00473
00474 bool TabKeyboardShortcutsWidget::event( QEvent* ev )
00475 {
00476 bool ret = QWidget::event( ev );
00477 if ( ev->type() == QEvent::KeyPress )
00478 keyPressEvent((QKeyEvent*)ev);
00479 if ( ev->type() == QEvent::KeyRelease )
00480 keyReleaseEvent((QKeyEvent*)ev);
00481 return ret;
00482 }
00483
00484 void TabKeyboardShortcutsWidget::keyPressEvent(QKeyEvent *k)
00485 {
00486 if (setKeyButton->isChecked())
00487 {
00488 QStringList tl;
00489 if (!keyDisplay->text().isEmpty())
00490 {
00491 tl = keyDisplay->text().split("+", QString::SkipEmptyParts);
00492 Part4 = tl[tl.count()-1];
00493 if (Part4 == tr("Alt") || Part4 == tr("Ctrl") || Part4 == tr("Shift") || Part4 == tr("Meta"))
00494 Part4 = "";
00495 }
00496 else
00497 Part4 = "";
00498 switch (k->key())
00499 {
00500 case Qt::Key_Meta:
00501 Part0 = tr("Meta+");
00502 keyCode |= Qt::META;
00503 break;
00504 case Qt::Key_Shift:
00505 Part3 = tr("Shift+");
00506 keyCode |= Qt::SHIFT;
00507 break;
00508 case Qt::Key_Alt:
00509 Part2 = tr("Alt+");
00510 keyCode |= Qt::ALT;
00511 break;
00512 case Qt::Key_Control:
00513 Part1 = tr("Ctrl+");
00514 keyCode |= Qt::CTRL;
00515 break;
00516 default:
00517 keyCode |= k->key();
00518 keyDisplay->setText(getKeyText(keyCode));
00519 releaseKeyboard();
00520 if (checkKey(keyCode))
00521 {
00522 QMessageBox::information(this, CommonStrings::trWarning,
00523 tr("This key sequence is already in use"),
00524 CommonStrings::tr_OK);
00525 selectedLVI->setText(1,keyMap[lviToActionMap[selectedLVI]].keySequence);
00526 keyDisplay->setText(keyMap[lviToActionMap[selectedLVI]].keySequence);
00527 }
00528 else
00529 {
00530 QKeySequence newKeySequence(keyCode);
00531 selectedLVI->setText(1, QString(newKeySequence));
00532 keyMap[lviToActionMap[selectedLVI]].keySequence=newKeySequence;
00533 userDef->setChecked(true);
00534 }
00535 setKeyButton->setChecked(false);
00536 }
00537 }
00538 if (setKeyButton->isChecked())
00539 keyDisplay->setText(Part0+Part1+Part2+Part3+Part4);
00540 }
00541
00542 void TabKeyboardShortcutsWidget::keyReleaseEvent(QKeyEvent *k)
00543 {
00544 if (setKeyButton->isChecked())
00545 {
00546 if (!keyDisplay->text().isEmpty())
00547 {
00548 QStringList tl;
00549 tl = keyDisplay->text().split("+", QString::SkipEmptyParts);
00550 Part4 = tl[tl.count()-1];
00551 if (Part4 == tr("Alt") || Part4 == tr("Ctrl") || Part4 == tr("Shift") || Part4 == tr("Meta"))
00552 Part4 = "";
00553 }
00554 else
00555 Part4 = "";
00556 if (k->key() == Qt::Key_Meta)
00557 {
00558 Part0 = "";
00559 keyCode &= ~Qt::META;
00560 }
00561 if (k->key() == Qt::Key_Shift)
00562 {
00563 Part3 = "";
00564 keyCode &= ~Qt::SHIFT;
00565 }
00566 if (k->key() == Qt::Key_Alt)
00567 {
00568 Part2 = "";
00569 keyCode &= ~Qt::ALT;
00570 }
00571 if (k->key() == Qt::Key_Control)
00572 {
00573 Part1 = "";
00574 keyCode &= ~Qt::CTRL;
00575 }
00576 keyDisplay->setText(Part0+Part1+Part2+Part3+Part4);
00577 }
00578 }
00579
00580 bool TabKeyboardShortcutsWidget::checkKey(int code)
00581 {
00582 bool ret = false;
00583 QKeySequence key = QKeySequence(code);
00584 for (QMap<QString,Keys>::Iterator it=keyMap.begin(); it!=keyMap.end(); ++it)
00585 {
00586 if (key.matches(it.value().keySequence) != QKeySequence::NoMatch)
00587 {
00588 ret = true;
00589 break;
00590 }
00591 }
00592 return ret;
00593 }
00594
00595 void TabKeyboardShortcutsWidget::clearSearchString( )
00596 {
00597 searchTextLineEdit->clear();
00598 }