From ea2395dd92166acfb4d8d4b1bf9c1a43635bda42 Mon Sep 17 00:00:00 2001 From: Martin Dobias Date: Wed, 1 Jun 2016 12:40:00 +0200 Subject: [PATCH] Integration of embedded widgets into layer tree + config GUI --- python/core/qgsdataitem.sip | 2 +- src/app/qgisapp.cpp | 1 + src/app/qgsapplayertreeviewmenuprovider.cpp | 26 +++ src/app/qgsapplayertreeviewmenuprovider.h | 1 + src/core/layertree/qgslayertreemodel.cpp | 25 +++ src/core/layertree/qgslayertreemodel.h | 1 + src/core/layertree/qgslayertreenode.h | 1 + src/gui/CMakeLists.txt | 7 + .../qgslayertreeembeddedconfigwidget.cpp | 87 ++++++++++ .../qgslayertreeembeddedconfigwidget.h | 25 +++ .../qgslayertreeembeddedwidgetregistry.cpp | 155 ++++++++++++++++++ .../qgslayertreeembeddedwidgetregistry.h | 108 ++++++++++++ src/gui/layertree/qgslayertreeview.cpp | 24 +++ src/ui/qgslayertreeembeddedconfigwidget.ui | 85 ++++++++++ 14 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 src/gui/layertree/qgslayertreeembeddedconfigwidget.cpp create mode 100644 src/gui/layertree/qgslayertreeembeddedconfigwidget.h create mode 100644 src/gui/layertree/qgslayertreeembeddedwidgetregistry.cpp create mode 100644 src/gui/layertree/qgslayertreeembeddedwidgetregistry.h create mode 100644 src/ui/qgslayertreeembeddedconfigwidget.ui diff --git a/python/core/qgsdataitem.sip b/python/core/qgsdataitem.sip index 5584dbbef21..3a8838295da 100644 --- a/python/core/qgsdataitem.sip +++ b/python/core/qgsdataitem.sip @@ -75,7 +75,7 @@ class QgsDataItem : QObject /** Create children. Children are not expected to have parent set. * This method MUST BE THREAD SAFE. */ - virtual QVector createChildren(); + virtual QVector createChildren() /Factory/; enum State { diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 68bcca2cb3a..10ad817124a 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -2815,6 +2815,7 @@ void QgisApp::initLayerTreeView() model->setFlag( QgsLayerTreeModel::AllowNodeRename ); model->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility ); model->setFlag( QgsLayerTreeModel::ShowLegendAsTree ); + model->setFlag( QgsLayerTreeModel::UseEmbeddedWidgets ); model->setAutoCollapseLegendNodes( 10 ); mLayerTreeView->setModel( model ); diff --git a/src/app/qgsapplayertreeviewmenuprovider.cpp b/src/app/qgsapplayertreeviewmenuprovider.cpp index f5e21cb3003..678c3266ffa 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.cpp +++ b/src/app/qgsapplayertreeviewmenuprovider.cpp @@ -237,6 +237,9 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu() duplicateLayersAction->setEnabled( false ); } + QAction* embeddedAction = menu->addAction( tr( "Embedded widgets..."), this, SLOT( editEmbeddedWidgets() ) ); + embeddedAction->setProperty( "layerId", layer->id() ); + addCustomLayerActions( menu, layer ); if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() ) @@ -555,3 +558,26 @@ void QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor( const QColor &co newSymbol->setColor( color ); node->setSymbol( newSymbol ); } + +#include "qgslayertreeembeddedconfigwidget.h" +void QgsAppLayerTreeViewMenuProvider::editEmbeddedWidgets() +{ + QAction* action = qobject_cast< QAction*>( sender() ); + if ( !action ) + return; + + QString layerId = action->property( "layerId" ).toString(); + QgsLayerTreeLayer* nodeLayer = QgsProject::instance()->layerTreeRoot()->findLayer( layerId ); + if ( !nodeLayer ) + return; + + QDialog d; + QgsLayerTreeEmbeddedConfigWidget* widget = new QgsLayerTreeEmbeddedConfigWidget(nodeLayer, &d); + + QLayout* l = new QVBoxLayout(&d); + l->addWidget(widget); + d.setLayout(l); + d.exec(); + + mView->layerTreeModel()->refreshLayerLegend( nodeLayer ); +} diff --git a/src/app/qgsapplayertreeviewmenuprovider.h b/src/app/qgsapplayertreeviewmenuprovider.h index 219f70fd66b..fa0ff6165c6 100644 --- a/src/app/qgsapplayertreeviewmenuprovider.h +++ b/src/app/qgsapplayertreeviewmenuprovider.h @@ -69,6 +69,7 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM void setVectorSymbolColor( const QColor &color ); void editSymbolLegendNodeSymbol(); void setSymbolLegendNodeColor( const QColor &color ); + void editEmbeddedWidgets(); }; #endif // QGSAPPLAYERTREEVIEWMENUPROVIDER_H diff --git a/src/core/layertree/qgslayertreemodel.cpp b/src/core/layertree/qgslayertreemodel.cpp index 89aa2eeec44..30f593f10c4 100644 --- a/src/core/layertree/qgslayertreemodel.cpp +++ b/src/core/layertree/qgslayertreemodel.cpp @@ -1149,6 +1149,21 @@ void QgsLayerTreeModel::removeLegendFromLayer( QgsLayerTreeLayer* nodeLayer ) } } +class EmbeddedWidgetLegendNode : public QgsLayerTreeModelLegendNode +{ + public: + EmbeddedWidgetLegendNode( QgsLayerTreeLayer* nodeL ) + : QgsLayerTreeModelLegendNode( nodeL ) + { + } + + virtual QVariant data( int role ) const override + { + Q_UNUSED( role ); + return QVariant(); + } + +}; void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL ) { @@ -1169,6 +1184,16 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL ) // apply filtering defined in layer node's custom properties (reordering, filtering, custom labels) QgsMapLayerLegendUtils::applyLayerNodeProperties( nodeL, lstNew ); + if ( testFlag( UseEmbeddedWidgets ) ) + { + int widgetsCount = nodeL->customProperty( "embeddedWidgets/count", 0 ).toInt(); + while ( widgetsCount > 0 ) + { + lstNew.insert( 0, new EmbeddedWidgetLegendNode( nodeL ) ); + --widgetsCount; + } + } + QList filteredLstNew = filterLegendNodes( lstNew ); bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent(); diff --git a/src/core/layertree/qgslayertreemodel.h b/src/core/layertree/qgslayertreemodel.h index 8939b816e14..f187aeab58e 100644 --- a/src/core/layertree/qgslayertreemodel.h +++ b/src/core/layertree/qgslayertreemodel.h @@ -80,6 +80,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel ShowRasterPreviewIcon = 0x0002, //!< Will use real preview of raster layer as icon (may be slow) ShowLegendAsTree = 0x0004, //!< For legends that support it, will show them in a tree instead of a list (needs also ShowLegend). Added in 2.8 DeferredLegendInvalidation = 0x0008, //!< defer legend model invalidation + UseEmbeddedWidgets = 0x0010, //!< Layer nodes may optionally include extra embedded widgets (if used in QgsLayerTreeView). Added in 2.16 // behavioral flags AllowNodeReorder = 0x1000, //!< Allow reordering with drag'n'drop diff --git a/src/core/layertree/qgslayertreenode.h b/src/core/layertree/qgslayertreenode.h index 111fa5972e3..428993522e0 100644 --- a/src/core/layertree/qgslayertreenode.h +++ b/src/core/layertree/qgslayertreenode.h @@ -58,6 +58,7 @@ class QDomElement; * - "embedded_project" - path to the external project (embedded root node only) * - "legend/..." - properties for legend appearance customization * - "expandedLegendNodes" - list of layer's legend nodes' rules in expanded state + * - "embeddedWidgets/..." - properties for embedded widgets (layer node only) * * @see also QgsLayerTree, QgsLayerTreeLayer, QgsLayerTreeGroup * @note added in 2.4 diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5824b6f93c2..ec397b73b77 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -153,6 +153,8 @@ SET(QGIS_GUI_SRCS editorwidgets/qgsvaluerelationwidgetfactory.cpp layertree/qgscustomlayerorderwidget.cpp + layertree/qgslayertreeembeddedconfigwidget.cpp + layertree/qgslayertreeembeddedwidgetregistry.cpp layertree/qgslayertreemapcanvasbridge.cpp layertree/qgslayertreeview.cpp layertree/qgslayertreeviewdefaultactions.cpp @@ -574,6 +576,8 @@ SET(QGIS_GUI_MOC_HDRS editorwidgets/qgsvaluerelationwidgetwrapper.h layertree/qgscustomlayerorderwidget.h + layertree/qgslayertreeembeddedconfigwidget.h + layertree/qgslayertreeembeddedwidgetregistry.h layertree/qgslayertreemapcanvasbridge.h layertree/qgslayertreeview.h layertree/qgslayertreeviewdefaultactions.h @@ -669,6 +673,9 @@ SET(QGIS_GUI_HDRS editorwidgets/qgsvaluemapwidgetfactory.h editorwidgets/qgsvaluerelationwidgetfactory.h + layertree/qgslayertreeembeddedconfigwidget.h + layertree/qgslayertreeembeddedwidgetregistry.h + raster/qgsrasterrendererwidget.h ) diff --git a/src/gui/layertree/qgslayertreeembeddedconfigwidget.cpp b/src/gui/layertree/qgslayertreeembeddedconfigwidget.cpp new file mode 100644 index 00000000000..36d83686f5d --- /dev/null +++ b/src/gui/layertree/qgslayertreeembeddedconfigwidget.cpp @@ -0,0 +1,87 @@ +#include "qgslayertreeembeddedconfigwidget.h" + +#include "qgslayertree.h" +#include "qgslayertreeembeddedwidgetregistry.h" + +#include + +QgsLayerTreeEmbeddedConfigWidget::QgsLayerTreeEmbeddedConfigWidget( QgsLayerTreeLayer* nodeLayer, QWidget* parent ) + : QWidget( parent ) + , mNodeLayer( nodeLayer ) +{ + setupUi( this ); + + connect( mBtnAdd, SIGNAL(clicked(bool)), this, SLOT(onAddClicked())); + connect( mBtnRemove, SIGNAL(clicked(bool)), this, SLOT(onRemoveClicked())); + + // populate available + QStringList lst; + Q_FOREACH ( const QString& providerId, QgsLayerTreeEmbeddedWidgetRegistry::instance()->providers() ) + { + QgsLayerTreeEmbeddedWidgetProvider* provider = QgsLayerTreeEmbeddedWidgetRegistry::instance()->provider( providerId ); + lst << provider->id(); + } + mListAvailable->setModel( new QStringListModel( lst, this ) ); + + // populate used + QStringList lstUsed; + int widgetsCount = nodeLayer->customProperty( "embeddedWidgets/count", 0 ).toInt(); + for ( int i = 0; i < widgetsCount; ++i ) + { + QString providerId = nodeLayer->customProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) ).toString(); + if ( /*QgsLayerTreeEmbeddedWidgetProvider* provider =*/ QgsLayerTreeEmbeddedWidgetRegistry::instance()->provider( providerId ) ) + { + lstUsed << providerId; + } + } + mListUsed->setModel( new QStringListModel( lstUsed, this ) ); +} + +void QgsLayerTreeEmbeddedConfigWidget::onAddClicked() +{ + if (!mListAvailable->currentIndex().isValid()) + return; + + QString providerId = mListAvailable->model()->data( mListAvailable->currentIndex() ).toString(); + if (QStringListModel* model = qobject_cast(mListUsed->model())) + { + int row = model->rowCount(); + model->insertRow( row ); + model->setData( model->index(row, 0), providerId ); + //QStringList lst = model->stringList(); + //lst << providerId; + //model->setStringList( lst ); + } + + updateCustomProperties(); +} + +void QgsLayerTreeEmbeddedConfigWidget::onRemoveClicked() +{ + if (!mListUsed->currentIndex().isValid()) + return; + + int row = mListUsed->currentIndex().row(); + mListUsed->model()->removeRow( row ); + + updateCustomProperties(); +} + +void QgsLayerTreeEmbeddedConfigWidget::updateCustomProperties() +{ + // clear old properties + int widgetsCount = mNodeLayer->customProperty( "embeddedWidgets/count", 0 ).toInt(); + for ( int i = 0; i < widgetsCount; ++i ) + { + mNodeLayer->removeCustomProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) ); + } + + // setup new properties + int newCount = mListUsed->model()->rowCount(); + mNodeLayer->setCustomProperty( "embeddedWidgets/count", newCount ); + for ( int i = 0; i < newCount; ++i ) + { + QString providerId = mListUsed->model()->data( mListUsed->model()->index(i, 0) ).toString(); + mNodeLayer->setCustomProperty( QString( "embeddedWidgets/%1/id" ).arg( i ), providerId ); + } +} diff --git a/src/gui/layertree/qgslayertreeembeddedconfigwidget.h b/src/gui/layertree/qgslayertreeembeddedconfigwidget.h new file mode 100644 index 00000000000..238340a1c4c --- /dev/null +++ b/src/gui/layertree/qgslayertreeembeddedconfigwidget.h @@ -0,0 +1,25 @@ +#ifndef QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H +#define QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H + +#include "ui_qgslayertreeembeddedconfigwidget.h" + +class QgsLayerTreeLayer; + +class GUI_EXPORT QgsLayerTreeEmbeddedConfigWidget : public QWidget, protected Ui::QgsLayerTreeEmbeddedConfigWidget +{ + Q_OBJECT + public: + QgsLayerTreeEmbeddedConfigWidget( QgsLayerTreeLayer* nodeLayer, QWidget* parent = nullptr ); + + private slots: + void onAddClicked(); + void onRemoveClicked(); + + private: + void updateCustomProperties(); + + private: + QgsLayerTreeLayer* mNodeLayer; +}; + +#endif // QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H diff --git a/src/gui/layertree/qgslayertreeembeddedwidgetregistry.cpp b/src/gui/layertree/qgslayertreeembeddedwidgetregistry.cpp new file mode 100644 index 00000000000..fdfcc1d5868 --- /dev/null +++ b/src/gui/layertree/qgslayertreeembeddedwidgetregistry.cpp @@ -0,0 +1,155 @@ +/*************************************************************************** + qgslayertreeembeddedwidgetregistry.cpp + -------------------------------------- + Date : May 2016 + Copyright : (C) 2016 by Martin Dobias + Email : wonder dot sk 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 "qgslayertreeembeddedwidgetregistry.h" + + +#include "qgsmaplayer.h" + + +class TransparencyWidgetProvider : public QgsLayerTreeEmbeddedWidgetProvider +{ + public: + virtual QString id() const override + { + return "transparency"; + } + + virtual TransparencyWidget* createWidget( QgsMapLayer* layer, QMap properties ) override + { + Q_UNUSED( properties ); + return new TransparencyWidget( layer ); + } + + virtual bool supportsLayer( QgsMapLayer *layer ) override + { + return layer->type() == QgsMapLayer::VectorLayer || layer->type() == QgsMapLayer::RasterLayer; + } +}; + + +///// + + +QgsLayerTreeEmbeddedWidgetRegistry*QgsLayerTreeEmbeddedWidgetRegistry::instance() +{ + static QgsLayerTreeEmbeddedWidgetRegistry* sInstance( new QgsLayerTreeEmbeddedWidgetRegistry() ); + return sInstance; +} + +QgsLayerTreeEmbeddedWidgetRegistry::~QgsLayerTreeEmbeddedWidgetRegistry() +{ + Q_FOREACH ( QgsLayerTreeEmbeddedWidgetProvider* provider, mProviders ) + { + removeProvider( provider->id() ); + } +} + +QStringList QgsLayerTreeEmbeddedWidgetRegistry::providers() const +{ + return mProviders.keys(); +} + +QgsLayerTreeEmbeddedWidgetProvider*QgsLayerTreeEmbeddedWidgetRegistry::provider( const QString& providerId ) const +{ + return mProviders.value( providerId ); +} + +bool QgsLayerTreeEmbeddedWidgetRegistry::addProvider( QgsLayerTreeEmbeddedWidgetProvider* provider ) +{ + if ( mProviders.contains( provider->id() ) ) + return false; + + mProviders.insert( provider->id(), provider ); + return true; +} + +bool QgsLayerTreeEmbeddedWidgetRegistry::removeProvider( const QString& providerId ) +{ + if ( !mProviders.contains( providerId ) ) + return false; + + delete mProviders.take( providerId ); + return true; +} + +QgsLayerTreeEmbeddedWidgetRegistry::QgsLayerTreeEmbeddedWidgetRegistry() +{ + addProvider( new TransparencyWidgetProvider() ); +} + + +///// + +#include +#include +#include +#include "qgsrasterlayer.h" +#include "qgsrasterrenderer.h" +#include "qgsvectorlayer.h" + +TransparencyWidget::TransparencyWidget( QgsMapLayer* layer ) + : mLayer( layer ) +{ + setAutoFillBackground( true ); // override the content from model + QLabel* l = new QLabel( "Transparency", this ); + mSlider = new QSlider( Qt::Horizontal, this ); + mSlider->setRange( 0, 100 ); + QHBoxLayout* lay = new QHBoxLayout(); + lay->addWidget( l ); + lay->addWidget( mSlider ); + setLayout( lay ); + + connect( mSlider, SIGNAL( valueChanged( int ) ), this, SLOT( sliderValueChanged( int ) ) ); + + // init from layer + if ( mLayer->type() == QgsMapLayer::VectorLayer ) + { + mSlider->setValue( qobject_cast( mLayer )->layerTransparency() ); + connect( mLayer, SIGNAL( layerTransparencyChanged( int ) ), this, SLOT( layerTrChanged() ) ); + } + else if ( mLayer->type() == QgsMapLayer::RasterLayer ) + { + mSlider->setValue( 100 - qobject_cast( mLayer )->renderer()->opacity() * 100 ); + // TODO: there is no signal for raster layers + } +} + +QSize TransparencyWidget::sizeHint() const +{ + return QWidget::sizeHint(); + //return QSize(200,200); // horizontal seems ignored, vertical is used for spacing +} + +void TransparencyWidget::sliderValueChanged( int value ) +{ + if ( mLayer->type() == QgsMapLayer::VectorLayer ) + { + qobject_cast( mLayer )->setLayerTransparency( value ); + } + else if ( mLayer->type() == QgsMapLayer::RasterLayer ) + { + qobject_cast( mLayer )->renderer()->setOpacity( 1 - value / 100. ); + } + + mLayer->triggerRepaint(); +} + +void TransparencyWidget::layerTrChanged() +{ + mSlider->blockSignals( true ); + mSlider->setValue( qobject_cast( mLayer )->layerTransparency() ); + mSlider->blockSignals( false ); +} diff --git a/src/gui/layertree/qgslayertreeembeddedwidgetregistry.h b/src/gui/layertree/qgslayertreeembeddedwidgetregistry.h new file mode 100644 index 00000000000..dd85dee570c --- /dev/null +++ b/src/gui/layertree/qgslayertreeembeddedwidgetregistry.h @@ -0,0 +1,108 @@ +/*************************************************************************** + qgslayertreeembeddedwidgetregistry.h + -------------------------------------- + Date : May 2016 + Copyright : (C) 2016 by Martin Dobias + Email : wonder dot sk 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 QGSLAYERTREEEMBEDDEDWIDGETREGISTRY_H +#define QGSLAYERTREEEMBEDDEDWIDGETREGISTRY_H + +#include +#include + +#if 0 +/** Base class for embedded widgets */ +class QgsLayerTreeEmbeddedWidget : public QWidget +{ + public: + +}; +#endif + +class QgsMapLayer; + +/** Provider interface to be implemented */ +class GUI_EXPORT QgsLayerTreeEmbeddedWidgetProvider +{ + public: + virtual ~QgsLayerTreeEmbeddedWidgetProvider() {} + + //! unique name of the provider (among other providers) + virtual QString id() const = 0; + + //! factory to create widgets + virtual QWidget* createWidget( QgsMapLayer* layer, QMap properties ) = 0; + + //! whether it makes sense to use this widget for a particular layer + virtual bool supportsLayer( QgsMapLayer* layer ) = 0; + +}; + +/** Singleton registry */ +class GUI_EXPORT QgsLayerTreeEmbeddedWidgetRegistry +{ + public: + + /** Means of accessing canonical single instance */ + static QgsLayerTreeEmbeddedWidgetRegistry* instance(); + + ~QgsLayerTreeEmbeddedWidgetRegistry(); + + QStringList providers() const; + + /** Get provider object from the provider's ID */ + QgsLayerTreeEmbeddedWidgetProvider* provider( const QString& providerId ) const; + + /** Register a provider, takes ownership of the object. + * Returns true on success, false if the provider is already registered. */ + bool addProvider( QgsLayerTreeEmbeddedWidgetProvider* provider ); + + /** Unregister a provider, the provider object is deleted. + * Returns true on success, false if the provider was not registered. */ + bool removeProvider( const QString& providerId ); + + protected: + QgsLayerTreeEmbeddedWidgetRegistry(); + + + //! storage of all the providers + QMap mProviders; +}; + + +//// + + +// TMP +class QSlider; +class QgsMapLayer; +#include +class TransparencyWidget : public QWidget +{ + Q_OBJECT + public: + TransparencyWidget( QgsMapLayer* layer ); + + virtual QSize sizeHint() const override; + + public slots: + void sliderValueChanged( int value ); + void layerTrChanged(); + + private: + QgsMapLayer* mLayer; + QSlider* mSlider; +}; + + + +#endif // QGSLAYERTREEEMBEDDEDWIDGETREGISTRY_H diff --git a/src/gui/layertree/qgslayertreeview.cpp b/src/gui/layertree/qgslayertreeview.cpp index 7530c264f0f..0f7e38d3b78 100644 --- a/src/gui/layertree/qgslayertreeview.cpp +++ b/src/gui/layertree/qgslayertreeview.cpp @@ -16,6 +16,7 @@ #include "qgslayertreeview.h" #include "qgslayertree.h" +#include "qgslayertreeembeddedwidgetregistry.h" #include "qgslayertreemodel.h" #include "qgslayertreemodellegendnode.h" #include "qgslayertreeviewdefaultactions.h" @@ -24,6 +25,7 @@ #include #include + QgsLayerTreeView::QgsLayerTreeView( QWidget *parent ) : QTreeView( parent ) , mDefaultActions( nullptr ) @@ -129,6 +131,28 @@ void QgsLayerTreeView::modelRowsInserted( const QModelIndex& index, int start, i if ( !parentNode ) return; + // EMBEDDED WIDGETS + if ( layerTreeModel()->testFlag( QgsLayerTreeModel::UseEmbeddedWidgets ) && QgsLayerTree::isLayer( parentNode ) ) + { + QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( parentNode ); + if ( QgsMapLayer* layer = nodeLayer->layer() ) + { + int widgetsCount = nodeLayer->customProperty( "embeddedWidgets/count", 0 ).toInt(); + QList legendNodes = layerTreeModel()->layerLegendNodes( nodeLayer ); + for ( int i = 0; i < widgetsCount; ++i ) + { + // TODO: check that the legend nodes are actually the placeholders for embedded widgets + QString providerId = nodeLayer->customProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) ).toString(); + if ( QgsLayerTreeEmbeddedWidgetProvider* provider = QgsLayerTreeEmbeddedWidgetRegistry::instance()->provider( providerId ) ) + { + QModelIndex index = layerTreeModel()->legendNode2index( legendNodes[i] ); + setIndexWidget( index, provider->createWidget( layer, QMap() ) ); + } + } + } + } + + if ( QgsLayerTree::isLayer( parentNode ) ) { // if ShowLegendAsTree flag is enabled in model, we may need to expand some legend nodes diff --git a/src/ui/qgslayertreeembeddedconfigwidget.ui b/src/ui/qgslayertreeembeddedconfigwidget.ui new file mode 100644 index 00000000000..18626b316a9 --- /dev/null +++ b/src/ui/qgslayertreeembeddedconfigwidget.ui @@ -0,0 +1,85 @@ + + + QgsLayerTreeEmbeddedConfigWidget + + + + 0 + 0 + 580 + 300 + + + + Form + + + + + + Available widgets + + + + + + + Used widgets + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + -> + + + + + + + <- + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + +