QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgscustomlayerorderwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscustomlayerorderwidget.cpp
3  --------------------------------------
4  Date : May 2014
5  Copyright : (C) 2014 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include <QCheckBox>
19 #include <QListView>
20 #include <QMimeData>
21 #include <QVBoxLayout>
22 
23 #include "qgslayertree.h"
25 
26 #include "qgsmaplayer.h"
27 #include "qgsmaplayerregistry.h"
28 
29 
30 
31 
33  : QWidget( parent )
34  , mBridge( bridge )
35 {
36  mModel = new CustomLayerOrderModel( bridge, this );
37 
38  mView = new QListView( this );
39  mView->setDragEnabled( true );
40  mView->setAcceptDrops( true );
42  mView->setSelectionMode( QAbstractItemView::ExtendedSelection );
43  mView->setDefaultDropAction( Qt::MoveAction );
44 
45  mView->setModel( mModel );
46 
47  mChkOverride = new QCheckBox( tr( "Control rendering order" ) );
49  connect( mChkOverride, SIGNAL( toggled( bool ) ), bridge, SLOT( setHasCustomLayerOrder( bool ) ) );
50 
51  connect( bridge, SIGNAL( hasCustomLayerOrderChanged( bool ) ), this, SLOT( bridgeHasCustomLayerOrderChanged( bool ) ) );
52  connect( bridge, SIGNAL( customLayerOrderChanged( QStringList ) ), this, SLOT( bridgeCustomLayerOrderChanged( QStringList ) ) );
53 
54  connect( mModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
55  connect( mModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
56 
57  connect( bridge->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ) );
58 
59  QVBoxLayout* l = new QVBoxLayout;
60  l->setMargin( 0 );
61  l->addWidget( mView );
62  l->addWidget( mChkOverride );
63  setLayout( l );
64 }
65 
67 {
68  mChkOverride->setChecked( state );
70  mView->setEnabled( state );
71 }
72 
74 {
75  Q_UNUSED( order );
77 }
78 
80 {
81  Q_UNUSED( state );
82  if ( QgsLayerTree::isLayer( node ) )
83  {
84  mModel->updateLayerVisibility( QgsLayerTree::toLayer( node )->layerId() );
85  }
86 }
87 
89 {
90  mBridge->setCustomLayerOrder( mModel->order() );
91 }
92 
93 
94 
96 
97 CustomLayerOrderModel::CustomLayerOrderModel( QgsLayerTreeMapCanvasBridge* bridge, QObject* parent )
98  : QAbstractListModel( parent )
99  , mBridge( bridge )
100 {
101 }
102 
103 int CustomLayerOrderModel::rowCount( const QModelIndex& ) const
104 {
105  return mOrder.count();
106 }
107 
108 QVariant CustomLayerOrderModel::data( const QModelIndex& index, int role ) const
109 {
110  QString id = mOrder.at( index.row() );
111 
112  if ( role == Qt::DisplayRole )
113  {
115  if ( layer )
116  return layer->name();
117  }
118 
119  if ( role == Qt::UserRole + 1 )
120  {
122  if ( layer )
123  return layer->id();
124  }
125 
126  if ( role == Qt::CheckStateRole )
127  {
128  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
129  if ( nodeLayer )
130  return nodeLayer->isVisible();
131  }
132 
133  return QVariant();
134 }
135 
136 bool CustomLayerOrderModel::setData( const QModelIndex& index, const QVariant& value, int role )
137 {
138  if ( role == Qt::CheckStateRole )
139  {
140  QString id = mOrder.at( index.row() );
141  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
142  if ( nodeLayer )
143  {
144  nodeLayer->setVisible( static_cast< Qt::CheckState >( value.toInt() ) );
145  return true;
146  }
147  }
148  return false;
149 }
150 
151 Qt::ItemFlags CustomLayerOrderModel::flags( const QModelIndex& index ) const
152 {
153  if ( !index.isValid() )
154  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
155  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
156 }
157 
158 Qt::DropActions CustomLayerOrderModel::supportedDropActions() const
159 {
160  return Qt::CopyAction | Qt::MoveAction;
161 }
162 
163 QStringList CustomLayerOrderModel::mimeTypes() const
164 {
165  QStringList types;
166  types << "application/qgis.layerorderdata";
167  return types;
168 }
169 
170 QMimeData*CustomLayerOrderModel::mimeData( const QModelIndexList& indexes ) const
171 {
172  QStringList lst;
173  Q_FOREACH ( const QModelIndex& index, indexes )
174  lst << data( index, Qt::UserRole + 1 ).toString();
175 
176  QMimeData* mimeData = new QMimeData();
177  mimeData->setData( "application/qgis.layerorderdata", lst.join( "\n" ).toUtf8() );
178  return mimeData;
179 }
180 
181 bool CustomLayerOrderModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
182 {
183  Q_UNUSED( parent );
184  Q_UNUSED( column );
185 
186  if ( action == Qt::IgnoreAction )
187  return true;
188 
189  if ( !data->hasFormat( "application/qgis.layerorderdata" ) )
190  return false;
191 
192  QByteArray encodedData = data->data( "application/qgis.layerorderdata" );
193  QStringList lst = QString::fromUtf8( encodedData ).split( '\n' );
194 
195  if ( row < 0 )
196  row = mOrder.count();
197 
198  beginInsertRows( QModelIndex(), row, row + lst.count() - 1 );
199  for ( int i = 0; i < lst.count(); ++i )
200  mOrder.insert( row + i, lst[i] );
201  endInsertRows();
202 
203  return true;
204 }
205 
206 bool CustomLayerOrderModel::removeRows( int row, int count, const QModelIndex& parent )
207 {
208  Q_UNUSED( parent );
209  if ( count <= 0 )
210  return false;
211 
212  beginRemoveRows( QModelIndex(), row, row + count - 1 );
213  while ( --count >= 0 )
214  mOrder.removeAt( row );
215  endRemoveRows();
216  return true;
217 }
218 
219 void CustomLayerOrderModel::refreshModel( const QStringList& order )
220 {
221  beginResetModel();
222  mOrder = order;
223  endResetModel();
224 }
225 
226 void CustomLayerOrderModel::updateLayerVisibility( const QString& layerId )
227 {
228  int row = mOrder.indexOf( layerId );
229  if ( row != -1 )
230  emit dataChanged( index( row ), index( row ) );
231 }
232 
233 
234 
static unsigned index
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void setCustomLayerOrder(const QStringList &order)
QByteArray data(const QString &mimeType) const
void setSelectionMode(QAbstractItemView::SelectionMode mode)
The QgsLayerTreeMapCanvasBridge class takes care of updates of layer set for QgsMapCanvas from a laye...
virtual bool hasFormat(const QString &mimeType) const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void bridgeHasCustomLayerOrderChanged(bool state)
virtual void setModel(QAbstractItemModel *model)
Qt::CheckState isVisible() const
QString join(const QString &separator) const
QgsLayerTreeMapCanvasBridge * mBridge
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isValid() const
void setEnabled(bool)
int count(const T &value) const
QString fromUtf8(const char *str, int size)
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
void setLayout(QLayout *layout)
void nodeVisibilityChanged(QgsLayerTreeNode *node, Qt::CheckState state)
int toInt(bool *ok) const
CustomLayerOrderModel * mModel
int row() const
This class is a base class for nodes in a layer tree.
void setVisible(Qt::CheckState visible)
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
void setMargin(int margin)
QgsLayerTreeGroup * rootGroup() const
void setAcceptDrops(bool on)
QgsLayerTreeLayer * findLayer(const QString &layerId) const
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
QgsCustomLayerOrderWidget(QgsLayerTreeMapCanvasBridge *bridge, QWidget *parent=nullptr)
void setChecked(bool)
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer. No type checking is done - use isLayer() to find out whether this operation is ...
Definition: qgslayertree.h:52
typedef DropActions
const QChar at(int position) const
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:53
void bridgeCustomLayerOrderChanged(const QStringList &order)
void setData(const QString &mimeType, const QByteArray &data)
void setDefaultDropAction(Qt::DropAction dropAction)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
void setDropIndicatorShown(bool enable)
void setDragEnabled(bool enable)
Layer tree node points to a map layer.
typedef ItemFlags
QByteArray toUtf8() const