Skip to content

Commit

Permalink
Legend customization via layer node's custom properties
Browse files Browse the repository at this point in the history
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 812f671
Show file tree
Hide file tree
Showing 14 changed files with 420 additions and 228 deletions.
272 changes: 152 additions & 120 deletions src/app/composer/qgscomposerlegendwidget.cpp

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/app/composer/qgscomposerlegendwidget.h
Expand Up @@ -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 );
Expand Down Expand Up @@ -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();

Expand Down
66 changes: 44 additions & 22 deletions src/core/composer/qgscomposerlegend.cpp
Expand Up @@ -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();

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" );
Expand Down Expand Up @@ -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 );
}
19 changes: 17 additions & 2 deletions src/core/composer/qgscomposerlegend.h
Expand Up @@ -21,6 +21,7 @@
#include "qgscomposerlegendstyle.h"
#include "qgscomposeritem.h"
#include "qgscomposerlegenditem.h"
#include "qgslayertreemodel.h"
#include "qgslegendmodel.h"
#include "qgslegendsettings.h"

Expand All @@ -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
*/
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -165,7 +180,7 @@ class CORE_EXPORT QgsComposerLegend : public QgsComposerItem

QgsLegendModel mLegendModel;

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

QgsLegendSettings mSettings;
Expand Down
4 changes: 2 additions & 2 deletions src/core/layertree/qgslayertreemodel.cpp
Expand Up @@ -461,9 +461,9 @@ void QgsLayerTreeModel::setRootGroup( QgsLayerTreeGroup* newRootGroup )

mRootNode = newRootGroup;

connectToRootNode();

endResetModel();

connectToRootNode();
}

void QgsLayerTreeModel::refreshLayerSymbology( QgsLayerTreeLayer* nodeLayer )
Expand Down
6 changes: 4 additions & 2 deletions src/core/layertree/qgslayertreemodel.h
Expand Up @@ -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 );
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/core/layertree/qgslayertreemodellegendnode.cpp
Expand Up @@ -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 )
{
Expand Down
8 changes: 5 additions & 3 deletions src/core/layertree/qgslayertreemodellegendnode.h
Expand Up @@ -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
Expand Down Expand Up @@ -99,6 +102,7 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
protected:
QgsLayerTreeLayer* mParent;
bool mEmbeddedInParent;
QString mUserLabel;
};

#include "qgslegendsymbolitemv2.h"
Expand Down Expand Up @@ -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;
};

Expand Down
4 changes: 3 additions & 1 deletion src/core/layertree/qgslayertreenode.cpp
Expand Up @@ -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 )
{
Expand Down
6 changes: 3 additions & 3 deletions src/core/qgslegendrenderer.cpp
Expand Up @@ -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" )
Expand Down Expand Up @@ -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.