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