• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • dialogs
kshortcutseditordelegate.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
3 Copyright (C) 1997 Nicolas Hadacek <hadacek@kde.org>
4 Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org>
5 Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
6 Copyright (C) 2006 Hamish Rodda <rodda@kde.org>
7 Copyright (C) 2007 Roberto Raggi <roberto@kdevelop.org>
8 Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com>
9 Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz>
10
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
20
21 You should have received a copy of the GNU Library General Public License
22 along with this library; see the file COPYING.LIB. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25*/
26
27
28
29#include "kshortcutsdialog_p.h"
30#include "kaction_p.h"
31
32#include <QApplication>
33#include <QHeaderView>
34#include <QKeyEvent>
35#include <QLabel>
36#include <QPainter>
37#include <QTreeWidgetItemIterator>
38
39#include "kaction.h"
40
41#include "kdebug.h"
42
43
44
45
46KShortcutsEditorDelegate::KShortcutsEditorDelegate(QTreeWidget *parent, bool allowLetterShortcuts)
47 : KExtendableItemDelegate(parent),
48 m_allowLetterShortcuts(allowLetterShortcuts),
49 m_editor(0)
50{
51 Q_ASSERT(qobject_cast<QAbstractItemView *>(parent));
52
53 QPixmap pixmap( 16, 16 );
54 pixmap.fill( QColor( Qt::transparent ) );
55 QPainter p( &pixmap );
56 QStyleOption option;
57 option.rect = pixmap.rect();
58
59 bool isRtl = QApplication::isRightToLeft();
60 QApplication::style()->drawPrimitive( isRtl ? QStyle::PE_IndicatorArrowLeft : QStyle::PE_IndicatorArrowRight, &option, &p );
61 p.end();
62 setExtendPixmap( pixmap );
63
64 pixmap.fill( QColor( Qt::transparent ) );
65 p.begin( &pixmap );
66 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowDown, &option, &p );
67 p.end();
68 setContractPixmap( pixmap );
69
70 parent->installEventFilter(this);
71
72 // Listen to activation signals
73 // connect(parent, SIGNAL(activated(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
74 connect(parent, SIGNAL(clicked(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
75
76 // Listen to collapse signals
77 connect(parent, SIGNAL(collapsed(QModelIndex)), this, SLOT(itemCollapsed(QModelIndex)));
78}
79
80
81void KShortcutsEditorDelegate::stealShortcut(
82 const QKeySequence &seq,
83 KAction *action)
84{
85 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
86
87 // Iterate over all items
88 QTreeWidgetItemIterator it(view, QTreeWidgetItemIterator::NoChildren);
89
90 for (; (*it); ++it) {
91 KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem *>(*it);
92 if (item && item->data(0, ObjectRole).value<QObject*>() == action) {
93
94 // We found the action, snapshot the current state. Steal the
95 // shortcut. We will save the change later.
96 KShortcut cut = action->shortcut();
97 if ( cut.primary().matches(seq) != QKeySequence::NoMatch
98 || seq.matches(cut.primary()) != QKeySequence::NoMatch) {
99 item->setKeySequence(LocalPrimary, QKeySequence());
100 }
101
102 if ( cut.alternate().matches(seq) != QKeySequence::NoMatch
103 || seq.matches(cut.alternate()) != QKeySequence::NoMatch) {
104 item->setKeySequence(LocalAlternate, QKeySequence());
105 }
106 break;
107 }
108 }
109
110}
111
112
113QSize KShortcutsEditorDelegate::sizeHint(const QStyleOptionViewItem &option,
114 const QModelIndex &index) const
115{
116 QSize ret(KExtendableItemDelegate::sizeHint(option, index));
117 ret.rheight() += 4;
118 return ret;
119}
120
121
122//slot
123void KShortcutsEditorDelegate::itemActivated(QModelIndex index)
124{
125 //As per our constructor our parent *is* a QTreeWidget
126 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
127
128 KShortcutsEditorItem *item = KShortcutsEditorPrivate::itemFromIndex(view, index);
129 if (!item) {
130 //that probably was a non-leaf (type() !=ActionItem) item
131 return;
132 }
133
134 int column = index.column();
135 if (column == Name) {
136 // If user click in the name column activate the (Global|Local)Primary
137 // column if possible.
138 if (!view->header()->isSectionHidden(LocalPrimary)) {
139 column = LocalPrimary;
140 } else if (!view->header()->isSectionHidden(GlobalPrimary)) {
141 column = GlobalPrimary;
142 } else {
143 // do nothing.
144 }
145 index = index.sibling(index.row(), column);
146 view->selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
147 }
148
149 // Check if the models wants us to edit the item at index
150 if (!index.data(ShowExtensionIndicatorRole).value<bool>()) {
151 return;
152 }
153
154 if (!isExtended(index)) {
155 //we only want maximum ONE extender open at any time.
156 if (m_editingIndex.isValid()) {
157 KShortcutsEditorItem *oldItem = KShortcutsEditorPrivate::itemFromIndex(view,
158 m_editingIndex);
159 Q_ASSERT(oldItem); //here we really expect nothing but a real KShortcutsEditorItem
160
161 oldItem->setNameBold(false);
162 contractItem(m_editingIndex);
163 }
164
165 m_editingIndex = index;
166 QWidget *viewport = static_cast<QAbstractItemView*>(parent())->viewport();
167
168 if (column >= LocalPrimary && column <= GlobalAlternate) {
169 ShortcutEditWidget *editor = new ShortcutEditWidget(viewport,
170 index.data(DefaultShortcutRole).value<QKeySequence>(),
171 index.data(ShortcutRole).value<QKeySequence>(),
172 m_allowLetterShortcuts);
173 if (column==GlobalPrimary) {
174 QObject *action = index.data(ObjectRole).value<QObject*>();
175 connect(
176 action, SIGNAL(globalShortcutChanged(QKeySequence)),
177 editor, SLOT(setKeySequence(QKeySequence)));
178 editor->setMultiKeyShortcutsAllowed(false);
179 KAction *kaction = qobject_cast<KAction*>(action);
180 if (kaction) {
181 editor->setComponentName(kaction->d->componentData.componentName());
182 }
183 }
184
185 m_editor = editor;
186 // For global shortcuts check against the kde standard shortcuts
187 if (column == GlobalPrimary || column == GlobalAlternate) {
188 editor->setCheckForConflictsAgainst(
189 KKeySequenceWidget::LocalShortcuts
190 | KKeySequenceWidget::GlobalShortcuts
191 | KKeySequenceWidget::StandardShortcuts );
192 }
193
194 editor->setCheckActionCollections(m_checkActionCollections);
195
196 connect(m_editor, SIGNAL(keySequenceChanged(QKeySequence)),
197 this, SLOT(keySequenceChanged(QKeySequence)));
198 connect(m_editor, SIGNAL(stealShortcut(QKeySequence,KAction*)),
199 this, SLOT(stealShortcut(QKeySequence,KAction*)));
200
201 } else if (column == RockerGesture) {
202 m_editor = new QLabel("A lame placeholder", viewport);
203
204 } else if (column == ShapeGesture) {
205 m_editor = new QLabel("<i>A towel</i>", viewport);
206
207 } else
208 return;
209
210 m_editor->installEventFilter(this);
211 item->setNameBold(true);
212 extendItem(m_editor, index);
213
214 } else {
215 //the item is extended, and clicking on it again closes it
216 item->setNameBold(false);
217 contractItem(index);
218 view->selectionModel()->select(index, QItemSelectionModel::Clear);
219 m_editingIndex = QModelIndex();
220 m_editor = 0;
221 }
222}
223
224
225//slot
226void KShortcutsEditorDelegate::itemCollapsed(QModelIndex index)
227{
228 if (!m_editingIndex.isValid()) {
229 return;
230 }
231
232 const QAbstractItemModel *model = index.model();
233 for (int row = 0; row < model->rowCount(index); ++row) {
234 QModelIndex rowIndex = model->index(row, 0, index);
235
236 for (int col = 0; col < index.model()->columnCount(index); ++col) {
237 QModelIndex colIndex = model->index(row, col, index);
238
239 if (colIndex == m_editingIndex) {
240 itemActivated(m_editingIndex); //this will *close* the item's editor because it's already open
241 }
242 }
243 }
244}
245
246
247//slot
248void KShortcutsEditorDelegate::hiddenBySearchLine(QTreeWidgetItem *item, bool hidden)
249{
250 if (!hidden || !item) {
251 return;
252 }
253 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
254 QTreeWidgetItem *editingItem = KShortcutsEditorPrivate::itemFromIndex(view, m_editingIndex);
255 if (editingItem == item) {
256 itemActivated(m_editingIndex); //this will *close* the item's editor because it's already open
257 }
258}
259
260
261bool KShortcutsEditorDelegate::eventFilter(QObject *o, QEvent *e)
262{
263 if (o == m_editor) {
264 //Prevent clicks in the empty part of the editor widget from closing the editor
265 //because they would propagate to the itemview and be interpreted as a click in
266 //an item's rect. That in turn would lead to an itemActivated() call, closing
267 //the current editor.
268
269 switch (e->type()) {
270 case QEvent::MouseButtonPress:
271 case QEvent::MouseButtonRelease:
272 case QEvent::MouseButtonDblClick:
273 return true;
274 default:
275 return false;
276 }
277 } else if (o == parent()) {
278 // Make left/right cursor keys switch items instead of operate the scroll bar
279 // (subclassing QtreeView/Widget would be cleaner but much more of a hassle)
280 // Note that in our case we know that the selection mode is SingleSelection,
281 // so we don't have to ask QAbstractItemView::selectionCommand() et al.
282
283 if (e->type() != QEvent::KeyPress) {
284 return false;
285 }
286 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
287 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
288 QItemSelectionModel *selection = view->selectionModel();
289 QModelIndex index = selection->currentIndex();
290
291 switch (ke->key()) {
292 case Qt::Key_Space:
293 case Qt::Key_Select:
294 // we are not using the standard "open editor" mechanism of QAbstractItemView,
295 // so let's emulate that here.
296 itemActivated(index);
297 return true;
298 case Qt::Key_Left:
299 index = index.sibling(index.row(), index.column() - 1);
300 break;
301 case Qt::Key_Right:
302 index = index.sibling(index.row(), index.column() + 1);
303 break;
304 default:
305 return false;
306 }
307 // a cursor key was pressed
308 if (index.isValid()) {
309 selection->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
310 //### using PositionAtCenter for now;
311 // EnsureVisible has no effect which seems to be a bug.
312 view->scrollTo(index, QAbstractItemView::PositionAtCenter);
313 }
314 return true;
315 }
316 return false;
317}
318
319
320//slot
321void KShortcutsEditorDelegate::keySequenceChanged(const QKeySequence &seq)
322{
323 QVariant ret = QVariant::fromValue(seq);
324 emit shortcutChanged(ret, m_editingIndex);
325}
326
327
328void KShortcutsEditorDelegate::setCheckActionCollections(
329 const QList<KActionCollection*> checkActionCollections )
330{
331 m_checkActionCollections = checkActionCollections;
332}
333
334//slot
335void KShortcutsEditorDelegate::shapeGestureChanged(const KShapeGesture &gest)
336{
337 //this is somewhat verbose because the gesture types are not "built in" to QVariant
338 QVariant ret = QVariant::fromValue(gest);
339 emit shortcutChanged(ret, m_editingIndex);
340}
341
342
343//slot
344void KShortcutsEditorDelegate::rockerGestureChanged(const KRockerGesture &gest)
345{
346 QVariant ret = QVariant::fromValue(gest);
347 emit shortcutChanged(ret, m_editingIndex);
348}
349
KAction
Class to encapsulate user-driven action or event.
Definition: kaction.h:217
KAction::shortcut
KShortcut shortcut
Definition: kaction.h:220
KExtendableItemDelegate
Definition: kextendableitemdelegate.h:51
KExtendableItemDelegate::sizeHint
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Re-implemented for internal reasons.
Definition: kextendableitemdelegate.cpp:178
KKeySequenceWidget::GlobalShortcuts
@ GlobalShortcuts
Check against global shortcuts.
Definition: kkeysequencewidget.h:103
KKeySequenceWidget::StandardShortcuts
@ StandardShortcuts
Check against standard shortcuts.
Definition: kkeysequencewidget.h:102
KKeySequenceWidget::LocalShortcuts
@ LocalShortcuts
Check with local shortcuts.
Definition: kkeysequencewidget.h:101
KRockerGesture
Definition: kgesture.h:153
KShapeGesture
Definition: kgesture.h:38
KShortcut
Represents a keyboard shortcut.
Definition: kshortcut.h:58
QAbstractItemModel
QItemSelectionModel
QLabel
QList
QObject
QTreeWidget
QWidget
kaction.h
kdebug.h
KStandardAction::cut
KAction * cut(const QObject *recvr, const char *slot, QObject *parent)
Cut selected area and store it in the clipboard.
Definition: kstandardaction.cpp:294
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal