bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const { if ( mSelectedOnTop ) { bool leftSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( left.row() ) ); bool rightSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( right.row() ) ); if ( leftSelected && !rightSelected ) { return sortOrder() == Qt::AscendingOrder; } else if ( rightSelected && !leftSelected ) { return sortOrder() == Qt::DescendingOrder; } } if ( mTableModel->sortCacheExpression().isEmpty() ) { //shortcut when no sort order set return false; } return qgsVariantLessThan( left.data( QgsAttributeTableModel::SortRole ), right.data( QgsAttributeTableModel::SortRole ) ); }
bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const { if ( mSelectedOnTop ) { bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) ); bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) ); if ( leftSelected && !rightSelected ) { return true; } else if ( rightSelected && !leftSelected ) { return false; } } QVariant leftData = left.data( QgsAttributeTableModel::SortRole ); QVariant rightData = right.data( QgsAttributeTableModel::SortRole ); if ( leftData.isNull() ) return true; if ( rightData.isNull() ) return false; switch ( leftData.type() ) { case QVariant::Int: case QVariant::UInt: case QVariant::LongLong: case QVariant::ULongLong: return leftData.toLongLong() < rightData.toLongLong(); case QVariant::Double: return leftData.toDouble() < rightData.toDouble(); case QVariant::Date: return leftData.toDate() < rightData.toDate(); case QVariant::DateTime: return leftData.toDateTime() < rightData.toDateTime(); default: return leftData.toString().localeAwareCompare( rightData.toString() ) < 0; } // Avoid warning. Will never reach this return false; }
QWidget *QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const { Q_UNUSED( option ); QgsVectorLayer *vl = layer( index.model() ); if ( !vl ) return nullptr; int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt(); QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup ); QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vl, fieldIdx, nullptr, parent, context ); QWidget *w = eww->widget(); w->setAutoFillBackground( true ); w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget const int fieldOrigin = vl->fields().fieldOrigin( fieldIdx ); bool readOnly = true; if ( fieldOrigin == QgsFields::OriginJoin ) { int srcFieldIndex; const QgsVectorLayerJoinInfo *info = vl->joinBuffer()->joinForFieldIndex( fieldIdx, vl->fields(), srcFieldIndex ); if ( info && info->isEditable() ) readOnly = info->joinLayer()->editFormConfig().readOnly( srcFieldIndex ); } else readOnly = vl->editFormConfig().readOnly( fieldIdx ); eww->setEnabled( !readOnly ); return w; }
void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order ) { int myColumn = mColumnMapping.at( column ); masterModel()->prefetchColumnData( myColumn ); QSortFilterProxyModel::sort( myColumn, order ); emit sortColumnChanged( column, order ); }
QModelIndexList QgsAttributeTableFilterModel::fidToIndexList( QgsFeatureId fid ) { QModelIndexList indexes; foreach ( QModelIndex idx, masterModel()->idToIndexList( fid ) ) { indexes.append( mapFromMaster( idx ) ); }
void QgsAttributeTableFilterModel::sort( const QString &expression, Qt::SortOrder order ) { if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder ) order = Qt::AscendingOrder; QSortFilterProxyModel::sort( -1 ); masterModel()->prefetchSortData( expression ); QSortFilterProxyModel::sort( 0, order ); }
bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const { Q_UNUSED( sourceParent ); switch ( mFilterMode ) { case ShowAll: return true; case ShowFilteredList: return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) ); case ShowSelected: return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) ); case ShowVisible: return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) ); case ShowEdited: { QgsVectorLayerEditBuffer *editBuffer = layer()->editBuffer(); if ( editBuffer ) { QgsFeatureId fid = masterModel()->rowToId( sourceRow ); if ( editBuffer->isFeatureAdded( fid ) ) return true; if ( editBuffer->isFeatureAttributesChanged( fid ) ) return true; if ( editBuffer->isFeatureGeometryChanged( fid ) ) return true; return false; } return false; } default: Q_ASSERT( false ); // In debug mode complain return true; // In release mode accept row } // returns are handled in their respective case statement above }
void QgsDualView::updateSelectedFeatures() { QgsFeatureRequest r = mMasterModel->request(); if ( r.filterType() == QgsFeatureRequest::FilterNone && r.filterRect().isNull() ) return; // already requested all features r.setFilterFids( masterModel()->layer()->selectedFeatureIds() ); mMasterModel->setRequest( r ); mMasterModel->loadLayer(); emit filterChanged(); }
void QgsDualView::copyCellContent() const { QAction *action = qobject_cast<QAction *>( sender() ); if ( action && action->data().isValid() && action->data().canConvert<QModelIndex>() ) { QModelIndex index = action->data().toModelIndex(); QVariant var = masterModel()->data( index, Qt::DisplayRole ); QApplication::clipboard()->setText( var.toString() ); } }
bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const { if ( mSelectedOnTop ) { // TODO: does the model index (left/right) need to be converted to first? bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) ); bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) ); if ( leftSelected && !rightSelected ) { return true; } else if ( rightSelected && !leftSelected ) { return false; } } return QSortFilterProxyModel::lessThan( left, right ); }
bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const { if ( mSelectedOnTop ) { bool leftSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( left.row() ) ); bool rightSelected = layer()->selectedFeaturesIds().contains( masterModel()->rowToId( right.row() ) ); if ( leftSelected && !rightSelected ) { return sortOrder() == Qt::AscendingOrder; } else if ( rightSelected && !leftSelected ) { return sortOrder() == Qt::DescendingOrder; } } return qgsVariantLessThan( left.data( QgsAttributeTableModel::SortRole ), right.data( QgsAttributeTableModel::SortRole ) ); }
QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const { Q_UNUSED( option ); QgsVectorLayer *vl = layer( index.model() ); if ( !vl ) return nullptr; int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt(); QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup ); QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( vl, fieldIdx, nullptr, parent, context ); QWidget* w = eww->widget(); w->setAutoFillBackground( true ); w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget eww->setEnabled( !vl->editFormConfig().readOnly( fieldIdx ) ); return w; }
QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const { Q_UNUSED( option ); QgsVectorLayer *vl = layer( index.model() ); if ( !vl ) return nullptr; int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt(); QString widgetType = vl->editFormConfig()->widgetType( fieldIdx ); QgsEditorWidgetConfig cfg = vl->editFormConfig()->widgetConfig( fieldIdx ); QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup ); QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, vl, fieldIdx, cfg, nullptr, parent, context ); QWidget* w = eww->widget(); w->setAutoFillBackground( true ); eww->setEnabled( !vl->editFormConfig()->readOnly( fieldIdx ) ); return w; }
void QgsAttributeTableFilterModel::sort( QString expression, Qt::SortOrder order ) { QSortFilterProxyModel::sort( -1 ); masterModel()->prefetchSortData( expression ); QSortFilterProxyModel::sort( 0, order ) ; }
void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order ) { masterModel()->prefetchColumnData( column ); QSortFilterProxyModel::sort( column, order ); }
QModelIndex QgsAttributeTableFilterModel::fidToIndex( QgsFeatureId fid ) { return mapFromMaster( masterModel()->idToIndex( fid ) ); }
QgsFeatureId QgsAttributeTableFilterModel::rowToId( const QModelIndex& row ) { return masterModel()->rowToId( mapToSource( row ).row() ); }
void QgsAttributeTableFilterModel::generateListOfVisibleFeatures() { if ( !layer() ) return; bool filter = false; QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() ); QgsRenderContext renderContext; renderContext.expressionContext() << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( layer() ); QgsFeatureRendererV2* renderer = layer()->rendererV2(); mFilteredFeatures.clear(); if ( !renderer ) { QgsDebugMsg( "Cannot get renderer" ); return; } const QgsMapSettings& ms = mCanvas->mapSettings(); if ( layer()->hasScaleBasedVisibility() && ( layer()->minimumScale() > ms.scale() || layer()->maximumScale() <= ms.scale() ) ) { QgsDebugMsg( "Out of scale limits" ); } else { if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent ) { // setup scale // mapRenderer()->renderContext()->scale is not automaticaly updated when // render extent changes (because it's scale is used to identify if changed // since last render) -> use local context renderContext.setExtent( ms.visibleExtent() ); renderContext.setMapToPixel( ms.mapToPixel() ); renderContext.setRendererScale( ms.scale() ); } filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter; } renderer->startRender( renderContext, layer()->fields() ); QgsFeatureRequest r( masterModel()->request() ); if ( !r.filterRect().isNull() ) { r.setFilterRect( r.filterRect().intersect( &rect ) ); } else { r.setFilterRect( rect ); } QgsFeatureIterator features = masterModel()->layerCache()->getFeatures( r ); QgsFeature f; while ( features.nextFeature( f ) ) { renderContext.expressionContext().setFeature( f ); if ( !filter || renderer->willRenderFeature( f, renderContext ) ) { mFilteredFeatures << f.id(); } #if 0 if ( t.elapsed() > 5000 ) { bool cancel = false; emit progress( i, cancel ); if ( cancel ) break; t.restart(); } #endif } features.close(); if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent ) { renderer->stopRender( renderContext ); } }
QString QgsAttributeTableFilterModel::sortExpression() const { return masterModel()->sortCacheExpression(); }
void QgsDualView::setFilterMode( QgsAttributeTableFilterModel::FilterMode filterMode ) { // cleanup any existing connections switch ( mFilterModel->filterMode() ) { case QgsAttributeTableFilterModel::ShowVisible: disconnect( mFilterModel->mapCanvas(), &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged ); break; case QgsAttributeTableFilterModel::ShowAll: case QgsAttributeTableFilterModel::ShowEdited: case QgsAttributeTableFilterModel::ShowFilteredList: break; case QgsAttributeTableFilterModel::ShowSelected: disconnect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures ); break; } QgsFeatureRequest r = mMasterModel->request(); bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible; bool requiresTableReload = ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) // previous request was subset || ( needsGeometry && r.flags() & QgsFeatureRequest::NoGeometry ) // no geometry for last request || ( mMasterModel->rowCount() == 0 ); // no features if ( !needsGeometry ) r.setFlags( r.flags() | QgsFeatureRequest::NoGeometry ); else r.setFlags( r.flags() & ~( QgsFeatureRequest::NoGeometry ) ); r.setFilterFids( QgsFeatureIds() ); r.setFilterRect( QgsRectangle() ); r.disableFilter(); // setup new connections and filter request parameters switch ( filterMode ) { case QgsAttributeTableFilterModel::ShowVisible: connect( mFilterModel->mapCanvas(), &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged ); if ( mFilterModel->mapCanvas() ) { QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() ); r.setFilterRect( rect ); } break; case QgsAttributeTableFilterModel::ShowAll: case QgsAttributeTableFilterModel::ShowEdited: case QgsAttributeTableFilterModel::ShowFilteredList: break; case QgsAttributeTableFilterModel::ShowSelected: connect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures ); r.setFilterFids( masterModel()->layer()->selectedFeatureIds() ); break; } if ( requiresTableReload ) { mMasterModel->setRequest( r ); whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry ); mMasterModel->loadLayer(); } //update filter model mFilterModel->setFilterMode( filterMode ); emit filterChanged(); }