• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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 #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"

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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