QGIS API Documentation  2.14.0-Essen
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 ), mBridge( bridge )
99 {
100 }
101 
102 int CustomLayerOrderModel::rowCount( const QModelIndex& ) const
103 {
104  return mOrder.count();
105 }
106 
107 QVariant CustomLayerOrderModel::data( const QModelIndex& index, int role ) const
108 {
109  QString id = mOrder.at( index.row() );
110 
111  if ( role == Qt::DisplayRole )
112  {
114  if ( layer )
115  return layer->name();
116  }
117 
118  if ( role == Qt::UserRole + 1 )
119  {
121  if ( layer )
122  return layer->id();
123  }
124 
125  if ( role == Qt::CheckStateRole )
126  {
127  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
128  if ( nodeLayer )
129  return nodeLayer->isVisible();
130  }
131 
132  return QVariant();
133 }
134 
135 bool CustomLayerOrderModel::setData( const QModelIndex& index, const QVariant& value, int role )
136 {
137  if ( role == Qt::CheckStateRole )
138  {
139  QString id = mOrder.at( index.row() );
140  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
141  if ( nodeLayer )
142  {
143  nodeLayer->setVisible( static_cast< Qt::CheckState >( value.toInt() ) );
144  return true;
145  }
146  }
147  return false;
148 }
149 
150 Qt::ItemFlags CustomLayerOrderModel::flags( const QModelIndex& index ) const
151 {
152  if ( !index.isValid() )
153  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
154  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
155 }
156 
157 Qt::DropActions CustomLayerOrderModel::supportedDropActions() const
158 {
159  return Qt::CopyAction | Qt::MoveAction;
160 }
161 
162 QStringList CustomLayerOrderModel::mimeTypes() const
163 {
164  QStringList types;
165  types << "application/qgis.layerorderdata";
166  return types;
167 }
168 
169 QMimeData*CustomLayerOrderModel::mimeData( const QModelIndexList& indexes ) const
170 {
171  QStringList lst;
172  Q_FOREACH ( const QModelIndex& index, indexes )
173  lst << data( index, Qt::UserRole + 1 ).toString();
174 
175  QMimeData* mimeData = new QMimeData();
176  mimeData->setData( "application/qgis.layerorderdata", lst.join( "\n" ).toUtf8() );
177  return mimeData;
178 }
179 
180 bool CustomLayerOrderModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
181 {
182  Q_UNUSED( parent );
183  Q_UNUSED( column );
184 
185  if ( action == Qt::IgnoreAction )
186  return true;
187 
188  if ( !data->hasFormat( "application/qgis.layerorderdata" ) )
189  return false;
190 
191  QByteArray encodedData = data->data( "application/qgis.layerorderdata" );
192  QStringList lst = QString::fromUtf8( encodedData ).split( '\n' );
193 
194  if ( row < 0 )
195  row = mOrder.count();
196 
197  beginInsertRows( QModelIndex(), row, row + lst.count() - 1 );
198  for ( int i = 0; i < lst.count(); ++i )
199  mOrder.insert( row + i, lst[i] );
200  endInsertRows();
201 
202  return true;
203 }
204 
205 bool CustomLayerOrderModel::removeRows( int row, int count, const QModelIndex& parent )
206 {
207  Q_UNUSED( parent );
208  if ( count <= 0 )
209  return false;
210 
211  beginRemoveRows( QModelIndex(), row, row + count - 1 );
212  while ( --count >= 0 )
213  mOrder.removeAt( row );
214  endRemoveRows();
215  return true;
216 }
217 
218 void CustomLayerOrderModel::refreshModel( const QStringList& order )
219 {
220  beginResetModel();
221  mOrder = order;
222  endResetModel();
223 }
224 
225 void CustomLayerOrderModel::updateLayerVisibility( const QString& layerId )
226 {
227  int row = mOrder.indexOf( layerId );
228  if ( row != -1 )
229  emit dataChanged( index( row ), index( row ) );
230 }
231 
232 
233 
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)
QString name() const
Get the display name of the layer.
The QgsLayerTreeMapCanvasBridge class takes care of updates of layer set for QgsMapCanvas from a laye...
virtual bool hasFormat(const QString &mimeType) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void bridgeHasCustomLayerOrderChanged(bool state)
virtual void setModel(QAbstractItemModel *model)
QString join(const QString &separator) const
QgsLayerTreeMapCanvasBridge * mBridge
QString tr(const char *sourceText, const char *disambiguation, int n)
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
QgsLayerTreeGroup * rootGroup() const
bool isValid() const
Qt::CheckState isVisible() const
void setEnabled(bool)
int count(const T &value) const
QString fromUtf8(const char *str, int size)
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.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
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)
void setAcceptDrops(bool on)
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
QgsLayerTreeLayer * findLayer(const QString &layerId) const
Find layer node representing the map layer specified by its ID. Searches recursively the whole sub-tr...
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