QGIS API Documentation  2.14.0-Essen
qgsfeaturelistview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsAttributeTableView.cpp
3  --------------------------------------
4  Date : Feb 2009
5  Copyright : (C) 2009 Vita Cizek
6  Email : weetya (at) gmail.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 
16 #include <QHeaderView>
17 #include <QKeyEvent>
18 #include <QMenu>
19 #include <QSet>
20 #include <QSettings>
21 
22 #include "qgsactionmenu.h"
25 #include "qgsattributetablemodel.h"
26 #include "qgsfeaturelistmodel.h"
28 #include "qgsfeaturelistview.h"
30 #include "qgslogger.h"
31 #include "qgsmapcanvas.h"
32 #include "qgsvectordataprovider.h"
33 #include "qgsvectorlayer.h"
35 
37  : QListView( parent )
38  , mModel( nullptr )
39  , mCurrentEditSelectionModel( nullptr )
40  , mFeatureSelectionModel( nullptr )
41  , mFeatureSelectionManager( nullptr )
42  , mItemDelegate( nullptr )
43  , mEditSelectionDrag( false )
44  , mRowAnchor( 0 )
45 {
46  setSelectionMode( QAbstractItemView::ExtendedSelection );
47 }
48 
50 {
51  return mModel->layerCache();
52 }
53 
55 {
56  QListView::setModel( featureListModel );
57  mModel = featureListModel;
58 
59  delete mFeatureSelectionModel;
60 
61  mCurrentEditSelectionModel = new QItemSelectionModel( mModel->masterModel(), this );
62  if ( !mFeatureSelectionManager )
63  {
64  mFeatureSelectionManager = new QgsVectorLayerSelectionManager( mModel->layerCache()->layer(), mModel );
65  }
66 
67  mFeatureSelectionModel = new QgsFeatureSelectionModel( featureListModel, featureListModel, mFeatureSelectionManager, this );
68  setSelectionModel( mFeatureSelectionModel );
69 
70  if ( mItemDelegate && mItemDelegate->parent() == this )
71  {
72  delete mItemDelegate;
73  }
74 
75  mItemDelegate = new QgsFeatureListViewDelegate( mModel, this );
76  mItemDelegate->setEditSelectionModel( mCurrentEditSelectionModel );
77  setItemDelegate( mItemDelegate );
78 
79  mItemDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
80  connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
81  connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
82 
83  connect( mCurrentEditSelectionModel, SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( editSelectionChanged( QItemSelection, QItemSelection ) ) );
84 
85 }
86 
88 {
89  if ( mModel->setDisplayExpression( expression ) )
90  {
91  emit displayExpressionChanged( expression );
92  return true;
93  }
94  else
95  {
96  return false;
97  }
98 }
99 
101 {
102  return mModel->displayExpression();
103 }
104 
106 {
107  return mModel->parserErrorString();
108 }
109 
111 {
112  QgsFeatureIds selection;
113  Q_FOREACH ( const QModelIndex& idx, mCurrentEditSelectionModel->selectedIndexes() )
114  {
116  }
117  return selection;
118 }
119 
121 {
122  mItemDelegate->setCurrentFeatureEdited( state );
123  viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
124 }
125 
127 {
128  if ( mModel )
129  {
130  QPoint pos = event->pos();
131 
132  QModelIndex index = indexAt( pos );
133 
134  if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
135  {
136  mEditSelectionDrag = true;
137  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
138  }
139  else
140  {
141  mFeatureSelectionModel->enableSync( false );
142  selectRow( index, true );
144  }
145  }
146  else
147  {
148  QgsDebugMsg( "No model assigned to this view" );
149  }
150 }
151 
152 void QgsFeatureListView::editSelectionChanged( const QItemSelection& deselected, const QItemSelection& selected )
153 {
154  if ( isVisible() && updatesEnabled() )
155  {
156  QItemSelection localDeselected = mModel->mapSelectionFromMaster( deselected );
157  QItemSelection localSelected = mModel->mapSelectionFromMaster( selected );
158  viewport()->update( visualRegionForSelection( localDeselected ) | visualRegionForSelection( localSelected ) );
159  }
160 
161  QItemSelection currentSelection = mCurrentEditSelectionModel->selection();
162  if ( currentSelection.size() == 1 )
163  {
164  QModelIndexList indexList = currentSelection.indexes();
165  if ( !indexList.isEmpty() )
166  {
167  QgsFeature feat;
168  mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), feat );
169 
170  emit currentEditSelectionChanged( feat );
171  }
172  }
173 }
174 
176 {
177  QItemSelection selection;
178  selection.append( QItemSelectionRange( mModel->index( 0, 0 ), mModel->index( mModel->rowCount() - 1, 0 ) ) );
179 
180  mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
181 }
182 
184 {
185  QItemSelection selection;
186 
187  Q_FOREACH ( QgsFeatureId fid, fids )
188  {
189  selection.append( QItemSelectionRange( mModel->mapToMaster( mModel->fidToIdx( fid ) ) ) );
190  }
191 
192  bool ok = true;
193  emit aboutToChangeEditSelection( ok );
194 
195  if ( ok )
196  mCurrentEditSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
197 }
198 
200 {
201  bool ok = true;
202  emit aboutToChangeEditSelection( ok );
203 
204  if ( ok )
205  mCurrentEditSelectionModel->select( index, command );
206 }
207 
208 void QgsFeatureListView::repaintRequested( const QModelIndexList& indexes )
209 {
210  Q_FOREACH ( const QModelIndex& index, indexes )
211  {
212  update( index );
213  }
214 }
215 
217 {
218  setDirtyRegion( viewport()->rect() );
219 }
220 
228 {
229  QPoint pos = event->pos();
230 
231  QModelIndex index = indexAt( pos );
232 
233  if ( mEditSelectionDrag )
234  {
235  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
236  }
237  else
238  {
239  selectRow( index, false );
240  }
241 }
242 
251 {
252  Q_UNUSED( event );
253 
254  if ( mEditSelectionDrag )
255  {
256  mEditSelectionDrag = false;
257  }
258  else
259  {
260  mFeatureSelectionModel->enableSync( true );
261  }
262 }
263 
265 {
266  if ( Qt::Key_Up == event->key() || Qt::Key_Down == event->key() )
267  {
268  int currentRow = 0;
269  if ( 0 != mCurrentEditSelectionModel->selectedIndexes().count() )
270  {
271  QModelIndex localIndex = mModel->mapFromMaster( mCurrentEditSelectionModel->selectedIndexes().first() );
272  currentRow = localIndex.row();
273  }
274 
275  QModelIndex newLocalIndex;
276  QModelIndex newIndex;
277 
278  switch ( event->key() )
279  {
280  case Qt::Key_Up:
281  newLocalIndex = mModel->index( currentRow - 1, 0 );
282  newIndex = mModel->mapToMaster( newLocalIndex );
283  if ( newIndex.isValid() )
284  {
285  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
286  scrollTo( newLocalIndex );
287  }
288  break;
289 
290  case Qt::Key_Down:
291  newLocalIndex = mModel->index( currentRow + 1, 0 );
292  newIndex = mModel->mapToMaster( newLocalIndex );
293  if ( newIndex.isValid() )
294  {
295  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
296  scrollTo( newLocalIndex );
297  }
298  break;
299 
300  default:
301  break;
302  }
303  }
304  else
305  {
306  QListView::keyPressEvent( event );
307  }
308 }
309 
311 {
312  QModelIndex index = indexAt( event->pos() );
313 
314  if ( index.isValid() )
315  {
316  QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();
317 
318  QgsActionMenu* menu = new QgsActionMenu( mModel->layerCache()->layer(), &feature, this );
319  menu->exec( event->globalPos() );
320  }
321 }
322 
323 void QgsFeatureListView::selectRow( const QModelIndex& index, bool anchor )
324 {
326  int row = index.row();
327 
328  if ( anchor )
329  mRowAnchor = row;
330 
331  if ( selectionMode() != QListView::SingleSelection
332  && command.testFlag( QItemSelectionModel::Toggle ) )
333  {
334  if ( anchor )
335  mCtrlDragSelectionFlag = mFeatureSelectionModel->isSelected( index )
336  ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
337  command &= ~QItemSelectionModel::Toggle;
338  command |= mCtrlDragSelectionFlag;
339  if ( !anchor )
340  command |= QItemSelectionModel::Current;
341  }
342 
343  QModelIndex tl = model()->index( qMin( mRowAnchor, row ), 0 );
344  QModelIndex br = model()->index( qMax( mRowAnchor, row ), model()->columnCount() - 1 );
345 
346  mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
347 }
348 
350 {
351  delete mFeatureSelectionManager;
352 
353  mFeatureSelectionManager = featureSelectionManager;
354 
355  if ( mFeatureSelectionModel )
356  mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
357 }
QModelIndexList indexes() const
void setDirtyRegion(const QRegion &region)
virtual void setSelectionModel(QItemSelectionModel *selectionModel)
static unsigned index
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
void setCurrentFeatureEdited(bool state)
Sets if the currently shown form has received any edit events so far.
void setSelectionMode(QAbstractItemView::SelectionMode mode)
virtual void mouseReleaseEvent(QMouseEvent *event) override
bool setDisplayExpression(const QString &expression)
bool setDisplayExpression(const QString &displayExpression)
The display expression is an expression used to render the fields into a single string which is displ...
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
virtual void setModel(QAbstractItemModel *model)
bool isVisible() const
T value() const
bool featureByIndex(const QModelIndex &index, QgsFeature &feat)
QWidget * viewport() const
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
const QString displayExpression() const
Returns the expression which is currently used to render the features.
const QPoint & globalPos() const
void enableSync(bool enable)
Enables or disables synchronisation to the QgsVectorLayer When synchronisation is disabled...
QString parserErrorString()
Returns a detailed message about errors while parsing a QgsExpression.
void update()
int size() const
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
bool isValid() const
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const
QgsFeatureListModel * featureListModel()
Get the featureListModel used by this view.
void append(const T &value)
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
bool updatesEnabled() const
virtual QVariant data(const QModelIndex &index, int role) const override
void aboutToChangeEditSelection(bool &ok)
This class is a menu that is populated automatically with the actions defined for a given layer...
Definition: qgsactionmenu.h:30
const QItemSelection selection() const
QString parserErrorString()
Returns a detailed message about errors while parsing a QgsExpression.
virtual void select(const QModelIndex &index, QFlags< QItemSelectionModel::SelectionFlag > command)
QModelIndexList selectedIndexes() const
void setItemDelegate(QAbstractItemDelegate *delegate)
int row() const
virtual void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
QPoint pos() const
void displayExpressionChanged(const QString &expression)
Is emitted, whenever the display expression is successfully changed.
QAction * exec()
QgsFeatureIds currentEditSelection()
Get the currentEditSelection.
QRect rect() const
int key() const
virtual void mouseMoveEvent(QMouseEvent *event) override
QgsAttributeTableModel * masterModel()
This class caches features of a given QgsVectorLayer.
State state() const
virtual bool event(QEvent *e)
void setEditSelection(const QgsFeatureIds &fids)
Set the feature(s) to be edited.
virtual QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &index, const QEvent *event) const
virtual void selectFeatures(const QItemSelection &selection, const SelectionFlags &command)
Select features on this table.
const QPoint & pos() const
virtual QModelIndex indexAt(const QPoint &p) const
virtual void selectAll() override
Select all currently visible features.
QVariant data(int role) const
virtual void mousePressEvent(QMouseEvent *event) override
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
virtual void contextMenuEvent(QContextMenuEvent *event) override
virtual void keyPressEvent(QKeyEvent *event) override
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QgsFeatureListView(QWidget *parent=nullptr)
Creates a feature list view.
QgsVectorLayerCache * layerCache()
virtual void keyPressEvent(QKeyEvent *event)
virtual void scrollTo(const QModelIndex &index, ScrollHint hint)
const QPoint & pos() const
QAbstractItemModel * model() const
QModelIndex fidToIdx(const QgsFeatureId fid) const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setEditSelectionModel(QItemSelectionModel *editSelectionModel)
Is an interface class to abstract feature selection handling.
QObject * parent() const
void currentEditSelectionChanged(QgsFeature &feat)
Is emitted, whenever the current edit selection has been changed.
virtual QItemSelection mapSelectionFromMaster(const QItemSelection &selection) const
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
virtual void setModel(QgsFeatureListModel *featureListModel)
Set the QgsFeatureListModel which is used to retrieve information.
QString displayExpression() const
QgsVectorLayerCache * layerCache()
Returns the layer cache.