Skip to content
Permalink
Browse files

[FEATURE][API] Add interface hooks to allow plugins to register

"development/debugging" tools

These tools appear in a new Development/Debugging Tools dock,
and provide a unified handling and place for these tools in the
UI.

The intention here is that specialised development/debugging tools
will be moved to this common interface, e.g.
- network logger
- first aid style Python local variables inspector
- startup time debugging tools
- layer load and rendering time debugging tools
... ?
  • Loading branch information
nyalldawson committed Mar 25, 2020
1 parent bab86e9 commit b1d50c2116b10d38304c325464850f484b7ce10d
@@ -1116,6 +1116,29 @@ Unregister a previously registered tab in the options dialog.
.. seealso:: :py:func:`registerOptionsWidgetFactory`

.. versionadded:: 3.0
%End

virtual void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) = 0;
%Docstring
Register a new tool in the development/debugging tools dock.

.. note::

Ownership of the factory is not transferred, and the factory must
be unregistered when plugin is unloaded.

.. seealso:: :py:func:`unregisterDevToolWidgetFactory`

.. versionadded:: 3.14
%End

virtual void unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) = 0;
%Docstring
Unregister a previously registered tool factory from the development/debugging tools dock.

.. seealso:: :py:func:`registerDevToolWidgetFactory`

.. versionadded:: 3.14
%End

virtual void registerCustomDropHandler( QgsCustomDropHandler *handler ) = 0;
@@ -27,6 +27,7 @@ SET(QGIS_APP_SRCS
qgscustomization.cpp
qgscustomprojectiondialog.cpp
qgsdatumtransformtablewidget.cpp
qgsdevtoolspanelwidget.cpp
qgsdiscoverrelationsdialog.cpp
qgsdxfexportdialog.cpp
qgsformannotationdialog.cpp
@@ -78,6 +78,7 @@
#include "qgsrelationmanager.h"
#include "qgsapplication.h"
#include "qgslayerstylingwidget.h"
#include "qgsdevtoolspanelwidget.h"
#include "qgstaskmanager.h"
#include "qgsweakrelation.h"
#include "qgsziputils.h"
@@ -1121,6 +1122,23 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mMapStylingDock->hide();
endProfile();

startProfile( QStringLiteral( "Dev Tools dock" ) );
mDevToolsDock = new QgsDockWidget( this );
mDevToolsDock->setWindowTitle( tr( "Debugging/Development Tools" ) );
mDevToolsDock->setObjectName( QStringLiteral( "DevTools" ) );
QShortcut *showDevToolsDock = new QShortcut( QKeySequence( tr( "F12" ) ), this );
connect( showDevToolsDock, &QShortcut::activated, mDevToolsDock, &QgsDockWidget::toggleUserVisible );
showDevToolsDock->setObjectName( QStringLiteral( "ShowDevToolsPanel" ) );
showDevToolsDock->setWhatsThis( tr( "Show Debugging/Development Tools" ) );

mDevToolsWidget = new QgsDevToolsPanelWidget( mDevToolFactories );
mDevToolsDock->setWidget( mDevToolsWidget );
// connect( mDevToolsDock, &QDockWidget::visibilityChanged, mActionStyleDock, &QAction::setChecked );

addDockWidget( Qt::RightDockWidgetArea, mDevToolsDock );
mDevToolsDock->hide();
endProfile();

startProfile( QStringLiteral( "Snapping dialog" ) );
mSnappingDialog = new QgsSnappingWidget( QgsProject::instance(), mMapCanvas, this );
connect( mSnappingDialog, &QgsSnappingWidget::snappingConfigChanged, QgsProject::instance(), [ = ] { QgsProject::instance()->setSnappingConfig( mSnappingDialog->config() ); } );
@@ -11857,6 +11875,22 @@ void QgisApp::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory )
mOptionsWidgetFactories.removeAll( factory );
}

