Skip to content

Commit 6e140b9

Browse files
committed
[FEATURE] Edit legend symbols directly from layer tree
This adds a new "edit symbol" item to the right-click menu for a renderer child legend item (eg categories for the categorised renderer). Selecting it opens a symbol editor dialog which allows for directly editing the classes symbol. It's much faster than opening the layer properties and going through the style tab.
1 parent 83e139a commit 6e140b9

20 files changed

+265
-2
lines changed

python/core/layertree/qgslayertreemodellegendnode.sip

+14
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@ class QgsSymbolV2LegendNode : QgsLayerTreeModelLegendNode
145145
//! @note added in 2.10
146146
QSize minimumIconSize() const;
147147

148+
/** Returns the symbol used by the legend node.
149+
* @see setSymbol()
150+
* @note added in QGIS 2.14
151+
*/
152+
const QgsSymbolV2* symbol() const;
153+
154+
/** Sets the symbol to be used by the legend node. The symbol change is also propagated
155+
* to the associated vector layer's renderer.
156+
* @param symbol new symbol for node. Ownership is transferred.
157+
* @see symbol()
158+
* @note added in QGIS 2.14
159+
*/
160+
void setSymbol( QgsSymbolV2* symbol /Transfer/ );
161+
148162
public slots:
149163

150164
/** Checks all items belonging to the same layer as this node.

python/core/symbology-ng/qgscategorizedsymbolrendererv2.sip

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
155155
// @note added in 2.5
156156
virtual bool legendSymbolItemChecked( const QString& key );
157157

158+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol /Transfer/ );
159+
158160
//! item in symbology was checked
159161
// @note added in 2.5
160162
virtual void checkLegendSymbolItem( const QString& key, bool state = true );

python/core/symbology-ng/qgsgraduatedsymbolrendererv2.sip

+2
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
282282
//! @note added in 2.6
283283
virtual void checkLegendSymbolItem( const QString& key, bool state = true );
284284

285+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol /Transfer/ );
286+
285287
//! If supported by the renderer, return classification attribute for the use in legend
286288
//! @note added in 2.6
287289
virtual QString legendClassificationAttribute();

python/core/symbology-ng/qgslegendsymbolitemv2.sip

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class QgsLegendSymbolItemV2
4848
//! Key of the parent legend node. For legends with tree hierarchy
4949
//! @note added in 2.8
5050
QString parentRuleKey() const;
51+
52+
//! Set symbol of the item. Takes ownership of symbol.
53+
void setSymbol( QgsSymbolV2* s /Transfer/ );
5154
};
5255

5356

python/core/symbology-ng/qgsrendererv2.sip

+7
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ class QgsFeatureRendererV2
200200
//! @note added in 2.5
201201
virtual void checkLegendSymbolItem( const QString& key, bool state = true );
202202

203+
/** Sets the symbol to be used for a legend symbol item.
204+
* @param key rule key for legend symbol
205+
* @param symbol new symbol for legend item. Ownership is transferred to renderer.
206+
* @note added in QGIS 2.14
207+
*/
208+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol /Transfer/ );
209+
203210
//! return a list of item text / symbol
204211
//! @note not available in python bindings
205212
// virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, const QString& rule = "" );

python/core/symbology-ng/qgsrulebasedrendererv2.sip

+2
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
358358
//! @note added in 2.5
359359
virtual void checkLegendSymbolItem( const QString& key, bool state = true );
360360

361+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol /Transfer/ );
362+
361363
//! return a list of item text / symbol
362364
//! @note not available in python bindings
363365
// virtual QgsLegendSymbolList legendSymbolItems();

src/app/qgsapplayertreeviewmenuprovider.cpp

+40-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
#include "qgslayertreemodellegendnode.h"
1010
#include "qgslayertreeviewdefaultactions.h"
1111
#include "qgsmaplayerstyleguiutils.h"
12+
#include "qgsmaplayerregistry.h"
1213
#include "qgsproject.h"
1314
#include "qgsrasterlayer.h"
15+
#include "qgsrendererv2.h"
16+
#include "qgssymbolv2.h"
17+
#include "qgsstylev2.h"
1418
#include "qgsvectordataprovider.h"
1519
#include "qgsvectorlayer.h"
1620
#include "qgslayertreeregistrybridge.h"
17-
21+
#include "qgssymbolv2selectordialog.h"
1822

1923
QgsAppLayerTreeViewMenuProvider::QgsAppLayerTreeViewMenuProvider( QgsLayerTreeView* view, QgsMapCanvas* canvas )
2024
: mView( view )
@@ -200,6 +204,14 @@ QMenu* QgsAppLayerTreeViewMenuProvider::createContextMenu()
200204
symbolNode, SLOT( checkAllItems() ) );
201205
menu->addAction( QgsApplication::getThemeIcon( "/mActionHideAllLayers.png" ), tr( "&Hide All Items" ),
202206
symbolNode, SLOT( uncheckAllItems() ) );
207+
menu->addSeparator();
208+
QAction* editSymbolAction = new QAction( tr( "Edit Symbol..." ), menu );
209+
//store the layer id and rule key in action, so we can later retrieve the corresponding
210+
//legend node, if it still exists
211+
editSymbolAction->setProperty( "layerId", symbolNode->layerNode()->layerId() );
212+
editSymbolAction->setProperty( "ruleKey", symbolNode->data( QgsLayerTreeModelLegendNode::RuleKeyRole ).toString() );
213+
connect( editSymbolAction, SIGNAL( triggered() ), this, SLOT( editSymbolLegendNodeSymbol() ) );
214+
menu->addAction( editSymbolAction );
203215
}
204216
}
205217
}
@@ -352,3 +364,30 @@ void QgsAppLayerTreeViewMenuProvider::addCustomLayerActions( QMenu* menu, QgsMap
352364
menu->addSeparator();
353365
}
354366
}
367+
368+
void QgsAppLayerTreeViewMenuProvider::editSymbolLegendNodeSymbol()
369+
{
370+
QAction* action = qobject_cast< QAction*>( sender() );
371+
if ( !action )
372+
return;
373+
374+
QString layerId = action->property( "layerId" ).toString();
375+
QString ruleKey = action->property( "ruleKey" ).toString();
376+
377+
QgsSymbolV2LegendNode* node = dynamic_cast<QgsSymbolV2LegendNode*>( mView->layerTreeModel()->findLegendNode( layerId, ruleKey ) );
378+
if ( !node )
379+
return;
380+
381+
const QgsSymbolV2* originalSymbol = node->symbol();
382+
if ( !originalSymbol )
383+
return;
384+
385+
QScopedPointer< QgsSymbolV2 > symbol( originalSymbol->clone() );
386+
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() );
387+
QgsSymbolV2SelectorDialog dlg( symbol.data(), QgsStyleV2::defaultStyle(), vlayer, mView );
388+
dlg.setMapCanvas( mCanvas );
389+
if ( dlg.exec() )
390+
{
391+
node->setSymbol( symbol.take() );
392+
}
393+
}

src/app/qgsapplayertreeviewmenuprovider.h

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class QgsAppLayerTreeViewMenuProvider : public QObject, public QgsLayerTreeViewM
4444
QgsMapCanvas* mCanvas;
4545

4646
QMap< QgsMapLayer::LayerType, QList< LegendLayerAction > > mLegendLayerActionMap;
47+
48+
private slots:
49+
50+
void editSymbolLegendNodeSymbol();
4751
};
4852

4953
#endif // QGSAPPLAYERTREEVIEWMENUPROVIDER_H

src/core/layertree/qgslayertreemodellegendnode.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,29 @@ QSize QgsSymbolV2LegendNode::minimumIconSize() const
185185
return minSz;
186186
}
187187

