QGIS API Documentation 3.41.0-Master (88383c3d16f)
Loading...
Searching...
No Matches
qgsvectorlayerproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdlgvectorlayerproperties.cpp
3 Unified property dialog for vector layers
4 -------------------
5 begin : 2004-01-28
6 copyright : (C) 2004 by Gary E.Sherman
7 email : sherman at mrcc.com
8***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19#include <memory>
20#include <limits>
21
22#include "qgsactionmanager.h"
23#include "qgsjoindialog.h"
26#include "qgsapplication.h"
29#include "qgsdiagramwidget.h"
32#include "qgslabelingwidget.h"
33#include "qgsmapcanvas.h"
35#include "qgsmetadatawidget.h"
37#include "qgsproject.h"
38#include "qgsvectorlayer.h"
41#include "moc_qgsvectorlayerproperties.cpp"
44#include "qgsdatasourceuri.h"
45#include "qgsrenderer.h"
47#include "qgssettings.h"
49#include "qgsstyle.h"
50#include "qgsauxiliarystorage.h"
55#include "qgslabelinggui.h"
56#include "qgsmessagebar.h"
59#include "qgsmaskingwidget.h"
62#include "qgsproviderregistry.h"
64#include "qgslayertreemodel.h"
65#include "qgsmaptip.h"
66#include "qgsgui.h"
67#include "qgsnative.h"
70#include "qgsfileutils.h"
71#include "qgswebview.h"
72#include "qgswebframe.h"
73#include "qgsexpressionfinder.h"
74#if WITH_QTWEBKIT
75#include <QWebElement>
76#endif
77
78#include <QDesktopServices>
79#include <QMessageBox>
80#include <QDir>
81#include <QFile>
82#include <QFileDialog>
83#include <QFileInfo>
84#include <QFontDialog>
85#include <QComboBox>
86#include <QCheckBox>
87#include <QHeaderView>
88#include <QColorDialog>
89#include <QMenu>
90#include <QUrl>
91#include <QRegularExpressionValidator>
92
93
95 QgsMapCanvas *canvas,
96 QgsMessageBar *messageBar,
97 QgsVectorLayer *lyr,
98 QWidget *parent,
99 Qt::WindowFlags fl
100)
101 : QgsLayerPropertiesDialog( lyr, canvas, QStringLiteral( "VectorLayerProperties" ), parent, fl )
102 , mMessageBar( messageBar )
103 , mLayer( lyr )
104 , mOriginalSubsetSQL( lyr->subsetString() )
105{
106 setupUi( this );
107 connect( pbnQueryBuilder, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnQueryBuilder_clicked );
108 connect( pbnIndex, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnIndex_clicked );
109 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerProperties::mCrsSelector_crsChanged );
110 connect( pbnUpdateExtents, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnUpdateExtents_clicked );
111 connect( mButtonAddJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddJoin_clicked );
112 connect( mButtonEditJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditJoin_clicked );
113 connect( mJoinTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked );
114 connect( mButtonRemoveJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveJoin_clicked );
115 connect( mButtonAddWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddWmsDimension_clicked );
116 connect( mButtonEditWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditWmsDimension_clicked );
117 connect( mWmsDimensionsTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked );
118 connect( mButtonRemoveWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked );
119 connect( mSimplifyDrawingGroupBox, &QGroupBox::toggled, this, &QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled );
120 connect( buttonRemoveMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::removeSelectedMetadataUrl );
121 connect( buttonAddMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::addMetadataUrl );
122 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerProperties::showHelp );
123
124 mProjectDirtyBlocker = std::make_unique<QgsProjectDirtyBlocker>( QgsProject::instance() );
125
126 // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
127 // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
128 // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
129 initOptionsBase( false );
130
131 mBtnStyle = new QPushButton( tr( "Style" ), this );
132 QMenu *menuStyle = new QMenu( this );
133 mActionLoadStyle = new QAction( tr( "Load Style…" ), this );
134 connect( mActionLoadStyle, &QAction::triggered, this, &QgsVectorLayerProperties::loadStyle );
135
136 mActionSaveStyle = new QAction( tr( "Save Current Style…" ), this );
137 connect( mActionSaveStyle, &QAction::triggered, this, &QgsVectorLayerProperties::saveStyleAs );
138
139 mActionSaveMultipleStyles = new QAction( tr( "Save Multiple Styles…" ), this );
140 connect( mActionSaveMultipleStyles, &QAction::triggered, this, &QgsVectorLayerProperties::saveMultipleStylesAs );
141
142 mSourceGroupBox->hide();
143
144 mBtnStyle->setMenu( menuStyle );
145 connect( menuStyle, &QMenu::aboutToShow, this, &QgsVectorLayerProperties::aboutToShowStyleMenu );
146 buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
147
149
150 connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsVectorLayerProperties::apply );
151 connect( this, &QDialog::accepted, this, &QgsVectorLayerProperties::apply );
152 connect( this, &QDialog::rejected, this, &QgsVectorLayerProperties::rollback );
153
154 if ( mCanvas )
155 {
156 mContext = mCanvas->createExpressionContext();
157 }
158 else
159 {
164 }
165 mContext << QgsExpressionContextUtils::layerScope( mLayer );
166
167 mMapTipFieldComboBox->setLayer( lyr );
168 mDisplayExpressionWidget->setLayer( lyr );
169 mDisplayExpressionWidget->registerExpressionContextGenerator( this );
170 initMapTipPreview();
171
172 connect( mMapTipInsertFieldButton, &QAbstractButton::clicked, this, &QgsVectorLayerProperties::insertField );
173 connect( mMapTipInsertExpressionButton, &QAbstractButton::clicked, this, &QgsVectorLayerProperties::insertOrEditExpression );
174
175 if ( !mLayer )
176 return;
177
178 connect( mEnableMapTips, &QAbstractButton::toggled, mHtmlMapTipGroupBox, &QWidget::setEnabled );
179 mEnableMapTips->setChecked( mLayer->mapTipsEnabled() );
180
181 QVBoxLayout *layout = nullptr;
182
183 if ( mLayer->isSpatial() )
184 {
185 // Create the Labeling dialog tab
186 layout = new QVBoxLayout( labelingFrame );
187 layout->setContentsMargins( 0, 0, 0, 0 );
188 labelingDialog = new QgsLabelingWidget( mLayer, mCanvas, labelingFrame );
189 labelingDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
190 connect( labelingDialog, &QgsLabelingWidget::auxiliaryFieldCreated, this, [=] { updateAuxiliaryStoragePage(); } );
191 layout->addWidget( labelingDialog );
192 labelingFrame->setLayout( layout );
193
194 // Create the masking dialog tab
195 layout = new QVBoxLayout( mMaskingFrame );
196 layout->setContentsMargins( 0, 0, 0, 0 );
197 mMaskingWidget = new QgsMaskingWidget( mMaskingFrame );
198 mMaskingWidget->setLayer( mLayer );
199 mMaskingWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
200 layout->addWidget( mMaskingWidget );
201 mMaskingFrame->setLayout( layout );
202 }
203 else
204 {
205 labelingDialog = nullptr;
206 mOptsPage_Labels->setEnabled( false ); // disable labeling item
207 mOptsPage_Masks->setEnabled( false ); // disable masking item
208 mGeomGroupBox->setEnabled( false );
209 mGeomGroupBox->setVisible( false );
210 mCrsGroupBox->setEnabled( false );
211 mCrsGroupBox->setVisible( false );
212 }
213
214 // Create the Actions dialog tab
215 QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
216 actionLayout->setContentsMargins( 0, 0, 0, 0 );
217 mActionDialog = new QgsAttributeActionDialog( *mLayer->actions(), actionOptionsFrame );
218 mActionDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
219 actionLayout->addWidget( mActionDialog );
220
221 mSourceFieldsPropertiesDialog = new QgsSourceFieldsProperties( mLayer, mSourceFieldsFrame );
222 mSourceFieldsPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
223 mSourceFieldsFrame->setLayout( new QVBoxLayout( mSourceFieldsFrame ) );
224 mSourceFieldsFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
225 mSourceFieldsFrame->layout()->addWidget( mSourceFieldsPropertiesDialog );
226
227 connect( mSourceFieldsPropertiesDialog, &QgsSourceFieldsProperties::toggleEditing, this, static_cast<void ( QgsVectorLayerProperties::* )()>( &QgsVectorLayerProperties::toggleEditing ) );
228
229 mAttributesFormPropertiesDialog = new QgsAttributesFormProperties( mLayer, mAttributesFormFrame );
230 mAttributesFormPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
231 mAttributesFormFrame->setLayout( new QVBoxLayout( mAttributesFormFrame ) );
232 mAttributesFormFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
233 mAttributesFormFrame->layout()->addWidget( mAttributesFormPropertiesDialog );
234
235 // Metadata tab, before the syncToLayer
236 QVBoxLayout *metadataLayout = new QVBoxLayout( metadataFrame );
237 metadataLayout->setContentsMargins( 0, 0, 0, 0 );
238 mMetadataWidget = new QgsMetadataWidget( this, mLayer );
239 mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
240 mMetadataWidget->setMapCanvas( mCanvas );
241 metadataLayout->addWidget( mMetadataWidget );
242 metadataFrame->setLayout( metadataLayout );
243
244 QVBoxLayout *temporalLayout = new QVBoxLayout( temporalFrame );
245 temporalLayout->setContentsMargins( 0, 0, 0, 0 );
246 mTemporalWidget = new QgsVectorLayerTemporalPropertiesWidget( this, mLayer );
247 temporalLayout->addWidget( mTemporalWidget );
248
249 setMetadataWidget( mMetadataWidget, mOptsPage_Metadata );
250
251 mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
252 QMenu *menuMetadata = new QMenu( this );
253 mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata from File…" ), this, &QgsVectorLayerProperties::loadMetadataFromFile );
254 mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata to File…" ), this, &QgsVectorLayerProperties::saveMetadataToFile );
255 menuMetadata->addSeparator();
256 menuMetadata->addAction( tr( "Save to Default Location" ), this, &QgsVectorLayerProperties::saveMetadataAsDefault );
257 menuMetadata->addAction( tr( "Restore from Default Location" ), this, &QgsVectorLayerProperties::loadDefaultMetadata );
258 mBtnMetadata->setMenu( menuMetadata );
259 buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
260
261 mSelectionColorButton->setAllowOpacity( true );
262 mSelectionColorButton->setColorDialogTitle( tr( "Override Selection Color" ) );
263 if ( mCanvas )
264 {
265 mSelectionColorButton->setColor( mCanvas->selectionColor() );
266 mSelectionColorButton->setDefaultColor( mCanvas->selectionColor() );
267 }
268 connect( mRadioOverrideSelectionColor, &QRadioButton::toggled, mSelectionColorButton, &QWidget::setEnabled );
269 mSelectionColorButton->setEnabled( false );
270 connect( mRadioOverrideSelectionSymbol, &QRadioButton::toggled, mSelectionSymbolButton, &QWidget::setEnabled );
271 switch ( mLayer->geometryType() )
272 {
274 mSelectionSymbolButton->setSymbolType( Qgis::SymbolType::Marker );
275 break;
277 mSelectionSymbolButton->setSymbolType( Qgis::SymbolType::Line );
278 break;
280 mSelectionSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
281 break;
282
285 break;
286 }
287 mSelectionSymbolButton->setEnabled( false );
288 mRadioDefaultSelectionColor->setChecked( true );
289
290 // Diagram tab, before the syncToLayer
291 QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
292 diagLayout->setContentsMargins( 0, 0, 0, 0 );
293 diagramPropertiesDialog = new QgsDiagramWidget( mLayer, mCanvas, mDiagramFrame );
294 diagramPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
295 connect( diagramPropertiesDialog, &QgsDiagramWidget::auxiliaryFieldCreated, this, [=] { updateAuxiliaryStoragePage(); } );
296 diagLayout->addWidget( diagramPropertiesDialog );
297 mDiagramFrame->setLayout( diagLayout );
298
299 syncToLayer();
300
301 if ( mLayer->dataProvider() )
302 {
303 //enable spatial index button group if supported by provider, or if one already exists
306 {
307 pbnIndex->setEnabled( false );
308 }
310 {
311 pbnIndex->setEnabled( false );
312 pbnIndex->setText( tr( "Spatial Index Exists" ) );
313 }
314
316 {
317 cboProviderEncoding->addItems( QgsVectorDataProvider::availableEncodings() );
318 QString enc = mLayer->dataProvider()->encoding();
319 int encindex = cboProviderEncoding->findText( enc );
320 if ( encindex < 0 )
321 {
322 cboProviderEncoding->insertItem( 0, enc );
323 encindex = 0;
324 }
325 cboProviderEncoding->setCurrentIndex( encindex );
326 }
327 else if ( mLayer->providerType() == QLatin1String( "ogr" ) )
328 {
329 // if OGR_L_TestCapability(OLCStringsAsUTF8) returns true, OGR provider encoding can be set to only UTF-8
330 // so make encoding box grayed out
331 cboProviderEncoding->addItem( mLayer->dataProvider()->encoding() );
332 cboProviderEncoding->setEnabled( false );
333 }
334 else
335 {
336 // other providers do not use mEncoding, so hide the group completely
337 mDataSourceEncodingFrame->hide();
338 }
339 }
340
341 mCrsSelector->setCrs( mLayer->crs() );
342
343 //insert existing join info
344 const QList<QgsVectorLayerJoinInfo> &joins = mLayer->vectorJoins();
345 for ( const QgsVectorLayerJoinInfo &join : joins )
346 {
347 addJoinToTreeWidget( join );
348 }
349
350 mOldJoins = mLayer->vectorJoins();
351
352 // Legend tab
353 mLegendWidget->setMapCanvas( mCanvas );
354 mLegendWidget->setLayer( mLayer );
355 mLegendConfigEmbeddedWidget->setLayer( mLayer );
356
357 // WMS Name as layer short name
358 mLayerShortNameLineEdit->setText( mLayer->serverProperties()->shortName() );
359 // WMS Name validator
360 QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
361 mLayerShortNameLineEdit->setValidator( shortNameValidator );
362
363 //layer title and abstract
364 mLayerTitleLineEdit->setText( mLayer->serverProperties()->title() );
365 if ( mLayer->serverProperties()->wfsTitle() != mLayer->serverProperties()->title() )
366 mLayerOptWfsTitleLineEdit->setText( mLayer->serverProperties()->wfsTitle() );
367 mLayerAbstractTextEdit->setPlainText( mLayer->serverProperties()->abstract() );
368 mLayerKeywordListLineEdit->setText( mLayer->serverProperties()->keywordList() );
369 mLayerDataUrlLineEdit->setText( mLayer->serverProperties()->dataUrl() );
370 mLayerDataUrlFormatComboBox->setCurrentIndex(
371 mLayerDataUrlFormatComboBox->findText(
373 )
374 );
375 //layer attribution
376 mLayerAttributionLineEdit->setText( mLayer->serverProperties()->attribution() );
377 mLayerAttributionUrlLineEdit->setText( mLayer->serverProperties()->attributionUrl() );
378
379 // Setup the layer metadata URL
380 tableViewMetadataUrl->setSelectionMode( QAbstractItemView::SingleSelection );
381 tableViewMetadataUrl->setSelectionBehavior( QAbstractItemView::SelectRows );
382 tableViewMetadataUrl->horizontalHeader()->setStretchLastSection( true );
383 tableViewMetadataUrl->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
384
385 mMetadataUrlModel = new QStandardItemModel( tableViewMetadataUrl );
386 mMetadataUrlModel->clear();
387 mMetadataUrlModel->setColumnCount( 3 );
388 QStringList metadataUrlHeaders;
389 metadataUrlHeaders << tr( "URL" ) << tr( "Type" ) << tr( "Format" );
390 mMetadataUrlModel->setHorizontalHeaderLabels( metadataUrlHeaders );
391 tableViewMetadataUrl->setModel( mMetadataUrlModel );
392 tableViewMetadataUrl->setItemDelegate( new MetadataUrlItemDelegate( this ) );
393
394 const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mLayer->serverProperties()->metadataUrls();
395 for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
396 {
397 const int row = mMetadataUrlModel->rowCount();
398 mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
399 mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
400 mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
401 }
402
403 // layer legend url
404 mLayerLegendUrlLineEdit->setText( mLayer->legendUrl() );
405 mLayerLegendUrlFormatComboBox->setCurrentIndex(
406 mLayerLegendUrlFormatComboBox->findText(
407 mLayer->legendUrlFormat()
408 )
409 );
410
411 //insert existing dimension info
412 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
413 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &wmsDims = serverProperties->wmsDimensions();
414 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
415 {
416 addWmsDimensionInfoToTreeWidget( dim );
417 }
418
419 QString myStyle = QgsApplication::reportStyleSheet();
420 myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
421 teMetadataViewer->clear();
422 teMetadataViewer->document()->setDefaultStyleSheet( myStyle );
423 teMetadataViewer->setHtml( htmlMetadata() );
424 teMetadataViewer->setOpenLinks( false );
425 connect( teMetadataViewer, &QTextBrowser::anchorClicked, this, &QgsVectorLayerProperties::openUrl );
426 mMetadataFilled = true;
427
428 QgsSettings settings;
429 // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
430 // this will be read by restoreOptionsBaseUi()
431 if ( !settings.contains( QStringLiteral( "/Windows/VectorLayerProperties/tab" ) ) )
432 {
433 settings.setValue( QStringLiteral( "Windows/VectorLayerProperties/tab" ), mOptStackedWidget->indexOf( mOptsPage_Style ) );
434 }
435
436 QList<QgsMapLayer *> dependencySources;
437 const QSet<QgsMapLayerDependency> constDependencies = mLayer->dependencies();
438 for ( const QgsMapLayerDependency &dep : constDependencies )
439 {
440 QgsMapLayer *layer = QgsProject::instance()->mapLayer( dep.layerId() );
441 if ( layer )
442 dependencySources << layer;
443 }
444
445 mLayersDependenciesTreeModel = new QgsLayerTreeFilterProxyModel( this );
446 mLayersDependenciesTreeModel->setLayerTreeModel( new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot(), mLayersDependenciesTreeModel ) );
447 mLayersDependenciesTreeModel->setCheckedLayers( dependencySources );
448 connect( QgsProject::instance(), &QObject::destroyed, this, [=] { mLayersDependenciesTreeView->setModel( nullptr ); } );
449 mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel );
450
451 mRefreshSettingsWidget->setLayer( mLayer );
452
453 // auxiliary layer
454 QMenu *menu = new QMenu( this );
455
456 mAuxiliaryLayerActionNew = new QAction( tr( "Create" ), this );
457 menu->addAction( mAuxiliaryLayerActionNew );
458 connect( mAuxiliaryLayerActionNew, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerNew );
459
460 mAuxiliaryLayerActionClear = new QAction( tr( "Clear" ), this );
461 menu->addAction( mAuxiliaryLayerActionClear );
462 connect( mAuxiliaryLayerActionClear, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerClear );
463
464 mAuxiliaryLayerActionDelete = new QAction( tr( "Delete" ), this );
465 menu->addAction( mAuxiliaryLayerActionDelete );
466 connect( mAuxiliaryLayerActionDelete, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerDelete );
467
468 mAuxiliaryLayerActionExport = new QAction( tr( "Export" ), this );
469 menu->addAction( mAuxiliaryLayerActionExport );
470 connect( mAuxiliaryLayerActionExport, &QAction::triggered, this, [=] { emit exportAuxiliaryLayer( mLayer->auxiliaryLayer() ); } );
471
472 mAuxiliaryStorageActions->setMenu( menu );
473
474 connect( mAuxiliaryStorageFieldsDeleteBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerDeleteField );
475 connect( mAuxiliaryStorageFieldsAddBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerAddField );
476
477 updateAuxiliaryStoragePage();
478
479 mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#information-properties" ) );
480 mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#source-properties" ) );
481 mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#symbology-properties" ) );
482 mOptsPage_Labels->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#labels-properties" ) );
483 mOptsPage_Masks->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#masks-properties" ) );
484 mOptsPage_Diagrams->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#diagrams-properties" ) );
485 mOptsPage_SourceFields->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#fields-properties" ) );
486 mOptsPage_AttributesForm->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#attributes-form-properties" ) );
487 mOptsPage_Joins->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#joins-properties" ) );
488 mOptsPage_AuxiliaryStorage->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#auxiliary-storage-properties" ) );
489 mOptsPage_Actions->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#actions-properties" ) );
490 mOptsPage_Display->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#display-properties" ) );
491 mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#rendering-properties" ) );
492 mOptsPage_Temporal->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#temporal-properties" ) );
493 mOptsPage_Variables->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#variables-properties" ) );
494 mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#metadata-properties" ) );
495 mOptsPage_DataDependencies->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#dependencies-properties" ) );
496 mOptsPage_Legend->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#legend-properties" ) );
497 mOptsPage_Server->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#qgis-server-properties" ) );
498
499
501
502 initialize();
503}
504
505void QgsVectorLayerProperties::toggleEditing()
506{
507 if ( !mLayer )
508 return;
509
510 emit toggleEditing( mLayer );
511
512 setPbnQueryBuilderEnabled();
513}
514
515void QgsVectorLayerProperties::insertField()
516{
517 // Convert the selected field to an expression and
518 // insert it into the action at the cursor position
519 if ( mMapTipFieldComboBox->currentField().isEmpty() )
520 return;
521 QString expression = QStringLiteral( "[%\"" );
522 expression += mMapTipFieldComboBox->currentField();
523 expression += QLatin1String( "\"%]" );
524
525 mMapTipWidget->insertText( expression );
526}
527
528void QgsVectorLayerProperties::insertOrEditExpression()
529{
530 // Get the linear indexes if the start and end of the selection
531 int selectionStart = mMapTipWidget->selectionStart();
532 int selectionEnd = mMapTipWidget->selectionEnd();
533 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mMapTipWidget );
534
535 QgsExpressionContext context = createExpressionContext();
536 QgsExpressionBuilderDialog exprDlg( mLayer, expression, this, QStringLiteral( "generic" ), context );
537
538 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
539 if ( exprDlg.exec() == QDialog::Accepted && !exprDlg.expressionText().trimmed().isEmpty() )
540 mMapTipWidget->insertText( "[%" + exprDlg.expressionText().trimmed() + "%]" );
541 else // Restore the selection
542 mMapTipWidget->setLinearSelection( selectionStart, selectionEnd );
543}
544
545void QgsVectorLayerProperties::addMetadataUrl()
546{
547 const int row = mMetadataUrlModel->rowCount();
548 mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
549 mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
550 mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
551}
552
553void QgsVectorLayerProperties::removeSelectedMetadataUrl()
554{
555 const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
556 if ( selectedRows.empty() )
557 return;
558 mMetadataUrlModel->removeRow( selectedRows[0].row() );
559}
560
562{
563 if ( !mSourceWidget )
564 {
565 mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mLayer );
566 if ( mSourceWidget )
567 {
568 QHBoxLayout *layout = new QHBoxLayout();
569 layout->addWidget( mSourceWidget );
570 mSourceGroupBox->setLayout( layout );
571 if ( !mSourceWidget->groupTitle().isEmpty() )
572 mSourceGroupBox->setTitle( mSourceWidget->groupTitle() );
573
574 mSourceGroupBox->show();
575
576 connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [=]( bool isValid ) {
577 buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
578 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
579 } );
580 }
581 }
582
583 if ( mSourceWidget )
584 {
585 mSourceWidget->setMapCanvas( mCanvas );
586 mSourceWidget->setSourceUri( mLayer->source() );
587 }
588
589 // populate the general information
590 mLayerOrigNameLineEdit->setText( mLayer->name() );
591 mBackupCrs = mLayer->crs();
592
593 //see if we are dealing with a pg layer here
594 mSubsetGroupBox->setEnabled( true );
595 txtSubsetSQL->setText( mLayer->subsetString() );
596 // if the user is allowed to type an adhoc query, the app will crash if the query
597 // is bad. For this reason, the sql box is disabled and the query must be built
598 // using the query builder, either by typing it in by hand or using the buttons, etc
599 // on the builder. If the ability to enter a query directly into the box is required,
600 // a mechanism to check it must be implemented.
601 txtSubsetSQL->setReadOnly( true );
602 txtSubsetSQL->setCaretWidth( 0 );
603 txtSubsetSQL->setCaretLineVisible( false );
604 setPbnQueryBuilderEnabled();
605 if ( mLayer->dataProvider() && !mLayer->dataProvider()->supportsSubsetString() )
606 {
607 // hide subset box entirely if not supported by data provider
608 mSubsetGroupBox->hide();
609 }
610
611 mDisplayExpressionWidget->setField( mLayer->displayExpression() );
612 mEnableMapTips->setChecked( mLayer->mapTipsEnabled() );
613 mMapTipWidget->setText( mLayer->mapTipTemplate() );
614
615 // set up the scale based layer visibility stuff....
616 mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
617 mScaleVisibilityGroupBox->setChecked( mLayer->hasScaleBasedVisibility() );
618 mScaleRangeWidget->setMapCanvas( mCanvas );
619
620 mUseReferenceScaleGroupBox->setChecked( mLayer->renderer() && mLayer->renderer()->referenceScale() > 0 );
621 mReferenceScaleWidget->setShowCurrentScaleButton( true );
622 mReferenceScaleWidget->setMapCanvas( mCanvas );
623 if ( mUseReferenceScaleGroupBox->isChecked() )
624 mReferenceScaleWidget->setScale( mLayer->renderer()->referenceScale() );
625 else if ( mCanvas )
626 mReferenceScaleWidget->setScale( mCanvas->scale() );
627
628 // get simplify drawing configuration
629 const QgsVectorSimplifyMethod &simplifyMethod = mLayer->simplifyMethod();
631 mSimplifyDrawingSpinBox->setValue( simplifyMethod.threshold() );
632 mSimplifyDrawingSpinBox->setClearValue( 1.0 );
633
634 QgsVectorLayerSelectionProperties *selectionProperties = qobject_cast<QgsVectorLayerSelectionProperties *>( mLayer->selectionProperties() );
635 if ( selectionProperties->selectionColor().isValid() )
636 {
637 mSelectionColorButton->setColor( selectionProperties->selectionColor() );
638 }
639 if ( QgsSymbol *symbol = selectionProperties->selectionSymbol() )
640 {
641 mSelectionSymbolButton->setSymbol( symbol->clone() );
642 }
643 switch ( selectionProperties->selectionRenderingMode() )
644 {
646 mRadioDefaultSelectionColor->setChecked( true );
647 break;
648
650 {
651 if ( selectionProperties->selectionColor().isValid() )
652 {
653 mRadioOverrideSelectionColor->setChecked( true );
654 }
655 else
656 {
657 mRadioDefaultSelectionColor->setChecked( true );
658 }
659 break;
660 }
661
663 if ( selectionProperties->selectionSymbol() )
664 {
665 mRadioOverrideSelectionSymbol->setChecked( true );
666 }
667 else
668 {
669 mRadioDefaultSelectionColor->setChecked( true );
670 }
671 break;
672 }
673
674 QString remark = QStringLiteral( " (%1)" ).arg( tr( "Not supported" ) );
675 const QgsVectorDataProvider *provider = mLayer->dataProvider();
676 if ( !( provider && ( provider->capabilities() & Qgis::VectorProviderCapability::SimplifyGeometries ) ) )
677 {
678 mSimplifyDrawingAtProvider->setChecked( false );
679 mSimplifyDrawingAtProvider->setEnabled( false );
680 if ( !mSimplifyDrawingAtProvider->text().endsWith( remark ) )
681 mSimplifyDrawingAtProvider->setText( mSimplifyDrawingAtProvider->text().append( remark ) );
682 }
683 else
684 {
685 mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() );
686 mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() );
687 if ( mSimplifyDrawingAtProvider->text().endsWith( remark ) )
688 {
689 QString newText = mSimplifyDrawingAtProvider->text();
690 newText.chop( remark.size() );
691 mSimplifyDrawingAtProvider->setText( newText );
692 }
693 }
694
695 // disable simplification for point layers, now it is not implemented
696 if ( mLayer->geometryType() == Qgis::GeometryType::Point )
697 {
698 mSimplifyDrawingGroupBox->setChecked( false );
699 mSimplifyDrawingGroupBox->setEnabled( false );
700 }
701
702 // Default local simplification algorithm
703 mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), QVariant::fromValue( Qgis::VectorSimplificationAlgorithm::Distance ) );
704 mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), QVariant::fromValue( Qgis::VectorSimplificationAlgorithm::SnapToGrid ) );
705 mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), QVariant::fromValue( Qgis::VectorSimplificationAlgorithm::Visvalingam ) );
706 mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( QVariant::fromValue( simplifyMethod.simplifyAlgorithm() ) ) );
707
708 QStringList myScalesList = Qgis::defaultProjectScales().split( ',' );
709 myScalesList.append( QStringLiteral( "1:1" ) );
710 mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
711 mSimplifyMaximumScaleComboBox->setScale( simplifyMethod.maximumScale() );
712
713 mForceRasterCheckBox->setChecked( mLayer->renderer() && mLayer->renderer()->forceRasterRender() );
714
715 mRefreshSettingsWidget->syncToLayer();
716
717 mRefreshLayerNotificationCheckBox->setChecked( mLayer->isRefreshOnNotifyEnabled() );
718 mNotificationMessageCheckBox->setChecked( !mLayer->refreshOnNotifyMessage().isEmpty() );
719 mNotifyMessagValueLineEdit->setText( mLayer->refreshOnNotifyMessage() );
720
721
722 // load appropriate symbology page (V1 or V2)
723 updateSymbologyPage();
724
725 mActionDialog->init( *mLayer->actions(), mLayer->attributeTableConfig() );
726
727 if ( labelingDialog )
728 labelingDialog->adaptToLayer();
729
730 mSourceFieldsPropertiesDialog->init();
731 mAttributesFormPropertiesDialog->init();
732
733 // set initial state for variable editor
734 updateVariableEditor();
735
736 if ( diagramPropertiesDialog )
737 diagramPropertiesDialog->syncToOwnLayer();
738
739 // sync all plugin dialogs
740 for ( QgsMapLayerConfigWidget *page : std::as_const( mConfigWidgets ) )
741 {
742 page->syncToLayer( mLayer );
743 }
744
745 mMetadataWidget->setMetadata( &mLayer->metadata() );
746
747 mTemporalWidget->syncToLayer();
748
749 mLegendWidget->setLayer( mLayer );
750}
751
753{
754 if ( labelingDialog )
755 {
756 labelingDialog->writeSettingsToLayer();
757 }
758 mBackupCrs = mLayer->crs();
759 // apply legend settings
760 mLegendWidget->applyToLayer();
761 mLegendConfigEmbeddedWidget->applyToLayer();
762
763 // save metadata
764 mMetadataWidget->acceptMetadata();
765 mMetadataFilled = false;
766
767 // save masking settings
768 if ( mMaskingWidget )
769 mMaskingWidget->apply();
770
771 // set up the scale based layer visibility stuff....
772 mLayer->setScaleBasedVisibility( mScaleVisibilityGroupBox->isChecked() );
773 mLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
774 mLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
775
776 // provider-specific options
777 if ( mLayer->dataProvider() )
778 {
780 {
781 mLayer->setProviderEncoding( cboProviderEncoding->currentText() );
782 }
783 }
784
785 mLayer->setDisplayExpression( mDisplayExpressionWidget->asExpression() );
786 mLayer->setMapTipsEnabled( mEnableMapTips->isChecked() );
787 mLayer->setMapTipTemplate( mMapTipWidget->text() );
788
789 mLayer->actions()->clearActions();
790 const auto constActions = mActionDialog->actions();
791 for ( const QgsAction &action : constActions )
792 {
793 mLayer->actions()->addAction( action );
794 }
795 QgsAttributeTableConfig attributeTableConfig = mLayer->attributeTableConfig();
796 attributeTableConfig.update( mLayer->fields() );
797 attributeTableConfig.setActionWidgetStyle( mActionDialog->attributeTableWidgetStyle() );
798 QVector<QgsAttributeTableConfig::ColumnConfig> columns = attributeTableConfig.columns();
799
800 for ( int i = 0; i < columns.size(); ++i )
801 {
802 if ( columns.at( i ).type == QgsAttributeTableConfig::Action )
803 {
804 columns[i].hidden = !mActionDialog->showWidgetInAttributeTable();
805 }
806 }
807
808 attributeTableConfig.setColumns( columns );
809
810 mLayer->setAttributeTableConfig( attributeTableConfig );
811
812 mLayer->setName( mLayerOrigNameLineEdit->text() );
813
814 mAttributesFormPropertiesDialog->apply();
815 mSourceFieldsPropertiesDialog->apply();
816
817 // Update temporal properties
818 mTemporalWidget->saveTemporalProperties();
819
820 if ( mLayer->renderer() )
821 {
822 QgsRendererPropertiesDialog *dlg = static_cast<QgsRendererPropertiesDialog *>( widgetStackRenderers->currentWidget() );
823 dlg->apply();
824 }
825
826 //apply diagram settings
827 diagramPropertiesDialog->apply();
828
829 // apply all plugin dialogs
830 for ( QgsMapLayerConfigWidget *page : std::as_const( mConfigWidgets ) )
831 {
832 page->apply();
833 }
834
835 //layer title and abstract
836 if ( mLayer->serverProperties()->shortName() != mLayerShortNameLineEdit->text() )
837 mMetadataFilled = false;
838 mLayer->serverProperties()->setShortName( mLayerShortNameLineEdit->text() );
839
840 if ( mLayer->serverProperties()->title() != mLayerTitleLineEdit->text() )
841 mMetadataFilled = false;
842 mLayer->serverProperties()->setTitle( mLayerTitleLineEdit->text() );
843
844 if ( !mLayerOptWfsTitleLineEdit->text().isEmpty() && mLayerOptWfsTitleLineEdit->text() != mLayerTitleLineEdit->text() )
845 {
846 mLayer->serverProperties()->setWfsTitle( mLayerOptWfsTitleLineEdit->text() );
847 mMetadataFilled = false;
848 }
849 else
850 {
851 mLayer->serverProperties()->setWfsTitle( QString() );
852 }
853
854 if ( mLayer->serverProperties()->abstract() != mLayerAbstractTextEdit->toPlainText() )
855 mMetadataFilled = false;
856 mLayer->serverProperties()->setAbstract( mLayerAbstractTextEdit->toPlainText() );
857
858 if ( mLayer->serverProperties()->keywordList() != mLayerKeywordListLineEdit->text() )
859 mMetadataFilled = false;
860 mLayer->serverProperties()->setKeywordList( mLayerKeywordListLineEdit->text() );
861
862 if ( mLayer->serverProperties()->dataUrl() != mLayerDataUrlLineEdit->text() )
863 mMetadataFilled = false;
864 mLayer->serverProperties()->setDataUrl( mLayerDataUrlLineEdit->text() );
865
866 if ( mLayer->serverProperties()->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
867 mMetadataFilled = false;
868 mLayer->serverProperties()->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
869
870 //layer attribution
871 if ( mLayer->serverProperties()->attribution() != mLayerAttributionLineEdit->text() )
872 mMetadataFilled = false;
873 mLayer->serverProperties()->setAttribution( mLayerAttributionLineEdit->text() );
874
875 if ( mLayer->serverProperties()->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
876 mMetadataFilled = false;
877 mLayer->serverProperties()->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
878
879 // Metadata URL
880 QList<QgsMapLayerServerProperties::MetadataUrl> metaUrls;
881 for ( int row = 0; row < mMetadataUrlModel->rowCount(); row++ )
882 {
884 metaUrl.url = mMetadataUrlModel->item( row, 0 )->text();
885 metaUrl.type = mMetadataUrlModel->item( row, 1 )->text();
886 metaUrl.format = mMetadataUrlModel->item( row, 2 )->text();
887 metaUrls.append( metaUrl );
888 mMetadataFilled = false;
889 }
890 mLayer->serverProperties()->setMetadataUrls( metaUrls );
891
892 // LegendURL
893 if ( mLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
894 mMetadataFilled = false;
895 mLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
896
897 if ( mLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
898 mMetadataFilled = false;
899 mLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
900
901 //layer simplify drawing configuration
903 if ( mSimplifyDrawingGroupBox->isChecked() )
904 {
906 if ( mSimplifyDrawingSpinBox->value() > 1 )
908 }
909 QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
910 simplifyMethod.setSimplifyHints( simplifyHints );
911 simplifyMethod.setSimplifyAlgorithm( mSimplifyAlgorithmComboBox->currentData().value<Qgis::VectorSimplificationAlgorithm>() );
912 simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
913 simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
914 simplifyMethod.setMaximumScale( mSimplifyMaximumScaleComboBox->scale() );
915 mLayer->setSimplifyMethod( simplifyMethod );
916
917 if ( mLayer->renderer() )
918 {
919 mLayer->renderer()->setForceRasterRender( mForceRasterCheckBox->isChecked() );
920 mLayer->renderer()->setReferenceScale( mUseReferenceScaleGroupBox->isChecked() ? mReferenceScaleWidget->scale() : -1 );
921 }
922
923 QgsVectorLayerSelectionProperties *selectionProperties = qobject_cast<QgsVectorLayerSelectionProperties *>( mLayer->selectionProperties() );
924 if ( mSelectionColorButton->color() != mSelectionColorButton->defaultColor() )
925 selectionProperties->setSelectionColor( mSelectionColorButton->color() );
926 else
927 selectionProperties->setSelectionColor( QColor() );
928 if ( QgsSymbol *symbol = mSelectionSymbolButton->symbol() )
929 selectionProperties->setSelectionSymbol( symbol->clone() );
930
931 if ( mRadioOverrideSelectionSymbol->isChecked() )
932 {
934 }
935 else if ( mRadioOverrideSelectionColor->isChecked() )
936 {
938 }
939 else
940 {
942 }
943
944 mRefreshSettingsWidget->saveToLayer();
945
946 mLayer->setRefreshOnNotifyEnabled( mRefreshLayerNotificationCheckBox->isChecked() );
947 mLayer->setRefreshOnNofifyMessage( mNotificationMessageCheckBox->isChecked() ? mNotifyMessagValueLineEdit->text() : QString() );
948
949 mOldJoins = mLayer->vectorJoins();
950
951 //save variables
952 QgsExpressionContextUtils::setLayerVariables( mLayer, mVariableEditor->variablesInActiveScope() );
953 updateVariableEditor();
954
955 // save dependencies
956 QSet<QgsMapLayerDependency> deps;
957 const auto checkedLayers = mLayersDependenciesTreeModel->checkedLayers();
958 for ( const QgsMapLayer *layer : checkedLayers )
959 deps << QgsMapLayerDependency( layer->id() );
960 if ( !mLayer->setDependencies( deps ) )
961 {
962 QMessageBox::warning( nullptr, tr( "Save Dependency" ), tr( "This configuration introduces a cycle in data dependencies and will be ignored." ) );
963 }
964
965 // Why is this here? Well, we if we're making changes to the layer's source then potentially
966 // we are changing the geometry type of the layer, or even going from spatial <-> non spatial types.
967 // So we need to ensure that anything from the dialog which sets things like renderer properties
968 // happens BEFORE we change the source, otherwise we might end up with a renderer which is not
969 // compatible with the new geometry type of the layer. (And likewise for other properties like
970 // fields!)
971 bool dialogNeedsResync = false;
972 if ( mSourceWidget )
973 {
974 const QString newSource = mSourceWidget->sourceUri();
975 if ( newSource != mLayer->source() )
976 {
977 mLayer->setDataSource( newSource, mLayer->name(), mLayer->providerType(), QgsDataProvider::ProviderOptions(), Qgis::DataProviderReadFlags() );
978
979 // resync dialog to layer's new state -- this allows any changed layer properties
980 // (such as a forced creation of a new renderer compatible with the new layer, new field configuration, etc)
981 // to show in the dialog correctly
982 dialogNeedsResync = true;
983 }
984 }
985 // now apply the subset string AFTER setting the layer's source. It's messy, but the subset string
986 // can form part of the layer's source, but it WON'T be present in the URI returned by the source widget!
987 // If we don't apply the subset string AFTER changing the source, then the subset string will be lost.
988 mSubsetGroupBox->setEnabled( true );
989 if ( txtSubsetSQL->text() != mLayer->subsetString() )
990 {
991 // set the subset sql for the layer
992 mLayer->setSubsetString( txtSubsetSQL->text() );
993 mMetadataFilled = false;
994 // need to resync the dialog, the subset string may have changed the layer's geometry type!
995 dialogNeedsResync = true;
996 }
997 mOriginalSubsetSQL = mLayer->subsetString();
998
999 if ( dialogNeedsResync )
1000 syncToLayer();
1001
1002 mLayer->triggerRepaint();
1003 // notify the project we've made a change
1004 mProjectDirtyBlocker.reset();
1005 QgsProject::instance()->setDirty( true );
1006 mProjectDirtyBlocker = std::make_unique<QgsProjectDirtyBlocker>( QgsProject::instance() );
1007}
1008
1010{
1011 if ( mOldJoins != mLayer->vectorJoins() )
1012 {
1013 // need to undo changes in vector layer joins - they are applied directly to the layer (not in apply())
1014 // so other parts of the properties dialog can use the fields from the joined layers
1015
1016 const auto constVectorJoins = mLayer->vectorJoins();
1017 for ( const QgsVectorLayerJoinInfo &info : constVectorJoins )
1018 mLayer->removeJoin( info.joinLayerId() );
1019
1020 for ( const QgsVectorLayerJoinInfo &info : std::as_const( mOldJoins ) )
1021 mLayer->addJoin( info );
1022 }
1023
1024 if ( mOriginalSubsetSQL != mLayer->subsetString() )
1025 {
1026 // need to undo changes in subset string - they are applied directly to the layer (not in apply())
1027 // by QgsQueryBuilder::accept()
1028
1029 mLayer->setSubsetString( mOriginalSubsetSQL );
1030 }
1031
1032 // Store it because QgsLayerPropertiesDialog::rollback() calls syncToLayer() which
1033 // resets the backupCrs
1034 const QgsCoordinateReferenceSystem backupCrs { mBackupCrs };
1035
1037
1038 if ( backupCrs != mLayer->crs() )
1039 mLayer->setCrs( backupCrs );
1040}
1041
1042void QgsVectorLayerProperties::pbnQueryBuilder_clicked()
1043{
1044 // launch the query builder
1046
1047 // Set the sql in the query builder to the same in the prop dialog
1048 // (in case the user has already changed it)
1049 dialog->setSubsetString( txtSubsetSQL->text() );
1050 // Open the query builder
1051 if ( dialog->exec() )
1052 {
1053 // if the sql is changed, update it in the prop subset text box
1054 txtSubsetSQL->setText( dialog->subsetString() );
1055 //TODO If the sql is changed in the prop dialog, the layer extent should be recalculated
1056
1057 // The datasource for the layer needs to be updated with the new sql since this gets
1058 // saved to the project file. This should happen at the map layer level...
1059 }
1060 // delete the query builder object
1061 delete dialog;
1062}
1063
1064void QgsVectorLayerProperties::pbnIndex_clicked()
1065{
1066 QgsVectorDataProvider *pr = mLayer->dataProvider();
1067 if ( pr )
1068 {
1069 setCursor( Qt::WaitCursor );
1070 bool errval = pr->createSpatialIndex();
1071 setCursor( Qt::ArrowCursor );
1072 if ( errval )
1073 {
1074 pbnIndex->setEnabled( false );
1075 pbnIndex->setText( tr( "Spatial Index Exists" ) );
1076 QMessageBox::information( this, tr( "Spatial Index" ), tr( "Creation of spatial index successful" ) );
1077 }
1078 else
1079 {
1080 QMessageBox::warning( this, tr( "Spatial Index" ), tr( "Creation of spatial index failed" ) );
1081 }
1082 }
1083}
1084
1085QString QgsVectorLayerProperties::htmlMetadata()
1086{
1087 return mLayer->htmlMetadata();
1088}
1089
1090void QgsVectorLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
1091{
1092 QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mCanvas, tr( "Select Transformation for the vector layer" ) );
1093 mLayer->setCrs( crs );
1094 mMetadataFilled = false;
1095 mMetadataWidget->crsChanged();
1096}
1097
1098void QgsVectorLayerProperties::saveMultipleStylesAs()
1099{
1100 QgsMapLayerSaveStyleDialog dlg( mLayer );
1101 dlg.setSaveOnlyCurrentStyle( false );
1102 QgsSettings settings;
1103
1104 if ( dlg.exec() )
1105 {
1106 apply();
1107
1108 // Store the original style, that we can restore at the end
1109 const QString originalStyle { mLayer->styleManager()->currentStyle() };
1110 const QListWidget *stylesWidget { dlg.stylesWidget() };
1111
1112 // Collect selected (checked) styles for export/save
1113 QStringList stylesSelected;
1114 for ( int i = 0; i < stylesWidget->count(); i++ )
1115 {
1116 if ( stylesWidget->item( i )->checkState() == Qt::CheckState::Checked )
1117 {
1118 stylesSelected.push_back( stylesWidget->item( i )->text() );
1119 }
1120 }
1121
1122 if ( !stylesSelected.isEmpty() )
1123 {
1124 int styleIndex = 0;
1125 for ( const QString &styleName : std::as_const( stylesSelected ) )
1126 {
1127 bool defaultLoadedFlag = false;
1128
1129 StyleType type = dlg.currentStyleType();
1130 mLayer->styleManager()->setCurrentStyle( styleName );
1131 switch ( type )
1132 {
1133 case QML:
1134 case SLD:
1135 {
1136 QString message;
1137 const QString filePath { dlg.outputFilePath() };
1138 const QFileInfo fi { filePath };
1139 QString safePath { QString( filePath ).replace( fi.baseName(), QStringLiteral( "%1_%2" ).arg( fi.baseName(), QgsFileUtils::stringToSafeFilename( styleName ) ) ) };
1140 if ( styleIndex > 0 && stylesSelected.count() > 1 )
1141 {
1142 int i = 1;
1143 while ( QFile::exists( safePath ) )
1144 {
1145 const QFileInfo fi { safePath };
1146 safePath = QString( safePath ).replace( '.' + fi.completeSuffix(), QStringLiteral( "_%1.%2" ).arg( QString::number( i ), fi.completeSuffix() ) );
1147 i++;
1148 }
1149 }
1150 if ( type == QML )
1151 message = mLayer->saveNamedStyle( safePath, defaultLoadedFlag, dlg.styleCategories() );
1152 else
1153 message = mLayer->saveSldStyle( safePath, defaultLoadedFlag );
1154
1155 //reset if the default style was loaded OK only
1156 if ( defaultLoadedFlag )
1157 {
1158 syncToLayer();
1159 }
1160 else
1161 {
1162 //let the user know what went wrong
1163 QMessageBox::information( this, tr( "Save Style" ), message );
1164 }
1165
1166 break;
1167 }
1168 case DatasourceDatabase:
1169 {
1170 QString infoWindowTitle = QObject::tr( "Save style '%1' to DB (%2)" )
1171 .arg( styleName, mLayer->providerType() );
1172 QString msgError;
1173
1174 QgsMapLayerSaveStyleDialog::SaveToDbSettings dbSettings = dlg.saveToDbSettings();
1175
1176 // If a name is defined, we add _1 etc. else we use the style name
1177 QString name { dbSettings.name };
1178 if ( name.isEmpty() )
1179 {
1180 name = styleName;
1181 }
1182 else
1183 {
1184 name += QStringLiteral( "_%1" ).arg( styleName );
1185 QStringList ids, names, descriptions;
1186 mLayer->listStylesInDatabase( ids, names, descriptions, msgError );
1187 int i = 1;
1188 while ( names.contains( name ) )
1189 {
1190 name = QStringLiteral( "%1 %2" ).arg( name, QString::number( i ) );
1191 i++;
1192 }
1193 }
1194
1195 QString errorMessage;
1196 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), dbSettings.name, errorMessage ) )
1197 {
1198 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ), QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1199 {
1200 return;
1201 }
1202 }
1203 else if ( !errorMessage.isEmpty() )
1204 {
1205 QMessageBox::warning( this, infoWindowTitle, errorMessage );
1206 return;
1207 }
1208
1209 mLayer->saveStyleToDatabase( name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, msgError, dlg.styleCategories() );
1210
1211 if ( !msgError.isNull() )
1212 {
1213 QMessageBox::warning( this, infoWindowTitle, msgError );
1214 }
1215 else
1216 {
1217 QMessageBox::information( this, infoWindowTitle, tr( "Style '%1' saved" ).arg( styleName ) );
1218 }
1219 break;
1220 }
1221 case UserDatabase:
1222 break;
1223 }
1224 styleIndex++;
1225 }
1226 // Restore original style
1227 mLayer->styleManager()->setCurrentStyle( originalStyle );
1228 }
1229 } // Nothing selected!
1230}
1231
1232void QgsVectorLayerProperties::aboutToShowStyleMenu()
1233{
1234 // this should be unified with QgsRasterLayerProperties::aboutToShowStyleMenu()
1235 QMenu *m = qobject_cast<QMenu *>( sender() );
1236 m->clear();
1237
1238 m->addAction( mActionLoadStyle );
1239 m->addAction( mActionSaveStyle );
1240
1241 // If we have multiple styles, offer an option to save them at once
1242 if ( mLayer->styleManager()->styles().count() > 1 )
1243 {
1244 mActionSaveStyle->setText( tr( "Save Current Style…" ) );
1245 m->addAction( mActionSaveMultipleStyles );
1246 }
1247 else
1248 {
1249 mActionSaveStyle->setText( tr( "Save Style…" ) );
1250 }
1251
1252 m->addSeparator();
1253 m->addAction( tr( "Save as Default" ), this, &QgsVectorLayerProperties::saveDefaultStyle );
1254 m->addAction( tr( "Restore Default" ), this, &QgsVectorLayerProperties::loadDefaultStyle );
1255
1256 // re-add style manager actions!
1257 m->addSeparator();
1259}
1260
1261void QgsVectorLayerProperties::mButtonAddJoin_clicked()
1262{
1263 if ( !mLayer )
1264 return;
1265
1266 QList<QgsMapLayer *> joinedLayers;
1267 const QList<QgsVectorLayerJoinInfo> &joins = mLayer->vectorJoins();
1268 joinedLayers.reserve( joins.size() );
1269 for ( int i = 0; i < joins.size(); ++i )
1270 {
1271 joinedLayers.append( joins[i].joinLayer() );
1272 }
1273
1274 QgsJoinDialog d( mLayer, joinedLayers );
1275 if ( d.exec() == QDialog::Accepted )
1276 {
1277 QgsVectorLayerJoinInfo info = d.joinInfo();
1278 //create attribute index if possible
1279 if ( d.createAttributeIndex() )
1280 {
1281 QgsVectorLayer *joinLayer = info.joinLayer();
1282 if ( joinLayer )
1283 {
1284 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1285 }
1286 }
1287 mLayer->addJoin( info );
1288 addJoinToTreeWidget( info );
1289 setPbnQueryBuilderEnabled();
1290 mSourceFieldsPropertiesDialog->init();
1291 mAttributesFormPropertiesDialog->init();
1292 }
1293}
1294
1295void QgsVectorLayerProperties::mButtonEditJoin_clicked()
1296{
1297 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1298 mJoinTreeWidget_itemDoubleClicked( currentJoinItem, 0 );
1299}
1300
1301void QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1302{
1303 if ( !mLayer || !item )
1304 {
1305 return;
1306 }
1307
1308 // if current item is a child item, we should use its parent to be able to edit join
1309 QTreeWidgetItem *currentJoinItem = item;
1310 if ( item->parent() )
1311 {
1312 currentJoinItem = item->parent();
1313 }
1314
1315
1316 QList<QgsMapLayer *> joinedLayers;
1317 QString joinLayerId = currentJoinItem->data( 0, Qt::UserRole ).toString();
1318 const QList<QgsVectorLayerJoinInfo> &joins = mLayer->vectorJoins();
1319 int j = -1;
1320 for ( int i = 0; i < joins.size(); ++i )
1321 {
1322 QgsVectorLayer *joinLayer = joins[i].joinLayer();
1323 if ( !joinLayer )
1324 continue; // invalid join (unresolved join layer)
1325
1326 if ( joinLayer->id() == joinLayerId )
1327 {
1328 j = i;
1329 }
1330 else
1331 {
1332 // remove already joined layers from possible list to be displayed in dialog
1333 joinedLayers.append( joinLayer );
1334 }
1335 }
1336 if ( j == -1 )
1337 {
1338 return;
1339 }
1340
1341 QgsJoinDialog d( mLayer, joinedLayers );
1342 d.setWindowTitle( tr( "Edit Vector Join" ) );
1343 d.setJoinInfo( joins[j] );
1344
1345 if ( d.exec() == QDialog::Accepted )
1346 {
1347 QgsVectorLayerJoinInfo info = d.joinInfo();
1348
1349 // remove old join
1350 mLayer->removeJoin( joinLayerId );
1351 int idx = mJoinTreeWidget->indexOfTopLevelItem( item );
1352 mJoinTreeWidget->takeTopLevelItem( idx );
1353
1354 // add the new edited
1355
1356 //create attribute index if possible
1357 if ( d.createAttributeIndex() )
1358 {
1359 QgsVectorLayer *joinLayer = info.joinLayer();
1360 if ( joinLayer )
1361 {
1362 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1363 }
1364 }
1365 mLayer->addJoin( info );
1366 addJoinToTreeWidget( info, idx );
1367
1368 setPbnQueryBuilderEnabled();
1369 mSourceFieldsPropertiesDialog->init();
1370 mAttributesFormPropertiesDialog->init();
1371 }
1372}
1373
1374void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorLayerJoinInfo &join, const int insertIndex )
1375{
1376 QTreeWidgetItem *joinItem = new QTreeWidgetItem();
1377 joinItem->setFlags( Qt::ItemIsEnabled );
1378
1379 QgsVectorLayer *joinLayer = join.joinLayer();
1380 if ( !mLayer || !joinLayer )
1381 {
1382 return;
1383 }
1384
1385 joinItem->setText( 0, tr( "Join layer" ) );
1386 if ( mLayer->auxiliaryLayer() && mLayer->auxiliaryLayer()->id() == join.joinLayerId() )
1387 {
1388 return;
1389 }
1390
1391 joinItem->setText( 1, joinLayer->name() );
1392
1393 QFont f = joinItem->font( 0 );
1394 f.setBold( true );
1395 joinItem->setFont( 0, f );
1396 joinItem->setFont( 1, f );
1397
1398 joinItem->setData( 0, Qt::UserRole, join.joinLayerId() );
1399
1400 QTreeWidgetItem *childJoinField = new QTreeWidgetItem();
1401 childJoinField->setText( 0, tr( "Join field" ) );
1402 childJoinField->setText( 1, join.joinFieldName() );
1403 childJoinField->setFlags( Qt::ItemIsEnabled );
1404 joinItem->addChild( childJoinField );
1405
1406 QTreeWidgetItem *childTargetField = new QTreeWidgetItem();
1407 childTargetField->setText( 0, tr( "Target field" ) );
1408 childTargetField->setText( 1, join.targetFieldName() );
1409 joinItem->addChild( childTargetField );
1410
1411 QTreeWidgetItem *childMemCache = new QTreeWidgetItem();
1412 childMemCache->setText( 0, tr( "Cache join layer in virtual memory" ) );
1413 if ( join.isUsingMemoryCache() )
1414 childMemCache->setText( 1, QChar( 0x2714 ) );
1415 joinItem->addChild( childMemCache );
1416
1417 QTreeWidgetItem *childDynForm = new QTreeWidgetItem();
1418 childDynForm->setText( 0, tr( "Dynamic form" ) );
1419 if ( join.isDynamicFormEnabled() )
1420 childDynForm->setText( 1, QChar( 0x2714 ) );
1421 joinItem->addChild( childDynForm );
1422
1423 QTreeWidgetItem *childEditable = new QTreeWidgetItem();
1424 childEditable->setText( 0, tr( "Editable join layer" ) );
1425 if ( join.isEditable() )
1426 childEditable->setText( 1, QChar( 0x2714 ) );
1427 joinItem->addChild( childEditable );
1428
1429 QTreeWidgetItem *childUpsert = new QTreeWidgetItem();
1430 childUpsert->setText( 0, tr( "Upsert on edit" ) );
1431 if ( join.hasUpsertOnEdit() )
1432 childUpsert->setText( 1, QChar( 0x2714 ) );
1433 joinItem->addChild( childUpsert );
1434
1435 QTreeWidgetItem *childCascade = new QTreeWidgetItem();
1436 childCascade->setText( 0, tr( "Delete cascade" ) );
1437 if ( join.hasCascadedDelete() )
1438 childCascade->setText( 1, QChar( 0x2714 ) );
1439 joinItem->addChild( childCascade );
1440
1441 QTreeWidgetItem *childPrefix = new QTreeWidgetItem();
1442 childPrefix->setText( 0, tr( "Custom field name prefix" ) );
1443 childPrefix->setText( 1, join.prefix() );
1444 joinItem->addChild( childPrefix );
1445
1446 QTreeWidgetItem *childFields = new QTreeWidgetItem();
1447 childFields->setText( 0, tr( "Joined fields" ) );
1448 const QStringList *list = join.joinFieldNamesSubset();
1449 if ( list )
1450 childFields->setText( 1, QLocale().toString( list->count() ) );
1451 else
1452 childFields->setText( 1, tr( "all" ) );
1453 joinItem->addChild( childFields );
1454
1455 if ( insertIndex >= 0 )
1456 mJoinTreeWidget->insertTopLevelItem( insertIndex, joinItem );
1457 else
1458 mJoinTreeWidget->addTopLevelItem( joinItem );
1459
1460 mJoinTreeWidget->setCurrentItem( joinItem );
1461 mJoinTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1462}
1463
1464QgsExpressionContext QgsVectorLayerProperties::createExpressionContext() const
1465{
1466 return mContext;
1467}
1468
1469void QgsVectorLayerProperties::openPanel( QgsPanelWidget *panel )
1470{
1471 QDialog *dlg = new QDialog();
1472 QString key = QStringLiteral( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
1473 QgsSettings settings;
1474 dlg->restoreGeometry( settings.value( key ).toByteArray() );
1475 dlg->setWindowTitle( panel->panelTitle() );
1476 dlg->setLayout( new QVBoxLayout() );
1477 dlg->layout()->addWidget( panel );
1478 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
1479 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
1480 dlg->layout()->addWidget( buttonBox );
1481 dlg->exec();
1482 settings.setValue( key, dlg->saveGeometry() );
1483 panel->acceptPanel();
1484}
1485
1486void QgsVectorLayerProperties::mButtonRemoveJoin_clicked()
1487{
1488 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1489 // if current item is a child item, we should use its parent to be able to remove join
1490 if ( currentJoinItem && currentJoinItem->parent() )
1491 {
1492 currentJoinItem = currentJoinItem->parent();
1493 }
1494
1495 if ( !mLayer || !currentJoinItem )
1496 {
1497 return;
1498 }
1499
1500 mLayer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
1501 mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
1502 setPbnQueryBuilderEnabled();
1503 mSourceFieldsPropertiesDialog->init();
1504 mAttributesFormPropertiesDialog->init();
1505}
1506
1507
1508void QgsVectorLayerProperties::mButtonAddWmsDimension_clicked()
1509{
1510 if ( !mLayer )
1511 return;
1512
1513 // get wms dimensions name
1514 QStringList alreadyDefinedDimensions;
1515 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1516 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1517 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : dims )
1518 {
1519 alreadyDefinedDimensions << dim.name;
1520 }
1521
1522 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1523 if ( d.exec() == QDialog::Accepted )
1524 {
1526 // save dimension
1527 serverProperties->addWmsDimension( info );
1528 addWmsDimensionInfoToTreeWidget( info );
1529 }
1530}
1531
1532void QgsVectorLayerProperties::mButtonEditWmsDimension_clicked()
1533{
1534 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1535 mWmsDimensionsTreeWidget_itemDoubleClicked( currentWmsDimensionItem, 0 );
1536}
1537
1538void QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1539{
1540 if ( !mLayer || !item )
1541 {
1542 return;
1543 }
1544
1545 QString wmsDimName = item->data( 0, Qt::UserRole ).toString();
1546 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1547 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1548 QStringList alreadyDefinedDimensions;
1549 int j = -1;
1550 for ( int i = 0; i < dims.size(); ++i )
1551 {
1552 QString dimName = dims[i].name;
1553 if ( dimName == wmsDimName )
1554 {
1555 j = i;
1556 }
1557 else
1558 {
1559 alreadyDefinedDimensions << dimName;
1560 }
1561 }
1562 if ( j == -1 )
1563 {
1564 return;
1565 }
1566
1567 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1568 d.setWindowTitle( tr( "Edit WMS Dimension" ) );
1569 d.setInfo( dims[j] );
1570
1571 if ( d.exec() == QDialog::Accepted )
1572 {
1574
1575 // remove old
1576 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1577 serverProperties->removeWmsDimension( wmsDimName );
1578 int idx = mWmsDimensionsTreeWidget->indexOfTopLevelItem( item );
1579 mWmsDimensionsTreeWidget->takeTopLevelItem( idx );
1580
1581 // save new
1582 serverProperties->addWmsDimension( info );
1583 addWmsDimensionInfoToTreeWidget( info, idx );
1584 }
1585}
1586
1587void QgsVectorLayerProperties::addWmsDimensionInfoToTreeWidget( const QgsMapLayerServerProperties::WmsDimensionInfo &wmsDim, const int insertIndex )
1588{
1589 QTreeWidgetItem *wmsDimensionItem = new QTreeWidgetItem();
1590 wmsDimensionItem->setFlags( Qt::ItemIsEnabled );
1591
1592 wmsDimensionItem->setText( 0, tr( "Dimension" ) );
1593 wmsDimensionItem->setText( 1, wmsDim.name );
1594
1595 QFont f = wmsDimensionItem->font( 0 );
1596 f.setBold( true );
1597 wmsDimensionItem->setFont( 0, f );
1598 wmsDimensionItem->setFont( 1, f );
1599
1600 wmsDimensionItem->setData( 0, Qt::UserRole, wmsDim.name );
1601
1602 QTreeWidgetItem *childWmsDimensionField = new QTreeWidgetItem();
1603 childWmsDimensionField->setText( 0, tr( "Field" ) );
1604 childWmsDimensionField->setText( 1, wmsDim.fieldName );
1605 childWmsDimensionField->setFlags( Qt::ItemIsEnabled );
1606 wmsDimensionItem->addChild( childWmsDimensionField );
1607
1608 QTreeWidgetItem *childWmsDimensionEndField = new QTreeWidgetItem();
1609 childWmsDimensionEndField->setText( 0, tr( "End field" ) );
1610 childWmsDimensionEndField->setText( 1, wmsDim.endFieldName );
1611 childWmsDimensionEndField->setFlags( Qt::ItemIsEnabled );
1612 wmsDimensionItem->addChild( childWmsDimensionEndField );
1613
1614 QTreeWidgetItem *childWmsDimensionUnits = new QTreeWidgetItem();
1615 childWmsDimensionUnits->setText( 0, tr( "Units" ) );
1616 childWmsDimensionUnits->setText( 1, wmsDim.units );
1617 childWmsDimensionUnits->setFlags( Qt::ItemIsEnabled );
1618 wmsDimensionItem->addChild( childWmsDimensionUnits );
1619
1620 QTreeWidgetItem *childWmsDimensionUnitSymbol = new QTreeWidgetItem();
1621 childWmsDimensionUnitSymbol->setText( 0, tr( "Unit symbol" ) );
1622 childWmsDimensionUnitSymbol->setText( 1, wmsDim.unitSymbol );
1623 childWmsDimensionUnitSymbol->setFlags( Qt::ItemIsEnabled );
1624 wmsDimensionItem->addChild( childWmsDimensionUnitSymbol );
1625
1626 QTreeWidgetItem *childWmsDimensionDefaultValue = new QTreeWidgetItem();
1627 childWmsDimensionDefaultValue->setText( 0, tr( "Default display" ) );
1628 childWmsDimensionDefaultValue->setText( 1, QgsMapLayerServerProperties::wmsDimensionDefaultDisplayLabels().value( wmsDim.defaultDisplayType ) );
1629 childWmsDimensionDefaultValue->setFlags( Qt::ItemIsEnabled );
1630 wmsDimensionItem->addChild( childWmsDimensionDefaultValue );
1631
1632 QTreeWidgetItem *childWmsDimensionRefValue = new QTreeWidgetItem();
1633 childWmsDimensionRefValue->setText( 0, tr( "Reference value" ) );
1634 childWmsDimensionRefValue->setText( 1, wmsDim.referenceValue.toString() );
1635 childWmsDimensionRefValue->setFlags( Qt::ItemIsEnabled );
1636 wmsDimensionItem->addChild( childWmsDimensionRefValue );
1637
1638 if ( insertIndex >= 0 )
1639 mWmsDimensionsTreeWidget->insertTopLevelItem( insertIndex, wmsDimensionItem );
1640 else
1641 mWmsDimensionsTreeWidget->addTopLevelItem( wmsDimensionItem );
1642
1643 mWmsDimensionsTreeWidget->setCurrentItem( wmsDimensionItem );
1644 mWmsDimensionsTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1645}
1646
1647void QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked()
1648{
1649 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1650 if ( !mLayer || !currentWmsDimensionItem )
1651 {
1652 return;
1653 }
1654
1655 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1656 serverProperties->removeWmsDimension( currentWmsDimensionItem->data( 0, Qt::UserRole ).toString() );
1657 mWmsDimensionsTreeWidget->takeTopLevelItem( mWmsDimensionsTreeWidget->indexOfTopLevelItem( currentWmsDimensionItem ) );
1658}
1659
1660
1661void QgsVectorLayerProperties::updateSymbologyPage()
1662{
1663 //find out the type of renderer in the vectorlayer, create a dialog with these settings and add it to the form
1664 delete mRendererDialog;
1665 mRendererDialog = nullptr;
1666
1667 if ( mLayer->renderer() )
1668 {
1669 mRendererDialog = new QgsRendererPropertiesDialog( mLayer, QgsStyle::defaultStyle(), true, this );
1670 mRendererDialog->setDockMode( false );
1671 QgsSymbolWidgetContext context;
1672 context.setMapCanvas( mCanvas );
1673 context.setMessageBar( mMessageBar );
1674 mRendererDialog->setContext( context );
1675 connect( mRendererDialog, &QgsRendererPropertiesDialog::showPanel, this, &QgsVectorLayerProperties::openPanel );
1676 connect( mRendererDialog, &QgsRendererPropertiesDialog::layerVariablesChanged, this, &QgsVectorLayerProperties::updateVariableEditor );
1677 connect( mRendererDialog, &QgsRendererPropertiesDialog::widgetChanged, this, [=] { updateAuxiliaryStoragePage(); } );
1678 }
1679 else
1680 {
1681 mOptsPage_Style->setEnabled( false ); // hide symbology item
1682 }
1683
1684 if ( mRendererDialog )
1685 {
1686 mRendererDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
1687 widgetStackRenderers->addWidget( mRendererDialog );
1688 widgetStackRenderers->setCurrentWidget( mRendererDialog );
1689 widgetStackRenderers->currentWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
1690 }
1691}
1692
1693void QgsVectorLayerProperties::setPbnQueryBuilderEnabled()
1694{
1695 pbnQueryBuilder->setEnabled( mLayer && mLayer->dataProvider() && mLayer->dataProvider()->supportsSubsetString() && !mLayer->isEditable() );
1696
1697 if ( mLayer && mLayer->isEditable() )
1698 {
1699 pbnQueryBuilder->setToolTip( tr( "Stop editing mode to enable this." ) );
1700 }
1701}
1702
1703void QgsVectorLayerProperties::pbnUpdateExtents_clicked()
1704{
1705 mLayer->updateExtents( true ); // force update whatever options activated
1706 mMetadataFilled = false;
1707}
1708
1710{
1712
1713 if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) && !mMetadataFilled )
1714 {
1715 // set the metadata contents (which can be expensive)
1716 teMetadataViewer->clear();
1717 teMetadataViewer->setHtml( htmlMetadata() );
1718 mMetadataFilled = true;
1719 }
1720 else if ( index == mOptStackedWidget->indexOf( mOptsPage_SourceFields ) || index == mOptStackedWidget->indexOf( mOptsPage_Joins ) )
1721 {
1722 // store any edited attribute form field configuration to prevent loss of edits when adding/removing fields and/or joins
1723 mAttributesFormPropertiesDialog->store();
1724 }
1725
1726 resizeAlltabs( index );
1727}
1728
1729void QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled( bool checked )
1730{
1731 const QgsVectorDataProvider *provider = mLayer->dataProvider();
1732 if ( !( provider && ( provider->capabilities() & Qgis::VectorProviderCapability::SimplifyGeometries ) != 0 ) )
1733 {
1734 mSimplifyDrawingAtProvider->setEnabled( false );
1735 }
1736 else
1737 {
1738 mSimplifyDrawingAtProvider->setEnabled( checked );
1739 }
1740}
1741
1742void QgsVectorLayerProperties::updateVariableEditor()
1743{
1744 QgsExpressionContext context;
1745 mVariableEditor->setContext( &context );
1746 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
1747 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
1748 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
1749 mVariableEditor->reloadContext();
1750 mVariableEditor->setEditableScopeIndex( 2 );
1751}
1752
1753void QgsVectorLayerProperties::showHelp()
1754{
1755 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
1756
1757 if ( helpPage.isValid() )
1758 {
1759 QgsHelp::openHelp( helpPage.toString() );
1760 }
1761 else
1762 {
1763 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html" ) );
1764 }
1765}
1766
1767void QgsVectorLayerProperties::updateAuxiliaryStoragePage()
1768{
1769 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1770
1771 if ( alayer )
1772 {
1773 // set widgets to enable state
1774 mAuxiliaryStorageInformationGrpBox->setEnabled( true );
1775 mAuxiliaryStorageFieldsGrpBox->setEnabled( true );
1776
1777 // update key
1778 mAuxiliaryStorageKeyLineEdit->setText( alayer->joinInfo().targetFieldName() );
1779
1780 // update feature count
1781 const qlonglong features = alayer->featureCount();
1782 mAuxiliaryStorageFeaturesLineEdit->setText( QLocale().toString( features ) );
1783
1784 // update actions
1785 mAuxiliaryLayerActionClear->setEnabled( true );
1786 mAuxiliaryLayerActionDelete->setEnabled( true );
1787 mAuxiliaryLayerActionExport->setEnabled( true );
1788 mAuxiliaryLayerActionNew->setEnabled( false );
1789
1790 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1791 if ( alayer )
1792 {
1793 const int fields = alayer->auxiliaryFields().count();
1794 mAuxiliaryStorageFieldsLineEdit->setText( QLocale().toString( fields ) );
1795
1796 // add fields
1797 mAuxiliaryStorageFieldsTree->clear();
1798 for ( const QgsField &field : alayer->auxiliaryFields() )
1799 {
1801 QTreeWidgetItem *item = new QTreeWidgetItem();
1802
1803 item->setText( 0, prop.origin() );
1804 item->setText( 1, prop.name() );
1805 item->setText( 2, prop.comment() );
1806 item->setText( 3, field.typeName() );
1807 item->setText( 4, field.name() );
1808
1809 mAuxiliaryStorageFieldsTree->addTopLevelItem( item );
1810 }
1811 }
1812 }
1813 else
1814 {
1815 mAuxiliaryStorageInformationGrpBox->setEnabled( false );
1816 mAuxiliaryStorageFieldsGrpBox->setEnabled( false );
1817
1818 mAuxiliaryLayerActionClear->setEnabled( false );
1819 mAuxiliaryLayerActionDelete->setEnabled( false );
1820 mAuxiliaryLayerActionExport->setEnabled( false );
1821 mAuxiliaryLayerActionNew->setEnabled( true );
1822
1823 mAuxiliaryStorageFieldsTree->clear();
1824 mAuxiliaryStorageKeyLineEdit->setText( QString() );
1825 mAuxiliaryStorageFieldsLineEdit->setText( QString() );
1826 mAuxiliaryStorageFeaturesLineEdit->setText( QString() );
1827 }
1828}
1829
1830void QgsVectorLayerProperties::onAuxiliaryLayerNew()
1831{
1832 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1833
1834 if ( alayer )
1835 return;
1836
1837 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
1838 if ( dlg.exec() == QDialog::Accepted )
1839 {
1840 updateAuxiliaryStoragePage();
1841 }
1842}
1843
1844void QgsVectorLayerProperties::onAuxiliaryLayerClear()
1845{
1846 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1847
1848 if ( !alayer )
1849 return;
1850
1851 const QString msg = tr( "Are you sure you want to clear auxiliary data for %1?" ).arg( mLayer->name() );
1852 QMessageBox::StandardButton reply;
1853 reply = QMessageBox::question( this, "Clear Auxiliary Data", msg, QMessageBox::Yes | QMessageBox::No );
1854
1855 if ( reply == QMessageBox::Yes )
1856 {
1857 QApplication::setOverrideCursor( Qt::WaitCursor );
1858 alayer->clear();
1859 QApplication::restoreOverrideCursor();
1860 updateAuxiliaryStoragePage();
1861 mLayer->triggerRepaint();
1862 }
1863}
1864
1865void QgsVectorLayerProperties::onAuxiliaryLayerDelete()
1866{
1867 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1868 if ( !alayer )
1869 return;
1870
1871 const QString msg = tr( "Are you sure you want to delete auxiliary storage for %1?" ).arg( mLayer->name() );
1872 QMessageBox::StandardButton reply;
1873 reply = QMessageBox::question( this, "Delete Auxiliary Storage", msg, QMessageBox::Yes | QMessageBox::No );
1874
1875 if ( reply == QMessageBox::Yes )
1876 {
1877 QApplication::setOverrideCursor( Qt::WaitCursor );
1878 QgsDataSourceUri uri( alayer->source() );
1879
1880 // delete each attribute to correctly update layer settings and data
1881 // defined buttons
1882 while ( alayer->auxiliaryFields().size() > 0 )
1883 {
1884 QgsField aField = alayer->auxiliaryFields()[0];
1885 deleteAuxiliaryField( alayer->fields().indexOf( aField.name() ) );
1886 }
1887
1888 mLayer->setAuxiliaryLayer(); // remove auxiliary layer
1890 QApplication::restoreOverrideCursor();
1891 updateAuxiliaryStoragePage();
1892 mLayer->triggerRepaint();
1893 }
1894}
1895
1896void QgsVectorLayerProperties::onAuxiliaryLayerDeleteField()
1897{
1898 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1899 if ( !alayer )
1900 return;
1901
1902 QList<QTreeWidgetItem *> items = mAuxiliaryStorageFieldsTree->selectedItems();
1903 if ( items.count() < 1 )
1904 return;
1905
1906 // get auxiliary field name and index from item
1907 const QTreeWidgetItem *item = items[0];
1909 def.setOrigin( item->text( 0 ) );
1910 def.setName( item->text( 1 ) );
1911 def.setComment( item->text( 2 ) );
1912
1913 const QString fieldName = QgsAuxiliaryLayer::nameFromProperty( def );
1914
1915 const int index = mLayer->auxiliaryLayer()->fields().indexOf( fieldName );
1916 if ( index < 0 )
1917 return;
1918
1919 // should be only 1 field
1920 const QString msg = tr( "Are you sure you want to delete auxiliary field %1 for %2?" ).arg( item->text( 1 ), item->text( 0 ) );
1921
1922 QMessageBox::StandardButton reply;
1923 const QString title = QObject::tr( "Delete Auxiliary Field" );
1924 reply = QMessageBox::question( this, title, msg, QMessageBox::Yes | QMessageBox::No );
1925
1926 if ( reply == QMessageBox::Yes )
1927 {
1928 QApplication::setOverrideCursor( Qt::WaitCursor );
1929 deleteAuxiliaryField( index );
1930 mLayer->triggerRepaint();
1931 QApplication::restoreOverrideCursor();
1932 }
1933}
1934
1935void QgsVectorLayerProperties::onAuxiliaryLayerAddField()
1936{
1937 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
1938 if ( !alayer )
1939 return;
1940
1941 QgsNewAuxiliaryFieldDialog dlg( QgsPropertyDefinition(), mLayer, false );
1942 if ( dlg.exec() == QDialog::Accepted )
1943 {
1944 updateAuxiliaryStoragePage();
1945 }
1946}
1947
1948void QgsVectorLayerProperties::deleteAuxiliaryField( int index )
1949{
1950 if ( !mLayer->auxiliaryLayer() )
1951 return;
1952
1953 int key = mLayer->auxiliaryLayer()->propertyFromIndex( index );
1955
1956 if ( mLayer->auxiliaryLayer()->deleteAttribute( index ) )
1957 {
1958 mLayer->updateFields();
1959
1960 // immediately deactivate data defined button
1961 if ( key >= 0 && def.origin().compare( "labeling", Qt::CaseInsensitive ) == 0
1962 && labelingDialog
1963 && labelingDialog->labelingGui() )
1964 {
1965 labelingDialog->labelingGui()->deactivateField( static_cast<QgsPalLayerSettings::Property>( key ) );
1966 }
1967
1968 updateAuxiliaryStoragePage();
1969 mSourceFieldsPropertiesDialog->init();
1970 }
1971 else
1972 {
1973 const QString title = QObject::tr( "Delete Auxiliary Field" );
1974 const QString errors = mLayer->auxiliaryLayer()->commitErrors().join( QLatin1String( "\n " ) );
1975 const QString msg = QObject::tr( "Unable to remove auxiliary field (%1)" ).arg( errors );
1976 mMessageBar->pushMessage( title, msg, Qgis::MessageLevel::Warning );
1977 }
1978}
1979
1980bool QgsVectorLayerProperties::eventFilter( QObject *obj, QEvent *ev )
1981{
1982 // If the map tip preview container is resized, resize the map tip
1983 if ( obj == mMapTipPreviewContainer && ev->type() == QEvent::Resize )
1984 {
1985 resizeMapTip();
1986 }
1987 return QgsOptionsDialogBase::eventFilter( obj, ev );
1988}
1989
1990void QgsVectorLayerProperties::initMapTipPreview()
1991{
1992 // HTML editor and preview are in a splitter. By default, the editor takes 2/3 of the space
1993 mMapTipSplitter->setSizes( { 400, 200 } );
1994 // Event filter is used to resize the map tip when the container is resized
1995 mMapTipPreviewContainer->installEventFilter( this );
1996
1997 // Note: there's quite a bit of overlap between this and the code in QgsMapTip::showMapTip
1998 // Create the WebView
1999 mMapTipPreview = new QgsWebView( mMapTipPreviewContainer );
2000
2001#if WITH_QTWEBKIT
2002 mMapTipPreview->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks ); //Handle link clicks by yourself
2003 mMapTipPreview->setContextMenuPolicy( Qt::NoContextMenu ); //No context menu is allowed if you don't need it
2004 connect( mMapTipPreview, &QWebView::loadFinished, this, &QgsVectorLayerProperties::resizeMapTip );
2005#endif
2006
2007 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
2008 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
2009 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );
2010
2011 // Disable scrollbars, avoid random resizing issues
2012 mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
2013 mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
2014
2015 // Update the map tip preview when the expression or the map tip template changes
2016 connect( mMapTipWidget, &QgsCodeEditorHTML::textChanged, this, &QgsVectorLayerProperties::updateMapTipPreview );
2017 connect( mDisplayExpressionWidget, qOverload<const QString &>( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsVectorLayerProperties::updateMapTipPreview );
2018}
2019
2020void QgsVectorLayerProperties::updateMapTipPreview()
2021{
2022 mMapTipPreview->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
2023 const QString htmlContent = QgsMapTip::vectorMapTipPreviewText( mLayer, mCanvas, mMapTipWidget->text(), mDisplayExpressionWidget->asExpression() );
2024 mMapTipPreview->setHtml( htmlContent );
2025}
2026
2027void QgsVectorLayerProperties::resizeMapTip()
2028{
2029 // Ensure the map tip is not bigger than the container
2030 mMapTipPreview->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
2031#if WITH_QTWEBKIT
2032 // Get the content size
2033 const QWebElement container = mMapTipPreview->page()->mainFrame()->findFirstElement(
2034 QStringLiteral( "#QgsWebViewContainer" )
2035 );
2036 const int width = container.geometry().width();
2037 const int height = container.geometry().height();
2038 mMapTipPreview->resize( width, height );
2039
2040 // Move the map tip to the center of the container
2041 mMapTipPreview->move( ( mMapTipPreviewContainer->width() - mMapTipPreview->width() ) / 2, ( mMapTipPreviewContainer->height() - mMapTipPreview->height() ) / 2 );
2042
2043#else
2044 mMapTipPreview->adjustSize();
2045#endif
2046}
@ SimplifyGeometries
Supports simplification of geometries on provider side according to a distance tolerance.
@ SelectEncoding
Allows user to select encoding.
@ CreateSpatialIndex
Allows creation of spatial index.
QFlags< VectorRenderingSimplificationFlag > VectorRenderingSimplificationFlags
Simplification flags for vector feature rendering.
Definition qgis.h:2904
@ Present
A valid spatial index exists for the source.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
@ NoSimplification
No simplification can be applied.
@ GeometrySimplification
The geometries can be simplified using the current map2pixel context state.
VectorSimplificationAlgorithm
Simplification algorithms for vector features.
Definition qgis.h:2873
@ Distance
The simplification uses the distance between points to remove duplicate points.
@ SnapToGrid
The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ Warning
Warning message.
Definition qgis.h:156
static QString defaultProjectScales()
A string with default project scales.
Definition qgis.cpp:253
@ Polygon
Polygons.
@ Unknown
Unknown types.
@ Null
No geometry.
QFlags< DataProviderReadFlag > DataProviderReadFlags
Flags which control data provider construction.
Definition qgis.h:450
QFlags< VectorProviderCapability > VectorProviderCapabilities
Vector data provider capabilities.
Definition qgis.h:500
@ Marker
Marker symbol.
@ Line
Line symbol.
@ Fill
Fill symbol.
@ CustomColor
Use default symbol with a custom selection color.
@ CustomSymbol
Use a custom symbol.
@ Default
Use default symbol and selection colors.
void clearActions()
Removes all actions.
QUuid addAction(Qgis::AttributeActionType type, const QString &name, const QString &command, bool capture=false)
Add an action with the given name and action details.
Utility class that encapsulates an action based on vector attributes.
Definition qgsaction.h:37
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QRegularExpression shortNameRegularExpression()
Returns the short name regular expression for line edit validator.
void init(const QgsActionManager &action, const QgsAttributeTableConfig &attributeTableConfig)
QList< QgsAction > actions() const
QgsAttributeTableConfig::ActionWidgetStyle attributeTableWidgetStyle() const
This is a container for configuration of the attribute table.
@ Action
This column represents an action widget.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void setActionWidgetStyle(ActionWidgetStyle actionWidgetStyle)
Set the style of the action widget.
void setColumns(const QVector< QgsAttributeTableConfig::ColumnConfig > &columns)
Set the list of columns visible in the attribute table.
void store()
Stores currently opened widget configuration.
void apply()
Applies the attribute from properties to the vector layer.
Class allowing to manage the auxiliary storage for a vector layer.
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
static QgsPropertyDefinition propertyDefinitionFromField(const QgsField &field)
Returns the property definition from an auxiliary field.
bool clear()
Deletes all features from the layer.
bool deleteAttribute(int attr) override
Removes attribute from the layer and commits changes.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
int propertyFromIndex(int index) const
Returns the underlying property key for the field index.
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
QgsPropertyDefinition propertyDefinitionFromIndex(int index) const
Returns the property definition for the underlying field index.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
This class represents a coordinate reference system (CRS).
virtual bool supportsSubsetString() const
Returns true if the provider supports setting of subset strings.
Class for storing the component parts of a RDBMS data source URI (e.g.
static bool run(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr, const QString &windowTitle=QString())
Runs the dialog (if required) prompting for the desired transform to use from sourceCrs to destinatio...
void syncToOwnLayer()
Updates the widget to reflect the layer's current diagram settings.
void apply() override
Saves the labeling configuration and immediately updates the map canvas to reflect the changes.
void auxiliaryFieldCreated()
Emitted when an auxiliary field is created.
A generic dialog for building expression strings.
static void setLayerVariables(QgsMapLayer *layer, const QVariantMap &variables)
Sets all layer context variables.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
bool forceRasterRender() const
Returns whether the renderer must render as a raster.
void setForceRasterRender(bool forceRaster)
Sets whether the renderer should be rendered to a raster destination.
double referenceScale() const
Returns the symbology reference scale.
void setReferenceScale(double scale)
Sets the symbology reference scale.
virtual Qgis::SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QString name
Definition qgsfield.h:62
int count
Definition qgsfields.h:50
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
static QString stringToSafeFilename(const QString &string)
Converts a string to a safe filename, replacing characters which are not safe for filenames with an '...
static QgsProviderSourceWidgetProviderRegistry * sourceWidgetProviderRegistry()
Returns the registry of provider source widget providers.
Definition qgsgui.cpp:120
static QgsSubsetStringEditorProviderRegistry * subsetStringEditorProviderRegistry()
Returns the registry of subset string editors of data providers.
Definition qgsgui.cpp:115
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
Master widget for configuration of labeling of a vector layer.
void adaptToLayer()
reload the settings shown in the dialog from the current layer
QgsLabelingGui * labelingGui()
Returns the labeling gui widget or nullptr if none.
void auxiliaryFieldCreated()
Emitted when an auxiliary field is created.
void writeSettingsToLayer()
save config to layer
Base class for "layer properties" dialogs, containing common utilities for handling functionality in ...
QPushButton * mBtnStyle
Style button.
void saveMetadataToFile()
Allows the user to save the layer's metadata as a file.
virtual void rollback()
Rolls back changes made to the layer.
void optionsStackedWidget_CurrentChanged(int index) override
QList< QgsMapLayerConfigWidget * > mConfigWidgets
Layer config widgets.
void setMetadataWidget(QgsMetadataWidget *widget, QWidget *page)
Sets the metadata widget and page associated with the dialog.
void loadDefaultStyle()
Reloads the default style for the layer.
void saveStyleAs()
Saves a style when appriate button is pressed.
void loadStyle()
Triggers a dialog to load a saved style.
QgsMapCanvas * mCanvas
Associated map canvas.
void loadDefaultMetadata()
Reloads the default layer metadata for the layer.
void loadMetadataFromFile()
Allows the user to load layer metadata from a file.
void saveDefaultStyle()
Saves the default style when appropriate button is pressed.
QPushButton * mBtnMetadata
Metadata button.
void initialize()
Initialize the dialog.
void saveMetadataAsDefault()
Saves the current layer metadata as the default for the layer.
void openUrl(const QUrl &url)
Handles opening a url from the dialog.
QgsLayerTreeFilterProxyModel is a sort filter proxy model to easily reproduce the legend/layer tree i...
QList< QgsMapLayer * > checkedLayers() const
Returns the checked layers.
void setLayerTreeModel(QgsLayerTreeModel *layerTreeModel)
Sets the layer tree model.
void setCheckedLayers(const QList< QgsMapLayer * > layers)
Initialize the list of checked layers.
The QgsLayerTreeModel class is model implementation for Qt item views framework.
Map canvas is a class for displaying all GIS data types on a canvas.
QColor selectionColor() const
Returns color for selected features.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
double scale() const
Returns the last reported scale of the canvas.
A panel widget that can be shown in the map style dock.
This class models dependencies with or between map layers.
The QgsMapLayerSaveStyleDialog class provides the UI to save the current style or multiple styles int...
Manages QGIS Server properties for a map layer.
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layerused by QGIS Server in GetCapabilities request.
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
void setAttributionUrl(const QString &url)
Sets the attribution url of the layer used by QGIS Server in GetCapabilities request.
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request.
void setShortName(const QString &name)
Sets the short name of the layer used by QGIS Server to identify the layer.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString keywordList() const
Returns the keyword list of the layerused by QGIS Server in GetCapabilities request.
QString wfsTitle() const
Returns the optional WFS title if set or the title of the layer used by QGIS WFS in GetCapabilities r...
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
void setKeywordList(const QString &keywords)
Sets the keywords list of the layerused by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
void setWfsTitle(const QString &title)
Sets the title of the layer used by QGIS Server in WFS GetCapabilities request.
QString abstract() const
Returns the abstract of the layerused by QGIS Server in GetCapabilities request.
void addStyleManagerActions(QMenu *m, QgsMapLayer *layer)
adds actions to the menu in accordance to the layer
static QgsMapLayerStyleGuiUtils * instance()
returns a singleton instance of this class
QString currentStyle() const
Returns name of the current style.
QStringList styles() const
Returns list of all defined style names.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
void setRefreshOnNotifyEnabled(bool enabled)
Set whether provider notification is connected to triggerRepaint.
virtual QString saveSldStyle(const QString &uri, bool &resultFlag) const
Saves the properties of this layer to an SLD format file.
QString source() const
Returns the source for the layer.
void setLegendUrl(const QString &legendUrl)
Sets the URL for the layer's legend.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
QgsCoordinateReferenceSystem crs
Definition qgsmaplayer.h:83
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
void setDataSource(const QString &dataSource, const QString &baseName=QString(), const QString &provider=QString(), bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
QString id
Definition qgsmaplayer.h:79
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition qgsmaplayer.h:82
bool isRefreshOnNotifyEnabled() const
Returns true if the refresh on provider nofification is enabled.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Saves named and sld style of the layer to the style table in the db.
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
void setRefreshOnNofifyMessage(const QString &message)
Set the notification message that triggers repaint If refresh on notification is enabled,...
void setName(const QString &name)
Set the display name of the layer.
QString refreshOnNotifyMessage() const
Returns the message that should be notified by the provider to triggerRepaint.
void setMapTipsEnabled(bool enabled)
Enable or disable map tips for this layer.
double minimumScale() const
Returns the minimum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
QString legendUrl() const
Returns the URL for the layer's legend.
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
virtual QString saveNamedStyle(const QString &uri, bool &resultFlag, StyleCategories categories=AllStyleCategories)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
bool mapTipsEnabled
Definition qgsmaplayer.h:90
double maximumScale() const
Returns the maximum map scale (i.e.
QString mapTipTemplate
Definition qgsmaplayer.h:89
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
The QgsMapSettings class contains configuration for rendering of the map.
static QString vectorMapTipPreviewText(QgsMapLayer *layer, QgsMapCanvas *mapCanvas, const QString &mapTemplate, const QString &displayExpression)
Returns the html that would be displayed in a maptip for a given layer.
A bar for displaying non-blocking messages to the user.
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
A wizard to edit metadata on a map layer.
void acceptMetadata()
Saves the metadata to the layer.
void crsChanged()
If the CRS is updated.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas associated with the widget.
void setMetadata(const QgsAbstractMetadataBase *metadata)
Sets the metadata to display in the widget.
A dialog to create a new auxiliary field.
A dialog to create a new auxiliary layer.
void resizeAlltabs(int index)
Resizes all tabs when the dialog is resized.
QStackedWidget * mOptStackedWidget
void initOptionsBase(bool restoreUi=true, const QString &title=QString())
Set up the base ui connections for vertical tabs.
Property
Data definable properties.
Base class for any widget that can be shown as a inline panel.
QString panelTitle()
The title of the panel.
void acceptPanel()
Accept the panel.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void setDirty(bool b=true)
Flag the project as dirty (modified).
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
Definition for a property.
Definition qgsproperty.h:45
QString comment() const
Returns the comment of the property.
void setOrigin(const QString &origin)
Sets the origin of the property.
QString name() const
Returns the name of the property.
void setName(const QString &name)
Sets the name of the property.
QString origin() const
Returns the origin of the property.
void setComment(const QString &comment)
Sets comment of the property.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderSourceWidget * createWidget(QgsMapLayer *layer, QWidget *parent=nullptr)
Creates a new widget to configure the source of the specified layer.
virtual QString groupTitle() const
Returns an optional group title for the source settings, for use in layer properties dialogs.
void validChanged(bool isValid)
Emitted whenever the validation status of the widget changes.
virtual QString sourceUri() const =0
Returns the source URI as currently defined by the widget.
virtual void setMapCanvas(QgsMapCanvas *mapCanvas)
Sets a map canvas associated with the widget.
virtual void setSourceUri(const QString &uri)=0
Sets the source uri to show in the widget.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the dialog is shown, e.g., the associated map canvas and expression context...
void apply()
Apply the changes from the dialog to the layer.
void layerVariablesChanged()
Emitted when expression context variables on the associated vector layers have been changed.
void widgetChanged()
Emitted when something on the widget has changed.
void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
void setMetadataUrls(const QList< QgsServerMetadataUrlProperties::MetadataUrl > &metaUrls)
Sets a the list of metadata URL for the layer.
QList< QgsServerMetadataUrlProperties::MetadataUrl > metadataUrls() const
Returns a list of metadataUrl resources associated for the layer.
static QMap< int, QString > wmsDimensionDefaultDisplayLabels()
Returns WMS Dimension default display labels.
bool addWmsDimension(const QgsServerWmsDimensionProperties::WmsDimensionInfo &wmsDimInfo)
Adds a QGIS Server WMS Dimension.
bool removeWmsDimension(const QString &wmsDimName)
Removes a QGIS Server WMS Dimension.
const QList< QgsServerWmsDimensionProperties::WmsDimensionInfo > wmsDimensions() const
Returns the QGIS Server WMS Dimension list.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:146
Interface for a dialog that can edit subset strings.
virtual QString subsetString() const =0
Returns the subset string entered in the dialog.
virtual void setSubsetString(const QString &subsetString)=0
Sets a subset string into the dialog.
QgsSubsetStringEditorInterface * createDialog(QgsVectorLayer *layer, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Creates a new dialog to edit the subset string of the provided layer.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
This is the base class for vector data providers.
static QStringList availableEncodings()
Returns a list of available encodings.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
QString encoding() const
Returns the encoding which is used for accessing data.
Defines left outer join from our vector layer to some other vector layer.
bool hasCascadedDelete() const
Returns whether a feature deleted on the target layer has to impact the joined layer by deleting the ...
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...
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
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.
QString joinFieldName() const
Returns name of the field of joined layer that will be used for join.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
QString joinLayerId() const
ID of the joined layer - may be used to resolve 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)
bool eventFilter(QObject *obj, QEvent *ev) override
QgsVectorLayerProperties(QgsMapCanvas *canvas, QgsMessageBar *messageBar, QgsVectorLayer *lyr=nullptr, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
void optionsStackedWidget_CurrentChanged(int index) final
void toggleEditing(QgsMapLayer *)
void exportAuxiliaryLayer(QgsAuxiliaryLayer *layer)
Implementation of layer selection properties for vector layers.
void setSelectionSymbol(QgsSymbol *symbol)
Sets the symbol used to render selected features in the layer.
QgsSymbol * selectionSymbol() const
Returns the symbol used to render selected features in the layer.
Qgis::SelectionRenderingMode selectionRenderingMode() const
Returns the selection rendering mode to use for selected features in the layer.
QColor selectionColor() const
Returns the color to use for rendering selected features in the layer.
void setSelectionColor(const QColor &color)
Sets the color to use for rendering selected features in the layer.
void setSelectionRenderingMode(Qgis::SelectionRenderingMode mode)
Sets the selection rendering mode to use for selected features in the layer.
A widget for configuring the temporal properties for a vector layer.
void syncToLayer()
Updates the widget state to match the current layer state.
void saveTemporalProperties()
Save widget temporal properties inputs.
Represents a vector layer which manages a vector based data sets.
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
bool setDependencies(const QSet< QgsMapLayerDependency > &layers) FINAL
Sets the list of dependencies.
void setProviderEncoding(const QString &encoding)
Sets the text encoding of the data provider.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
virtual void updateExtents(bool force=false)
Update the extents for the layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
QgsMapLayerSelectionProperties * selectionProperties() override
Returns the layer's selection properties.
This class contains information how to simplify geometries fetched from a vector layer.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported,...
Qgis::VectorRenderingSimplificationFlags simplifyHints() const
Gets the simplification hints of the vector layer managed.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
Qgis::VectorSimplificationAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
void setSimplifyHints(Qgis::VectorRenderingSimplificationFlags simplifyHints)
Sets the simplification hints of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
void setSimplifyAlgorithm(Qgis::VectorSimplificationAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
The QgsWebView class is a collection of stubs to mimic the API of QWebView on systems where the real ...
Definition qgswebview.h:66
The QgsWmsDimensionDialog class provides an interface for WMS/OAPIF (WFS3) dimensions configuration A...
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
QString format
Format specification of online resource.
Setting to define QGIS Server WMS Dimension.