diff --git a/python/gui/auto_generated/qgisinterface.sip.in b/python/gui/auto_generated/qgisinterface.sip.in index fa03eb23571f..c56c47b0c061 100644 --- a/python/gui/auto_generated/qgisinterface.sip.in +++ b/python/gui/auto_generated/qgisinterface.sip.in @@ -986,6 +986,14 @@ Opens the options dialog. The ``currentPage`` argument can be used to force the dialog to open at a specific page. .. versionadded:: 3.0 +%End + + virtual void showProjectPropertiesDialog( const QString ¤tPage = QString() ) = 0; +%Docstring +Opens the project properties dialog. The ``currentPage`` argument can be used to force +the dialog to open at a specific page. + +.. versionadded:: 3.16 %End virtual void buildStyleSheet( const QMap &opts ) = 0; @@ -1176,6 +1184,33 @@ Unregister a previously registered tab in the options dialog. .. seealso:: :py:func:`registerOptionsWidgetFactory` .. versionadded:: 3.0 +%End + + virtual void registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0; +%Docstring +Register a new tab in the project properties dialog. + +.. note:: + + Ownership of the factory is not transferred, and the factory must + be unregistered when plugin is unloaded. + +.. seealso:: :py:class:`QgsOptionsWidgetFactory` + +.. seealso:: :py:func:`unregisterProjectPropertiesWidgetFactory` + +.. versionadded:: 3.16 +%End + + virtual void unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0; +%Docstring +Unregister a previously registered tab in the options dialog. + +.. seealso:: :py:class:`QgsOptionsWidgetFactory` + +.. seealso:: :py:func:`registerProjectPropertiesWidgetFactory` + +.. versionadded:: 3.16 %End virtual void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) = 0; diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 590f2153670f..cd2d42982334 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -12179,6 +12179,17 @@ QMap< QString, QString > QgisApp::projectPropertiesPagesMap() sProjectPropertiesPagesMap.insert( QCoreApplication::translate( "QgsProjectPropertiesBase", "Temporal" ), QStringLiteral( "mTemporalOptions" ) ); } ); + int idx = sProjectPropertiesPagesMap.count(); + for ( const QPointer< QgsOptionsWidgetFactory > &f : qgis::as_const( mProjectPropertiesWidgetFactories ) ) + { + // remove any deleted factories + if ( f ) + { + sProjectPropertiesPagesMap.insert( f->title(), f->title() ); + } + idx++; + } + return sProjectPropertiesPagesMap; } @@ -12620,6 +12631,16 @@ void QgisApp::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) mOptionsWidgetFactories.removeAll( factory ); } +void QgisApp::registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) +{ + mProjectPropertiesWidgetFactories << factory; +} + +void QgisApp::unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) +{ + mProjectPropertiesWidgetFactories.removeAll( factory ); +} + void QgisApp::registerDevToolFactory( QgsDevToolWidgetFactory *factory ) { mDevToolFactories << factory; @@ -14115,7 +14136,16 @@ void QgisApp::projectProperties( const QString ¤tPage ) // dialog results in the construction of the spatial reference // system QMap QApplication::setOverrideCursor( Qt::WaitCursor ); - QgsProjectProperties *pp = new QgsProjectProperties( mMapCanvas, this ); + + QList< QgsOptionsWidgetFactory * > factories; + const auto constProjectPropertiesWidgetFactories = mProjectPropertiesWidgetFactories; + for ( const QPointer< QgsOptionsWidgetFactory > &f : constProjectPropertiesWidgetFactories ) + { + if ( f ) + factories << f; + } + QgsProjectProperties *pp = new QgsProjectProperties( mMapCanvas, this, QgsGuiUtils::ModalDialogFlags, factories ); + // if called from the status bar, show the projection tab if ( mShowProjectionTab ) { diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 62d5d33f49ea..45039581443a 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -733,6 +733,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow //! Unregister a previously registered tab in the options dialog void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ); + //! Register a new tab in the project properties dialog + void registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ); + + //! Unregister a previously registered tab in the project properties dialog + void unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ); + //! Register a dev tool factory void registerDevToolFactory( QgsDevToolWidgetFactory *factory ); @@ -2555,6 +2561,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow QList mMapLayerPanelFactories; QList> mOptionsWidgetFactories; + QList> mProjectPropertiesWidgetFactories; QList mDevToolFactories; diff --git a/src/app/qgisappinterface.cpp b/src/app/qgisappinterface.cpp index dde798f9fa48..823e576c03d3 100644 --- a/src/app/qgisappinterface.cpp +++ b/src/app/qgisappinterface.cpp @@ -445,6 +445,11 @@ void QgisAppInterface::showOptionsDialog( QWidget *parent, const QString ¤ return qgis->showOptionsDialog( parent, currentPage ); } +void QgisAppInterface::showProjectPropertiesDialog( const QString ¤tPage ) +{ + return qgis->showProjectProperties( currentPage ); +} + QMap QgisAppInterface::defaultStyleSheetOptions() { return qgis->styleSheetBuilder()->defaultOptions(); @@ -546,6 +551,16 @@ void QgisAppInterface::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory * qgis->unregisterOptionsWidgetFactory( factory ); } +void QgisAppInterface::registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) +{ + qgis->registerProjectPropertiesWidgetFactory( factory ); +} + +void QgisAppInterface::unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) +{ + qgis->unregisterProjectPropertiesWidgetFactory( factory ); +} + void QgisAppInterface::registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) { qgis->registerDevToolFactory( factory ); diff --git a/src/app/qgisappinterface.h b/src/app/qgisappinterface.h index e98f5abab68c..23d3348c886b 100644 --- a/src/app/qgisappinterface.h +++ b/src/app/qgisappinterface.h @@ -115,6 +115,7 @@ class APP_EXPORT QgisAppInterface : public QgisInterface QList openLayoutDesigners() override; QgsLayoutDesignerInterface *openLayoutDesigner( QgsMasterLayoutInterface *layout ) override; void showOptionsDialog( QWidget *parent = nullptr, const QString ¤tPage = QString() ) override; + void showProjectPropertiesDialog( const QString ¤tPage = QString() ) override; QMap defaultStyleSheetOptions() override; void buildStyleSheet( const QMap &opts ) override; void saveStyleSheetOptions( const QMap &opts ) override; @@ -145,6 +146,8 @@ class APP_EXPORT QgisAppInterface : public QgisInterface void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) override; void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override; void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override; + void registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) override; + void unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) override; void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override; void unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override; void registerCustomDropHandler( QgsCustomDropHandler *handler ) override; diff --git a/src/app/qgsprojectproperties.cpp b/src/app/qgsprojectproperties.cpp index 7c6fb14ec4d9..9b41f4e10c41 100644 --- a/src/app/qgsprojectproperties.cpp +++ b/src/app/qgsprojectproperties.cpp @@ -76,7 +76,7 @@ //qt includes #include #include -#include // Qt 4.4 +#include #include #include #include @@ -87,7 +87,7 @@ const char *QgsProjectProperties::GEO_NONE_DESC = QT_TRANSLATE_NOOP( "QgsOptions //stdc++ includes -QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl ) +QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl, const QList &optionsFactories ) : QgsOptionsDialogBase( QStringLiteral( "ProjectProperties" ), parent, fl ) , mMapCanvas( mapCanvas ) , mEllipsoidIndex( 0 ) @@ -971,6 +971,24 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa mBearingFormat.reset( QgsProject::instance()->displaySettings()->bearingFormat()->clone() ); + const auto constOptionsFactories = optionsFactories; + for ( QgsOptionsWidgetFactory *factory : constOptionsFactories ) + { + QListWidgetItem *item = new QListWidgetItem(); + item->setIcon( factory->icon() ); + item->setText( factory->title() ); + item->setToolTip( factory->title() ); + + mOptionsListWidget->addItem( item ); + + QgsOptionsPageWidget *page = factory->createWidget( this ); + if ( !page ) + continue; + + mAdditionalProjectPropertiesWidgets << page; + mOptionsStackedWidget->addWidget( page ); + } + restoreOptionsBaseUi(); #ifdef QGISDEBUG @@ -1525,6 +1543,11 @@ void QgsProjectProperties::apply() QgsProject::instance()->displaySettings()->setBearingFormat( mBearingFormat->clone() ); + for ( QgsOptionsPageWidget *widget : qgis::as_const( mAdditionalProjectPropertiesWidgets ) ) + { + widget->apply(); + } + //refresh canvases to reflect new properties, eg background color and scale bar after changing display units. for ( QgsMapCanvas *canvas : constMapCanvases ) { @@ -2524,6 +2547,17 @@ void QgsProjectProperties::showHelp() { link = QStringLiteral( "working_with_ogc/server/getting_started.html#prepare-a-project-to-serve" ); } + + // give first priority to created pages which have specified a help key + for ( const QgsOptionsPageWidget *widget : qgis::as_const( mAdditionalProjectPropertiesWidgets ) ) + { + if ( widget == activeTab ) + { + link = widget->helpKey(); + break; + } + } + QgsHelp::openHelp( link ); } diff --git a/src/app/qgsprojectproperties.h b/src/app/qgsprojectproperties.h index ceb22835b97c..625f0e959cb3 100644 --- a/src/app/qgsprojectproperties.h +++ b/src/app/qgsprojectproperties.h @@ -17,8 +17,10 @@ ***************************************************************************/ -#include "qgsoptionsdialogbase.h" #include "ui_qgsprojectpropertiesbase.h" + +#include "qgsoptionsdialogbase.h" +#include "qgsoptionswidgetfactory.h" #include "qgis.h" #include "qgsunittypes.h" #include "qgsguiutils.h" @@ -26,6 +28,8 @@ #include "qgshelp.h" #include "qgis_app.h" +#include + class QgsMapCanvas; class QgsRelationManagerDialog; class QgsStyle; @@ -35,6 +39,7 @@ class QgsMetadataWidget; class QgsTreeWidgetItem; class QgsLayerCapabilitiesModel; class QgsBearingNumericFormat; +class QgsOptionsPageWidget; /** * Dialog to set project level properties @@ -48,7 +53,8 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui: public: //! Constructor - QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *parent = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags ); + QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *parent = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, + const QList &optionsFactories = QList() ); ~QgsProjectProperties() override; @@ -250,6 +256,8 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui: int mEllipsoidIndex; bool mBlockCrsUpdates = false; + QList< QgsOptionsPageWidget * > mAdditionalProjectPropertiesWidgets; + std::unique_ptr< QgsBearingNumericFormat > mBearingFormat; //! populate WMTS tree diff --git a/src/gui/qgisinterface.h b/src/gui/qgisinterface.h index 32b4840a458c..f151d5554fcf 100644 --- a/src/gui/qgisinterface.h +++ b/src/gui/qgisinterface.h @@ -848,6 +848,13 @@ class GUI_EXPORT QgisInterface : public QObject */ virtual void showOptionsDialog( QWidget *parent = nullptr, const QString ¤tPage = QString() ) = 0; + /** + * Opens the project properties dialog. The \a currentPage argument can be used to force + * the dialog to open at a specific page. + * \since QGIS 3.16 + */ + virtual void showProjectPropertiesDialog( const QString ¤tPage = QString() ) = 0; + /** * Generate stylesheet * \param opts generated default option values, or a changed copy of them @@ -984,6 +991,24 @@ class GUI_EXPORT QgisInterface : public QObject */ virtual void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0; + /** + * Register a new tab in the project properties dialog. + * \note Ownership of the factory is not transferred, and the factory must + * be unregistered when plugin is unloaded. + * \see QgsOptionsWidgetFactory + * \see unregisterProjectPropertiesWidgetFactory() + * \since QGIS 3.16 + */ + virtual void registerProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0; + + /** + * Unregister a previously registered tab in the options dialog. + * \see QgsOptionsWidgetFactory + * \see registerProjectPropertiesWidgetFactory() + * \since QGIS 3.16 + */ + virtual void unregisterProjectPropertiesWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0; + /** * Register a new tool in the development/debugging tools dock. * \note Ownership of the factory is not transferred, and the factory must