|
QGIS API Documentation
master-3f58142
|
00001 /*************************************************************************** 00002 QgsAttributeTableView.cpp 00003 -------------------------------------- 00004 Date : Feb 2009 00005 Copyright : (C) 2009 Vita Cizek 00006 Email : weetya (at) gmail.com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include <QKeyEvent> 00017 #include <QSettings> 00018 #include <QHeaderView> 00019 #include <QMenu> 00020 00021 #include "qgsattributetableview.h" 00022 #include "qgsattributetablemodel.h" 00023 #include "qgsattributetabledelegate.h" 00024 #include "qgsattributetablefiltermodel.h" 00025 #include "qgsvectorlayer.h" 00026 #include "qgsvectorlayercache.h" 00027 #include "qgsvectordataprovider.h" 00028 #include "qgslogger.h" 00029 #include "qgsmapcanvas.h" 00030 #include "qgsfeatureselectionmodel.h" 00031 00032 QgsAttributeTableView::QgsAttributeTableView( QWidget *parent ) 00033 : QTableView( parent ) 00034 , mMasterModel( NULL ) 00035 , mFilterModel( NULL ) 00036 , mFeatureSelectionModel( NULL ) 00037 , mActionPopup( NULL ) 00038 { 00039 QSettings settings; 00040 restoreGeometry( settings.value( "/BetterAttributeTable/geometry" ).toByteArray() ); 00041 00042 verticalHeader()->setDefaultSectionSize( 20 ); 00043 horizontalHeader()->setHighlightSections( false ); 00044 00045 mTableDelegate = new QgsAttributeTableDelegate( this ); 00046 setItemDelegate( mTableDelegate ); 00047 00048 setSelectionBehavior( QAbstractItemView::SelectRows ); 00049 setSelectionMode( QAbstractItemView::ExtendedSelection ); 00050 setSortingEnabled( true ); 00051 00052 verticalHeader()->viewport()->installEventFilter( this ); 00053 00054 connect( verticalHeader(), SIGNAL( sectionPressed( int ) ), this, SLOT( selectRow( int ) ) ); 00055 connect( verticalHeader(), SIGNAL( sectionEntered( int ) ), this, SLOT( _q_selectRow( int ) ) ); 00056 } 00057 00058 QgsAttributeTableView::~QgsAttributeTableView() 00059 { 00060 if ( mActionPopup ) 00061 { 00062 delete mActionPopup; 00063 } 00064 } 00065 00066 void QgsAttributeTableView::setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVectorLayerCache *layerCache ) 00067 { 00068 QgsAttributeTableModel* oldModel = mMasterModel; 00069 QgsAttributeTableFilterModel* filterModel = mFilterModel; 00070 00071 mMasterModel = new QgsAttributeTableModel( layerCache, this ); 00072 00073 mLayerCache = layerCache; 00074 00075 mMasterModel->loadLayer(); 00076 00077 mFilterModel = new QgsAttributeTableFilterModel( canvas, mMasterModel, mMasterModel ); 00078 setModel( mFilterModel ); 00079 delete mFeatureSelectionModel; 00080 mFeatureSelectionModel = new QgsFeatureSelectionModel( mFilterModel, mFilterModel, layerCache->layer(), mFilterModel ); 00081 connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) ); 00082 connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) ); 00083 setSelectionModel( mFeatureSelectionModel ); 00084 00085 delete oldModel; 00086 delete filterModel; 00087 } 00088 00089 bool QgsAttributeTableView::eventFilter( QObject *object, QEvent *event ) 00090 { 00091 if ( object == verticalHeader()->viewport() ) 00092 { 00093 switch ( event->type() ) 00094 { 00095 case QEvent::MouseButtonPress: 00096 mFeatureSelectionModel->enableSync( false ); 00097 break; 00098 00099 case QEvent::MouseButtonRelease: 00100 mFeatureSelectionModel->enableSync( true ); 00101 break; 00102 00103 default: 00104 break; 00105 } 00106 } 00107 return false; 00108 } 00109 00110 void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel ) 00111 { 00112 if ( mFilterModel ) 00113 { 00114 // Cleanup old model stuff if present 00115 disconnect( mFilterModel, SIGNAL( filterAboutToBeInvalidated() ), this, SLOT( onFilterAboutToBeInvalidated() ) ); 00116 disconnect( mFilterModel, SIGNAL( filterInvalidated() ), this, SLOT( onFilterInvalidated() ) ); 00117 } 00118 00119 mFilterModel = filterModel; 00120 QTableView::setModel( filterModel ); 00121 00122 delete mFeatureSelectionModel; 00123 mFeatureSelectionModel = NULL; 00124 00125 if ( filterModel ) 00126 { 00127 mFeatureSelectionModel = new QgsFeatureSelectionModel( mFilterModel, mFilterModel, mFilterModel->layer(), mFilterModel ); 00128 setSelectionModel( mFeatureSelectionModel ); 00129 mTableDelegate->setFeatureSelectionModel( mFeatureSelectionModel ); 00130 connect( mFeatureSelectionModel, SIGNAL( requestRepaint( QModelIndexList ) ), this, SLOT( repaintRequested( QModelIndexList ) ) ); 00131 connect( mFeatureSelectionModel, SIGNAL( requestRepaint() ), this, SLOT( repaintRequested() ) ); 00132 } 00133 } 00134 00135 void QgsAttributeTableView::closeEvent( QCloseEvent *e ) 00136 { 00137 Q_UNUSED( e ); 00138 QSettings settings; 00139 settings.setValue( "/BetterAttributeTable/geometry", QVariant( saveGeometry() ) ); 00140 } 00141 00142 void QgsAttributeTableView::mousePressEvent( QMouseEvent *event ) 00143 { 00144 setSelectionMode( QAbstractItemView::NoSelection ); 00145 QTableView::mousePressEvent( event ); 00146 setSelectionMode( QAbstractItemView::ExtendedSelection ); 00147 } 00148 00149 void QgsAttributeTableView::mouseReleaseEvent( QMouseEvent *event ) 00150 { 00151 setSelectionMode( QAbstractItemView::NoSelection ); 00152 QTableView::mouseReleaseEvent( event ); 00153 setSelectionMode( QAbstractItemView::ExtendedSelection ); 00154 } 00155 00156 void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event ) 00157 { 00158 setSelectionMode( QAbstractItemView::NoSelection ); 00159 QTableView::mouseMoveEvent( event ); 00160 setSelectionMode( QAbstractItemView::ExtendedSelection ); 00161 } 00162 00163 void QgsAttributeTableView::keyPressEvent( QKeyEvent *event ) 00164 { 00165 switch ( event->key() ) 00166 { 00167 00168 // Default Qt behavior would be to change the selection. 00169 // We don't make it that easy for the user to trash his selection. 00170 case Qt::Key_Up: 00171 case Qt::Key_Down: 00172 case Qt::Key_Left: 00173 case Qt::Key_Right: 00174 setSelectionMode( QAbstractItemView::NoSelection ); 00175 QTableView::keyPressEvent( event ); 00176 setSelectionMode( QAbstractItemView::ExtendedSelection ); 00177 break; 00178 00179 default: 00180 QTableView::keyPressEvent( event ); 00181 break; 00182 } 00183 } 00184 00185 void QgsAttributeTableView::repaintRequested( QModelIndexList indexes ) 00186 { 00187 foreach ( const QModelIndex index, indexes ) 00188 { 00189 update( index ); 00190 } 00191 } 00192 00193 void QgsAttributeTableView::repaintRequested() 00194 { 00195 setDirtyRegion( viewport()->rect() ); 00196 } 00197 00198 void QgsAttributeTableView::selectAll() 00199 { 00200 QItemSelection selection; 00201 selection.append( QItemSelectionRange( mFilterModel->index( 0, 0 ), mFilterModel->index( mFilterModel->rowCount() - 1, 0 ) ) ); 00202 mFeatureSelectionModel->selectFeatures( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows ); 00203 } 00204 00205 void QgsAttributeTableView::contextMenuEvent( QContextMenuEvent* event ) 00206 { 00207 if ( mActionPopup ) 00208 { 00209 delete mActionPopup; 00210 mActionPopup = 0; 00211 } 00212 00213 QModelIndex idx = indexAt( event->pos() ); 00214 if ( !idx.isValid() ) 00215 { 00216 return; 00217 } 00218 00219 QgsVectorLayer *vlayer = mFilterModel->layer(); 00220 if ( !vlayer ) 00221 return; 00222 00223 mActionPopup = new QMenu(); 00224 00225 mActionPopup->addAction( tr( "Select All" ), this, SLOT( selectAll() ), QKeySequence::SelectAll ); 00226 00227 // let some other parts of the application add some actions 00228 emit willShowContextMenu( mActionPopup, idx ); 00229 00230 if ( mActionPopup->actions().count() > 0 ) 00231 { 00232 mActionPopup->popup( event->globalPos() ); 00233 } 00234 } 00235 00236 void QgsAttributeTableView::selectRow( int row ) 00237 { 00238 selectRow( row, true ); 00239 } 00240 00241 void QgsAttributeTableView::_q_selectRow( int row ) 00242 { 00243 selectRow( row, false ); 00244 } 00245 00246 void QgsAttributeTableView::selectRow( int row, bool anchor ) 00247 { 00248 if ( selectionBehavior() == QTableView::SelectColumns 00249 || ( selectionMode() == QTableView::SingleSelection 00250 && selectionBehavior() == QTableView::SelectItems ) ) 00251 return; 00252 00253 if ( row >= 0 && row < model()->rowCount() ) 00254 { 00255 int column = horizontalHeader()->logicalIndexAt( isRightToLeft() ? viewport()->width() : 0 ); 00256 QModelIndex index = model()->index( row, column ); 00257 QItemSelectionModel::SelectionFlags command = selectionCommand( index ); 00258 selectionModel()->setCurrentIndex( index, QItemSelectionModel::NoUpdate ); 00259 if (( anchor && !( command & QItemSelectionModel::Current ) ) 00260 || ( selectionMode() == QTableView::SingleSelection ) ) 00261 mRowSectionAnchor = row; 00262 00263 if ( selectionMode() != QTableView::SingleSelection 00264 && command.testFlag( QItemSelectionModel::Toggle ) ) 00265 { 00266 if ( anchor ) 00267 mCtrlDragSelectionFlag = mFeatureSelectionModel->isSelected( index ) 00268 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; 00269 command &= ~QItemSelectionModel::Toggle; 00270 command |= mCtrlDragSelectionFlag; 00271 if ( !anchor ) 00272 command |= QItemSelectionModel::Current; 00273 } 00274 00275 QModelIndex tl = model()->index( qMin( mRowSectionAnchor, row ), 0 ); 00276 QModelIndex br = model()->index( qMax( mRowSectionAnchor, row ), model()->columnCount() - 1 ); 00277 if ( verticalHeader()->sectionsMoved() && tl.row() != br.row() ) 00278 setSelection( visualRect( tl ) | visualRect( br ), command ); 00279 else 00280 mFeatureSelectionModel->selectFeatures( QItemSelection( tl, br ), command ); 00281 } 00282 }