QGIS API Documentation  master-3f58142
src/gui/attributetable/qgsattributetableview.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines