KDEUI
kshortcutseditor.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries Copyright (C) 1998 Mark Donohoe <donohoe@kde.org> 00002 Copyright (C) 1997 Nicolas Hadacek <hadacek@kde.org> 00003 Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org> 00004 Copyright (C) 2001 Ellis Whitehead <ellis@kde.org> 00005 Copyright (C) 2006 Hamish Rodda <rodda@kde.org> 00006 Copyright (C) 2007 Roberto Raggi <roberto@kdevelop.org> 00007 Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com> 00008 Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz> 00009 00010 This library is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU Library General Public 00012 License as published by the Free Software Foundation; either 00013 version 2 of the License, or (at your option) any later version. 00014 00015 This library is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 Library General Public License for more details. 00019 00020 You should have received a copy of the GNU Library General Public License 00021 along with this library; see the file COPYING.LIB. If not, write to 00022 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00023 Boston, MA 02110-1301, USA. 00024 */ 00025 00026 #include "kshortcutseditor.h" 00027 00028 // The following is needed for KShortcutsEditorPrivate and QTreeWidgetHack 00029 #include "kshortcutsdialog_p.h" 00030 00031 #include <QHeaderView> 00032 #include <QList> 00033 #include <QObject> 00034 #include <QTimer> 00035 #include <QTextDocument> 00036 #include <QTextTable> 00037 #include <QTextCursor> 00038 #include <QTextTableFormat> 00039 #include <QPrinter> 00040 #include <QPrintDialog> 00041 00042 #include "kaction.h" 00043 #include "kactioncollection.h" 00044 #include "kactioncategory.h" 00045 #include "kdebug.h" 00046 #include "kdeprintdialog.h" 00047 #include "kglobalaccel.h" 00048 #include "kmessagebox.h" 00049 #include "kshortcut.h" 00050 #include "kaboutdata.h" 00051 00052 //--------------------------------------------------------------------- 00053 // KShortcutsEditor 00054 //--------------------------------------------------------------------- 00055 00056 KShortcutsEditor::KShortcutsEditor(KActionCollection *collection, QWidget *parent, ActionTypes actionType, 00057 LetterShortcuts allowLetterShortcuts ) 00058 : QWidget( parent ) 00059 , d(new KShortcutsEditorPrivate(this)) 00060 { 00061 d->initGUI(actionType, allowLetterShortcuts); 00062 addCollection(collection); 00063 } 00064 00065 00066 KShortcutsEditor::KShortcutsEditor(QWidget *parent, ActionTypes actionType, LetterShortcuts allowLetterShortcuts) 00067 : QWidget(parent) 00068 , d(new KShortcutsEditorPrivate(this)) 00069 { 00070 d->initGUI(actionType, allowLetterShortcuts); 00071 } 00072 00073 00074 KShortcutsEditor::~KShortcutsEditor() 00075 { 00076 delete d; 00077 } 00078 00079 00080 bool KShortcutsEditor::isModified() const 00081 { 00082 // Iterate over all items 00083 QTreeWidgetItemIterator it(d->ui.list, QTreeWidgetItemIterator::NoChildren); 00084 00085 for (; (*it); ++it) { 00086 KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem *>(*it); 00087 if (item && item->isModified()) { 00088 return true; 00089 } 00090 } 00091 return false; 00092 } 00093 00094 void KShortcutsEditor::clearCollections() 00095 { 00096 d->delegate->contractAll(); 00097 d->ui.list->clear(); 00098 d->actionCollections.clear(); 00099 QTimer::singleShot(0, this, SLOT(resizeColumns())); 00100 } 00101 00102 void KShortcutsEditor::addCollection(KActionCollection *collection, const QString &title) 00103 { 00104 // KXmlGui add action collections unconditionally. If some plugin doesn't 00105 // provide actions we don't want to create empty subgroups. 00106 if (collection->isEmpty()) { 00107 return; 00108 } 00109 00110 // We add a bunch of items. Prevent the treewidget from permanently 00111 // updating. 00112 setUpdatesEnabled(false); 00113 00114 d->actionCollections.append(collection); 00115 // Forward our actionCollections to the delegate which does the conflict 00116 // checking. 00117 d->delegate->setCheckActionCollections(d->actionCollections); 00118 QString displayTitle = title; 00119 00120 if (displayTitle.isEmpty()) { 00121 // Use the programName (Translated). 00122 if (const KAboutData *about = collection->componentData().aboutData()) { 00123 displayTitle = about->programName(); 00124 } 00125 // Yes it happens. Some apps don't set the programName. 00126 if (displayTitle.isEmpty()) { 00127 displayTitle = i18n("Unknown"); 00128 } 00129 } 00130 00131 QTreeWidgetItem *hier[3]; 00132 hier[KShortcutsEditorPrivate::Root] = d->ui.list->invisibleRootItem(); 00133 hier[KShortcutsEditorPrivate::Program] = d->findOrMakeItem( hier[KShortcutsEditorPrivate::Root], displayTitle); 00134 hier[KShortcutsEditorPrivate::Action] = NULL; 00135 00136 // Set to remember which actions we have seen. 00137 QSet<QAction*> actionsSeen; 00138 00139 // Add all categories in their own subtree below the collections root node 00140 QList<KActionCategory*> categories = collection->findChildren<KActionCategory*>(); 00141 foreach (KActionCategory *category, categories) { 00142 hier[KShortcutsEditorPrivate::Action] = d->findOrMakeItem(hier[KShortcutsEditorPrivate::Program], category->text()); 00143 foreach(QAction *action, category->actions()) { 00144 // Set a marker that we have seen this action 00145 actionsSeen.insert(action); 00146 d->addAction(action, hier, KShortcutsEditorPrivate::Action); 00147 } 00148 } 00149 00150 // The rest of the shortcuts is added as a direct shild of the action 00151 // collections root node 00152 foreach (QAction *action, collection->actions()) { 00153 if (actionsSeen.contains(action)) { 00154 continue; 00155 } 00156 00157 d->addAction(action, hier, KShortcutsEditorPrivate::Program); 00158 } 00159 00160 // sort the list 00161 d->ui.list->sortItems(Name, Qt::AscendingOrder); 00162 00163 // reenable updating 00164 setUpdatesEnabled(true); 00165 00166 QTimer::singleShot(0, this, SLOT(resizeColumns())); 00167 } 00168 00169 00170 void KShortcutsEditor::clearConfiguration() 00171 { 00172 d->clearConfiguration(); 00173 } 00174 00175 00176 #ifndef KDE_NO_DEPRECATED 00177 void KShortcutsEditor::importConfiguration( KConfig *config) 00178 { 00179 d->importConfiguration(config); 00180 } 00181 #endif 00182 00183 00184 void KShortcutsEditor::importConfiguration( KConfigBase *config) 00185 { 00186 d->importConfiguration(config); 00187 } 00188 00189 00190 #ifndef KDE_NO_DEPRECATED 00191 void KShortcutsEditor::exportConfiguration( KConfig *config) const 00192 { 00193 exportConfiguration(static_cast<KConfigBase*>(config)); 00194 } 00195 #endif 00196 00197 00198 void KShortcutsEditor::exportConfiguration( KConfigBase *config) const 00199 { 00200 Q_ASSERT(config); 00201 if (!config) return; 00202 00203 if (d->actionTypes & KShortcutsEditor::GlobalAction) { 00204 QString groupName = "Global Shortcuts"; 00205 KConfigGroup group( config, groupName ); 00206 foreach (KActionCollection* collection, d->actionCollections) { 00207 collection->exportGlobalShortcuts( &group, true ); 00208 } 00209 } 00210 if (d->actionTypes & ~KShortcutsEditor::GlobalAction) { 00211 QString groupName = "Shortcuts"; 00212 KConfigGroup group( config, groupName ); 00213 foreach (KActionCollection* collection, d->actionCollections) { 00214 collection->writeSettings( &group, true ); 00215 } 00216 } 00217 } 00218 00219 00220 void KShortcutsEditor::writeConfiguration( KConfigGroup *config) const 00221 { 00222 foreach (KActionCollection* collection, d->actionCollections) 00223 collection->writeSettings(config); 00224 } 00225 00226 00227 //slot 00228 void KShortcutsEditor::resizeColumns() 00229 { 00230 for (int i = 0; i < d->ui.list->columnCount(); i++) 00231 d->ui.list->resizeColumnToContents(i); 00232 } 00233 00234 00235 void KShortcutsEditor::commit() 00236 { 00237 for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) { 00238 if (KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem*>(*it)) { 00239 item->commit(); 00240 } 00241 } 00242 } 00243 00244 00245 void KShortcutsEditor::save() 00246 { 00247 writeConfiguration(); 00248 // we have to call commit. If we wouldn't do that the changes would be 00249 // undone on deletion! That would lead to weird problems. Changes to 00250 // Global Shortcuts would vanish completely. Changes to local shortcuts 00251 // would vanish for this session. 00252 commit(); 00253 } 00254 00255 00256 // KDE5 : rename to undo() 00257 void KShortcutsEditor::undoChanges() 00258 { 00259 //This function used to crash sometimes when invoked by clicking on "cancel" 00260 //with Qt 4.2.something. Apparently items were deleted too early by Qt. 00261 //It seems to work with 4.3-ish Qt versions. Keep an eye on this. 00262 for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) { 00263 if (KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem*>(*it)) { 00264 item->undo(); 00265 } 00266 } 00267 } 00268 00269 00270 //We ask the user here if there are any conflicts, as opposed to undoChanges(). 00271 //They don't do the same thing anyway, this just not to confuse any readers. 00272 //slot 00273 void KShortcutsEditor::allDefault() 00274 { 00275 d->allDefault(); 00276 } 00277 00278 00279 void KShortcutsEditor::printShortcuts() const 00280 { 00281 d->printShortcuts(); 00282 } 00283 00284 00285 //--------------------------------------------------------------------- 00286 // KShortcutsEditorPrivate 00287 //--------------------------------------------------------------------- 00288 00289 KShortcutsEditorPrivate::KShortcutsEditorPrivate( KShortcutsEditor *q ) 00290 : q(q), 00291 delegate(0) 00292 {} 00293 00294 void KShortcutsEditorPrivate::initGUI( KShortcutsEditor::ActionTypes types, KShortcutsEditor::LetterShortcuts allowLetterShortcuts ) 00295 { 00296 actionTypes = types; 00297 00298 ui.setupUi(q); 00299 q->layout()->setMargin(0); 00300 ui.searchFilter->searchLine()->setTreeWidget(ui.list); // Plug into search line 00301 ui.list->header()->setResizeMode(QHeaderView::ResizeToContents); 00302 ui.list->header()->hideSection(GlobalAlternate); //not expected to be very useful 00303 ui.list->header()->hideSection(ShapeGesture); //mouse gestures didn't make it in time... 00304 ui.list->header()->hideSection(RockerGesture); 00305 if (!(actionTypes & KShortcutsEditor::GlobalAction)) { 00306 ui.list->header()->hideSection(GlobalPrimary); 00307 } else if (!(actionTypes & ~KShortcutsEditor::GlobalAction)) { 00308 ui.list->header()->hideSection(LocalPrimary); 00309 ui.list->header()->hideSection(LocalAlternate); 00310 } 00311 00312 // Create the Delegate. It is responsible for the KKeySeqeunceWidgets that 00313 // really change the shortcuts. 00314 delegate = new KShortcutsEditorDelegate( 00315 ui.list, 00316 allowLetterShortcuts == KShortcutsEditor::LetterShortcutsAllowed); 00317 00318 ui.list->setItemDelegate(delegate); 00319 ui.list->setSelectionBehavior(QAbstractItemView::SelectItems); 00320 ui.list->setSelectionMode(QAbstractItemView::SingleSelection); 00321 //we have our own editing mechanism 00322 ui.list->setEditTriggers(QAbstractItemView::NoEditTriggers); 00323 ui.list->setAlternatingRowColors(true); 00324 00325 //TODO listen to changes to global shortcuts 00326 QObject::connect(delegate, SIGNAL(shortcutChanged(QVariant, const QModelIndex &)), 00327 q, SLOT(capturedShortcut(QVariant, const QModelIndex &))); 00328 //hide the editor widget chen its item becomes hidden 00329 QObject::connect(ui.searchFilter->searchLine(), SIGNAL(hiddenChanged(QTreeWidgetItem *, bool)), 00330 delegate, SLOT(hiddenBySearchLine(QTreeWidgetItem *, bool))); 00331 00332 ui.searchFilter->setFocus(); 00333 } 00334 00335 00336 bool KShortcutsEditorPrivate::addAction(QAction *action, QTreeWidgetItem *hier[], hierarchyLevel level) 00337 { 00338 // If the action name starts with unnamed- spit out a warning and ignore 00339 // it. That name will change at will and will break loading and writing 00340 QString actionName = action->objectName(); 00341 if (actionName.isEmpty() || actionName.startsWith(QLatin1String("unnamed-"))) { 00342 kError() << "Skipping action without name " << action->text() << "," << actionName << "!"; 00343 return false; 00344 } 00345 00346 // This code doesn't allow editing of QAction. It can not distinguish 00347 // between default and active shortcuts. This breaks many assumptions the 00348 // editor makes. 00349 KAction *kact; 00350 if ((kact = qobject_cast<KAction *>(action)) && kact->isShortcutConfigurable()) { 00351 new KShortcutsEditorItem((hier[level]), kact); 00352 return true; 00353 } 00354 00355 return false; 00356 } 00357 00358 void KShortcutsEditorPrivate::allDefault() 00359 { 00360 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00361 if (!(*it)->parent() || (*it)->type() != ActionItem) 00362 continue; 00363 00364 KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it); 00365 KAction *act = item->m_action; 00366 00367 if (act->shortcut() != act->shortcut(KAction::DefaultShortcut)) { 00368 changeKeyShortcut(item, LocalPrimary, act->shortcut(KAction::DefaultShortcut).primary()); 00369 changeKeyShortcut(item, LocalAlternate, act->shortcut(KAction::DefaultShortcut).alternate()); 00370 } 00371 00372 if (act->globalShortcut() != act->globalShortcut(KAction::DefaultShortcut)) { 00373 changeKeyShortcut(item, GlobalPrimary, act->globalShortcut(KAction::DefaultShortcut).primary()); 00374 changeKeyShortcut(item, GlobalAlternate, act->globalShortcut(KAction::DefaultShortcut).alternate()); 00375 } 00376 00377 if (act->shapeGesture() != act->shapeGesture(KAction::DefaultShortcut)) 00378 changeShapeGesture(item, act->shapeGesture(KAction::DefaultShortcut)); 00379 00380 if (act->rockerGesture() != act->rockerGesture(KAction::DefaultShortcut)) 00381 changeRockerGesture(item, act->rockerGesture(KAction::DefaultShortcut)); 00382 } 00383 } 00384 00385 //static 00386 KShortcutsEditorItem *KShortcutsEditorPrivate::itemFromIndex(QTreeWidget *const w, 00387 const QModelIndex &index) 00388 { 00389 QTreeWidgetItem *item = static_cast<QTreeWidgetHack *>(w)->itemFromIndex(index); 00390 if (item && item->type() == ActionItem) { 00391 return static_cast<KShortcutsEditorItem *>(item); 00392 } 00393 return 0; 00394 } 00395 00396 00397 QTreeWidgetItem *KShortcutsEditorPrivate::findOrMakeItem(QTreeWidgetItem *parent, const QString &name) 00398 { 00399 for (int i = 0; i < parent->childCount(); i++) { 00400 QTreeWidgetItem *child = parent->child(i); 00401 if (child->text(0) == name) 00402 return child; 00403 } 00404 QTreeWidgetItem *ret = new QTreeWidgetItem(parent, NonActionItem); 00405 ret->setText(0, name); 00406 ui.list->expandItem(ret); 00407 ret->setFlags(ret->flags() & ~Qt::ItemIsSelectable); 00408 return ret; 00409 } 00410 00411 00412 //private slot 00413 void KShortcutsEditorPrivate::capturedShortcut(const QVariant &newShortcut, const QModelIndex &index) 00414 { 00415 //dispatch to the right handler 00416 if (!index.isValid()) 00417 return; 00418 int column = index.column(); 00419 KShortcutsEditorItem *item = itemFromIndex(ui.list, index); 00420 Q_ASSERT(item); 00421 00422 if (column >= LocalPrimary && column <= GlobalAlternate) 00423 changeKeyShortcut(item, column, newShortcut.value<QKeySequence>()); 00424 else if (column == ShapeGesture) 00425 changeShapeGesture(item, newShortcut.value<KShapeGesture>()); 00426 else if (column == RockerGesture) 00427 changeRockerGesture(item, newShortcut.value<KRockerGesture>()); 00428 } 00429 00430 00431 void KShortcutsEditorPrivate::changeKeyShortcut(KShortcutsEditorItem *item, uint column, const QKeySequence &capture) 00432 { 00433 // The keySequence we get is cleared by KKeySequenceWidget. No conflicts. 00434 if (capture == item->keySequence(column)) { 00435 return; 00436 } 00437 00438 item->setKeySequence(column, capture); 00439 q->keyChange(); 00440 //force view update 00441 item->setText(column, capture.toString(QKeySequence::NativeText)); 00442 } 00443 00444 00445 void KShortcutsEditorPrivate::changeShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &capture) 00446 { 00447 if (capture == item->m_action->shapeGesture()) 00448 return; 00449 00450 if (capture.isValid()) { 00451 bool conflict = false; 00452 KShortcutsEditorItem *otherItem; 00453 00454 //search for conflicts 00455 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00456 if (!(*it)->parent() || (*it == item)) 00457 continue; 00458 00459 otherItem = static_cast<KShortcutsEditorItem *>(*it); 00460 00461 //comparisons are possibly expensive 00462 if (!otherItem->m_action->shapeGesture().isValid()) 00463 continue; 00464 00465 if (capture == otherItem->m_action->shapeGesture()) { 00466 conflict = true; 00467 break; 00468 } 00469 } 00470 00471 if (conflict && !stealShapeGesture(otherItem, capture)) 00472 return; 00473 } 00474 00475 item->setShapeGesture(capture); 00476 } 00477 00478 00479 void KShortcutsEditorPrivate::changeRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &capture) 00480 { 00481 if (capture == item->m_action->rockerGesture()) 00482 return; 00483 00484 if (capture.isValid()) { 00485 bool conflict = false; 00486 KShortcutsEditorItem *otherItem; 00487 00488 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00489 if (!(*it)->parent() || (*it == item)) 00490 continue; 00491 00492 otherItem = static_cast<KShortcutsEditorItem *>(*it); 00493 00494 if (capture == otherItem->m_action->rockerGesture()) { 00495 conflict = true; 00496 break; 00497 } 00498 } 00499 00500 if (conflict && !stealRockerGesture(otherItem, capture)) 00501 return; 00502 } 00503 00504 item->setRockerGesture(capture); 00505 } 00506 00507 00508 void KShortcutsEditorPrivate::clearConfiguration() 00509 { 00510 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00511 if (!(*it)->parent()) 00512 continue; 00513 00514 KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it); 00515 00516 changeKeyShortcut(item, LocalPrimary, QKeySequence()); 00517 changeKeyShortcut(item, LocalAlternate, QKeySequence()); 00518 00519 changeKeyShortcut(item, GlobalPrimary, QKeySequence()); 00520 changeKeyShortcut(item, GlobalAlternate, QKeySequence()); 00521 00522 changeShapeGesture(item, KShapeGesture() ); 00523 00524 } 00525 } 00526 00527 00528 void KShortcutsEditorPrivate::importConfiguration(KConfigBase *config) 00529 { 00530 Q_ASSERT(config); 00531 if (!config) return; 00532 00533 KConfigGroup globalShortcutsGroup(config, QLatin1String("Global Shortcuts")); 00534 if ((actionTypes & KShortcutsEditor::GlobalAction) && globalShortcutsGroup.exists()) { 00535 00536 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00537 00538 if (!(*it)->parent()) 00539 continue; 00540 00541 KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it); 00542 00543 QString actionName = item->data(Id).toString(); 00544 KShortcut sc(globalShortcutsGroup.readEntry(actionName, QString())); 00545 changeKeyShortcut(item, GlobalPrimary, sc.primary()); 00546 } 00547 } 00548 00549 KConfigGroup localShortcutsGroup(config, QLatin1String("Shortcuts")); 00550 if (actionTypes & ~KShortcutsEditor::GlobalAction) { 00551 00552 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { 00553 00554 if (!(*it)->parent()) 00555 continue; 00556 00557 KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it); 00558 00559 QString actionName = item->data(Name).toString(); 00560 KShortcut sc(localShortcutsGroup.readEntry(actionName, QString())); 00561 changeKeyShortcut(item, LocalPrimary, sc.primary()); 00562 changeKeyShortcut(item, LocalAlternate, sc.alternate()); 00563 } 00564 } 00565 } 00566 00567 00568 bool KShortcutsEditorPrivate::stealShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &gst) 00569 { 00570 QString title = i18n("Key Conflict"); 00571 QString message = i18n("The '%1' shape gesture has already been allocated to the \"%2\" action.\n" 00572 "Do you want to reassign it from that action to the current one?", 00573 gst.shapeName(), item->m_action->text()); 00574 00575 if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign"))) 00576 != KMessageBox::Continue) 00577 return false; 00578 00579 item->setShapeGesture(KShapeGesture()); 00580 return true; 00581 } 00582 00583 00584 bool KShortcutsEditorPrivate::stealRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &gst) 00585 { 00586 QString title = i18n("Key Conflict"); 00587 QString message = i18n("The '%1' rocker gesture has already been allocated to the \"%2\" action.\n" 00588 "Do you want to reassign it from that action to the current one?", 00589 gst.rockerName(), item->m_action->text()); 00590 00591 if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign"))) 00592 != KMessageBox::Continue) 00593 return false; 00594 00595 item->setRockerGesture(KRockerGesture()); 00596 return true; 00597 } 00598 00599 00600 /*TODO for the printShortcuts function 00601 Nice to have features (which I'm not sure I can do before may due to 00602 more important things): 00603 00604 - adjust the general page borders, IMHO they're too wide 00605 00606 - add a custom printer options page that allows to filter out all 00607 actions that don't have a shortcut set to reduce this list. IMHO this 00608 should be optional as people might want to simply print all and when 00609 they find a new action that they assign a shortcut they can simply use 00610 a pen to fill out the empty space 00611 00612 - find a way to align the Main/Alternate/Global entries in the shortcuts 00613 column without adding borders. I first did this without a nested table 00614 but instead simply added 3 rows and merged the 3 cells in the Action 00615 name and description column, but unfortunately I didn't find a way to 00616 remove the borders between the 6 shortcut cells. 00617 */ 00618 void KShortcutsEditorPrivate::printShortcuts() const 00619 { 00620 // One cant print on wince 00621 #ifndef _WIN32_WCE 00622 QTreeWidgetItem* root = ui.list->invisibleRootItem(); 00623 QTextDocument doc; 00624 doc.setDefaultFont(KGlobalSettings::generalFont()); 00625 QTextCursor cursor(&doc); 00626 cursor.beginEditBlock(); 00627 QTextCharFormat headerFormat; 00628 headerFormat.setProperty(QTextFormat::FontSizeAdjustment, 3); 00629 headerFormat.setFontWeight(QFont::Bold); 00630 cursor.insertText(i18nc("header for an applications shortcut list","Shortcuts for %1", 00631 KGlobal::mainComponent().aboutData()->programName()), 00632 headerFormat); 00633 QTextCharFormat componentFormat; 00634 componentFormat.setProperty(QTextFormat::FontSizeAdjustment, 2); 00635 componentFormat.setFontWeight(QFont::Bold); 00636 QTextBlockFormat componentBlockFormat = cursor.blockFormat(); 00637 componentBlockFormat.setTopMargin(16); 00638 componentBlockFormat.setBottomMargin(16); 00639 00640 QTextTableFormat tableformat; 00641 tableformat.setHeaderRowCount(1); 00642 tableformat.setCellPadding(4.0); 00643 tableformat.setCellSpacing(0); 00644 tableformat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid); 00645 tableformat.setBorder(0.5); 00646 00647 QList<QPair<QString,ColumnDesignation> > shortcutTitleToColumn; 00648 shortcutTitleToColumn << qMakePair(i18n("Main:"), LocalPrimary); 00649 shortcutTitleToColumn << qMakePair(i18n("Alternate:"), LocalAlternate); 00650 shortcutTitleToColumn << qMakePair(i18n("Global:"), GlobalPrimary); 00651 00652 for (int i = 0; i < root->childCount(); i++) { 00653 QTreeWidgetItem* item = root->child(i); 00654 cursor.insertBlock(componentBlockFormat, componentFormat); 00655 cursor.insertText(item->text(0)); 00656 00657 QTextTable* table = cursor.insertTable(1,3); 00658 table->setFormat(tableformat); 00659 int currow = 0; 00660 00661 QTextTableCell cell = table->cellAt(currow,0); 00662 QTextCharFormat format = cell.format(); 00663 format.setFontWeight(QFont::Bold); 00664 cell.setFormat(format); 00665 cell.firstCursorPosition().insertText(i18n("Action Name")); 00666 00667 cell = table->cellAt(currow,1); 00668 cell.setFormat(format); 00669 cell.firstCursorPosition().insertText(i18n("Shortcuts")); 00670 00671 cell = table->cellAt(currow,2); 00672 cell.setFormat(format); 00673 cell.firstCursorPosition().insertText(i18n("Description")); 00674 currow++; 00675 00676 for (QTreeWidgetItemIterator it(item); *it; ++it) { 00677 if ((*it)->type() != ActionItem) 00678 continue; 00679 00680 KShortcutsEditorItem* editoritem = static_cast<KShortcutsEditorItem*>(*it); 00681 table->insertRows(table->rows(),1); 00682 QVariant data = editoritem->data(Name,Qt::DisplayRole); 00683 table->cellAt(currow, 0).firstCursorPosition().insertText(data.toString()); 00684 00685 QTextTable* shortcutTable = 0 ; 00686 for(int k = 0; k < shortcutTitleToColumn.count(); k++) { 00687 data = editoritem->data(shortcutTitleToColumn.at(k).second,Qt::DisplayRole); 00688 QString key = data.value<QKeySequence>().toString(); 00689 00690 if(!key.isEmpty()) { 00691 if( !shortcutTable ) { 00692 shortcutTable = table->cellAt(currow, 1).firstCursorPosition().insertTable(1,2); 00693 QTextTableFormat shortcutTableFormat = tableformat; 00694 shortcutTableFormat.setCellSpacing(0.0); 00695 shortcutTableFormat.setHeaderRowCount(0); 00696 shortcutTableFormat.setBorder(0.0); 00697 shortcutTable->setFormat(shortcutTableFormat); 00698 } else { 00699 shortcutTable->insertRows(shortcutTable->rows(),1); 00700 } 00701 shortcutTable->cellAt(shortcutTable->rows()-1,0).firstCursorPosition().insertText(shortcutTitleToColumn.at(k).first); 00702 shortcutTable->cellAt(shortcutTable->rows()-1,1).firstCursorPosition().insertText(key); 00703 } 00704 } 00705 00706 KAction* action = editoritem->m_action; 00707 cell = table->cellAt(currow, 2); 00708 format = cell.format(); 00709 format.setProperty(QTextFormat::FontSizeAdjustment, -1); 00710 cell.setFormat(format); 00711 cell.firstCursorPosition().insertHtml(action->whatsThis()); 00712 00713 currow++; 00714 } 00715 cursor.movePosition(QTextCursor::End); 00716 } 00717 cursor.endEditBlock(); 00718 00719 QPrinter printer; 00720 QPrintDialog *dlg = KdePrint::createPrintDialog(&printer, q); 00721 if (dlg->exec() == QDialog::Accepted) { 00722 doc.print(&printer); 00723 } 00724 delete dlg; 00725 #endif 00726 } 00727 00728 #include "kshortcutseditor.moc"
KDE 4.6 API Reference