QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *layer ) { QMutexLocker locker( &layer->mFeatureSourceConstructorMutex ); mProviderFeatureSource = layer->dataProvider()->featureSource(); mFields = layer->fields(); mId = layer->id(); // update layer's join caches if necessary if ( layer->mJoinBuffer->containsJoins() ) layer->mJoinBuffer->createJoinCaches(); mJoinBuffer = layer->mJoinBuffer->clone(); mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer ); mCrs = layer->crs(); mHasEditBuffer = layer->editBuffer(); if ( mHasEditBuffer ) { #if 0 // TODO[MD]: after merge if ( request.filterType() == QgsFeatureRequest::FilterFid ) { // only copy relevant parts if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) ) mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] ); if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) ) mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] ); if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) ) mDeletedFeatureIds.insert( request.filterFid() ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() ); } else { #endif mAddedFeatures = QgsFeatureMap( layer->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( layer->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( layer->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( layer->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( layer->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( layer->editBuffer()->deletedAttributeIds() ); #if 0 } #endif } std::unique_ptr< QgsExpressionContextScope > layerScope( QgsExpressionContextUtils::layerScope( layer ) ); mLayerScope = *layerScope; }
QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( QgsVectorLayer *layer ) : mCrsId( 0 ) { mProviderFeatureSource = layer->dataProvider()->featureSource(); mFields = layer->fields(); mJoinBuffer = layer->mJoinBuffer->clone(); mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer ); mCrsId = layer->crs().srsid(); mCanBeSimplified = layer->hasGeometryType() && layer->geometryType() != QGis::Point; mHasEditBuffer = layer->editBuffer(); if ( mHasEditBuffer ) { #if 0 // TODO[MD]: after merge if ( request.filterType() == QgsFeatureRequest::FilterFid ) { // only copy relevant parts if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) ) mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] ); if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) ) mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] ); if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) ) mDeletedFeatureIds.insert( request.filterFid() ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() ); } else { #endif mAddedFeatures = QgsFeatureMap( layer->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( layer->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( layer->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( layer->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( layer->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( layer->editBuffer()->deletedAttributeIds() ); #if 0 } #endif } }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context ) { mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer, !request.filterRect().isNull() ); initModels( mapCanvas, request ); mConditionalFormatWidget->setLayer( layer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); if ( !mAttributeEditorScrollArea->layout() ) mAttributeEditorScrollArea->setLayout( new QGridLayout() ); mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); mAttributeForm->hideButtonBox(); connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, QgsAttributeEditorContext context ) { mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); initLayerCache( layer ); initModels( mapCanvas, request ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); mAttributeEditorScrollArea->setLayout( new QGridLayout() ); mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); mAttributeForm->hideButtonBox(); connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
void QgsFeaturePool::deleteFeature( QgsFeature& feature ) { mIndexMutex.lock(); mIndex.deleteFeature( feature ); mIndexMutex.unlock(); mLayerMutex.lock(); mFeatureCache.remove( feature.id() ); mLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << feature.id() ); mLayerMutex.unlock(); }
void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context, bool loadFeatures ) { if ( !layer ) return; mLayer = layer; mEditorContext = context; connect( mTableView, &QgsAttributeTableView::willShowContextMenu, this, &QgsDualView::viewWillShowContextMenu ); mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu ); connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &QgsDualView::showViewHeaderMenu ); connect( mTableView, &QgsAttributeTableView::columnResized, this, &QgsDualView::tableColumnResized ); connect( mFeatureList, &QgsFeatureListView::willShowContextMenu, this, &QgsDualView::widgetWillShowContextMenu ); initLayerCache( !( request.flags() & QgsFeatureRequest::NoGeometry ) || !request.filterRect().isNull() ); initModels( mapCanvas, request, loadFeatures ); mConditionalFormatWidget->setLayer( mLayer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); delete mAttributeForm; mAttributeForm = new QgsAttributeForm( mLayer, mTempAttributeFormFeature, mEditorContext ); mTempAttributeFormFeature = QgsFeature(); if ( !context.parentContext() ) { mAttributeEditorScrollArea = new QgsScrollArea(); mAttributeEditorScrollArea->setWidgetResizable( true ); mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); } else { mAttributeEditor->layout()->addWidget( mAttributeForm ); } connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged ); connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged ); connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature ); connect( mAttributeForm, &QgsAttributeForm::filterExpressionSet, this, &QgsDualView::filterExpressionSet ); connect( mFilterModel, &QgsAttributeTableFilterModel::sortColumnChanged, this, &QgsDualView::onSortColumnChanged ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request ) : QgsAbstractFeatureIterator( request ), L( layer ) { QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer; if ( L->editBuffer() ) { mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( L->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( L->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( L->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() ); } // prepare joins: may add more attributes to fetch (in order to allow join) if ( joinBuffer->containsJoins() ) prepareJoins(); // by default provider's request is the same mProviderRequest = mRequest; if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // prepare list of attributes to match provider fields QgsAttributeList providerSubset; QgsAttributeList subset = mProviderRequest.subsetOfAttributes(); const QgsFields &pendingFields = L->pendingFields(); int nPendingFields = pendingFields.count(); for ( int i = 0; i < subset.count(); ++i ) { int attrIndex = subset[i]; if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue; if ( L->pendingFields().fieldOrigin( attrIndex ) == QgsFields::OriginProvider ) providerSubset << L->pendingFields().fieldOriginIndex( attrIndex ); } mProviderRequest.setSubsetOfAttributes( providerSubset ); } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { mFetchedFid = false; } else // no filter or filter by rect { mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); rewindEditBuffer(); } }
void QgsFeaturePool::deleteFeature( const QgsFeatureId &fid ) { QgsFeature origFeature; if ( get( fid, origFeature ) ) { mIndexMutex.lock(); mIndex.deleteFeature( origFeature ); mIndexMutex.unlock(); } mLayerMutex.lock(); mFeatureCache.remove( origFeature.id() ); mLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << fid ); mLayerMutex.unlock(); }
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context ) { if ( !layer ) return; mEditorContext = context; connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) ); mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu ); connect( mTableView->horizontalHeader(), SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( showViewHeaderMenu( QPoint ) ) ); connect( mTableView, SIGNAL( columnResized( int, int ) ), this, SLOT( tableColumnResized( int, int ) ) ); initLayerCache( layer, !request.filterRect().isNull() ); initModels( mapCanvas, request ); mConditionalFormatWidget->setLayer( layer ); mTableView->setModel( mFilterModel ); mFeatureList->setModel( mFeatureListModel ); delete mAttributeForm; mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext ); if ( !context.parentContext() ) { mAttributeEditorScrollArea = new QScrollArea(); mAttributeEditorScrollArea->setWidgetResizable( true ); mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea ); mAttributeEditorScrollArea->setWidget( mAttributeForm ); } else { mAttributeEditor->layout()->addWidget( mAttributeForm ); } connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) ); connect( mAttributeForm, SIGNAL( modeChanged( QgsAttributeForm::Mode ) ), this, SIGNAL( formModeChanged( QgsAttributeForm::Mode ) ) ); connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) ); connect( mAttributeForm, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ), this, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ) ); connect( mFilterModel, SIGNAL( sortColumnChanged( int, Qt::SortOrder ) ), this, SLOT( onSortColumnChanged() ) ); if ( mFeatureListPreviewButton->defaultAction() ) mFeatureList->setDisplayExpression( mDisplayExpression ); else columnBoxInit(); // This slows down load of the attribute table heaps and uses loads of memory. //mTableView->resizeColumnsToContents(); mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) ); }
QgsCachedFeatureIterator::QgsCachedFeatureIterator( QgsVectorLayerCache *vlCache, const QgsFeatureRequest &featureRequest ) : QgsAbstractFeatureIterator( featureRequest ) , mVectorLayerCache( vlCache ) { if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mVectorLayerCache->sourceCrs() ) { mTransform = QgsCoordinateTransform( mVectorLayerCache->sourceCrs(), mRequest.destinationCrs() ); } try { mFilterRect = filterRectToSourceCrs( mTransform ); } catch ( QgsCsException & ) { // can't reproject mFilterRect close(); return; } if ( !mFilterRect.isNull() ) { // update request to be the unprojected filter rect mRequest.setFilterRect( mFilterRect ); } switch ( featureRequest.filterType() ) { case QgsFeatureRequest::FilterFids: mFeatureIds = featureRequest.filterFids(); break; case QgsFeatureRequest::FilterFid: mFeatureIds = QgsFeatureIds() << featureRequest.filterFid(); break; default: mFeatureIds = mVectorLayerCache->mCache.keys().toSet(); break; } mFeatureIdIterator = mFeatureIds.constBegin(); if ( mFeatureIdIterator == mFeatureIds.constEnd() ) close(); }
QgsCachedFeatureIterator::QgsCachedFeatureIterator( QgsVectorLayerCache *vlCache, QgsFeatureRequest featureRequest ) : QgsAbstractFeatureIterator( featureRequest ) , mVectorLayerCache( vlCache ) { switch ( featureRequest.filterType() ) { case QgsFeatureRequest::FilterFids: mFeatureIds = featureRequest.filterFids(); break; case QgsFeatureRequest::FilterFid: mFeatureIds = QgsFeatureIds() << featureRequest.filterFid(); break; default: mFeatureIds = mVectorLayerCache->mCache.keys().toSet(); break; } mFeatureIdIterator = mFeatureIds.begin(); }
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(); }
void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value ) { // Defer all updates if a bulk edit/rollback command is running if ( mBulkEditCommandRunning ) { mAttributeValueChanges.insert( QPair<QgsFeatureId, int>( fid, idx ), value ); return; } QgsDebugMsgLevel( QStringLiteral( "(%4) fid: %1, idx: %2, value: %3" ).arg( fid ).arg( idx ).arg( value.toString() ).arg( mFeatureRequest.filterType() ), 2 ); for ( SortCache &cache : mSortCaches ) { if ( cache.sortCacheAttributes.contains( idx ) ) { if ( cache.sortFieldIndex == -1 ) { if ( loadFeatureAtId( fid ) ) { mExpressionContext.setFeature( mFeat ); cache.sortCache[fid] = cache.sortCacheExpression.evaluate( &mExpressionContext ); } } else { QgsFieldFormatter *fieldFormatter = mFieldFormatters.at( cache.sortFieldIndex ); const QVariant &widgetCache = mAttributeWidgetCaches.at( cache.sortFieldIndex ); const QVariantMap &widgetConfig = mWidgetConfigs.at( cache.sortFieldIndex ); QVariant sortValue = fieldFormatter->representValue( layer(), cache.sortFieldIndex, widgetConfig, widgetCache, value ); cache.sortCache.insert( fid, sortValue ); } } } // No filter request: skip all possibly heavy checks if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone ) { if ( loadFeatureAtId( fid ) ) setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole ); } else { if ( loadFeatureAtId( fid ) ) { if ( mFeatureRequest.acceptFeature( mFeat ) ) { if ( !mIdRowMap.contains( fid ) ) { // Feature changed in such a way, it will be shown now featureAdded( fid ); } else { // Update representation setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole ); } } else { if ( mIdRowMap.contains( fid ) ) { // Feature changed such, that it is no longer shown featuresDeleted( QgsFeatureIds() << fid ); } // else: we don't care } } } }