34 #include <QHBoxLayout> 36 #include <QMessageBox> 41 QVBoxLayout *topLayout =
new QVBoxLayout(
this );
42 topLayout->setContentsMargins( 0, 9, 0, 0 );
43 setLayout( topLayout );
46 QHBoxLayout *buttonLayout =
new QHBoxLayout();
47 buttonLayout->setContentsMargins( 0, 0, 0, 0 );
49 mToggleEditingButton =
new QToolButton(
this );
50 mToggleEditingButton->setObjectName( QStringLiteral(
"mToggleEditingButton" ) );
52 mToggleEditingButton->setText( tr(
"Toggle editing" ) );
53 mToggleEditingButton->setEnabled(
false );
54 mToggleEditingButton->setCheckable(
true );
55 mToggleEditingButton->setToolTip( tr(
"Toggle editing mode for child layer" ) );
56 buttonLayout->addWidget( mToggleEditingButton );
58 mSaveEditsButton =
new QToolButton(
this );
60 mSaveEditsButton->setText( tr(
"Save child layer edits" ) );
61 mSaveEditsButton->setToolTip( tr(
"Save child layer edits" ) );
62 mSaveEditsButton->setEnabled(
true );
63 buttonLayout->addWidget( mSaveEditsButton );
65 mAddFeatureButton =
new QToolButton(
this );
67 mAddFeatureButton->setText( tr(
"Add child feature" ) );
68 mAddFeatureButton->setToolTip( tr(
"Add child feature" ) );
69 mAddFeatureButton->setObjectName( QStringLiteral(
"mAddFeatureButton" ) );
70 buttonLayout->addWidget( mAddFeatureButton );
72 mDuplicateFeatureButton =
new QToolButton(
this );
74 mDuplicateFeatureButton->setText( tr(
"Duplicate child feature" ) );
75 mDuplicateFeatureButton->setToolTip( tr(
"Duplicate child feature" ) );
76 mDuplicateFeatureButton->setObjectName( QStringLiteral(
"mDuplicateFeatureButton" ) );
77 buttonLayout->addWidget( mDuplicateFeatureButton );
79 mDeleteFeatureButton =
new QToolButton(
this );
81 mDeleteFeatureButton->setText( tr(
"Delete child feature" ) );
82 mDeleteFeatureButton->setToolTip( tr(
"Delete child feature" ) );
83 mDeleteFeatureButton->setObjectName( QStringLiteral(
"mDeleteFeatureButton" ) );
84 buttonLayout->addWidget( mDeleteFeatureButton );
86 mLinkFeatureButton =
new QToolButton(
this );
88 mLinkFeatureButton->setText( tr(
"Link existing features" ) );
89 mLinkFeatureButton->setToolTip( tr(
"Link existing child features" ) );
90 mLinkFeatureButton->setObjectName( QStringLiteral(
"mLinkFeatureButton" ) );
91 buttonLayout->addWidget( mLinkFeatureButton );
93 mUnlinkFeatureButton =
new QToolButton(
this );
95 mUnlinkFeatureButton->setText( tr(
"Unlink feature" ) );
96 mUnlinkFeatureButton->setToolTip( tr(
"Unlink child feature" ) );
97 mUnlinkFeatureButton->setObjectName( QStringLiteral(
"mUnlinkFeatureButton" ) );
98 buttonLayout->addWidget( mUnlinkFeatureButton );
100 mZoomToFeatureButton =
new QToolButton(
this );
102 mZoomToFeatureButton->setText( tr(
"Zoom To Feature" ) );
103 mZoomToFeatureButton->setToolTip( tr(
"Zoom to child feature" ) );
104 mZoomToFeatureButton->setObjectName( QStringLiteral(
"mZoomToFeatureButton" ) );
105 buttonLayout->addWidget( mZoomToFeatureButton );
107 buttonLayout->addItem(
new QSpacerItem( 0, 0, QSizePolicy::Expanding ) );
109 mFormViewButton =
new QToolButton(
this );
110 mFormViewButton->setText( tr(
"Form view" ) );
111 mFormViewButton->setToolTip( tr(
"Switch to form view" ) );
113 mFormViewButton->setCheckable(
true );
115 buttonLayout->addWidget( mFormViewButton );
117 mTableViewButton =
new QToolButton(
this );
118 mTableViewButton->setText( tr(
"Table view" ) );
119 mTableViewButton->setToolTip( tr(
"Switch to table view" ) );
121 mTableViewButton->setCheckable(
true );
123 buttonLayout->addWidget( mTableViewButton );
125 mViewModeButtonGroup =
new QButtonGroup(
this );
130 topLayout->addLayout( buttonLayout );
132 mRelationLayout =
new QGridLayout();
133 mRelationLayout->setContentsMargins( 0, 0, 0, 0 );
134 topLayout->addLayout( mRelationLayout );
137 mDualView->
setView( mViewMode );
141 mRelationLayout->addWidget( mDualView );
144 connect( mViewModeButtonGroup,
static_cast<void ( QButtonGroup::* )(
int )
>( &QButtonGroup::buttonClicked ),
146 connect( mToggleEditingButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::toggleEditing );
147 connect( mSaveEditsButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::saveEdits );
148 connect( mAddFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::addFeature );
149 connect( mDuplicateFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::duplicateFeature );
150 connect( mDeleteFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::deleteSelectedFeatures );
151 connect( mLinkFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::linkFeature );
152 connect( mUnlinkFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::unlinkSelectedFeatures );
153 connect( mZoomToFeatureButton, &QAbstractButton::clicked,
this, &QgsRelationEditorWidget::zoomToSelectedFeatures );
170 mRelation = relation;
177 setTitle( relation.
name() );
182 if ( canChangeAttributes && !lyr->readOnly() )
184 mToggleEditingButton->setEnabled(
true );
189 mToggleEditingButton->setEnabled(
false );
192 setObjectName( QStringLiteral(
"referenced/" ) + mRelation.name() );
201 mDualView->
init( mRelation.referencingLayer(),
nullptr, myRequest, mEditorContext );
219 mRelation = relation;
220 mNmRelation = nmrelation;
222 if ( !mRelation.isValid() )
225 mToggleEditingButton->setVisible(
true );
228 for (
auto it = transactionGroups.constBegin(); it != transactionGroups.constEnd(); ++it )
230 if ( it.value()->layers().contains( mRelation.referencingLayer() ) )
232 mToggleEditingButton->setVisible(
false );
233 mSaveEditsButton->setVisible(
false );
246 setTitle( relation.
name() );
251 if ( canChangeAttributes && !lyr->readOnly() )
253 mToggleEditingButton->setEnabled(
true );
258 mToggleEditingButton->setEnabled(
false );
264 mZoomToFeatureButton->setVisible( mRelation.referencingLayer()->isSpatial() );
266 setObjectName( QStringLiteral(
"referenced/" ) + mRelation.name() );
273 mEditorContext = context;
278 return mFeatureSelectionMgr;
294 void QgsRelationEditorWidget::updateButtons()
296 bool editable =
false;
297 bool linkable =
false;
311 mAddFeatureButton->setEnabled( editable );
312 mDuplicateFeatureButton->setEnabled( editable && selectionNotEmpty );
313 mLinkFeatureButton->setEnabled( linkable );
314 mDeleteFeatureButton->setEnabled( editable && selectionNotEmpty );
315 mUnlinkFeatureButton->setEnabled( linkable && selectionNotEmpty );
317 mZoomToFeatureButton->setVisible(
333 mZoomToFeatureButton->setEnabled( selectionNotEmpty );
335 mToggleEditingButton->setChecked( editable );
336 mSaveEditsButton->setEnabled( editable );
339 void QgsRelationEditorWidget::addFeature()
361 int index = fields.
indexOf( fieldPair.first );
362 linkAttributes.insert( index, mFeature.
attribute( fieldPair.second ) );
367 int index = fields.
indexOf( fieldPair.first );
368 linkAttributes.insert( index, f.
attribute( fieldPair.second ) );
390 void QgsRelationEditorWidget::linkFeature()
401 if ( selectionDlg.exec() )
423 int index = fields.
indexOf( fieldPair.first );
424 linkAttributes.insert( index, mFeature.
attribute( fieldPair.second ) );
431 int index = fields.
indexOf( fieldPair.first );
432 linkAttributes.insert( index, relatedFeature.
attribute( fieldPair.second ) );
436 newFeatures << linkFeature;
441 Q_FOREACH (
const QgsFeature &f, newFeatures )
450 QMap<int, QVariant> keys;
455 keys.insert( idx, val );
460 QMapIterator<int, QVariant> it( keys );
461 while ( it.hasNext() )
471 void QgsRelationEditorWidget::duplicateFeature()
484 void QgsRelationEditorWidget::deleteFeature(
const QgsFeatureId featureid )
489 void QgsRelationEditorWidget::deleteSelectedFeatures()
494 void QgsRelationEditorWidget::deleteFeatures(
const QgsFeatureIds &featureids )
496 bool deleteFeatures =
true;
517 QStringList deletedFeaturesPks;
528 QString linkingFeaturesRequestExpression;
529 if ( !deletedFeaturesPks.empty() )
536 int relatedLinkingFeaturesCount = 0;
537 while ( relatedLinkingFeatures.
nextFeature( feature ) )
539 relatedLinkingFeaturesCount++;
542 if ( deletedFeaturesPks.size() == 1 && relatedLinkingFeaturesCount > 1 )
544 QMessageBox messageBox( QMessageBox::Question, tr(
"Really delete entry?" ), tr(
"The entry on %1 is still linked to %2 features on %3. Do you want to delete it?" ).arg( mNmRelation.
referencedLayer()->
name(), QString::number( relatedLinkingFeaturesCount ), mRelation.
referencedLayer()->
name() ), QMessageBox::NoButton,
this );
545 messageBox.addButton( QMessageBox::Cancel );
546 QAbstractButton *deleteButton = messageBox.addButton( tr(
"Delete" ), QMessageBox::AcceptRole );
549 if ( messageBox.clickedButton() != deleteButton )
550 deleteFeatures =
false;
552 else if ( deletedFeaturesPks.size() > 1 && relatedLinkingFeaturesCount > deletedFeaturesPks.size() )
554 QMessageBox messageBox( QMessageBox::Question, tr(
"Really delete entries?" ), tr(
"The %1 entries on %2 are still linked to %3 features on %4. Do you want to delete them?" ).arg( QString::number( deletedFeaturesPks.size() ), mNmRelation.
referencedLayer()->
name(), QString::number( relatedLinkingFeaturesCount ), mRelation.
referencedLayer()->
name() ), QMessageBox::NoButton,
this );
555 messageBox.addButton( QMessageBox::Cancel );
556 QAbstractButton *deleteButton = messageBox.addButton( tr(
"Delete" ), QMessageBox::AcceptRole );
559 if ( messageBox.clickedButton() != deleteButton )
560 deleteFeatures =
false;
569 if ( deleteFeatures )
576 void QgsRelationEditorWidget::unlinkFeature(
const QgsFeatureId featureid )
581 void QgsRelationEditorWidget::unlinkSelectedFeatures()
586 void QgsRelationEditorWidget::zoomToSelectedFeatures()
598 void QgsRelationEditorWidget::unlinkFeatures(
const QgsFeatureIds &featureids )
604 .setFilterFids( featureids )
616 QString filter = QStringLiteral(
"(%1) AND (%2)" ).arg(
618 filters.join( QStringLiteral(
" OR " ) ) );
622 .setFilterExpression( filter ) );
638 QMap<int, QgsField> keyFields;
648 keyFields.insert( idx, fld );
653 QMapIterator<int, QgsField> it( keyFields );
654 while ( it.hasNext() )
663 void QgsRelationEditorWidget::toggleEditing(
bool state )
679 void QgsRelationEditorWidget::saveEdits()
686 void QgsRelationEditorWidget::onCollapsedStateChanged(
bool collapsed )
695 void QgsRelationEditorWidget::updateUi()
716 filters << filter.prepend(
'(' ).append(
')' );
734 return mLinkFeatureButton->isVisible();
739 mLinkFeatureButton->setVisible( showLinkButton );
744 return mUnlinkFeatureButton->isVisible();
749 mUnlinkFeatureButton->setVisible( showUnlinkButton );
761 if ( mShowLabel && mRelation.
isValid() )
762 setTitle( mRelation.
name() );
764 setTitle( QString() );
771 QAction *qAction =
nullptr;
774 connect( qAction, &QAction::triggered,
this, [
this, fid]() { deleteFeature( fid ); } );
777 connect( qAction, &QAction::triggered,
this, [
this, fid]() { unlinkFeature( fid ); } );
Wrapper for iterator of features from vector data provider or vector layer.
QSet< QgsFeatureId > QgsFeatureIds
void init(QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsAttributeEditorContext &context=QgsAttributeEditorContext(), bool loadFeatures=true)
Has to be called to initialize the dual view.
bool collapsed
The collapsed state of this group box.
QString referencedField() const
Gets the name of the referenced (parent) field.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
int selectedFeatureCount() override
Returns the number of features that are selected in this layer.
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features...
This class contains context information for attribute editor widgets.
QList< QgsFeature > QgsFeatureList
QgsVectorLayer referencingLayer
ViewMode
The view modes, in which this widget can present information.
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void selectByIds(const QgsFeatureIds &ids, SelectBehavior behavior=SetSelection)
Select matching features using a list of feature IDs.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
This signal is emitted when selection was changed.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QgsAttributeList referencedFields() const
Returns a list of attributes used to form the referenced fields (most likely primary key) on the refe...
QgsFeatureRequest getReferencedFeatureRequest(const QgsAttributes &attributes) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Map canvas is a class for displaying all GIS data types on a canvas.
void setView(ViewMode view)
Change the current view mode.
const QgsFeatureIds & selectedFeatures()
Gets the selected features.
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Defines a relation between matching fields of the two involved tables of a relation.
Shows the features and attributes in a table layout.
#define QgsDebugMsgLevel(str, level)
QString referencingField() const
Gets the name of the referencing (child) field.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
QMap< int, QVariant > QgsAttributeMap
void editingStopped()
Is emitted, when edited changes successfully have been written to the data provider.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a list of features to the sink.
QgsVectorLayer referencedLayer
Encapsulate a field in an attribute table or data source.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsFeatureRequest getRelatedFeaturesRequest(const QgsFeature &feature) const
Creates a request to return all the features on the referencing (child) layer which have a foreign ke...
void editingStarted()
Is emitted, when editing on this layer has started.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
This selection manager synchronizes a local set of selected features with an attribute table...
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered) ...
void showContextMenuExternally(QgsActionMenu *menu, QgsFeatureId fid)
Emitted when selecting context menu on the feature list to create the context menu individually...
void zoomToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids)
Set canvas extent to the bounding box of a set of features.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
#define FID_TO_STRING(fid)
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
QMap< QPair< QString, QString >, QgsTransactionGroup * > transactionGroups()
Map of transaction groups.
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext)
Duplicates a feature and it's children (one level deep).
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsMapCanvas * mapCanvas() const
Returns the associated map canvas (e.g.
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
const QgsVectorLayerTools * vectorLayerTools() const
Returns the associated vector layer tools.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink.
QList< QgsRelation::FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names o...
QString expression() const
Returns the original, unmodified expression string.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider.
QList< int > QgsAttributeList
bool nextFeature(QgsFeature &f)
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required...
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Is an interface class to abstract feature selection handling.
Represents a vector layer which manages a vector based data sets.
Allows modification of attribute values.
const QgsFeatureIds & selectedFeatureIds() const override
Returns reference to identifiers of selected features.
This widget is used to show the attributes of a set of features of a QgsVectorLayer.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsExpression * filterExpression() const
Returns the filter expression if set.