Krita Source Code Documentation
Loading...
Searching...
No Matches
KisShortcutsEditorDelegate Class Reference

#include <KisShortcutsDialog_p.h>

+ Inheritance diagram for KisShortcutsEditorDelegate:

Public Slots

void hiddenBySearchLine (QTreeWidgetItem *, bool)
 

Signals

void shortcutChanged (QVariant, const QModelIndex &)
 

Public Member Functions

bool eventFilter (QObject *, QEvent *) override
 
 KisShortcutsEditorDelegate (QTreeWidget *parent, bool allowLetterShortcuts)
 
void setCheckActionCollections (const QList< KisKActionCollection * > checkActionCollections)
 
QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const override
 

Private Slots

void itemActivated (QModelIndex index)
 
void itemCollapsed (QModelIndex index)
 
void keySequenceChanged (const QKeySequence &)
 
void stealShortcut (const QKeySequence &seq, QAction *action)
 

Private Attributes

bool m_allowLetterShortcuts
 
QList< KisKActionCollection * > m_checkActionCollections
 List of actionCollections to check for conflicts.
 
QPersistentModelIndex m_editingIndex
 
QWidget * m_editor
 

Detailed Description

Mixes the KisKShortcutWidget into the treeview used by KisShortcutsEditor. When selecting an shortcut it changes the display from "CTRL-W" to the Widget.

Bug
That delegate uses KExtendableItemDelegate. That means a cell can be expanded. When selected a cell is replaced by a KisShortcutsEditor. When painting the widget KExtendableItemDelegate reparents the widget to the viewport of the itemview it belongs to. The widget is destroyed when the user selects another shortcut or explicitly issues a contractItem event. But when the user clears the model the delegate misses that event and doesn't delete the KShortcutseditor. And remains as a visible artifact in your treeview. Additionally when closing your application you get an assertion failure from KExtendableItemDelegate.

Definition at line 104 of file KisShortcutsDialog_p.h.

Constructor & Destructor Documentation

◆ KisShortcutsEditorDelegate()

KisShortcutsEditorDelegate::KisShortcutsEditorDelegate ( QTreeWidget * parent,
bool allowLetterShortcuts )

Definition at line 36 of file KisShortcutsEditorDelegate.cpp.

