QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 class CustomLayerOrderModel : public QAbstractListModel
31 {
32  public:
33  CustomLayerOrderModel( QgsLayerTreeMapCanvasBridge* bridge, QObject* parent = 0 )
34  : QAbstractListModel( parent ), mBridge( bridge )
35  {
36  }
37 
38  int rowCount( const QModelIndex & ) const override
39  {
40  return mOrder.count();
41  }
42 
43  QVariant data( const QModelIndex &index, int role ) const override
44  {
45  QString id = mOrder.at( index.row() );
46 
47  if ( role == Qt::DisplayRole )
48  {
50  if ( layer )
51  return layer->name();
52  }
53 
54  if ( role == Qt::UserRole + 1 )
55  {
57  if ( layer )
58  return layer->id();
59  }
60 
61  if ( role == Qt::CheckStateRole )
62  {
63  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
64  if ( nodeLayer )
65  return nodeLayer->isVisible();
66  }
67 
68  return QVariant();
69  }
70 
71  bool setData( const QModelIndex &index, const QVariant &value, int role ) override
72  {
73  if ( role == Qt::CheckStateRole )
74  {
75  QString id = mOrder.at( index.row() );
76  QgsLayerTreeLayer* nodeLayer = mBridge->rootGroup()->findLayer( id );
77  if ( nodeLayer )
78  {
79  nodeLayer->setVisible(( Qt::CheckState )value.toInt() );
80  return true;
81  }
82  }
83  return false;
84  }
85 
86  Qt::ItemFlags flags( const QModelIndex &index ) const override
87  {
88  if ( !index.isValid() )
89  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
90  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
91  }
92 
93  Qt::DropActions supportedDropActions() const override
94  {
95  return Qt::MoveAction;
96  }
97 
98  QStringList mimeTypes() const override
99  {
100  QStringList types;
101  types << "application/qgis.layerorderdata";
102  return types;
103  }
104 
105  QMimeData* mimeData( const QModelIndexList& indexes ) const override
106  {
107  QStringList lst;
108  foreach ( QModelIndex index, indexes )
109  lst << data( index, Qt::UserRole + 1 ).toString();
110 
111  QMimeData* mimeData = new QMimeData();
112  mimeData->setData( "application/qgis.layerorderdata", lst.join( "\n" ).toUtf8() );
113  return mimeData;
114  }
115 
116  bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override
117  {
118  Q_UNUSED( parent );
119  Q_UNUSED( column );
120 
121  if ( action == Qt::IgnoreAction )
122  return true;
123 
124  if ( !data->hasFormat( "application/qgis.layerorderdata" ) )
125  return false;
126 
127  QByteArray encodedData = data->data( "application/qgis.layerorderdata" );
128  QStringList lst = QString::fromUtf8( encodedData ).split( "\n" );
129 
130  if ( row < 0 )
131  row = mOrder.count();
132 
133  beginInsertRows( QModelIndex(), row, row + lst.count() - 1 );
134  for ( int i = 0; i < lst.count(); ++i )
135  mOrder.insert( row + i, lst[i] );
136  endInsertRows();
137 
138  return true;
139  }
140 
141  bool removeRows( int row, int count, const QModelIndex& parent ) override
142  {
143  Q_UNUSED( parent );
144  if ( count <= 0 )
145  return false;
146 
147  beginRemoveRows( QModelIndex(), row, row + count - 1 );
148  while ( --count >= 0 )
149  mOrder.removeAt( row );
150  endRemoveRows();
151  return true;
152  }
153 
154  void refreshModel( const QStringList& order )
155  {
156  beginResetModel();
157  mOrder = order;
158  endResetModel();
159  }
160 
161  QStringList order() const { return mOrder; }
162 
163  void updateLayerVisibility( const QString& layerId )
164  {
165  int row = mOrder.indexOf( layerId );
166  if ( row != -1 )
167  emit dataChanged( index( row ), index( row ) );
168  }
169 
170  protected:
172  QStringList mOrder;
173 };
174 
175 
177  : QWidget( parent )
178  , mBridge( bridge )
179 {
180  mModel = new CustomLayerOrderModel( bridge, this );
181 
182  mView = new QListView( this );
183  mView->setDragEnabled( true );
184  mView->setAcceptDrops( true );
185  mView->setDropIndicatorShown( true );
186  mView->setDragDropMode( QAbstractItemView::InternalMove );
187  mView->setSelectionMode( QAbstractItemView::ExtendedSelection );
188 
189  mView->setModel( mModel );
190 
191  mChkOverride = new QCheckBox( tr( "Control rendering order" ) );
193  connect( mChkOverride, SIGNAL( toggled( bool ) ), bridge, SLOT( setHasCustomLayerOrder( bool ) ) );
194 
195  connect( bridge, SIGNAL( hasCustomLayerOrderChanged( bool ) ), this, SLOT( bridgeHasCustomLayerOrderChanged( bool ) ) );
196  connect( bridge, SIGNAL( customLayerOrderChanged( QStringList ) ), this, SLOT( bridgeCustomLayerOrderChanged( QStringList ) ) );
197 
198  connect( mModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
199  connect( mModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( modelUpdated() ) );
200 
201  connect( bridge->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ), this, SLOT( nodeVisibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ) );
202 
203  QVBoxLayout* l = new QVBoxLayout;
204  l->setMargin( 0 );
205  l->addWidget( mView );
206  l->addWidget( mChkOverride );
207  setLayout( l );
208 }
209 
211 {
212  mChkOverride->setChecked( state );
214  mView->setEnabled( state );
215 }
216 
218 {
219  Q_UNUSED( order );
221 }
222 
224 {
225  Q_UNUSED( state );
226  if ( QgsLayerTree::isLayer( node ) )
227  {
228  mModel->updateLayerVisibility( QgsLayerTree::toLayer( node )->layerId() );
229  }
230 }
231 
233 {
235 }