Skip to content

Commit ea2395d

Browse files
committed
Integration of embedded widgets into layer tree + config GUI
1 parent 2b1560c commit ea2395d

14 files changed

+547
-1
lines changed

python/core/qgsdataitem.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class QgsDataItem : QObject
7575

7676
/** Create children. Children are not expected to have parent set.
7777
* This method MUST BE THREAD SAFE. */
78-
virtual QVector<QgsDataItem*> createChildren();
78+
virtual QVector<QgsDataItem*> createChildren() /Factory/;
7979

8080
enum State
8181
{

src/app/qgisapp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,6 +2815,7 @@ void QgisApp::initLayerTreeView()
28152815
model->setFlag( QgsLayerTreeModel::AllowNodeRename );
28162816
model->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility );
28172817
model->setFlag( QgsLayerTreeModel::ShowLegendAsTree );
2818+
model->setFlag( QgsLayerTreeModel::UseEmbeddedWidgets );
28182819
model->setAutoCollapseLegendNodes( 10 );
28192820

28202821
mLayerTreeView->setModel( model );

src/app/qgsapplayertreeviewmenuprovider.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
237237
duplicateLayersAction->setEnabled( false );
238238
}
239239

240+
QAction* embeddedAction = menu->addAction( tr( "Embedded widgets..."), this, SLOT( editEmbeddedWidgets() ) );
241+
embeddedAction->setProperty( "layerId", layer->id() );
242+
240243
addCustomLayerActions( menu, layer );
241244

242245
if ( layer && QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
@@ -555,3 +558,26 @@ void QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor( const QColor &co
555558
newSymbol->setColor( color );
556559
node->setSymbol( newSymbol );
557560
}
561+
562+
#include "qgslayertreeembeddedconfigwidget.h"
563+
void QgsAppLayerTreeViewMenuProvider::editEmbeddedWidgets()
564+
{
565+
QAction* action = qobject_cast< QAction*>( sender() );
566+
if ( !action )
567+
return;
568+
569+
QString layerId = action->property( "layerId" ).toString();
570+
QgsLayerTreeLayer* nodeLayer = QgsProject::instance()->layerTreeRoot()->findLayer( layerId );
571+
if ( !nodeLayer )
572+
return;
573+
574+
QDialog d;
575+
QgsLayerTreeEmbeddedConfigWidget* widget = new QgsLayerTreeEmbeddedConfigWidget(nodeLayer, &d);
576+
577+
QLayout* l = new QVBoxLayout(&d);
578+
l->addWidget(widget);
579+
d.setLayout(l);
580+
d.exec();
581+
582+
mView->layerTreeModel()->refreshLayerLegend( nodeLayer );
583+
}

src/app/qgsapplayertreeviewmenuprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM
6969
void setVectorSymbolColor( const QColor &color );
7070
void editSymbolLegendNodeSymbol();
7171
void setSymbolLegendNodeColor( const QColor &color );
72+
void editEmbeddedWidgets();
7273
};
7374

7475
#endif // QGSAPPLAYERTREEVIEWMENUPROVIDER_H

src/core/layertree/qgslayertreemodel.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,21 @@ void QgsLayerTreeModel::removeLegendFromLayer( QgsLayerTreeLayer* nodeLayer )
11491149
}
11501150
}
11511151

1152+
class EmbeddedWidgetLegendNode : public QgsLayerTreeModelLegendNode
1153+
{
1154+
public:
1155+
EmbeddedWidgetLegendNode( QgsLayerTreeLayer* nodeL )
1156+
: QgsLayerTreeModelLegendNode( nodeL )
1157+
{
1158+
}
1159+
1160+
virtual QVariant data( int role ) const override
1161+
{
1162+
Q_UNUSED( role );
1163+
return QVariant();
1164+
}
1165+
1166+
};
11521167

