Skip to content

Commit 2d807f5

Browse files
committed
[FEATURE] Interface for plugins to embed pages in the options dialog
Allows plugins to embed their options into the standard options dialog, instead of implementing their own config dialog and having to have extra menu items just for those...
1 parent cc0007c commit 2d807f5

12 files changed

+238
-61
lines changed

python/gui/gui.sip

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
%Include qgsnewvectorlayerdialog.sip
130130
%Include qgsnewgeopackagelayerdialog.sip
131131
%Include qgsoptionsdialogbase.sip
132+
%Include qgsoptionswidgetfactory.sip
132133
%Include qgsorderbydialog.sip
133134
%Include qgsowssourceselect.sip
134135
%Include qgspanelwidget.sip

python/gui/qgisinterface.sip

+9-46
Original file line numberDiff line numberDiff line change
@@ -296,53 +296,16 @@ class QgisInterface : QObject
296296
* windows which are hidden rather than deleted when closed. */
297297
virtual void removeWindow( QAction *action ) = 0;
298298

299-
/** Register action to the shortcuts manager so its shortcut can be changed in GUI */
300-
virtual bool registerMainWindowAction( QAction* action, const QString& defaultShortcut ) = 0;
301-
302-
/** Unregister a previously registered action. (e.g. when plugin is going to be unloaded) */
303-
virtual bool unregisterMainWindowAction( QAction* action ) = 0;
304-
305-
/** Register a new tab in the vector layer properties dialog.
306-
* @note added in QGIS 2.16
307-
* @note Ownership of the factory is not transferred, and the factory must
308-
* be unregistered when plugin is unloaded.
309-
* @see unregisterMapLayerPropertiesFactory() */
310-
virtual void registerMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory* factory ) = 0;
311-
312-
/** Unregister a previously registered tab in the vector layer properties dialog.
313-
* @note added in QGIS 2.16
314-
* @see registerMapLayerPropertiesFactory()
315-
*/
316-
virtual void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory* factory ) = 0;
317-
318-
/** Register a new custom drop handler.
319-
* @note added in QGIS 3.0
320-
* @note Ownership of the factory is not transferred, and the factory must
321-
* be unregistered when plugin is unloaded.
322-
* @see unregisterCustomDropHandler() */
323-
virtual void registerCustomDropHandler( QgsCustomDropHandler* handler ) = 0;
324-
325-
/** Unregister a previously registered custom drop handler.
326-
* @note added in QGIS 3.0
327-
* @see registerCustomDropHandler() */
328-
virtual void unregisterCustomDropHandler( QgsCustomDropHandler* handler ) = 0;
329-
330-
// @todo is this deprecated in favour of QgsContextHelp?
331-
/** Open a url in the users browser. By default the QGIS doc directory is used
332-
* as the base for the URL. To open a URL that is not relative to the installed
333-
* QGIS documentation, set useQgisDocDirectory to false.
334-
* @param url URL to open
335-
* @param useQgisDocDirectory If true, the URL will be formed by concatenating
336-
* url to the QGIS documentation directory path (prefix/share/doc)
337-
* @deprecated
338-
*/
339-
virtual void openURL( const QString& url, bool useQgisDocDirectory = true ) = 0 /Deprecated/;
340-
341-
/** Accessors for inserting items into menus and toolbars.
342-
* An item can be inserted before any existing action.
343-
*/
299+
virtual bool registerMainWindowAction( QAction *action, const QString &defaultShortcut ) = 0;
300+
virtual bool unregisterMainWindowAction( QAction *action ) = 0;
301+
virtual void registerMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) = 0;
302+
virtual void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) = 0;
303+
virtual void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0;
304+
virtual void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0;
305+
virtual void registerCustomDropHandler( QgsCustomDropHandler *handler ) = 0;
306+
virtual void unregisterCustomDropHandler( QgsCustomDropHandler *handler ) = 0;
307+
virtual void openURL( const QString &url, bool useQgisDocDirectory = true ) = 0 /Deprecated/;
344308

345-
// Menus
346309
virtual QMenu *projectMenu() = 0;
347310
virtual QMenu *editMenu() = 0;
348311
virtual QMenu *viewMenu() = 0;
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
class QgsOptionsPageWidget : QWidget
2+
{
3+
%TypeHeaderCode
4+
#include <qgsoptionswidgetfactory.h>
5+
%End
6+
7+
public:
8+
9+
QgsOptionsPageWidget( QWidget *parent /TransferThis/ = 0 );
10+
11+
public slots:
12+
13+
virtual void apply() = 0;
14+
15+
};
16+
17+
class QgsOptionsWidgetFactory
18+
{
19+
%TypeHeaderCode
20+
#include <qgsoptionswidgetfactory.h>
21+
%End
22+
23+
public:
24+
25+
QgsOptionsWidgetFactory();
26+
27+
QgsOptionsWidgetFactory( const QString &title, const QIcon &icon );
28+
virtual ~QgsOptionsWidgetFactory();
29+
30+
virtual QIcon icon() const;
31+
void setIcon( const QIcon &icon );
32+
virtual QString title() const;
33+
void setTitle( const QString &title );
34+
35+
virtual QgsOptionsPageWidget *createWidget( QWidget *parent = 0 ) const = 0 /Factory/;
36+
37+
38+
};
39+

