QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsshortcutsmanager.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsshortcutsmanager.cpp
3  ---------------------
4  begin : May 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsshortcutsmanager.h"
17 #include "qgslogger.h"
18 #include "qgssettings.h"
19 
20 #include <QShortcut>
21 
22 QgsShortcutsManager::QgsShortcutsManager( QObject *parent, const QString &settingsRoot )
23  : QObject( parent )
24  , mSettingsPath( settingsRoot )
25 {
26 }
27 
28 void QgsShortcutsManager::registerAllChildren( QObject *object, bool recursive )
29 {
30  registerAllChildActions( object, recursive );
31  registerAllChildShortcuts( object, recursive );
32 }
33 
34 void QgsShortcutsManager::registerAllChildActions( QObject *object, bool recursive )
35 {
36  if ( recursive )
37  {
38  QList< QAction * > actions = object->findChildren< QAction * >();
39  const auto constActions = actions;
40  for ( QAction *a : constActions )
41  {
42  registerAction( a, a->shortcut().toString( QKeySequence::NativeText ) );
43  }
44  }
45  else
46  {
47  const auto constChildren = object->children();
48  for ( QObject *child : constChildren )
49  {
50  if ( QAction *a = qobject_cast<QAction *>( child ) )
51  {
52  registerAction( a, a->shortcut().toString( QKeySequence::NativeText ) );
53  }
54  }
55  }
56 }
57 
58 void QgsShortcutsManager::registerAllChildShortcuts( QObject *object, bool recursive )
59 {
60  if ( recursive )
61  {
62  QList< QShortcut * > shortcuts = object->findChildren< QShortcut * >();
63  const auto constShortcuts = shortcuts;
64  for ( QShortcut *s : constShortcuts )
65  {
66  registerShortcut( s, s->key().toString( QKeySequence::NativeText ) );
67  }
68  }
69  else
70  {
71  const auto constChildren = object->children();
72  for ( QObject *child : constChildren )
73  {
74  if ( QShortcut *s = qobject_cast<QShortcut *>( child ) )
75  {
76  registerShortcut( s, s->key().toString( QKeySequence::NativeText ) );
77  }
78  }
79  }
80 }
81 
82 bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaultSequence )
83 {
84  if ( mActions.contains( action ) )
85  return false; // already registered
86 
87 #ifdef QGISDEBUG
88  // if using a debug build, warn on duplicate actions
89  if ( actionByName( action->text() ) || shortcutByName( action->text() ) )
90  QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( action->text() ) );
91 #endif
92 
93  mActions.insert( action, defaultSequence );
94  connect( action, &QObject::destroyed, this, &QgsShortcutsManager::actionDestroyed );
95 
96  QString actionText = action->text();
97  actionText.remove( '&' ); // remove the accelerator
98 
99  // load overridden value from settings
100  QgsSettings settings;
101  QString sequence = settings.value( mSettingsPath + actionText, defaultSequence ).toString();
102 
103  action->setShortcut( sequence );
104  if ( !action->toolTip().isEmpty() )
105  {
106  const QStringList parts = action->toolTip().split( '\n' );
107  QString formatted = QStringLiteral( "<b>%1</b>" ).arg( parts.at( 0 ) );
108  if ( parts.count() > 1 )
109  {
110  for ( int i = 1; i < parts.count(); ++i )
111  formatted += QStringLiteral( "<p>%1</p>" ).arg( parts.at( i ) );
112  }
113 
114  action->setToolTip( formatted );
115  updateActionToolTip( action, sequence );
116  }
117 
118  return true;
119 }
120 
121 bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &defaultSequence )
122 {
123 #ifdef QGISDEBUG
124  // if using a debug build, warn on duplicate actions
125  if ( actionByName( shortcut->objectName() ) || shortcutByName( shortcut->objectName() ) )
126  QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( shortcut->objectName() ) );
127 #endif
128 
129  mShortcuts.insert( shortcut, defaultSequence );
130  connect( shortcut, &QObject::destroyed, this, &QgsShortcutsManager::shortcutDestroyed );
131 
132  QString shortcutName = shortcut->objectName();
133 
134  // load overridden value from settings
135  QgsSettings settings;
136  QString keySequence = settings.value( mSettingsPath + shortcutName, defaultSequence ).toString();
137 
138  shortcut->setKey( keySequence );
139 
140  return true;
141 }
142 
144 {
145  if ( !mActions.contains( action ) )
146  return false;
147 
148  mActions.remove( action );
149  return true;
150 }
151 
152 bool QgsShortcutsManager::unregisterShortcut( QShortcut *shortcut )
153 {
154  if ( !mShortcuts.contains( shortcut ) )
155  return false;
156 
157  mShortcuts.remove( shortcut );
158  return true;
159 }
160 
161 QList<QAction *> QgsShortcutsManager::listActions() const
162 {
163  return mActions.keys();
164 }
165 
166 QList<QShortcut *> QgsShortcutsManager::listShortcuts() const
167 {
168  return mShortcuts.keys();
169 }
170 
171 QList<QObject *> QgsShortcutsManager::listAll() const
172 {
173  QList< QObject * > list;
174  ActionsHash::const_iterator actionIt = mActions.constBegin();
175  for ( ; actionIt != mActions.constEnd(); ++actionIt )
176  {
177  list << actionIt.key();
178  }
179  ShortcutsHash::const_iterator shortcutIt = mShortcuts.constBegin();
180  for ( ; shortcutIt != mShortcuts.constEnd(); ++shortcutIt )
181  {
182  list << shortcutIt.key();
183  }
184  return list;
185 }
186 
187 QString QgsShortcutsManager::objectDefaultKeySequence( QObject *object ) const
188 {
189  if ( QAction *action = qobject_cast< QAction * >( object ) )
190  return defaultKeySequence( action );
191  else if ( QShortcut *shortcut = qobject_cast< QShortcut * >( object ) )
192  return defaultKeySequence( shortcut );
193  else
194  return QString();
195 }
196 
197 QString QgsShortcutsManager::defaultKeySequence( QAction *action ) const
198 {
199  return mActions.value( action, QString() );
200 }
201 
202 QString QgsShortcutsManager::defaultKeySequence( QShortcut *shortcut ) const
203 {
204  return mShortcuts.value( shortcut, QString() );
205 }
206 
207 bool QgsShortcutsManager::setKeySequence( const QString &name, const QString &sequence )
208 {
209  if ( QAction *action = actionByName( name ) )
210  return setKeySequence( action, sequence );
211  else if ( QShortcut *shortcut = shortcutByName( name ) )
212  return setKeySequence( shortcut, sequence );
213  else
214  return false;
215 }
216 
217 bool QgsShortcutsManager::setObjectKeySequence( QObject *object, const QString &sequence )
218 {
219  if ( QAction *action = qobject_cast< QAction * >( object ) )
220  return setKeySequence( action, sequence );
221  else if ( QShortcut *shortcut = qobject_cast< QShortcut * >( object ) )
222  return setKeySequence( shortcut, sequence );
223  else
224  return false;
225 }
226 
227 bool QgsShortcutsManager::setKeySequence( QAction *action, const QString &sequence )
228 {
229  action->setShortcut( sequence );
230  this->updateActionToolTip( action, sequence );
231 
232  QString actionText = action->text();
233  actionText.remove( '&' ); // remove the accelerator
234 
235  // save to settings
236  QgsSettings settings;
237  settings.setValue( mSettingsPath + actionText, sequence );
238  return true;
239 }
240 
241 bool QgsShortcutsManager::setKeySequence( QShortcut *shortcut, const QString &sequence )
242 {
243  shortcut->setKey( sequence );
244 
245  QString shortcutText = shortcut->objectName();
246 
247  // save to settings
248  QgsSettings settings;
249  settings.setValue( mSettingsPath + shortcutText, sequence );
250  return true;
251 }
252 
253 QObject *QgsShortcutsManager::objectForSequence( const QKeySequence &sequence ) const
254 {
255  if ( QAction *action = actionForSequence( sequence ) )
256  return action;
257  else if ( QShortcut *shortcut = shortcutForSequence( sequence ) )
258  return shortcut;
259  else
260  return nullptr;
261 }
262 
263 QAction *QgsShortcutsManager::actionForSequence( const QKeySequence &sequence ) const
264 {
265  if ( sequence.isEmpty() )
266  return nullptr;
267 
268  for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
269  {
270  if ( it.key()->shortcut() == sequence )
271  return it.key();
272  }
273 
274  return nullptr;
275 }
276 
277 QShortcut *QgsShortcutsManager::shortcutForSequence( const QKeySequence &sequence ) const
278 {
279  if ( sequence.isEmpty() )
280  return nullptr;
281 
282  for ( ShortcutsHash::const_iterator it = mShortcuts.constBegin(); it != mShortcuts.constEnd(); ++it )
283  {
284  if ( it.key()->key() == sequence )
285  return it.key();
286  }
287 
288  return nullptr;
289 }
290 
291 QAction *QgsShortcutsManager::actionByName( const QString &name ) const
292 {
293  for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
294  {
295  if ( it.key()->text() == name )
296  return it.key();
297  }
298 
299  return nullptr;
300 }
301 
302 QShortcut *QgsShortcutsManager::shortcutByName( const QString &name ) const
303 {
304  for ( ShortcutsHash::const_iterator it = mShortcuts.constBegin(); it != mShortcuts.constEnd(); ++it )
305  {
306  if ( it.key()->objectName() == name )
307  return it.key();
308  }
309 
310  return nullptr;
311 }
312 
313 void QgsShortcutsManager::actionDestroyed()
314 {
315  mActions.remove( qobject_cast<QAction *>( sender() ) );
316 }
317 
318 void QgsShortcutsManager::shortcutDestroyed()
319 {
320  mShortcuts.remove( qobject_cast<QShortcut *>( sender() ) );
321 }
322 
323 void QgsShortcutsManager::updateActionToolTip( QAction *action, const QString &sequence )
324 {
325  QString current = action->toolTip();
326  // Remove the old shortcut.
327  QRegExp rx( "\\(.*\\)" );
328  current.replace( rx, QString() );
329 
330  if ( !sequence.isEmpty() )
331  {
332  action->setToolTip( current + " (" + sequence + ")" );
333  }
334  else
335  {
336  action->setToolTip( current );
337  }
338 }
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
bool setKeySequence(const QString &name, const QString &sequence)
Modifies an action or shortcut's key sequence.
QList< QObject * > listAll() const
Returns a list of both actions and shortcuts in the manager.
QgsShortcutsManager(QObject *parent=nullptr, const QString &settingsRoot="/shortcuts/")
Constructor for QgsShortcutsManager.
QString objectDefaultKeySequence(QObject *object) const
Returns the default sequence for an object (either a QAction or QShortcut).
QList< QShortcut * > listShortcuts() const
Returns a list of shortcuts in the manager.
bool unregisterShortcut(QShortcut *shortcut)
Removes a shortcut from the manager.
bool registerShortcut(QShortcut *shortcut, const QString &defaultSequence=QString())
Registers a QShortcut with the manager so the shortcut can be configured in GUI.
QString defaultKeySequence(QAction *action) const
Returns the default sequence for an action.
bool setObjectKeySequence(QObject *object, const QString &sequence)
Modifies an object's (either a QAction or a QShortcut) key sequence.
bool registerAction(QAction *action, const QString &defaultShortcut=QString())
Registers an action with the manager so the shortcut can be configured in GUI.
void registerAllChildren(QObject *object, bool recursive=false)
Automatically registers all QActions and QShortcuts which are children of the passed object.
QShortcut * shortcutByName(const QString &name) const
Returns a shortcut by its name, or nullptr if nothing found.
void registerAllChildShortcuts(QObject *object, bool recursive=false)
Automatically registers all QShortcuts which are children of the passed object.
QAction * actionByName(const QString &name) const
Returns an action by its name, or nullptr if nothing found.
QShortcut * shortcutForSequence(const QKeySequence &sequence) const
Returns the shortcut which is associated for a key sequence, or nullptr if no shortcut is associated.
QList< QAction * > listActions() const
Returns a list of all actions in the manager.
QAction * actionForSequence(const QKeySequence &sequence) const
Returns the action which is associated for a shortcut sequence, or nullptr if no action is associated...
void registerAllChildActions(QObject *object, bool recursive=false)
Automatically registers all QActions which are children of the passed object.
bool unregisterAction(QAction *action)
Removes an action from the manager.
QObject * objectForSequence(const QKeySequence &sequence) const
Returns the object (QAction or QShortcut) matching the specified key sequence,.