void QgisApp::registerDevToolFactory( QgsDevToolWidgetFactory *factory )
{
mDevToolFactories << factory;
if ( mDevToolsWidget )
{
// widget was already created, so we manually need to push this factory to the widget
mDevToolsWidget->addToolFactory( factory );
}
}

void QgisApp::unregisterDevToolFactory( QgsDevToolWidgetFactory *factory )
{
mDevToolsWidget->removeToolFactory( factory );
mDevToolFactories.removeAll( factory );
}

QgsMapLayer *QgisApp::activeLayer()
{
return mLayerTreeView ? mLayerTreeView->currentLayer() : nullptr;
@@ -139,6 +139,8 @@ class QgsLayoutCustomDropHandler;
class QgsProxyProgressTask;
class QgsNetworkRequestParameters;
class QgsBearingNumericFormat;
class QgsDevToolsPanelWidget;
class QgsDevToolWidgetFactory;

#include <QMainWindow>
#include <QToolBar>
@@ -682,6 +684,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 dev tool factory
void registerDevToolFactory( QgsDevToolWidgetFactory *factory );

//! Unregister a previously registered dev tool factory
void unregisterDevToolFactory( QgsDevToolWidgetFactory *factory );

//! Register a new custom drop handler.
void registerCustomDropHandler( QgsCustomDropHandler *handler );

@@ -2334,6 +2342,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsUserProfileManager *mUserProfileManager = nullptr;
QgsDockWidget *mMapStylingDock = nullptr;
QgsLayerStylingWidget *mMapStyleWidget = nullptr;
QgsDockWidget *mDevToolsDock = nullptr;
QgsDevToolsPanelWidget *mDevToolsWidget = nullptr;

//! Persistent tile scale slider
QgsTileScaleWidget *mpTileScaleWidget = nullptr;
@@ -2377,6 +2387,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QList<QgsMapLayerConfigWidgetFactory *> mMapLayerPanelFactories;
QList<QPointer<QgsOptionsWidgetFactory>> mOptionsWidgetFactories;

QList<QgsDevToolWidgetFactory * > mDevToolFactories;

QVector<QPointer<QgsCustomDropHandler>> mCustomDropHandlers;
QVector<QPointer<QgsLayoutCustomDropHandler>> mCustomLayoutDropHandlers;

@@ -536,6 +536,16 @@ void QgisAppInterface::unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *
qgis->unregisterOptionsWidgetFactory( factory );
}

void QgisAppInterface::registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory )
{
qgis->registerDevToolFactory( factory );
}

void QgisAppInterface::unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory )
{
qgis->unregisterDevToolFactory( factory );
}

