From ac3a01f0415a3b02083ceeb76cc4817be3ba306c Mon Sep 17 00:00:00 2001 From: Yoann Quenach de Quivillic Date: Thu, 31 Oct 2024 10:02:14 +0100 Subject: [PATCH] Apply suggestions from review --- python/PyQt6/core/auto_additions/qgis.py | 30 +++++ python/PyQt6/core/auto_generated/qgis.sip.in | 14 +++ .../PyQt6/gui/auto_additions/qgscodeeditor.py | 2 +- .../codeeditors/qgscodeeditor.sip.in | 4 +- .../codeeditors/qgscodeeditorpython.sip.in | 2 +- .../gui/auto_generated/qgisinterface.sip.in | 8 +- python/console/console_sci.py | 47 ++++---- python/console/console_settings.py | 28 +++-- python/console/console_settings.ui | 36 +----- python/core/auto_additions/qgis.py | 30 +++++ python/core/auto_generated/qgis.sip.in | 14 +++ python/gui/auto_additions/qgscodeeditor.py | 2 +- .../codeeditors/qgscodeeditor.sip.in | 4 +- .../codeeditors/qgscodeeditorpython.sip.in | 2 +- .../gui/auto_generated/qgisinterface.sip.in | 8 +- .../qgsdocumentationpanelwidget.cpp | 5 +- .../qgsdocumentationpanelwidget.h | 4 +- src/app/qgisapp.cpp | 92 +--------------- src/app/qgisapp.h | 2 +- src/app/qgisappinterface.cpp | 4 +- src/app/qgisappinterface.h | 2 +- src/app/qgsdevtoolspanelwidget.cpp | 104 +++++++++++++++++- src/app/qgsdevtoolspanelwidget.h | 9 +- src/core/qgis.h | 26 +++++ src/gui/codeeditors/qgscodeeditor.cpp | 9 +- src/gui/codeeditors/qgscodeeditor.h | 6 +- src/gui/codeeditors/qgscodeeditorpython.cpp | 36 +++--- src/gui/codeeditors/qgscodeeditorpython.h | 6 +- src/gui/qgisinterface.h | 8 +- src/ui/qgsdocumentationpanelbase.ui | 28 ++--- 30 files changed, 344 insertions(+), 228 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 9a81e9040780..59b03362e427 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -10868,6 +10868,36 @@ """ # -- Qgis.ColorModel.baseClass = Qgis +# monkey patching scoped based enum +Qgis.DocumentationApi.PyQgis.__doc__ = "PyQgis API documentation" +Qgis.DocumentationApi.PyQgisSearch.__doc__ = "Search in PyQgis API documentation" +Qgis.DocumentationApi.CppQgis.__doc__ = "C++ QGIS API documentation" +Qgis.DocumentationApi.Qt.__doc__ = "Qt API documentation" +Qgis.DocumentationApi.__doc__ = """Documentation Api + +.. versionadded:: 3.42 + +* ``PyQgis``: PyQgis API documentation +* ``PyQgisSearch``: Search in PyQgis API documentation +* ``CppQgis``: C++ QGIS API documentation +* ``Qt``: Qt API documentation + +""" +# -- +Qgis.DocumentationApi.baseClass = Qgis +# monkey patching scoped based enum +Qgis.DocumentationBrowser.DeveloperToolsPanel.__doc__ = "Embedded webview in the DevTools panel" +Qgis.DocumentationBrowser.SystemWebBrowser.__doc__ = "Default system web browser" +Qgis.DocumentationBrowser.__doc__ = """Documentation API browser + +.. versionadded:: 3.42 + +* ``DeveloperToolsPanel``: Embedded webview in the DevTools panel +* ``SystemWebBrowser``: Default system web browser + +""" +# -- +Qgis.DocumentationBrowser.baseClass = Qgis try: Qgis.__attribute_docs__ = {'QGIS_DEV_VERSION': 'The development version', 'DEFAULT_SEARCH_RADIUS_MM': 'Identify search radius in mm', 'DEFAULT_MAPTOPIXEL_THRESHOLD': 'Default threshold between map coordinates and device coordinates for map2pixel simplification', 'DEFAULT_HIGHLIGHT_COLOR': 'Default highlight color. The transparency is expected to only be applied to polygon\nfill. Lines and outlines are rendered opaque.', 'DEFAULT_HIGHLIGHT_BUFFER_MM': 'Default highlight buffer in mm.', 'DEFAULT_HIGHLIGHT_MIN_WIDTH_MM': 'Default highlight line/stroke minimum width in mm.', 'SCALE_PRECISION': 'Fudge factor used to compare two scales. The code is often going from scale to scale\ndenominator. So it looses precision and, when a limit is inclusive, can lead to errors.\nTo avoid that, use this factor instead of using <= or >=.\n\n.. deprecated:: 3.40\n\n No longer used by QGIS and will be removed in QGIS 4.0.', 'DEFAULT_Z_COORDINATE': 'Default Z coordinate value.\nThis value have to be assigned to the Z coordinate for the vertex.', 'DEFAULT_M_COORDINATE': 'Default M coordinate value.\nThis value have to be assigned to the M coordinate for the vertex.\n\n.. versionadded:: 3.20', 'UI_SCALE_FACTOR': 'UI scaling factor. This should be applied to all widget sizes obtained from font metrics,\nto account for differences in the default font sizes across different platforms.', 'DEFAULT_SNAP_TOLERANCE': 'Default snapping distance tolerance.', 'DEFAULT_SNAP_UNITS': 'Default snapping distance units.'} Qgis.version = staticmethod(Qgis.version) diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index 714c9e794b5e..0225de7d39f2 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -3169,6 +3169,20 @@ The development version Cmyk, }; + enum class DocumentationApi /BaseType=IntEnum/ + { + PyQgis, + PyQgisSearch, + CppQgis, + Qt, + }; + + enum class DocumentationBrowser /BaseType=IntEnum/ + { + DeveloperToolsPanel, + SystemWebBrowser, + }; + static const double DEFAULT_SEARCH_RADIUS_MM; static const float DEFAULT_MAPTOPIXEL_THRESHOLD; diff --git a/python/PyQt6/gui/auto_additions/qgscodeeditor.py b/python/PyQt6/gui/auto_additions/qgscodeeditor.py index 0449f760090a..668fbcdafcd1 100644 --- a/python/PyQt6/gui/auto_additions/qgscodeeditor.py +++ b/python/PyQt6/gui/auto_additions/qgscodeeditor.py @@ -57,7 +57,7 @@ QgsCodeEditor.Flags.baseClass = QgsCodeEditor Flags = QgsCodeEditor # dirty hack since SIP seems to introduce the flags in module try: - QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted whent the F1 key is pressed while hovering over a word\n\n.. versionadded:: 3.42\n'} + QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n'} QgsCodeEditor.languageToString = staticmethod(QgsCodeEditor.languageToString) QgsCodeEditor.defaultColor = staticmethod(QgsCodeEditor.defaultColor) QgsCodeEditor.color = staticmethod(QgsCodeEditor.color) diff --git a/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditor.sip.in b/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditor.sip.in index 605ec9b40620..aa184913a5e0 100644 --- a/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditor.sip.in +++ b/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditor.sip.in @@ -520,9 +520,9 @@ Emitted when the persistent history of commands run in the editor is cleared. %End - void helpRequested( QString word ); + void helpRequested( const QString &word ); %Docstring -Emitted whent the F1 key is pressed while hovering over a word +Emitted when documentation was requested for the specified ``word``. .. versionadded:: 3.42 %End diff --git a/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in b/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in index 1130559bd339..e42a32690ce3 100644 --- a/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in +++ b/python/PyQt6/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in @@ -98,7 +98,7 @@ Searches the selected text in the official PyQGIS online documentation. virtual void showApiDocumentation( const QString &item ); %Docstring -Searches the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. +Displays the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. .. versionadded:: 3.42 %End diff --git a/python/PyQt6/gui/auto_generated/qgisinterface.sip.in b/python/PyQt6/gui/auto_generated/qgisinterface.sip.in index a3ec357aeca3..04d4e289c185 100644 --- a/python/PyQt6/gui/auto_generated/qgisinterface.sip.in +++ b/python/PyQt6/gui/auto_generated/qgisinterface.sip.in @@ -1492,14 +1492,14 @@ Unregister a previously registered tool factory from the development/debugging t .. versionadded:: 3.14 %End - virtual void showApiDocumentation( const QString &api = QStringLiteral( "pyqgis" ), bool embedded = true, const QString &object = QString(), const QString &module = QString() ) = 0; + virtual void showApiDocumentation( Qgis::DocumentationApi api = Qgis::DocumentationApi::PyQgis, Qgis::DocumentationBrowser browser = Qgis::DocumentationBrowser::DeveloperToolsPanel, const QString &object = QString(), const QString &module = QString() ) = 0; %Docstring Show a page of the API documentation -:param api: "pyqgis" or "qgis" or "qt" or "pyqgis-search" -:param embedded: If ``True``, the documentation will be opened in the embedded devtools webview. Otherwise, use system web browser +:param api: Which API to display +:param browser: Web browser used to display the API documentation :param object: object to show in the documentation -:param module: used only if api = "pyqgis" +:param module: used only if api = :py:class:`Qgis`.DocumentationApi.PyQgis .. versionadded:: 3.42 %End diff --git a/python/console/console_sci.py b/python/console/console_sci.py index 5f1087ce604a..ccff0305449b 100644 --- a/python/console/console_sci.py +++ b/python/console/console_sci.py @@ -105,37 +105,46 @@ def __parse_object(object=None): return 'qt', module, obj """, r""" -def _help(object=None, api="pyqgis", embedded=True, force_search=False): +def _help(object=None, api=Qgis.DocumentationApi.PyQgis, force_search=False): ''' Link to the C++ or PyQGIS API documentation for the given object. If no object is given, the main PyQGIS API page is opened. If the object is not part of the QGIS API but is a Qt object the Qt documentation is opened. ''' + + pythonSettingsTreeNode = QgsSettingsTree.node("gui").childNode("code-editor").childNode("python") + browserName = pythonSettingsTreeNode.childSetting('context-help-browser').valueAsVariant() + try: + browser = Qgis.DocumentationBrowser[browserName] + except KeyError: + browser = Qgis.DocumentationBrowser.DeveloperToolsPanel + if not object: - return iface.showApiDocumentation(api, embedded=embedded) + return iface.showApiDocumentation(api, browser=browser) + embedded = browser == Qgis.DocumentationBrowser.DeveloperToolsPanel if isinstance(object, str): try: object = eval(object) except (SyntaxError, NameError): if embedded and not force_search: - return iface.showApiDocumentation(api, embedded=True) + return iface.showApiDocumentation(api, browser=browser) else: - return iface.showApiDocumentation("pyqgis-search", object=object, embedded=False) + return iface.showApiDocumentation(Qgis.DocumentationApi.PyQgisSearch, object=object, browser=Qgis.DocumentationBrowser.SystemWebBrowser) obj_info = __parse_object(object) if not obj_info: if force_search or isinstance(object, str) and not embedded: - return iface.showApiDocumentation("pyqgis-search", object=object, embedded=False) + return iface.showApiDocumentation(Qgis.DocumentationApi.PyQgisSearch, object=object, browser=Qgis.DocumentationBrowser.SystemWebBrowser) else: - return iface.showApiDocumentation(api, embedded=embedded) + return iface.showApiDocumentation(api, browser=browser) obj_type, module, class_name = obj_info if obj_type == "qt": - api = "qt" + api = Qgis.DocumentationApi.Qt - iface.showApiDocumentation(api, embedded=embedded, object=class_name, module=module) + iface.showApiDocumentation(api, browser=browser, object=class_name, module=module) """, r""" @@ -145,7 +154,7 @@ def _api(object=None): If no object is given, the main API page is opened. If the object is not part of the QGIS API but is a Qt object the Qt documentation is opened. ''' - return _help(object, api="qgis") + return _help(object, api=Qgis.DocumentationApi.CppQgis) """, r""" def _pyqgis(object=None): @@ -154,7 +163,7 @@ def _pyqgis(object=None): If no object is given, the main PyQGIS API page is opened. If the object is not part of the QGIS API but is a Qt object the Qt documentation is opened. ''' - return _help(object, api="pyqgis") + return _help(object, api=Qgis.DocumentationApi.PyQgis) """ ] @@ -238,9 +247,9 @@ def execCommandImpl(self, cmd, show_input=True): if cmd == "?": self.shell.console_widget.shell_output.insertHelp() elif cmd == '_pyqgis': - self.shell.showApi("pyqgis") + self.shell.showApi(Qgis.DocumentationApi.PyQgis) elif cmd == '_api': - self.shell.showApi("qgis") + self.shell.showApi(Qgis.DocumentationApi.CppQgis) elif cmd == '_cookbook': webbrowser.open( "https://docs.qgis.org/{}/en/docs/pyqgis_developer_cookbook/".format( @@ -474,18 +483,10 @@ def runFile(self, filename, override_file_name: Optional[str] = None): QgsProcessingUtils.stringToPythonLiteral(dirname)), False) def showApiDocumentation(self, text, force_search=False): + self._interpreter.execCommandImpl(f'_help({repr(text)}, api=Qgis.DocumentationApi.PyQgis, force_search={force_search})', show_input=False) - pythonSettingsTreeNode = QgsSettingsTree.node("gui").childNode("code-editor").childNode("python") - - embedded = pythonSettingsTreeNode.childSetting('context-help-embedded').value() - api = "pyqgis" if pythonSettingsTreeNode.childSetting('context-help-pyqgis').value() else "qgis" - - self._interpreter.execCommandImpl(f'_help({repr(text)}, api="{api}", embedded={embedded}, force_search={force_search})', show_input=False) - - def showApi(self, api): - pythonSettingsTreeNode = QgsSettingsTree.node("gui").childNode("code-editor").childNode("python") - embedded = pythonSettingsTreeNode.childSetting('context-help-embedded').value() - self._interpreter.execCommandImpl(f'_help(api="{api}", embedded={embedded})', show_input=False) + def showApi(self, api: Qgis.DocumentationApi): + self._interpreter.execCommandImpl(f'_help(api=Qgis.DocumentationApi.{api.name})', show_input=False) def populateContextMenu(self, menu): diff --git a/python/console/console_settings.py b/python/console/console_settings.py index 93af15b063a6..19e36be258a5 100644 --- a/python/console/console_settings.py +++ b/python/console/console_settings.py @@ -25,7 +25,7 @@ from qgis.PyQt.QtWidgets import QWidget, QFileDialog, QMessageBox, QTableWidgetItem, QHBoxLayout from qgis.PyQt.QtGui import QIcon, QDesktopServices -from qgis.core import QgsSettings, QgsApplication, QgsSettingsTree +from qgis.core import QgsSettings, QgsApplication, QgsSettingsTree, Qgis from qgis.gui import QgsOptionsPageWidget, QgsOptionsWidgetFactory from .console_compile_apis import PrepareAPIDialog @@ -76,6 +76,10 @@ def __init__(self, parent): self.parent = parent self.setupUi(self) + # Populate the documentation Browser combobox + self.contextHelpBrowser.addItem(QCoreApplication.translate("PythonConsole", "Embedded Webview (developer tools)"), Qgis.DocumentationBrowser.DeveloperToolsPanel) + self.contextHelpBrowser.addItem(QCoreApplication.translate("PythonConsole", "Default system web browser"), Qgis.DocumentationBrowser.SystemWebBrowser) + self.autopep8Level.setClearValue(1) self.maxLineLength.setClearValue(80) @@ -211,15 +215,17 @@ def saveSettings(self): settings.setValue("pythonConsole/formatOnSave", self.formatOnSave.isChecked()) - pythonSettingsTreeNode = QgsSettingsTree.node("gui").childNode("code-editor").childNode("python") + codeEditorTreeNode = QgsSettingsTree.node("gui").childNode("code-editor") + pythonSettingsTreeNode = codeEditorTreeNode.childNode("python") pythonSettingsTreeNode.childSetting("sort-imports").setValue(self.sortImports.isChecked()) pythonSettingsTreeNode.childSetting("formatter").setValue(self.formatter.currentText()) pythonSettingsTreeNode.childSetting("autopep8-level").setValue(self.autopep8Level.value()) pythonSettingsTreeNode.childSetting("black-normalize-quotes").setValue(self.blackNormalizeQuotes.isChecked()) pythonSettingsTreeNode.childSetting("max-line-length").setValue(self.maxLineLength.value()) pythonSettingsTreeNode.childSetting('external-editor').setValue(self.externalEditor.text()) - pythonSettingsTreeNode.childSetting('context-help-embedded').setValue(self.contextHelpBrowser.currentIndex() == 0) - pythonSettingsTreeNode.childSetting('context-help-pyqgis').setValue(self.contextHelpApi.currentIndex() == 0) + pythonSettingsTreeNode.childSetting('context-help-browser').setVariantValue(self.contextHelpBrowser.currentData().name) + + codeEditorTreeNode.childSetting('context-help-hover').setValue(self.contextHelpHover.isChecked()) def restoreSettings(self): settings = QgsSettings() @@ -245,7 +251,8 @@ def restoreSettings(self): self.autoSurround.setChecked(settings.value("pythonConsole/autoSurround", True, type=bool)) self.autoInsertImport.setChecked(settings.value("pythonConsole/autoInsertImport", False, type=bool)) - pythonSettingsTreeNode = QgsSettingsTree.node("gui").childNode("code-editor").childNode("python") + codeEditorTreeNode = QgsSettingsTree.node("gui").childNode("code-editor") + pythonSettingsTreeNode = codeEditorTreeNode.childNode("python") self.formatOnSave.setChecked(settings.value("pythonConsole/formatOnSave", False, type=bool)) self.sortImports.setChecked(pythonSettingsTreeNode.childSetting("sort-imports").value()) @@ -253,8 +260,15 @@ def restoreSettings(self): self.autopep8Level.setValue(pythonSettingsTreeNode.childSetting("autopep8-level").value()) self.blackNormalizeQuotes.setChecked(pythonSettingsTreeNode.childSetting("black-normalize-quotes").value()) self.maxLineLength.setValue(pythonSettingsTreeNode.childSetting("max-line-length").value()) - self.contextHelpBrowser.setCurrentIndex(0 if pythonSettingsTreeNode.childSetting('context-help-embedded').value() else 1) - self.contextHelpApi.setCurrentIndex(0 if pythonSettingsTreeNode.childSetting('context-help-pyqgis').value() else 1) + + browserName = pythonSettingsTreeNode.childSetting('context-help-browser').valueAsVariant() + try: + browser = Qgis.DocumentationBrowser[browserName] + except KeyError: + browser = Qgis.DocumentationBrowser.DeveloperToolsPanel + + self.contextHelpBrowser.setCurrentIndex(self.contextHelpBrowser.findData(browser)) + self.contextHelpHover.setChecked(codeEditorTreeNode.childSetting('context-help-hover').value()) if settings.value("pythonConsole/autoCompleteSource") == 'fromDoc': self.autoCompFromDoc.setChecked(True) diff --git a/python/console/console_settings.ui b/python/console/console_settings.ui index 501f7de33810..a95715b34490 100644 --- a/python/console/console_settings.ui +++ b/python/console/console_settings.ui @@ -55,7 +55,7 @@ 0 0 739 - 1242 + 1240 @@ -606,40 +606,15 @@ - - - - Embedded Webview (developer tools) - - - - - Default system web browser - - - + - - + + - API + F1 works on hovered words - - - - - PyQGIS - - - - - C++ QGIS - - - - @@ -677,7 +652,6 @@ autoSurround autoInsertImport contextHelpBrowser - contextHelpApi formatOnSave sortImports maxLineLength diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 19add9257295..2c88eaac2c20 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -10779,6 +10779,36 @@ """ # -- Qgis.ColorModel.baseClass = Qgis +# monkey patching scoped based enum +Qgis.DocumentationApi.PyQgis.__doc__ = "PyQgis API documentation" +Qgis.DocumentationApi.PyQgisSearch.__doc__ = "Search in PyQgis API documentation" +Qgis.DocumentationApi.CppQgis.__doc__ = "C++ QGIS API documentation" +Qgis.DocumentationApi.Qt.__doc__ = "Qt API documentation" +Qgis.DocumentationApi.__doc__ = """Documentation Api + +.. versionadded:: 3.42 + +* ``PyQgis``: PyQgis API documentation +* ``PyQgisSearch``: Search in PyQgis API documentation +* ``CppQgis``: C++ QGIS API documentation +* ``Qt``: Qt API documentation + +""" +# -- +Qgis.DocumentationApi.baseClass = Qgis +# monkey patching scoped based enum +Qgis.DocumentationBrowser.DeveloperToolsPanel.__doc__ = "Embedded webview in the DevTools panel" +Qgis.DocumentationBrowser.SystemWebBrowser.__doc__ = "Default system web browser" +Qgis.DocumentationBrowser.__doc__ = """Documentation API browser + +.. versionadded:: 3.42 + +* ``DeveloperToolsPanel``: Embedded webview in the DevTools panel +* ``SystemWebBrowser``: Default system web browser + +""" +# -- +Qgis.DocumentationBrowser.baseClass = Qgis from enum import Enum diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index cfaf28f6283f..554c49ca9c6a 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -3169,6 +3169,20 @@ The development version Cmyk, }; + enum class DocumentationApi + { + PyQgis, + PyQgisSearch, + CppQgis, + Qt, + }; + + enum class DocumentationBrowser + { + DeveloperToolsPanel, + SystemWebBrowser, + }; + static const double DEFAULT_SEARCH_RADIUS_MM; static const float DEFAULT_MAPTOPIXEL_THRESHOLD; diff --git a/python/gui/auto_additions/qgscodeeditor.py b/python/gui/auto_additions/qgscodeeditor.py index d6374e103a41..7c4121878534 100644 --- a/python/gui/auto_additions/qgscodeeditor.py +++ b/python/gui/auto_additions/qgscodeeditor.py @@ -56,7 +56,7 @@ QgsCodeEditor.Flags.baseClass = QgsCodeEditor Flags = QgsCodeEditor # dirty hack since SIP seems to introduce the flags in module try: - QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted whent the F1 key is pressed while hovering over a word\n\n.. versionadded:: 3.42\n'} + QgsCodeEditor.__attribute_docs__ = {'SEARCH_RESULT_INDICATOR': 'Indicator index for search results', 'sessionHistoryCleared': 'Emitted when the history of commands run in the current session is cleared.\n\n.. versionadded:: 3.30\n', 'persistentHistoryCleared': 'Emitted when the persistent history of commands run in the editor is cleared.\n\n.. versionadded:: 3.30\n', 'helpRequested': 'Emitted when documentation was requested for the specified ``word``.\n\n.. versionadded:: 3.42\n'} QgsCodeEditor.languageToString = staticmethod(QgsCodeEditor.languageToString) QgsCodeEditor.defaultColor = staticmethod(QgsCodeEditor.defaultColor) QgsCodeEditor.color = staticmethod(QgsCodeEditor.color) diff --git a/python/gui/auto_generated/codeeditors/qgscodeeditor.sip.in b/python/gui/auto_generated/codeeditors/qgscodeeditor.sip.in index 47847693be0e..f7312489bddd 100644 --- a/python/gui/auto_generated/codeeditors/qgscodeeditor.sip.in +++ b/python/gui/auto_generated/codeeditors/qgscodeeditor.sip.in @@ -520,9 +520,9 @@ Emitted when the persistent history of commands run in the editor is cleared. %End - void helpRequested( QString word ); + void helpRequested( const QString &word ); %Docstring -Emitted whent the F1 key is pressed while hovering over a word +Emitted when documentation was requested for the specified ``word``. .. versionadded:: 3.42 %End diff --git a/python/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in b/python/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in index 1130559bd339..e42a32690ce3 100644 --- a/python/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in +++ b/python/gui/auto_generated/codeeditors/qgscodeeditorpython.sip.in @@ -98,7 +98,7 @@ Searches the selected text in the official PyQGIS online documentation. virtual void showApiDocumentation( const QString &item ); %Docstring -Searches the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. +Displays the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. .. versionadded:: 3.42 %End diff --git a/python/gui/auto_generated/qgisinterface.sip.in b/python/gui/auto_generated/qgisinterface.sip.in index a3ec357aeca3..04d4e289c185 100644 --- a/python/gui/auto_generated/qgisinterface.sip.in +++ b/python/gui/auto_generated/qgisinterface.sip.in @@ -1492,14 +1492,14 @@ Unregister a previously registered tool factory from the development/debugging t .. versionadded:: 3.14 %End - virtual void showApiDocumentation( const QString &api = QStringLiteral( "pyqgis" ), bool embedded = true, const QString &object = QString(), const QString &module = QString() ) = 0; + virtual void showApiDocumentation( Qgis::DocumentationApi api = Qgis::DocumentationApi::PyQgis, Qgis::DocumentationBrowser browser = Qgis::DocumentationBrowser::DeveloperToolsPanel, const QString &object = QString(), const QString &module = QString() ) = 0; %Docstring Show a page of the API documentation -:param api: "pyqgis" or "qgis" or "qt" or "pyqgis-search" -:param embedded: If ``True``, the documentation will be opened in the embedded devtools webview. Otherwise, use system web browser +:param api: Which API to display +:param browser: Web browser used to display the API documentation :param object: object to show in the documentation -:param module: used only if api = "pyqgis" +:param module: used only if api = :py:class:`Qgis`.DocumentationApi.PyQgis .. versionadded:: 3.42 %End diff --git a/src/app/devtools/documentation/qgsdocumentationpanelwidget.cpp b/src/app/devtools/documentation/qgsdocumentationpanelwidget.cpp index 81cefc3c92e3..15841a37e6a6 100644 --- a/src/app/devtools/documentation/qgsdocumentationpanelwidget.cpp +++ b/src/app/devtools/documentation/qgsdocumentationpanelwidget.cpp @@ -27,9 +27,8 @@ QgsDocumentationPanelWidget::QgsDocumentationPanelWidget( QWidget *parent ) { setupUi( this ); - connect( mPythonHomeButton, &QToolButton::clicked, this, [] {QgisApp::instance()->showApiDocumentation( QStringLiteral( "pyqgis" ), true );} ); - connect( mCppHomeButton, &QToolButton::clicked, this, [] {QgisApp::instance()->showApiDocumentation( QStringLiteral( "qgis" ), true );} ); - connect( mQtHomeButton, &QToolButton::clicked, this, [] {QgisApp::instance()->showApiDocumentation( QStringLiteral( "qt" ), true );} ); + connect( mPyQgisHomeButton, &QToolButton::clicked, this, [] {QgisApp::instance()->showApiDocumentation( Qgis::DocumentationApi::PyQgis, Qgis::DocumentationBrowser::DeveloperToolsPanel );} ); + connect( mQtHomeButton, &QToolButton::clicked, this, [] {QgisApp::instance()->showApiDocumentation( Qgis::DocumentationApi::Qt, Qgis::DocumentationBrowser::DeveloperToolsPanel );} ); connect( mOpenUrlButton, &QToolButton::clicked, this, [this] {QgisApp::instance()->openURL( mWebView->url().toString(), false );} ); } diff --git a/src/app/devtools/documentation/qgsdocumentationpanelwidget.h b/src/app/devtools/documentation/qgsdocumentationpanelwidget.h index e0288928a229..76a4f84a326b 100644 --- a/src/app/devtools/documentation/qgsdocumentationpanelwidget.h +++ b/src/app/devtools/documentation/qgsdocumentationpanelwidget.h @@ -21,9 +21,9 @@ /** * \ingroup app * \class QgsDocumentationPanelWidget - * \brief A panel widget showing profiled startup times for debugging. + * \brief A panel widget showing the API documentation. * - * \since QGIS 3.14 + * \since QGIS 3.42 */ class QgsDocumentationPanelWidget : public QgsDevToolWidget, private Ui::QgsDocumentationPanelBase { diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 2c4759bc6431..51ecbabd1137 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -12964,12 +12964,12 @@ void QgisApp::helpContents() void QgisApp::apiDocumentation() { - showApiDocumentation( "qgis", false ); + showApiDocumentation( Qgis::DocumentationApi::CppQgis, Qgis::DocumentationBrowser::SystemWebBrowser ); } void QgisApp::pyQgisApiDocumentation() { - showApiDocumentation( "pyqgis", false ); + showApiDocumentation( Qgis::DocumentationApi::PyQgis, Qgis::DocumentationBrowser::SystemWebBrowser ); } void QgisApp::reportaBug() @@ -13114,93 +13114,9 @@ void QgisApp::unregisterDevToolFactory( QgsDevToolWidgetFactory *factory ) } -void QgisApp::showApiDocumentation( const QString &api, bool embedded, const QString &object, const QString &module ) +void QgisApp::showApiDocumentation( Qgis::DocumentationApi api, Qgis::DocumentationBrowser browser, const QString &object, const QString &module ) { - bool useQgisDocDirectory = false; - QString baseUrl; - QString version; - - if ( api == "qt" ) - { - version = QString( qVersion() ).split( '.' ).mid( 0, 2 ).join( '.' ); - baseUrl = QString( "https://doc.qt.io/qt-%1/" ).arg( version ); - } - else if ( api.contains( "qgis" ) ) - { - if ( Qgis::version().toLower().contains( QStringLiteral( "master" ) ) ) - { - version = QStringLiteral( "master" ); - } - else - { - version = QString( Qgis::version() ).split( '.' ).mid( 0, 2 ).join( '.' ); - } - - if ( api.contains( "pyqgis" ) ) - { - QgsSettings settings; - baseUrl = settings.value( QStringLiteral( "qgis/PyQgisApiUrl" ), - QString( "https://qgis.org/pyqgis/%1/" ).arg( version ) ).toString(); - } - else - { - if ( QFileInfo::exists( QgsApplication::pkgDataPath() + "/doc/api/index.html" ) ) - { - useQgisDocDirectory = true; - baseUrl = "api/"; - } - else - { - QgsSettings settings; - baseUrl = settings.value( QStringLiteral( "qgis/QgisApiUrl" ), - QString( "https://qgis.org/api/%1/" ).arg( version ) ).toString(); - } - } - } - else - { - messageBar()->pushWarning( tr( "Unknown API" ), api ); - return; - } - - QString url; - if ( object.isEmpty() ) - { - url = baseUrl == "api/" ? baseUrl + "index.html" : baseUrl; - } - else - { - if ( api == QStringLiteral( "pyqgis" ) ) - { - url = baseUrl + QString( "%1/%2.html" ).arg( module, object ); - } - else if ( api == QStringLiteral( "pyqgis-search" ) ) - { - url = baseUrl + QString( "search.html?q=%2" ).arg( object ); - } - else if ( api == QStringLiteral( "qgis" ) ) - { - url = baseUrl + QString( "class%1.html" ).arg( object ); - } - else // Qt - { - url = baseUrl + QString( "%1.html" ).arg( object.toLower() ); - } - } - - if ( embedded ) - { - if ( useQgisDocDirectory ) - { - url = "file://" + QgsApplication::pkgDataPath() + "/doc/" + url; - } - mDevToolsDock->show(); - mDevToolsWidget->showUrl( QUrl( url ) ); - } - else - { - openURL( url, useQgisDocDirectory ); - } + mDevToolsWidget->showApiDocumentation( api, browser, object, module ); } void QgisApp::registerApplicationExitBlocker( QgsApplicationExitBlockerInterface *blocker ) diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 38aa74ca3698..34b8e29d21b7 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -799,7 +799,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow void unregisterDevToolFactory( QgsDevToolWidgetFactory *factory ); //! Show a page of the API documentation - void showApiDocumentation( const QString &api, bool embedded, const QString &object = QString(), const QString &module = QString() ); + void showApiDocumentation( Qgis::DocumentationApi api, Qgis::DocumentationBrowser browser, const QString &object = QString(), const QString &module = QString() ); /** * Register a new application exit blocker, which can be used to prevent the QGIS application diff --git a/src/app/qgisappinterface.cpp b/src/app/qgisappinterface.cpp index 9cf91b5bb2d1..ca870fc2040e 100644 --- a/src/app/qgisappinterface.cpp +++ b/src/app/qgisappinterface.cpp @@ -641,9 +641,9 @@ void QgisAppInterface::unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory * qgis->unregisterDevToolFactory( factory ); } -void QgisAppInterface::showApiDocumentation( const QString &api, bool embedded, const QString &object, const QString &module ) +void QgisAppInterface::showApiDocumentation( Qgis::DocumentationApi api, Qgis::DocumentationBrowser browser, const QString &object, const QString &module ) { - qgis->showApiDocumentation( api, embedded, object, module ); + qgis->showApiDocumentation( api, browser, object, module ); } diff --git a/src/app/qgisappinterface.h b/src/app/qgisappinterface.h index 8237d5e9c595..b67407b5d6d9 100644 --- a/src/app/qgisappinterface.h +++ b/src/app/qgisappinterface.h @@ -157,7 +157,7 @@ class APP_EXPORT QgisAppInterface : public QgisInterface void unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) override; void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override; void unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override; - void showApiDocumentation( const QString &api, bool embedded, const QString &object, const QString &module ) override; + void showApiDocumentation( Qgis::DocumentationApi api, Qgis::DocumentationBrowser browser, const QString &object, const QString &module ) override; void registerApplicationExitBlocker( QgsApplicationExitBlockerInterface *blocker ) override; void unregisterApplicationExitBlocker( QgsApplicationExitBlockerInterface *blocker ) override; void registerMapToolHandler( QgsAbstractMapToolHandler *handler ) override; diff --git a/src/app/qgsdevtoolspanelwidget.cpp b/src/app/qgsdevtoolspanelwidget.cpp index 705dedee221f..250b10e7d8c1 100644 --- a/src/app/qgsdevtoolspanelwidget.cpp +++ b/src/app/qgsdevtoolspanelwidget.cpp @@ -19,6 +19,8 @@ #include "qgsdevtoolwidget.h" #include "qgspanelwidgetstack.h" #include "qgssettingsentryimpl.h" +#include "qgsapplication.h" +#include "qgsdockwidget.h" #include "devtools/documentation/qgsdocumentationpanelwidget.h" const QgsSettingsEntryString *QgsDevToolsPanelWidget::settingLastActiveTab = new QgsSettingsEntryString( QStringLiteral( "last-active-tab" ), QgsDevToolsPanelWidget::sTreeDevTools, QString(), QStringLiteral( "Last visible tab in developer tools panel" ) ); @@ -56,7 +58,7 @@ void QgsDevToolsPanelWidget::addToolWidget( QgsDevToolWidget *widget ) QListWidgetItem *item = new QListWidgetItem( widget->windowIcon(), QString() ); item->setToolTip( widget->windowTitle() ); - item->setData( Qt::UserRole, widget->windowTitle() ); + item->setData( Qt::UserRole, widget->objectName() ); mOptionsListWidget->addItem( item ); if ( mOptionsListWidget->count() == 1 ) { @@ -126,8 +128,106 @@ void QgsDevToolsPanelWidget::setCurrentTool( int row ) mStackedWidget->setCurrentIndex( row ); } +void QgsDevToolsPanelWidget::showApiDocumentation( + Qgis::DocumentationApi api, Qgis::DocumentationBrowser browser, const QString &object, const QString &module +) +{ + bool useQgisDocDirectory = false; + QString baseUrl; + QString version; + + if ( api == Qgis::DocumentationApi::Qt ) + { + version = QString( qVersion() ).split( '.' ).mid( 0, 2 ).join( '.' ); + baseUrl = QString( "https://doc.qt.io/qt-%1/" ).arg( version ); + } + else + { + if ( Qgis::version().toLower().contains( QStringLiteral( "master" ) ) ) + { + version = QStringLiteral( "master" ); + } + else + { + version = QString( Qgis::version() ).split( '.' ).mid( 0, 2 ).join( '.' ); + } + + if ( api == Qgis::DocumentationApi::PyQgis || api == Qgis::DocumentationApi::PyQgisSearch ) + { + QgsSettings settings; + baseUrl = settings.value( QStringLiteral( "qgis/PyQgisApiUrl" ), + QString( "https://qgis.org/pyqgis/%1/" ).arg( version ) ).toString(); + } + else + { + if ( QFileInfo::exists( QgsApplication::pkgDataPath() + "/doc/api/index.html" ) ) + { + useQgisDocDirectory = true; + baseUrl = "api/"; + } + else + { + QgsSettings settings; + baseUrl = settings.value( QStringLiteral( "qgis/QgisApiUrl" ), + QString( "https://qgis.org/api/%1/" ).arg( version ) ).toString(); + } + } + } + + + QString url; + if ( object.isEmpty() ) + { + url = baseUrl == "api/" ? baseUrl + "index.html" : baseUrl; + } + else + { + switch ( api ) + { + case Qgis::DocumentationApi::PyQgis: + url = baseUrl + QString( "%1/%2.html" ).arg( module, object ); + break; + case Qgis::DocumentationApi::PyQgisSearch: + url = baseUrl + QString( "search.html?q=%2" ).arg( object ); + break; + case Qgis::DocumentationApi::CppQgis: + url = baseUrl + QString( "class%1.html" ).arg( object ); + break; + case Qgis::DocumentationApi::Qt: + url = baseUrl + QString( "%1.html" ).arg( object.toLower() ); + break; + } + } +#ifndef HAVE_WEBENGINE + // QWebView does not support the search function from the PyQGIS documentation homepage + if ( api == QStringLiteral( "pyqgis-search" ) ) + { + browser = Qgis::DocumentationBrowser::SystemWebBrowser; + } +#endif + + switch ( browser ) + { + case Qgis::DocumentationBrowser::SystemWebBrowser: + QgisApp::instance()->openURL( url, useQgisDocDirectory ); + break; + case Qgis::DocumentationBrowser::DeveloperToolsPanel: + if ( useQgisDocDirectory ) + { + url = "file://" + QgsApplication::pkgDataPath() + "/doc/" + url; + } + if ( QgsDockWidget *dock = QgisApp::instance()->findChild< QgsDockWidget * >( "DevTools" ) ) + { + dock->setUserVisible( true ); + } + showUrl( QUrl( url ) ); + break; + } + +} + void QgsDevToolsPanelWidget::showUrl( const QUrl &url ) { - whileBlocking( mOptionsListWidget )->setCurrentRow( 0 ); + setActiveTab( mDocumentationPanel->objectName() ); mDocumentationPanel->showUrl( url ); } diff --git a/src/app/qgsdevtoolspanelwidget.h b/src/app/qgsdevtoolspanelwidget.h index d35f4677bcf0..4b482fd45433 100644 --- a/src/app/qgsdevtoolspanelwidget.h +++ b/src/app/qgsdevtoolspanelwidget.h @@ -40,6 +40,13 @@ class APP_EXPORT QgsDevToolsPanelWidget : public QWidget, private Ui::QgsDevTool void setActiveTab( const QString &title ); + void showApiDocumentation( + Qgis::DocumentationApi api = Qgis::DocumentationApi::PyQgis, + Qgis::DocumentationBrowser browser = Qgis::DocumentationBrowser::DeveloperToolsPanel, + const QString &object = QString(), + const QString &module = QString() + ); + void showUrl( const QUrl &url ); private slots: @@ -49,7 +56,7 @@ class APP_EXPORT QgsDevToolsPanelWidget : public QWidget, private Ui::QgsDevTool private: QMap< QgsDevToolWidgetFactory *, int> mFactoryPages; - QgsDocumentationPanelWidget *mDocumentationPanel; + QgsDocumentationPanelWidget *mDocumentationPanel = nullptr; }; #endif // QGSDEVTOOLSPANELWIDGET_H diff --git a/src/core/qgis.h b/src/core/qgis.h index 40a0c1affc01..ff24677cc551 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -5573,6 +5573,32 @@ class CORE_EXPORT Qgis }; Q_ENUM( ColorModel ) + /** + * Documentation Api + * + * \since QGIS 3.42 + */ + enum class DocumentationApi : int + { + PyQgis, //!< PyQgis API documentation + PyQgisSearch, //!< Search in PyQgis API documentation + CppQgis, //!< C++ QGIS API documentation + Qt, //!< Qt API documentation + }; + Q_ENUM( DocumentationApi ) + + /** + * Documentation API browser + * + * \since QGIS 3.42 + */ + enum class DocumentationBrowser : int + { + DeveloperToolsPanel, //!< Embedded webview in the DevTools panel + SystemWebBrowser, //!< Default system web browser + }; + Q_ENUM( DocumentationBrowser ) + /** * Identify search radius in mm */ diff --git a/src/gui/codeeditors/qgscodeeditor.cpp b/src/gui/codeeditors/qgscodeeditor.cpp index 9d1fa8b0a39f..bd83094f8250 100644 --- a/src/gui/codeeditors/qgscodeeditor.cpp +++ b/src/gui/codeeditors/qgscodeeditor.cpp @@ -24,6 +24,7 @@ #include "qgscodeeditorhistorydialog.h" #include "qgsstringutils.h" #include "qgsfontutils.h" +#include "qgssettingsentryimpl.h" #include #include @@ -38,6 +39,12 @@ #include #include "Qsci/qscilexer.h" +///@cond PRIVATE +const QgsSettingsEntryBool *QgsCodeEditor::settingContextHelpHover = new QgsSettingsEntryBool( QStringLiteral( "context-help-hover" ), sTreeCodeEditor, false, QStringLiteral( "Whether the context help should works on hovered words" ) ); +///@endcond PRIVATE + + + QMap< QgsCodeEditorColorScheme::ColorRole, QString > QgsCodeEditor::sColorRoleToSettingsKey { {QgsCodeEditorColorScheme::ColorRole::Default, QStringLiteral( "defaultFontColor" ) }, @@ -200,7 +207,7 @@ void QgsCodeEditor::keyPressEvent( QKeyEvent *event ) QString text = selectedText(); // Check if mouse is hovering over a word - if ( text.isEmpty() ) + if ( text.isEmpty() && settingContextHelpHover->value() ) { text = wordAtPoint( mapFromGlobal( QCursor::pos() ) ); } diff --git a/src/gui/codeeditors/qgscodeeditor.h b/src/gui/codeeditors/qgscodeeditor.h index dc8bf185583f..21008cbd85d6 100644 --- a/src/gui/codeeditors/qgscodeeditor.h +++ b/src/gui/codeeditors/qgscodeeditor.h @@ -33,6 +33,7 @@ class QgsFilterLineEdit; class QToolButton; class QCheckBox; +class QgsSettingsEntryBool; SIP_IF_MODULE( HAVE_QSCI_SIP ) @@ -107,6 +108,7 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla #ifndef SIP_RUN static inline QgsSettingsTreeNode *sTreeCodeEditor = QgsSettingsTree::sTreeGui->createChildNode( QStringLiteral( "code-editor" ) ); + static const QgsSettingsEntryBool *settingContextHelpHover; #endif /** @@ -553,11 +555,11 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla /** - * Emitted whent the F1 key is pressed while hovering over a word + * Emitted when documentation was requested for the specified \a word. * * \since QGIS 3.42 */ - void helpRequested( QString word ); + void helpRequested( const QString &word ); protected: diff --git a/src/gui/codeeditors/qgscodeeditorpython.cpp b/src/gui/codeeditors/qgscodeeditorpython.cpp index b2309cf386da..078026aeb287 100644 --- a/src/gui/codeeditors/qgscodeeditorpython.cpp +++ b/src/gui/codeeditors/qgscodeeditorpython.cpp @@ -22,6 +22,7 @@ #include "qgspythonrunner.h" #include "qgsprocessingutils.h" #include "qgssettingsentryimpl.h" +#include "qgssettingsentryenumflag.h" #include "qgssettings.h" #include #include @@ -52,8 +53,7 @@ const QgsSettingsEntryBool *QgsCodeEditorPython::settingSortImports = new QgsSet const QgsSettingsEntryInteger *QgsCodeEditorPython::settingAutopep8Level = new QgsSettingsEntryInteger( QStringLiteral( "autopep8-level" ), sTreePythonCodeEditor, 1, QStringLiteral( "Autopep8 aggressive level" ) ); const QgsSettingsEntryBool *QgsCodeEditorPython::settingBlackNormalizeQuotes = new QgsSettingsEntryBool( QStringLiteral( "black-normalize-quotes" ), sTreePythonCodeEditor, true, QStringLiteral( "Whether quotes should be normalized when auto-formatting code using black" ) ); const QgsSettingsEntryString *QgsCodeEditorPython::settingExternalPythonEditorCommand = new QgsSettingsEntryString( QStringLiteral( "external-editor" ), sTreePythonCodeEditor, QString(), QStringLiteral( "Command to launch an external Python code editor. Use the token to insert the filename, to insert line number, and to insert the column number." ) ); -const QgsSettingsEntryBool *QgsCodeEditorPython::settingContextHelpEmbedded = new QgsSettingsEntryBool( QStringLiteral( "context-help-embedded" ), sTreePythonCodeEditor, true, QStringLiteral( "Whether the context help should be displayed in an embedded webview in the devtools panel" ) ); -const QgsSettingsEntryBool *QgsCodeEditorPython::settingContextHelpPyQgis = new QgsSettingsEntryBool( QStringLiteral( "context-help-pyqgis" ), sTreePythonCodeEditor, true, QStringLiteral( "Whether the context help should use the PyQGIS api instead of the C++ API" ) ); +const QgsSettingsEntryEnumFlag< Qgis::DocumentationBrowser > *QgsCodeEditorPython::settingContextHelpBrowser = new QgsSettingsEntryEnumFlag< Qgis::DocumentationBrowser >( QStringLiteral( "context-help-browser" ), sTreePythonCodeEditor, Qgis::DocumentationBrowser::DeveloperToolsPanel, QStringLiteral( "Web browser used to display the api documentation" ) ); ///@endcond PRIVATE @@ -730,35 +730,25 @@ void QgsCodeEditorPython::showApiDocumentation( const QString &text ) { QString searchText = text; searchText = searchText.replace( QLatin1String( ">>> " ), QString() ).replace( QLatin1String( "... " ), QString() ).trimmed(); // removing prompts - QRegularExpression qgisExpression( "^Qgs[A-Z][a-zA-Z]" ); QRegularExpression qtExpression( "^Q[A-Z][a-zA-Z]" ); - bool pyQgis = QgsCodeEditorPython::settingContextHelpPyQgis->value(); - - const QString qgisVersion = QString( Qgis::version() ).split( '.' ).mid( 0, 2 ).join( '.' ); - const QString qtVersion = QString( qVersion() ).split( '.' ).mid( 0, 2 ).join( '.' ); - - QgsSettings settings; - - if ( qgisExpression.match( searchText ).hasMatch() ) - { - if ( !pyQgis ) - { - - QString baseUrl = settings.value( QStringLiteral( "qgis/QgisApiUrl" ), - QString( "https://qgis.org/api/%1" ).arg( qgisVersion ) ).toString(); - QDesktopServices::openUrl( QUrl( QString( "%1/class%2.html" ).arg( baseUrl, searchText ) ) ); - return; - } - } - else if ( qtExpression.match( searchText ).hasMatch() ) + if ( qtExpression.match( searchText ).hasMatch() ) { + const QString qtVersion = QString( qVersion() ).split( '.' ).mid( 0, 2 ).join( '.' ); QString baseUrl = QString( "https://doc.qt.io/qt-%1" ).arg( qtVersion ); QDesktopServices::openUrl( QUrl( QStringLiteral( "%1/%2.html" ).arg( baseUrl, searchText.toLower() ) ) ); return; } - QDesktopServices::openUrl( QUrl( QStringLiteral( "https://qgis.org/pyqgis/%1/search.html?q=%2" ).arg( qgisVersion, searchText ) ) ); + const QString qgisVersion = QString( Qgis::version() ).split( '.' ).mid( 0, 2 ).join( '.' ); + if ( searchText.isEmpty() ) + { + QDesktopServices::openUrl( QUrl( QStringLiteral( "https://qgis.org/pyqgis/%1/" ).arg( qgisVersion ) ) ); + } + else + { + QDesktopServices::openUrl( QUrl( QStringLiteral( "https://qgis.org/pyqgis/%1/search.html?q=%2" ).arg( qgisVersion, searchText ) ) ); + } } void QgsCodeEditorPython::toggleComment() diff --git a/src/gui/codeeditors/qgscodeeditorpython.h b/src/gui/codeeditors/qgscodeeditorpython.h index 50d3a2e4c369..f0c9efc6bc9e 100644 --- a/src/gui/codeeditors/qgscodeeditorpython.h +++ b/src/gui/codeeditors/qgscodeeditorpython.h @@ -23,6 +23,7 @@ class QgsSettingsEntryInteger; class QgsSettingsEntryBool; +template class QgsSettingsEntryEnumFlag; SIP_IF_MODULE( HAVE_QSCI_SIP ) @@ -62,8 +63,7 @@ class GUI_EXPORT QgsCodeEditorPython : public QgsCodeEditor static const QgsSettingsEntryInteger *settingAutopep8Level; static const QgsSettingsEntryBool *settingBlackNormalizeQuotes; static const QgsSettingsEntryString *settingExternalPythonEditorCommand; - static const QgsSettingsEntryBool *settingContextHelpEmbedded; - static const QgsSettingsEntryBool *settingContextHelpPyQgis; + static const QgsSettingsEntryEnumFlag< Qgis::DocumentationBrowser > *settingContextHelpBrowser; ///@endcond PRIVATE #endif @@ -132,7 +132,7 @@ class GUI_EXPORT QgsCodeEditorPython : public QgsCodeEditor void searchSelectedTextInPyQGISDocs(); /** - * Searches the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. + * Displays the given text in the official APIs (PyQGIS, C++ QGIS or Qt) documentation. * * \since QGIS 3.42 */ diff --git a/src/gui/qgisinterface.h b/src/gui/qgisinterface.h index c2603b627d4f..4c454e6c3ba2 100644 --- a/src/gui/qgisinterface.h +++ b/src/gui/qgisinterface.h @@ -1282,13 +1282,13 @@ class GUI_EXPORT QgisInterface : public QObject /** * Show a page of the API documentation - * \param api "pyqgis" or "qgis" or "qt" or "pyqgis-search" - * \param embedded If TRUE, the documentation will be opened in the embedded devtools webview. Otherwise, use system web browser + * \param api Which API to display + * \param browser Web browser used to display the API documentation * \param object object to show in the documentation - * \param module used only if api = "pyqgis" + * \param module used only if api = Qgis::DocumentationApi::PyQgis * \since QGIS 3.42 */ - virtual void showApiDocumentation( const QString &api = QStringLiteral( "pyqgis" ), bool embedded = true, const QString &object = QString(), const QString &module = QString() ) = 0; + virtual void showApiDocumentation( Qgis::DocumentationApi api = Qgis::DocumentationApi::PyQgis, Qgis::DocumentationBrowser browser = Qgis::DocumentationBrowser::DeveloperToolsPanel, const QString &object = QString(), const QString &module = QString() ) = 0; /** * Register a new application exit blocker, which can be used to prevent the QGIS application diff --git a/src/ui/qgsdocumentationpanelbase.ui b/src/ui/qgsdocumentationpanelbase.ui index a32d940998a9..409e3a3c9f18 100644 --- a/src/ui/qgsdocumentationpanelbase.ui +++ b/src/ui/qgsdocumentationpanelbase.ui @@ -21,27 +21,10 @@ - + PyQGIS API Documentation - - - :/images/themes/default/mIconPythonFile.svg:/images/themes/default/mIconPythonFile.svg - - - - 24 - 24 - - - - - - - - C++ API documentation - :/images/icons/qgis_icon.svg:/images/icons/qgis_icon.svg @@ -52,6 +35,9 @@ 24 + + true + @@ -69,6 +55,9 @@ 24 + + true + @@ -99,6 +88,9 @@ 24 + + true +