Skip to content

Commit 012c347

Browse files
committedJan 22, 2015
Restructure the code in QgsLayerTreeModel to group legend-related code
1 parent 56069c9 commit 012c347

File tree

2 files changed

+194
-105
lines changed

2 files changed

+194
-105
lines changed
 

‎src/core/layertree/qgslayertreemodel.cpp

Lines changed: 169 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,7 @@ QgsLayerTreeModel::QgsLayerTreeModel( QgsLayerTreeGroup* rootNode, QObject *pare
4848

4949
QgsLayerTreeModel::~QgsLayerTreeModel()
5050
{
51-
foreach ( QList<QgsLayerTreeModelLegendNode*> nodeL, mOriginalLegendNodes )
52-
qDeleteAll( nodeL );
53-
mOriginalLegendNodes.clear();
54-
mLegendNodes.clear(); // does not own the nodes
51+
legendCleanup();
5552
}
5653

5754
QgsLayerTreeNode* QgsLayerTreeModel::index2node( const QModelIndex& index ) const
@@ -63,26 +60,11 @@ QgsLayerTreeNode* QgsLayerTreeModel::index2node( const QModelIndex& index ) cons
6360
return qobject_cast<QgsLayerTreeNode*>( obj );
6461
}
6562

66-
QgsLayerTreeModelLegendNode* QgsLayerTreeModel::index2legendNode( const QModelIndex& index )
67-
{
68-
return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
69-
}
70-
71-
QModelIndex QgsLayerTreeModel::legendNode2index( QgsLayerTreeModelLegendNode* legendNode )
72-
{
73-
QModelIndex parentIndex = node2index( legendNode->layerNode() );
74-
Q_ASSERT( parentIndex.isValid() );
75-
int row = mLegendNodes[legendNode->layerNode()].indexOf( legendNode );
76-
if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
77-
return QModelIndex();
78-
return index( row, 0, parentIndex );
79-
}
80-
8163

8264
int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
8365
{
84-
if ( index2legendNode( parent ) )
85-
return 0; // they are leaves
66+
if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
67+
return legendNodeRowCount( nodeLegend );
8668

8769
QgsLayerTreeNode* n = index2node( parent );
8870
if ( !n )
@@ -93,11 +75,7 @@ int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
9375
if ( !testFlag( ShowLegend ) )
9476
return 0;
9577

96-
QgsLayerTreeLayer* nL = QgsLayerTree::toLayer( n );
97-
if ( mLegendNodes[nL].count() == 1 && mLegendNodes[nL][0]->isEmbeddedInParent() )
98-
return 0;
99-
100-
return mLegendNodes[nL].count();
78+
return legendRootRowCount( QgsLayerTree::toLayer( n ) );
10179
}
10280

10381
return n->children().count();
@@ -115,20 +93,22 @@ QModelIndex QgsLayerTreeModel::index( int row, int column, const QModelIndex &pa
11593
row < 0 || row >= rowCount( parent ) )
11694
return QModelIndex();
11795

96+
if ( QgsLayerTreeModelLegendNode* nodeLegend = index2legendNode( parent ) )
97+
return legendNodeIndex( row, column, nodeLegend );
98+
11899
QgsLayerTreeNode *n = index2node( parent );
119100
if ( !n )
120101
return QModelIndex(); // have no children
121102

122103
if ( testFlag( ShowLegend ) && QgsLayerTree::isLayer( n ) )
123104
{
124-
QgsLayerTreeLayer* nL = QgsLayerTree::toLayer( n );
125-
Q_ASSERT( mLegendNodes.contains( nL ) );
126-
return createIndex( row, column, static_cast<QObject*>( mLegendNodes[nL].at( row ) ) );
105+
return legendRootIndex( row, column, QgsLayerTree::toLayer( n ) );
127106
}
128107

129108
return createIndex( row, column, static_cast<QObject*>( n->children().at( row ) ) );
130109
}
131110

111+
132112
QModelIndex QgsLayerTreeModel::parent( const QModelIndex &child ) const
133113
{
134114
if ( !child.isValid() )
@@ -159,17 +139,14 @@ QModelIndex QgsLayerTreeModel::parent( const QModelIndex &child ) const
159139
return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
160140
}
161141

142+
162143
QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
163144
{
164145
if ( !index.isValid() || index.column() > 1 )
165146
return QVariant();
166147

167148
if ( QgsLayerTreeModelLegendNode* sym = index2legendNode( index ) )
168-
{
169-
if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
170-
return QVariant();
171-
return sym->data( role );
172-
}
149+
return legendNodeData( sym, role );
173150

174151
QgsLayerTreeNode* node = index2node( index );
175152
if ( role == Qt::DisplayRole || role == Qt::EditRole )
@@ -223,9 +200,9 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
223200
QIcon icon;
224201

225202
// if there's just on legend entry that should be embedded in layer - do that!
226-
if ( testFlag( ShowLegend ) && mLegendNodes[nodeLayer].count() == 1 && mLegendNodes[nodeLayer][0]->isEmbeddedInParent() )
203+
if ( testFlag( ShowLegend ) && legendEmbeddedInParent( nodeLayer ) )
227204
{
228-
icon = QIcon( qvariant_cast<QPixmap>( mLegendNodes[nodeLayer][0]->data( Qt::DecorationRole ) ) );
205+
icon = legendIconEmbeddedInParent( nodeLayer );
229206
}
230207
else if ( layer->type() == QgsMapLayer::VectorLayer )
231208
{
@@ -297,6 +274,7 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
297274
return QVariant();
298275
}
299276

277+
300278
Qt::ItemFlags QgsLayerTreeModel::flags( const QModelIndex& index ) const
301279
{
302280
if ( !index.isValid() )
@@ -308,12 +286,7 @@ Qt::ItemFlags QgsLayerTreeModel::flags( const QModelIndex& index ) const
308286
}
309287

310288
if ( QgsLayerTreeModelLegendNode* symn = index2legendNode( index ) )
311-
{
312-
Qt::ItemFlags f = symn->flags();
313-
if ( !testFlag( AllowLegendChangeState ) )
314-
f &= ~Qt::ItemIsUserCheckable;
315-
return f;
316-
}
289+
return legendNodeFlags( symn );
317290

318291
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
319292

@@ -471,11 +444,6 @@ QgsLayerTreeLayer* QgsLayerTreeModel::layerNodeForSymbologyNode( const QModelInd
471444
return symNode ? symNode->layerNode() : 0;
472445
}
473446

474-
QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer )
475-
{
476-
return mLegendNodes.value( nodeLayer );
477-
}
478-
479447
QgsLayerTreeGroup*QgsLayerTreeModel::rootGroup() const
480448
{
481449
return mRootNode;
@@ -487,8 +455,7 @@ void QgsLayerTreeModel::setRootGroup( QgsLayerTreeGroup* newRootGroup )
487455

488456
disconnectFromRootNode();
489457

490-
Q_ASSERT( mLegendNodes.isEmpty() );
491-
Q_ASSERT( mOriginalLegendNodes.isEmpty() );
458+
Q_ASSERT( mLegend.isEmpty() );
492459

493460
mRootNode = newRootGroup;
494461

@@ -621,12 +588,7 @@ void QgsLayerTreeModel::setLegendMapViewData( double mapUnitsPerPixel, int dpi,
621588
mLegendMapViewScale = scale;
622589

623590
// now invalidate legend nodes!
624-
QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelLegendNode*> > x;
625-
foreach ( const QList<QgsLayerTreeModelLegendNode*>& lst, mOriginalLegendNodes )
626-
{
627-
foreach ( QgsLayerTreeModelLegendNode* legendNode, lst )
628-
legendNode->invalidateMapBasedData();
629-
}
591+
legendInvalidateMapBasedData();
630592
}
631593

632594
void QgsLayerTreeModel::legendMapViewData( double* mapUnitsPerPixel, int* dpi, double* scale )
@@ -767,50 +729,6 @@ void QgsLayerTreeModel::legendNodeDataChanged()
767729
}
768730

769731

770-
void QgsLayerTreeModel::removeLegendFromLayer( QgsLayerTreeLayer* nodeLayer )
771-
{
772-
if ( mLegendNodes.contains( nodeLayer ) )
773-
{
774-
qDeleteAll( mOriginalLegendNodes[nodeLayer] );
775-
mOriginalLegendNodes.remove( nodeLayer );
776-
mLegendNodes.remove( nodeLayer );
777-
}
778-
}
779-
780-
781-
void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
782-
{
783-
if ( !nodeL->layer() )
784-
return;
785-
786-
QgsMapLayerLegend* layerLegend = nodeL->layer()->legend();
787-
if ( !layerLegend )
788-
return;
789-
790-
QList<QgsLayerTreeModelLegendNode*> lstNew = layerLegend->createLayerTreeModelLegendNodes( nodeL );
791-
792-
// apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
793-
QgsMapLayerLegendUtils::applyLayerNodeProperties( nodeL, lstNew );
794-
795-
QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
796-
797-
bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
798-
799-
if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, filteredLstNew.count() - 1 );
800-
801-
foreach ( QgsLayerTreeModelLegendNode* n, lstNew )
802-
{
803-
n->setParent( this );
804-
connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
805-
}
806-
807-
mOriginalLegendNodes[nodeL] = lstNew;
808-
mLegendNodes[nodeL] = filteredLstNew;
809-
810-
if ( ! isEmbedded ) endInsertRows();
811-
}
812-
813-
814732
void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer* nodeLayer )
815733
{
816734
if ( !nodeLayer->layer() )
@@ -1109,3 +1027,155 @@ QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::filterLegendNodes( const
11091027

11101028
return filtered;
11111029
}
1030+
1031+
1032+
1033+
///////////////////////////////////////////////////////////////////////////////
1034+
// Legend nodes routines - start
1035+
1036+
void QgsLayerTreeModel::legendCleanup()
1037+
{
1038+
foreach ( const LayerLegendData& data, mLegend )
1039+
qDeleteAll( data.originalNodes );
1040+
mLegend.clear();
1041+
}
1042+
1043+
1044+
void QgsLayerTreeModel::removeLegendFromLayer( QgsLayerTreeLayer* nodeLayer )
1045+
{
1046+
if ( mLegend.contains( nodeLayer ) )
1047+
{
1048+
qDeleteAll( mLegend[nodeLayer].originalNodes );
1049+
mLegend.remove( nodeLayer );
1050+
}
1051+
}
1052+
1053+
1054+
void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )
1055+
{
1056+
if ( !nodeL->layer() )
1057+
return;
1058+
1059+
QgsMapLayerLegend* layerLegend = nodeL->layer()->legend();
1060+
if ( !layerLegend )
1061+
return;
1062+
1063+
QList<QgsLayerTreeModelLegendNode*> lstNew = layerLegend->createLayerTreeModelLegendNodes( nodeL );
1064+
1065+
// apply filtering defined in layer node's custom properties (reordering, filtering, custom labels)
1066+
QgsMapLayerLegendUtils::applyLayerNodeProperties( nodeL, lstNew );
1067+
1068+
QList<QgsLayerTreeModelLegendNode*> filteredLstNew = filterLegendNodes( lstNew );
1069+
1070+
bool isEmbedded = filteredLstNew.count() == 1 && filteredLstNew[0]->isEmbeddedInParent();
1071+
1072+
if ( ! isEmbedded ) beginInsertRows( node2index( nodeL ), 0, filteredLstNew.count() - 1 );
1073+
1074+
foreach ( QgsLayerTreeModelLegendNode* n, lstNew )
1075+
{
1076+
n->setParent( this );
1077+
connect( n, SIGNAL( dataChanged() ), this, SLOT( legendNodeDataChanged() ) );
1078+
}
1079+
1080+
mLegend[nodeL].originalNodes = lstNew;
1081+
mLegend[nodeL].activeNodes = filteredLstNew;
1082+
1083+
if ( ! isEmbedded ) endInsertRows();
1084+
}
1085+
1086+
1087+
QgsLayerTreeModelLegendNode* QgsLayerTreeModel::index2legendNode( const QModelIndex& index )
1088+
{
1089+
return qobject_cast<QgsLayerTreeModelLegendNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
1090+
}
1091+
1092+
1093+
QModelIndex QgsLayerTreeModel::legendNode2index( QgsLayerTreeModelLegendNode* legendNode )
1094+
{
1095+
QModelIndex parentIndex = node2index( legendNode->layerNode() );
1096+
Q_ASSERT( parentIndex.isValid() );
1097+
int row = mLegend[legendNode->layerNode()].activeNodes.indexOf( legendNode );
1098+
if ( row < 0 ) // legend node may be filtered (exists within the list of original nodes, but not in active nodes)
1099+
return QModelIndex();
1100+
return index( row, 0, parentIndex );
1101+
}
1102+
1103+
1104+
int QgsLayerTreeModel::legendNodeRowCount( QgsLayerTreeModelLegendNode* node ) const
1105+
{
1106+
Q_UNUSED( node );
1107+
return 0; // they are leaves
1108+
}
1109+
1110+
1111+
int QgsLayerTreeModel::legendRootRowCount( QgsLayerTreeLayer* nL ) const
1112+
{
1113+
if ( legendEmbeddedInParent( nL ) )
1114+
return 0;
1115+
1116+
return mLegend[nL].activeNodes.count();
1117+
}
1118+
1119+
1120+
QModelIndex QgsLayerTreeModel::legendRootIndex( int row, int column, QgsLayerTreeLayer* nL ) const
1121+
{
1122+
Q_ASSERT( mLegend.contains( nL ) );
1123+
return createIndex( row, column, static_cast<QObject*>( mLegend[nL].activeNodes.at( row ) ) );
1124+
}
1125+
1126+
1127+
QModelIndex QgsLayerTreeModel::legendNodeIndex( int row, int column, QgsLayerTreeModelLegendNode* node ) const
1128+
{
1129+
Q_UNUSED( row );
1130+
Q_UNUSED( column );
1131+
Q_UNUSED( node );
1132+
return QModelIndex(); // have no children
1133+
}
1134+
1135+
1136+
QVariant QgsLayerTreeModel::legendNodeData( QgsLayerTreeModelLegendNode* node, int role ) const
1137+
{
1138+
if ( role == Qt::CheckStateRole && !testFlag( AllowLegendChangeState ) )
1139+
return QVariant();
1140+
return node->data( role );
1141+
}
1142+
1143+
1144+
Qt::ItemFlags QgsLayerTreeModel::legendNodeFlags( QgsLayerTreeModelLegendNode* node ) const
1145+
{
1146+
Qt::ItemFlags f = node->flags();
1147+
if ( !testFlag( AllowLegendChangeState ) )
1148+
f &= ~Qt::ItemIsUserCheckable;
1149+
return f;
1150+
}
1151+
1152+
1153+
bool QgsLayerTreeModel::legendEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const
1154+
{
1155+
const LayerLegendData& data = mLegend[nodeLayer];
1156+
return data.activeNodes.count() == 1 && data.activeNodes[0]->isEmbeddedInParent();
1157+
}
1158+
1159+
1160+
QIcon QgsLayerTreeModel::legendIconEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const
1161+
{
1162+
return QIcon( qvariant_cast<QPixmap>( mLegend[nodeLayer].activeNodes[0]->data( Qt::DecorationRole ) ) );
1163+
}
1164+
1165+
1166+
QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLayerTreeLayer* nodeLayer )
1167+
{
1168+
return mLegend.value( nodeLayer ).activeNodes;
1169+
}
1170+
1171+
void QgsLayerTreeModel::legendInvalidateMapBasedData()
1172+
{
1173+
foreach ( const LayerLegendData& data, mLegend )
1174+
{
1175+
foreach ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
1176+
legendNode->invalidateMapBasedData();
1177+
}
1178+
}
1179+
1180+
// Legend nodes routines - end
1181+
///////////////////////////////////////////////////////////////////////////////

