Skip to content
Permalink
Browse files

Legend customization via layer node's custom properties

This allows for reordering, renaming and removal of legend nodes.
Composer either uses default project layer tree (auto-update on)
or customized layer tree (auto-update off).
  • Loading branch information
wonder-sk committed Sep 1, 2014
1 parent 3021bda commit 812f671f826d8b5c8ae0bbcfe938ea9287d068d6

Large diffs are not rendered by default.

@@ -40,6 +40,8 @@ class QgsComposerLegendWidget: public QgsComposerItemBaseWidget, private Ui::Qgs
/**Updates the legend layers and groups*/
void updateLegend();

QgsComposerLegend* legend() { return mLegend; }

public slots:

void on_mWrapCharLineEdit_textChanged( const QString& text );
@@ -74,7 +76,7 @@ class QgsComposerLegendWidget: public QgsComposerItemBaseWidget, private Ui::Qgs
void on_mAddToolButton_clicked();
void on_mEditPushButton_clicked();
void on_mCountToolButton_clicked( bool checked );
void on_mUpdatePushButton_clicked();
void resetLayerNodeToDefaults();
void on_mUpdateAllPushButton_clicked();
void on_mAddGroupToolButton_clicked();

@@ -36,9 +36,7 @@ QgsComposerLegend::QgsComposerLegend( QgsComposition* composition )
, mCustomLayerTree( 0 )
, mComposerMap( 0 )
{
mLegendModel2 = new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot() );
mLegendModel2->setFlag( QgsLayerTreeModel::AllowSymbologyChangeState, false );
mLegendModel2->setFlag( QgsLayerTreeModel::AllowNodeReorder, true );
mLegendModel2 = new QgsLegendModelV2( QgsProject::instance()->layerTreeRoot() );

adjustBoxSize();

@@ -253,11 +251,6 @@ bool QgsComposerLegend::writeXML( QDomElement& elem, QDomDocument & doc ) const
style( QgsComposerLegendStyle::Symbol ).writeXML( "symbol", composerLegendStyles, doc );
style( QgsComposerLegendStyle::SymbolLabel ).writeXML( "symbolLabel", composerLegendStyles, doc );

#if 0
//write model properties
mLegendModel.writeXML( composerLegendElem, doc );
#endif

if ( mCustomLayerTree )
{
// if not using auto-update - store the custom layer tree
@@ -327,21 +320,8 @@ bool QgsComposerLegend::readXML( const QDomElement& itemElem, const QDomDocument
mComposerMap = mComposition->getComposerMapById( itemElem.attribute( "map" ).toInt() );
}

#if 0
//read model properties
QDomNodeList modelNodeList = itemElem.elementsByTagName( "Model" );
if ( modelNodeList.size() > 0 )
{
QDomElement modelElem = modelNodeList.at( 0 ).toElement();
mLegendModel.readXML( modelElem, doc );
}
#endif

QDomElement layerTreeElem = itemElem.firstChildElement( "layer-tree-group" );
if ( layerTreeElem.isNull() )
{
setCustomLayerTree( QgsLayerTreeGroup::readXML( layerTreeElem ) );
}
setCustomLayerTree( QgsLayerTreeGroup::readXML( layerTreeElem ) );

//restore general composer item properties
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
@@ -437,3 +417,45 @@ void QgsComposerLegend::invalidateCurrentMap()
}
mComposerMap = 0;
}

// -------------------------------------------------------------------------
#include "qgslayertreemodellegendnode.h"
#include "qgsvectorlayer.h"

QgsLegendModelV2::QgsLegendModelV2( QgsLayerTreeGroup* rootNode, QObject* parent )
: QgsLayerTreeModel( rootNode, parent )
{
setFlag( QgsLayerTreeModel::AllowSymbologyChangeState, false );
setFlag( QgsLayerTreeModel::AllowNodeReorder, true );
}

QVariant QgsLegendModelV2::data( const QModelIndex& index, int role ) const
{
// handle custom layer node labels
if ( QgsLayerTreeNode* node = index2node( index ) )
{
if ( QgsLayerTree::isLayer( node ) && ( role == Qt::DisplayRole || role == Qt::EditRole ) && !node->customProperty( "legend/title-label" ).isNull() )
{
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
QString name = node->customProperty( "legend/title-label" ).toString();
if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole )
{
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() );
if ( vlayer && vlayer->pendingFeatureCount() >= 0 )
name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
}
return name;
}
}

return QgsLayerTreeModel::data( index, role );
}

Qt::ItemFlags QgsLegendModelV2::flags( const QModelIndex& index ) const
{
// make the legend nodes selectable even if they are not by default
if ( index2symnode( index ) )
return QgsLayerTreeModel::flags( index ) | Qt::ItemIsSelectable;

return QgsLayerTreeModel::flags( index );
}
@@ -21,6 +21,7 @@
#include "qgscomposerlegendstyle.h"
#include "qgscomposeritem.h"
#include "qgscomposerlegenditem.h"
#include "qgslayertreemodel.h"
#include "qgslegendmodel.h"
#include "qgslegendsettings.h"

@@ -32,6 +33,20 @@ class QgsComposerMap;
class QgsLegendRenderer;


