void QgsComposerAttributeTableV2::setRelationId( const QString relationId ) { if ( relationId == mRelationId ) { //no change return; } QgsVectorLayer* prevLayer = sourceLayer(); mRelationId = relationId; QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId ); QgsVectorLayer* newLayer = relation.referencingLayer(); if ( mSource == QgsComposerAttributeTableV2::RelationChildren && newLayer != prevLayer ) { if ( prevLayer ) { //disconnect from previous layer disconnect( prevLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } //rebuild column list to match all columns from layer resetColumns(); //listen for modifications to layer and refresh table when they occur connect( newLayer, SIGNAL( layerModified() ), this, SLOT( refreshAttributes() ) ); } refreshAttributes(); emit changed(); }
void QgsRelationReferenceWidgetWrapper::initWidget( QWidget *editor ) { QgsRelationReferenceWidget *w = dynamic_cast<QgsRelationReferenceWidget *>( editor ); if ( !w ) { w = new QgsRelationReferenceWidget( editor ); } mWidget = w; mWidget->setEditorContext( context(), mCanvas, mMessageBar ); bool showForm = config( QStringLiteral( "ShowForm" ), false ).toBool(); bool mapIdent = config( QStringLiteral( "MapIdentification" ), false ).toBool(); bool readOnlyWidget = config( QStringLiteral( "ReadOnly" ), false ).toBool(); bool orderByValue = config( QStringLiteral( "OrderByValue" ), false ).toBool(); bool showOpenFormButton = config( QStringLiteral( "ShowOpenFormButton" ), true ).toBool(); mWidget->setEmbedForm( showForm ); mWidget->setReadOnlySelector( readOnlyWidget ); mWidget->setAllowMapIdentification( mapIdent ); mWidget->setOrderByValue( orderByValue ); mWidget->setOpenFormButtonVisible( showOpenFormButton ); if ( config( QStringLiteral( "FilterFields" ), QVariant() ).isValid() ) { mWidget->setFilterFields( config( QStringLiteral( "FilterFields" ) ).toStringList() ); mWidget->setChainFilters( config( QStringLiteral( "ChainFilters" ) ).toBool() ); } mWidget->setAllowAddFeatures( config( QStringLiteral( "AllowAddFeatures" ), false ).toBool() ); const QVariant relationName = config( QStringLiteral( "Relation" ) ); QgsRelation relation; // invalid relation by default if ( relationName.isValid() ) relation = QgsProject::instance()->relationManager()->relation( relationName.toString() ); else if ( ! layer()->referencingRelations( fieldIdx() ).isEmpty() ) relation = layer()->referencingRelations( fieldIdx() )[0]; // If this widget is already embedded by the same relation, reduce functionality const QgsAttributeEditorContext *ctx = &context(); do { if ( ctx->relation().name() == relation.name() ) { mWidget->setEmbedForm( false ); mWidget->setReadOnlySelector( false ); mWidget->setAllowMapIdentification( false ); break; } ctx = ctx->parentContext(); } while ( ctx ); mWidget->setRelation( relation, config( QStringLiteral( "AllowNULL" ) ).toBool() ); connect( mWidget, &QgsRelationReferenceWidget::foreignKeyChanged, this, &QgsRelationReferenceWidgetWrapper::foreignKeyChanged ); }
void QgsRelReferenceConfigDlg::on_mComboRelation_indexChanged( int idx ) { QString relName = mComboRelation->itemData( idx ).toString(); QgsRelation rel = QgsProject::instance()->relationManager()->relation( relName ); QgsVectorLayer* referencedLayer = rel.referencedLayer(); if ( referencedLayer ) { mTxtDisplayExpression->setText( referencedLayer->displayExpression() ); } }
void QgsRelReferenceConfigDlg::previewExpressionBuilder() { QString relName = mComboRelation->itemData( mComboRelation->currentIndex() ).toString(); QgsRelation relation = QgsProject::instance()->relationManager()->relation( relName ); // Show expression builder QgsExpressionBuilderDialog dlg( relation.referencedLayer(), mTxtDisplayExpression->text() , this ); dlg.setWindowTitle( tr( "Preview Expression" ) ); if ( dlg.exec() == QDialog::Accepted ) { mTxtDisplayExpression->setText( dlg.expressionText() ); } }
void QgsRelationEditorWidget::setRelations( const QgsRelation& relation, const QgsRelation& nmrelation ) { if ( mRelation.isValid() ) { disconnect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); disconnect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); } if ( mNmRelation.isValid() ) { disconnect( mNmRelation.referencedLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); disconnect( mNmRelation.referencedLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); } mRelation = relation; mNmRelation = nmrelation; if ( !mRelation.isValid() ) return; connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); if ( mNmRelation.isValid() ) { connect( mNmRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); connect( mNmRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); } setTitle( relation.name() ); QgsVectorLayer* lyr = relation.referencingLayer(); bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; if ( canChangeAttributes && !lyr->isReadOnly() ) { mToggleEditingButton->setEnabled( true ); updateButtons(); } else { mToggleEditingButton->setEnabled( false ); } setObjectName( mRelation.name() ); loadState(); updateUi(); }
void QgsRelationReferenceWidgetWrapper::initWidget( QWidget* editor ) { QgsRelationReferenceWidget* w = dynamic_cast<QgsRelationReferenceWidget*>( editor ); if ( !w ) { w = new QgsRelationReferenceWidget( editor ); } mWidget = w; mWidget->setEditorContext( context(), mCanvas, mMessageBar ); bool showForm = config( "ShowForm", true ).toBool(); bool mapIdent = config( "MapIdentification", false ).toBool(); bool readOnlyWidget = config( "ReadOnly", false ).toBool(); bool orderByValue = config( "OrderByValue", false ).toBool(); mWidget->setEmbedForm( showForm ); mWidget->setReadOnlySelector( readOnlyWidget ); mWidget->setAllowMapIdentification( mapIdent ); mWidget->setOrderByValue( orderByValue ); if ( config( "FilterFields", QVariant() ).isValid() ) { mWidget->setFilterFields( config( "FilterFields" ).toStringList() ); mWidget->setChainFilters( config( "ChainFilters" ).toBool() ); } mWidget->setAllowAddFeatures( config( "AllowAddFeatures", false ).toBool() ); QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() ); // If this widget is already embedded by the same relation, reduce functionality const QgsAttributeEditorContext* ctx = &context(); do { if ( ctx->relation().name() == relation.name() ) { mWidget->setEmbedForm( false ); mWidget->setReadOnlySelector( false ); mWidget->setAllowMapIdentification( false ); } ctx = ctx->parentContext(); } while ( ctx ); mWidget->setRelation( relation, config( "AllowNULL" ).toBool() ); connect( mWidget, SIGNAL( foreignKeyChanged( QVariant ) ), this, SLOT( foreignKeyChanged( QVariant ) ) ); }
QgsVectorLayer *QgsComposerAttributeTableV2::sourceLayer() { switch ( mSource ) { case QgsComposerAttributeTableV2::AtlasFeature: return mComposition->atlasComposition().coverageLayer(); case QgsComposerAttributeTableV2::LayerAttributes: return mVectorLayer; case QgsComposerAttributeTableV2::RelationChildren: { QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId ); return relation.referencingLayer(); } } return 0; }
QgsEditorWidgetConfig QgsRelReferenceConfigDlg::config() { QgsEditorWidgetConfig myConfig; myConfig.insert( "AllowNULL", mCbxAllowNull->isChecked() ); myConfig.insert( "ShowForm", mCbxShowForm->isChecked() ); myConfig.insert( "Relation", mComboRelation->itemData( mComboRelation->currentIndex() ) ); QString relName = mComboRelation->itemData( mComboRelation->currentIndex() ).toString(); QgsRelation relation = QgsProject::instance()->relationManager()->relation( relName ); if ( relation.isValid() ) { relation.referencedLayer()->setDisplayExpression( mTxtDisplayExpression->text() ); } return myConfig; }
QString QgsRelationReferenceFieldFormatter::representValue( QgsVectorLayer* layer, int fieldIndex, const QVariantMap& config, const QVariant& cache, const QVariant& value ) const { Q_UNUSED( cache ); // Some sanity checks if ( !config.contains( QStringLiteral( "Relation" ) ) ) { QgsMessageLog::logMessage( "Missing Relation in configuration" ); return value.toString(); } QgsRelation relation = QgsProject::instance()->relationManager()->relation( config[QStringLiteral( "Relation" )].toString() ); if ( !relation.isValid() ) { QgsMessageLog::logMessage( "Invalid relation" ); return value.toString(); } QgsVectorLayer* referencingLayer = relation.referencingLayer(); if ( layer != referencingLayer ) { QgsMessageLog::logMessage( "representValue() with inconsistent layer parameter w.r.t relation referencingLayer" ); return value.toString(); } int referencingFieldIdx = referencingLayer->fields().lookupField( relation.fieldPairs().at( 0 ).first ); if ( referencingFieldIdx != fieldIndex ) { QgsMessageLog::logMessage( "representValue() with inconsistent fieldIndex parameter w.r.t relation referencingFieldIdx" ); return value.toString(); } QgsVectorLayer* referencedLayer = relation.referencedLayer(); if ( !referencedLayer ) { QgsMessageLog::logMessage( "Cannot find referenced layer" ); return value.toString(); } // Attributes from the referencing layer QgsAttributes attrs = QgsAttributes( layer->fields().count() ); // Set the value on the foreign key field of the referencing record attrs[ referencingFieldIdx ] = value; QgsFeatureRequest request = relation.getReferencedFeatureRequest( attrs ); QgsFeature feature; referencedLayer->getFeatures( request ).nextFeature( feature ); if ( !feature.isValid() ) return value.toString(); QgsExpression expr( referencedLayer->displayExpression() ); QgsExpressionContext context; context << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope() << QgsExpressionContextUtils::layerScope( referencedLayer ); context.setFeature( feature ); QString title = expr.evaluate( &context ).toString(); if ( expr.hasEvalError() ) { int referencedFieldIdx = referencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second ); title = feature.attribute( referencedFieldIdx ).toString(); } return title; }
void QgsRelationEditorWidget::setRelationFeature( const QgsRelation& relation, const QgsFeature& feature ) { if ( mRelation.isValid() ) { disconnect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); disconnect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); } mRelation = relation; mFeature = feature; connect( mRelation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( updateButtons() ) ); connect( mRelation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( updateButtons() ) ); setTitle( relation.name() ); QgsVectorLayer* lyr = relation.referencingLayer(); bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; if ( canChangeAttributes && !lyr->isReadOnly() ) { mToggleEditingButton->setEnabled( true ); updateButtons(); } else { mToggleEditingButton->setEnabled( false ); } setObjectName( mRelation.name() ); loadState(); // If not yet initialized, it is not (yet) visible, so we don't load it to be faster (lazy loading) // If it is already initialized, it has been set visible before and the currently shown feature is changing // and the widget needs updating if ( mVisible ) { QgsFeatureRequest myRequest = mRelation.getRelatedFeaturesRequest( mFeature ); mDualView->init( mRelation.referencingLayer(), nullptr, myRequest, mEditorContext ); } }
void QgsRelationWidgetWrapper::initWidget( QWidget* editor ) { QgsRelationEditorWidget* w = dynamic_cast<QgsRelationEditorWidget*>( editor ); // if the editor cannot be cast to relation editor, insert a new one if ( !w ) { w = new QgsRelationEditorWidget( editor ); w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); if ( ! editor->layout() ) { editor->setLayout( new QGridLayout() ); } editor->layout()->addWidget( w ); } QgsAttributeEditorContext myContext( QgsAttributeEditorContext( context(), mRelation, QgsAttributeEditorContext::Multiple, QgsAttributeEditorContext::Embed ) ); w->setEditorContext( myContext ); QgsRelation nmrel = QgsProject::instance()->relationManager()->relation( config( "nm-rel" ).toString() ); // If this widget is already embedded by the same relation, reduce functionality const QgsAttributeEditorContext* ctx = &context(); do { if (( ctx->relation().name() == mRelation.name() && ctx->formMode() == QgsAttributeEditorContext::Embed ) || ctx->relation().name() == nmrel.name() ) { w->setVisible( false ); break; } ctx = ctx->parentContext(); } while ( ctx ); w->setRelations( mRelation, nmrel ); mWidget = w; }
void QgsRelationReferenceWidget::setRelation( const QgsRelation& relation, bool allowNullValue ) { mAllowNull = allowNullValue; mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector ); if ( relation.isValid() ) { mInvalidLabel->hide(); mRelation = relation; mReferencingLayer = relation.referencingLayer(); mRelationName = relation.name(); mReferencedLayer = relation.referencedLayer(); mFkeyFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second ); QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed ); if ( mEmbedForm ) { mAttributeEditorFrame->setTitle( mReferencedLayer->name() ); mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this ); mReferencedAttributeForm->hideButtonBox(); mAttributeEditorLayout->addWidget( mReferencedAttributeForm ); } } else { mInvalidLabel->show(); } if ( mShown && isVisible() ) { init(); } }
void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool allowNullValue ) { mAllowNull = allowNullValue; mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector ); if ( relation.isValid() ) { mInvalidLabel->hide(); mRelation = relation; mReferencingLayer = relation.referencingLayer(); mRelationName = relation.name(); mReferencedLayer = relation.referencedLayer(); mReferencedField = relation.fieldPairs().at( 0 ).second; if ( mComboBox ) mComboBox->setIdentifierField( mReferencedField ); mReferencedFieldIdx = mReferencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second ); mReferencingFieldIdx = mReferencingLayer->fields().lookupField( relation.fieldPairs().at( 0 ).first ); mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() ); if ( mEmbedForm ) { QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed ); mAttributeEditorFrame->setTitle( mReferencedLayer->name() ); mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this ); mAttributeEditorLayout->addWidget( mReferencedAttributeForm ); } connect( mReferencedLayer, &QgsVectorLayer::editingStarted, this, &QgsRelationReferenceWidget::updateAddEntryButton ); connect( mReferencedLayer, &QgsVectorLayer::editingStopped, this, &QgsRelationReferenceWidget::updateAddEntryButton ); updateAddEntryButton(); } else { mInvalidLabel->show(); } if ( mShown && isVisible() ) { init(); } }
void QgsRelationEditorWidget::setRelations( const QgsRelation &relation, const QgsRelation &nmrelation ) { if ( mRelation.isValid() ) { disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons ); disconnect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons ); } if ( mNmRelation.isValid() ) { disconnect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons ); disconnect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons ); } mRelation = relation; mNmRelation = nmrelation; if ( !mRelation.isValid() ) return; mToggleEditingButton->setVisible( true ); const auto transactionGroups = QgsProject::instance()->transactionGroups(); for ( auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it ) { if ( it.value()->layers().contains( mRelation.referencingLayer() ) ) { mToggleEditingButton->setVisible( false ); mSaveEditsButton->setVisible( false ); } } connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons ); connect( mRelation.referencingLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons ); if ( mNmRelation.isValid() ) { connect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStarted, this, &QgsRelationEditorWidget::updateButtons ); connect( mNmRelation.referencedLayer(), &QgsVectorLayer::editingStopped, this, &QgsRelationEditorWidget::updateButtons ); } setTitle( relation.name() ); QgsVectorLayer *lyr = relation.referencingLayer(); bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues; if ( canChangeAttributes && !lyr->readOnly() ) { mToggleEditingButton->setEnabled( true ); updateButtons(); } else { mToggleEditingButton->setEnabled( false ); } if ( mNmRelation.isValid() ) mZoomToFeatureButton->setVisible( mNmRelation.referencedLayer()->isSpatial() ); else mZoomToFeatureButton->setVisible( mRelation.referencingLayer()->isSpatial() ); setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() ); updateUi(); }
QgsRelation QgsRelation::createFromXml( const QDomNode &node ) { QDomElement elem = node.toElement(); if ( elem.tagName() != "relation" ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) ); } QgsRelation relation; QString referencingLayerId = elem.attribute( "referencingLayer" ); QString referencedLayerId = elem.attribute( "referencedLayer" ); QString id = elem.attribute( "id" ); QString name = elem.attribute( "name" ); const QMap<QString, QgsMapLayer*>& mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); QgsMapLayer* referencingLayer = mapLayers[referencingLayerId]; QgsMapLayer* referencedLayer = mapLayers[referencedLayerId]; if ( !referencingLayer ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencingLayerId ) ); } else if ( QgsMapLayer::VectorLayer != referencingLayer->type() ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencingLayerId ) ); } if ( !referencedLayer ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencedLayerId ) ); } else if ( QgsMapLayer::VectorLayer != referencedLayer->type() ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencedLayerId ) ); } relation.mReferencingLayerId = referencingLayerId; relation.mReferencingLayer = qobject_cast<QgsVectorLayer*>( referencingLayer ); relation.mReferencedLayerId = referencedLayerId; relation.mReferencedLayer = qobject_cast<QgsVectorLayer*>( referencedLayer ); relation.mRelationId = id; relation.mRelationName = name; QDomNodeList references = elem.elementsByTagName( "fieldRef" ); for ( int i = 0; i < references.size(); ++i ) { QDomElement refEl = references.at( i ).toElement(); QString referencingField = refEl.attribute( "referencingField" ); QString referencedField = refEl.attribute( "referencedField" ); relation.addFieldPair( referencingField, referencedField ); } relation.updateRelationStatus(); return relation; }
QgsRelation QgsRelation::createFromXml( const QDomNode &node, QgsReadWriteContext &context ) { QDomElement elem = node.toElement(); if ( elem.tagName() != QLatin1String( "relation" ) ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) ); } QgsRelation relation; QString referencingLayerId = elem.attribute( QStringLiteral( "referencingLayer" ) ); QString referencedLayerId = elem.attribute( QStringLiteral( "referencedLayer" ) ); QString id = elem.attribute( QStringLiteral( "id" ) ); QString name = context.projectTranslator()->translate( QStringLiteral( "project:relations" ), elem.attribute( QStringLiteral( "name" ) ) ); QString strength = elem.attribute( QStringLiteral( "strength" ) ); const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers(); QgsMapLayer *referencingLayer = mapLayers[referencingLayerId]; QgsMapLayer *referencedLayer = mapLayers[referencedLayerId]; if ( !referencingLayer ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencingLayerId ) ); } else if ( QgsMapLayer::VectorLayer != referencingLayer->type() ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencingLayerId ) ); } if ( !referencedLayer ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencedLayerId ) ); } else if ( QgsMapLayer::VectorLayer != referencedLayer->type() ) { QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencedLayerId ) ); } relation.d->mReferencingLayerId = referencingLayerId; relation.d->mReferencingLayer = qobject_cast<QgsVectorLayer *>( referencingLayer ); relation.d->mReferencedLayerId = referencedLayerId; relation.d->mReferencedLayer = qobject_cast<QgsVectorLayer *>( referencedLayer ); relation.d->mRelationId = id; relation.d->mRelationName = name; if ( strength == QLatin1String( "Composition" ) ) { relation.d->mRelationStrength = RelationStrength::Composition; } else { relation.d->mRelationStrength = RelationStrength::Association; } QDomNodeList references = elem.elementsByTagName( QStringLiteral( "fieldRef" ) ); for ( int i = 0; i < references.size(); ++i ) { QDomElement refEl = references.at( i ).toElement(); QString referencingField = refEl.attribute( QStringLiteral( "referencingField" ) ); QString referencedField = refEl.attribute( QStringLiteral( "referencedField" ) ); relation.addFieldPair( referencingField, referencedField ); } relation.updateRelationStatus(); return relation; }
bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &contents ) { contents.clear(); if (( mSource == QgsComposerAttributeTableV2::AtlasFeature || mSource == QgsComposerAttributeTableV2::RelationChildren ) && !mComposition->atlasComposition().enabled() ) { //source mode requires atlas, but atlas disabled return false; } QgsVectorLayer* layer = sourceLayer(); if ( !layer ) { //no source layer return false; } //prepare filter expression std::auto_ptr<QgsExpression> filterExpression; bool activeFilter = false; if ( mFilterFeatures && !mFeatureFilter.isEmpty() ) { filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) ); if ( !filterExpression->hasParserError() ) { activeFilter = true; } } QgsRectangle selectionRect; if ( mComposerMap && mShowOnlyVisibleFeatures ) { selectionRect = *mComposerMap->currentMapExtent(); if ( layer && mComposition->mapSettings().hasCrsTransformEnabled() ) { //transform back to layer CRS QgsCoordinateTransform coordTransform( layer->crs(), mComposition->mapSettings().destinationCrs() ); try { selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); return false; } } } QgsFeatureRequest req; if ( mSource == QgsComposerAttributeTableV2::RelationChildren ) { QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId ); QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( atlasFeature ) { req = relation.getRelatedFeaturesRequest( *atlasFeature ); } else { //no atlas feature, so empty table return true; } } if ( !selectionRect.isEmpty() ) req.setFilterRect( selectionRect ); req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoFlags ); if ( mSource == QgsComposerAttributeTableV2::AtlasFeature && mComposition->atlasComposition().enabled() ) { //source mode is current atlas feature QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( atlasFeature ) { req.setFilterFid( atlasFeature->id() ); } else { //no atlas feature, so empty table return true; } } QgsFeature f; int counter = 0; QgsFeatureIterator fit = layer->getFeatures( req ); while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures ) { //check feature against filter if ( activeFilter ) { QVariant result = filterExpression->evaluate( &f, layer->pendingFields() ); // skip this feature if the filter evaluation is false if ( !result.toBool() ) { continue; } } //check against atlas feature intersection if ( mFilterToAtlasIntersection ) { if ( !f.geometry() || ! mComposition->atlasComposition().enabled() ) { continue; } QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature(); if ( !atlasFeature || !atlasFeature->geometry() || !f.geometry()->intersects( atlasFeature->geometry() ) ) { //feature falls outside current atlas feature continue; } } QgsComposerTableRow currentRow; QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin(); for ( ; columnIt != mColumns.constEnd(); ++columnIt ) { int idx = layer->fieldNameIndex(( *columnIt )->attribute() ); if ( idx != -1 ) { currentRow << f.attributes()[idx]; } else { // Lets assume it's an expression QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() ); expression->setCurrentRowNumber( counter + 1 ); expression->prepare( layer->pendingFields() ); QVariant value = expression->evaluate( f ) ; currentRow << value; } } if ( !mShowUniqueRowsOnly || !contentsContainsRow( contents, currentRow ) ) { contents << currentRow; ++counter; } } //sort the list, starting with the last attribute QgsComposerAttributeTableCompareV2 c; QList< QPair<int, bool> > sortColumns = sortAttributes(); for ( int i = sortColumns.size() - 1; i >= 0; --i ) { c.setSortColumn( sortColumns.at( i ).first ); c.setAscending( sortColumns.at( i ).second ); qStableSort( contents.begin(), contents.end(), c ); } recalculateTableSize(); return true; }