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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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 
46 KShortcutsEditorDelegate::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 
81 void 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 
113 QSize 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
123 void 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
226 void 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
248 void 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 
261 bool 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
321 void KShortcutsEditorDelegate::keySequenceChanged(const QKeySequence &seq)
322 {
323  QVariant ret = QVariant::fromValue(seq);
324  emit shortcutChanged(ret, m_editingIndex);
325 }
326 
327 
328 void KShortcutsEditorDelegate::setCheckActionCollections(
329  const QList<KActionCollection*> checkActionCollections )
330 {
331  m_checkActionCollections = checkActionCollections;
332 }
333 
334 //slot
335 void 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
344 void KShortcutsEditorDelegate::rockerGestureChanged(const KRockerGesture &gest)
345 {
346  QVariant ret = QVariant::fromValue(gest);
347  emit shortcutChanged(ret, m_editingIndex);
348 }
349 
QModelIndex
QEvent
QWidget
QAbstractItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const =0
QApplication::isRightToLeft
bool isRightToLeft()
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
QEvent::type
Type type() const
QAbstractItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
kdebug.h
QAbstractItemView
KKeySequenceWidget::GlobalShortcuts
Check against global shortcuts.
Definition: kkeysequencewidget.h:103
QItemSelectionModel::currentIndex
QModelIndex currentIndex() const
QAbstractItemView::selectionModel
QItemSelectionModel * selectionModel() const
KRockerGesture
Definition: kgesture.h:152
QTreeWidgetItemIterator
KExtendableItemDelegate
Definition: kextendableitemdelegate.h:51
QVariant::value
T value() const
KAction::shortcut
KShortcut shortcut
Definition: kaction.h:220
KShortcut
Represents a keyboard shortcut.
Definition: kshortcut.h:57
KKeySequenceWidget::LocalShortcuts
Check with local shortcuts.
Definition: kkeysequencewidget.h:101
QTreeWidget
QStyleOption
QModelIndex::isValid
bool isValid() const
QKeySequence::matches
SequenceMatch matches(const QKeySequence &seq) const
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QHeaderView::isSectionHidden
bool isSectionHidden(int logicalIndex) const
QStyleOptionViewItem
QObject
QPainter
QItemSelectionModel::select
virtual void select(const QModelIndex &index, QFlags< QItemSelectionModel::SelectionFlag > command)
QModelIndex::row
int row() const
QList< KActionCollection * >
QColor
QPixmap
kaction.h
QKeyEvent::key
int key() const
QSize
KKeySequenceWidget::StandardShortcuts
Check against standard shortcuts.
Definition: kkeysequencewidget.h:102
QTreeView::scrollTo
virtual void scrollTo(const QModelIndex &index, ScrollHint hint)
QVariant::fromValue
QVariant fromValue(const T &value)
KShortcut::alternate
QKeySequence alternate() const
Returns the alternate key sequence of this shortcut.
Definition: kshortcut.cpp:139
QKeyEvent
KStandardAction::Clear
Definition: kstandardaction.h:162
QModelIndex::model
const QAbstractItemModel * model() const
QModelIndex::data
QVariant data(int role) const
QTreeWidgetItem
QApplication::style
QStyle * style()
QKeySequence
KShapeGesture
Definition: kgesture.h:37
QModelIndex::sibling
QModelIndex sibling(int row, int column) const
KAction
Class to encapsulate user-driven action or event.
Definition: kaction.h:216
QAbstractItemModel::columnCount
virtual int columnCount(const QModelIndex &parent) const =0
QModelIndex::column
int column() const
QStyle::drawPrimitive
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const =0
QAbstractItemModel
QItemSelectionModel::setCurrentIndex
void setCurrentIndex(const QModelIndex &index, QFlags< QItemSelectionModel::SelectionFlag > command)
QTreeView::header
QHeaderView * header() const
KShortcut::primary
QKeySequence primary() const
Returns the primary key sequence of this shortcut.
Definition: kshortcut.cpp:134
QItemSelectionModel
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QLabel
KExtendableItemDelegate::sizeHint
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Re-implemented for internal reasons.
Definition: kextendableitemdelegate.cpp:178
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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