QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
80 bool QgsFeatureListView::setDisplayExpression( const QString expression )
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 ( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
107  {
108  selection << idx.data( QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
109  }
110  return selection;
111 }
112 
114 {
115  mItemDelegate->setCurrentFeatureEdited( state );
116  viewport()->update( visualRegionForSelection( mCurrentEditSelectionModel->selection() ) );
117 }
118 
119 void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
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  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 
192 void QgsFeatureListView::setEditSelection( const QModelIndex& index, QItemSelectionModel::SelectionFlags command )
193 {
194  bool ok = true;
195  emit aboutToChangeEditSelection( ok );
196 
197  if ( ok )
198  mCurrentEditSelectionModel->select( index, command );
199 }
200 
201 void QgsFeatureListView::repaintRequested( QModelIndexList indexes )
202 {
203  foreach ( const QModelIndex index, indexes )
204  {
205  update( index );
206  }
207 }
208 
210 {
211  setDirtyRegion( viewport()->rect() );
212 }
213 
220 void QgsFeatureListView::mouseMoveEvent( QMouseEvent *event )
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 
243 void QgsFeatureListView::mouseReleaseEvent( QMouseEvent *event )
244 {
245  Q_UNUSED( event );
246 
247  if ( mEditSelectionDrag )
248  {
249  mEditSelectionDrag = false;
250  }
251  else
252  {
253  mFeatureSelectionModel->enableSync( true );
254  }
255 }
256 
257 void QgsFeatureListView::keyPressEvent( QKeyEvent *event )
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 
303 void QgsFeatureListView::contextMenuEvent( QContextMenuEvent *event )
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 {
318  QItemSelectionModel::SelectionFlags command = selectionCommand( index );
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 }
static unsigned index
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
void setCurrentFeatureEdited(bool state)
Sets if the currently shown form has received any edit events so far.
virtual void mouseReleaseEvent(QMouseEvent *event) override
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:317
virtual QModelIndex mapToMaster(const QModelIndex &proxyIndex) const
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool featureByIndex(const QModelIndex &index, QgsFeature &feat)
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:113
const QString displayExpression() const
Returns the expression which is currently used to render the features.
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.
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.
QgsFeatureListModel * featureListModel()
Get the featureListModel used by this view.
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
bool setDisplayExpression(const QString expression)
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
virtual void selectFeatures(const QItemSelection &selection, SelectionFlags command)
Select features on this table.
QString parserErrorString()
Returns a detailed message about errors while parsing a QgsExpression.
QgsFeatureIds currentEditSelection()
Get the currentEditSelection.
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.
bool setDisplayExpression(const QString displayExpression)
The display expression is an expression used to render the fields into a single string which is displ...
virtual void selectAll() override
Select all currently visible features.
virtual void mousePressEvent(QMouseEvent *event) override
virtual void contextMenuEvent(QContextMenuEvent *event) override
virtual void keyPressEvent(QKeyEvent *event) override
qint64 QgsFeatureId
Definition: qgsfeature.h:30
QgsVectorLayerCache * layerCache()
QModelIndex fidToIdx(const QgsFeatureId fid) const
void setEditSelectionModel(QItemSelectionModel *editSelectionModel)
void currentEditSelectionChanged(QgsFeature &feat)
Is emitted, whenever the current edit selection has been changed.
virtual QItemSelection mapSelectionFromMaster(const QItemSelection &selection) const
virtual void setModel(QgsFeatureListModel *featureListModel)
Set the QgsFeatureListModel which is used to retrieve information.
QString displayExpression() const
QgsVectorLayerCache * layerCache()
Returns the layer cache.