Composite setting key for QAction & QShortcuts keyboad shortcuts

This commit is contained in:
Yoann Quenach de Quivillic 2023-03-23 22:54:24 +01:00 committed by Nyall Dawson
parent b148ff1051
commit b35d5fd15d
4 changed files with 188 additions and 85 deletions

View File

@ -36,25 +36,27 @@ Constructor for QgsShortcutsManager.
taken to not register actions which conflict with the built in QGIS actions. taken to not register actions which conflict with the built in QGIS actions.
%End %End
void registerAllChildren( QObject *object, bool recursive = false ); void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring %Docstring
Automatically registers all QActions and QShortcuts which are children of the Automatically registers all QActions and QShortcuts which are children of the
passed object. passed object.
:param object: parent object containing actions and shortcuts to register :param object: parent object containing actions and shortcuts to register
:param recursive: set to ``True`` to recursively add child actions and shortcuts :param recursive: set to ``True`` to recursively add child actions and shortcuts
:param section: Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
.. seealso:: :py:func:`registerAllChildActions` .. seealso:: :py:func:`registerAllChildActions`
.. seealso:: :py:func:`registerAllChildShortcuts` .. seealso:: :py:func:`registerAllChildShortcuts`
%End %End
void registerAllChildActions( QObject *object, bool recursive = false ); void registerAllChildActions( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring %Docstring
Automatically registers all QActions which are children of the passed object. Automatically registers all QActions which are children of the passed object.
:param object: parent object containing actions to register :param object: parent object containing actions to register
:param recursive: set to ``True`` to recursively add child actions :param recursive: set to ``True`` to recursively add child actions
:param section: Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
.. seealso:: :py:func:`registerAction` .. seealso:: :py:func:`registerAction`
@ -63,12 +65,13 @@ Automatically registers all QActions which are children of the passed object.
.. seealso:: :py:func:`registerAllChildShortcuts` .. seealso:: :py:func:`registerAllChildShortcuts`
%End %End
void registerAllChildShortcuts( QObject *object, bool recursive = false ); void registerAllChildShortcuts( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring %Docstring
Automatically registers all QShortcuts which are children of the passed object. Automatically registers all QShortcuts which are children of the passed object.
:param object: parent object containing shortcuts to register :param object: parent object containing shortcuts to register
:param recursive: set to ``True`` to recursively add child shortcuts :param recursive: set to ``True`` to recursively add child shortcuts
:param section: Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
.. seealso:: :py:func:`registerShortcut` .. seealso:: :py:func:`registerShortcut`
@ -77,13 +80,14 @@ Automatically registers all QShortcuts which are children of the passed object.
.. seealso:: :py:func:`registerAllChildActions` .. seealso:: :py:func:`registerAllChildActions`
%End %End
bool registerAction( QAction *action, const QString &defaultShortcut = QString() ); bool registerAction( QAction *action, const QString &defaultShortcut = QString(), const QString &section = QString() );
%Docstring %Docstring
Registers an action with the manager so the shortcut can be configured in GUI. Registers an action with the manager so the shortcut can be configured in GUI.
:param action: action to register. The action must have a unique text string for :param action: action to register. The action must have a unique text string for
identification. identification.
:param defaultShortcut: default key sequence for action :param defaultShortcut: default key sequence for action
:param section: Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
:return: ``True`` if action was successfully registered :return: ``True`` if action was successfully registered
@ -94,13 +98,14 @@ Registers an action with the manager so the shortcut can be configured in GUI.
.. seealso:: :py:func:`registerAllChildActions` .. seealso:: :py:func:`registerAllChildActions`
%End %End
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString() ); bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() );
%Docstring %Docstring
Registers a QShortcut with the manager so the shortcut can be configured in GUI. Registers a QShortcut with the manager so the shortcut can be configured in GUI.
:param shortcut: QShortcut to register. The shortcut must have a unique QObject.objectName() for :param shortcut: QShortcut to register. The shortcut must have a unique QObject.objectName() for
identification. identification.
:param defaultSequence: default key sequence for shortcut :param defaultSequence: default key sequence for shortcut
:param section: Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
:return: ``True`` if shortcut was successfully registered :return: ``True`` if shortcut was successfully registered
@ -291,6 +296,22 @@ Returns a shortcut by its name, or ``None`` if nothing found
QString settingsPath() const; QString settingsPath() const;
%Docstring %Docstring
Returns the root settings path used to store shortcut customization. Returns the root settings path used to store shortcut customization.
%End
QString objectSettingKey( QObject *object ) const;
%Docstring
Returns the full settings key matching the QShortcut or QAction
Return an empty QString if the QObject is not registered
.. versionadded:: 3.30
%End
QObject *objectForSettingKey( const QString &name ) const;
%Docstring
Returns the QShortcut or QAction matching the the full setting key
Return None if the key was not found
.. versionadded:: 3.30
%End %End
}; };

