QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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  connect( mModel->layerCache()->layer(), SIGNAL( attributeValueChanged( QgsFeatureId, int, QVariant ) ), this, SLOT( repaintRequested() ) );
86 }
87 
89 {
90  if ( mModel->setDisplayExpression( expression ) )
91  {
92  emit displayExpressionChanged( expression );
93  return true;
94  }
95  else
96  {
97  return false;
98  }
99 }
100 
102 {
103  return mModel->displayExpression();
104 }
105 
107 {
108  return mModel->parserErrorString();
109 }
110 
112 {
113  QgsFeatureIds selection;
114  Q_FOREACH ( const QModelIndex& idx, mCurrentEditSelectionModel->selectedIndexes() )
115  {
117  }
118  return selection;
119 }
120 
122 {
123  mItemDelegate->setCurrentFeatureEdited( state );
124  viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
125 }
126 
128 {
129  if ( mModel )
130  {
131  QPoint pos = event->pos();
132 
133  QModelIndex index = indexAt( pos );
134 
135  if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
136  {
137  mEditSelectionDrag = true;
138  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
139  }
140  else
141  {
142  mFeatureSelectionModel->enableSync( false );
143  selectRow( index, true );
145  }
146  }
147  else
148  {
149  QgsDebugMsg( "No model assigned to this view" );
150  }
151 }
152 
153 void QgsFeatureListView::editSelectionChanged( const QItemSelection& deselected, const QItemSelection& selected )
154 {
155  if ( isVisible() && updatesEnabled() )
156  {
157  QItemSelection localDeselected = mModel->mapSelectionFromMaster( deselected );
158  QItemSelection localSelected = mModel->mapSelectionFromMaster( selected );
159  viewport()->update( visualRegionForSelection( localDeselected ) | visualRegionForSelection( localSelected ) );
160  }
161 
162  QItemSelection currentSelection = mCurrentEditSelectionModel->selection();
163  if ( currentSelection.size() == 1 )
164  {
165  QModelIndexList indexList = currentSelection.indexes();
166  if ( !indexList.isEmpty() )
167  {
168  QgsFeature feat;
169  mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), feat );
170 
171  emit currentEditSelectionChanged( feat );
172  }
173  }
174 }
175 
177 {
178  QItemSelection selection;
179  selection.append( QItemSelectionRange( mModel->index( 0, 0 ), mModel->index( mModel->rowCount() - 1, 0 ) ) );
180 
181  mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
182 }
183 
185 {
186  QItemSelection selection;
187 
188  Q_FOREACH ( QgsFeatureId fid, fids )
189  {
190  selection.append( QItemSelectionRange( mModel->mapToMaster( mModel->fidToIdx( fid ) ) ) );
191  }
192 
193  bool ok = true;
194  emit aboutToChangeEditSelection( ok );
195 
196  if ( ok )
197  mCurrentEditSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
198 }
199 
201 {
202  bool ok = true;
203  emit aboutToChangeEditSelection( ok );
204 
205  if ( ok )
206  mCurrentEditSelectionModel->select( index, command );
207 }
208 
209 void QgsFeatureListView::repaintRequested( const QModelIndexList& indexes )
210 {
211  Q_FOREACH ( const QModelIndex& index, indexes )
212  {
213  update( index );
214  }
215 }
216 
218 {
219  setDirtyRegion( viewport()->rect() );
220 }
221 
229 {
230  QPoint pos = event->pos();
231 
232  QModelIndex index = indexAt( pos );
233 
234  if ( mEditSelectionDrag )
235  {
236  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
237  }
238  else
239  {
240  selectRow( index, false );
241  }
242 }
243 
252 {
253  Q_UNUSED( event );
254 
255  if ( mEditSelectionDrag )
256  {
257  mEditSelectionDrag = false;
258  }
259  else
260  {
261  if ( mFeatureSelectionModel )
262  mFeatureSelectionModel->enableSync( true );
263  }
264 }
265 
267 {
268  if ( Qt::Key_Up == event->key() || Qt::Key_Down == event->key() )
269  {
270  int currentRow = 0;
271  if ( 0 != mCurrentEditSelectionModel->selectedIndexes().count() )
272  {
273  QModelIndex localIndex = mModel->mapFromMaster( mCurrentEditSelectionModel->selectedIndexes().first() );
274  currentRow = localIndex.row();
275  }
276 
277  QModelIndex newLocalIndex;
278  QModelIndex newIndex;
279 
280  switch ( event->key() )
281  {
282  case Qt::Key_Up:
283  newLocalIndex = mModel->index( currentRow - 1, 0 );
284  newIndex = mModel->mapToMaster( newLocalIndex );
285  if ( newIndex.isValid() )
286  {
287  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
288  scrollTo( newLocalIndex );
289  }
290  break;
291 
292  case Qt::Key_Down:
293  newLocalIndex = mModel->index( currentRow + 1, 0 );
294  newIndex = mModel->mapToMaster( newLocalIndex );
295  if ( newIndex.isValid() )
296  {
297  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
298  scrollTo( newLocalIndex );
299  }
300  break;
301 
302  default:
303  break;
304  }
305  }
306  else
307  {
308  QListView::keyPressEvent( event );
309  }
310 }
311 
313 {
314  QModelIndex index = indexAt( event->pos() );
315 
316  if ( index.isValid() )
317  {
318  QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();
319 
320  QgsActionMenu* menu = new QgsActionMenu( mModel->layerCache()->layer(), &feature, this );
321  menu->exec( event->globalPos() );
322  }
323 }
324 
325 void QgsFeatureListView::selectRow( const QModelIndex& index, bool anchor )
326 {
328  int row = index.row();
329 
330  if ( anchor )
331  mRowAnchor = row;
332 
333  if ( selectionMode() != QListView::SingleSelection
334  && command.testFlag( QItemSelectionModel::Toggle ) )
335  {
336  if ( anchor )
337  mCtrlDragSelectionFlag = mFeatureSelectionModel->isSelected( index )
338  ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
339  command &= ~QItemSelectionModel::Toggle;
340  command |= mCtrlDragSelectionFlag;
341  if ( !anchor )
342  command |= QItemSelectionModel::Current;
343  }
344 
345  QModelIndex tl = model()->index( qMin( mRowAnchor, row ), 0 );
346  QModelIndex br = model()->index( qMax( mRowAnchor, row ), model()->columnCount() - 1 );
347 
348  mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
349 }
350 
352 {
353  delete mFeatureSelectionManager;
354 
355  mFeatureSelectionManager = featureSelectionManager;
356 
357  if ( mFeatureSelectionModel )
358  mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
359 }
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 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
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 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()
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
int size() const
Get the feature id of the feature in this row.
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.
QString displayExpression() const
QAction * exec()
QgsFeatureIds currentEditSelection()
Get the currentEditSelection.
QRect rect() const
int key() const
virtual void mouseMoveEvent(QMouseEvent *event) override
QgsAttributeTableModel * masterModel()
virtual QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
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
const QString displayExpression() const
Returns the expression which is currently used to render the features.
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
QModelIndex fidToIdx(const QgsFeatureId fid) const
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
virtual void contextMenuEvent(QContextMenuEvent *event) override
virtual void keyPressEvent(QKeyEvent *event) override
qint64 QgsFeatureId
Definition: qgsfeature.h:31
virtual QItemSelection mapSelectionFromMaster(const QItemSelection &selection) const
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
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 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
virtual void setModel(QgsFeatureListModel *featureListModel)
Set the QgsFeatureListModel which is used to retrieve information.
QgsVectorLayerCache * layerCache()
Returns the layer cache.