/** \ingroup MapComposer
* Item model implementation based on layer tree model for composer legend
*/
class QgsLegendModelV2 : public QgsLayerTreeModel
{
public:
QgsLegendModelV2( QgsLayerTreeGroup* rootNode, QObject *parent = 0 );

QVariant data( const QModelIndex& index, int role ) const;

Qt::ItemFlags flags( const QModelIndex &index ) const;
};


/** \ingroup MapComposer
* A legend that can be placed onto a map composition
*/
@@ -59,7 +74,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem
QgsLegendModel* model() {return &mLegendModel;}

//! @note added in 2.6
QgsLayerTreeModel* modelV2() { return mLegendModel2; }
QgsLegendModelV2* modelV2() { return mLegendModel2; }

//! @note added in 2.6
void setAutoUpdateModel( bool autoUpdate );
@@ -165,7 +180,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem

QgsLegendModel mLegendModel;

QgsLayerTreeModel* mLegendModel2;
QgsLegendModelV2* mLegendModel2;
QgsLayerTreeGroup* mCustomLayerTree;

QgsLegendSettings mSettings;
@@ -461,9 +461,9 @@ void QgsLayerTreeModel::setRootGroup( QgsLayerTreeGroup* newRootGroup )

mRootNode = newRootGroup;

connectToRootNode();

endResetModel();

connectToRootNode();
}

void QgsLayerTreeModel::refreshLayerSymbology( QgsLayerTreeLayer* nodeLayer )
@@ -104,6 +104,10 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
//! Return layer node to which a symbology node belongs to. Returns null pointer if index is not a symbology node.
QgsLayerTreeLayer* layerNodeForSymbologyNode( const QModelIndex& index ) const;

// TODO: rename to some better name
//! @note added in 2.6
static QgsLayerTreeModelLegendNode* index2symnode( const QModelIndex& index );

//! Return list of legend nodes attached to a particular layer node
//! @note added in 2.6
QList<QgsLayerTreeModelLegendNode*> layerLegendNodes( QgsLayerTreeLayer* nodeLayer );
@@ -166,8 +170,6 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
//! emit dataChanged() for layer tree node items
void recursivelyEmitDataChanged( const QModelIndex& index = QModelIndex() );

static QgsLayerTreeModelLegendNode* index2symnode( const QModelIndex& index );

static const QIcon& iconGroup();

protected:
@@ -145,7 +145,7 @@ QVariant QgsSymbolV2LegendNode::data( int role ) const
}
else if ( role == Qt::EditRole )
{
return mItem.label();
return mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
}
else if ( role == Qt::DecorationRole )
{
@@ -55,6 +55,9 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
virtual bool isEmbeddedInParent() const { return mEmbeddedInParent; }
virtual void setEmbeddedInParent( bool embedded ) { mEmbeddedInParent = embedded; }

virtual QString userLabel() const { return mUserLabel; }
virtual void setUserLabel( const QString& userLabel ) { mUserLabel = userLabel; }

struct ItemContext
{
//! Painter
@@ -99,6 +102,7 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
protected:
QgsLayerTreeLayer* mParent;
bool mEmbeddedInParent;
QString mUserLabel;
};

#include "qgslegendsymbolitemv2.h"
@@ -127,16 +131,14 @@ class CORE_EXPORT QgsSymbolV2LegendNode : public QgsLayerTreeModelLegendNode

virtual void setEmbeddedInParent( bool embedded );

void setUserLabel( const QString& userLabel ) { mUserLabel = userLabel; }
QString userLabel() const { return mUserLabel; }
void setUserLabel( const QString& userLabel ) { mUserLabel = userLabel; updateLabel(); }

private:
void updateLabel();

private:
QgsLegendSymbolItemV2 mItem;
mutable QIcon mIcon; // cached symbol preview
QString mUserLabel;
QString mLabel;
};

@@ -142,10 +142,12 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*

void QgsLayerTreeNode::removeChildrenPrivate( int from, int count )
{
if ( count <= 0 )
if ( from < 0 || count <= 0 )
return;

int to = from + count - 1;
if ( to >= mChildren.count() )
return;
emit willRemoveChildren( this, from, to );
while ( --count >= 0 )
{
@@ -558,7 +558,7 @@ QSizeF QgsLegendRenderer::drawGroupTitle( QgsLayerTreeGroup* nodeGroup, QPainter

QgsComposerLegendStyle::Style QgsLegendRenderer::nodeLegendStyle( QgsLayerTreeNode* node, QgsLayerTreeModel* model )
{
QString style = node->customProperty( "legendStyle" ).toString();
QString style = node->customProperty( "legend/title-style" ).toString();
if ( style == "hidden" )
return QgsComposerLegendStyle::Hidden;
else if ( style == "group" )
@@ -597,7 +597,7 @@ void QgsLegendRenderer::setNodeLegendStyle( QgsLayerTreeNode* node, QgsComposerL
}

if ( !str.isEmpty() )
node->setCustomProperty( "legendStyle", str );
node->setCustomProperty( "legend/title-style", str );
else
node->removeCustomProperty( "legendStyle" );
node->removeCustomProperty( "legend/title-style" );
}

0 comments on commit 812f671

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