‎src/core/layertree/qgslayertreemodel.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,22 +216,41 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
216216
//! Filter nodes from QgsMapLayerLegend according to the current filtering rules
217217
QList<QgsLayerTreeModelLegendNode*> filterLegendNodes( const QList<QgsLayerTreeModelLegendNode*>& nodes );
218218

219+
int legendRootRowCount( QgsLayerTreeLayer* nL ) const;
220+
int legendNodeRowCount( QgsLayerTreeModelLegendNode* node ) const;
221+
QModelIndex legendRootIndex( int row, int column, QgsLayerTreeLayer* nL ) const;
222+
QModelIndex legendNodeIndex( int row, int column, QgsLayerTreeModelLegendNode* node ) const;
223+
QVariant legendNodeData( QgsLayerTreeModelLegendNode* node, int role ) const;
224+
Qt::ItemFlags legendNodeFlags( QgsLayerTreeModelLegendNode* node ) const;
225+
bool legendEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
226+
QIcon legendIconEmbeddedInParent( QgsLayerTreeLayer* nodeLayer ) const;
227+
void legendCleanup();
228+
void legendInvalidateMapBasedData();
229+
219230
protected:
220231
//! Pointer to the root node of the layer tree. Not owned by the model
221232
QgsLayerTreeGroup* mRootNode;
222233
//! Set of flags for the model
223234
Flags mFlags;
224-
//! Active legend nodes for each layer node. May have been filtered.
225-
//! Owner of legend nodes is still mOriginalLegendNodes !
226-
QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelLegendNode*> > mLegendNodes;
227-
//! Data structure for storage of legend nodes for each layer.
228-
//! These are nodes as received from QgsMapLayerLegend
229-
QMap<QgsLayerTreeLayer*, QList<QgsLayerTreeModelLegendNode*> > mOriginalLegendNodes;
230235
//! Current index - will be underlined
231236
QPersistentModelIndex mCurrentIndex;
232237
//! Minimal number of nodes when legend should be automatically collapsed. -1 = disabled
233238
int mAutoCollapseLegendNodesCount;
234239

240+
struct LayerLegendData
241+
{
242+
//! Active legend nodes. May have been filtered.
243+
//! Owner of legend nodes is still originalNodes !
244+
QList<QgsLayerTreeModelLegendNode*> activeNodes;
245+
//! Data structure for storage of legend nodes.
246+
//! These are nodes as received from QgsMapLayerLegend
247+
QList<QgsLayerTreeModelLegendNode*> originalNodes;
248+
//LayerLegendTreeNode* treeRoot; // if null using ordinary
249+
};
250+
251+
//! Per layer data about layer's legend nodes
252+
QMap<QgsLayerTreeLayer*, LayerLegendData> mLegend;
253+
235254
QFont mFontLayer;
236255
QFont mFontGroup;
237256

0 commit comments

Comments
 (0)
Please sign in to comment.