188+
const QgsSymbolV2* QgsSymbolV2LegendNode::symbol() const
189+
{
190+
return mItem.symbol();
191+
}
192+
193+
void QgsSymbolV2LegendNode::setSymbol( QgsSymbolV2* symbol )
194+
{
195+
if ( !symbol )
196+
return;
197+
198+
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
199+
if ( !vlayer || !vlayer->rendererV2() )
200+
return;
201+
202+
mItem.setSymbol( symbol );
203+
vlayer->rendererV2()->setLegendSymbolItem( mItem.ruleKey(), symbol->clone() );
204+
205+
mPixmap = QPixmap();
206+
207+
emit dataChanged();
208+
vlayer->triggerRepaint();
209+
}
210+
188211
void QgsSymbolV2LegendNode::checkAllItems()
189212
{
190213
checkAll( true );

src/core/layertree/qgslayertreemodellegendnode.h

+14
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,20 @@ class CORE_EXPORT QgsSymbolV2LegendNode : public QgsLayerTreeModelLegendNode
175175
//! @note added in 2.10
176176
QSize minimumIconSize() const;
177177

178+
/** Returns the symbol used by the legend node.
179+
* @see setSymbol()
180+
* @note added in QGIS 2.14
181+
*/
182+
const QgsSymbolV2* symbol() const;
183+
184+
/** Sets the symbol to be used by the legend node. The symbol change is also propagated
185+
* to the associated vector layer's renderer.
186+
* @param symbol new symbol for node. Ownership is transferred.
187+
* @see symbol()
188+
* @note added in QGIS 2.14
189+
*/
190+
void setSymbol( QgsSymbolV2* symbol );
191+
178192
public slots:
179193

180194
/** Checks all items belonging to the same layer as this node.

src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,16 @@ bool QgsCategorizedSymbolRendererV2::legendSymbolItemChecked( const QString& key
954954
return true;
955955
}
956956

957+
void QgsCategorizedSymbolRendererV2::setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol )
958+
{
959+
bool ok;
960+
int index = key.toInt( &ok );
961+
if ( ok )
962+
updateCategorySymbol( index, symbol );
963+
else
964+
delete symbol;
965+
}
966+
957967
void QgsCategorizedSymbolRendererV2::checkLegendSymbolItem( const QString& key, bool state )
958968
{
959969
bool ok;

src/core/symbology-ng/qgscategorizedsymbolrendererv2.h

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
186186
// @note added in 2.5
187187
virtual bool legendSymbolItemChecked( const QString& key ) override;
188188

189+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol ) override;
190+
189191
//! item in symbology was checked
190192
// @note added in 2.5
191193
virtual void checkLegendSymbolItem( const QString& key, bool state = true ) override;

src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,15 @@ void QgsGraduatedSymbolRendererV2::checkLegendSymbolItem( const QString& key, bo
14331433
updateRangeRenderState( index, state );
14341434
}
14351435

1436+
void QgsGraduatedSymbolRendererV2::setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol )
1437+
{
1438+
bool ok;
1439+
int index = key.toInt( &ok );
1440+
if ( ok )
1441+
updateRangeSymbol( index, symbol );
1442+
else
1443+
delete symbol;
1444+
}
14361445

14371446
void QgsGraduatedSymbolRendererV2::addClass( QgsSymbolV2* symbol )
14381447
{

src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h

+2
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
325325
//! @note added in 2.6
326326
virtual void checkLegendSymbolItem( const QString& key, bool state = true ) override;
327327

328+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol ) override;
329+
328330
//! If supported by the renderer, return classification attribute for the use in legend
329331
//! @note added in 2.6
330332
virtual QString legendClassificationAttribute() const override { return classAttribute(); }

src/core/symbology-ng/qgslegendsymbolitemv2.h

-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ class CORE_EXPORT QgsLegendSymbolItemV2
6666
//! @note added in 2.8
6767
QString parentRuleKey() const { return mParentKey; }
6868

69-
protected:
7069
//! Set symbol of the item. Takes ownership of symbol.
7170
void setSymbol( QgsSymbolV2* s );
7271

src/core/symbology-ng/qgsrendererv2.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,12 @@ void QgsFeatureRendererV2::checkLegendSymbolItem( const QString& key, bool state
671671
Q_UNUSED( state );
672672
}
673673

674+
void QgsFeatureRendererV2::setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol )
675+
{
676+
Q_UNUSED( key );
677+
delete symbol;
678+
}
679+
674680
QgsLegendSymbolList QgsFeatureRendererV2::legendSymbolItems( double scaleDenominator, const QString& rule )
675681
{
676682
Q_UNUSED( scaleDenominator );

src/core/symbology-ng/qgsrendererv2.h

+7
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ class CORE_EXPORT QgsFeatureRendererV2
228228
//! @note added in 2.5
229229
virtual void checkLegendSymbolItem( const QString& key, bool state = true );
230230

231+
/** Sets the symbol to be used for a legend symbol item.
232+
* @param key rule key for legend symbol
233+
* @param symbol new symbol for legend item. Ownership is transferred to renderer.
234+
* @note added in QGIS 2.14
235+
*/
236+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol );
237+
231238
//! return a list of item text / symbol
232239
//! @note not available in python bindings
233240
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, const QString& rule = "" );

src/core/symbology-ng/qgsrulebasedrendererv2.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,15 @@ void QgsRuleBasedRendererV2::checkLegendSymbolItem( const QString& key, bool sta
990990
rule->setActive( state );
991991
}
992992

993+
void QgsRuleBasedRendererV2::setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol )
994+
{
995+
Rule* rule = mRootRule->findRuleByKey( key );
996+
if ( rule )
997+
rule->setSymbol( symbol );
998+
else
999+
delete symbol;
1000+
}
1001+
9931002
QgsLegendSymbolList QgsRuleBasedRendererV2::legendSymbolItems( double scaleDenominator, const QString& rule )
9941003
{
9951004
return mRootRule->legendSymbolItems( scaleDenominator, rule );

src/core/symbology-ng/qgsrulebasedrendererv2.h

+2
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
418418
//! @note added in 2.5
419419
virtual void checkLegendSymbolItem( const QString& key, bool state = true ) override;
420420

421+
virtual void setLegendSymbolItem( const QString& key, QgsSymbolV2* symbol ) override;
422+
421423
//! return a list of item text / symbol
422424
//! @note not available in python bindings
423425
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, const QString& rule = "" ) override;

0 commit comments

Comments
 (0)