QGIS API Documentation  2.12.0-Lyon
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( 0 )
39  , mCurrentEditSelectionModel( 0 )
40  , mFeatureSelectionModel( 0 )
41  , mItemDelegate( 0 )
42  , mEditSelectionDrag( false )
43  , mRowAnchor( 0 )
44 {
45  setSelectionMode( QAbstractItemView::ExtendedSelection );
46 }
47 
49 {
50  return mModel->layerCache();
51 }
52 
54 {
55  QListView::setModel( featureListModel );
56  mModel = featureListModel;
57 
58  delete mFeatureSelectionModel;
59  mFeatureSelectionModel = new QgsFeatureSelectionModel( featureListModel, featureListModel, new QgsVectorLayerSelectionManager( featureListModel->layerCache()->layer(), this ), this );
60  setSelectionModel( mFeatureSelectionModel );
61 
62  mCurrentEditSelectionModel = new QItemSelectionModel( mModel->masterModel(), this );
63 
64  if ( mItemDelegate && mItemDelegate->parent() == this )
65  {
66  delete mItemDelegate;
67  }
68 
69  mItemDelegate = new QgsFeatureListViewDelegate( mModel, this );
70  mItemDelegate->setEditSelectionModel( mCurrentEditSelectionModel );
71  setItemDelegate( mItemDelegate );
72 
73  mItemDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
74  connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
75  connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
76 
77  connect( mCurrentEditSelectionModel, SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( editSelectionChanged( QItemSelection, QItemSelection ) ) );
78 }
79 
81 {
82  if ( mModel->setDisplayExpression( expression ) )
83  {
84  emit displayExpressionChanged( expression );
85  return true;
86  }
87  else
88  {
89  return false;
90  }
91 }
92 
94 {
95  return mModel->displayExpression();
96 }
97 
99 {
100  return mModel->parserErrorString();
101 }
102 
104 {
105  QgsFeatureIds selection;
106  Q_FOREACH ( const QModelIndex& idx, mCurrentEditSelectionModel->selectedIndexes() )
107  {
109  }
110  return selection;
111 }
112 
114 {
115  mItemDelegate->setCurrentFeatureEdited( state );
116  viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
117 }
118 
120 {
121  if ( mModel )
122  {
123  QPoint pos = event->pos();
124 
125  QModelIndex index = indexAt( pos );
126 
127  if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
128  {
129  mEditSelectionDrag = true;
130  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
131  }
132  else
133  {
134  mFeatureSelectionModel->enableSync( false );
135  selectRow( index, true );
137  }
138  }
139  else
140  {
141  QgsDebugMsg( "No model assigned to this view" );
142  }
143 }
144 
145 void QgsFeatureListView::editSelectionChanged( QItemSelection deselected, QItemSelection selected )
146 {
147  if ( isVisible() && updatesEnabled() )
148  {
149  QItemSelection localDeselected = mModel->mapSelectionFromMaster( deselected );
150  QItemSelection localSelected = mModel->mapSelectionFromMaster( selected );
151  viewport()->update( visualRegionForSelection( localDeselected ) | visualRegionForSelection( localSelected ) );
152  }
153 
154  QItemSelection currentSelection = mCurrentEditSelectionModel->selection();
155  if ( currentSelection.size() == 1 )
156  {
157  QModelIndexList indexList = currentSelection.indexes();
158  if ( !indexList.isEmpty() )
159  {
160  QgsFeature feat;
161  mModel->featureByIndex( mModel->mapFromMaster( indexList.first() ), feat );
162 
163  emit currentEditSelectionChanged( feat );
164  }
165  }
166 }
167 
169 {
170  QItemSelection selection;
171  selection.append( QItemSelectionRange( mModel->index( 0, 0 ), mModel->index( mModel->rowCount() - 1, 0 ) ) );
172 
173  mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
174 }
175 
177 {
178  QItemSelection selection;
179 
180  Q_FOREACH ( QgsFeatureId fid, fids )
181  {
182  selection.append( QItemSelectionRange( mModel->mapToMaster( mModel->fidToIdx( fid ) ) ) );
183  }
184 
185  bool ok = true;
186  emit aboutToChangeEditSelection( ok );
187 
188  if ( ok )
189  mCurrentEditSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
190 }
191 
193 {
194  bool ok = true;
195  emit aboutToChangeEditSelection( ok );
196 
197  if ( ok )
198  mCurrentEditSelectionModel->select( index, command );
199 }
200 
201 void QgsFeatureListView::repaintRequested( const QModelIndexList& indexes )
202 {
203  Q_FOREACH ( const QModelIndex& index, indexes )
204  {
205  update( index );
206  }
207 }
208 
210 {
211  setDirtyRegion( viewport()->rect() );
212 }
213 
221 {
222  QPoint pos = event->pos();
223 
224  QModelIndex index = indexAt( pos );
225 
226  if ( mEditSelectionDrag )
227  {
228  setEditSelection( mModel->mapToMaster( index ), QItemSelectionModel::ClearAndSelect );
229  }
230  else
231  {
232  selectRow( index, false );
233  }
234 }
235 
244 {
245  Q_UNUSED( event );
246 
247  if ( mEditSelectionDrag )
248  {
249  mEditSelectionDrag = false;
250  }
251  else
252  {
253  mFeatureSelectionModel->enableSync( true );
254  }
255 }
256 
258 {
259  if ( Qt::Key_Up == event->key() || Qt::Key_Down == event->key() )
260  {
261  int currentRow = 0;
262  if ( 0 != mCurrentEditSelectionModel->selectedIndexes().count() )
263  {
264  QModelIndex localIndex = mModel->mapFromMaster( mCurrentEditSelectionModel->selectedIndexes().first() );
265  currentRow = localIndex.row();
266  }
267 
268  QModelIndex newLocalIndex;
269  QModelIndex newIndex;
270 
271  switch ( event->key() )
272  {
273  case Qt::Key_Up:
274  newLocalIndex = mModel->index( currentRow - 1, 0 );
275  newIndex = mModel->mapToMaster( newLocalIndex );
276  if ( newIndex.isValid() )
277  {
278  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
279  scrollTo( newLocalIndex );
280  }
281  break;
282 
283  case Qt::Key_Down:
284  newLocalIndex = mModel->index( currentRow + 1, 0 );
285  newIndex = mModel->mapToMaster( newLocalIndex );
286  if ( newIndex.isValid() )
287  {
288  setEditSelection( newIndex, QItemSelectionModel::ClearAndSelect );
289  scrollTo( newLocalIndex );
290  }
291  break;
292 
293  default:
294  break;
295  }
296  }
297  else
298  {
299  QListView::keyPressEvent( event );
300  }
301 }
302 
304 {
305  QModelIndex index = indexAt( event->pos() );
306 
307  if ( index.isValid() )
308  {
309  QgsFeature feature = mModel->data( index, QgsFeatureListModel::FeatureRole ).value<QgsFeature>();
310 
311  QgsActionMenu menu( mModel->layerCache()->layer(), &feature, this );
312  menu.exec( event->globalPos() );
313  }
314 }
315 
316 void QgsFeatureListView::selectRow( const QModelIndex& index, bool anchor )
317 {
319  int row = index.row();
320 
321  if ( anchor )
322  mRowAnchor = row;
323 
324  if ( selectionMode() != QListView::SingleSelection
325  && command.testFlag( QItemSelectionModel::Toggle ) )
326  {
327  if ( anchor )
328  mCtrlDragSelectionFlag = mFeatureSelectionModel->isSelected( index )
329  ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
330  command &= ~QItemSelectionModel::Toggle;
331  command |= mCtrlDragSelectionFlag;
332  if ( !anchor )
333  command |= QItemSelectionModel::Current;
334  }
335 
336  QModelIndex tl = model()->index( qMin( mRowAnchor, row ), 0 );
337  QModelIndex br = model()->index( qMax( mRowAnchor, row ), model()->columnCount() - 1 );
338 
339  mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
340 }
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:176
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
Element positionToElement(const QPoint &pos)
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QgsFeatureListView(QWidget *parent=0)
Creates a feature list view.
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
QPoint pos() const
QAction * exec()
QgsFeatureIds currentEditSelection()
Get the currentEditSelection.
QRect rect() const
int key() const
virtual void mouseMoveEvent(QMouseEvent *event) override
QgsAttributeTableModel * masterModel()
void displayExpressionChanged(const QString expression)
Is emitted, whenever the display expression is successfully changed.
This class caches features of a given QgsVectorLayer.
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
virtual void contextMenuEvent(QContextMenuEvent *event) override
virtual void keyPressEvent(QKeyEvent *event) override
qint64 QgsFeatureId
Definition: qgsfeature.h:31
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)
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.