void QgisAppInterface::registerCustomDropHandler( QgsCustomDropHandler *handler )
{
qgis->registerCustomDropHandler( handler );
@@ -143,6 +143,8 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
void unregisterMapLayerConfigWidgetFactory( QgsMapLayerConfigWidgetFactory *factory ) override;
void registerOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override;
void unregisterOptionsWidgetFactory( QgsOptionsWidgetFactory *factory ) override;
void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override;
void unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) override;
void registerCustomDropHandler( QgsCustomDropHandler *handler ) override;
void unregisterCustomDropHandler( QgsCustomDropHandler *handler ) override;
void registerCustomLayoutDropHandler( QgsLayoutCustomDropHandler *handler ) override;
@@ -0,0 +1,77 @@
/***************************************************************************
qgsdevtoolspanelwidget.cpp
---------------------
Date : March 2020
Copyright : (C) 2020 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 "qgsdevtoolspanelwidget.h"
#include "qgisapp.h"
#include "qgsdevtoolwidgetfactory.h"
#include "qgsdevtoolwidget.h"
#include "qgspanelwidgetstack.h"


QgsDevToolsPanelWidget::QgsDevToolsPanelWidget( const QList<QgsDevToolWidgetFactory *> &factories, QWidget *parent )
: QWidget( parent )
{
setupUi( this );

mOptionsListWidget->setIconSize( QgisApp::instance()->iconSize( false ) );
mOptionsListWidget->setMaximumWidth( static_cast< int >( mOptionsListWidget->iconSize().width() * 1.18 ) );

for ( QgsDevToolWidgetFactory *factory : factories )
addToolFactory( factory );

connect( mOptionsListWidget, &QListWidget::currentRowChanged, this, &QgsDevToolsPanelWidget::setCurrentTool );
}

QgsDevToolsPanelWidget::~QgsDevToolsPanelWidget() = default;

void QgsDevToolsPanelWidget::addToolFactory( QgsDevToolWidgetFactory *factory )
{
if ( QgsDevToolWidget *toolWidget = factory->createWidget( this ) )
{
QgsPanelWidgetStack *toolStack = new QgsPanelWidgetStack();
toolStack->setMainPanel( toolWidget );
mStackedWidget->addWidget( toolStack );

QListWidgetItem *item = new QListWidgetItem( factory->icon(), QString() );
item->setToolTip( factory->title() );
mOptionsListWidget->addItem( item );
int row = mOptionsListWidget->row( item );
mFactoryPages[factory] = row;

if ( mOptionsListWidget->count() == 1 )
{
setCurrentTool( 0 );
}
}
}

void QgsDevToolsPanelWidget::removeToolFactory( QgsDevToolWidgetFactory *factory )
{
if ( mFactoryPages.contains( factory ) )
{
int currentRow = mStackedWidget->currentIndex();
int row = mFactoryPages.value( factory );
mStackedWidget->removeWidget( mStackedWidget->widget( row ) );
mOptionsListWidget->removeItemWidget( mOptionsListWidget->item( row ) );
mFactoryPages.remove( factory );
if ( currentRow == row )
setCurrentTool( 0 );
}
}

void QgsDevToolsPanelWidget::setCurrentTool( int row )
{
whileBlocking( mOptionsListWidget )->setCurrentRow( row );
mStackedWidget->setCurrentIndex( row );
}
@@ -0,0 +1,44 @@
/***************************************************************************
qgsdevtoolspanelwidget.h
---------------------
Date : March 2020
Copyright : (C) 2020 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 QGSDEVTOOLSPANELWIDGET_H
#define QGSDEVTOOLSPANELWIDGET_H

#include "ui_qgsdevtoolswidgetbase.h"
#include "qgis_app.h"

class QgsDevToolWidgetFactory;

class APP_EXPORT QgsDevToolsPanelWidget : public QWidget, private Ui::QgsDevToolsWidgetBase
{
Q_OBJECT
public:

QgsDevToolsPanelWidget( const QList<QgsDevToolWidgetFactory *> &factories, QWidget *parent = nullptr );
~QgsDevToolsPanelWidget() override;

void addToolFactory( QgsDevToolWidgetFactory *factory );

void removeToolFactory( QgsDevToolWidgetFactory *factory );

private slots:

void setCurrentTool( int row );

private:

QMap< QgsDevToolWidgetFactory *, int> mFactoryPages;
};

#endif // QGSDEVTOOLSPANELWIDGET_H
@@ -61,6 +61,7 @@ class QgsLocatorFilter;
class QgsStatusBar;
class QgsMeshLayer;
class QgsBrowserGuiModel;
class QgsDevToolWidgetFactory;


/**
@@ -927,6 +928,22 @@ class GUI_EXPORT QgisInterface : public QObject
*/
virtual void unregisterOptionsWidgetFactory( 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
* be unregistered when plugin is unloaded.
* \see unregisterDevToolWidgetFactory()
* \since QGIS 3.14
*/
virtual void registerDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) = 0;

/**
* Unregister a previously registered tool factory from the development/debugging tools dock.
* \see registerDevToolWidgetFactory()
* \since QGIS 3.14
*/
virtual void unregisterDevToolWidgetFactory( QgsDevToolWidgetFactory *factory ) = 0;

/**
* Register a new custom drop handler.
* \note Ownership of the factory is not transferred, and the factory must

0 comments on commit b1d50c2

Please sign in to comment.
You can’t perform that action at this time.