QGIS API Documentation 3.41.0-Master (3440c17df1d)
Loading...
Searching...
No Matches
qgsjoindialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsjoindialog.cpp
3 --------------------
4 begin : July 10, 2010
5 copyright : (C) 2010 by Marco Hugentobler
6 email : marco dot hugentobler at sourcepole dot ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsjoindialog.h"
19#include "moc_qgsjoindialog.cpp"
20#include "qgsmaplayer.h"
21#include "qgsproject.h"
23#include "qgsvectorlayer.h"
25#include "qgsmaplayercombobox.h"
26#include "qgsfieldcombobox.h"
27#include "qgshelp.h"
28
29#include <QStandardItemModel>
30#include <QPushButton>
31
32QgsJoinDialog::QgsJoinDialog( QgsVectorLayer *layer, QList<QgsMapLayer *> alreadyJoinedLayers, QWidget *parent, Qt::WindowFlags f )
33 : QDialog( parent, f )
34 , mLayer( layer )
35{
36 setupUi( this );
37 connect( buttonBox, &QDialogButtonBox::helpRequested, this, [ = ]
38 {
39 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#joins-properties" ) );
40 } );
41
42 if ( !mLayer )
43 {
44 return;
45 }
46 // adds self layer to the joined layer (cannot join to itself)
47 alreadyJoinedLayers.append( layer );
48
49 mTargetFieldComboBox->setLayer( mLayer );
50
51 mDynamicFormCheckBox->setToolTip( tr( "This option allows values of the joined fields to be automatically reloaded when the \"Target Field\" is changed" ) );
52
53 mEditableJoinLayer->setToolTip( tr( "This option allows values of the joined layers to be editable if they're themselves editable" ) );
54 mUpsertOnEditCheckBox->setToolTip( tr( "Automatically adds a matching row to the joined table, but if one already exists then update that matching row instead" ) );
55 mDeleteCascadeCheckBox->setToolTip( tr( "Automatically delete the corresponding feature of the linked layer if one exists" ) );
56
57 mJoinLayerComboBox->setFilters( Qgis::LayerFilter::VectorLayer );
58 mJoinLayerComboBox->setExceptedLayerList( alreadyJoinedLayers );
59 connect( mJoinLayerComboBox, &QgsMapLayerComboBox::layerChanged, mJoinFieldComboBox, &QgsFieldComboBox::setLayer );
60 connect( mJoinLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsJoinDialog::joinedLayerChanged );
61
62 mCacheInMemoryCheckBox->setChecked( true );
63 mCacheEnabled = mCacheInMemoryCheckBox->isChecked();
64
65 QgsMapLayer *joinLayer = mJoinLayerComboBox->currentLayer();
66 if ( joinLayer && joinLayer->isValid() )
67 {
68 mJoinFieldComboBox->setLayer( joinLayer );
69 joinedLayerChanged( joinLayer );
70 }
71
72 connect( mJoinLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsJoinDialog::checkDefinitionValid );
73 connect( mJoinFieldComboBox, &QgsFieldComboBox::fieldChanged, this, &QgsJoinDialog::checkDefinitionValid );
74 connect( mTargetFieldComboBox, &QgsFieldComboBox::fieldChanged, this, &QgsJoinDialog::checkDefinitionValid );
75 connect( mEditableJoinLayer, &QGroupBox::toggled, this, &QgsJoinDialog::editableJoinLayerChanged );
76
77 checkDefinitionValid();
78}
79
81{
82 mJoinLayerComboBox->setLayer( joinInfo.joinLayer() );
83 mJoinFieldComboBox->setField( joinInfo.joinFieldName() );
84 mTargetFieldComboBox->setField( joinInfo.targetFieldName() );
85
86 mCacheEnabled = joinInfo.isUsingMemoryCache();
87 mCacheInMemoryCheckBox->setChecked( joinInfo.isUsingMemoryCache() );
88
89 mDynamicFormCheckBox->setChecked( joinInfo.isDynamicFormEnabled() );
90 mEditableJoinLayer->setChecked( joinInfo.isEditable() );
91 mUpsertOnEditCheckBox->setChecked( joinInfo.hasUpsertOnEdit() );
92 mDeleteCascadeCheckBox->setChecked( joinInfo.hasCascadedDelete() );
93
94 if ( joinInfo.prefix().isNull() )
95 {
96 mUseCustomPrefix->setChecked( false );
97 }
98 else
99 {
100 mUseCustomPrefix->setChecked( true );
101 mCustomPrefix->setText( joinInfo.prefix() );
102 }
103
104 QStringList *lst = joinInfo.joinFieldNamesSubset();
105 mUseJoinFieldsSubset->setChecked( lst && !lst->isEmpty() );
106 QAbstractItemModel *model = mJoinFieldsSubsetView->model();
107 if ( model )
108 {
109 for ( int i = 0; i < model->rowCount(); ++i )
110 {
111 const QModelIndex index = model->index( i, 0 );
112 if ( lst && lst->contains( model->data( index, Qt::DisplayRole ).toString() ) )
113 {
114 model->setData( index, Qt::Checked, Qt::CheckStateRole );
115 }
116 else
117 {
118 model->setData( index, Qt::Unchecked, Qt::CheckStateRole );
119 }
120 }
121 }
122
123 editableJoinLayerChanged();
124}
125
127{
129 info.setJoinLayer( qobject_cast<QgsVectorLayer *>( mJoinLayerComboBox->currentLayer() ) );
130 info.setJoinFieldName( mJoinFieldComboBox->currentField() );
131 info.setTargetFieldName( mTargetFieldComboBox->currentField() );
132 info.setUsingMemoryCache( mCacheInMemoryCheckBox->isChecked() );
133 info.setDynamicFormEnabled( mDynamicFormCheckBox->isChecked() );
134
135 info.setEditable( mEditableJoinLayer->isChecked() );
136 if ( info.isEditable() )
137 {
138 info.setUpsertOnEdit( mUpsertOnEditCheckBox->isChecked() );
139 info.setCascadedDelete( mDeleteCascadeCheckBox->isChecked() );
140 }
141
142 if ( mUseCustomPrefix->isChecked() )
143 info.setPrefix( mCustomPrefix->text() );
144 else
145 info.setPrefix( QString() );
146
147 if ( mUseJoinFieldsSubset->isChecked() )
148 {
149 QStringList lst;
150 QAbstractItemModel *model = mJoinFieldsSubsetView->model();
151 if ( model )
152 {
153 for ( int i = 0; i < model->rowCount(); ++i )
154 {
155 const QModelIndex index = model->index( i, 0 );
156 if ( model->data( index, Qt::CheckStateRole ).toInt() == Qt::Checked )
157 lst << model->data( index ).toString();
158 }
159 }
160 info.setJoinFieldNamesSubset( new QStringList( lst ) );
161 }
162
163 return info;
164}
165
167{
168 return mCreateIndexCheckBox->isChecked();
169}
170
171void QgsJoinDialog::joinedLayerChanged( QgsMapLayer *layer )
172{
173 mJoinFieldComboBox->clear();
174
175 QgsVectorLayer *vLayer = qobject_cast<QgsVectorLayer *>( layer );
176 if ( !vLayer )
177 {
178 return;
179 }
180
181 mUseJoinFieldsSubset->setChecked( false );
182 QStandardItemModel *subsetModel = new QStandardItemModel( this );
183 const QgsFields layerFields = vLayer->fields();
184 for ( const QgsField &field : layerFields )
185 {
186 QStandardItem *subsetItem = new QStandardItem( field.name() );
187 subsetItem->setCheckable( true );
188 //subsetItem->setFlags( subsetItem->flags() | Qt::ItemIsUserCheckable );
189 subsetModel->appendRow( subsetItem );
190 }
191 mJoinFieldsSubsetView->setModel( subsetModel );
192
193 QgsVectorDataProvider *dp = vLayer->dataProvider();
194 const bool canCreateAttrIndex = dp && ( dp->capabilities() & Qgis::VectorProviderCapability::CreateAttributeIndex );
195 if ( canCreateAttrIndex )
196 {
197 mCreateIndexCheckBox->setEnabled( true );
198 }
199 else
200 {
201 mCreateIndexCheckBox->setEnabled( false );
202 mCreateIndexCheckBox->setChecked( false );
203 }
204
205 if ( !mUseCustomPrefix->isChecked() )
206 {
207 mCustomPrefix->setText( layer->name() + '_' );
208 }
209}
210
211void QgsJoinDialog::checkDefinitionValid()
212{
213 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( mJoinLayerComboBox->currentIndex() != -1
214 && mJoinFieldComboBox->currentIndex() != -1
215 && mTargetFieldComboBox->currentIndex() != -1 );
216}
217
218void QgsJoinDialog::editableJoinLayerChanged()
219{
220 if ( mEditableJoinLayer->isChecked() )
221 {
222 mCacheInMemoryCheckBox->setEnabled( false );
223 mCacheInMemoryCheckBox->setToolTip( tr( "Caching can not be enabled if editable join layer is enabled" ) );
224 mCacheEnabled = mCacheInMemoryCheckBox->isChecked();
225 mCacheInMemoryCheckBox->setChecked( false );
226 }
227 else
228 {
229 mCacheInMemoryCheckBox->setEnabled( true );
230 mCacheInMemoryCheckBox->setToolTip( QString() );
231 mCacheInMemoryCheckBox->setChecked( mCacheEnabled );
232 }
233}
@ CreateAttributeIndex
Can create indexes on provider's fields.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
void setLayer(QgsMapLayer *layer)
Sets the layer for which fields are listed in the combobox.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:46
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
QgsJoinDialog(QgsVectorLayer *layer, QList< QgsMapLayer * > alreadyJoinedLayers, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
QgsVectorLayerJoinInfo joinInfo() const
Returns the join info.
bool createAttributeIndex() const
Returns true if user wants to create an attribute index on the join field.
void setJoinInfo(const QgsVectorLayerJoinInfo &joinInfo)
Configure the dialog for an existing join.
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
This is the base class for vector data providers.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
Defines left outer join from our vector layer to some other vector layer.
void setDynamicFormEnabled(bool enabled)
Sets whether the form has to be dynamically updated with joined fields when a feature is being create...
bool hasCascadedDelete() const
Returns whether a feature deleted on the target layer has to impact the joined layer by deleting the ...
void setUsingMemoryCache(bool enabled)
Sets whether values from the joined layer should be cached in memory to speed up lookups.
bool isDynamicFormEnabled() const
Returns whether the form has to be dynamically updated with joined fields when a feature is being cre...
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
void setEditable(bool enabled)
Sets whether the form of the target layer allows editing joined fields.
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
void setCascadedDelete(bool enabled)
Sets whether a feature deleted on the target layer has to impact the joined layer by deleting the cor...
void setJoinFieldName(const QString &fieldName)
Sets name of the field of joined layer that will be used for join.
bool isUsingMemoryCache() const
Returns whether values from the joined layer should be cached in memory to speed up lookups.
QString prefix() const
Returns prefix of fields from the joined layer. If nullptr, joined layer's name will be used.
static QStringList joinFieldNamesSubset(const QgsVectorLayerJoinInfo &info, bool blocklisted=true)
Returns the list of field names to use for joining considering blocklisted fields and subset.
void setTargetFieldName(const QString &fieldName)
Sets name of the field of our layer that will be used for join.
QString joinFieldName() const
Returns name of the field of joined layer that will be used for join.
void setUpsertOnEdit(bool enabled)
Sets whether a feature created on the target layer has to impact the joined layer by creating a new f...
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
void setPrefix(const QString &prefix)
Sets prefix of fields from the joined layer. If nullptr, joined layer's name will be used.
void setJoinLayer(QgsVectorLayer *layer)
Sets weak reference to the joined layer.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet)
void setJoinFieldNamesSubset(QStringList *fieldNamesSubset)
Sets the subset of fields to be used from joined layer.
Represents a vector layer which manages a vector based data sets.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.