Compare commits

...

18 Commits

Author SHA1 Message Date
Patrice Pineault
bd2741269e
Merge 87b83d1b1b91a5ab257903c00f41909fc3764e64 into 82d7ab9b62f8c97d448ee0f7ef7ffe6ddcfbcc08 2025-10-01 14:05:21 +10:00
qgis-bot
82d7ab9b62 auto sipify 🍺 2025-10-01 03:49:17 +00:00
Nyall Dawson
8bc1f639bb Update tests 2025-10-01 13:46:41 +10:00
Nyall Dawson
928bdd8cc4 Fix tooltip formatting for console actions
The tooltip text should be in bold, not the shortcut
2025-10-01 13:46:41 +10:00
Nyall Dawson
1db5d1d246 Add common actions for run script, run selection
Allows these shortcuts to be customised
2025-10-01 13:46:41 +10:00
Nyall Dawson
1e3167082c Use correct shortcut in context menu for console script editor
And add reformat code action to menu
2025-10-01 13:46:41 +10:00
Nyall Dawson
c6accd8517 Fix more misleading names
These objects are actions, not buttons
2025-10-01 13:46:41 +10:00
Nyall Dawson
41962a0a24 Use correct user-set shortcuts for console script editor code actions
And rename member variable for correctness
2025-10-01 13:46:41 +10:00
Nyall Dawson
0fc8b37487 Set shortcut for script editor toggle comment action 2025-10-01 13:46:41 +10:00
Nyall Dawson
1c53ab415b Use registered shortcuts for code editor comment/reformat actions 2025-10-01 13:46:41 +10:00
Nyall Dawson
579a818ce7 Add sequenceForCommonAction 2025-10-01 13:46:41 +10:00
Nyall Dawson
5ed5f51121 [api] Add framework to handle common actions in shortcuts manager
Common actions allow for shortcuts to be registered for actions
which do not yet exist, or which are not associated with a single
global QAction object attached to at the application level. For
example, code editor actions which will be created as children
of individual code editor widgets, but which should have
shortcuts available for user configuration via the shortcuts
manager dialog.
2025-10-01 13:46:41 +10:00
Nyall Dawson
62fbbe6392 Refactor to extract utility function 2025-10-01 13:46:41 +10:00
Nyall Dawson
ac1260d159 Handle shortcut manager sections which don't have trailing "/" 2025-10-01 13:46:41 +10:00
Nyall Dawson
d9a4c80aa9 Rename method to more generic name 2025-10-01 13:46:41 +10:00
Nyall Dawson
d63653925c Fix 3d build 2025-10-01 10:54:09 +10:00
Patrice Pineault
87b83d1b1b fix possible null pointer dereference 2025-09-24 11:12:04 -04:00
Patrice Pineault
76a8cd6d84 mClassificationMethod->setLabelFormat, setLabelPrecision and setLabelTrimTrailingZeroes in QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl() 2025-09-24 10:08:10 -04:00
20 changed files with 684 additions and 329 deletions

View File

@ -262,7 +262,7 @@ if (WITH_3D)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/3d/project.py.in ${CMAKE_CURRENT_BINARY_DIR}/3d/project.py @ONLY)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/3d/pyproject.toml.temp" "${toml}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/3d/pyproject.toml.temp ${CMAKE_CURRENT_BINARY_DIR}/3d/pyproject.toml)
SET(SIP_CONCAT_PARTS 10) # 3D doesn't have enough .sip files to fill 15+ .cpp files
SET(SIP_CONCAT_PARTS 8) # 3D doesn't have enough .sip files to fill 15+ .cpp files
GENERATE_SIP_PYTHON_MODULE_CODE(qgis._3d_p 3d/3d.sip "${sip_files_3d}" cpp_files)
BUILD_SIP_PYTHON_MODULE(qgis._3d_p 3d/3d.sip ${cpp_files} "" qgis_core qgis_3d)
endif()

View File

@ -0,0 +1,18 @@
# The following has been generated automatically from src/gui/qgsshortcutsmanager.h
# monkey patching scoped based enum
QgsShortcutsManager.CommonAction.CodeToggleComment.__doc__ = "Toggle code comments"
QgsShortcutsManager.CommonAction.CodeReformat.__doc__ = "Reformat code"
QgsShortcutsManager.CommonAction.CodeRunScript.__doc__ = "Run script"
QgsShortcutsManager.CommonAction.CodeRunSelection.__doc__ = "Run selection from script"
QgsShortcutsManager.CommonAction.__doc__ = """Contains common actions which are used across a variety of classes.
.. versionadded:: 4.0
* ``CodeToggleComment``: Toggle code comments
* ``CodeReformat``: Reformat code
* ``CodeRunScript``: Run script
* ``CodeRunSelection``: Run selection from script
"""
# --
QgsShortcutsManager.CommonAction.baseClass = QgsShortcutsManager

View File

@ -23,6 +23,14 @@ rather accessed through :py:func:`QgsGui.shortcutsManager()`.
#include "qgsshortcutsmanager.h"
%End
public:
enum class CommonAction
{
CodeToggleComment,
CodeReformat,
CodeRunScript,
CodeRunSelection,
};
QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" );
%Docstring
Constructor for QgsShortcutsManager.
@ -36,6 +44,8 @@ Constructor for QgsShortcutsManager.
QGIS actions.
%End
~QgsShortcutsManager();
void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring
Automatically registers all QActions and QShortcuts which are children
@ -105,6 +115,16 @@ in GUI.
.. seealso:: :py:func:`unregisterAction`
.. seealso:: :py:func:`registerAllChildActions`
%End
void initializeCommonAction( QAction *action, CommonAction commonAction );
%Docstring
Initializes an ``action`` as a common action.
This automatically configures the ``action`` to use the properties for
the common action, such as setting the action's tooltip and shortcut.
.. versionadded:: 4.0
%End
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() );
@ -290,6 +310,14 @@ if no shortcut is associated.
.. seealso:: :py:func:`objectForSequence`
.. seealso:: :py:func:`actionForSequence`
%End
QKeySequence sequenceForCommonAction( CommonAction action ) const;
%Docstring
Returns the key sequence which is associated with a common ``action``,
or an empty sequence if no shortcut is assigned to that action.
.. versionadded:: 4.0
%End
QAction *actionByName( const QString &name ) const;

View File

@ -6977,28 +6977,30 @@ QgsShapeburstFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwid
QgsShapeburstFillSymbolLayerWidget.setSymbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L426
QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427
QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L236
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L163
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L171
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L155
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L262
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L254
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L94
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L70
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L81
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L59
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L106
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L204
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L243
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L116
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L126
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L267
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.initializeCommonAction: src/gui/qgsshortcutsmanager.h#L119
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L238
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L293
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L285
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L109
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L85
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L96
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L74
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L131
QgsShortcutsManager.sequenceForCommonAction: src/gui/qgsshortcutsmanager.h#L260
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L205
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L277
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L274
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L254
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L141
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L151
QgsShortcutsManager: src/gui/qgsshortcutsmanager.h#L36
QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264
QgsSimpleFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwidget.h#L271

View File

@ -19,5 +19,4 @@ __author__ = "Salvatore Larosa"
__date__ = "September 2012"
__copyright__ = "(C) 2012, Salvatore Larosa"
from .console import show_console # NOQA
from .console import init_options_widget
from .console import show_console, init_console # NOQA

View File

@ -61,6 +61,7 @@ from qgis.gui import (
QgsGui,
QgsApplicationExitBlockerInterface,
QgsCodeEditorDockWidget,
QgsShortcutsManager,
)
from functools import partial
@ -106,8 +107,11 @@ def console_displayhook(obj):
_console_output = obj
def init_options_widget():
"""called from QGIS to add the console options widget"""
def init_console():
"""
Called from QGIS to initialize the console related options and shortcuts,
before the dock is shown
"""
global _options_factory
_options_factory.setTitle(QCoreApplication.translate("PythonConsole", "Python"))
iface.registerOptionsWidgetFactory(_options_factory)
@ -221,169 +225,137 @@ class PythonConsoleWidget(QWidget):
# Action for Open File
openFileBt = QCoreApplication.translate("PythonConsole", "Open Script…")
self.openFileButton = QAction(self)
self.openFileButton.setCheckable(False)
self.openFileButton.setEnabled(True)
self.openFileButton.setIcon(
self.open_file_action = QAction(self)
self.open_file_action.setIcon(
QgsApplication.getThemeIcon("mActionScriptOpen.svg")
)
self.openFileButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.openFileButton.setIconVisibleInMenu(True)
self.openFileButton.setToolTip(openFileBt + " <b>Ctrl+O</b>")
self.openFileButton.setText(openFileBt)
self.open_file_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.open_file_action.setIconVisibleInMenu(True)
self.open_file_action.setToolTip(f"<b>{openFileBt}</b> (Ctrl+O)")
self.open_file_action.setText(openFileBt)
openExtEditorBt = QCoreApplication.translate(
"PythonConsole", "Open in External Editor"
)
self.openInEditorButton = QAction(self)
self.openInEditorButton.setCheckable(False)
self.openInEditorButton.setEnabled(True)
self.openInEditorButton.setIcon(
self.open_in_editor_action = QAction(self)
self.open_in_editor_action.setIcon(
QgsApplication.getThemeIcon("console/iconShowEditorConsole.svg")
)
self.openInEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.openInEditorButton.setIconVisibleInMenu(True)
self.openInEditorButton.setToolTip(openExtEditorBt)
self.openInEditorButton.setText(openExtEditorBt)
self.open_in_editor_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.open_in_editor_action.setIconVisibleInMenu(True)
self.open_in_editor_action.setToolTip(openExtEditorBt)
self.open_in_editor_action.setText(openExtEditorBt)
# Action for Save File
saveFileBt = QCoreApplication.translate("PythonConsole", "Save")
self.saveFileButton = QAction(self)
self.saveFileButton.setCheckable(False)
self.saveFileButton.setEnabled(False)
self.saveFileButton.setIcon(QgsApplication.getThemeIcon("mActionFileSave.svg"))
self.saveFileButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.saveFileButton.setIconVisibleInMenu(True)
self.saveFileButton.setToolTip(saveFileBt + " <b>Ctrl+S</b>")
self.saveFileButton.setText(saveFileBt)
self.save_file_action = QAction(self)
self.save_file_action.setEnabled(False)
self.save_file_action.setIcon(
QgsApplication.getThemeIcon("mActionFileSave.svg")
)
self.save_file_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.save_file_action.setIconVisibleInMenu(True)
self.save_file_action.setToolTip(f"<b>{saveFileBt}</b> (Ctrl+S)")
self.save_file_action.setText(saveFileBt)
# Action for Save File As
saveAsFileBt = QCoreApplication.translate("PythonConsole", "Save As…")
self.saveAsFileButton = QAction(self)
self.saveAsFileButton.setCheckable(False)
self.saveAsFileButton.setEnabled(True)
self.saveAsFileButton.setIcon(
self.save_as_file_action = QAction(self)
self.save_as_file_action.setIcon(
QgsApplication.getThemeIcon("mActionFileSaveAs.svg")
)
self.saveAsFileButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.saveAsFileButton.setIconVisibleInMenu(True)
self.saveAsFileButton.setToolTip(saveAsFileBt + " <b>Ctrl+Shift+S</b>")
self.saveAsFileButton.setText(saveAsFileBt)
self.save_as_file_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.save_as_file_action.setIconVisibleInMenu(True)
self.save_as_file_action.setToolTip(f"<b>{saveAsFileBt}</b> (Ctrl+Shift+S)")
self.save_as_file_action.setText(saveAsFileBt)
# Action Cut
cutEditorBt = QCoreApplication.translate("PythonConsole", "Cut")
self.cutEditorButton = QAction(self)
self.cutEditorButton.setCheckable(False)
self.cutEditorButton.setEnabled(True)
self.cutEditorButton.setIcon(QgsApplication.getThemeIcon("mActionEditCut.svg"))
self.cutEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.cutEditorButton.setIconVisibleInMenu(True)
self.cutEditorButton.setToolTip(cutEditorBt + " <b>Ctrl+X</b>")
self.cutEditorButton.setText(cutEditorBt)
self.cut_action = QAction(self)
self.cut_action.setIcon(QgsApplication.getThemeIcon("mActionEditCut.svg"))
self.cut_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.cut_action.setIconVisibleInMenu(True)
self.cut_action.setToolTip(f"<b>{cutEditorBt}</b> (Ctrl+X)")
self.cut_action.setText(cutEditorBt)
# Action Copy
copyEditorBt = QCoreApplication.translate("PythonConsole", "Copy")
self.copyEditorButton = QAction(self)
self.copyEditorButton.setCheckable(False)
self.copyEditorButton.setEnabled(True)
self.copyEditorButton.setIcon(
QgsApplication.getThemeIcon("mActionEditCopy.svg")
)
self.copyEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.copyEditorButton.setIconVisibleInMenu(True)
self.copyEditorButton.setToolTip(copyEditorBt + " <b>Ctrl+C</b>")
self.copyEditorButton.setText(copyEditorBt)
self.copy_action = QAction(self)
self.copy_action.setIcon(QgsApplication.getThemeIcon("mActionEditCopy.svg"))
self.copy_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.copy_action.setIconVisibleInMenu(True)
self.copy_action.setToolTip(f"<b>{copyEditorBt}</b> (Ctrl+C)")
self.copy_action.setText(copyEditorBt)
# Action Paste
pasteEditorBt = QCoreApplication.translate("PythonConsole", "Paste")
self.pasteEditorButton = QAction(self)
self.pasteEditorButton.setCheckable(False)
self.pasteEditorButton.setEnabled(True)
self.pasteEditorButton.setIcon(
QgsApplication.getThemeIcon("mActionEditPaste.svg")
)
self.pasteEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.pasteEditorButton.setIconVisibleInMenu(True)
self.pasteEditorButton.setToolTip(pasteEditorBt + " <b>Ctrl+V</b>")
self.pasteEditorButton.setText(pasteEditorBt)
self.paste_action = QAction(self)
self.paste_action.setIcon(QgsApplication.getThemeIcon("mActionEditPaste.svg"))
self.paste_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.paste_action.setIconVisibleInMenu(True)
self.paste_action.setToolTip(f"<b>{pasteEditorBt}</b> (Ctrl+V)")
self.paste_action.setText(pasteEditorBt)
# Action Run Script (subprocess)
runScriptEditorBt = QCoreApplication.translate("PythonConsole", "Run Script")
self.runScriptEditorButton = QAction(self)
self.runScriptEditorButton.setCheckable(False)
self.runScriptEditorButton.setEnabled(True)
self.runScriptEditorButton.setIcon(
QgsApplication.getThemeIcon("mActionStart.svg")
self.run_script_action = QAction(self)
self.run_script_action.setIcon(QgsApplication.getThemeIcon("mActionStart.svg"))
self.run_script_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.run_script_action.setIconVisibleInMenu(True)
QgsGui.shortcutsManager().initializeCommonAction(
self.run_script_action, QgsShortcutsManager.CommonAction.CodeRunScript
)
self.runScriptEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.runScriptEditorButton.setIconVisibleInMenu(True)
self.runScriptEditorButton.setToolTip(
runScriptEditorBt + " <b>Ctrl+Shift+E</b>"
)
self.runScriptEditorButton.setText(runScriptEditorBt)
# Action Run Selected
runSelectedEditorBt = QCoreApplication.translate(
"PythonConsole", "Run Selected"
)
self.runSelectedEditorButton = QAction(self)
self.runSelectedEditorButton.setCheckable(False)
self.runSelectedEditorButton.setEnabled(True)
self.runSelectedEditorButton.setIcon(
self.run_selection_action = QAction(self)
self.run_selection_action.setIcon(
QgsApplication.getThemeIcon("mActionRunSelected.svg")
)
self.runSelectedEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.runSelectedEditorButton.setIconVisibleInMenu(True)
self.runSelectedEditorButton.setToolTip(runSelectedEditorBt + " <b>Ctrl+E</b>")
self.runSelectedEditorButton.setShortcut("Ctrl+E")
self.runSelectedEditorButton.setText(runSelectedEditorBt)
self.run_selection_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.run_selection_action.setIconVisibleInMenu(True)
QgsGui.shortcutsManager().initializeCommonAction(
self.run_selection_action, QgsShortcutsManager.CommonAction.CodeRunSelection
)
# Action Toggle comment
toggleText = QCoreApplication.translate("PythonConsole", "Toggle Comment")
self.toggleCommentEditorButton = QAction(self)
self.toggleCommentEditorButton.setCheckable(False)
self.toggleCommentEditorButton.setEnabled(True)
self.toggleCommentEditorButton.setIcon(
self.toggle_comment_action = QAction(self)
self.toggle_comment_action.setIcon(
QgsApplication.getThemeIcon(
"console/iconCommentEditorConsole.svg",
self.palette().color(QPalette.ColorRole.WindowText),
),
)
self.toggleCommentEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.toggleCommentEditorButton.setIconVisibleInMenu(True)
self.toggleCommentEditorButton.setToolTip(toggleText + " <b>Ctrl+:</b>")
self.toggleCommentEditorButton.setText(toggleText)
self.toggle_comment_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.toggle_comment_action.setIconVisibleInMenu(True)
QgsGui.shortcutsManager().initializeCommonAction(
self.toggle_comment_action,
QgsShortcutsManager.CommonAction.CodeToggleComment,
)
# Action Format code
reformatCodeText = QCoreApplication.translate("PythonConsole", "Reformat Code")
self.reformatCodeEditorButton = QAction(self)
self.reformatCodeEditorButton.setCheckable(False)
self.reformatCodeEditorButton.setEnabled(True)
self.reformatCodeEditorButton.setIcon(
self.reformat_code_action = QAction(self)
self.reformat_code_action.setIcon(
QgsApplication.getThemeIcon("console/iconFormatCode.svg")
)
self.reformatCodeEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.reformatCodeEditorButton.setIconVisibleInMenu(True)
self.reformatCodeEditorButton.setToolTip(
reformatCodeText + " <b>Ctrl+Alt+F</b>"
self.reformat_code_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.reformat_code_action.setIconVisibleInMenu(True)
QgsGui.shortcutsManager().initializeCommonAction(
self.reformat_code_action, QgsShortcutsManager.CommonAction.CodeReformat
)
self.reformatCodeEditorButton.setShortcut("Ctrl+Alt+F")
self.reformatCodeEditorButton.setText(reformatCodeText)
# Action for Object browser
objList = QCoreApplication.translate("PythonConsole", "Object Inspector…")
self.objectListButton = QAction(self)
self.objectListButton.setCheckable(True)
self.objectListButton.setEnabled(
self.object_inspector_action = QAction(self)
self.object_inspector_action.setCheckable(True)
self.object_inspector_action.setEnabled(
QgsSettings().value("pythonConsole/enableObjectInsp", False, type=bool)
)
self.objectListButton.setIcon(
self.object_inspector_action.setIcon(
QgsApplication.getThemeIcon("console/iconClassBrowserConsole.svg")
)
self.objectListButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.objectListButton.setIconVisibleInMenu(True)
self.objectListButton.setToolTip(objList)
self.objectListButton.setText(objList)
self.object_inspector_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.object_inspector_action.setIconVisibleInMenu(True)
self.object_inspector_action.setToolTip(objList)
self.object_inspector_action.setText(objList)
# Action for Find text
findText = QCoreApplication.translate("PythonConsole", "Find Text")
@ -395,7 +367,7 @@ class PythonConsoleWidget(QWidget):
)
self.find_text_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.find_text_action.setIconVisibleInMenu(True)
self.find_text_action.setToolTip(findText + " <b>Ctrl+F</b>")
self.find_text_action.setToolTip(f"<b>{findText}</b> (Ctrl+F)")
self.find_text_action.setText(findText)
self.tabEditorWidget.search_bar_toggled.connect(
@ -407,75 +379,65 @@ class PythonConsoleWidget(QWidget):
# Action Show Editor
showEditor = QCoreApplication.translate("PythonConsole", "Show Editor")
self.showEditorButton = QAction(self)
self.showEditorButton.setEnabled(True)
self.showEditorButton.setCheckable(True)
self.showEditorButton.setIcon(
self.show_editor_action = QAction(self)
self.show_editor_action.setCheckable(True)
self.show_editor_action.setIcon(
QgsApplication.getThemeIcon("console/iconShowEditorConsole.svg")
)
self.showEditorButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.showEditorButton.setIconVisibleInMenu(True)
self.showEditorButton.setToolTip(showEditor)
self.showEditorButton.setText(showEditor)
self.show_editor_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.show_editor_action.setIconVisibleInMenu(True)
self.show_editor_action.setToolTip(showEditor)
self.show_editor_action.setText(showEditor)
# Action for Clear button
clearBt = QCoreApplication.translate("PythonConsole", "Clear Console")
self.clearButton = QAction(self)
self.clearButton.setCheckable(False)
self.clearButton.setEnabled(True)
self.clearButton.setIcon(
self.clear_action = QAction(self)
self.clear_action.setIcon(
QgsApplication.getThemeIcon("console/iconClearConsole.svg")
)
self.clearButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.clearButton.setIconVisibleInMenu(True)
self.clearButton.setToolTip(clearBt)
self.clearButton.setText(clearBt)
self.clear_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.clear_action.setIconVisibleInMenu(True)
self.clear_action.setToolTip(clearBt)
self.clear_action.setText(clearBt)
# Action for settings
optionsBt = QCoreApplication.translate("PythonConsole", "Options…")
self.optionsButton = QAction(self)
self.optionsButton.setCheckable(False)
self.optionsButton.setEnabled(True)
self.optionsButton.setIcon(
self.options_action = QAction(self)
self.options_action.setIcon(
QgsApplication.getThemeIcon("console/iconSettingsConsole.svg")
)
self.optionsButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.optionsButton.setIconVisibleInMenu(True)
self.optionsButton.setToolTip(optionsBt)
self.optionsButton.setText(optionsBt)
self.options_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.options_action.setIconVisibleInMenu(True)
self.options_action.setToolTip(optionsBt)
self.options_action.setText(optionsBt)
# Action for Run script
runBt = QCoreApplication.translate("PythonConsole", "Run Command")
self.runButton = QAction(self)
self.runButton.setCheckable(False)
self.runButton.setEnabled(True)
self.runButton.setIcon(QgsApplication.getThemeIcon("mActionStart.svg"))
self.runButton.setMenuRole(QAction.MenuRole.PreferencesRole)
self.runButton.setIconVisibleInMenu(True)
self.runButton.setToolTip(runBt)
self.runButton.setText(runBt)
self.run_action = QAction(self)
self.run_action.setIcon(QgsApplication.getThemeIcon("mActionStart.svg"))
self.run_action.setMenuRole(QAction.MenuRole.PreferencesRole)
self.run_action.setIconVisibleInMenu(True)
self.run_action.setToolTip(runBt)
self.run_action.setText(runBt)
# Help button
self.helpConsoleAction = QAction(self)
self.helpConsoleAction.setEnabled(True)
self.helpConsoleAction.setText(
self.help_console_action = QAction(self)
self.help_console_action.setText(
QCoreApplication.translate("PythonConsole", "Python Console Help")
)
self.helpAPIAction = QAction(self)
self.helpAPIAction.setEnabled(True)
self.helpAPIAction.setText(
self.help_api_action = QAction(self)
self.help_api_action.setText(
QCoreApplication.translate("PythonConsole", "PyQGIS API Documentation")
)
self.helpCookbookAction = QAction(self)
self.helpCookbookAction.setEnabled(True)
self.helpCookbookAction.setText(
self.help_cookbook_action = QAction(self)
self.help_cookbook_action.setText(
QCoreApplication.translate("PythonConsole", "PyQGIS Cookbook")
)
self.helpMenu = QMenu(self)
self.helpMenu.addAction(self.helpConsoleAction)
self.helpMenu.addAction(self.helpAPIAction)
self.helpMenu.addAction(self.helpCookbookAction)
self.helpMenu.addAction(self.help_console_action)
self.helpMenu.addAction(self.help_api_action)
self.helpMenu.addAction(self.help_cookbook_action)
helpBt = QCoreApplication.translate("PythonConsole", "Help…")
self.helpButton = QToolButton(self)
@ -495,12 +457,12 @@ class PythonConsoleWidget(QWidget):
self.toolBar.setIconSize(icon_size)
self.toolBar.setMovable(False)
self.toolBar.setFloatable(False)
self.toolBar.addAction(self.clearButton)
self.toolBar.addAction(self.runButton)
self.toolBar.addAction(self.clear_action)
self.toolBar.addAction(self.run_action)
self.toolBar.addSeparator()
self.toolBar.addAction(self.showEditorButton)
self.toolBar.addAction(self.show_editor_action)
self.toolBar.addSeparator()
self.toolBar.addAction(self.optionsButton)
self.toolBar.addAction(self.options_action)
self.toolBar.addWidget(self.helpButton)
self.toolBar.addSeparator()
self.toolBar.addWidget(parent.dockToggleButton())
@ -513,25 +475,25 @@ class PythonConsoleWidget(QWidget):
self.toolBarEditor.setIconSize(icon_size)
self.toolBarEditor.setMovable(False)
self.toolBarEditor.setFloatable(False)
self.toolBarEditor.addAction(self.openFileButton)
self.toolBarEditor.addAction(self.openInEditorButton)
self.toolBarEditor.addAction(self.open_file_action)
self.toolBarEditor.addAction(self.open_in_editor_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.saveFileButton)
self.toolBarEditor.addAction(self.saveAsFileButton)
self.toolBarEditor.addAction(self.save_file_action)
self.toolBarEditor.addAction(self.save_as_file_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.runScriptEditorButton)
self.toolBarEditor.addAction(self.runSelectedEditorButton)
self.toolBarEditor.addAction(self.run_script_action)
self.toolBarEditor.addAction(self.run_selection_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.cutEditorButton)
self.toolBarEditor.addAction(self.copyEditorButton)
self.toolBarEditor.addAction(self.pasteEditorButton)
self.toolBarEditor.addAction(self.cut_action)
self.toolBarEditor.addAction(self.copy_action)
self.toolBarEditor.addAction(self.paste_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.find_text_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.toggleCommentEditorButton)
self.toolBarEditor.addAction(self.reformatCodeEditorButton)
self.toolBarEditor.addAction(self.toggle_comment_action)
self.toolBarEditor.addAction(self.reformat_code_action)
self.toolBarEditor.addSeparator()
self.toolBarEditor.addAction(self.objectListButton)
self.toolBarEditor.addAction(self.object_inspector_action)
self.widgetButton = QWidget()
sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred)
@ -585,25 +547,25 @@ class PythonConsoleWidget(QWidget):
# ------------ Signal -------------------------------
self.objectListButton.toggled.connect(self.toggleObjectListWidget)
self.toggleCommentEditorButton.triggered.connect(self.toggleComment)
self.reformatCodeEditorButton.triggered.connect(self.reformatCode)
self.runScriptEditorButton.triggered.connect(self.runScriptEditor)
self.runSelectedEditorButton.triggered.connect(self.runSelectedEditor)
self.cutEditorButton.triggered.connect(self.cutEditor)
self.copyEditorButton.triggered.connect(self.copyEditor)
self.pasteEditorButton.triggered.connect(self.pasteEditor)
self.showEditorButton.toggled.connect(self.toggleEditor)
self.clearButton.triggered.connect(self.shell_output.clearConsole)
self.optionsButton.triggered.connect(self.openSettings)
self.runButton.triggered.connect(self.shell.entered)
self.openFileButton.triggered.connect(self.openScriptFile)
self.openInEditorButton.triggered.connect(self.openScriptFileExtEditor)
self.saveFileButton.triggered.connect(self.saveScriptFile)
self.saveAsFileButton.triggered.connect(self.saveAsScriptFile)
self.helpConsoleAction.triggered.connect(self.openHelpConsole)
self.helpAPIAction.triggered.connect(self.openHelpAPI)
self.helpCookbookAction.triggered.connect(self.openHelpCookbook)
self.object_inspector_action.toggled.connect(self.toggleObjectListWidget)
self.toggle_comment_action.triggered.connect(self.toggleComment)
self.reformat_code_action.triggered.connect(self.reformatCode)
self.run_script_action.triggered.connect(self.runScriptEditor)
self.run_selection_action.triggered.connect(self.runSelectedEditor)
self.cut_action.triggered.connect(self.cutEditor)
self.copy_action.triggered.connect(self.copyEditor)
self.paste_action.triggered.connect(self.pasteEditor)
self.show_editor_action.toggled.connect(self.toggleEditor)
self.clear_action.triggered.connect(self.shell_output.clearConsole)
self.options_action.triggered.connect(self.openSettings)
self.run_action.triggered.connect(self.shell.entered)
self.open_file_action.triggered.connect(self.openScriptFile)
self.open_in_editor_action.triggered.connect(self.openScriptFileExtEditor)
self.save_file_action.triggered.connect(self.saveScriptFile)
self.save_as_file_action.triggered.connect(self.saveAsScriptFile)
self.help_console_action.triggered.connect(self.openHelpConsole)
self.help_api_action.triggered.connect(self.openHelpAPI)
self.help_cookbook_action.triggered.connect(self.openHelpCookbook)
self.listClassMethod.itemClicked.connect(self.onClickGoToLine)
if iface is not None:

View File

@ -33,7 +33,13 @@ from operator import itemgetter
from pathlib import Path
from qgis.core import Qgis, QgsApplication, QgsBlockingNetworkRequest, QgsSettings
from qgis.gui import QgsCodeEditorPython, QgsCodeEditorWidget, QgsMessageBar
from qgis.gui import (
QgsCodeEditorPython,
QgsCodeEditorWidget,
QgsGui,
QgsMessageBar,
QgsShortcutsManager,
)
from qgis.PyQt.Qsci import QsciScintilla
from qgis.PyQt.QtCore import (
@ -159,15 +165,6 @@ class Editor(QgsCodeEditorPython):
syntaxCheckAction.setShortcut("Ctrl+4")
menu.addAction(syntaxCheckAction)
runSelected = QAction(
QgsApplication.getThemeIcon("mActionRunSelected.svg"), # spellok
QCoreApplication.translate("PythonConsole", "Run Selected"),
menu,
)
runSelected.triggered.connect(self.runSelectedCode) # spellok
runSelected.setShortcut("Ctrl+E") # spellok
menu.addAction(runSelected) # spellok
word = self.selectedText() or self.wordAtPoint(e.pos())
if word:
context_help_action = QAction(
@ -185,13 +182,24 @@ class Editor(QgsCodeEditorPython):
context_help_action.setShortcut(QKeySequence.StandardKey.HelpContents)
menu.addAction(context_help_action)
start_action = QAction(
QgsApplication.getThemeIcon("mActionStart.svg"),
QCoreApplication.translate("PythonConsole", "Run Script"),
menu,
run_selection_action = QAction(menu)
run_selection_action.setIcon(
QgsApplication.getThemeIcon("mActionRunSelected.svg"),
)
run_selection_action.triggered.connect(self.runSelectedCode)
QgsGui.shortcutsManager().initializeCommonAction(
run_selection_action,
QgsShortcutsManager.CommonAction.CodeRunSelection,
)
menu.addAction(run_selection_action)
start_action = QAction(self)
start_action.setIcon(QgsApplication.getThemeIcon("mActionStart.svg"))
start_action.triggered.connect(self.runScriptCode)
start_action.setShortcut("Ctrl+Shift+E")
QgsGui.shortcutsManager().initializeCommonAction(
start_action,
QgsShortcutsManager.CommonAction.CodeRunScript,
)
menu.addAction(start_action)
menu.addSeparator()
@ -258,18 +266,31 @@ class Editor(QgsCodeEditorPython):
menu.addAction(selectAllAction)
menu.addSeparator()
toggle_comment_action = QAction(
toggle_comment_action = QAction(menu)
toggle_comment_action.setIcon(
QgsApplication.getThemeIcon(
"console/iconCommentEditorConsole.svg",
self.palette().color(QPalette.ColorRole.WindowText),
),
QCoreApplication.translate("PythonConsole", "Toggle Comment"),
menu,
)
)
toggle_comment_action.triggered.connect(self.toggleComment)
toggle_comment_action.setShortcut("Ctrl+:")
QgsGui.shortcutsManager().initializeCommonAction(
toggle_comment_action,
QgsShortcutsManager.CommonAction.CodeToggleComment,
)
menu.addAction(toggle_comment_action)
reformat_code_action = QAction(menu)
reformat_code_action.setIcon(
QgsApplication.getThemeIcon("console/iconFormatCode.svg")
)
reformat_code_action.triggered.connect(self.reformatCode)
QgsGui.shortcutsManager().initializeCommonAction(
reformat_code_action,
QgsShortcutsManager.CommonAction.CodeReformat,
)
menu.addAction(reformat_code_action)
menu.addSeparator()
gist_menu = QMenu(self)
gist_menu.setTitle(
@ -299,14 +320,14 @@ class Editor(QgsCodeEditorPython):
syntaxCheckAction.setEnabled(False)
pasteAction.setEnabled(False)
cutAction.setEnabled(False)
runSelected.setEnabled(False) # spellok
run_selection_action.setEnabled(False)
copyAction.setEnabled(False)
selectAllAction.setEnabled(False)
undoAction.setEnabled(False)
redoAction.setEnabled(False)
showCodeInspection.setEnabled(False)
if self.hasSelectedText():
runSelected.setEnabled(True) # spellok
run_selection_action.setEnabled(True)
copyAction.setEnabled(True)
cutAction.setEnabled(True)
if not self.text() == "":
@ -326,17 +347,17 @@ class Editor(QgsCodeEditorPython):
listObj = self.console_widget.listClassMethod
if listObj.isVisible():
listObj.hide()
self.console_widget.objectListButton.setChecked(False)
self.console_widget.object_inspector_action.setChecked(False)
else:
listObj.show()
self.console_widget.objectListButton.setChecked(True)
self.console_widget.object_inspector_action.setChecked(True)
def shareOnGist(self, is_public):
self.code_editor_widget.shareOnGist(is_public)
def hideEditor(self):
self.console_widget.splitterObj.hide()
self.console_widget.showEditorButton.setChecked(False)
self.console_widget.show_editor_action.setChecked(False)
def createTempFile(self):
name = tempfile.NamedTemporaryFile(delete=False).name
@ -475,7 +496,7 @@ class Editor(QgsCodeEditorPython):
)
self.tab_widget.setTabToolTip(index, self.code_editor_widget.filePath())
self.setModified(False)
self.console_widget.saveFileButton.setEnabled(False)
self.console_widget.save_file_action.setEnabled(False)
self.console_widget.updateTabListScript(
self.code_editor_widget.filePath(), action="append"
)
@ -720,7 +741,7 @@ class EditorTabWidget(QTabWidget):
# New Editor button
self.newTabButton = QToolButton()
txtToolTipNewTab = QCoreApplication.translate("PythonConsole", "New Editor")
self.newTabButton.setToolTip(txtToolTipNewTab + " <b>Ctrl+T</b>")
self.newTabButton.setToolTip(f"<b>{txtToolTipNewTab}</b> (Ctrl+T)")
self.newTabButton.setAutoRaise(True)
self.newTabButton.setIcon(
QgsApplication.getThemeIcon("console/iconNewTabEditorConsole.svg")
@ -810,7 +831,7 @@ class EditorTabWidget(QTabWidget):
def enableSaveIfModified(self, tab):
tabWidget = self.widget(tab)
if tabWidget:
self.console_widget.saveFileButton.setEnabled(tabWidget.isModified())
self.console_widget.save_file_action.setEnabled(tabWidget.isModified())
def enableToolBarEditor(self, enable):
if self.topFrame.isVisible():
@ -864,7 +885,7 @@ class EditorTabWidget(QTabWidget):
index = self.indexOf(tab)
s = self.tabText(index)
self.setTabTitle(index, f"*{s}" if modified else re.sub(r"^(\*)", "", s))
self.console_widget.saveFileButton.setEnabled(modified)
self.console_widget.save_file_action.setEnabled(modified)
def setTabTitle(self, tab, title):
self.setTabText(tab, title)
@ -1071,10 +1092,9 @@ class EditorTabWidget(QTabWidget):
objInspectorEnabled = QgsSettings().value(
"pythonConsole/enableObjectInsp", False, type=bool
)
listObj = self.console_widget.objectListButton
if self.console_widget.listClassMethod.isVisible():
listObj.setChecked(objInspectorEnabled)
listObj.setEnabled(objInspectorEnabled)
self.console_widget.object_inspector_action.setChecked(objInspectorEnabled)
self.console_widget.object_inspector_action.setEnabled(objInspectorEnabled)
if objInspectorEnabled:
cW = self.currentWidget()
if cW and not self.console_widget.listClassMethod.isVisible():

View File

@ -348,7 +348,7 @@ class ShellOutputScintilla(QgsCodeEditorPython):
Ed = self.console_widget.splitterObj
if not Ed.isVisible():
Ed.show()
self.console_widget.showEditorButton.setChecked(True)
self.console_widget.show_editor_action.setChecked(True)
self.shell_editor.setFocus()
def copy(self):

View File

@ -0,0 +1,18 @@
# The following has been generated automatically from src/gui/qgsshortcutsmanager.h
# monkey patching scoped based enum
QgsShortcutsManager.CommonAction.CodeToggleComment.__doc__ = "Toggle code comments"
QgsShortcutsManager.CommonAction.CodeReformat.__doc__ = "Reformat code"
QgsShortcutsManager.CommonAction.CodeRunScript.__doc__ = "Run script"
QgsShortcutsManager.CommonAction.CodeRunSelection.__doc__ = "Run selection from script"
QgsShortcutsManager.CommonAction.__doc__ = """Contains common actions which are used across a variety of classes.
.. versionadded:: 4.0
* ``CodeToggleComment``: Toggle code comments
* ``CodeReformat``: Reformat code
* ``CodeRunScript``: Run script
* ``CodeRunSelection``: Run selection from script
"""
# --
QgsShortcutsManager.CommonAction.baseClass = QgsShortcutsManager

View File

@ -23,6 +23,14 @@ rather accessed through :py:func:`QgsGui.shortcutsManager()`.
#include "qgsshortcutsmanager.h"
%End
public:
enum class CommonAction
{
CodeToggleComment,
CodeReformat,
CodeRunScript,
CodeRunSelection,
};
QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" );
%Docstring
Constructor for QgsShortcutsManager.
@ -36,6 +44,8 @@ Constructor for QgsShortcutsManager.
QGIS actions.
%End
~QgsShortcutsManager();
void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring
Automatically registers all QActions and QShortcuts which are children
@ -105,6 +115,16 @@ in GUI.
.. seealso:: :py:func:`unregisterAction`
.. seealso:: :py:func:`registerAllChildActions`
%End
void initializeCommonAction( QAction *action, CommonAction commonAction );
%Docstring
Initializes an ``action`` as a common action.
This automatically configures the ``action`` to use the properties for
the common action, such as setting the action's tooltip and shortcut.
.. versionadded:: 4.0
%End
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() );
@ -290,6 +310,14 @@ if no shortcut is associated.
.. seealso:: :py:func:`objectForSequence`
.. seealso:: :py:func:`actionForSequence`
%End
QKeySequence sequenceForCommonAction( CommonAction action ) const;
%Docstring
Returns the key sequence which is associated with a common ``action``,
or an empty sequence if no shortcut is assigned to that action.
.. versionadded:: 4.0
%End
QAction *actionByName( const QString &name ) const;

View File

@ -6977,28 +6977,30 @@ QgsShapeburstFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwid
QgsShapeburstFillSymbolLayerWidget.setSymbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L426
QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427
QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L236
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L163
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L171
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L155
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L262
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L254
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L94
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L70
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L81
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L59
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L106
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L204
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L243
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L116
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L126
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L267
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.initializeCommonAction: src/gui/qgsshortcutsmanager.h#L119
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L238
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L293
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L285
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L109
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L85
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L96
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L74
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L131
QgsShortcutsManager.sequenceForCommonAction: src/gui/qgsshortcutsmanager.h#L260
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L205
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L277
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L274
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L254
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L141
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L151
QgsShortcutsManager: src/gui/qgsshortcutsmanager.h#L36
QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264
QgsSimpleFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwidget.h#L271

View File

@ -30,7 +30,7 @@ from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QPalette
from qgis.PyQt.QtWidgets import QMessageBox, QFileDialog, QVBoxLayout
from qgis.gui import QgsGui, QgsErrorDialog, QgsCodeEditorWidget
from qgis.gui import QgsGui, QgsErrorDialog, QgsCodeEditorWidget, QgsShortcutsManager
from qgis.core import (
QgsApplication,
QgsFileUtils,
@ -122,6 +122,9 @@ class ScriptEditorDialog(BASE, WIDGET):
self.palette().color(QPalette.ColorRole.WindowText),
)
)
QgsGui.shortcutsManager().initializeCommonAction(
self.actionToggleComment, QgsShortcutsManager.CommonAction.CodeToggleComment
)
# Connect signals and slots
self.actionOpenScript.triggered.connect(self.openScript)

View File

@ -3247,7 +3247,7 @@ void QgisApp::showStyleManager()
void QgisApp::initPythonConsoleOptions()
{
QgsPythonRunner::run( QStringLiteral( "import console" ) );
QgsPythonRunner::run( QStringLiteral( "console.init_options_widget()" ) );
QgsPythonRunner::run( QStringLiteral( "console.init_console()" ) );
}
void QgisApp::showPythonDialog()

View File

@ -25,6 +25,7 @@
#include "qgsstringutils.h"
#include "qgsfontutils.h"
#include "qgssettingsentryimpl.h"
#include "qgsshortcutsmanager.h"
#include <QLabel>
#include <QWidget>
@ -252,25 +253,30 @@ void QgsCodeEditor::keyPressEvent( QKeyEvent *event )
}
}
const bool ctrlModifier = event->modifiers() & Qt::ControlModifier;
const bool altModifier = event->modifiers() & Qt::AltModifier;
// Ctrl+Alt+F: reformat code
// check for reformat code sequence
const bool canReformat = languageCapabilities() & Qgis::ScriptLanguageCapability::Reformat;
if ( !isReadOnly() && canReformat && ctrlModifier && altModifier && event->key() == Qt::Key_F )
if ( !isReadOnly() && canReformat )
{
event->accept();
reformatCode();
return;
const QKeySequence reformatCodeSequence = QgsGui::shortcutsManager()->sequenceForCommonAction( QgsShortcutsManager::CommonAction::CodeReformat );
if ( !reformatCodeSequence.isEmpty() && reformatCodeSequence.matches( event->key() | event->modifiers() ) )
{
event->accept();
reformatCode();
return;
}
}
// Toggle comment when user presses Ctrl+:
// Check for toggle comment sequence
const bool canToggle = languageCapabilities() & Qgis::ScriptLanguageCapability::ToggleComment;
if ( !isReadOnly() && canToggle && ctrlModifier && event->key() == Qt::Key_Colon )
if ( !isReadOnly() && canToggle )
{
event->accept();
toggleComment();
return;
const QKeySequence toggleCommentCodeSequence = QgsGui::shortcutsManager()->sequenceForCommonAction( QgsShortcutsManager::CommonAction::CodeToggleComment );
if ( !toggleCommentCodeSequence.isEmpty() && toggleCommentCodeSequence.matches( event->key() | event->modifiers() ) )
{
event->accept();
toggleComment();
return;
}
}
QsciScintilla::keyPressEvent( event );
@ -299,7 +305,7 @@ void QgsCodeEditor::contextMenuEvent( QContextMenuEvent *event )
if ( languageCapabilities() & Qgis::ScriptLanguageCapability::Reformat )
{
QAction *reformatAction = new QAction( tr( "Reformat Code" ), menu );
reformatAction->setShortcut( QStringLiteral( "Ctrl+Alt+F" ) );
reformatAction->setShortcut( QgsGui::shortcutsManager()->sequenceForCommonAction( QgsShortcutsManager::CommonAction::CodeReformat ) );
reformatAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconFormatCode.svg" ) ) );
reformatAction->setEnabled( !isReadOnly() );
connect( reformatAction, &QAction::triggered, this, &QgsCodeEditor::reformatCode );
@ -317,7 +323,7 @@ void QgsCodeEditor::contextMenuEvent( QContextMenuEvent *event )
if ( languageCapabilities() & Qgis::ScriptLanguageCapability::ToggleComment )
{
QAction *toggleCommentAction = new QAction( tr( "Toggle Comment" ), menu );
toggleCommentAction->setShortcut( QStringLiteral( "Ctrl+:" ) );
toggleCommentAction->setShortcut( QgsGui::shortcutsManager()->sequenceForCommonAction( QgsShortcutsManager::CommonAction::CodeToggleComment ) );
toggleCommentAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconCommentEditorConsole.svg" ), palette().color( QPalette::ColorRole::WindowText ) ) );
toggleCommentAction->setEnabled( !isReadOnly() );
connect( toggleCommentAction, &QAction::triggered, this, &QgsCodeEditor::toggleComment );

View File

@ -17,6 +17,7 @@
#include "moc_qgsshortcutsmanager.cpp"
#include "qgslogger.h"
#include "qgssettings.h"
#include "qgsapplication.h"
#include <QShortcut>
#include <QRegularExpression>
@ -26,6 +27,33 @@ QgsShortcutsManager::QgsShortcutsManager( QObject *parent, const QString &settin
: QObject( parent )
, mSettingsPath( settingsRoot )
{
// Register common actions
auto registerCommonAction = [this]( CommonAction commonAction, const QIcon &icon, const QString &text, const QString &toolTip, const QString &sequence, const QString &objectName, const QString &section ) {
QAction *action = new QAction( icon, text, this );
action->setToolTip( toolTip );
setObjectName( objectName );
// We do not want these actions to be enabled, they are just there to be able to change
// the shortcuts in the Shortcuts Manager.
action->setEnabled( false );
action->setProperty( "commonAction", static_cast< int >( commonAction ) );
registerAction( action, sequence, section );
mCommonActions.insert( static_cast< int >( commonAction ), action );
};
registerCommonAction( CommonAction::CodeToggleComment, QgsApplication::getThemeIcon( QStringLiteral( "console/iconCommentEditorConsole.svg" ), QgsApplication::palette().color( QPalette::ColorRole::WindowText ) ), tr( "Toggle Comment" ), tr( "Toggle comment" ), QStringLiteral( "Ctrl+/" ), QStringLiteral( "mEditorToggleComment" ), QStringLiteral( "Editor" ) );
registerCommonAction( CommonAction::CodeReformat, QgsApplication::getThemeIcon( QStringLiteral( "console/iconFormatCode.svg" ) ), tr( "Reformat Code" ), tr( "Reformat code" ), QStringLiteral( "Ctrl+Alt+F" ), QStringLiteral( "mEditorReformatCode" ), QStringLiteral( "Editor" ) );
registerCommonAction( CommonAction::CodeRunScript, QgsApplication::getThemeIcon( QStringLiteral( "mActionStart.svg" ) ), tr( "Run Script" ), tr( "Run entire script" ), QStringLiteral( "Ctrl+Shift+E" ), QStringLiteral( "mEditorRunScript" ), QStringLiteral( "Editor" ) );
registerCommonAction( CommonAction::CodeRunSelection, QgsApplication::getThemeIcon( QStringLiteral( "mActionRunSelected.svg" ) ), tr( "Run Selection" ), tr( "Run selected part of script" ), QStringLiteral( "Ctrl+E" ), QStringLiteral( "mEditorRunSelection" ), QStringLiteral( "Editor" ) );
}
QgsShortcutsManager::~QgsShortcutsManager()
{
// delete all common actions BEFORE this object is destroyed -- they have a lambda connection which
// we do NOT want to be triggered during the qt child object cleanup which will occur after this destructor
const QHash< int, QAction * > commonActionsToCleanup = std::move( mCommonActions );
for ( auto it = commonActionsToCleanup.constBegin(); it != commonActionsToCleanup.constEnd(); ++it )
{
delete it.value();
}
}
void QgsShortcutsManager::registerAllChildren( QObject *object, bool recursive, const QString &section )
@ -93,7 +121,7 @@ bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaul
QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( key ) );
#endif
const QString settingKey = mSettingsPath + section + key;
const QString settingKey = mSettingsPath + ( section.isEmpty() || section.endsWith( QStringLiteral( "/" ) ) ? section : section + QStringLiteral( "/" ) ) + key;
mActions.insert( action, { defaultSequence, settingKey } );
connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } );
@ -105,21 +133,28 @@ bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaul
action->setShortcut( sequence );
if ( !action->toolTip().isEmpty() )
{
const QStringList parts = action->toolTip().split( '\n' );
QString formatted = QStringLiteral( "<b>%1</b>" ).arg( parts.at( 0 ) );
if ( parts.count() > 1 )
{
for ( int i = 1; i < parts.count(); ++i )
formatted += QStringLiteral( "<p>%1</p>" ).arg( parts.at( i ) );
}
action->setToolTip( formatted );
action->setToolTip( formatActionToolTip( action->toolTip() ) );
updateActionToolTip( action, sequence );
}
return true;
}
void QgsShortcutsManager::initializeCommonAction( QAction *action, CommonAction commonAction )
{
const auto it = mCommonActions.constFind( static_cast< int >( commonAction ) );
if ( it == mCommonActions.constEnd() )
return;
// copy properties from common action
action->setText( it.value()->text() );
action->setToolTip( it.value()->toolTip() );
action->setShortcut( it.value()->shortcut() );
mLinkedCommonActions.insert( action, commonAction );
connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } );
}
bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &defaultSequence, const QString &section )
{
#ifdef QGISDEBUG
@ -130,7 +165,7 @@ bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &
QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( shortcut->objectName() ) );
#endif
const QString settingKey = mSettingsPath + section + shortcut->objectName();
const QString settingKey = mSettingsPath + ( section.isEmpty() || section.endsWith( QStringLiteral( "/" ) ) ? section : section + QStringLiteral( "/" ) ) + shortcut->objectName();
mShortcuts.insert( shortcut, { defaultSequence, settingKey } );
connect( shortcut, &QObject::destroyed, this, [shortcut, this]() { shortcutDestroyed( shortcut ); } );
@ -237,6 +272,21 @@ bool QgsShortcutsManager::setKeySequence( QAction *action, const QString &sequen
action->setShortcut( sequence );
this->updateActionToolTip( action, sequence );
if ( action->property( "commonAction" ).isValid() )
{
// if the key sequence for a common action is changed, update all QActions currently linked
// to that common action
const CommonAction commonAction = static_cast< CommonAction >( action->property( "commonAction" ).toInt() );
for ( auto it = mLinkedCommonActions.constBegin(); it != mLinkedCommonActions.constEnd(); ++it )
{
if ( it.value() == commonAction )
{
it.key()->setShortcut( action->shortcut() );
it.key()->setToolTip( action->toolTip() );
}
}
}
const QString settingKey = mActions[action].second;
// save to settings
@ -299,6 +349,15 @@ QShortcut *QgsShortcutsManager::shortcutForSequence( const QKeySequence &sequenc
return nullptr;
}
QKeySequence QgsShortcutsManager::sequenceForCommonAction( CommonAction action ) const
{
const auto it = mCommonActions.constFind( static_cast< int >( action ) );
if ( it == mCommonActions.constEnd() )
return QKeySequence();
return it.value()->shortcut();
}
QAction *QgsShortcutsManager::actionByName( const QString &name ) const
{
for ( ActionsHash::const_iterator it = mActions.constBegin(); it != mActions.constEnd(); ++it )
@ -331,6 +390,7 @@ QShortcut *QgsShortcutsManager::shortcutByName( const QString &name ) const
void QgsShortcutsManager::actionDestroyed( QAction *action )
{
mActions.remove( action );
mLinkedCommonActions.remove( action );
}
QString QgsShortcutsManager::objectSettingKey( QObject *object ) const
@ -366,10 +426,26 @@ void QgsShortcutsManager::shortcutDestroyed( QShortcut *shortcut )
mShortcuts.remove( shortcut );
}
QString QgsShortcutsManager::formatActionToolTip( const QString &toolTip )
{
if ( toolTip.isEmpty() )
return QString();
const QStringList parts = toolTip.split( '\n' );
QString formatted = QStringLiteral( "<b>%1</b>" ).arg( parts.at( 0 ) );
if ( parts.count() > 1 )
{
for ( int i = 1; i < parts.count(); ++i )
formatted += QStringLiteral( "<p>%1</p>" ).arg( parts.at( i ) );
}
return formatted;
}
void QgsShortcutsManager::updateActionToolTip( QAction *action, const QString &sequence )
{
QString current = action->toolTip();
const thread_local QRegularExpression rx( QStringLiteral( "\\((.*)\\)" ) );
const thread_local QRegularExpression rx( QStringLiteral( "\\s*\\((.*)\\)" ) );
// Look for the last occurrence of text inside parentheses
QRegularExpressionMatch match;
if ( current.lastIndexOf( rx, -1, &match ) != -1 )

View File

@ -38,6 +38,19 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
Q_OBJECT
public:
/**
* Contains common actions which are used across a variety of classes.
* \since QGIS 4.0
*/
enum class CommonAction
{
CodeToggleComment, //!< Toggle code comments
CodeReformat, //!< Reformat code
CodeRunScript, //!< Run script
CodeRunSelection, //!< Run selection from script
};
Q_ENUM( CommonAction )
/**
* Constructor for QgsShortcutsManager.
* \param parent parent object
@ -47,6 +60,8 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
*/
QgsShortcutsManager( QObject *parent SIP_TRANSFERTHIS = nullptr, const QString &settingsRoot = "/shortcuts/" );
~QgsShortcutsManager() override;
/**
* Automatically registers all QActions and QShortcuts which are children of the
* passed object.
@ -93,6 +108,16 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
*/
bool registerAction( QAction *action, const QString &defaultShortcut = QString(), const QString &section = QString() );
/**
* Initializes an \a action as a common action.
*
* This automatically configures the \a action to use the properties for the common action, such
* as setting the action's tooltip and shortcut.
*
* \since QGIS 4.0
*/
void initializeCommonAction( QAction *action, CommonAction commonAction );
/**
* 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
@ -228,6 +253,12 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
*/
QShortcut *shortcutForSequence( const QKeySequence &sequence ) const;
/**
* Returns the key sequence which is associated with a common \a action, or an empty sequence if no shortcut is assigned to that action.
* \since QGIS 4.0
*/
QKeySequence sequenceForCommonAction( CommonAction action ) const;
/**
* Returns an action by its name, or NULLPTR if nothing found.
* \param name action name. Must match QAction's text.
@ -273,6 +304,10 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
ActionsHash mActions;
ShortcutsHash mShortcuts;
QString mSettingsPath;
QHash< int, QAction * > mCommonActions;
QHash< QAction *, CommonAction > mLinkedCommonActions;
static QString formatActionToolTip( const QString &toolTip );
/**
* Updates the action to include the shortcut keys. Shortcut keys are

View File

@ -1046,6 +1046,10 @@ void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
if ( mBlockUpdates || !mClassificationMethod )
return;
mClassificationMethod->setLabelFormat( txtLegendFormat->text() );
mClassificationMethod->setLabelPrecision( spinPrecision->value() );
mClassificationMethod->setLabelTrimTrailingZeroes( cbxTrimTrailingZeroes->isChecked() );
QgsTemporaryCursorOverride override( Qt::WaitCursor );
QString attrName = mExpressionWidget->currentField();
int nclasses = spinGraduatedClasses->value();

View File

@ -135,7 +135,10 @@ class TestQgsCodeEditor(QgisTestCase):
else:
font_db = QFontDatabase()
self.assertTrue(font_db.isFixedPitch(font.family(), font_db.styleString(font)))
self.assertTrue(
font_db.isFixedPitch(font.family(), font_db.styleString(font)),
f"Font {font.family()} ({font_db.styleString(font)}) is not fixed pitch",
)
QgsSettings().setValue(
"codeEditor/fontfamily", getTestFont().family(), QgsSettings.Section.Gui

View File

@ -182,25 +182,25 @@ class TestQgsCodeEditorPython(QgisTestCase):
# Check single line comment
editor.setText("#Hello World")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "Hello World")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "# Hello World")
# Check multiline comment
editor.setText("Hello\nQGIS\nWorld")
editor.setSelection(0, 0, 1, 4)
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "# Hello\n# QGIS\nWorld")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "Hello\nQGIS\nWorld")
# Check multiline comment with already commented lines
editor.setText("Hello\n# QGIS\nWorld")
editor.setSelection(0, 0, 2, 4)
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "# Hello\n# # QGIS\n# World")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier)
QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "Hello\n# QGIS\nWorld")

View File

@ -1,4 +1,4 @@
"""QGIS Unit tests for QgsActionManager.
"""QGIS Unit tests for QgsShortcutsManager.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -10,7 +10,9 @@ __author__ = "Nyall Dawson"
__date__ = "28/05/2016"
__copyright__ = "Copyright 2016, The QGIS Project"
from qgis.PyQt.QtCore import QCoreApplication
from typing import List
from qgis.PyQt.QtCore import QCoreApplication, QObject, QEvent
from qgis.PyQt.QtWidgets import QAction, QShortcut, QWidget
from qgis.core import QgsSettings
from qgis.gui import QgsGui, QgsShortcutsManager
@ -25,11 +27,15 @@ class TestQgsShortcutsManager(QgisTestCase):
"""Run before all tests"""
super().setUpClass()
QCoreApplication.setOrganizationName("QGIS_Test")
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsWFSProviderGUI.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsWFSProviderGUI")
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsShortcutsManager.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsShortcutsManager")
QgsSettings().clear()
start_app()
@staticmethod
def filter_common_actions(actions: list[QObject]) -> list[QObject]:
return [a for a in actions if a.property("commonAction") is None]
def testInstance(self):
"""test retrieving global instance"""
self.assertTrue(QgsGui.shortcutsManager())
@ -38,9 +44,12 @@ class TestQgsShortcutsManager(QgisTestCase):
action = QAction("test", None)
QgsGui.shortcutsManager().registerAction(action)
# check that the same instance is returned
self.assertEqual(QgsGui.shortcutsManager().listActions(), [action])
self.assertEqual(
self.filter_common_actions(QgsGui.shortcutsManager().listActions()),
[action],
)
s2 = QgsShortcutsManager()
self.assertEqual(s2.listActions(), [])
self.assertEqual(self.filter_common_actions(s2.listActions()), [])
def testConstructor(self):
"""test constructing managers"""
@ -87,11 +96,15 @@ class TestQgsShortcutsManager(QgisTestCase):
action2 = QAction("action2", None)
action2.setShortcut("y")
self.assertTrue(s.registerAction(action2, "B"))
self.assertCountEqual(s.listActions(), [action1, action2])
self.assertCountEqual(
self.filter_common_actions(s.listActions()), [action1, action2]
)
# try re-registering an existing action - should fail, but leave action registered
self.assertFalse(s.registerAction(action2, "B"))
self.assertCountEqual(s.listActions(), [action1, action2])
self.assertCountEqual(
self.filter_common_actions(s.listActions()), [action1, action2]
)
# actions should have been set to default sequences
self.assertEqual(action1.shortcut().toString(), "A")
@ -161,27 +174,31 @@ class TestQgsShortcutsManager(QgisTestCase):
# recursive
s = QgsShortcutsManager()
s.registerAllChildActions(w, True)
self.assertEqual(set(s.listActions()), {action1, action2})
self.assertEqual(
set(self.filter_common_actions(s.listActions())), {action1, action2}
)
s.registerAllChildShortcuts(w, True)
self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
# non recursive
s = QgsShortcutsManager()
s.registerAllChildActions(w, False)
self.assertEqual(set(s.listActions()), {action1})
self.assertEqual(set(self.filter_common_actions(s.listActions())), {action1})
s.registerAllChildShortcuts(w, False)
self.assertEqual(set(s.listShortcuts()), {shortcut1})
# recursive
s = QgsShortcutsManager()
s.registerAllChildren(w, True)
self.assertEqual(set(s.listActions()), {action1, action2})
self.assertEqual(
set(self.filter_common_actions(s.listActions())), {action1, action2}
)
self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
# non recursive
s = QgsShortcutsManager()
s.registerAllChildren(w, False)
self.assertEqual(set(s.listActions()), {action1})
self.assertEqual(set(self.filter_common_actions(s.listActions())), {action1})
self.assertEqual(set(s.listShortcuts()), {shortcut1})
def testUnregister(self):
@ -213,13 +230,15 @@ class TestQgsShortcutsManager(QgisTestCase):
s.registerAction(action1)
s.registerAction(action2)
self.assertEqual(set(s.listActions()), {action1, action2})
self.assertEqual(
set(self.filter_common_actions(s.listActions())), {action1, action2}
)
self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
self.assertTrue(s.unregisterAction(action1))
self.assertTrue(s.unregisterShortcut(shortcut1))
self.assertEqual(set(s.listActions()), {action2})
self.assertEqual(set(self.filter_common_actions(s.listActions())), {action2})
self.assertEqual(set(s.listShortcuts()), {shortcut2})
self.assertTrue(s.unregisterAction(action2))
@ -232,9 +251,9 @@ class TestQgsShortcutsManager(QgisTestCase):
s = QgsShortcutsManager(None)
self.assertEqual(s.listActions(), [])
self.assertEqual(self.filter_common_actions(s.listActions()), [])
self.assertEqual(s.listShortcuts(), [])
self.assertEqual(s.listAll(), [])
self.assertEqual(self.filter_common_actions(s.listAll()), [])
shortcut1 = QShortcut(None)
shortcut2 = QShortcut(None)
@ -245,9 +264,14 @@ class TestQgsShortcutsManager(QgisTestCase):
s.registerAction(action1)
s.registerAction(action2)
self.assertEqual(set(s.listActions()), {action1, action2})
self.assertEqual(
set(self.filter_common_actions(s.listActions())), {action1, action2}
)
self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
self.assertEqual(set(s.listAll()), {action1, action2, shortcut1, shortcut2})
self.assertEqual(
set(self.filter_common_actions(s.listAll())),
{action1, action2, shortcut1, shortcut2},
)
def testDefault(self):
"""test retrieving default sequences"""
@ -462,7 +486,134 @@ class TestQgsShortcutsManager(QgisTestCase):
self.assertEqual(action1.toolTip(), "<b>my tooltip</b>")
self.assertEqual(action2.toolTip(), "<b>my multiline</b><p>tooltip</p>")
self.assertEqual(action3.toolTip(), "<b>my tooltip </b> (Ctrl+S)")
self.assertEqual(action3.toolTip(), "<b>my tooltip</b> (Ctrl+S)")
def test_common_actions(self):
s = QgsShortcutsManager(None)
reformat_code_action = [
a
for a in s.listActions()
if a.property("commonAction")
== QgsShortcutsManager.CommonAction.CodeReformat.value
][0]
self.assertEqual(reformat_code_action.text(), "Reformat Code")
self.assertEqual(reformat_code_action.shortcut().toString(), "Ctrl+Alt+F")
self.assertEqual(
reformat_code_action.toolTip(), "<b>Reformat code</b> (Ctrl+Alt+F)"
)
toggle_code_comment_action = [
a
for a in s.listActions()
if a.property("commonAction")
== QgsShortcutsManager.CommonAction.CodeToggleComment.value
][0]
self.assertEqual(toggle_code_comment_action.text(), "Toggle Comment")
self.assertEqual(toggle_code_comment_action.shortcut().toString(), "Ctrl+/")
self.assertEqual(
toggle_code_comment_action.toolTip(), "<b>Toggle comment</b> (Ctrl+/)"
)
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeReformat
).toString(),
"Ctrl+Alt+F",
)
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeToggleComment
).toString(),
"Ctrl+/",
)
# link an action to a common action
my_reformat_action1 = QAction()
s.initializeCommonAction(
my_reformat_action1, QgsShortcutsManager.CommonAction.CodeReformat
)
my_reformat_action2 = QAction()
s.initializeCommonAction(
my_reformat_action2, QgsShortcutsManager.CommonAction.CodeReformat
)
# default properties should be set
self.assertEqual(my_reformat_action1.text(), "Reformat Code")
self.assertEqual(my_reformat_action1.shortcut().toString(), "Ctrl+Alt+F")
self.assertEqual(
my_reformat_action1.toolTip(), "<b>Reformat code</b> (Ctrl+Alt+F)"
)
self.assertEqual(my_reformat_action2.text(), "Reformat Code")
self.assertEqual(my_reformat_action2.shortcut().toString(), "Ctrl+Alt+F")
self.assertEqual(
my_reformat_action2.toolTip(), "<b>Reformat code</b> (Ctrl+Alt+F)"
)
my_toggle_comment_action = QAction()
s.initializeCommonAction(
my_toggle_comment_action, QgsShortcutsManager.CommonAction.CodeToggleComment
)
self.assertEqual(my_toggle_comment_action.text(), "Toggle Comment")
self.assertEqual(my_toggle_comment_action.shortcut().toString(), "Ctrl+/")
self.assertEqual(
my_toggle_comment_action.toolTip(), "<b>Toggle comment</b> (Ctrl+/)"
)
# change shortcut
s.setKeySequence(reformat_code_action, "B")
self.assertEqual(my_reformat_action1.shortcut().toString(), "B")
self.assertEqual(my_reformat_action1.toolTip(), "<b>Reformat code</b> (B)")
self.assertEqual(my_reformat_action2.shortcut().toString(), "B")
self.assertEqual(my_reformat_action2.toolTip(), "<b>Reformat code</b> (B)")
self.assertEqual(my_toggle_comment_action.shortcut().toString(), "Ctrl+/")
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeReformat
).toString(),
"B",
)
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeToggleComment
).toString(),
"Ctrl+/",
)
s.setKeySequence(toggle_code_comment_action, "C")
self.assertEqual(my_reformat_action1.shortcut().toString(), "B")
self.assertEqual(my_reformat_action1.toolTip(), "<b>Reformat code</b> (B)")
self.assertEqual(my_reformat_action2.shortcut().toString(), "B")
self.assertEqual(my_reformat_action2.toolTip(), "<b>Reformat code</b> (B)")
self.assertEqual(my_toggle_comment_action.shortcut().toString(), "C")
self.assertEqual(
my_toggle_comment_action.toolTip(), "<b>Toggle comment</b> (C)"
)
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeReformat
).toString(),
"B",
)
self.assertEqual(
s.sequenceForCommonAction(
QgsShortcutsManager.CommonAction.CodeToggleComment
).toString(),
"C",
)
# delete local action
my_reformat_action2.deleteLater()
QCoreApplication.sendPostedEvents(None, QEvent.Type.DeferredDelete)
my_reformat_action2 = None
# should be no crash
s.setKeySequence(reformat_code_action, "D")
self.assertEqual(my_reformat_action1.shortcut().toString(), "D")
self.assertEqual(my_reformat_action1.toolTip(), "<b>Reformat code</b> (D)")
self.assertEqual(my_toggle_comment_action.shortcut().toString(), "C")
self.assertEqual(
my_toggle_comment_action.toolTip(), "<b>Toggle comment</b> (C)"
)
if __name__ == "__main__":