View File

@ -89,6 +89,7 @@ void QgsConfigureShortcutsDialog::populateActions()
QString actionText; QString actionText;
QString sequence; QString sequence;
QIcon icon; QIcon icon;
const QString settingKey = mManager->objectSettingKey( obj );
if ( QAction *action = qobject_cast< QAction * >( obj ) ) if ( QAction *action = qobject_cast< QAction * >( obj ) )
{ {
@ -118,6 +119,7 @@ void QgsConfigureShortcutsDialog::populateActions()
QTreeWidgetItem *item = new QTreeWidgetItem( lst ); QTreeWidgetItem *item = new QTreeWidgetItem( lst );
item->setIcon( 0, icon ); item->setIcon( 0, icon );
item->setData( 0, Qt::UserRole, QVariant::fromValue( obj ) ); item->setData( 0, Qt::UserRole, QVariant::fromValue( obj ) );
item->setToolTip( 0, settingKey );
items.append( item ); items.append( item );
} }
@ -158,7 +160,7 @@ void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
QDomDocument doc( QStringLiteral( "shortcuts" ) ); QDomDocument doc( QStringLiteral( "shortcuts" ) );
QDomElement root = doc.createElement( QStringLiteral( "qgsshortcuts" ) ); QDomElement root = doc.createElement( QStringLiteral( "qgsshortcuts" ) );
root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0" ) ); root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1" ) );
root.setAttribute( QStringLiteral( "locale" ), settings.value( QgsApplication::settingsLocaleUserLocale->key(), "en_US" ).toString() ); root.setAttribute( QStringLiteral( "locale" ), settings.value( QgsApplication::settingsLocaleUserLocale->key(), "en_US" ).toString() );
doc.appendChild( root ); doc.appendChild( root );
@ -167,6 +169,7 @@ void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
{ {
QString actionText; QString actionText;
QString actionShortcut; QString actionShortcut;
QString actionSettingKey;
QKeySequence sequence; QKeySequence sequence;
if ( QAction *action = qobject_cast< QAction * >( obj ) ) if ( QAction *action = qobject_cast< QAction * >( obj ) )
@ -186,7 +189,9 @@ void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
continue; continue;
} }
if ( actionText.isEmpty() || actionShortcut.isEmpty() ) actionSettingKey = mManager->objectSettingKey( obj );
if ( actionSettingKey.isEmpty() )
{ {
continue; continue;
} }
@ -200,6 +205,7 @@ void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
QDomElement el = doc.createElement( QStringLiteral( "action" ) ); QDomElement el = doc.createElement( QStringLiteral( "action" ) );
el.setAttribute( QStringLiteral( "name" ), actionText ); el.setAttribute( QStringLiteral( "name" ), actionText );
el.setAttribute( QStringLiteral( "shortcut" ), actionShortcut ); el.setAttribute( QStringLiteral( "shortcut" ), actionShortcut );
el.setAttribute( QStringLiteral( "setting" ), actionSettingKey );
root.appendChild( el ); root.appendChild( el );
} }
@ -262,22 +268,44 @@ void QgsConfigureShortcutsDialog::loadShortcuts()
currentLocale = QLocale().name(); currentLocale = QLocale().name();
} }
const QString version = root.attribute( QStringLiteral( "version" ) );
if ( root.attribute( QStringLiteral( "locale" ) ) != currentLocale ) if ( root.attribute( QStringLiteral( "locale" ) ) != currentLocale )
{
if ( version < "1.1" )
{ {
QMessageBox::information( this, tr( "Loading Shortcuts" ), QMessageBox::information( this, tr( "Loading Shortcuts" ),
tr( "The file contains shortcuts created with different locale, so you can't use it." ) ); tr( "The file contains shortcuts created with different locale, so you can't use it." ) );
return; return;
} }
else // From version 1.1, if objectName is not empty, it is used as key.
{
QMessageBox::information( this, tr( "Loading Shortcuts" ),
tr( "The file contains shortcuts created with different locale, so some shortcuts may not work." ) );
}
}
QString actionName; QString actionName;
QString actionShortcut; QString actionShortcut;
QString actionSettingKey;
QDomElement child = root.firstChildElement(); QDomElement child = root.firstChildElement();
while ( !child.isNull() ) while ( !child.isNull() )
{ {
actionName = child.attribute( QStringLiteral( "name" ) );
actionShortcut = child.attribute( QStringLiteral( "shortcut" ) ); actionShortcut = child.attribute( QStringLiteral( "shortcut" ) );
if ( version < "1.1" )
{
actionName = child.attribute( QStringLiteral( "name" ) );
mManager->setKeySequence( actionName, actionShortcut ); mManager->setKeySequence( actionName, actionShortcut );
}
else
{
actionSettingKey = child.attribute( QStringLiteral( "setting" ) );
QObject *obj = mManager->objectForSettingKey( actionSettingKey );
if ( obj )
mManager->setObjectKeySequence( obj, actionShortcut );
}
child = child.nextSiblingElement(); child = child.nextSiblingElement();
} }