37 : KExtendableItemDelegate(parent),
38 m_allowLetterShortcuts(allowLetterShortcuts),
39 m_editor(0)
40{
41 Q_ASSERT(qobject_cast<QAbstractItemView *>(parent));
42
43 QPixmap pixmap(16, 16);
44 pixmap.fill(QColor(Qt::transparent));
45 QPainter p(&pixmap);
46 QStyleOption option;
47 option.rect = pixmap.rect();
48
49 bool isRtl = QApplication::isRightToLeft();
50 QApplication::style()->drawPrimitive(isRtl ? QStyle::PE_IndicatorArrowLeft : QStyle::PE_IndicatorArrowRight, &option, &p);
51 p.end();
52 setExtendPixmap(pixmap);
53
54 pixmap.fill(QColor(Qt::transparent));
55 p.begin(&pixmap);
56 QApplication::style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &option, &p);
57 p.end();
58 setContractPixmap(pixmap);
59
60 parent->installEventFilter(this);
61
62 // Listen to activation signals
63 // connect(parent, SIGNAL(activated(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
64 connect(parent, SIGNAL(clicked(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
65
66 // Listen to collapse signals
67 connect(parent, SIGNAL(collapsed(QModelIndex)), this, SLOT(itemCollapsed(QModelIndex)));
68}
const Params2D p
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
ChildIterator< value_type, is_const > parent(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:327

References connect(), itemActivated(), itemCollapsed(), and p.

Member Function Documentation

◆ eventFilter()

bool KisShortcutsEditorDelegate::eventFilter ( QObject * o,
QEvent * e )
override

Definition at line 218 of file KisShortcutsEditorDelegate.cpp.

219{
220 if (o == m_editor) {
221 //Prevent clicks in the empty part of the editor widget from closing the editor
222 //because they would propagate to the itemview and be interpreted as a click in
223 //an item's rect. That in turn would lead to an itemActivated() call, closing
224 //the current editor.
225
226 switch (e->type()) {
227 case QEvent::MouseButtonPress:
228 case QEvent::MouseButtonRelease:
229 case QEvent::MouseButtonDblClick:
230 return true;
231 default:
232 return false;
233 }
234 } else if (o == parent()) {
235 // Make left/right cursor keys switch items instead of operate the scroll bar
236 // (subclassing QtreeView/Widget would be cleaner but much more of a hassle)
237 // Note that in our case we know that the selection mode is SingleSelection,
238 // so we don't have to ask QAbstractItemView::selectionCommand() et al.
239
240 if (e->type() != QEvent::KeyPress) {
241 return false;
242 }
243 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
244 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
245 QItemSelectionModel *selection = view->selectionModel();
246 QModelIndex index = selection->currentIndex();
247
248 switch (ke->key()) {
249 case Qt::Key_Space:
250 case Qt::Key_Select:
251 // we are not using the standard "open editor" mechanism of QAbstractItemView,
252 // so let's emulate that here.
253 itemActivated(index);
254 return true;
255 case Qt::Key_Left:
256 index = index.sibling(index.row(), index.column() - 1);
257 break;
258 case Qt::Key_Right:
259 index = index.sibling(index.row(), index.column() + 1);
260 break;
261 default:
262 return false;
263 }
264 // a cursor key was pressed
265 if (index.isValid()) {
266 selection->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
267 //### using PositionAtCenter for now;
268 // EnsureVisible has no effect which seems to be a bug.
269 view->scrollTo(index, QAbstractItemView::PositionAtCenter);
270 }
271 return true;
272 }
273 return false;
274}

References itemActivated(), and m_editor.

◆ hiddenBySearchLine

void KisShortcutsEditorDelegate::hiddenBySearchLine ( QTreeWidgetItem * item,
bool hidden )
slot

Definition at line 206 of file KisShortcutsEditorDelegate.cpp.

207{
208 if (!hidden || !item) {
209 return;
210 }
211 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
212 QTreeWidgetItem *editingItem = ::itemFromIndex(view, m_editingIndex);
213 if (editingItem == item) {
214 itemActivated(m_editingIndex); //this will *close* the item's editor because it's already open
215 }
216}
QPersistentModelIndex m_editingIndex

References itemActivated(), and m_editingIndex.

◆ itemActivated

void KisShortcutsEditorDelegate::itemActivated ( QModelIndex index)
privateslot

Definition at line 111 of file KisShortcutsEditorDelegate.cpp.

112{
113 //As per our constructor our parent *is* a QTreeWidget
114 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
115
116 KisShortcutsEditorItem *item = ::itemFromIndex(view, index);
117 if (!item) {
118 //that probably was a non-leaf (type() !=ActionItem) item
119 return;
120 }
121
122 int column = index.column();
123 if (column == Name) {
124 // If clicking the name try to activate the Primary column
125 if (!view->header()->isSectionHidden(LocalPrimary)) {
126 column = LocalPrimary;
127 } else {
128 // do nothing.
129 }
130 index = index.sibling(index.row(), column);
131 view->selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
132 }
133
134 // Check if the models wants us to edit the item at index
135 if (!index.data(ShowExtensionIndicatorRole).value<bool>()) {
136 return;
137 }
138
139 if (!isExtended(index)) {
140 //we only want maximum ONE extender open at any time.
141 if (m_editingIndex.isValid()) {
142 KisShortcutsEditorItem *oldItem = ::itemFromIndex(view, m_editingIndex);
143 Q_ASSERT(oldItem); //here we really expect nothing but a real KisShortcutsEditorItem
144
145 oldItem->setNameBold(false);
146 contractItem(m_editingIndex);
147 }
148
149 m_editingIndex = index;
150 QWidget *viewport = static_cast<QAbstractItemView *>(parent())->viewport();
151
152 if (column >= LocalPrimary && column <= Id) {
154 new ShortcutEditWidget(viewport,
155 index.data(DefaultShortcutRole).value<QKeySequence>(),
156 index.data(ShortcutRole).value<QKeySequence>(),
158
159
161
162 editor->setCheckActionCollections(m_checkActionCollections);
163
164 connect(m_editor, SIGNAL(keySequenceChanged(QKeySequence)),
165 this, SLOT(keySequenceChanged(QKeySequence)));
166 connect(m_editor, SIGNAL(stealShortcut(QKeySequence,QAction*)),
167 this, SLOT(stealShortcut(QKeySequence,QAction*)));
168 } else {
169 return;
170 }
171
172 m_editor->installEventFilter(this);
173 item->setNameBold(true);
174 extendItem(m_editor, index);
175
176 } else {
177 //the item is extended, and clicking on it again closes it
178 item->setNameBold(false);
179 contractItem(index);
180 view->selectionModel()->select(index, QItemSelectionModel::Clear);
181 m_editingIndex = QModelIndex();
182 m_editor = 0;
183 }
184}
@ ShortcutRole
@ DefaultShortcutRole
@ LocalPrimary
void keySequenceChanged(const QKeySequence &)
QList< KisKActionCollection * > m_checkActionCollections
List of actionCollections to check for conflicts.
void stealShortcut(const QKeySequence &seq, QAction *action)

References connect(), DefaultShortcutRole, Id, keySequenceChanged(), LocalPrimary, m_allowLetterShortcuts, m_checkActionCollections, m_editingIndex, m_editor, Name, KisShortcutsEditorItem::setNameBold(), ShortcutRole, and stealShortcut().

◆ itemCollapsed

void KisShortcutsEditorDelegate::itemCollapsed ( QModelIndex index)
privateslot

When the user collapses a hole subtree of shortcuts then remove eventually extended items. Else we get that artifact bug. See above.

Definition at line 187 of file KisShortcutsEditorDelegate.cpp.

188{
189 if (!m_editingIndex.isValid()) {
190 return;
191 }
192
193 const QAbstractItemModel *model = index.model();
194 for (int row = 0; row < model->rowCount(index); ++row) {
195 for (int col = 0; col < index.model()->columnCount(index); ++col) {
196 QModelIndex colIndex = model->index(row, col, index);
197
198 if (colIndex == m_editingIndex) {
199 itemActivated(m_editingIndex); //this will *close* the item's editor because it's already open
200 }
201 }
202 }
203}

References itemActivated(), and m_editingIndex.

◆ keySequenceChanged

void KisShortcutsEditorDelegate::keySequenceChanged ( const QKeySequence & seq)
privateslot

Definition at line 277 of file KisShortcutsEditorDelegate.cpp.

278{
279 QVariant ret = QVariant::fromValue(seq);
280 Q_EMIT shortcutChanged(ret, m_editingIndex);
281}
void shortcutChanged(QVariant, const QModelIndex &)

References m_editingIndex, and shortcutChanged().

◆ setCheckActionCollections()

void KisShortcutsEditorDelegate::setCheckActionCollections ( const QList< KisKActionCollection * > checkActionCollections)

Set a list of action collections to check against for conflicting shortcuts.

See also
KisKKeySequenceWidget::setCheckActionCollections

Definition at line 283 of file KisShortcutsEditorDelegate.cpp.

285{
286 m_checkActionCollections = checkActionCollections;
287}

References m_checkActionCollections.

◆ shortcutChanged

void KisShortcutsEditorDelegate::shortcutChanged ( QVariant ,
const QModelIndex &  )
signal

◆ sizeHint()

QSize KisShortcutsEditorDelegate::sizeHint ( const QStyleOptionViewItem & option,
const QModelIndex & index ) const
override

Definition at line 102 of file KisShortcutsEditorDelegate.cpp.

104{
105 QSize ret(KExtendableItemDelegate::sizeHint(option, index));
106 ret.rheight() += 4;
107 return ret;
108}

◆ stealShortcut

void KisShortcutsEditorDelegate::stealShortcut ( const QKeySequence & seq,
QAction * action )
privateslot

If the user allowed stealing a shortcut we want to be able to undo that.

Definition at line 70 of file KisShortcutsEditorDelegate.cpp.

71{
72 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
73
74 // Iterate over all items
75 QTreeWidgetItemIterator it(view, QTreeWidgetItemIterator::NoChildren);
76
77 for (; (*it); ++it) {
78 KisShortcutsEditorItem *item = dynamic_cast<KisShortcutsEditorItem *>(*it);
79 if (item && (item->data(0, ObjectRole).value<QObject*>() == dynamic_cast<QObject*>(action))) {
80
81 // We found the action, snapshot the current state. Steal the
82 // shortcut. We will save the change later.
83 const QList<QKeySequence> cut = action->shortcuts();
84 const QKeySequence primary = cut.isEmpty() ? QKeySequence() : cut.at(0);
85 const QKeySequence alternate = cut.size() <= 1 ? QKeySequence() : cut.at(1);
86
87 if (primary.matches(seq) != QKeySequence::NoMatch
88 || seq.matches(primary) != QKeySequence::NoMatch) {
89 item->setKeySequence(LocalPrimary, QKeySequence());
90 }
91
92 if (alternate.matches(seq) != QKeySequence::NoMatch
93 || seq.matches(alternate) != QKeySequence::NoMatch) {
94 item->setKeySequence(LocalAlternate, QKeySequence());
95 }
96 break;
97 }
98 }
99
100}
@ LocalAlternate
QVariant data(int column, int role=Qt::DisplayRole) const override
void setKeySequence(uint column, const QKeySequence &seq)
QAction * cut(const QObject *recvr, const char *slot, QObject *parent)

References KisShortcutsEditorItem::data(), LocalAlternate, LocalPrimary, ObjectRole, and KisShortcutsEditorItem::setKeySequence().

Member Data Documentation

◆ m_allowLetterShortcuts

bool KisShortcutsEditorDelegate::m_allowLetterShortcuts
private

Definition at line 122 of file KisShortcutsDialog_p.h.

◆ m_checkActionCollections

QList<KisKActionCollection *> KisShortcutsEditorDelegate::m_checkActionCollections
private

List of actionCollections to check for conflicts.

Definition at line 126 of file KisShortcutsDialog_p.h.

◆ m_editingIndex

QPersistentModelIndex KisShortcutsEditorDelegate::m_editingIndex
mutableprivate

Definition at line 121 of file KisShortcutsDialog_p.h.

◆ m_editor

QWidget* KisShortcutsEditorDelegate::m_editor
private

Definition at line 123 of file KisShortcutsDialog_p.h.


The documentation for this class was generated from the following files: