KXmlGui

kshortcutseditoritem.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 1998 Mark Donohoe <[email protected]>
4  SPDX-FileCopyrightText: 1997 Nicolas Hadacek <[email protected]>
5  SPDX-FileCopyrightText: 1998 Matthias Ettrich <[email protected]>
6  SPDX-FileCopyrightText: 2001 Ellis Whitehead <[email protected]>
7  SPDX-FileCopyrightText: 2006 Hamish Rodda <[email protected]>
8  SPDX-FileCopyrightText: 2007 Roberto Raggi <[email protected]>
9  SPDX-FileCopyrightText: 2007 Andreas Hartmetz <[email protected]>
10  SPDX-FileCopyrightText: 2008 Michael Jansen <[email protected]>
11 
12  SPDX-License-Identifier: LGPL-2.0-or-later
13 */
14 #include "config-xmlgui.h"
15 
16 #include "kshortcutsdialog_p.h"
17 #include "debug.h"
18 
19 #include <QAction>
20 #include <QTreeWidgetItem>
21 
22 #if HAVE_GLOBALACCEL
23 # include <kglobalaccel.h>
24 #endif
25 
26 KShortcutsEditorItem::KShortcutsEditorItem(QTreeWidgetItem *parent, QAction *action)
27  : QTreeWidgetItem(parent, ActionItem)
28  , m_action(action)
29  , m_isNameBold(false)
30  , m_oldLocalShortcut(nullptr)
31  , m_oldGlobalShortcut(nullptr)
32 {
33  // Filtering message requested by translators (scripting).
34  m_id = m_action->objectName();
35  m_actionNameInTable = i18nc("@item:intable Action name in shortcuts configuration", "%1", KLocalizedString::removeAcceleratorMarker(m_action->text()));
36  if (m_actionNameInTable.isEmpty()) {
37  qCWarning(DEBUG_KXMLGUI) << "Action without text!" << m_action->objectName();
38  m_actionNameInTable = m_id;
39  }
40 
41  m_collator.setNumericMode(true);
42  m_collator.setCaseSensitivity(Qt::CaseSensitive);
43 }
44 
45 KShortcutsEditorItem::~KShortcutsEditorItem()
46 {
47  delete m_oldLocalShortcut;
48  delete m_oldGlobalShortcut;
49 }
50 
51 bool KShortcutsEditorItem::isModified() const
52 {
53  return m_oldLocalShortcut || m_oldGlobalShortcut;
54 }
55 
56 QVariant KShortcutsEditorItem::data(int column, int role) const
57 {
58  switch (role) {
59  case Qt::DisplayRole:
60  switch (column) {
61  case Name:
62  return m_actionNameInTable;
63  case Id:
64  return m_id;
65  case LocalPrimary:
66  case LocalAlternate:
67  case GlobalPrimary:
68  case GlobalAlternate:
69  return keySequence(column);
70  default:
71  break;
72  }
73  break;
74  case Qt::DecorationRole:
75  if (column == Name) {
76  return m_action->icon();
77  } else {
78  return QIcon();
79  }
80  case Qt::WhatsThisRole:
81  return m_action->whatsThis();
82  case Qt::ToolTipRole:
83  // There is no such thing as a QAction::description(). So we have
84  // nothing to display here.
85  return QVariant();
86  case Qt::FontRole:
87  if (column == Name && m_isNameBold) {
88  QFont modifiedFont = treeWidget()->font();
89  modifiedFont.setBold(true);
90  return modifiedFont;
91  }
92  break;
93  case KExtendableItemDelegate::ShowExtensionIndicatorRole:
94  switch (column) {
95  case Name:
96  return false;
97  case LocalPrimary:
98  case LocalAlternate:
99  return !m_action->property("isShortcutConfigurable").isValid()
100  || m_action->property("isShortcutConfigurable").toBool();
101 #if HAVE_GLOBALACCEL
102  case GlobalPrimary:
103  case GlobalAlternate:
104  if (!KGlobalAccel::self()->hasShortcut(m_action)) {
105  return false;
106  }
107  return true;
108 #endif
109  default:
110  return false;
111  }
112  //the following are custom roles, defined in this source file only
113  case ShortcutRole:
114  switch (column) {
115  case LocalPrimary:
116  case LocalAlternate:
117  case GlobalPrimary:
118  case GlobalAlternate:
119  return keySequence(column);
120  default:
121  // Column not valid for this role
122  Q_ASSERT(false);
123  return QVariant();
124  }
125 
126  case DefaultShortcutRole: {
127  QList<QKeySequence> defaultShortcuts = m_action->property("defaultShortcuts").value<QList<QKeySequence> >();
128 #if HAVE_GLOBALACCEL
129  QList<QKeySequence> defaultGlobalShortcuts = KGlobalAccel::self()->defaultShortcut(m_action);
130 #endif
131 
132  switch (column) {
133  case LocalPrimary:
134  return primarySequence(defaultShortcuts);
135  case LocalAlternate:
136  return alternateSequence(defaultShortcuts);
137 #if HAVE_GLOBALACCEL
138  case GlobalPrimary:
139  return primarySequence(defaultGlobalShortcuts);
140  case GlobalAlternate:
141  return alternateSequence(defaultGlobalShortcuts);
142 #endif
143  default:
144  // Column not valid for this role
145  Q_ASSERT(false);
146  return QVariant();
147  }
148  }
149  case ObjectRole:
150  return QVariant::fromValue(static_cast<QObject *>(m_action));
151 
152  default:
153  break;
154  }
155 
156  return QVariant();
157 }
158 
159 bool KShortcutsEditorItem::operator<(const QTreeWidgetItem &other) const
160 {
161  const int column = treeWidget() ? treeWidget()->sortColumn() : 0;
162  return m_collator.compare(text(column), other.text(column)) < 0;
163 }
164 
165 QKeySequence KShortcutsEditorItem::keySequence(uint column) const
166 {
167  QList<QKeySequence> shortcuts = m_action->shortcuts();
168 #if HAVE_GLOBALACCEL
169  QList<QKeySequence> globalShortcuts = KGlobalAccel::self()->shortcut(m_action);
170 #endif
171 
172  switch (column) {
173  case LocalPrimary:
174  return primarySequence(shortcuts);
175  case LocalAlternate:
176  return alternateSequence(shortcuts);
177 #if HAVE_GLOBALACCEL
178  case GlobalPrimary:
179  return primarySequence(globalShortcuts);
180  case GlobalAlternate:
181  return alternateSequence(globalShortcuts);
182 #endif
183  default:
184  return QKeySequence();
185  }
186 }
187 
188 void KShortcutsEditorItem::setKeySequence(uint column, const QKeySequence &seq)
189 {
191 #if HAVE_GLOBALACCEL
192  if (column == GlobalPrimary || column == GlobalAlternate) {
193  ks = KGlobalAccel::self()->shortcut(m_action);
194  if (!m_oldGlobalShortcut) {
195  m_oldGlobalShortcut = new QList<QKeySequence>(ks);
196  }
197  } else
198 #endif
199  {
200  ks = m_action->shortcuts();
201  if (!m_oldLocalShortcut) {
202  m_oldLocalShortcut = new QList<QKeySequence>(ks);
203  }
204  }
205 
206  if (column == LocalAlternate || column == GlobalAlternate) {
207  if (ks.isEmpty()) {
208  ks << QKeySequence();
209  }
210 
211  if (ks.size() <= 1) {
212  ks << seq;
213  } else {
214  ks[1] = seq;
215  }
216  } else {
217  if (ks.isEmpty()) {
218  ks << seq;
219  } else {
220  ks[0] = seq;
221  }
222  }
223 
224  //avoid also setting the default shortcut - what we are setting here is custom by definition
225 #if HAVE_GLOBALACCEL
226  if (column == GlobalPrimary || column == GlobalAlternate) {
228 
229  } else
230 #endif
231  {
232  m_action->setShortcuts(ks);
233  }
234 
235  updateModified();
236 }
237 
238 //our definition of modified is "modified since the chooser was shown".
239 void KShortcutsEditorItem::updateModified()
240 {
241  if (m_oldLocalShortcut && *m_oldLocalShortcut == m_action->shortcuts()) {
242  delete m_oldLocalShortcut;
243  m_oldLocalShortcut = nullptr;
244  }
245 #if HAVE_GLOBALACCEL
246  if (m_oldGlobalShortcut && *m_oldGlobalShortcut == KGlobalAccel::self()->shortcut(m_action)) {
247  delete m_oldGlobalShortcut;
248  m_oldGlobalShortcut = nullptr;
249  }
250 #endif
251 }
252 
253 bool KShortcutsEditorItem::isModified(uint column) const
254 {
255  switch (column) {
256  case Name:
257  return false;
258  case LocalPrimary:
259  case LocalAlternate:
260  if (!m_oldLocalShortcut) {
261  return false;
262  }
263  if (column == LocalPrimary) {
264  return primarySequence(*m_oldLocalShortcut) != primarySequence(m_action->shortcuts());
265  } else {
266  return alternateSequence(*m_oldLocalShortcut) != alternateSequence(m_action->shortcuts());
267  }
268 #if HAVE_GLOBALACCEL
269  case GlobalPrimary:
270  case GlobalAlternate:
271  if (!m_oldGlobalShortcut) {
272  return false;
273  }
274  if (column == GlobalPrimary) {
275  return primarySequence(*m_oldGlobalShortcut) != primarySequence(KGlobalAccel::self()->shortcut(m_action));
276  } else {
277  return alternateSequence(*m_oldGlobalShortcut) != alternateSequence(KGlobalAccel::self()->shortcut(m_action));
278  }
279 #endif
280  default:
281  return false;
282  }
283 }
284 
285 void KShortcutsEditorItem::undo()
286 {
287  if (m_oldLocalShortcut) {
288  // We only ever reset the active Shortcut
289  m_action->setShortcuts(*m_oldLocalShortcut);
290  }
291 
292 #if HAVE_GLOBALACCEL
293  if (m_oldGlobalShortcut) {
294  KGlobalAccel::self()->setShortcut(m_action, *m_oldGlobalShortcut, KGlobalAccel::NoAutoloading);
295  }
296 #endif
297 
298  updateModified();
299 }
300 
301 void KShortcutsEditorItem::commit()
302 {
303  delete m_oldLocalShortcut;
304  m_oldLocalShortcut = nullptr;
305  delete m_oldGlobalShortcut;
306  m_oldGlobalShortcut = nullptr;
307 }
static QString removeAcceleratorMarker(const QString &label)
int size() const const
T value(int i) const const
void setBold(bool enable)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
CaseSensitive
bool isEmpty() const const
DisplayRole
QList< QKeySequence > shortcut(const QAction *action) const
QVariant fromValue(const T &value)
static KGlobalAccel * self()
void keySequence(QWindow *window, const QKeySequence &keySequence)
const QList< QKeySequence > & shortcut(StandardShortcut id)
QList< QKeySequence > defaultShortcut(const QAction *action) const
bool setShortcut(QAction *action, const QList< QKeySequence > &shortcut, GlobalShortcutLoading loadFlag=Autoloading)
QString text(int column) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Aug 12 2020 22:50:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.