11531168
void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
11541169
{
@@ -1169,6 +1184,16 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
11691184
// apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
11701185
QgsMapLayerLegendUtils::applyLayerNodeProperties( nodeL, lstNew );
11711186

1187+
if ( testFlag( UseEmbeddedWidgets ) )
1188+
{
1189+
int widgetsCount = nodeL->customProperty( "embeddedWidgets/count", 0 ).toInt();
1190+
while ( widgetsCount > 0 )
1191+
{
1192+
lstNew.insert( 0, new EmbeddedWidgetLegendNode( nodeL ) );
1193+
--widgetsCount;
1194+
}
1195+
}
1196+
11721197
QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
11731198

11741199
bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();

src/core/layertree/qgslayertreemodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
8080
ShowRasterPreviewIcon = 0x0002, //!< Will use real preview of raster layer as icon (may be slow)
8181
ShowLegendAsTree = 0x0004, //!< For legends that support it, will show them in a tree instead of a list (needs also ShowLegend). Added in 2.8
8282
DeferredLegendInvalidation = 0x0008, //!< defer legend model invalidation
83+
UseEmbeddedWidgets = 0x0010, //!< Layer nodes may optionally include extra embedded widgets (if used in QgsLayerTreeView). Added in 2.16
8384

8485
// behavioral flags
8586
AllowNodeReorder = 0x1000, //!< Allow reordering with drag'n'drop

src/core/layertree/qgslayertreenode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class QDomElement;
5858
* - "embedded_project" - path to the external project (embedded root node only)
5959
* - "legend/..." - properties for legend appearance customization
6060
* - "expandedLegendNodes" - list of layer's legend nodes' rules in expanded state
61+
* - "embeddedWidgets/..." - properties for embedded widgets (layer node only)
6162
*
6263
* @see also QgsLayerTree, QgsLayerTreeLayer, QgsLayerTreeGroup
6364
* @note added in 2.4

src/gui/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ SET(QGIS_GUI_SRCS
153153
editorwidgets/qgsvaluerelationwidgetfactory.cpp
154154

155155
layertree/qgscustomlayerorderwidget.cpp
156+
layertree/qgslayertreeembeddedconfigwidget.cpp
157+
layertree/qgslayertreeembeddedwidgetregistry.cpp
156158
layertree/qgslayertreemapcanvasbridge.cpp
157159
layertree/qgslayertreeview.cpp
158160
layertree/qgslayertreeviewdefaultactions.cpp
@@ -574,6 +576,8 @@ SET(QGIS_GUI_MOC_HDRS
574576
editorwidgets/qgsvaluerelationwidgetwrapper.h
575577

576578
layertree/qgscustomlayerorderwidget.h
579+
layertree/qgslayertreeembeddedconfigwidget.h
580+
layertree/qgslayertreeembeddedwidgetregistry.h
577581
layertree/qgslayertreemapcanvasbridge.h
578582
layertree/qgslayertreeview.h
579583
layertree/qgslayertreeviewdefaultactions.h
@@ -669,6 +673,9 @@ SET(QGIS_GUI_HDRS
669673
editorwidgets/qgsvaluemapwidgetfactory.h
670674
editorwidgets/qgsvaluerelationwidgetfactory.h
671675

676+
layertree/qgslayertreeembeddedconfigwidget.h
677+
layertree/qgslayertreeembeddedwidgetregistry.h
678+
672679
raster/qgsrasterrendererwidget.h
673680
)
674681

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include "qgslayertreeembeddedconfigwidget.h"
2+
3+
#include "qgslayertree.h"
4+
#include "qgslayertreeembeddedwidgetregistry.h"
5+
6+
#include <QStringListModel>
7+
8+
QgsLayerTreeEmbeddedConfigWidget::QgsLayerTreeEmbeddedConfigWidget( QgsLayerTreeLayer* nodeLayer, QWidget* parent )
9+
: QWidget( parent )
10+
, mNodeLayer( nodeLayer )
11+
{
12+
setupUi( this );
13+
14+
connect( mBtnAdd, SIGNAL(clicked(bool)), this, SLOT(onAddClicked()));
15+
connect( mBtnRemove, SIGNAL(clicked(bool)), this, SLOT(onRemoveClicked()));
16+
17+
// populate available
18+
QStringList lst;
19+
Q_FOREACH ( const QString& providerId, QgsLayerTreeEmbeddedWidgetRegistry::instance()->providers() )
20+
{
21+
QgsLayerTreeEmbeddedWidgetProvider* provider = QgsLayerTreeEmbeddedWidgetRegistry::instance()->provider( providerId );
22+
lst << provider->id();
23+
}
24+
mListAvailable->setModel( new QStringListModel( lst, this ) );
25+
26+
// populate used
27+
QStringList lstUsed;
28+
int widgetsCount = nodeLayer->customProperty( "embeddedWidgets/count", 0 ).toInt();
29+
for ( int i = 0; i < widgetsCount; ++i )
30+
{
31+
QString providerId = nodeLayer->customProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) ).toString();
32+
if ( /*QgsLayerTreeEmbeddedWidgetProvider* provider =*/ QgsLayerTreeEmbeddedWidgetRegistry::instance()->provider( providerId ) )
33+
{
34+
lstUsed << providerId;
35+
}
36+
}
37+
mListUsed->setModel( new QStringListModel( lstUsed, this ) );
38+
}
39+
40+
void QgsLayerTreeEmbeddedConfigWidget::onAddClicked()
41+
{
42+
if (!mListAvailable->currentIndex().isValid())
43+
return;
44+
45+
QString providerId = mListAvailable->model()->data( mListAvailable->currentIndex() ).toString();
46+
if (QStringListModel* model = qobject_cast<QStringListModel*>(mListUsed->model()))
47+
{
48+
int row = model->rowCount();
49+
model->insertRow( row );
50+
model->setData( model->index(row, 0), providerId );
51+
//QStringList lst = model->stringList();
52+
//lst << providerId;
53+
//model->setStringList( lst );
54+
}
55+
56+
updateCustomProperties();
57+
}
58+
59+
void QgsLayerTreeEmbeddedConfigWidget::onRemoveClicked()
60+
{
61+
if (!mListUsed->currentIndex().isValid())
62+
return;
63+
64+
int row = mListUsed->currentIndex().row();
65+
mListUsed->model()->removeRow( row );
66+
67+
updateCustomProperties();
68+
}
69+
70+
void QgsLayerTreeEmbeddedConfigWidget::updateCustomProperties()
71+
{
72+
// clear old properties
73+
int widgetsCount = mNodeLayer->customProperty( "embeddedWidgets/count", 0 ).toInt();
74+
for ( int i = 0; i < widgetsCount; ++i )
75+
{
76+
mNodeLayer->removeCustomProperty( QString( "embeddedWidgets/%1/id" ).arg( i ) );
77+
}
78+
79+
// setup new properties
80+
int newCount = mListUsed->model()->rowCount();
81+
mNodeLayer->setCustomProperty( "embeddedWidgets/count", newCount );
82+
for ( int i = 0; i < newCount; ++i )
83+
{
84+
QString providerId = mListUsed->model()->data( mListUsed->model()->index(i, 0) ).toString();
85+
mNodeLayer->setCustomProperty( QString( "embeddedWidgets/%1/id" ).arg( i ), providerId );
86+
}
87+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H
2+
#define QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H
3+
4+
#include "ui_qgslayertreeembeddedconfigwidget.h"
5+
6+
class QgsLayerTreeLayer;
7+
8+
class GUI_EXPORT QgsLayerTreeEmbeddedConfigWidget : public QWidget, protected Ui::QgsLayerTreeEmbeddedConfigWidget
9+
{
10+
Q_OBJECT
11+
public:
12+
QgsLayerTreeEmbeddedConfigWidget( QgsLayerTreeLayer* nodeLayer, QWidget* parent = nullptr );
13+
14+
private slots:
15+
void onAddClicked();
16+
void onRemoveClicked();
17+
18+
private:
19+
void updateCustomProperties();
20+
21+
private:
22+
QgsLayerTreeLayer* mNodeLayer;
23+
};
24+
25+
#endif // QGSLAYERTREEEMBEDDEDCONFIGWIDGET_H

0 commit comments

Comments
 (0)