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) 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}") 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) 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) 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) BUILD_SIP_PYTHON_MODULE(qgis._3d_p 3d/3d.sip ${cpp_files} "" qgis_core qgis_3d)
endif() 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" #include "qgsshortcutsmanager.h"
%End %End
public: public:
enum class CommonAction
{
CodeToggleComment,
CodeReformat,
CodeRunScript,
CodeRunSelection,
};
QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" ); QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" );
%Docstring %Docstring
Constructor for QgsShortcutsManager. Constructor for QgsShortcutsManager.
@ -36,6 +44,8 @@ Constructor for QgsShortcutsManager.
QGIS actions. QGIS actions.
%End %End
~QgsShortcutsManager();
void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() ); void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring %Docstring
Automatically registers all QActions and QShortcuts which are children Automatically registers all QActions and QShortcuts which are children
@ -105,6 +115,16 @@ in GUI.
.. seealso:: :py:func:`unregisterAction` .. seealso:: :py:func:`unregisterAction`
.. seealso:: :py:func:`registerAllChildActions` .. 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 %End
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() ); 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:`objectForSequence`
.. seealso:: :py:func:`actionForSequence` .. 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 %End
QAction *actionByName( const QString &name ) const; 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.setSymbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L426
QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427 QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427
QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407 QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L236 QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L267
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L221 QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L163 QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L171 QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L155 QgsShortcutsManager.initializeCommonAction: src/gui/qgsshortcutsmanager.h#L119
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L213 QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L262 QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L238
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L254 QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L293
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L94 QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L285
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L70 QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L109
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L81 QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L85
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L59 QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L96
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L106 QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L74
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L180 QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L131
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L196 QgsShortcutsManager.sequenceForCommonAction: src/gui/qgsshortcutsmanager.h#L260
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L204 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L205
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L188 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L246 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L243 QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L229 QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L277
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L116 QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L274
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L126 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 QgsShortcutsManager: src/gui/qgsshortcutsmanager.h#L36
QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264 QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264
QgsSimpleFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwidget.h#L271 QgsSimpleFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwidget.h#L271

View File

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

View File

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

View File

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

View File

@ -348,7 +348,7 @@ class ShellOutputScintilla(QgsCodeEditorPython):
Ed = self.console_widget.splitterObj Ed = self.console_widget.splitterObj
if not Ed.isVisible(): if not Ed.isVisible():
Ed.show() Ed.show()
self.console_widget.showEditorButton.setChecked(True) self.console_widget.show_editor_action.setChecked(True)
self.shell_editor.setFocus() self.shell_editor.setFocus()
def copy(self): 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" #include "qgsshortcutsmanager.h"
%End %End
public: public:
enum class CommonAction
{
CodeToggleComment,
CodeReformat,
CodeRunScript,
CodeRunSelection,
};
QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" ); QgsShortcutsManager( QObject *parent /TransferThis/ = 0, const QString &settingsRoot = "/shortcuts/" );
%Docstring %Docstring
Constructor for QgsShortcutsManager. Constructor for QgsShortcutsManager.
@ -36,6 +44,8 @@ Constructor for QgsShortcutsManager.
QGIS actions. QGIS actions.
%End %End
~QgsShortcutsManager();
void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() ); void registerAllChildren( QObject *object, bool recursive = false, const QString &section = QString() );
%Docstring %Docstring
Automatically registers all QActions and QShortcuts which are children Automatically registers all QActions and QShortcuts which are children
@ -105,6 +115,16 @@ in GUI.
.. seealso:: :py:func:`unregisterAction` .. seealso:: :py:func:`unregisterAction`
.. seealso:: :py:func:`registerAllChildActions` .. 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 %End
bool registerShortcut( QShortcut *shortcut, const QString &defaultSequence = QString(), const QString &section = QString() ); 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:`objectForSequence`
.. seealso:: :py:func:`actionForSequence` .. 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 %End
QAction *actionByName( const QString &name ) const; 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.setSymbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L426
QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427 QgsShapeburstFillSymbolLayerWidget.symbolLayer: src/gui/symbology/qgssymbollayerwidget.h#L427
QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407 QgsShapeburstFillSymbolLayerWidget: src/gui/symbology/qgssymbollayerwidget.h#L407
QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L236 QgsShortcutsManager.actionByName: src/gui/qgsshortcutsmanager.h#L267
QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L221 QgsShortcutsManager.actionForSequence: src/gui/qgsshortcutsmanager.h#L246
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L163 QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L188
QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L171 QgsShortcutsManager.defaultKeySequence: src/gui/qgsshortcutsmanager.h#L196
QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L155 QgsShortcutsManager.initializeCommonAction: src/gui/qgsshortcutsmanager.h#L119
QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L213 QgsShortcutsManager.objectDefaultKeySequence: src/gui/qgsshortcutsmanager.h#L180
QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L262 QgsShortcutsManager.objectForSequence: src/gui/qgsshortcutsmanager.h#L238
QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L254 QgsShortcutsManager.objectForSettingKey: src/gui/qgsshortcutsmanager.h#L293
QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L94 QgsShortcutsManager.objectSettingKey: src/gui/qgsshortcutsmanager.h#L285
QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L70 QgsShortcutsManager.registerAction: src/gui/qgsshortcutsmanager.h#L109
QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L81 QgsShortcutsManager.registerAllChildActions: src/gui/qgsshortcutsmanager.h#L85
QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L59 QgsShortcutsManager.registerAllChildShortcuts: src/gui/qgsshortcutsmanager.h#L96
QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L106 QgsShortcutsManager.registerAllChildren: src/gui/qgsshortcutsmanager.h#L74
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L180 QgsShortcutsManager.registerShortcut: src/gui/qgsshortcutsmanager.h#L131
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L196 QgsShortcutsManager.sequenceForCommonAction: src/gui/qgsshortcutsmanager.h#L260
QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L204 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L205
QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L188 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L221
QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L246 QgsShortcutsManager.setKeySequence: src/gui/qgsshortcutsmanager.h#L229
QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L243 QgsShortcutsManager.setObjectKeySequence: src/gui/qgsshortcutsmanager.h#L213
QgsShortcutsManager.shortcutForSequence: src/gui/qgsshortcutsmanager.h#L229 QgsShortcutsManager.settingsPath: src/gui/qgsshortcutsmanager.h#L277
QgsShortcutsManager.unregisterAction: src/gui/qgsshortcutsmanager.h#L116 QgsShortcutsManager.shortcutByName: src/gui/qgsshortcutsmanager.h#L274
QgsShortcutsManager.unregisterShortcut: src/gui/qgsshortcutsmanager.h#L126 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 QgsShortcutsManager: src/gui/qgsshortcutsmanager.h#L36
QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264 QgsSimpleFillSymbolLayerWidget.create: src/gui/symbology/qgssymbollayerwidget.h#L264
QgsSimpleFillSymbolLayerWidget.setColor: src/gui/symbology/qgssymbollayerwidget.h#L271 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.QtGui import QPalette
from qgis.PyQt.QtWidgets import QMessageBox, QFileDialog, QVBoxLayout 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 ( from qgis.core import (
QgsApplication, QgsApplication,
QgsFileUtils, QgsFileUtils,
@ -122,6 +122,9 @@ class ScriptEditorDialog(BASE, WIDGET):
self.palette().color(QPalette.ColorRole.WindowText), self.palette().color(QPalette.ColorRole.WindowText),
) )
) )
QgsGui.shortcutsManager().initializeCommonAction(
self.actionToggleComment, QgsShortcutsManager.CommonAction.CodeToggleComment
)
# Connect signals and slots # Connect signals and slots
self.actionOpenScript.triggered.connect(self.openScript) self.actionOpenScript.triggered.connect(self.openScript)

View File

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

View File

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

View File

@ -17,6 +17,7 @@
#include "moc_qgsshortcutsmanager.cpp" #include "moc_qgsshortcutsmanager.cpp"
#include "qgslogger.h" #include "qgslogger.h"
#include "qgssettings.h" #include "qgssettings.h"
#include "qgsapplication.h"
#include <QShortcut> #include <QShortcut>
#include <QRegularExpression> #include <QRegularExpression>
@ -26,6 +27,33 @@ QgsShortcutsManager::QgsShortcutsManager( QObject *parent, const QString &settin
: QObject( parent ) : QObject( parent )
, mSettingsPath( settingsRoot ) , 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 ) 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 ) ); QgsLogger::warning( QStringLiteral( "Duplicate shortcut registered: %1" ).arg( key ) );
#endif #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 } ); mActions.insert( action, { defaultSequence, settingKey } );
connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } ); connect( action, &QObject::destroyed, this, [action, this]() { actionDestroyed( action ); } );
@ -105,21 +133,28 @@ bool QgsShortcutsManager::registerAction( QAction *action, const QString &defaul
action->setShortcut( sequence ); action->setShortcut( sequence );
if ( !action->toolTip().isEmpty() ) if ( !action->toolTip().isEmpty() )
{ {
const QStringList parts = action->toolTip().split( '\n' ); action->setToolTip( formatActionToolTip( action->toolTip() ) );
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 );
updateActionToolTip( action, sequence ); updateActionToolTip( action, sequence );
} }
return true; 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 ) bool QgsShortcutsManager::registerShortcut( QShortcut *shortcut, const QString &defaultSequence, const QString &section )
{ {
#ifdef QGISDEBUG #ifdef QGISDEBUG
@ -130,7 +165,7 @@ 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
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 } ); mShortcuts.insert( shortcut, { defaultSequence, settingKey } );
connect( shortcut, &QObject::destroyed, this, [shortcut, this]() { shortcutDestroyed( shortcut ); } ); connect( shortcut, &QObject::destroyed, this, [shortcut, this]() { shortcutDestroyed( shortcut ); } );
@ -237,6 +272,21 @@ bool QgsShortcutsManager::setKeySequence( QAction *action, const QString &sequen
action->setShortcut( sequence ); action->setShortcut( sequence );
this->updateActionToolTip( action, 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; const QString settingKey = mActions[action].second;
// save to settings // save to settings
@ -299,6 +349,15 @@ QShortcut *QgsShortcutsManager::shortcutForSequence( const QKeySequence &sequenc
return nullptr; 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 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 )
@ -331,6 +390,7 @@ QShortcut *QgsShortcutsManager::shortcutByName( const QString &name ) const
void QgsShortcutsManager::actionDestroyed( QAction *action ) void QgsShortcutsManager::actionDestroyed( QAction *action )
{ {
mActions.remove( action ); mActions.remove( action );
mLinkedCommonActions.remove( action );
} }
QString QgsShortcutsManager::objectSettingKey( QObject *object ) const QString QgsShortcutsManager::objectSettingKey( QObject *object ) const
@ -366,10 +426,26 @@ void QgsShortcutsManager::shortcutDestroyed( QShortcut *shortcut )
mShortcuts.remove( 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 ) void QgsShortcutsManager::updateActionToolTip( QAction *action, const QString &sequence )
{ {
QString current = action->toolTip(); 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 // Look for the last occurrence of text inside parentheses
QRegularExpressionMatch match; QRegularExpressionMatch match;
if ( current.lastIndexOf( rx, -1, &match ) != -1 ) if ( current.lastIndexOf( rx, -1, &match ) != -1 )

View File

@ -38,6 +38,19 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
Q_OBJECT Q_OBJECT
public: 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. * Constructor for QgsShortcutsManager.
* \param parent parent object * \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( QObject *parent SIP_TRANSFERTHIS = nullptr, const QString &settingsRoot = "/shortcuts/" );
~QgsShortcutsManager() override;
/** /**
* 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.
@ -93,6 +108,16 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
*/ */
bool registerAction( QAction *action, const QString &defaultShortcut = QString(), const QString &section = QString() ); 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. * 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
@ -228,6 +253,12 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
*/ */
QShortcut *shortcutForSequence( const QKeySequence &sequence ) const; 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. * Returns an action by its name, or NULLPTR if nothing found.
* \param name action name. Must match QAction's text. * \param name action name. Must match QAction's text.
@ -273,6 +304,10 @@ class GUI_EXPORT QgsShortcutsManager : public QObject
ActionsHash mActions; ActionsHash mActions;
ShortcutsHash mShortcuts; ShortcutsHash mShortcuts;
QString mSettingsPath; 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 * Updates the action to include the shortcut keys. Shortcut keys are

View File

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

View File

@ -135,7 +135,10 @@ class TestQgsCodeEditor(QgisTestCase):
else: else:
font_db = QFontDatabase() 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( QgsSettings().setValue(
"codeEditor/fontfamily", getTestFont().family(), QgsSettings.Section.Gui "codeEditor/fontfamily", getTestFont().family(), QgsSettings.Section.Gui

View File

@ -182,25 +182,25 @@ class TestQgsCodeEditorPython(QgisTestCase):
# Check single line comment # Check single line comment
editor.setText("#Hello World") editor.setText("#Hello World")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier) QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "Hello World") self.assertEqual(editor.text(), "Hello World")
QTest.keyClick(editor, ":", Qt.KeyboardModifier.ControlModifier) QTest.keyClick(editor, "/", Qt.KeyboardModifier.ControlModifier)
self.assertEqual(editor.text(), "# Hello World") self.assertEqual(editor.text(), "# Hello World")
# Check multiline comment # Check multiline comment
editor.setText("Hello\nQGIS\nWorld") editor.setText("Hello\nQGIS\nWorld")
editor.setSelection(0, 0, 1, 4) 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") 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") self.assertEqual(editor.text(), "Hello\nQGIS\nWorld")
# Check multiline comment with already commented lines # Check multiline comment with already commented lines
editor.setText("Hello\n# QGIS\nWorld") editor.setText("Hello\n# QGIS\nWorld")
editor.setSelection(0, 0, 2, 4) 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") 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") 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 .. 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 it under the terms of the GNU General Public License as published by
@ -10,7 +10,9 @@ __author__ = "Nyall Dawson"
__date__ = "28/05/2016" __date__ = "28/05/2016"
__copyright__ = "Copyright 2016, The QGIS Project" __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.PyQt.QtWidgets import QAction, QShortcut, QWidget
from qgis.core import QgsSettings from qgis.core import QgsSettings
from qgis.gui import QgsGui, QgsShortcutsManager from qgis.gui import QgsGui, QgsShortcutsManager
@ -25,11 +27,15 @@ class TestQgsShortcutsManager(QgisTestCase):
"""Run before all tests""" """Run before all tests"""
super().setUpClass() super().setUpClass()
QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationName("QGIS_Test")
QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsWFSProviderGUI.com") QCoreApplication.setOrganizationDomain("QGIS_TestPyQgsShortcutsManager.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsWFSProviderGUI") QCoreApplication.setApplicationName("QGIS_TestPyQgsShortcutsManager")
QgsSettings().clear() QgsSettings().clear()
start_app() 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): def testInstance(self):
"""test retrieving global instance""" """test retrieving global instance"""
self.assertTrue(QgsGui.shortcutsManager()) self.assertTrue(QgsGui.shortcutsManager())
@ -38,9 +44,12 @@ class TestQgsShortcutsManager(QgisTestCase):
action = QAction("test", None) action = QAction("test", None)
QgsGui.shortcutsManager().registerAction(action) QgsGui.shortcutsManager().registerAction(action)
# check that the same instance is returned # 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() s2 = QgsShortcutsManager()
self.assertEqual(s2.listActions(), []) self.assertEqual(self.filter_common_actions(s2.listActions()), [])
def testConstructor(self): def testConstructor(self):
"""test constructing managers""" """test constructing managers"""
@ -87,11 +96,15 @@ class TestQgsShortcutsManager(QgisTestCase):
action2 = QAction("action2", None) action2 = QAction("action2", None)
action2.setShortcut("y") action2.setShortcut("y")
self.assertTrue(s.registerAction(action2, "B")) 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 # try re-registering an existing action - should fail, but leave action registered
self.assertFalse(s.registerAction(action2, "B")) 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 # actions should have been set to default sequences
self.assertEqual(action1.shortcut().toString(), "A") self.assertEqual(action1.shortcut().toString(), "A")
@ -161,27 +174,31 @@ class TestQgsShortcutsManager(QgisTestCase):
# recursive # recursive
s = QgsShortcutsManager() s = QgsShortcutsManager()
s.registerAllChildActions(w, True) 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) s.registerAllChildShortcuts(w, True)
self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2}) self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
# non recursive # non recursive
s = QgsShortcutsManager() s = QgsShortcutsManager()
s.registerAllChildActions(w, False) s.registerAllChildActions(w, False)
self.assertEqual(set(s.listActions()), {action1}) self.assertEqual(set(self.filter_common_actions(s.listActions())), {action1})
s.registerAllChildShortcuts(w, False) s.registerAllChildShortcuts(w, False)
self.assertEqual(set(s.listShortcuts()), {shortcut1}) self.assertEqual(set(s.listShortcuts()), {shortcut1})
# recursive # recursive
s = QgsShortcutsManager() s = QgsShortcutsManager()
s.registerAllChildren(w, True) 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}) self.assertEqual(set(s.listShortcuts()), {shortcut1, shortcut2})
# non recursive # non recursive
s = QgsShortcutsManager() s = QgsShortcutsManager()
s.registerAllChildren(w, False) 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}) self.assertEqual(set(s.listShortcuts()), {shortcut1})
def testUnregister(self): def testUnregister(self):
@ -213,13 +230,15 @@ class TestQgsShortcutsManager(QgisTestCase):
s.registerAction(action1) s.registerAction(action1)
s.registerAction(action2) 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.listShortcuts()), {shortcut1, shortcut2})
self.assertTrue(s.unregisterAction(action1)) self.assertTrue(s.unregisterAction(action1))
self.assertTrue(s.unregisterShortcut(shortcut1)) 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.assertEqual(set(s.listShortcuts()), {shortcut2})
self.assertTrue(s.unregisterAction(action2)) self.assertTrue(s.unregisterAction(action2))
@ -232,9 +251,9 @@ class TestQgsShortcutsManager(QgisTestCase):
s = QgsShortcutsManager(None) s = QgsShortcutsManager(None)
self.assertEqual(s.listActions(), []) self.assertEqual(self.filter_common_actions(s.listActions()), [])
self.assertEqual(s.listShortcuts(), []) self.assertEqual(s.listShortcuts(), [])
self.assertEqual(s.listAll(), []) self.assertEqual(self.filter_common_actions(s.listAll()), [])
shortcut1 = QShortcut(None) shortcut1 = QShortcut(None)
shortcut2 = QShortcut(None) shortcut2 = QShortcut(None)
@ -245,9 +264,14 @@ class TestQgsShortcutsManager(QgisTestCase):
s.registerAction(action1) s.registerAction(action1)
s.registerAction(action2) 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.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): def testDefault(self):
"""test retrieving default sequences""" """test retrieving default sequences"""
@ -462,7 +486,134 @@ class TestQgsShortcutsManager(QgisTestCase):
self.assertEqual(action1.toolTip(), "<b>my tooltip</b>") self.assertEqual(action1.toolTip(), "<b>my tooltip</b>")
self.assertEqual(action2.toolTip(), "<b>my multiline</b><p>tooltip</p>") 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__": if __name__ == "__main__":