29#include "kshortcutsdialog_p.h"
35#include <QTextDocument>
38#include <QTextTableFormat>
40#include <QPrintDialog>
59, d(new KShortcutsEditorPrivate(this))
61 d->initGUI(actionType, allowLetterShortcuts);
68, d(new KShortcutsEditorPrivate(this))
70 d->initGUI(actionType, allowLetterShortcuts);
83 QTreeWidgetItemIterator it(d->ui.list, QTreeWidgetItemIterator::NoChildren);
86 KShortcutsEditorItem* item =
dynamic_cast<KShortcutsEditorItem *
>(*it);
87 if (item && item->isModified()) {
96 d->delegate->contractAll();
98 d->actionCollections.clear();
112 setUpdatesEnabled(
false);
114 d->actionCollections.append(collection);
117 d->delegate->setCheckActionCollections(d->actionCollections);
118 QString displayTitle = title;
120 if (displayTitle.isEmpty()) {
123 displayTitle = about->programName();
126 if (displayTitle.isEmpty()) {
127 displayTitle =
i18n(
"Unknown");
131 QTreeWidgetItem *hier[3];
132 hier[KShortcutsEditorPrivate::Root] = d->ui.list->invisibleRootItem();
133 hier[KShortcutsEditorPrivate::Program] = d->findOrMakeItem( hier[KShortcutsEditorPrivate::Root], displayTitle);
134 hier[KShortcutsEditorPrivate::Action] = NULL;
142 hier[KShortcutsEditorPrivate::Action] = d->findOrMakeItem(hier[KShortcutsEditorPrivate::Program], category->
text());
145 actionsSeen.insert(action);
146 d->addAction(action, hier, KShortcutsEditorPrivate::Action);
153 if (actionsSeen.contains(action)) {
157 d->addAction(action, hier, KShortcutsEditorPrivate::Program);
161 d->ui.list->sortItems(Name, Qt::AscendingOrder);
164 setUpdatesEnabled(
true);
172 d->clearConfiguration();
176#ifndef KDE_NO_DEPRECATED
179 d->importConfiguration(
config);
186 d->importConfiguration(
config);
190#ifndef KDE_NO_DEPRECATED
204 QString groupName =
"Global Shortcuts";
211 QString groupName =
"Shortcuts";
230 for (
int i = 0; i < d->ui.list->columnCount(); i++)
231 d->ui.list->resizeColumnToContents(i);
237 for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) {
238 if (KShortcutsEditorItem* item =
dynamic_cast<KShortcutsEditorItem*
>(*it)) {
262 for (QTreeWidgetItemIterator it(d->ui.list); (*it); ++it) {
263 if (KShortcutsEditorItem* item =
dynamic_cast<KShortcutsEditorItem*
>(*it)) {
299 q->layout()->setMargin(0);
300 ui.searchFilter->searchLine()->setTreeWidget(ui.list);
301 ui.list->header()->setResizeMode(QHeaderView::ResizeToContents);
302 ui.list->header()->hideSection(GlobalAlternate);
303 ui.list->header()->hideSection(ShapeGesture);
304 ui.list->header()->hideSection(RockerGesture);
306 ui.list->header()->hideSection(GlobalPrimary);
308 ui.list->header()->hideSection(LocalPrimary);
309 ui.list->header()->hideSection(LocalAlternate);
314 delegate =
new KShortcutsEditorDelegate(
318 ui.list->setItemDelegate(delegate);
319 ui.list->setSelectionBehavior(QAbstractItemView::SelectItems);
320 ui.list->setSelectionMode(QAbstractItemView::SingleSelection);
322 ui.list->setEditTriggers(QAbstractItemView::NoEditTriggers);
323 ui.list->setAlternatingRowColors(
true);
326 QObject::connect(delegate, SIGNAL(shortcutChanged(QVariant,QModelIndex)),
327 q, SLOT(capturedShortcut(QVariant,QModelIndex)));
329 QObject::connect(ui.searchFilter->searchLine(), SIGNAL(hiddenChanged(QTreeWidgetItem*,
bool)),
330 delegate, SLOT(hiddenBySearchLine(QTreeWidgetItem*,
bool)));
332 ui.searchFilter->setFocus();
336bool KShortcutsEditorPrivate::addAction(
QAction *action, QTreeWidgetItem *hier[], hierarchyLevel level)
340 QString actionName = action->objectName();
341 if (actionName.isEmpty() || actionName.startsWith(QLatin1String(
"unnamed-"))) {
342 kError() <<
"Skipping action without name " << action->text() <<
"," << actionName <<
"!";
351 new KShortcutsEditorItem((hier[level]), kact);
358void KShortcutsEditorPrivate::allDefault()
360 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
361 if (!(*it)->parent() || (*it)->type() != ActionItem)
364 KShortcutsEditorItem *item =
static_cast<KShortcutsEditorItem *
>(*it);
386KShortcutsEditorItem *KShortcutsEditorPrivate::itemFromIndex(
QTreeWidget *
const w,
387 const QModelIndex &index)
389 QTreeWidgetItem *item =
static_cast<QTreeWidgetHack *
>(w)->itemFromIndex(index);
390 if (item && item->type() == ActionItem) {
391 return static_cast<KShortcutsEditorItem *
>(item);
397QTreeWidgetItem *KShortcutsEditorPrivate::findOrMakeItem(QTreeWidgetItem *parent,
const QString &name)
399 for (
int i = 0; i < parent->childCount(); i++) {
400 QTreeWidgetItem *child = parent->child(i);
401 if (child->text(0) == name)
404 QTreeWidgetItem *ret =
new QTreeWidgetItem(parent, NonActionItem);
405 ret->setText(0, name);
406 ui.list->expandItem(ret);
407 ret->setFlags(ret->flags() & ~Qt::ItemIsSelectable);
413void KShortcutsEditorPrivate::capturedShortcut(
const QVariant &newShortcut,
const QModelIndex &index)
416 if (!index.isValid())
418 int column = index.column();
419 KShortcutsEditorItem *item = itemFromIndex(ui.list, index);
422 if (column >= LocalPrimary && column <= GlobalAlternate)
423 changeKeyShortcut(item, column, newShortcut.value<QKeySequence>());
424 else if (column == ShapeGesture)
425 changeShapeGesture(item, newShortcut.value<
KShapeGesture>());
426 else if (column == RockerGesture)
431void KShortcutsEditorPrivate::changeKeyShortcut(KShortcutsEditorItem *item, uint column,
const QKeySequence &capture)
434 if (capture == item->keySequence(column)) {
438 item->setKeySequence(column, capture);
441 item->setText(column, capture.toString(QKeySequence::NativeText));
445void KShortcutsEditorPrivate::changeShapeGesture(KShortcutsEditorItem *item,
const KShapeGesture &capture)
447 if (capture == item->m_action->shapeGesture())
451 bool conflict =
false;
452 KShortcutsEditorItem *otherItem;
455 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
456 if (!(*it)->parent() || (*it == item))
459 otherItem =
static_cast<KShortcutsEditorItem *
>(*it);
462 if (!otherItem->m_action->shapeGesture().isValid())
465 if (capture == otherItem->m_action->shapeGesture()) {
471 if (conflict && !stealShapeGesture(otherItem, capture))
475 item->setShapeGesture(capture);
479void KShortcutsEditorPrivate::changeRockerGesture(KShortcutsEditorItem *item,
const KRockerGesture &capture)
481 if (capture == item->m_action->rockerGesture())
485 bool conflict =
false;
486 KShortcutsEditorItem *otherItem;
488 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
489 if (!(*it)->parent() || (*it == item))
492 otherItem =
static_cast<KShortcutsEditorItem *
>(*it);
494 if (capture == otherItem->m_action->rockerGesture()) {
500 if (conflict && !stealRockerGesture(otherItem, capture))
504 item->setRockerGesture(capture);
508void KShortcutsEditorPrivate::clearConfiguration()
510 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
511 if (!(*it)->parent())
514 KShortcutsEditorItem *item =
static_cast<KShortcutsEditorItem *
>(*it);
516 changeKeyShortcut(item, LocalPrimary, QKeySequence());
517 changeKeyShortcut(item, LocalAlternate, QKeySequence());
519 changeKeyShortcut(item, GlobalPrimary, QKeySequence());
520 changeKeyShortcut(item, GlobalAlternate, QKeySequence());
528void KShortcutsEditorPrivate::importConfiguration(
KConfigBase *config)
533 KConfigGroup globalShortcutsGroup(config, QLatin1String(
"Global Shortcuts"));
536 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
538 if (!(*it)->parent())
541 KShortcutsEditorItem *item =
static_cast<KShortcutsEditorItem *
>(*it);
543 QString actionName = item->data(Id).toString();
544 KShortcut sc(globalShortcutsGroup.readEntry(actionName, QString()));
545 changeKeyShortcut(item, GlobalPrimary, sc.primary());
549 KConfigGroup localShortcutsGroup(config, QLatin1String(
"Shortcuts"));
552 for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) {
554 if (!(*it)->parent())
557 KShortcutsEditorItem *item =
static_cast<KShortcutsEditorItem *
>(*it);
559 QString actionName = item->data(Name).toString();
560 KShortcut sc(localShortcutsGroup.readEntry(actionName, QString()));
561 changeKeyShortcut(item, LocalPrimary, sc.primary());
562 changeKeyShortcut(item, LocalAlternate, sc.alternate());
568bool KShortcutsEditorPrivate::stealShapeGesture(KShortcutsEditorItem *item,
const KShapeGesture &gst)
570 QString title =
i18n(
"Key Conflict");
571 QString
message =
i18n(
"The '%1' shape gesture has already been allocated to the \"%2\" action.\n"
572 "Do you want to reassign it from that action to the current one?",
573 gst.
shapeName(), item->m_action->text());
584bool KShortcutsEditorPrivate::stealRockerGesture(KShortcutsEditorItem *item,
const KRockerGesture &gst)
586 QString title =
i18n(
"Key Conflict");
587 QString
message =
i18n(
"The '%1' rocker gesture has already been allocated to the \"%2\" action.\n"
588 "Do you want to reassign it from that action to the current one?",
618void KShortcutsEditorPrivate::printShortcuts()
const
622 QTreeWidgetItem* root = ui.list->invisibleRootItem();
625 QTextCursor cursor(&doc);
626 cursor.beginEditBlock();
627 QTextCharFormat headerFormat;
628 headerFormat.setProperty(QTextFormat::FontSizeAdjustment, 3);
629 headerFormat.setFontWeight(QFont::Bold);
630 cursor.insertText(
i18nc(
"header for an applications shortcut list",
"Shortcuts for %1",
633 QTextCharFormat componentFormat;
634 componentFormat.setProperty(QTextFormat::FontSizeAdjustment, 2);
635 componentFormat.setFontWeight(QFont::Bold);
636 QTextBlockFormat componentBlockFormat = cursor.blockFormat();
637 componentBlockFormat.setTopMargin(16);
638 componentBlockFormat.setBottomMargin(16);
640 QTextTableFormat tableformat;
641 tableformat.setHeaderRowCount(1);
642 tableformat.setCellPadding(4.0);
643 tableformat.setCellSpacing(0);
644 tableformat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
645 tableformat.setBorder(0.5);
648 shortcutTitleToColumn << qMakePair(
i18n(
"Main:"), LocalPrimary);
649 shortcutTitleToColumn << qMakePair(
i18n(
"Alternate:"), LocalAlternate);
650 shortcutTitleToColumn << qMakePair(
i18n(
"Global:"), GlobalPrimary);
652 for (
int i = 0; i < root->childCount(); i++) {
653 QTreeWidgetItem* item = root->child(i);
654 cursor.insertBlock(componentBlockFormat, componentFormat);
655 cursor.insertText(item->text(0));
657 QTextTable* table = cursor.insertTable(1,3);
658 table->setFormat(tableformat);
661 QTextTableCell cell = table->cellAt(currow,0);
662 QTextCharFormat format = cell.format();
663 format.setFontWeight(QFont::Bold);
664 cell.setFormat(format);
665 cell.firstCursorPosition().insertText(
i18n(
"Action Name"));
667 cell = table->cellAt(currow,1);
668 cell.setFormat(format);
669 cell.firstCursorPosition().insertText(
i18n(
"Shortcuts"));
671 cell = table->cellAt(currow,2);
672 cell.setFormat(format);
673 cell.firstCursorPosition().insertText(
i18n(
"Description"));
676 for (QTreeWidgetItemIterator it(item); *it; ++it) {
677 if ((*it)->type() != ActionItem)
680 KShortcutsEditorItem* editoritem =
static_cast<KShortcutsEditorItem*
>(*it);
681 table->insertRows(table->rows(),1);
682 QVariant data = editoritem->data(Name,Qt::DisplayRole);
683 table->cellAt(currow, 0).firstCursorPosition().insertText(data.toString());
685 QTextTable* shortcutTable = 0 ;
686 for(
int k = 0; k < shortcutTitleToColumn.count(); k++) {
687 data = editoritem->data(shortcutTitleToColumn.at(k).second,Qt::DisplayRole);
688 QString key = data.value<QKeySequence>().toString();
691 if( !shortcutTable ) {
692 shortcutTable = table->cellAt(currow, 1).firstCursorPosition().insertTable(1,2);
693 QTextTableFormat shortcutTableFormat = tableformat;
694 shortcutTableFormat.setCellSpacing(0.0);
695 shortcutTableFormat.setHeaderRowCount(0);
696 shortcutTableFormat.setBorder(0.0);
697 shortcutTable->setFormat(shortcutTableFormat);
699 shortcutTable->insertRows(shortcutTable->rows(),1);
701 shortcutTable->cellAt(shortcutTable->rows()-1,0).firstCursorPosition().insertText(shortcutTitleToColumn.at(k).first);
702 shortcutTable->cellAt(shortcutTable->rows()-1,1).firstCursorPosition().insertText(key);
706 KAction* action = editoritem->m_action;
707 cell = table->cellAt(currow, 2);
708 format = cell.format();
709 format.setProperty(QTextFormat::FontSizeAdjustment, -1);
710 cell.setFormat(format);
711 cell.firstCursorPosition().insertHtml(action->whatsThis());
715 cursor.movePosition(QTextCursor::End);
717 cursor.endEditBlock();
721 if (dlg->exec() == QDialog::Accepted) {
728#include "kshortcutseditor.moc"
Categorize actions for KShortcutsEditor.
const QList< QAction * > actions() const
Returns the actions belonging to this category.
A container for a set of QAction objects.
void writeSettings(KConfigGroup *config=0, bool writeDefaults=false, QAction *oneAction=0) const
Write the current configurable key associations to config.
void exportGlobalShortcuts(KConfigGroup *config, bool writeDefaults=false) const
Export the current configurable global key associations to config.
KComponentData componentData() const
The KComponentData with which this class is associated.
bool isEmpty() const
Returns whether the action collection is empty or not.
QList< QAction * > actions() const
Returns the list of KActions which belong to this action collection.
Class to encapsulate user-driven action or event.
bool isShortcutConfigurable() const
Returns true if this action's shortcut is configurable.
KShapeGesture shapeGesture(ShortcutTypes type=ActiveShortcut) const
KRockerGesture rockerGesture(ShortcutTypes type=ActiveShortcut) const
@ DefaultShortcut
The shortcut is a default shortcut - it becomes active when somebody decides to reset shortcuts to de...
const KAboutData * aboutData() const
static QFont generalFont()
Returns the default general font.
An abstract class for GUI data such as ToolTip and Icon.
static int warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
Display a "warning" dialog.
QString rockerName() const
Return a user-friendly name of the button combination.
bool isValid() const
Return true if this gesture is valid.
QString shapeName() const
Return the user-visible name for this gesture's shape, like "triangle" or "line".
bool isValid() const
Return true if this gesture is valid.
Represents a keyboard shortcut.
QKeySequence primary() const
Returns the primary key sequence of this shortcut.
QKeySequence alternate() const
Returns the alternate key sequence of this shortcut.
Widget for configuration of KAccel and KGlobalAccel.
virtual ~KShortcutsEditor()
Destructor.
void resizeColumns()
Resize columns to width required.
void commit()
Commit the changes without saving.
void clearCollections()
Removes all action collections from the editor.
void clearConfiguration()
Removes all configured shortcuts.
void exportConfiguration(KConfig *config) const
Export the current setting to configuration config.
@ LetterShortcutsAllowed
Letter shortcuts are allowed.
KShortcutsEditor(KActionCollection *collection, QWidget *parent, ActionTypes actionTypes=AllActions, LetterShortcuts allowLetterShortcuts=LetterShortcutsAllowed)
Constructor.
void printShortcuts() const
Opens a printing dialog to print all the shortcuts.
@ GlobalAction
Actions which are triggered by any keypress in the windowing system.
void save()
Save the changes.
void addCollection(KActionCollection *, const QString &title=QString())
Insert an action collection, i.e.
void undoChanges()
Undo all change made since the last commit().
bool isModified() const
Are the unsaved changes?
void writeConfiguration(KConfigGroup *config=0) const
Write the current settings to the config object.
void importConfiguration(KConfig *config)
Import the settings from configuration config.
void allDefault()
Set all shortcuts to their default values (bindings).
QString i18n(const char *text)
QString i18nc(const char *ctxt, const char *text)
Defines platform-independent classes for keyboard shortcut handling.
const KComponentData & mainComponent()
KSharedConfigPtr config()
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
QPrintDialog * createPrintDialog(QPrinter *printer, PageSelectPolicy pageSelectPolicy, const QList< QWidget * > &customTabs, QWidget *parent=0)