src/app/qgisapp.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
#include "qgsfieldformatter.h"
168168
#include "qgsfieldformatterregistry.h"
169169
#include "qgsformannotation.h"
170+
#include "qgisgui.h"
170171
#include "qgshtmlannotation.h"
171172
#include "qgsprojectionselectiondialog.h"
172173
#include "qgsgpsinformationwidget.h"
@@ -9105,7 +9106,7 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString &currentPage )
91059106

91069107
bool oldCapitalize = mySettings.value( QStringLiteral( "/qgis/capitalizeLayerName" ), QVariant( false ) ).toBool();
91079108

9108-
QgsOptions *optionsDialog = new QgsOptions( parent );
9109+
std::unique_ptr< QgsOptions > optionsDialog( new QgsOptions( parent, QgisGui::ModalDialogFlags, mOptionsWidgetFactories ) );
91099110
if ( !currentPage.isEmpty() )
91109111
{
91119112
optionsDialog->setCurrentPage( currentPage );
@@ -9167,8 +9168,6 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString &currentPage )
91679168
mMagnifierWidget->setDefaultFactor( factor );
91689169
mMagnifierWidget->updateMagnification( factor );
91699170
}
9170-
9171-
delete optionsDialog;
91729171
}
91739172

91749173
void QgisApp::fullHistogramStretch()
@@ -9385,6 +9384,16 @@ void QgisApp::unregisterMapLayerPropertiesFactory( QgsMapLayerConfigWidgetFactor
93859384
mMapStyleWidget->setPageFactories( mMapLayerPanelFactories );
93869385
}
93879386

9387+
void QgisApp::registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory )
9388+
{
9389+
mOptionsWidgetFactories << factory;
9390+
}
9391+
9392+
void QgisApp::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory )
9393+
{
9394+
mOptionsWidgetFactories.removeAll( factory );
9395+
}
9396+
93889397
//! Get a pointer to the currently selected map layer
93899398
QgsMapLayer *QgisApp::activeLayer()
93909399
{

src/app/qgisapp.h

+8
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class QgsUserInputDockWidget;
8787
class QgsVectorLayer;
8888
class QgsVectorLayerTools;
8989
class QgsWelcomePage;
90+
class QgsOptionsWidgetFactory;
9091

9192
class QDomDocument;
9293
class QNetworkReply;
@@ -536,6 +537,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
536537
//! Unregister a previously registered tab in the layer properties dialog
537538
void unregisterMapLayerPropertiesFactory( QgsMapLayerConfigWidgetFactory *factory );
538539

540+
//! Register a new tab in the options dialog
541+
void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory );
542+
543+
//! Unregister a previously registered tab in the options dialog
544+
void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory );
545+
539546
//! Register a new custom drop handler.
540547
void registerCustomDropHandler( QgsCustomDropHandler *handler );
541548

@@ -1847,6 +1854,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
18471854
QgsSnappingUtils *mSnappingUtils = nullptr;
18481855

18491856
QList<QgsMapLayerConfigWidgetFactory *> mMapLayerPanelFactories;
1857+
QList<QgsOptionsWidgetFactory *> mOptionsWidgetFactories;
18501858

18511859
QList<QgsCustomDropHandler *> mCustomDropHandlers;
18521860

src/app/qgisappinterface.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,16 @@ void QgisAppInterface::unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigW
503503
qgis->unregisterMapLayerPropertiesFactory( factory );
504504
}
505505

506+
void QgisAppInterface::registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory )
507+
{
508+
qgis->registerOptionsWidgetFactory( factory );
509+
}
510+
511+
void QgisAppInterface::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory )
512+
{
513+
qgis->unregisterOptionsWidgetFactory( factory );
514+
}
515+
506516
void QgisAppInterface::registerCustomDropHandler( QgsCustomDropHandler *handler )
507517
{
508518
qgis->registerCustomDropHandler( handler );

src/app/qgisappinterface.h

+3-10
Original file line numberDiff line numberDiff line change
@@ -302,19 +302,12 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
302302
//! Unregister a previously registered action. (e.g. when plugin is going to be unloaded.
303303
virtual bool unregisterMainWindowAction( QAction *action ) override;
304304

305-
/** Register a new tab in the vector layer properties dialog.
306-
* @note added in QGIS 2.16
307-
* @note Ownership of the factory is not transferred, and the factory must
308-
* be unregistered when plugin is unloaded.
309-
* @see unregisterMapLayerPropertiesFactory() */
310305
virtual void registerMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) override;
311-
312-
/** Unregister a previously registered tab in the vector layer properties dialog.
313-
* @note added in QGIS 2.16
314-
* @see registerMapLayerPropertiesFactory()
315-
*/
316306
virtual void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) override;
317307

