2014-05-21 15:28:23 +07:00
|
|
|
/***************************************************************************
|
|
|
|
qgslayertreemodel.cpp
|
|
|
|
--------------------------------------
|
|
|
|
Date : May 2014
|
|
|
|
Copyright : (C) 2014 by Martin Dobias
|
|
|
|
Email : wonder dot sk at gmail dot com
|
|
|
|
***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
2014-05-05 16:58:10 +02:00
|
|
|
#include "qgslayertreemodel.h"
|
|
|
|
|
2014-05-17 22:14:36 +07:00
|
|
|
#include "qgslayertree.h"
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
#include <QMimeData>
|
|
|
|
#include <QTextStream>
|
|
|
|
|
|
|
|
#include "qgsdataitem.h"
|
2014-05-15 14:52:18 +07:00
|
|
|
#include "qgspluginlayer.h"
|
|
|
|
#include "qgsrasterlayer.h"
|
2014-05-05 16:58:10 +02:00
|
|
|
#include "qgsrendererv2.h"
|
2014-05-15 14:52:18 +07:00
|
|
|
#include "qgssymbollayerv2utils.h"
|
2014-05-05 16:58:10 +02:00
|
|
|
#include "qgsvectorlayer.h"
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeModel::QgsLayerTreeModel( QgsLayerTreeGroup* rootNode, QObject *parent )
|
|
|
|
: QAbstractItemModel( parent )
|
|
|
|
, mRootNode( rootNode )
|
|
|
|
, mFlags( ShowSymbology )
|
2014-05-22 18:52:31 +07:00
|
|
|
, mCurrentNode( 0 )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( mRootNode );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
connect( mRootNode, SIGNAL( willAddChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillAddChildren( QgsLayerTreeNode*, int, int ) ) );
|
|
|
|
connect( mRootNode, SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeAddedChildren( QgsLayerTreeNode*, int, int ) ) );
|
|
|
|
connect( mRootNode, SIGNAL( willRemoveChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeWillRemoveChildren( QgsLayerTreeNode*, int, int ) ) );
|
|
|
|
connect( mRootNode, SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ), this, SLOT( nodeRemovedChildren() ) );
|
|
|
|
connect( mRootNode, SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode* ) ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QgsLayerTreeModel::~QgsLayerTreeModel()
|
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
foreach ( QList<QgsLayerTreeModelSymbologyNode*> nodeL, mSymbologyNodes )
|
|
|
|
qDeleteAll( nodeL );
|
2014-05-05 16:58:10 +02:00
|
|
|
mSymbologyNodes.clear();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* QgsLayerTreeModel::index2node( const QModelIndex& index ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !index.isValid() )
|
2014-05-05 16:58:10 +02:00
|
|
|
return mRootNode;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QObject* obj = reinterpret_cast<QObject*>( index.internalPointer() );
|
|
|
|
return qobject_cast<QgsLayerTreeNode*>( obj );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeModelSymbologyNode* QgsLayerTreeModel::index2symnode( const QModelIndex& index )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
return qobject_cast<QgsLayerTreeModelSymbologyNode*>( reinterpret_cast<QObject*>( index.internalPointer() ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
int QgsLayerTreeModel::rowCount( const QModelIndex &parent ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( index2symnode( parent ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
|
|
|
return 0; // they are leaves
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* n = index2node( parent );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( parent.isValid() && parent.column() != 0 )
|
2014-05-05 16:58:10 +02:00
|
|
|
return 0;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isLayer( n ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nL = QgsLayerTree::toLayer( n );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
return mSymbologyNodes[nL].count();
|
|
|
|
}
|
|
|
|
|
|
|
|
return n->children().count();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
int QgsLayerTreeModel::columnCount( const QModelIndex &parent ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_UNUSED( parent );
|
2014-05-05 16:58:10 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex QgsLayerTreeModel::index( int row, int column, const QModelIndex &parent ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( column != 0 || row < 0 || row >= rowCount( parent ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* n = index2node( parent );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !n )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeModelSymbologyNode* sym = index2symnode( parent );
|
|
|
|
Q_ASSERT( sym );
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex(); // have no children
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !n || column != 0 || row >= rowCount( parent ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( testFlag( ShowSymbology ) && QgsLayerTree::isLayer( n ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nL = QgsLayerTree::toLayer( n );
|
|
|
|
Q_ASSERT( mSymbologyNodes.contains( nL ) );
|
|
|
|
return createIndex( row, column, static_cast<QObject*>( mSymbologyNodes[nL].at( row ) ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
return createIndex( row, column, static_cast<QObject*>( n->children().at( row ) ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex QgsLayerTreeModel::parent( const QModelIndex &child ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !child.isValid() )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* n = index2node( child );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
QgsLayerTreeNode* parentNode = 0;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !n )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeModelSymbologyNode* sym = index2symnode( child );
|
|
|
|
Q_ASSERT( sym );
|
2014-05-05 16:58:10 +02:00
|
|
|
parentNode = sym->parent();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
parentNode = n->parent(); // must not be null
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( parentNode );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
QgsLayerTreeNode* grandParentNode = parentNode->parent();
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !grandParentNode )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex(); // root node -> invalid index
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
int row = grandParentNode->children().indexOf( parentNode );
|
|
|
|
Q_ASSERT( row >= 0 );
|
|
|
|
return createIndex( row, 0, static_cast<QObject*>( parentNode ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !index.isValid() )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QVariant();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTreeModelSymbologyNode* sym = index2symnode( index ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( role == Qt::DisplayRole )
|
2014-05-05 16:58:10 +02:00
|
|
|
return sym->name();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( role == Qt::DecorationRole )
|
2014-05-05 16:58:10 +02:00
|
|
|
return sym->icon();
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* node = index2node( index );
|
|
|
|
if ( role == Qt::DisplayRole || role == Qt::EditRole )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isGroup( node ) )
|
|
|
|
return QgsLayerTree::toGroup( node )->name();
|
|
|
|
else if ( QgsLayerTree::isLayer( node ) )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
2014-05-15 14:52:18 +07:00
|
|
|
QString name = nodeLayer->layerName();
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( nodeLayer->customProperty( "showFeatureCount", 0 ).toInt() && role == Qt::DisplayRole )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( nodeLayer->layer() );
|
|
|
|
if ( vlayer && vlayer->pendingFeatureCount() >= 0 )
|
2014-05-15 14:52:18 +07:00
|
|
|
name += QString( " [%1]" ).arg( vlayer->pendingFeatureCount() );
|
|
|
|
}
|
|
|
|
return name;
|
|
|
|
}
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
else if ( role == Qt::DecorationRole && index.column() == 0 )
|
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isGroup( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsDataCollectionItem::iconDir();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( QgsLayerTree::isLayer( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer();
|
|
|
|
if ( !layer )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QVariant();
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( layer->type() == QgsMapLayer::RasterLayer )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsLayerItem::iconRaster();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( layer->type() == QgsMapLayer::VectorLayer )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>( layer );
|
2014-05-22 17:55:30 +07:00
|
|
|
if ( vlayer->isEditable() )
|
|
|
|
{
|
|
|
|
if ( vlayer->isModified() )
|
|
|
|
return QIcon( QgsApplication::getThemePixmap( "/mIconEditableEdits.png" ) );
|
|
|
|
else
|
|
|
|
return QIcon( QgsApplication::getThemePixmap( "/mIconEditable.png" ) );
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( vlayer->geometryType() == QGis::Point )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsLayerItem::iconPoint();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( vlayer->geometryType() == QGis::Line )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsLayerItem::iconLine();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( vlayer->geometryType() == QGis::Polygon )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsLayerItem::iconPolygon();
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( vlayer->geometryType() == QGis::NoGeometry )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QgsLayerItem::iconTable();
|
|
|
|
}
|
|
|
|
return QgsLayerItem::iconDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( role == Qt::CheckStateRole )
|
|
|
|
{
|
2014-05-23 00:14:39 +07:00
|
|
|
if ( !testFlag( AllowNodeChangeVisibility ) )
|
2014-05-10 22:18:47 +07:00
|
|
|
return QVariant();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isLayer( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
2014-05-23 00:24:23 +07:00
|
|
|
if ( nodeLayer->layer() && nodeLayer->layer()->type() == QgsMapLayer::VectorLayer )
|
|
|
|
{
|
|
|
|
if ( qobject_cast<QgsVectorLayer*>( nodeLayer->layer() )->geometryType() == QGis::NoGeometry )
|
|
|
|
return QVariant(); // do not show checkbox for non-spatial tables
|
|
|
|
}
|
2014-05-17 22:54:03 +07:00
|
|
|
return nodeLayer->isVisible();
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( QgsLayerTree::isGroup( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeGroup* nodeGroup = QgsLayerTree::toGroup( node );
|
2014-05-05 16:58:10 +02:00
|
|
|
return nodeGroup->isVisible();
|
|
|
|
}
|
|
|
|
}
|
2014-05-11 17:42:27 +07:00
|
|
|
else if ( role == Qt::FontRole )
|
|
|
|
{
|
|
|
|
QFont f;
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( node->customProperty( "embedded" ).toInt() )
|
|
|
|
f.setItalic( true );
|
|
|
|
if ( QgsLayerTree::isLayer( node ) )
|
|
|
|
f.setBold( true );
|
2014-05-22 18:52:31 +07:00
|
|
|
if ( node == mCurrentNode )
|
|
|
|
f.setUnderline( true );
|
2014-05-11 17:42:27 +07:00
|
|
|
return f;
|
|
|
|
}
|
2014-05-22 18:20:47 +07:00
|
|
|
else if ( role == Qt::ToolTipRole )
|
|
|
|
{
|
|
|
|
if ( QgsLayerTree::isLayer( node ) )
|
|
|
|
{
|
|
|
|
if ( QgsMapLayer* layer = QgsLayerTree::toLayer( node )->layer() )
|
|
|
|
return layer->publicSource();
|
|
|
|
}
|
|
|
|
}
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
Qt::ItemFlags QgsLayerTreeModel::flags( const QModelIndex& index ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !index.isValid() )
|
2014-05-23 00:14:39 +07:00
|
|
|
{
|
|
|
|
Qt::ItemFlags rootFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
|
|
if ( testFlag( AllowNodeReorder ) )
|
|
|
|
rootFlags |= Qt::ItemIsDropEnabled;
|
|
|
|
return rootFlags;
|
|
|
|
}
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( index2symnode( index ) )
|
2014-05-23 00:14:39 +07:00
|
|
|
return Qt::ItemIsEnabled; // | Qt::ItemIsSelectable;
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-23 00:14:39 +07:00
|
|
|
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
|
|
if ( testFlag( AllowNodeRename ) )
|
|
|
|
f |= Qt::ItemIsEditable;
|
|
|
|
if ( testFlag( AllowNodeReorder ) )
|
|
|
|
f |= Qt::ItemIsDragEnabled;
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* node = index2node( index );
|
2014-05-23 00:14:39 +07:00
|
|
|
if ( testFlag( AllowNodeChangeVisibility ) && ( QgsLayerTree::isLayer( node ) || QgsLayerTree::isGroup( node ) ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
f |= Qt::ItemIsUserCheckable;
|
2014-05-23 00:14:39 +07:00
|
|
|
if ( testFlag( AllowNodeReorder ) && QgsLayerTree::isGroup( node ) )
|
|
|
|
f |= Qt::ItemIsDropEnabled;
|
2014-05-05 16:58:10 +02:00
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
bool QgsLayerTreeModel::setData( const QModelIndex& index, const QVariant& value, int role )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* node = index2node( index );
|
|
|
|
if ( !node )
|
|
|
|
return QgsLayerTreeModel::setData( index, value, role );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( role == Qt::CheckStateRole )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-23 00:14:39 +07:00
|
|
|
if ( !testFlag( AllowNodeChangeVisibility ) )
|
2014-05-10 22:18:47 +07:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isLayer( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
|
|
|
|
layer->setVisible(( Qt::CheckState )value.toInt() );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( QgsLayerTree::isGroup( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeGroup* group = QgsLayerTree::toGroup( node );
|
|
|
|
group->setVisible(( Qt::CheckState )value.toInt() );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( role == Qt::EditRole )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-23 00:14:39 +07:00
|
|
|
if ( !testFlag( AllowNodeRename ) )
|
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( QgsLayerTree::isLayer( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* layer = QgsLayerTree::toLayer( node );
|
|
|
|
layer->setLayerName( value.toString() );
|
|
|
|
emit dataChanged( index, index );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( QgsLayerTree::isGroup( node ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTree::toGroup( node )->setName( value.toString() );
|
|
|
|
emit dataChanged( index, index );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
return QAbstractItemModel::setData( index, value, role );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex QgsLayerTreeModel::node2index( QgsLayerTreeNode* node ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !node->parent() )
|
2014-05-05 16:58:10 +02:00
|
|
|
return QModelIndex(); // this is the only root item -> invalid index
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex parentIndex = node2index( node->parent() );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
int row = node->parent()->children().indexOf( node );
|
|
|
|
Q_ASSERT( row >= 0 );
|
|
|
|
return index( row, 0, parentIndex );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
static bool _isChildOfNode( QgsLayerTreeNode* child, QgsLayerTreeNode* node )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !child->parent() )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( child->parent() == node )
|
2014-05-05 16:58:10 +02:00
|
|
|
return true;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
return _isChildOfNode( child->parent(), node );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
static bool _isChildOfNodes( QgsLayerTreeNode* child, QList<QgsLayerTreeNode*> nodes )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
foreach ( QgsLayerTreeNode* n, nodes )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( _isChildOfNode( child, n ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QList<QgsLayerTreeNode*> QgsLayerTreeModel::indexes2nodes( const QModelIndexList& list, bool skipInternal ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
|
|
|
QList<QgsLayerTreeNode*> nodes;
|
2014-05-21 15:28:23 +07:00
|
|
|
foreach ( QModelIndex index, list )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* node = index2node( index );
|
|
|
|
if ( !node )
|
2014-05-05 16:58:10 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
nodes << node;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !skipInternal )
|
2014-05-05 16:58:10 +02:00
|
|
|
return nodes;
|
|
|
|
|
|
|
|
// remove any children of nodes if both parent node and children are selected
|
|
|
|
QList<QgsLayerTreeNode*> nodesFinal;
|
2014-05-21 15:28:23 +07:00
|
|
|
foreach ( QgsLayerTreeNode* node, nodes )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !_isChildOfNodes( node, nodes ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
nodesFinal << node;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nodesFinal;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::refreshLayerSymbology( QgsLayerTreeLayer* nodeLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
|
|
|
// update title
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex idx = node2index( nodeLayer );
|
|
|
|
emit dataChanged( idx, idx );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
// update children
|
2014-05-21 15:28:23 +07:00
|
|
|
beginRemoveRows( idx, 0, rowCount( idx ) - 1 );
|
|
|
|
removeSymbologyFromLayer( nodeLayer );
|
2014-05-15 14:52:18 +07:00
|
|
|
endRemoveRows();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
addSymbologyToLayer( nodeLayer );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
2014-05-22 18:52:31 +07:00
|
|
|
void QgsLayerTreeModel::setCurrentNode( QgsLayerTreeNode* currentNode )
|
|
|
|
{
|
|
|
|
if ( mCurrentNode )
|
|
|
|
{
|
|
|
|
QModelIndex idx = node2index( mCurrentNode );
|
|
|
|
emit dataChanged( idx, idx );
|
|
|
|
}
|
|
|
|
|
|
|
|
mCurrentNode = currentNode;
|
|
|
|
|
|
|
|
if ( mCurrentNode )
|
|
|
|
{
|
|
|
|
QModelIndex idx = node2index( mCurrentNode );
|
|
|
|
emit dataChanged( idx, idx );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( node );
|
|
|
|
beginInsertRows( node2index( node ), indexFrom, indexTo );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
static QList<QgsLayerTreeLayer*> _layerNodesInSubtree( QgsLayerTreeNode* node, int indexFrom, int indexTo )
|
|
|
|
{
|
|
|
|
QList<QgsLayerTreeNode*> children = node->children();
|
|
|
|
QList<QgsLayerTreeLayer*> newLayerNodes;
|
|
|
|
for ( int i = indexFrom; i <= indexTo; ++i )
|
|
|
|
{
|
|
|
|
QgsLayerTreeNode* child = children.at( i );
|
|
|
|
if ( QgsLayerTree::isLayer( child ) )
|
|
|
|
newLayerNodes << QgsLayerTree::toLayer( child );
|
|
|
|
else if ( QgsLayerTree::isGroup( child ) )
|
|
|
|
newLayerNodes << QgsLayerTree::toGroup( child )->findLayers();
|
|
|
|
}
|
|
|
|
return newLayerNodes;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::nodeAddedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( node );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
endInsertRows();
|
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
foreach ( QgsLayerTreeLayer* newLayerNode, _layerNodesInSubtree( node, indexFrom, indexTo ) )
|
|
|
|
connectToLayer( newLayerNode );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::nodeWillRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( node );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
beginRemoveRows( node2index( node ), indexFrom, indexTo );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
// disconnect from layers and remove their symbology
|
|
|
|
foreach ( QgsLayerTreeLayer* nodeLayer, _layerNodesInSubtree( node, indexFrom, indexTo ) )
|
|
|
|
disconnectFromLayer( nodeLayer );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void QgsLayerTreeModel::nodeRemovedChildren()
|
|
|
|
{
|
|
|
|
endRemoveRows();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::nodeVisibilityChanged( QgsLayerTreeNode* node )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
Q_ASSERT( node );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QModelIndex index = node2index( node );
|
|
|
|
emit dataChanged( index, index );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-05-15 14:52:18 +07:00
|
|
|
void QgsLayerTreeModel::nodeLayerLoaded()
|
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nodeLayer = qobject_cast<QgsLayerTreeLayer*>( sender() );
|
|
|
|
if ( !nodeLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
return;
|
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
// deffered connection to the layer
|
|
|
|
connectToLayer( nodeLayer );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void QgsLayerTreeModel::layerRendererChanged()
|
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
|
|
|
|
if ( !layer )
|
2014-05-15 14:52:18 +07:00
|
|
|
return;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
|
|
|
|
if ( !nodeLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
return;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
refreshLayerSymbology( nodeLayer );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
void QgsLayerTreeModel::layerNeedsUpdate()
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-22 17:55:30 +07:00
|
|
|
QgsMapLayer* layer = qobject_cast<QgsMapLayer*>( sender() );
|
|
|
|
if ( !layer )
|
|
|
|
return;
|
|
|
|
|
|
|
|
QgsLayerTreeLayer* nodeLayer = mRootNode->findLayer( layer->id() );
|
|
|
|
if ( !nodeLayer )
|
|
|
|
return;
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
QModelIndex index = node2index( nodeLayer );
|
|
|
|
emit dataChanged( index, index );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::removeSymbologyFromLayer( QgsLayerTreeLayer* nodeLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( mSymbologyNodes.contains( nodeLayer ) )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
qDeleteAll( mSymbologyNodes[nodeLayer] );
|
|
|
|
mSymbologyNodes.remove( nodeLayer );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
disconnect( nodeLayer->layer(), SIGNAL( rendererChanged() ), this, SLOT( layerRendererChanged() ) );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::addSymbologyToLayer( QgsLayerTreeLayer* nodeL )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !nodeL->layer() )
|
2014-05-15 14:52:18 +07:00
|
|
|
return;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( nodeL->layer()->type() == QgsMapLayer::VectorLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
addSymbologyToVectorLayer( nodeL );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( nodeL->layer()->type() == QgsMapLayer::RasterLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
addSymbologyToRasterLayer( nodeL );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
2014-05-21 15:28:23 +07:00
|
|
|
else if ( nodeL->layer()->type() == QgsMapLayer::PluginLayer )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
addSymbologyToPluginLayer( nodeL );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
// be ready for any subsequent changes of the renderer
|
2014-05-21 15:28:23 +07:00
|
|
|
connect( nodeL->layer(), SIGNAL( rendererChanged() ), this, SLOT( layerRendererChanged() ) );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::addSymbologyToVectorLayer( QgsLayerTreeLayer* nodeL )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>( nodeL->layer() );
|
2014-05-15 14:52:18 +07:00
|
|
|
QgsFeatureRendererV2* r = vlayer->rendererV2();
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !r )
|
2014-05-15 14:52:18 +07:00
|
|
|
return;
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
bool showFeatureCount = nodeL->customProperty( "showFeatureCount", 0 ).toBool();
|
|
|
|
if ( showFeatureCount )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
|
|
|
vlayer->countSymbolFeatures();
|
|
|
|
}
|
|
|
|
QSize iconSize( 16, 16 );
|
|
|
|
QgsLegendSymbolList items = r->legendSymbolItems();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
beginInsertRows( node2index( nodeL ), 0, items.count() - 1 );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
typedef QPair<QString, QgsSymbolV2*> XY;
|
|
|
|
foreach ( XY item, items )
|
|
|
|
{
|
|
|
|
QString label = item.first;
|
2014-05-22 19:52:30 +07:00
|
|
|
QIcon icon;
|
|
|
|
if ( item.second )
|
|
|
|
icon = QgsSymbolLayerV2Utils::symbolPreviewPixmap( item.second, iconSize );
|
|
|
|
if ( showFeatureCount && item.second )
|
2014-05-21 15:28:23 +07:00
|
|
|
label += QString( " [%1]" ).arg( vlayer->featureCount( item.second ) );
|
2014-05-22 19:52:30 +07:00
|
|
|
lst << new QgsLayerTreeModelSymbologyNode( nodeL, label, icon );
|
2014-05-15 14:52:18 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
endInsertRows();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::addSymbologyToRasterLayer( QgsLayerTreeLayer* nodeL )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsRasterLayer* rlayer = static_cast<QgsRasterLayer*>( nodeL->layer() );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
QgsLegendColorList rasterItemList = rlayer->legendSymbologyItems();
|
|
|
|
|
|
|
|
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
|
|
|
|
|
2014-05-21 19:30:29 +07:00
|
|
|
// temporary solution for WMS. Ideally should be done with a delegate.
|
|
|
|
if ( rlayer->providerType() == "wms" )
|
|
|
|
{
|
|
|
|
QImage img = rlayer->dataProvider()->getLegendGraphic( 1000 ); // dummy scale - should not be required!
|
|
|
|
if ( !img.isNull() )
|
|
|
|
lst << new QgsLayerTreeModelSymbologyNode( nodeL, tr( "Double-click to view legend" ) );
|
|
|
|
}
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
// Paletted raster may have many colors, for example UInt16 may have 65536 colors
|
|
|
|
// and it is very slow, so we limit max count
|
2014-05-21 15:28:23 +07:00
|
|
|
QSize iconSize( 16, 16 );
|
2014-05-15 14:52:18 +07:00
|
|
|
int count = 0;
|
|
|
|
int max_count = 1000;
|
2014-05-21 15:28:23 +07:00
|
|
|
int total_count = qMin( max_count + 1, rasterItemList.count() );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
beginInsertRows( node2index( nodeL ), 0, total_count - 1 );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
for ( QgsLegendColorList::const_iterator itemIt = rasterItemList.constBegin();
|
|
|
|
itemIt != rasterItemList.constEnd(); ++itemIt, ++count )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-15 14:52:18 +07:00
|
|
|
QPixmap pix( iconSize );
|
|
|
|
pix.fill( itemIt->second );
|
2014-05-21 15:28:23 +07:00
|
|
|
lst << new QgsLayerTreeModelSymbologyNode( nodeL, itemIt->first, QIcon( pix ) );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
if ( count == max_count )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-15 14:52:18 +07:00
|
|
|
pix.fill( Qt::transparent );
|
|
|
|
QString label = tr( "following %1 items\nnot displayed" ).arg( rasterItemList.size() - max_count );
|
2014-05-21 15:28:23 +07:00
|
|
|
lst << new QgsLayerTreeModelSymbologyNode( nodeL, label, QIcon( pix ) );
|
2014-05-15 14:52:18 +07:00
|
|
|
break;
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
}
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
endInsertRows();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
void QgsLayerTreeModel::addSymbologyToPluginLayer( QgsLayerTreeLayer* nodeL )
|
2014-05-15 14:52:18 +07:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsPluginLayer* player = static_cast<QgsPluginLayer*>( nodeL->layer() );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
QList<QgsLayerTreeModelSymbologyNode*>& lst = mSymbologyNodes[nodeL];
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QSize iconSize( 16, 16 );
|
|
|
|
QgsLegendSymbologyList symbologyList = player->legendSymbologyItems( iconSize );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
beginInsertRows( node2index( nodeL ), 0, symbologyList.count() - 1 );
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
typedef QPair<QString, QPixmap> XY;
|
2014-05-21 15:28:23 +07:00
|
|
|
foreach ( XY item, symbologyList )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
lst << new QgsLayerTreeModelSymbologyNode( nodeL, item.first, QIcon( item.second ) );
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
2014-05-15 14:52:18 +07:00
|
|
|
|
|
|
|
endInsertRows();
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-22 17:55:30 +07:00
|
|
|
void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer* nodeLayer )
|
|
|
|
{
|
|
|
|
if ( !nodeLayer->layer() )
|
|
|
|
{
|
|
|
|
// in order to connect to layer, we need to have it loaded.
|
|
|
|
// keep an eye on the layer ID: once loaded, we will use it
|
|
|
|
connect( nodeLayer, SIGNAL( layerLoaded() ), this, SLOT( nodeLayerLoaded() ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( testFlag( ShowSymbology ) )
|
|
|
|
{
|
|
|
|
addSymbologyToLayer( nodeLayer );
|
|
|
|
}
|
|
|
|
|
|
|
|
QgsMapLayer* layer = nodeLayer->layer();
|
|
|
|
if ( layer->type() == QgsMapLayer::VectorLayer )
|
|
|
|
{
|
|
|
|
// using unique connection because there may be temporarily more nodes for a layer than just one
|
|
|
|
// which would create multiple connections, however disconnect() would disconnect all multiple connections
|
|
|
|
// even if we wanted to disconnect just one connection in each call.
|
|
|
|
connect( layer, SIGNAL( editingStarted() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
|
|
|
|
connect( layer, SIGNAL( editingStopped() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
|
|
|
|
connect( layer, SIGNAL( layerModified() ), this, SLOT( layerNeedsUpdate() ), Qt::UniqueConnection );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// try to find out if the layer ID is present in the tree multiple times
|
|
|
|
static int _numLayerCount( QgsLayerTreeGroup* group, const QString& layerId )
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
foreach ( QgsLayerTreeNode* child, group->children() )
|
|
|
|
{
|
|
|
|
if ( QgsLayerTree::isLayer( child ) )
|
|
|
|
{
|
|
|
|
if ( QgsLayerTree::toLayer( child )->layerId() == layerId )
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
else if ( QgsLayerTree::isGroup( child ) )
|
|
|
|
{
|
|
|
|
count += _numLayerCount( QgsLayerTree::toGroup( child ), layerId );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QgsLayerTreeModel::disconnectFromLayer( QgsLayerTreeLayer* nodeLayer )
|
|
|
|
{
|
|
|
|
if ( !nodeLayer->layer() )
|
|
|
|
return; // we were never connected
|
|
|
|
|
|
|
|
if ( testFlag( ShowSymbology ) )
|
|
|
|
{
|
|
|
|
removeSymbologyFromLayer( nodeLayer );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( _numLayerCount( mRootNode, nodeLayer->layerId() ) == 1 )
|
|
|
|
{
|
|
|
|
// last instance of the layer in the tree: disconnect from all signals from layer!
|
|
|
|
disconnect( nodeLayer->layer(), 0, this, 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-05 16:58:10 +02:00
|
|
|
Qt::DropActions QgsLayerTreeModel::supportedDropActions() const
|
|
|
|
{
|
2014-05-23 00:14:39 +07:00
|
|
|
return Qt::MoveAction;
|
2014-05-05 16:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList QgsLayerTreeModel::mimeTypes() const
|
|
|
|
{
|
|
|
|
QStringList types;
|
|
|
|
types << "application/qgis.layertreemodeldata";
|
|
|
|
return types;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QMimeData* QgsLayerTreeModel::mimeData( const QModelIndexList& indexes ) const
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QList<QgsLayerTreeNode*> nodesFinal = indexes2nodes( indexes, true );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( nodesFinal.count() == 0 )
|
2014-05-05 16:58:10 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
QMimeData *mimeData = new QMimeData();
|
|
|
|
|
|
|
|
QDomDocument doc;
|
2014-05-21 15:28:23 +07:00
|
|
|
QDomElement rootElem = doc.createElement( "layer_tree_model_data" );
|
|
|
|
foreach ( QgsLayerTreeNode* node, nodesFinal )
|
|
|
|
node->writeXML( rootElem );
|
|
|
|
doc.appendChild( rootElem );
|
2014-05-05 16:58:10 +02:00
|
|
|
QString txt = doc.toString();
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
mimeData->setData( "application/qgis.layertreemodeldata", txt.toUtf8() );
|
2014-05-05 16:58:10 +02:00
|
|
|
return mimeData;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
bool QgsLayerTreeModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( action == Qt::IgnoreAction )
|
2014-05-05 16:58:10 +02:00
|
|
|
return true;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !data->hasFormat( "application/qgis.layertreemodeldata" ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( column > 0 )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* nodeParent = index2node( parent );
|
|
|
|
if ( !QgsLayerTree::isGroup( nodeParent ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QByteArray encodedData = data->data( "application/qgis.layertreemodeldata" );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
QDomDocument doc;
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( !doc.setContent( QString::fromUtf8( encodedData ) ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
QDomElement rootElem = doc.documentElement();
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( rootElem.tagName() != "layer_tree_model_data" )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
QList<QgsLayerTreeNode*> nodes;
|
|
|
|
|
|
|
|
QDomElement elem = rootElem.firstChildElement();
|
2014-05-21 15:28:23 +07:00
|
|
|
while ( !elem.isNull() )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* node = QgsLayerTreeNode::readXML( elem );
|
|
|
|
if ( node )
|
2014-05-05 16:58:10 +02:00
|
|
|
nodes << node;
|
|
|
|
|
|
|
|
elem = elem.nextSiblingElement();
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( nodes.count() == 0 )
|
2014-05-05 16:58:10 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
if ( parent.isValid() && row == -1 )
|
2014-05-18 00:34:03 +07:00
|
|
|
row = 0; // if dropped directly onto group item, insert at first position
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTree::toGroup( nodeParent )->insertChildNodes( row, nodes );
|
2014-05-05 16:58:10 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-21 15:28:23 +07:00
|
|
|
bool QgsLayerTreeModel::removeRows( int row, int count, const QModelIndex& parent )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTreeNode* parentNode = index2node( parent );
|
|
|
|
if ( QgsLayerTree::isGroup( parentNode ) )
|
2014-05-05 16:58:10 +02:00
|
|
|
{
|
2014-05-21 15:28:23 +07:00
|
|
|
QgsLayerTree::toGroup( parentNode )->removeChildren( row, count );
|
2014-05-05 16:58:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|