QGIS API Documentation  2.8.6-Wien
qgsattributetableview.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 <QKeyEvent>
17 #include <QSettings>
18 #include <QHeaderView>
19 #include <QMenu>
20 
21 #include "qgsattributetableview.h"
22 #include "qgsattributetablemodel.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsvectorlayercache.h"
28 #include "qgsvectordataprovider.h"
29 #include "qgslogger.h"
30 #include "qgsmapcanvas.h"
32 
34  : QTableView( parent )
35  , mMasterModel( NULL )
36  , mFilterModel( NULL )
37  , mFeatureSelectionModel( NULL )
38  , mFeatureSelectionManager( NULL )
39  , mModel( NULL )
40  , mActionPopup( NULL )
41  , mLayerCache( NULL )
42  , mRowSectionAnchor( 0 )
43  , mCtrlDragSelectionFlag( QItemSelectionModel::Select )
44 {
45  QSettings settings;
46  restoreGeometry( settings.value( "/BetterAttributeTable/geometry" ).toByteArray() );
47 
48  verticalHeader()->setDefaultSectionSize( 20 );
49  horizontalHeader()->setHighlightSections( false );
50 
51  mTableDelegate = new QgsAttributeTableDelegate( this );
52  setItemDelegate( mTableDelegate );
53 
54  setSelectionBehavior( QAbstractItemView::SelectRows );
55  setSelectionMode( QAbstractItemView::ExtendedSelection );
56  setSortingEnabled( true );
57 
58  verticalHeader()->viewport()->installEventFilter( this );
59 
60  connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) );
61  connect( verticalHeader(), SIGNAL( sectionEntered( int ) ), this, SLOT( _q_selectRow( int ) ) );
62 }
63 
65 {
66  delete mActionPopup;
67 }
68 
69 bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event )
70 {
71  if ( object == verticalHeader()->viewport() )
72  {
73  switch ( event->type() )
74  {
75  case QEvent::MouseButtonPress:
76  mFeatureSelectionModel->enableSync( false );
77  break;
78 
79  case QEvent::MouseButtonRelease:
80  mFeatureSelectionModel->enableSync( true );
81  break;
82 
83  default:
84  break;
85  }
86  }
87  return false;
88 }
89 
91 {
92  if ( mFilterModel )
93  {
94  // Cleanup old model stuff if present
95  disconnect( mFilterModel, SIGNAL( filterAboutToBeInvalidated() ), this, SLOT( onFilterAboutToBeInvalidated() ) );
96  disconnect( mFilterModel, SIGNAL( filterInvalidated() ), this, SLOT( onFilterInvalidated() ) );
97  }
98 
99  mFilterModel = filterModel;
100  QTableView::setModel( filterModel );
101 
102  connect( mFilterModel, SIGNAL( destroyed() ), this, SLOT( modelDeleted() ) );
103 
104  delete mFeatureSelectionModel;
105  mFeatureSelectionModel = 0;
106 
107  if ( filterModel )
108  {
109  if ( !mFeatureSelectionManager )
110  {
111  mFeatureSelectionManager = new QgsVectorLayerSelectionManager( mFilterModel->layer(), mFilterModel );
112  }
113 
114  mFeatureSelectionModel = new QgsFeatureSelectionModel( mFilterModel, mFilterModel, mFeatureSelectionManager, mFilterModel );
115  setSelectionModel( mFeatureSelectionModel );
116  mTableDelegate->setFeatureSelectionModel( mFeatureSelectionModel );
117  connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
118  connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
119  }
120 }
121 
123 {
124  if ( mFeatureSelectionManager )
125  delete mFeatureSelectionManager;
126 
127  mFeatureSelectionManager = featureSelectionManager;
128 
129  if ( mFeatureSelectionModel )
130  mFeatureSelectionModel->setFeatureSelectionManager( mFeatureSelectionManager );
131 }
132 
133 void QgsAttributeTableView::closeEvent( QCloseEvent *e )
134 {
135  Q_UNUSED( e );
136  QSettings settings;
137  settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
138 }
139 
140 void QgsAttributeTableView::mousePressEvent( QMouseEvent *event )
141 {
142  setSelectionMode( QAbstractItemView::NoSelection );
143  QTableView::mousePressEvent( event );
144  setSelectionMode( QAbstractItemView::ExtendedSelection );
145 }
146 
148 {
149  setSelectionMode( QAbstractItemView::NoSelection );
150  QTableView::mouseReleaseEvent( event );
151  setSelectionMode( QAbstractItemView::ExtendedSelection );
152 }
153 
154 void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
155 {
156  setSelectionMode( QAbstractItemView::NoSelection );
157  QTableView::mouseMoveEvent( event );
158  setSelectionMode( QAbstractItemView::ExtendedSelection );
159 }
160 
161 void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
162 {
163  switch ( event->key() )
164  {
165 
166  // Default Qt behavior would be to change the selection.
167  // We don't make it that easy for the user to trash his selection.
168  case Qt::Key_Up:
169  case Qt::Key_Down:
170  case Qt::Key_Left:
171  case Qt::Key_Right:
172  setSelectionMode( QAbstractItemView::NoSelection );
173  QTableView::keyPressEvent( event );
174  setSelectionMode( QAbstractItemView::ExtendedSelection );
175  break;
176 
177  default:
178  QTableView::keyPressEvent( event );
179  break;
180  }
181 }
182 
183 void QgsAttributeTableView::repaintRequested( QModelIndexList indexes )
184 {
185  foreach ( const QModelIndex index, indexes )
186  {
187  update( index );
188  }
189 }
190 
192 {
193  setDirtyRegion( viewport()->rect() );
194 }
195 
197 {
198  QItemSelection selection;
199  selection.append( QItemSelectionRange( mFilterModel->index( 0, 0 ), mFilterModel->index( mFilterModel->rowCount() - 1, 0 ) ) );
200  mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
201 }
202 
203 void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event )
204 {
205  delete mActionPopup;
206  mActionPopup = 0;
207 
208  QModelIndex idx = indexAt( event->pos() );
209  if ( !idx.isValid() )
210  {
211  return;
212  }
213 
214  QgsVectorLayer *vlayer = mFilterModel->layer();
215  if ( !vlayer )
216  return;
217 
218  mActionPopup = new QMenu();
219 
220  mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll );
221 
222  // let some other parts of the application add some actions
223  emit willShowContextMenu( mActionPopup, idx );
224 
225  if ( mActionPopup->actions().count() > 0 )
226  {
227  mActionPopup->popup( event->globalPos() );
228  }
229 }
230 
232 {
233  selectRow( row, true );
234 }
235 
237 {
238  selectRow( row, false );
239 }
240 
241 void QgsAttributeTableView::modelDeleted()
242 {
243  mFilterModel = 0;
244  mFeatureSelectionManager = 0;
245  mFeatureSelectionModel = 0;
246 }
247 
248 void QgsAttributeTableView::selectRow( int row, bool anchor )
249 {
250  if ( selectionBehavior() == QTableView::SelectColumns
251  || ( selectionMode() == QTableView::SingleSelection
252  && selectionBehavior() == QTableView::SelectItems ) )
253  return;
254 
255  if ( row >= 0 && row < model()->rowCount() )
256  {
257  int column = horizontalHeader()->logicalIndexAt( isRightToLeft() ? viewport()->width() : 0 );
258  QModelIndex index = model()->index( row, column );
259  QItemSelectionModel::SelectionFlags command = selectionCommand( index );
260  selectionModel()->setCurrentIndex( index, QItemSelectionModel::NoUpdate );
261  if (( anchor && !( command & QItemSelectionModel::Current ) )
262  || ( selectionMode() == QTableView::SingleSelection ) )
263  mRowSectionAnchor = row;
264 
265  if ( selectionMode() != QTableView::SingleSelection
266  && command.testFlag( QItemSelectionModel::Toggle ) )
267  {
268  if ( anchor )
269  mCtrlDragSelectionFlag = mFeatureSelectionModel->isSelected( index )
270  ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
271  command &= ~QItemSelectionModel::Toggle;
272  command |= mCtrlDragSelectionFlag;
273  if ( !anchor )
274  command |= QItemSelectionModel::Current;
275  }
276 
277  QModelIndex tl = model()->index( qMin( mRowSectionAnchor, row ), 0 );
278  QModelIndex br = model()->index( qMax( mRowSectionAnchor, row ), model()->columnCount() - 1 );
279  if ( verticalHeader()->sectionsMoved() && tl.row() != br.row() )
280  setSelection( visualRect( tl ) | visualRect( br ), command );
281  else
282  mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
283  }
284 }
static unsigned index
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
virtual bool eventFilter(QObject *object, QEvent *event) override
This event filter is installed on the verticalHeader to intercept mouse press and release events...
virtual void selectAll() override
void enableSync(bool enable)
Enables or disables synchronisation to the QgsVectorLayer When synchronisation is disabled...
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
void mouseReleaseEvent(QMouseEvent *event) override
Called for mouse release events on a table cell.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QgsAttributeTableView(QWidget *parent=0)
virtual void selectFeatures(const QItemSelection &selection, SelectionFlags command)
Select features on this table.
void mousePressEvent(QMouseEvent *event) override
Called for mouse press events on a table cell.
virtual void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
virtual void setModel(QgsAttributeTableFilterModel *filterModel)
void willShowContextMenu(QMenu *menu, QModelIndex atIndex)
Is emitted, in order to provide a hook to add aditional menu entries to the context menu...
void mouseMoveEvent(QMouseEvent *event) override
Called for mouse move events on a table cell.
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
setFeatureSelectionManager
A delegate item class for QgsAttributeTable (see Qt documentation for QItemDelegate).
virtual void selectRow(int row)
virtual void _q_selectRow(int row)
Is an interface class to abstract feature selection handling.
void closeEvent(QCloseEvent *event) override
Saves geometry to the settings on close.
Represents a vector layer which manages a vector based data sets.
void keyPressEvent(QKeyEvent *event) override
Called for key press events Disables selection change by only pressing an arrow key.
void contextMenuEvent(QContextMenuEvent *event) override
Is called when the context menu will be shown.
#define tr(sourceText)