308+
virtual void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override;
309+
virtual void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override;
310+
318311
/** Register a new custom drop handler.
319312
* @note added in QGIS 3.0
320313
* @note Ownership of the factory is not transferred, and the factory must

src/app/qgsoptions.cpp

+24-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "qgsunittypes.h"
4747
#include "qgsclipboard.h"
4848
#include "qgssettings.h"
49+
#include "qgsoptionswidgetfactory.h"
4950

5051
#include <QInputDialog>
5152
#include <QFileDialog>
@@ -74,7 +75,7 @@
7475
* \class QgsOptions - Set user options and preferences
7576
* Constructor
7677
*/
77-
QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
78+
QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOptionsWidgetFactory *> &optionsFactories )
7879
: QgsOptionsDialogBase( QStringLiteral( "Options" ), parent, fl )
7980
, mSettings( nullptr )
8081
{
@@ -926,6 +927,23 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
926927

927928
mAdvancedSettingsEditor->setSettingsObject( mSettings );
928929

930+
Q_FOREACH ( QgsOptionsWidgetFactory *factory, optionsFactories )
931+
{
932+
QListWidgetItem *item = new QListWidgetItem();
933+
item->setIcon( factory->icon() );
934+
item->setText( factory->title() );
935+
item->setToolTip( factory->title() );
936+
937+
mOptionsListWidget->addItem( item );
938+
939+
QgsOptionsPageWidget *page = factory->createWidget( this );
940+
if ( !page )
941+
continue;
942+
943+
mAdditionalOptionWidgets << page;
944+
mOptionsStackedWidget->addWidget( page );
945+
}
946+
929947
// restore window and widget geometry/state
930948
restoreOptionsBaseUi();
931949
}
@@ -1473,6 +1491,11 @@ void QgsOptions::saveOptions()
14731491
}
14741492

14751493
saveDefaultDatumTransformations();
1494+
1495+
Q_FOREACH ( QgsOptionsPageWidget *widget, mAdditionalOptionWidgets )
1496+
{
1497+
widget->apply();
1498+
}
14761499
}
14771500

14781501
void QgsOptions::rejectOptions()

src/app/qgsoptions.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "qgis_app.h"
3131

3232
class QgsExpressionContext;
33+
class QgsOptionsPageWidget;
3334

3435
/**
3536
* \class QgsOptions
@@ -45,8 +46,10 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption
4546
* @param parent Parent widget (usually a QgisApp)
4647
* @param name name for the widget
4748
* @param modal true for modal dialog
49+
* @param optionsFactories factories for additional option pages
4850
*/
49-
QgsOptions( QWidget *parent = nullptr, Qt::WindowFlags fl = QgisGui::ModalDialogFlags );
51+
QgsOptions( QWidget *parent = nullptr, Qt::WindowFlags fl = QgisGui::ModalDialogFlags,
52+
const QList<QgsOptionsWidgetFactory *> &optionsFactories = QList<QgsOptionsWidgetFactory *>() );
5053

5154
~QgsOptions();
5255

@@ -245,6 +248,10 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption
245248
static const int PALETTE_COLOR_ROLE = Qt::UserRole + 1;
246249
static const int PALETTE_LABEL_ROLE = Qt::UserRole + 2;
247250

251+
private:
252+
253+
QList< QgsOptionsPageWidget * > mAdditionalOptionWidgets;
254+
248255
};
249256

250257
#endif // #ifndef QGSOPTIONS_H

src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ SET(QGIS_GUI_MOC_HDRS
416416
qgsnewvectorlayerdialog.h
417417
qgsnewgeopackagelayerdialog.h
418418
qgsoptionsdialogbase.h
419+
qgsoptionswidgetfactory.h
419420
qgsorderbydialog.h
420421
qgsowssourceselect.h
421422
qgssourceselectdialog.h

src/gui/qgisinterface.h

+14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class QgsRasterLayer;
4141
class QgsSnappingUtils;
4242
class QgsVectorLayer;
4343
class QgsVectorLayerTools;
44+
class QgsOptionsWidgetFactory;
4445

4546
#include <QObject>
4647
#include <QFont>
@@ -364,6 +365,19 @@ class GUI_EXPORT QgisInterface : public QObject
364365
*/
365366
virtual void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) = 0;
366367

368+
/** Register a new tab in the options dialog.
369+
* @note added in QGIS 3.0
370+
* @note Ownership of the factory is not transferred, and the factory must
371+
* be unregistered when plugin is unloaded.
372+
* @see unregisterOptionsWidgetFactory() */
373+
virtual void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0;
374+
375+
/** Unregister a previously registered tab in the options dialog.
376+
* @note added in QGIS 3.0
377+
* @see registerOptionsWidgetFactory()
378+
*/
379+
virtual void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) = 0;
380+
367381
/** Register a new custom drop handler.
368382
* @note added in QGIS 3.0
369383
* @note Ownership of the factory is not transferred, and the factory must

0 commit comments

Comments
 (0)