QGIS API Documentation  master-59fd5e0
src/gui/attributetable/qgsattributetablefiltermodel.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002      QgsAttributeTableFilterModel.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 <QItemSelectionModel>
00017 
00018 #include "qgsattributetablefiltermodel.h"
00019 #include "qgsattributetablemodel.h"
00020 #include "qgsvectorlayer.h"
00021 #include "qgsfeature.h"
00022 #include "qgsmapcanvas.h"
00023 #include "qgslogger.h"
00024 #include "qgsrendererv2.h"
00025 #include "qgsvectorlayereditbuffer.h"
00027 // Filter Model //
00029 
00030 QgsAttributeTableFilterModel::QgsAttributeTableFilterModel( QgsMapCanvas* canvas, QgsAttributeTableModel* sourceModel, QObject* parent )
00031     : QSortFilterProxyModel( parent )
00032     , mCanvas( canvas )
00033     , mFilterMode( ShowAll )
00034     , mSelectedOnTop( false )
00035 {
00036   mMasterSelection = new QItemSelectionModel( this, this );
00037   setSourceModel( sourceModel );
00038   setDynamicSortFilter( true );
00039   setSortRole( QgsAttributeTableModel::SortRole );
00040   connect( layer(), SIGNAL( selectionChanged() ), SLOT( selectionChanged() ) );
00041 }
00042 
00043 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
00044 {
00045   if ( mSelectedOnTop )
00046   {
00047     bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) );
00048     bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) );
00049 
00050     if ( leftSelected && !rightSelected )
00051     {
00052       return true;
00053     }
00054     else if ( rightSelected && !leftSelected )
00055     {
00056       return false;
00057     }
00058   }
00059 
00060 
00061   QVariant leftData = left.data( QgsAttributeTableModel::SortRole );
00062   QVariant rightData = right.data( QgsAttributeTableModel::SortRole );
00063 
00064   if ( leftData.isNull() )
00065     return true;
00066 
00067   if ( rightData.isNull() )
00068     return false;
00069 
00070   switch ( leftData.type() )
00071   {
00072     case QVariant::Int:
00073     case QVariant::UInt:
00074     case QVariant::LongLong:
00075     case QVariant::ULongLong:
00076       return leftData.toLongLong() < rightData.toLongLong();
00077 
00078     case QVariant::Double:
00079       return leftData.toDouble() < rightData.toDouble();
00080 
00081     default:
00082       return leftData.toString().localeAwareCompare( rightData.toString() ) < 0;
00083   }
00084 
00085   // Avoid warning. Will never reach this
00086   return false;
00087 }
00088 
00089 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
00090 {
00091   masterModel()->prefetchColumnData( column );
00092   QSortFilterProxyModel::sort( column, order );
00093 }
00094 
00095 void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop )
00096 {
00097   if ( mSelectedOnTop != selectedOnTop )
00098   {
00099     mSelectedOnTop = selectedOnTop;
00100 
00101     if ( sortColumn() == -1 )
00102     {
00103       sort( 0 );
00104     }
00105     invalidate();
00106   }
00107 }
00108 
00109 void QgsAttributeTableFilterModel::setSourceModel( QgsAttributeTableModel* sourceModel )
00110 {
00111   mTableModel = sourceModel;
00112   delete mMasterSelection;
00113   mMasterSelection = new QItemSelectionModel( sourceModel, this );
00114 
00115   QSortFilterProxyModel::setSourceModel( sourceModel );
00116 }
00117 
00118 bool QgsAttributeTableFilterModel::selectedOnTop()
00119 {
00120   return mSelectedOnTop;
00121 }
00122 
00123 void QgsAttributeTableFilterModel::setFilteredFeatures( QgsFeatureIds ids )
00124 {
00125   mFilteredFeatures = ids;
00126   setFilterMode( ShowFilteredList );
00127   invalidateFilter();
00128 }
00129 
00130 void QgsAttributeTableFilterModel::setFilterMode( FilterMode filterMode )
00131 {
00132   if ( filterMode != mFilterMode )
00133   {
00134     if ( filterMode == ShowVisible )
00135     {
00136       connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
00137       generateListOfVisibleFeatures();
00138     }
00139     else
00140     {
00141       disconnect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );
00142     }
00143 
00144     if ( filterMode == ShowSelected )
00145     {
00146       generateListOfVisibleFeatures();
00147     }
00148 
00149     mFilterMode = filterMode;
00150     invalidateFilter();
00151   }
00152 }
00153 
00154 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
00155 {
00156   Q_UNUSED( sourceParent );
00157   switch ( mFilterMode )
00158   {
00159     case ShowAll:
00160       return true;
00161       break;
00162 
00163     case ShowFilteredList:
00164       return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
00165       break;
00166 
00167     case ShowSelected:
00168       return layer()->selectedFeaturesIds().contains( masterModel()->rowToId( sourceRow ) );
00169       break;
00170 
00171     case ShowVisible:
00172       return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
00173       break;
00174 
00175     case ShowEdited:
00176     {
00177       QgsVectorLayerEditBuffer* editBuffer = layer()->editBuffer();
00178       if ( editBuffer )
00179       {
00180         const QList<QgsFeatureId> addedFeatures = editBuffer->addedFeatures().keys();
00181         const QList<QgsFeatureId> changedFeatures = editBuffer->changedAttributeValues().keys();
00182         const QgsFeatureId fid = masterModel()->rowToId( sourceRow );
00183         return addedFeatures.contains( fid ) || changedFeatures.contains( fid );
00184       }
00185       return false;
00186       break;
00187     }
00188 
00189     default:
00190       Q_ASSERT( false ); // In debug mode complain
00191       return true; // In release mode accept row
00192       break;
00193   }
00194   // returns are handled in their respective case statement above
00195 }
00196 
00197 void QgsAttributeTableFilterModel::extentsChanged()
00198 {
00199   generateListOfVisibleFeatures();
00200   invalidateFilter();
00201 }
00202 
00203 void QgsAttributeTableFilterModel::selectionChanged()
00204 {
00205   if ( ShowSelected == mFilterMode )
00206   {
00207     generateListOfVisibleFeatures();
00208     invalidateFilter();
00209   }
00210   else if ( mSelectedOnTop )
00211   {
00212     sort( sortColumn(), sortOrder() );
00213     invalidate();
00214   }
00215 }
00216 
00217 void QgsAttributeTableFilterModel::generateListOfVisibleFeatures()
00218 {
00219   if ( !layer() )
00220     return;
00221 
00222   bool filter = false;
00223   QgsRectangle rect = mCanvas->mapRenderer()->mapToLayerCoordinates( layer(), mCanvas->extent() );
00224   QgsRenderContext renderContext;
00225   QgsFeatureRendererV2* renderer = layer()->rendererV2();
00226 
00227   mFilteredFeatures.clear();
00228 
00229   if ( !renderer )
00230   {
00231     QgsDebugMsg( "Cannot get renderer" );
00232     return;
00233   }
00234 
00235   if ( layer()->hasScaleBasedVisibility() &&
00236        ( layer()->minimumScale() > mCanvas->mapRenderer()->scale() ||
00237          layer()->maximumScale() <= mCanvas->mapRenderer()->scale() ) )
00238   {
00239     QgsDebugMsg( "Out of scale limits" );
00240   }
00241   else
00242   {
00243     if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
00244     {
00245       // setup scale
00246       // mapRenderer()->renderContext()->scale is not automaticaly updated when
00247       // render extent changes (because it's scale is used to identify if changed
00248       // since last render) -> use local context
00249       renderContext.setExtent( mCanvas->mapRenderer()->rendererContext()->extent() );
00250       renderContext.setMapToPixel( mCanvas->mapRenderer()->rendererContext()->mapToPixel() );
00251       renderContext.setRendererScale( mCanvas->mapRenderer()->scale() );
00252     }
00253 
00254     filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
00255   }
00256 
00257   renderer->startRender( renderContext, layer() );
00258 
00259   QgsFeatureIterator features = masterModel()->layerCache()->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setFilterRect( rect ) );
00260 
00261   QgsFeature f;
00262 
00263   while ( features.nextFeature( f ) )
00264   {
00265     if ( !filter || renderer->willRenderFeature( f ) )
00266     {
00267       mFilteredFeatures << f.id();
00268     }
00269 #if 0
00270     if ( t.elapsed() > 5000 )
00271     {
00272       bool cancel = false;
00273       emit progress( i, cancel );
00274       if ( cancel )
00275         break;
00276 
00277       t.restart();
00278     }
00279 #endif
00280   }
00281 
00282   features.close();
00283 
00284   if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
00285   {
00286     renderer->stopRender( renderContext );
00287   }
00288 }
00289 
00290 QgsFeatureId QgsAttributeTableFilterModel::rowToId( const QModelIndex& row )
00291 {
00292   return masterModel()->rowToId( mapToSource( row ).row() );
00293 }
00294 
00295 QModelIndex QgsAttributeTableFilterModel::fidToIndex( QgsFeatureId fid )
00296 {
00297   return mapFromMaster( masterModel()->idToIndex( fid ) );
00298 }
00299 
00300 QModelIndexList QgsAttributeTableFilterModel::fidToIndexList( QgsFeatureId fid )
00301 {
00302   QModelIndexList indexes;
00303   foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) )
00304   {
00305     indexes.append( mapFromMaster( idx ) );
00306   }
00307 
00308   return indexes;
00309 }
00310 
00311 QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
00312 {
00313   // Master is source
00314   return mapToSource( proxyIndex );
00315 }
00316 
00317 QModelIndex QgsAttributeTableFilterModel::mapFromMaster( const QModelIndex &sourceIndex ) const
00318 {
00319   // Master is source
00320   return mapFromSource( sourceIndex );
00321 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines