• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

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 void KShortcutsEditor::importConfiguration( KConfig *config)
00177 {
00178     d->importConfiguration(config);
00179 }
00180 
00181 
00182 void KShortcutsEditor::importConfiguration( KConfigBase *config)
00183 {
00184     d->importConfiguration(config);
00185 }
00186 
00187 
00188 void KShortcutsEditor::exportConfiguration( KConfig *config) const
00189 {
00190     exportConfiguration(static_cast<KConfigBase*>(config));
00191 }
00192 
00193 
00194 void KShortcutsEditor::exportConfiguration( KConfigBase *config) const
00195 {
00196     Q_ASSERT(config);
00197     if (!config) return;
00198 
00199     if (d->actionTypes & KShortcutsEditor::GlobalAction) {
00200         QString groupName = "Global Shortcuts";
00201         KConfigGroup group( config, groupName );
00202         foreach (KActionCollection* collection, d->actionCollections) {
00203             collection->exportGlobalShortcuts( &group, true );
00204         }
00205     }
00206     if (d->actionTypes & ~KShortcutsEditor::GlobalAction) {
00207         QString groupName = "Shortcuts";
00208         KConfigGroup group( config, groupName );
00209         foreach (KActionCollection* collection, d->actionCollections) {
00210             collection->writeSettings( &group, true );
00211         }
00212     }
00213 }
00214 
00215 
00216 void KShortcutsEditor::writeConfiguration( KConfigGroup *config) const
00217 {
00218     foreach (KActionCollection* collection, d->actionCollections)
00219         collection->writeSettings(config);
00220 }
00221 
00222 
00223 //slot
00224 void KShortcutsEditor::resizeColumns()
00225 {
00226     for (int i = 0; i < d->ui.list->columnCount(); i++)
00227         d->ui.list->resizeColumnToContents(i);
00228 }
00229 
00230 
00231 void KShortcutsEditor::commit()
00232 {
00233     for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) {
00234         if (KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem*>(*it)) {
00235             item->commit();
00236         }
00237     }
00238 }
00239 
00240 
00241 void KShortcutsEditor::save()
00242 {
00243     writeConfiguration();
00244     // we have to call commit. If we wouldn't do that the changes would be
00245     // undone on deletion! That would lead to weird problems. Changes to
00246     // Global Shortcuts would vanish completely. Changes to local shortcuts
00247     // would vanish for this session.
00248     commit();
00249 }
00250 
00251 
00252 // KDE5 : rename to undo()
00253 void KShortcutsEditor::undoChanges()
00254 {
00255     //This function used to crash sometimes when invoked by clicking on "cancel"
00256     //with Qt 4.2.something. Apparently items were deleted too early by Qt.
00257     //It seems to work with 4.3-ish Qt versions. Keep an eye on this.
00258     for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) {
00259         if (KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem*>(*it)) {
00260             item->undo();
00261         }
00262     }
00263 }
00264 
00265 
00266 //We ask the user here if there are any conflicts, as opposed to undoChanges().
00267 //They don't do the same thing anyway, this just not to confuse any readers.
00268 //slot
00269 void KShortcutsEditor::allDefault()
00270 {
00271     d->allDefault();
00272 }
00273 
00274 
00275 void KShortcutsEditor::printShortcuts() const
00276 {
00277     d->printShortcuts();
00278 }
00279 
00280 
00281 //---------------------------------------------------------------------
00282 // KShortcutsEditorPrivate
00283 //---------------------------------------------------------------------
00284 
00285 KShortcutsEditorPrivate::KShortcutsEditorPrivate( KShortcutsEditor *q )
00286     :   q(q),
00287         delegate(0)
00288     {}
00289 
00290 void KShortcutsEditorPrivate::initGUI( KShortcutsEditor::ActionTypes types, KShortcutsEditor::LetterShortcuts allowLetterShortcuts )
00291 {
00292     actionTypes = types;
00293 
00294     ui.setupUi(q);
00295     q->layout()->setMargin(0);
00296     ui.searchFilter->searchLine()->setTreeWidget(ui.list); // Plug into search line
00297     ui.list->header()->setResizeMode(QHeaderView::ResizeToContents);
00298     ui.list->header()->hideSection(GlobalAlternate);  //not expected to be very useful
00299     ui.list->header()->hideSection(ShapeGesture);  //mouse gestures didn't make it in time...
00300     ui.list->header()->hideSection(RockerGesture);
00301     if (!(actionTypes & KShortcutsEditor::GlobalAction)) {
00302         ui.list->header()->hideSection(GlobalPrimary);
00303     } else if (!(actionTypes & ~KShortcutsEditor::GlobalAction)) {
00304         ui.list->header()->hideSection(LocalPrimary);
00305         ui.list->header()->hideSection(LocalAlternate);
00306     }
00307 
00308     // Create the Delegate. It is responsible for the KKeySeqeunceWidgets that
00309     // really change the shortcuts.
00310     delegate = new KShortcutsEditorDelegate(
00311         ui.list,
00312         allowLetterShortcuts == KShortcutsEditor::LetterShortcutsAllowed);
00313 
00314     ui.list->setItemDelegate(delegate);
00315     ui.list->setSelectionBehavior(QAbstractItemView::SelectItems);
00316     ui.list->setSelectionMode(QAbstractItemView::SingleSelection);
00317     //we have our own editing mechanism
00318     ui.list->setEditTriggers(QAbstractItemView::NoEditTriggers);
00319     ui.list->setAlternatingRowColors(true);
00320 
00321     //TODO listen to changes to global shortcuts
00322     QObject::connect(delegate, SIGNAL(shortcutChanged(QVariant, const QModelIndex &)),
00323                      q, SLOT(capturedShortcut(QVariant, const QModelIndex &)));
00324     //hide the editor widget chen its item becomes hidden
00325     QObject::connect(ui.searchFilter->searchLine(), SIGNAL(hiddenChanged(QTreeWidgetItem *, bool)),
00326                      delegate, SLOT(hiddenBySearchLine(QTreeWidgetItem *, bool)));
00327 
00328     ui.searchFilter->setFocus();
00329 }
00330 
00331 
00332 bool KShortcutsEditorPrivate::addAction(QAction *action, QTreeWidgetItem *hier[], hierarchyLevel level)
00333 {
00334     // If the action name starts with unnamed- spit out a warning and ignore
00335     // it. That name will change at will and will break loading and writing
00336     QString actionName = action->objectName();
00337     if (actionName.isEmpty() || actionName.startsWith("unnamed-")) {
00338         kError() << "Skipping action without name " << action->text() << "," << actionName << "!";
00339         return false;
00340     }
00341 
00342     // This code doesn't allow editing of QAction. It can not distinguish
00343     // between default and active shortcuts. This breaks many assumptions the
00344     // editor makes.
00345     KAction *kact;
00346     if ((kact = qobject_cast<KAction *>(action)) && kact->isShortcutConfigurable()) {
00347         new KShortcutsEditorItem((hier[level]), kact);
00348         return true;
00349     }
00350 
00351     return false;
00352 }
00353 
00354 void KShortcutsEditorPrivate::allDefault()
00355 {
00356     for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00357         if (!(*it)->parent() || (*it)->type() != ActionItem)
00358             continue;
00359 
00360         KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it);
00361         KAction *act = item->m_action;
00362 
00363         if (act->shortcut() != act->shortcut(KAction::DefaultShortcut)) {
00364             changeKeyShortcut(item, LocalPrimary, act->shortcut(KAction::DefaultShortcut).primary());
00365             changeKeyShortcut(item, LocalAlternate, act->shortcut(KAction::DefaultShortcut).alternate());
00366         }
00367 
00368         if (act->globalShortcut() != act->globalShortcut(KAction::DefaultShortcut)) {
00369             changeKeyShortcut(item, GlobalPrimary, act->globalShortcut(KAction::DefaultShortcut).primary());
00370             changeKeyShortcut(item, GlobalAlternate, act->globalShortcut(KAction::DefaultShortcut).alternate());
00371         }
00372 
00373         if (act->shapeGesture() != act->shapeGesture(KAction::DefaultShortcut))
00374             changeShapeGesture(item, act->shapeGesture(KAction::DefaultShortcut));
00375 
00376         if (act->rockerGesture() != act->rockerGesture(KAction::DefaultShortcut))
00377             changeRockerGesture(item, act->rockerGesture(KAction::DefaultShortcut));
00378     }
00379 }
00380 
00381 //static
00382 KShortcutsEditorItem *KShortcutsEditorPrivate::itemFromIndex(QTreeWidget *const w,
00383                                                              const QModelIndex &index)
00384 {
00385     QTreeWidgetItem *item = static_cast<QTreeWidgetHack *>(w)->itemFromIndex(index);
00386     if (item && item->type() == ActionItem) {
00387         return static_cast<KShortcutsEditorItem *>(item);
00388     }
00389     return 0;
00390 }
00391 
00392 
00393 QTreeWidgetItem *KShortcutsEditorPrivate::findOrMakeItem(QTreeWidgetItem *parent, const QString &name)
00394 {
00395     for (int i = 0; i < parent->childCount(); i++) {
00396         QTreeWidgetItem *child = parent->child(i);
00397         if (child->text(0) == name)
00398             return child;
00399     }
00400     QTreeWidgetItem *ret = new QTreeWidgetItem(parent, NonActionItem);
00401     ret->setText(0, name);
00402     ui.list->expandItem(ret);
00403     ret->setFlags(ret->flags() & ~Qt::ItemIsSelectable);
00404     return ret;
00405 }
00406 
00407 
00408 //private slot
00409 void KShortcutsEditorPrivate::capturedShortcut(const QVariant &newShortcut, const QModelIndex &index)
00410 {
00411     //dispatch to the right handler
00412     if (!index.isValid())
00413         return;
00414     int column = index.column();
00415     KShortcutsEditorItem *item = itemFromIndex(ui.list, index);
00416     Q_ASSERT(item);
00417 
00418     if (column >= LocalPrimary && column <= GlobalAlternate)
00419         changeKeyShortcut(item, column, newShortcut.value<QKeySequence>());
00420     else if (column == ShapeGesture)
00421         changeShapeGesture(item, newShortcut.value<KShapeGesture>());
00422     else if (column == RockerGesture)
00423         changeRockerGesture(item, newShortcut.value<KRockerGesture>());
00424 }
00425 
00426 
00427 void KShortcutsEditorPrivate::changeKeyShortcut(KShortcutsEditorItem *item, uint column, const QKeySequence &capture)
00428 {
00429     // The keySequence we get is cleared by KKeySequenceWidget. No conflicts.
00430     if (capture == item->keySequence(column)) {
00431         return;
00432     }
00433 
00434     item->setKeySequence(column, capture);
00435     q->keyChange();
00436     //force view update
00437     item->setText(column, capture.toString(QKeySequence::NativeText));
00438 }
00439 
00440 
00441 void KShortcutsEditorPrivate::changeShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &capture)
00442 {
00443     if (capture == item->m_action->shapeGesture())
00444         return;
00445 
00446     if (capture.isValid()) {
00447         bool conflict = false;
00448         KShortcutsEditorItem *otherItem;
00449 
00450         //search for conflicts
00451         for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00452             if (!(*it)->parent() || (*it == item))
00453                 continue;
00454 
00455             otherItem = static_cast<KShortcutsEditorItem *>(*it);
00456 
00457             //comparisons are possibly expensive
00458             if (!otherItem->m_action->shapeGesture().isValid())
00459                 continue;
00460 
00461             if (capture == otherItem->m_action->shapeGesture()) {
00462                 conflict = true;
00463                 break;
00464             }
00465         }
00466 
00467         if (conflict && !stealShapeGesture(otherItem, capture))
00468             return;
00469     }
00470 
00471     item->setShapeGesture(capture);
00472 }
00473 
00474 
00475 void KShortcutsEditorPrivate::changeRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &capture)
00476 {
00477     if (capture == item->m_action->rockerGesture())
00478         return;
00479 
00480     if (capture.isValid()) {
00481         bool conflict = false;
00482         KShortcutsEditorItem *otherItem;
00483 
00484         for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00485             if (!(*it)->parent() || (*it == item))
00486                 continue;
00487 
00488             otherItem = static_cast<KShortcutsEditorItem *>(*it);
00489 
00490             if (capture == otherItem->m_action->rockerGesture()) {
00491                 conflict = true;
00492                 break;
00493             }
00494         }
00495 
00496         if (conflict && !stealRockerGesture(otherItem, capture))
00497             return;
00498     }
00499 
00500     item->setRockerGesture(capture);
00501 }
00502 
00503 
00504 void KShortcutsEditorPrivate::clearConfiguration()
00505 {
00506     for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00507         if (!(*it)->parent())
00508             continue;
00509 
00510         KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it);
00511 
00512         changeKeyShortcut(item, LocalPrimary,   QKeySequence());
00513         changeKeyShortcut(item, LocalAlternate, QKeySequence());
00514 
00515         changeKeyShortcut(item, GlobalPrimary,   QKeySequence());
00516         changeKeyShortcut(item, GlobalAlternate, QKeySequence());
00517 
00518         changeShapeGesture(item, KShapeGesture() );
00519 
00520     }
00521 }
00522 
00523 
00524 void KShortcutsEditorPrivate::importConfiguration(KConfigBase *config)
00525 {
00526     Q_ASSERT(config);
00527     if (!config) return;
00528 
00529     KConfigGroup globalShortcutsGroup(config, QLatin1String("Global Shortcuts"));
00530     if ((actionTypes & KShortcutsEditor::GlobalAction) && globalShortcutsGroup.exists()) {
00531 
00532         for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00533 
00534             if (!(*it)->parent())
00535                 continue;
00536 
00537             KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it);
00538 
00539             QString actionName = item->data(Name).toString();
00540             KShortcut sc(globalShortcutsGroup.readEntry(actionName, QString()));
00541             changeKeyShortcut(item, GlobalPrimary, sc.primary());
00542         }
00543     }
00544 
00545     KConfigGroup localShortcutsGroup(config, QLatin1String("Shortcuts"));
00546     if (actionTypes & ~KShortcutsEditor::GlobalAction) {
00547 
00548         for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
00549 
00550             if (!(*it)->parent())
00551                 continue;
00552 
00553             KShortcutsEditorItem *item = static_cast<KShortcutsEditorItem *>(*it);
00554 
00555             QString actionName = item->data(Name).toString();
00556             KShortcut sc(localShortcutsGroup.readEntry(actionName, QString()));
00557             changeKeyShortcut(item, LocalPrimary, sc.primary());
00558             changeKeyShortcut(item, LocalAlternate, sc.alternate());
00559         }
00560     }
00561 }
00562 
00563 
00564 bool KShortcutsEditorPrivate::stealShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &gst)
00565 {
00566     QString title = i18n("Key Conflict");
00567     QString message = i18n("The '%1' shape gesture has already been allocated to the \"%2\" action.\n"
00568                            "Do you want to reassign it from that action to the current one?",
00569                            gst.shapeName(), item->m_action->text());
00570 
00571     if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign")))
00572         != KMessageBox::Continue)
00573         return false;
00574 
00575     item->setShapeGesture(KShapeGesture());
00576     return true;
00577 }
00578 
00579 
00580 bool KShortcutsEditorPrivate::stealRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &gst)
00581 {
00582     QString title = i18n("Key Conflict");
00583     QString message = i18n("The '%1' rocker gesture has already been allocated to the \"%2\" action.\n"
00584                            "Do you want to reassign it from that action to the current one?",
00585                            gst.rockerName(), item->m_action->text());
00586 
00587     if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign")))
00588         != KMessageBox::Continue)
00589         return false;
00590 
00591     item->setRockerGesture(KRockerGesture());
00592     return true;
00593 }
00594 
00595 
00596 /*TODO for the printShortcuts function
00597 Nice to have features (which I'm not sure I can do before may due to
00598 more important things):
00599 
00600 - adjust the general page borders, IMHO they're too wide
00601 
00602 - add a custom printer options page that allows to filter out all
00603   actions that don't have a shortcut set to reduce this list. IMHO this
00604   should be optional as people might want to simply print all and  when
00605   they find a new action that they assign a shortcut they can simply use
00606   a pen to fill out the empty space
00607 
00608 - find a way to align the Main/Alternate/Global entries in the shortcuts
00609   column without adding borders. I first did this without a nested table
00610   but instead simply added 3 rows and merged the 3 cells in the Action
00611   name and description column, but unfortunately I didn't find a way to
00612   remove the borders between the 6 shortcut cells.
00613 */
00614 void KShortcutsEditorPrivate::printShortcuts() const
00615 {
00616     QTreeWidgetItem* root = ui.list->invisibleRootItem();
00617     QTextDocument doc;
00618     doc.setDefaultFont(KGlobalSettings::generalFont());
00619     QTextCursor cursor(&doc);
00620     cursor.beginEditBlock();
00621     QTextCharFormat headerFormat;
00622     headerFormat.setProperty(QTextFormat::FontSizeAdjustment, 3);
00623     headerFormat.setFontWeight(QFont::Bold);
00624     cursor.insertText(i18nc("header for an applications shortcut list","Shortcuts for %1",
00625                             KGlobal::mainComponent().aboutData()->programName()),
00626                       headerFormat);
00627     QTextCharFormat componentFormat;
00628     componentFormat.setProperty(QTextFormat::FontSizeAdjustment, 2);
00629     componentFormat.setFontWeight(QFont::Bold);
00630     QTextBlockFormat componentBlockFormat = cursor.blockFormat();
00631     componentBlockFormat.setTopMargin(16);
00632     componentBlockFormat.setBottomMargin(16);
00633 
00634     QTextTableFormat tableformat;
00635     tableformat.setHeaderRowCount(1);
00636     tableformat.setCellPadding(4.0);
00637     tableformat.setCellSpacing(0);
00638     tableformat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
00639     tableformat.setBorder(0.5);
00640 
00641     QList<QPair<QString,ColumnDesignation> > shortcutTitleToColumn;
00642     shortcutTitleToColumn << qMakePair(i18n("Main:"), LocalPrimary);
00643     shortcutTitleToColumn << qMakePair(i18n("Alternate:"), LocalAlternate);
00644     shortcutTitleToColumn << qMakePair(i18n("Global:"), GlobalPrimary);
00645 
00646     for (int i = 0; i < root->childCount(); i++) {
00647         QTreeWidgetItem* item = root->child(i);
00648         cursor.insertBlock(componentBlockFormat, componentFormat);
00649         cursor.insertText(item->text(0));
00650 
00651         QTextTable* table = cursor.insertTable(1,3);
00652         table->setFormat(tableformat);
00653         int currow = 0;
00654 
00655         QTextTableCell cell = table->cellAt(currow,0);
00656         QTextCharFormat format = cell.format();
00657         format.setFontWeight(QFont::Bold);
00658         cell.setFormat(format);
00659         cell.firstCursorPosition().insertText(i18n("Action Name"));
00660 
00661         cell = table->cellAt(currow,1);
00662         cell.setFormat(format);
00663         cell.firstCursorPosition().insertText(i18n("Shortcuts"));
00664 
00665         cell = table->cellAt(currow,2);
00666         cell.setFormat(format);
00667         cell.firstCursorPosition().insertText(i18n("Description"));
00668         currow++;
00669 
00670         for (QTreeWidgetItemIterator it(item); *it; ++it) {
00671             if ((*it)->type() != ActionItem)
00672                 continue;
00673 
00674             KShortcutsEditorItem* editoritem = static_cast<KShortcutsEditorItem*>(*it);
00675             table->insertRows(table->rows(),1);
00676             QVariant data = editoritem->data(Name,Qt::DisplayRole);
00677             table->cellAt(currow, 0).firstCursorPosition().insertText(data.toString());
00678 
00679             QTextTable* shortcutTable = 0 ;
00680             for(int k = 0; k < shortcutTitleToColumn.count(); k++) {
00681               data = editoritem->data(shortcutTitleToColumn.at(k).second,Qt::DisplayRole);
00682               QString key = data.value<QKeySequence>().toString();
00683 
00684               if(!key.isEmpty()) {
00685                 if( !shortcutTable ) {
00686                   shortcutTable = table->cellAt(currow, 1).firstCursorPosition().insertTable(1,2);
00687                   QTextTableFormat shortcutTableFormat = tableformat;
00688                   shortcutTableFormat.setCellSpacing(0.0);
00689                   shortcutTableFormat.setHeaderRowCount(0);
00690                   shortcutTableFormat.setBorder(0.0);
00691                   shortcutTable->setFormat(shortcutTableFormat);
00692                 } else {
00693                   shortcutTable->insertRows(shortcutTable->rows(),1);
00694                 }
00695                 shortcutTable->cellAt(shortcutTable->rows()-1,0).firstCursorPosition().insertText(shortcutTitleToColumn.at(k).first);
00696                 shortcutTable->cellAt(shortcutTable->rows()-1,1).firstCursorPosition().insertText(key);
00697               }
00698             }
00699 
00700             KAction* action = editoritem->m_action;
00701             cell = table->cellAt(currow, 2);
00702             format = cell.format();
00703             format.setProperty(QTextFormat::FontSizeAdjustment, -1);
00704             cell.setFormat(format);
00705             cell.firstCursorPosition().insertHtml(action->whatsThis());
00706 
00707             currow++;
00708         }
00709         cursor.movePosition(QTextCursor::End);
00710     }
00711     cursor.endEditBlock();
00712 
00713     QPrinter printer;
00714     QPrintDialog *dlg = KdePrint::createPrintDialog(&printer, q);
00715     if (dlg->exec() == QDialog::Accepted) {
00716         doc.print(&printer);
00717     }
00718     delete dlg;
00719 }
00720 
00721 #include "kshortcutseditor.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal