QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 }