View File

@ -27,87 +27,79 @@ QgsShortcutsManager::QgsShortcutsManager( QObject *parent, const QString &settin
{ {
} }
void QgsShortcutsManager::registerAllChildren( QObject *object, bool recursive ) void QgsShortcutsManager::registerAllChildren( QObject *object, bool recursive, const QString &section )
{ {
registerAllChildActions( object, recursive ); registerAllChildActions( object, recursive, section );
registerAllChildShortcuts( object, recursive ); registerAllChildShortcuts( object, recursive, section );
} }
void QgsShortcutsManager::registerAllChildActions( QObject *object, bool recursive ) void QgsShortcutsManager::registerAllChildActions( QObject *object, bool recursive, const QString &section )
{ {
if ( recursive ) const QList<QObject *> children = object->children();
{
const QList< QAction * > actions = object->findChildren< QAction * >();
for ( QAction *a : actions )
{
registerAction( a, a->shortcut().toString( QKeySequence::NativeText ) );
}
}
else
{
const QList< QObject *> children = object->children();
for ( QObject *child : children ) for ( QObject *child : children )
{ {
if ( QAction *a = qobject_cast<QAction *>( child ) ) if ( QAction *a = qobject_cast< QAction * >( child ) )
{ {
registerAction( a, a->shortcut().toString( QKeySequence::NativeText ) ); registerAction( a, a->shortcut().toString( QKeySequence::NativeText ), section );
} }
else if ( recursive )
{
const QString newSection = child->objectName().isEmpty() ? section : section + child->objectName() + "/";
registerAllChildActions( child, recursive, newSection );
} }
} }
} }
void QgsShortcutsManager::registerAllChildShortcuts( QObject *object, bool recursive ) void QgsShortcutsManager::registerAllChildShortcuts( QObject *object, bool recursive, const QString &section )
{ {
if ( recursive ) const QList<QObject *> children = object->children();
for ( QObject *child : children )
{ {
const QList< QShortcut * > shortcuts = object->findChildren< QShortcut * >(); if ( QShortcut *s = qobject_cast< QShortcut * >( child ) )
const auto constShortcuts = shortcuts;
for ( QShortcut *s : constShortcuts )
{ {
registerShortcut( s, s->key().toString( QKeySequence::NativeText ) ); registerShortcut( s, s->key().toString( QKeySequence::NativeText ), section );
} }
} else if ( recursive )
else
{ {
const auto constChildren = object->children(); const QString newSection = child->objectName().isEmpty() ? section : section + child->objectName() + "/";
for ( QObject *child : constChildren ) registerAllChildShortcuts( child, recursive, newSection );
{
if ( QShortcut *s = qobject_cast<QShortcut *>( child ) )
{
registerShortcut( s, s->key().toString( QKeySequence::NativeText ) );
}
} }
} }
} }
bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaultSequence ) bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaultSequence, const QString &section )
{ {
if ( qobject_cast< QWidgetAction * >( action ) ) if ( qobject_cast<QWidgetAction *>( action ) )
return false; return false;
if ( mActions.contains( action ) ) if ( mActions.contains( action ) )
return false; // already registered return false; // already registered
#ifdef QGISDEBUG
// if using a debug build, warn on duplicate or non-compliant actions // if using a debug build, warn on duplicate or non-compliant actions
if ( action->text().isEmpty() ) if ( action->text().isEmpty() && action->objectName().isEmpty() )
{ {
#ifdef QGISDEBUG
QgsLogger::warning( QStringLiteral( "Action has no text set: %1" ).arg( action->objectName() ) ); QgsLogger::warning( QStringLiteral( "Action has no text set: %1" ).arg( action->objectName() ) );
#endif
return false; return false;
} }
else if ( actionByName( action->text() ) || shortcutByName( action->text() ) )
QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( action->text() ) ); QString key = action->objectName().isEmpty() ? action->text() : action->objectName();
key.remove( '&' ); // remove the accelerator
#ifdef QGISDEBUG
if ( actionByName( key ) || shortcutByName( key ) )
QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( key ) );
#endif #endif
mActions.insert( action, defaultSequence ); const QString settingKey = mSettingsPath + section + key;
connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } );
QString actionText = action->text(); mActions.insert( action, {defaultSequence, settingKey} );
actionText.remove( '&' ); // remove the accelerator connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } );
// load overridden value from settings // load overridden value from settings
const QgsSettings settings; const QgsSettings settings;
const QString sequence = settings.value( mSettingsPath + actionText, defaultSequence ).toString(); const QString sequence = settings.value( settingKey, defaultSequence ).toString();
action->setShortcut( sequence ); action->setShortcut( sequence );
if ( !action->toolTip().isEmpty() ) if ( !action->toolTip().isEmpty() )
@ -127,7 +119,7 @@ bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaul
return true; return true;
} }
bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &defaultSequence ) bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &defaultSequence, const QString &section )
{ {
#ifdef QGISDEBUG #ifdef QGISDEBUG
// if using a debug build, warn on duplicate or non-compliant actions // if using a debug build, warn on duplicate or non-compliant actions
@ -137,14 +129,14 @@ bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &
QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( shortcut->objectName() ) ); QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( shortcut->objectName() ) );
#endif #endif
mShortcuts.insert( shortcut, defaultSequence ); const QString settingKey = mSettingsPath + section + shortcut->objectName();
connect( shortcut, &QObject::destroyed, this, [shortcut, this]() { shortcutDestroyed( shortcut ); } );
const QString shortcutName = shortcut->objectName(); mShortcuts.insert( shortcut, {defaultSequence, settingKey} );
connect( shortcut, &QObject::destroyed, this, [shortcut, this]() { shortcutDestroyed( shortcut ); } );
// load overridden value from settings // load overridden value from settings
const QgsSettings settings; const QgsSettings settings;
const QString keySequence = settings.value( mSettingsPath + shortcutName, defaultSequence ).toString(); const QString keySequence = settings.value( settingKey, defaultSequence ).toString();
shortcut->setKey( keySequence ); shortcut->setKey( keySequence );
@ -181,7 +173,7 @@ QList<QShortcut *> QgsShortcutsManager::listShortcuts() const
QList<QObject *> QgsShortcutsManager::listAll() const QList<QObject *> QgsShortcutsManager::listAll() const
{ {
QList< QObject * > list; QList<QObject *> list;
ActionsHash::const_iterator actionIt = mActions.constBegin(); ActionsHash::const_iterator actionIt = mActions.constBegin();
for ( ; actionIt != mActions.constEnd(); ++actionIt ) for ( ; actionIt != mActions.constEnd(); ++actionIt )
{ {
@ -207,12 +199,12 @@ QString QgsShortcutsManager::objectDefaultKeySequence( QObject *object ) const
QString QgsShortcutsManager::defaultKeySequence( QAction *action ) const QString QgsShortcutsManager::defaultKeySequence( QAction *action ) const
{ {
return mActions.value( action, QString() ); return mActions.value( action ).first;
} }
QString QgsShortcutsManager::defaultKeySequence( QShortcut *shortcut ) const QString QgsShortcutsManager::defaultKeySequence( QShortcut *shortcut ) const
{ {
return mShortcuts.value( shortcut, QString() ); return mShortcuts.value( shortcut ).first;
} }
bool QgsShortcutsManager::setKeySequence( const QString &name, const QString &sequence ) bool QgsShortcutsManager::setKeySequence( const QString &name, const QString &sequence )
@ -237,27 +229,34 @@ bool QgsShortcutsManager::setObjectKeySequence( QObject *object, const QString &
bool QgsShortcutsManager::setKeySequence( QAction *action, const QString &sequence ) bool QgsShortcutsManager::setKeySequence( QAction *action, const QString &sequence )
{ {
if ( !mActions.contains( action ) )
{
return false;
}
action->setShortcut( sequence ); action->setShortcut( sequence );
this->updateActionToolTip( action, sequence ); this->updateActionToolTip( action, sequence );
QString actionText = action->text(); const QString settingKey = mActions[action].second;
actionText.remove( '&' ); // remove the accelerator
// save to settings // save to settings
QgsSettings settings; QgsSettings settings;
settings.setValue( mSettingsPath + actionText, sequence ); settings.setValue( settingKey, sequence );
return true; return true;
} }
bool QgsShortcutsManager::setKeySequence( QShortcut *shortcut, const QString &sequence ) bool QgsShortcutsManager::setKeySequence( QShortcut *shortcut, const QString &sequence )
{ {
if ( !mShortcuts.contains( shortcut ) )
{
return false;
}
shortcut->setKey( sequence ); shortcut->setKey( sequence );
const QString shortcutText = shortcut->objectName(); const QString settingKey = mShortcuts[shortcut].second;
// save to settings // save to settings
QgsSettings settings; QgsSettings settings;
settings.setValue( mSettingsPath + shortcutText, sequence ); settings.setValue( settingKey, sequence );
return true; return true;
} }
@ -303,7 +302,14 @@ QAction *QgsShortcutsManager::actionByName( const QString &name ) const
{ {
for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it ) for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
{ {
if ( it.key()->text() == name ) if ( it.key()->objectName() == name )
return it.key();
}
for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
{
QString key = it.key()->text();
key.remove( '&' ); // remove the accelerator
if ( key == name )
return it.key(); return it.key();
} }
@ -326,6 +332,34 @@ void QgsShortcutsManager::actionDestroyed( QAction *action )
mActions.remove( action ); mActions.remove( action );
} }
QString QgsShortcutsManager::objectSettingKey( QObject *object ) const
{
if ( auto action = qobject_cast< QAction * >( object ) )
{
return mActions.value( action ).second;
}
else if ( auto shortcut = qobject_cast< QShortcut * >( object ) )
{
return mShortcuts.value( shortcut ).second;
}
return QString();
}
QObject *QgsShortcutsManager::objectForSettingKey( const QString &settingKey ) const
{
for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
{
if ( it.value().second == settingKey )
return it.key();
}
for ( ShortcutsHash::const_iterator it = mShortcuts.constBegin(); it != mShortcuts.constEnd(); ++it )
{
if ( it.value().second == settingKey )
return it.key();
}
return nullptr;
}
void QgsShortcutsManager::shortcutDestroyed( QShortcut *shortcut ) void QgsShortcutsManager::shortcutDestroyed( QShortcut *shortcut )
{ {
mShortcuts.remove( shortcut ); mShortcuts.remove( shortcut );

View File

@ -54,53 +54,58 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
* passed object. * passed object.
* \param object parent object containing actions and shortcuts to register * \param object parent object containing actions and shortcuts to register
* \param recursive set to TRUE to recursively add child actions and shortcuts * \param recursive set to TRUE to recursively add child actions and shortcuts
* \param section Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
* \see registerAllChildActions() * \see registerAllChildActions()
* \see registerAllChildShortcuts() * \see registerAllChildShortcuts()
*/ */
void registerAllChildren( QObject *object, bool recursive = false ); void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
/** /**
* Automatically registers all QActions which are children of the passed object. * Automatically registers all QActions which are children of the passed object.
* \param object parent object containing actions to register * \param object parent object containing actions to register
* \param recursive set to TRUE to recursively add child actions * \param recursive set to TRUE to recursively add child actions
* \param section Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
* \see registerAction() * \see registerAction()
* \see registerAllChildren() * \see registerAllChildren()
* \see registerAllChildShortcuts() * \see registerAllChildShortcuts()
*/ */
void registerAllChildActions( QObject *object, bool recursive = false ); void registerAllChildActions( QObject *object, bool recursive = false, const QString &section = QString() );
/** /**
* Automatically registers all QShortcuts which are children of the passed object. * Automatically registers all QShortcuts which are children of the passed object.
* \param object parent object containing shortcuts to register * \param object parent object containing shortcuts to register
* \param recursive set to TRUE to recursively add child shortcuts * \param recursive set to TRUE to recursively add child shortcuts
* \param section Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
* \see registerShortcut() * \see registerShortcut()
* \see registerAllChildren() * \see registerAllChildren()
* \see registerAllChildActions() * \see registerAllChildActions()
*/ */
void registerAllChildShortcuts( QObject *object, bool recursive = false ); void registerAllChildShortcuts( QObject *object, bool recursive = false, const QString &section = QString() );
/** /**
* Registers an action with the manager so the shortcut can be configured in GUI. * Registers an action with the manager so the shortcut can be configured in GUI.
* \param action action to register. The action must have a unique text string for * \param action action to register. The action must have a unique text string for
* identification. * identification.
* \param defaultShortcut default key sequence for action * \param defaultShortcut default key sequence for action
* \param section Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
* \returns TRUE if action was successfully registered * \returns TRUE if action was successfully registered
* \see registerShortcut() * \see registerShortcut()
* \see unregisterAction() * \see unregisterAction()
* \see registerAllChildActions() * \see registerAllChildActions()
*/ */
bool registerAction( QAction *action, const QString &defaultShortcut = QString() ); bool registerAction( QAction *action, const QString &defaultShortcut = QString(), const QString &section = QString() );
/** /**
* Registers a QShortcut with the manager so the shortcut can be configured in GUI. * Registers a QShortcut with the manager so the shortcut can be configured in GUI.
* \param shortcut QShortcut to register. The shortcut must have a unique QObject::objectName() for * \param shortcut QShortcut to register. The shortcut must have a unique QObject::objectName() for
* identification. * identification.
* \param defaultSequence default key sequence for shortcut * \param defaultSequence default key sequence for shortcut
* \param section Allows disambiguating shortcuts with the same objectName (since QGIS 3.32)
* \returns TRUE if shortcut was successfully registered * \returns TRUE if shortcut was successfully registered
* \see registerAction() * \see registerAction()
* \see registerAllChildShortcuts() * \see registerAllChildShortcuts()
*/ */
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString() ); bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() );
/** /**
* Removes an action from the manager. * Removes an action from the manager.
@ -242,15 +247,30 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
//! Returns the root settings path used to store shortcut customization. //! Returns the root settings path used to store shortcut customization.
QString settingsPath() const { return mSettingsPath; } QString settingsPath() const { return mSettingsPath; }
/**
* Returns the full settings key matching the QShortcut or QAction
* Return an empty QString if the QObject is not registered
*
* \since QGIS 3.30
*/
QString objectSettingKey( QObject *object ) const;
/**
* Returns the QShortcut or QAction matching the the full setting key
* Return nullptr if the key was not found
*
* \since QGIS 3.30
*/
QObject *objectForSettingKey( const QString &name ) const;
private slots: private slots:
void actionDestroyed( QAction *action ); void actionDestroyed( QAction *action );
void shortcutDestroyed( QShortcut *shortcut ); void shortcutDestroyed( QShortcut *shortcut );
private: private:
typedef QHash<QAction *, QPair<QString, QString>> ActionsHash;
typedef QHash< QAction *, QString > ActionsHash; typedef QHash<QShortcut *, QPair<QString, QString>> ShortcutsHash;
typedef QHash< QShortcut *, QString > ShortcutsHash;
ActionsHash mActions; ActionsHash mActions;
ShortcutsHash mShortcuts; ShortcutsHash mShortcuts;