QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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"
27 #include "qgsvectordataprovider.h"
28 #include "qgslogger.h"
29 #include "qgsmapcanvas.h"
31 
33  : QTableView( parent )
34  , mMasterModel( NULL )
35  , mFilterModel( NULL )
36  , mFeatureSelectionModel( NULL )
37  , mActionPopup( NULL )
38 {
39  QSettings settings;
40  restoreGeometry( settings.value( "/BetterAttributeTable/geometry" ).toByteArray() );
41 
42  verticalHeader()->setDefaultSectionSize( 20 );
43  horizontalHeader()->setHighlightSections( false );
44 
46  setItemDelegate( mTableDelegate );
47 
48  setSelectionBehavior( QAbstractItemView::SelectRows );
49  setSelectionMode( QAbstractItemView::ExtendedSelection );
50  setSortingEnabled( true );
51 
52  verticalHeader()->viewport()->installEventFilter( this );
53 
54  connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) );
55  connect( verticalHeader(), SIGNAL( sectionEntered( int ) ), this, SLOT( _q_selectRow( int ) ) );
56 }
57 
59 {
60  if ( mActionPopup )
61  {
62  delete mActionPopup;
63  }
64 }
65 
67 {
70 
71  mMasterModel = new QgsAttributeTableModel( layerCache, this );
72 
73  mLayerCache = layerCache;
74 
76 
81  connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
82  connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
83  setSelectionModel( mFeatureSelectionModel );
84 
85  delete oldModel;
86  delete filterModel;
87 }
88 
89 bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event )
90 {
91  if ( object == verticalHeader()->viewport() )
92  {
93  switch ( event->type() )
94  {
95  case QEvent::MouseButtonPress:
97  break;
98 
99  case QEvent::MouseButtonRelease:
101  break;
102 
103  default:
104  break;
105  }
106  }
107  return false;
108 }
109 
111 {
112  if ( mFilterModel )
113  {
114  // Cleanup old model stuff if present
115  disconnect( mFilterModel, SIGNAL( filterAboutToBeInvalidated() ), this, SLOT( onFilterAboutToBeInvalidated() ) );
116  disconnect( mFilterModel, SIGNAL( filterInvalidated() ), this, SLOT( onFilterInvalidated() ) );
117  }
118 
119  mFilterModel = filterModel;
120  QTableView::setModel( filterModel );
121 
122  delete mFeatureSelectionModel;
123  mFeatureSelectionModel = NULL;
124 
125  if ( filterModel )
126  {
128  setSelectionModel( mFeatureSelectionModel );
130  connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) );
131  connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) );
132  }
133 }
134 
135 void QgsAttributeTableView::closeEvent( QCloseEvent *e )
136 {
137  Q_UNUSED( e );
138  QSettings settings;
139  settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) );
140 }
141 
142 void QgsAttributeTableView::mousePressEvent( QMouseEvent *event )
143 {
144  setSelectionMode( QAbstractItemView::NoSelection );
146  setSelectionMode( QAbstractItemView::ExtendedSelection );
147 }
148 
150 {
151  setSelectionMode( QAbstractItemView::NoSelection );
153  setSelectionMode( QAbstractItemView::ExtendedSelection );
154 }
155 
156 void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
157 {
158  setSelectionMode( QAbstractItemView::NoSelection );
160  setSelectionMode( QAbstractItemView::ExtendedSelection );
161 }
162 
163 void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
164 {
165  switch ( event->key() )
166  {
167 
168  // Default Qt behavior would be to change the selection.
169  // We don't make it that easy for the user to trash his selection.
170  case Qt::Key_Up:
171  case Qt::Key_Down:
172  case Qt::Key_Left:
173  case Qt::Key_Right:
174  setSelectionMode( QAbstractItemView::NoSelection );
175  QTableView::keyPressEvent( event );
176  setSelectionMode( QAbstractItemView::ExtendedSelection );
177  break;
178 
179  default:
180  QTableView::keyPressEvent( event );
181  break;
182  }
183 }
184 
185 void QgsAttributeTableView::repaintRequested( QModelIndexList indexes )
186 {
187  foreach ( const QModelIndex index, indexes )
188  {
189  update( index );
190  }
191 }
192 
194 {
195  setDirtyRegion( viewport()->rect() );
196 }
197 
199 {
200  QItemSelection selection;
201  selection.append( QItemSelectionRange( mFilterModel->index( 0, 0 ), mFilterModel->index( mFilterModel->rowCount() - 1, 0 ) ) );
202  mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
203 }
204 
205 void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event )
206 {
207  if ( mActionPopup )
208  {
209  delete mActionPopup;
210  mActionPopup = 0;
211  }
212 
213  QModelIndex idx = indexAt( event->pos() );
214  if ( !idx.isValid() )
215  {
216  return;
217  }
218 
219  QgsVectorLayer *vlayer = mFilterModel->layer();
220  if ( !vlayer )
221  return;
222 
223  mActionPopup = new QMenu();
224 
225  mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll );
226 
227  // let some other parts of the application add some actions
228  emit willShowContextMenu( mActionPopup, idx );
229 
230  if ( mActionPopup->actions().count() > 0 )
231  {
232  mActionPopup->popup( event->globalPos() );
233  }
234 }
235 
237 {
238  selectRow( row, true );
239 }
240 
242 {
243  selectRow( row, false );
244 }
245 
246 void QgsAttributeTableView::selectRow( int row, bool anchor )
247 {
248  if ( selectionBehavior() == QTableView::SelectColumns
249  || ( selectionMode() == QTableView::SingleSelection
250  && selectionBehavior() == QTableView::SelectItems ) )
251  return;
252 
253  if ( row >= 0 && row < model()->rowCount() )
254  {
255  int column = horizontalHeader()->logicalIndexAt( isRightToLeft() ? viewport()->width() : 0 );
256  QModelIndex index = model()->index( row, column );
257  QItemSelectionModel::SelectionFlags command = selectionCommand( index );
258  selectionModel()->setCurrentIndex( index, QItemSelectionModel::NoUpdate );
259  if (( anchor && !( command & QItemSelectionModel::Current ) )
260  || ( selectionMode() == QTableView::SingleSelection ) )
261  mRowSectionAnchor = row;
262 
263  if ( selectionMode() != QTableView::SingleSelection
264  && command.testFlag( QItemSelectionModel::Toggle ) )
265  {
266  if ( anchor )
268  ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
269  command &= ~QItemSelectionModel::Toggle;
270  command |= mCtrlDragSelectionFlag;
271  if ( !anchor )
272  command |= QItemSelectionModel::Current;
273  }
274 
275  QModelIndex tl = model()->index( qMin( mRowSectionAnchor, row ), 0 );
276  QModelIndex br = model()->index( qMax( mRowSectionAnchor, row ), model()->columnCount() - 1 );
277  if ( verticalHeader()->sectionsMoved() && tl.row() != br.row() )
278  setSelection( visualRect( tl ) | visualRect( br ), command );
279  else
280  mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command );
281  }
282 }