From 6ec7f02e83524e798a9b921cc4f467a76f5e09b0 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 27 Oct 2018 10:38:06 +1000 Subject: [PATCH] Add a QgsDataItemGuiProvider interface and registry for providers These providers will be used to control how the browser data items behave within GUI, and to allow separation of GUI related properties of browser items from the core code. A new registry QgsDataItemGuiProviderRegistry has been created (modeled off QgsDataItemProviderRegistry), with an application wide instance available from QgsGui::instance()->dataItemGuiProviderRegistry() --- .../qgsdataitemproviderregistry.sip.in | 8 +- .../qgsdataitemguiprovider.sip.in | 44 +++++++++++ .../qgsdataitemguiproviderregistry.sip.in | 61 +++++++++++++++ python/gui/auto_generated/qgsgui.sip.in | 8 ++ python/gui/gui_auto.sip | 2 + src/core/qgsdataitemproviderregistry.h | 16 +++- src/gui/CMakeLists.txt | 4 + src/gui/qgsdataitemguiprovider.cpp | 18 +++++ src/gui/qgsdataitemguiprovider.h | 47 ++++++++++++ src/gui/qgsdataitemguiproviderregistry.cpp | 38 ++++++++++ src/gui/qgsdataitemguiproviderregistry.h | 76 +++++++++++++++++++ src/gui/qgsgui.cpp | 8 ++ src/gui/qgsgui.h | 9 +++ tests/src/python/CMakeLists.txt | 1 + .../test_qgsdataitemguiproviderregistry.py | 70 +++++++++++++++++ .../test_qgsdataitemproviderregistry.py | 2 +- 16 files changed, 404 insertions(+), 8 deletions(-) create mode 100644 python/gui/auto_generated/qgsdataitemguiprovider.sip.in create mode 100644 python/gui/auto_generated/qgsdataitemguiproviderregistry.sip.in create mode 100644 src/gui/qgsdataitemguiprovider.cpp create mode 100644 src/gui/qgsdataitemguiprovider.h create mode 100644 src/gui/qgsdataitemguiproviderregistry.cpp create mode 100644 src/gui/qgsdataitemguiproviderregistry.h create mode 100644 tests/src/python/test_qgsdataitemguiproviderregistry.py diff --git a/python/core/auto_generated/qgsdataitemproviderregistry.sip.in b/python/core/auto_generated/qgsdataitemproviderregistry.sip.in index 4ee4e537971..96c81ec5fd4 100644 --- a/python/core/auto_generated/qgsdataitemproviderregistry.sip.in +++ b/python/core/auto_generated/qgsdataitemproviderregistry.sip.in @@ -34,17 +34,19 @@ QgsDataItemProviderRegistry is not usually directly created, but rather accessed QList providers() const; %Docstring -Gets list of available providers +Returns the list of available providers. %End void addProvider( QgsDataItemProvider *provider /Transfer/ ); %Docstring -Add a provider implementation. Takes ownership of the object. +Adds a ``provider`` implementation to the registry. Ownership of the provider +is transferred to the registry. %End void removeProvider( QgsDataItemProvider *provider ); %Docstring -Remove provider implementation from the list (provider object is deleted) +Removes a ``provider`` implementation from the registry. +The provider object is automatically deleted. %End private: diff --git a/python/gui/auto_generated/qgsdataitemguiprovider.sip.in b/python/gui/auto_generated/qgsdataitemguiprovider.sip.in new file mode 100644 index 00000000000..192295ec32e --- /dev/null +++ b/python/gui/auto_generated/qgsdataitemguiprovider.sip.in @@ -0,0 +1,44 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdataitemguiprovider.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + +class QgsDataItemGuiProvider +{ +%Docstring + +Abstract base class for providers which affect how QgsDataItem items behave +within the application GUI. + +Providers must be registered via QgsDataItemGuiProviderRegistry. + +.. versionadded:: 3.6 +%End + +%TypeHeaderCode +#include "qgsdataitemguiprovider.h" +%End + public: + + virtual ~QgsDataItemGuiProvider(); + + virtual QString name() = 0; +%Docstring +Returns the provider's name. +%End + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdataitemguiprovider.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/qgsdataitemguiproviderregistry.sip.in b/python/gui/auto_generated/qgsdataitemguiproviderregistry.sip.in new file mode 100644 index 00000000000..3c54c0d8846 --- /dev/null +++ b/python/gui/auto_generated/qgsdataitemguiproviderregistry.sip.in @@ -0,0 +1,61 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdataitemguiproviderregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + +class QgsDataItemGuiProviderRegistry +{ +%Docstring +This class keeps a list of data item GUI providers that may affect how QgsDataItems +behave within the application GUI. + +QgsDataItemGuiProviderRegistry is not usually directly created, but rather accessed through +QgsGui.instance()->dataItemGuiProviderRegistry(). + +.. versionadded:: 3.6 +%End + +%TypeHeaderCode +#include "qgsdataitemguiproviderregistry.h" +%End + public: + + QgsDataItemGuiProviderRegistry(); + + ~QgsDataItemGuiProviderRegistry(); + + + QList providers() const; +%Docstring +Returns the list of available providers. +%End + + void addProvider( QgsDataItemGuiProvider *provider /Transfer/ ); +%Docstring +Adds a ``provider`` implementation to the registry. Ownership of the provider +is transferred to the registry. +%End + + void removeProvider( QgsDataItemGuiProvider *provider ); +%Docstring +Removes a ``provider`` implementation from the registry. +The provider object is automatically deleted. +%End + + private: + QgsDataItemGuiProviderRegistry( const QgsDataItemGuiProviderRegistry &rh ); +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsdataitemguiproviderregistry.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/auto_generated/qgsgui.sip.in b/python/gui/auto_generated/qgsgui.sip.in index 1ac8edd1fb4..6e310187382 100644 --- a/python/gui/auto_generated/qgsgui.sip.in +++ b/python/gui/auto_generated/qgsgui.sip.in @@ -74,6 +74,14 @@ Returns the global processing gui registry, used for registering the GUI behavio Returns the global processing recent algorithm log, used for tracking recently used processing algorithms. .. versionadded:: 3.4 +%End + + static QgsDataItemGuiProviderRegistry *dataItemGuiProviderRegistry(); +%Docstring +Returns the global data item GUI provider registry, used for tracking providers which affect the browser +GUI. + +.. versionadded:: 3.6 %End static void enableAutoGeometryRestore( QWidget *widget, const QString &key = QString() ); diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip index fed01fb6f7c..1e952467c33 100644 --- a/python/gui/gui_auto.sip +++ b/python/gui/gui_auto.sip @@ -1,5 +1,7 @@ // Include auto-generated SIP files %Include auto_generated/qgsattributeforminterface.sip +%Include auto_generated/qgsdataitemguiprovider.sip +%Include auto_generated/qgsdataitemguiproviderregistry.sip %Include auto_generated/qgsdetaileditemdata.sip %Include auto_generated/qgsexpressionbuilderdialog.sip %Include auto_generated/qgsgeometryrubberband.sip diff --git a/src/core/qgsdataitemproviderregistry.h b/src/core/qgsdataitemproviderregistry.h index 270225dceac..538cdf491c0 100644 --- a/src/core/qgsdataitemproviderregistry.h +++ b/src/core/qgsdataitemproviderregistry.h @@ -46,13 +46,21 @@ class CORE_EXPORT QgsDataItemProviderRegistry //! QgsDataItemProviderRegistry cannot be copied. QgsDataItemProviderRegistry &operator=( const QgsDataItemProviderRegistry &rh ) = delete; - //! Gets list of available providers + /** + * Returns the list of available providers. + */ QList providers() const { return mProviders; } - //! Add a provider implementation. Takes ownership of the object. + /** + * Adds a \a provider implementation to the registry. Ownership of the provider + * is transferred to the registry. + */ void addProvider( QgsDataItemProvider *provider SIP_TRANSFER ); - //! Remove provider implementation from the list (provider object is deleted) + /** + * Removes a \a provider implementation from the registry. + * The provider object is automatically deleted. + */ void removeProvider( QgsDataItemProvider *provider ); private: @@ -60,7 +68,7 @@ class CORE_EXPORT QgsDataItemProviderRegistry QgsDataItemProviderRegistry( const QgsDataItemProviderRegistry &rh ); #endif - //! available providers. this class owns the pointers + //! Available providers, owned by this class QList mProviders; }; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 7d006bc59c0..3602090d004 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -243,6 +243,8 @@ SET(QGIS_GUI_SRCS qgscredentialdialog.cpp qgscustomdrophandler.cpp qgscurveeditorwidget.cpp + qgsdataitemguiprovider.cpp + qgsdataitemguiproviderregistry.cpp qgsdatumtransformdialog.cpp qgsdatasourceselectdialog.cpp qgsdetaileditemdata.cpp @@ -767,6 +769,8 @@ ENDIF(MSVC) SET(QGIS_GUI_HDRS qgsattributeforminterface.h qgsattributeformlegacyinterface.h + qgsdataitemguiprovider.h + qgsdataitemguiproviderregistry.h qgsdetaileditemdata.h qgsexpressionbuilderdialog.h qgsgeometryrubberband.h diff --git a/src/gui/qgsdataitemguiprovider.cpp b/src/gui/qgsdataitemguiprovider.cpp new file mode 100644 index 00000000000..c4afbe9a2fa --- /dev/null +++ b/src/gui/qgsdataitemguiprovider.cpp @@ -0,0 +1,18 @@ +/*************************************************************************** + qgsdataitemguiprovider.cpp + -------------------------------------- + Date : October 2018 + Copyright : (C) 2018 by Nyall Dawson + Email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsdataitemguiprovider.h" + +// no implementation currently diff --git a/src/gui/qgsdataitemguiprovider.h b/src/gui/qgsdataitemguiprovider.h new file mode 100644 index 00000000000..18ab8b4e927 --- /dev/null +++ b/src/gui/qgsdataitemguiprovider.h @@ -0,0 +1,47 @@ +/*************************************************************************** + qgsdataitemguiprovider.h + -------------------------------------- + Date : October 2018 + Copyright : (C) 2018 by Nyall Dawson + Email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSDATAITEMGUIPROVIDER_H +#define QGSDATAITEMGUIPROVIDER_H + +#include "qgis_gui.h" + +class QString; + +/** + * \class QgsDataItemGuiProvider + * \ingroup gui + * + * Abstract base class for providers which affect how QgsDataItem items behave + * within the application GUI. + * + * Providers must be registered via QgsDataItemGuiProviderRegistry. + * + * \since QGIS 3.6 + */ +class GUI_EXPORT QgsDataItemGuiProvider +{ + public: + + virtual ~QgsDataItemGuiProvider() = default; + + /** + * Returns the provider's name. + */ + virtual QString name() = 0; + +}; + +#endif // QGSDATAITEMGUIPROVIDER_H diff --git a/src/gui/qgsdataitemguiproviderregistry.cpp b/src/gui/qgsdataitemguiproviderregistry.cpp new file mode 100644 index 00000000000..f12dc568b90 --- /dev/null +++ b/src/gui/qgsdataitemguiproviderregistry.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + qgsdataitemguiproviderregistry.cpp + -------------------------------------- + Date : October 2018 + Copyright : (C) 2018 by Nyall Dawson + Email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsdataitemguiproviderregistry.h" +#include "qgsdataitemguiprovider.h" + +QgsDataItemGuiProviderRegistry::QgsDataItemGuiProviderRegistry() +{ +} + +QgsDataItemGuiProviderRegistry::~QgsDataItemGuiProviderRegistry() +{ + qDeleteAll( mProviders ); +} + +void QgsDataItemGuiProviderRegistry::addProvider( QgsDataItemGuiProvider *provider ) +{ + mProviders.append( provider ); +} + +void QgsDataItemGuiProviderRegistry::removeProvider( QgsDataItemGuiProvider *provider ) +{ + int index = mProviders.indexOf( provider ); + if ( index >= 0 ) + delete mProviders.takeAt( index ); +} diff --git a/src/gui/qgsdataitemguiproviderregistry.h b/src/gui/qgsdataitemguiproviderregistry.h new file mode 100644 index 00000000000..f8b2ff62415 --- /dev/null +++ b/src/gui/qgsdataitemguiproviderregistry.h @@ -0,0 +1,76 @@ +/*************************************************************************** + qgsdataitemguiproviderregistry.h + -------------------------------------- + Date : October 2018 + Copyright : (C) 2018 by Nyall Dawson + Email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSDATAITEMGUIPROVIDERREGISTRY_H +#define QGSDATAITEMGUIPROVIDERREGISTRY_H + +#include "qgis_gui.h" +#include "qgis_sip.h" +#include + +class QgsDataItemGuiProvider; + +/** + * \class QgsDataItemGuiProviderRegistry + * \ingroup gui + * This class keeps a list of data item GUI providers that may affect how QgsDataItems + * behave within the application GUI. + * + * QgsDataItemGuiProviderRegistry is not usually directly created, but rather accessed through + * QgsGui::instance()->dataItemGuiProviderRegistry(). + * + * \since QGIS 3.6 + */ +class GUI_EXPORT QgsDataItemGuiProviderRegistry +{ + public: + + QgsDataItemGuiProviderRegistry(); + + ~QgsDataItemGuiProviderRegistry(); + + //! QgsDataItemGuiProviderRegistry cannot be copied. + QgsDataItemGuiProviderRegistry( const QgsDataItemGuiProviderRegistry &rh ) = delete; + //! QgsDataItemGuiProviderRegistry cannot be copied. + QgsDataItemGuiProviderRegistry &operator=( const QgsDataItemGuiProviderRegistry &rh ) = delete; + + /** + * Returns the list of available providers. + */ + QList providers() const { return mProviders; } + + /** + * Adds a \a provider implementation to the registry. Ownership of the provider + * is transferred to the registry. + */ + void addProvider( QgsDataItemGuiProvider *provider SIP_TRANSFER ); + + /** + * Removes a \a provider implementation from the registry. + * The provider object is automatically deleted. + */ + void removeProvider( QgsDataItemGuiProvider *provider ); + + private: +#ifdef SIP_RUN + QgsDataItemGuiProviderRegistry( const QgsDataItemGuiProviderRegistry &rh ); +#endif + + //! Available providers, owned by this class + QList mProviders; + +}; + +#endif // QGSDATAITEMGUIPROVIDERREGISTRY_H diff --git a/src/gui/qgsgui.cpp b/src/gui/qgsgui.cpp index d9cb507d824..1c792518097 100644 --- a/src/gui/qgsgui.cpp +++ b/src/gui/qgsgui.cpp @@ -43,6 +43,7 @@ #include "qgsprocessingrecentalgorithmlog.h" #include "qgswindowmanagerinterface.h" #include "qgssettings.h" +#include "qgsdataitemguiproviderregistry.h" QgsGui *QgsGui::instance() { @@ -95,6 +96,11 @@ QgsProcessingRecentAlgorithmLog *QgsGui::processingRecentAlgorithmLog() return instance()->mProcessingRecentAlgorithmLog; } +QgsDataItemGuiProviderRegistry *QgsGui::dataItemGuiProviderRegistry() +{ + return instance()->mDataItemGuiProviderRegistry; +} + void QgsGui::enableAutoGeometryRestore( QWidget *widget, const QString &key ) { if ( widget->objectName().isEmpty() ) @@ -130,6 +136,7 @@ QgsGui::HigFlags QgsGui::higFlags() QgsGui::~QgsGui() { delete mProcessingGuiRegistry; + delete mDataItemGuiProviderRegistry; delete mProcessingRecentAlgorithmLog; delete mLayoutItemGuiRegistry; delete mLayerTreeEmbeddedWidgetRegistry; @@ -168,4 +175,5 @@ QgsGui::QgsGui() mWidgetStateHelper = new QgsWidgetStateHelper(); mProcessingRecentAlgorithmLog = new QgsProcessingRecentAlgorithmLog(); mProcessingGuiRegistry = new QgsProcessingGuiRegistry(); + mDataItemGuiProviderRegistry = new QgsDataItemGuiProviderRegistry(); } diff --git a/src/gui/qgsgui.h b/src/gui/qgsgui.h index 779339f66dd..7206116c77d 100644 --- a/src/gui/qgsgui.h +++ b/src/gui/qgsgui.h @@ -34,6 +34,7 @@ class QgsWidgetStateHelper; class QgsProcessingGuiRegistry; class QgsProcessingRecentAlgorithmLog; class QgsWindowManagerInterface; +class QgsDataItemGuiProviderRegistry; /** * \ingroup gui @@ -105,6 +106,13 @@ class GUI_EXPORT QgsGui */ static QgsProcessingRecentAlgorithmLog *processingRecentAlgorithmLog(); + /** + * Returns the global data item GUI provider registry, used for tracking providers which affect the browser + * GUI. + * \since QGIS 3.6 + */ + static QgsDataItemGuiProviderRegistry *dataItemGuiProviderRegistry(); + /** * Register the widget to allow its position to be automatically saved and restored when open and closed. * Use this to avoid needing to call saveGeometry() and restoreGeometry() on your widget. @@ -158,6 +166,7 @@ class GUI_EXPORT QgsGui QgsLayoutItemGuiRegistry *mLayoutItemGuiRegistry = nullptr; QgsProcessingGuiRegistry *mProcessingGuiRegistry = nullptr; QgsProcessingRecentAlgorithmLog *mProcessingRecentAlgorithmLog = nullptr; + QgsDataItemGuiProviderRegistry *mDataItemGuiProviderRegistry = nullptr; std::unique_ptr< QgsWindowManagerInterface > mWindowManager; #ifdef SIP_RUN diff --git a/tests/src/python/CMakeLists.txt b/tests/src/python/CMakeLists.txt index 1d78fe816da..de110c46e42 100644 --- a/tests/src/python/CMakeLists.txt +++ b/tests/src/python/CMakeLists.txt @@ -34,6 +34,7 @@ ADD_PYTHON_TEST(PyQgsCoordinateTransformContext test_qgscoordinatetransformconte ADD_PYTHON_TEST(PyQgsDefaultValue test_qgsdefaultvalue.py) ADD_PYTHON_TEST(PyQgsXmlUtils test_qgsxmlutils.py) ADD_PYTHON_TEST(PyQgsCoordinateTransform test_qgscoordinatetransform.py) +ADD_PYTHON_TEST(PyQgsDataItemGuiProviderRegistry test_qgsdataitemguiproviderregistry.py) ADD_PYTHON_TEST(PyQgsDataItemProviderRegistry test_qgsdataitemproviderregistry.py) ADD_PYTHON_TEST(PyQgsDateTimeEdit test_qgsdatetimeedit.py) ADD_PYTHON_TEST(PyQgsDateTimeStatisticalSummary test_qgsdatetimestatisticalsummary.py) diff --git a/tests/src/python/test_qgsdataitemguiproviderregistry.py b/tests/src/python/test_qgsdataitemguiproviderregistry.py new file mode 100644 index 00000000000..eff0158984b --- /dev/null +++ b/tests/src/python/test_qgsdataitemguiproviderregistry.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +"""QGIS Unit tests for QgsDataItemGuiProviderRegistry + +.. 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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +""" +__author__ = 'Nyall Dawson' +__date__ = '27/10/2018' +__copyright__ = 'Copyright 2018, The QGIS Project' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +import qgis # NOQA + +from qgis.gui import (QgsGui, + QgsDataItemGuiProvider, + QgsDataItemGuiProviderRegistry) +from qgis.testing import start_app, unittest + +app = start_app() + + +class TestProvider(QgsDataItemGuiProvider): + + def __init__(self, name): + super().__init__() + self._name = name + + def name(self): + return self._name + + +class TestQgsDataItemGuiProviderRegistry(unittest.TestCase): + + def testAppRegistry(self): + # ensure there is an application instance + self.assertIsNotNone(QgsGui.dataItemGuiProviderRegistry()) + + def testRegistry(self): + registry = QgsDataItemGuiProviderRegistry() + initial_providers = registry.providers() + + # add a new provider + p1 = TestProvider('p1') + registry.addProvider(p1) + self.assertIn(p1, registry.providers()) + + p2 = TestProvider('p2') + registry.addProvider(p2) + self.assertIn(p1, registry.providers()) + self.assertIn(p2, registry.providers()) + + registry.removeProvider(None) + p3 = TestProvider('p3') + # not in registry yet + registry.removeProvider(p3) + + registry.removeProvider(p1) + self.assertNotIn('p1', [p.name() for p in registry.providers()]) + self.assertIn(p2, registry.providers()) + + registry.removeProvider(p2) + self.assertNotIn('p2', [p.name() for p in registry.providers()]) + self.assertEqual(registry.providers(), initial_providers) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/src/python/test_qgsdataitemproviderregistry.py b/tests/src/python/test_qgsdataitemproviderregistry.py index f476c297422..f65f6d62ac9 100644 --- a/tests/src/python/test_qgsdataitemproviderregistry.py +++ b/tests/src/python/test_qgsdataitemproviderregistry.py @@ -73,7 +73,7 @@ class TestQgsDataItemProviderRegistry(unittest.TestCase): registry.removeProvider(p2) self.assertNotIn('p2', [p.name() for p in registry.providers()]) self.assertEqual(registry.providers(), initial_providers) - + if __name__ == '__main__': unittest.main()