QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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"
24#include "qgssldexportcontext.h"
26#include "qgsapplication.h"
32#include "qgslabelingwidget.h"
33#include "qgsmapcanvas.h"
36#include "qgsmetadatawidget.h"
38#include "qgsnative.h"
39#include "qgsproject.h"
40#include "qgsvectorlayer.h"
46#include "qgsdatasourceuri.h"
47#include "qgsrenderer.h"
49#include "qgssettings.h"
51#include "qgsstyle.h"
52#include "qgsauxiliarystorage.h"
56#include "qgslabelinggui.h"
59#include "qgsmessagebar.h"
62#include "qgsmaskingwidget.h"
66#include "qgsproviderregistry.h"
68#include "qgslayertreemodel.h"
69
70#include <QDesktopServices>
71#include <QMessageBox>
72#include <QDir>
73#include <QFile>
74#include <QFileDialog>
75#include <QFileInfo>
76#include <QFontDialog>
77#include <QComboBox>
78#include <QCheckBox>
79#include <QHeaderView>
80#include <QColorDialog>
81#include <QMenu>
82#include <QUrl>
83#include <QRegularExpressionValidator>
84
85
87 QgsMapCanvas *canvas,
88 QgsMessageBar *messageBar,
89 QgsVectorLayer *lyr,
90 QWidget *parent,
91 Qt::WindowFlags fl
92)
93 : QgsOptionsDialogBase( QStringLiteral( "VectorLayerProperties" ), parent, fl )
94 , mCanvas( canvas )
95 , mMessageBar( messageBar )
96 , mLayer( lyr )
97 , mOriginalSubsetSQL( lyr->subsetString() )
98{
99 setupUi( this );
100 connect( pbnQueryBuilder, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnQueryBuilder_clicked );
101 connect( pbnIndex, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnIndex_clicked );
102 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerProperties::mCrsSelector_crsChanged );
103 connect( pbnUpdateExtents, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnUpdateExtents_clicked );
104 connect( mButtonAddJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddJoin_clicked );
105 connect( mButtonEditJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditJoin_clicked );
106 connect( mJoinTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked );
107 connect( mButtonRemoveJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveJoin_clicked );
108 connect( mButtonAddWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddWmsDimension_clicked );
109 connect( mButtonEditWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditWmsDimension_clicked );
110 connect( mWmsDimensionsTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked );
111 connect( mButtonRemoveWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked );
112 connect( mSimplifyDrawingGroupBox, &QGroupBox::toggled, this, &QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled );
113 connect( buttonRemoveMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::removeSelectedMetadataUrl );
114 connect( buttonAddMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::addMetadataUrl );
115 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerProperties::showHelp );
116
117 // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
118 // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
119 // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
120 initOptionsBase( false );
121
122 mBtnStyle = new QPushButton( tr( "Style" ), this );
123 QMenu *menuStyle = new QMenu( this );
124 mActionLoadStyle = new QAction( tr( "Load Style…" ), this );
125 connect( mActionLoadStyle, &QAction::triggered, this, &QgsVectorLayerProperties::loadStyle );
126
127 mActionSaveStyle = new QAction( tr( "Save Current Style…" ), this );
128 connect( mActionSaveStyle, &QAction::triggered, this, &QgsVectorLayerProperties::saveStyleAs );
129
130 mActionSaveMultipleStyles = new QAction( tr( "Save Multiple Styles…" ), this );
131 connect( mActionSaveMultipleStyles, &QAction::triggered, this, &QgsVectorLayerProperties::saveMultipleStylesAs );
132
133 mSourceGroupBox->hide();
134
135 mBtnStyle->setMenu( menuStyle );
136 connect( menuStyle, &QMenu::aboutToShow, this, &QgsVectorLayerProperties::aboutToShowStyleMenu );
137 buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
138
139 mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
140 QMenu *menuMetadata = new QMenu( this );
141 mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsVectorLayerProperties::loadMetadata );
142 mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsVectorLayerProperties::saveMetadataAs );
143 menuMetadata->addSeparator();
144 menuMetadata->addAction( tr( "Save as Default" ), this, &QgsVectorLayerProperties::saveDefaultMetadata );
145 menuMetadata->addAction( tr( "Restore Default" ), this, &QgsVectorLayerProperties::loadDefaultMetadata );
146 mBtnMetadata->setMenu( menuMetadata );
147 buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
148
149 connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsVectorLayerProperties::syncToLayer );
150
151 connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsVectorLayerProperties::apply );
152 connect( this, &QDialog::accepted, this, &QgsVectorLayerProperties::apply );
153 connect( this, &QDialog::rejected, this, &QgsVectorLayerProperties::onCancel );
154
160
161 mMapTipExpressionFieldWidget->setLayer( lyr );
162 mMapTipExpressionFieldWidget->registerExpressionContextGenerator( this );
163 mDisplayExpressionWidget->setLayer( lyr );
164 mDisplayExpressionWidget->registerExpressionContextGenerator( this );
165
166 connect( mInsertExpressionButton, &QAbstractButton::clicked, this, &QgsVectorLayerProperties::insertFieldOrExpression );
167
168 if ( !mLayer )
169 return;
170
171 QVBoxLayout *layout = nullptr;
172
173 if ( mLayer->isSpatial() )
174 {
175 // Create the Labeling dialog tab
176 layout = new QVBoxLayout( labelingFrame );
177 layout->setContentsMargins( 0, 0, 0, 0 );
178 labelingDialog = new QgsLabelingWidget( mLayer, mCanvas, labelingFrame );
179 labelingDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
180 connect( labelingDialog, &QgsLabelingWidget::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
181 layout->addWidget( labelingDialog );
182 labelingFrame->setLayout( layout );
183
184 // Create the masking dialog tab
185 layout = new QVBoxLayout( mMaskingFrame );
186 layout->setContentsMargins( 0, 0, 0, 0 );
187 mMaskingWidget = new QgsMaskingWidget( mMaskingFrame );
188 mMaskingWidget->setLayer( mLayer );
189 mMaskingWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
190 layout->addWidget( mMaskingWidget );
191 mMaskingFrame->setLayout( layout );
192 }
193 else
194 {
195 labelingDialog = nullptr;
196 mOptsPage_Labels->setEnabled( false ); // disable labeling item
197 mOptsPage_Masks->setEnabled( false ); // disable masking item
198 mGeomGroupBox->setEnabled( false );
199 mGeomGroupBox->setVisible( false );
200 mCrsGroupBox->setEnabled( false );
201 mCrsGroupBox->setVisible( false );
202 }
203
204 // Create the Actions dialog tab
205 QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
206 actionLayout->setContentsMargins( 0, 0, 0, 0 );
207 mActionDialog = new QgsAttributeActionDialog( *mLayer->actions(), actionOptionsFrame );
208 mActionDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
209 actionLayout->addWidget( mActionDialog );
210
211 mSourceFieldsPropertiesDialog = new QgsSourceFieldsProperties( mLayer, mSourceFieldsFrame );
212 mSourceFieldsPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
213 mSourceFieldsFrame->setLayout( new QVBoxLayout( mSourceFieldsFrame ) );
214 mSourceFieldsFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
215 mSourceFieldsFrame->layout()->addWidget( mSourceFieldsPropertiesDialog );
216
217 connect( mSourceFieldsPropertiesDialog, &QgsSourceFieldsProperties::toggleEditing, this, static_cast<void ( QgsVectorLayerProperties::* )()>( &QgsVectorLayerProperties::toggleEditing ) );
218
219 mAttributesFormPropertiesDialog = new QgsAttributesFormProperties( mLayer, mAttributesFormFrame );
220 mAttributesFormPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
221 mAttributesFormFrame->setLayout( new QVBoxLayout( mAttributesFormFrame ) );
222 mAttributesFormFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
223 mAttributesFormFrame->layout()->addWidget( mAttributesFormPropertiesDialog );
224
225 // Metadata tab, before the syncToLayer
226 QVBoxLayout *metadataLayout = new QVBoxLayout( metadataFrame );
227 metadataLayout->setContentsMargins( 0, 0, 0, 0 );
228 mMetadataWidget = new QgsMetadataWidget( this, mLayer );
229 mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
230 mMetadataWidget->setMapCanvas( mCanvas );
231 metadataLayout->addWidget( mMetadataWidget );
232 metadataFrame->setLayout( metadataLayout );
233
234 QVBoxLayout *temporalLayout = new QVBoxLayout( temporalFrame );
235 temporalLayout->setContentsMargins( 0, 0, 0, 0 );
236 mTemporalWidget = new QgsVectorLayerTemporalPropertiesWidget( this, mLayer );
237 temporalLayout->addWidget( mTemporalWidget );
238
239 syncToLayer();
240
241 if ( mLayer->dataProvider() )
242 {
243 //enable spatial index button group if supported by provider, or if one already exists
244 QgsVectorDataProvider::Capabilities capabilities = mLayer->dataProvider()->capabilities();
245 if ( !( capabilities & QgsVectorDataProvider::CreateSpatialIndex ) )
246 {
247 pbnIndex->setEnabled( false );
248 }
250 {
251 pbnIndex->setEnabled( false );
252 pbnIndex->setText( tr( "Spatial Index Exists" ) );
253 }
254
255 if ( capabilities & QgsVectorDataProvider::SelectEncoding )
256 {
257 cboProviderEncoding->addItems( QgsVectorDataProvider::availableEncodings() );
258 QString enc = mLayer->dataProvider()->encoding();
259 int encindex = cboProviderEncoding->findText( enc );
260 if ( encindex < 0 )
261 {
262 cboProviderEncoding->insertItem( 0, enc );
263 encindex = 0;
264 }
265 cboProviderEncoding->setCurrentIndex( encindex );
266 }
267 else if ( mLayer->providerType() == QLatin1String( "ogr" ) )
268 {
269 // if OGR_L_TestCapability(OLCStringsAsUTF8) returns true, OGR provider encoding can be set to only UTF-8
270 // so make encoding box grayed out
271 cboProviderEncoding->addItem( mLayer->dataProvider()->encoding() );
272 cboProviderEncoding->setEnabled( false );
273 }
274 else
275 {
276 // other providers do not use mEncoding, so hide the group completely
277 mDataSourceEncodingFrame->hide();
278 }
279 }
280
281 mCrsSelector->setCrs( mLayer->crs() );
282
283 //insert existing join info
284 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
285 for ( const QgsVectorLayerJoinInfo &join : joins )
286 {
287 addJoinToTreeWidget( join );
288 }
289
290 mOldJoins = mLayer->vectorJoins();
291
292 QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
293 diagLayout->setContentsMargins( 0, 0, 0, 0 );
294 diagramPropertiesDialog = new QgsDiagramProperties( mLayer, mDiagramFrame, mCanvas );
295 diagramPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
296 connect( diagramPropertiesDialog, &QgsDiagramProperties::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
297 diagLayout->addWidget( diagramPropertiesDialog );
298 mDiagramFrame->setLayout( diagLayout );
299
300 // Legend tab
301 mLegendWidget->setMapCanvas( mCanvas );
302 mLegendWidget->setLayer( mLayer );
303 mLegendConfigEmbeddedWidget->setLayer( mLayer );
304
305 // WMS Name as layer short name
306 mLayerShortNameLineEdit->setText( mLayer->shortName() );
307 // WMS Name validator
308 QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
309 mLayerShortNameLineEdit->setValidator( shortNameValidator );
310
311 //layer title and abstract
312 mLayerTitleLineEdit->setText( mLayer->title() );
313 mLayerAbstractTextEdit->setPlainText( mLayer->abstract() );
314 mLayerKeywordListLineEdit->setText( mLayer->keywordList() );
315 mLayerDataUrlLineEdit->setText( mLayer->dataUrl() );
316 mLayerDataUrlFormatComboBox->setCurrentIndex(
317 mLayerDataUrlFormatComboBox->findText(
318 mLayer->dataUrlFormat()
319 )
320 );
321 //layer attribution
322 mLayerAttributionLineEdit->setText( mLayer->attribution() );
323 mLayerAttributionUrlLineEdit->setText( mLayer->attributionUrl() );
324
325 // Setup the layer metadata URL
326 tableViewMetadataUrl->setSelectionMode( QAbstractItemView::SingleSelection );
327 tableViewMetadataUrl->setSelectionBehavior( QAbstractItemView::SelectRows );
328 tableViewMetadataUrl->horizontalHeader()->setStretchLastSection( true );
329 tableViewMetadataUrl->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
330
331 mMetadataUrlModel = new QStandardItemModel( tableViewMetadataUrl );
332 mMetadataUrlModel->clear();
333 mMetadataUrlModel->setColumnCount( 3 );
334 QStringList metadataUrlHeaders;
335 metadataUrlHeaders << tr( "URL" ) << tr( "Type" ) << tr( "Format" );
336 mMetadataUrlModel->setHorizontalHeaderLabels( metadataUrlHeaders );
337 tableViewMetadataUrl->setModel( mMetadataUrlModel );
338 tableViewMetadataUrl->setItemDelegate( new MetadataUrlItemDelegate( this ) );
339
340 const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mLayer->serverProperties()->metadataUrls();
341 for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
342 {
343 const int row = mMetadataUrlModel->rowCount();
344 mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
345 mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
346 mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
347 }
348
349 // layer legend url
350 mLayerLegendUrlLineEdit->setText( mLayer->legendUrl() );
351 mLayerLegendUrlFormatComboBox->setCurrentIndex(
352 mLayerLegendUrlFormatComboBox->findText(
353 mLayer->legendUrlFormat()
354 )
355 );
356
357 //insert existing dimension info
358 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
359 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &wmsDims = serverProperties->wmsDimensions();
360 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
361 {
362 addWmsDimensionInfoToTreeWidget( dim );
363 }
364
365 QString myStyle = QgsApplication::reportStyleSheet();
366 myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
367 teMetadataViewer->clear();
368 teMetadataViewer->document()->setDefaultStyleSheet( myStyle );
369 teMetadataViewer->setHtml( htmlMetadata() );
370 teMetadataViewer->setOpenLinks( false );
371 connect( teMetadataViewer, &QTextBrowser::anchorClicked, this, &QgsVectorLayerProperties::urlClicked );
372 mMetadataFilled = true;
373
374 QgsSettings settings;
375 // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
376 // this will be read by restoreOptionsBaseUi()
377 if ( !settings.contains( QStringLiteral( "/Windows/VectorLayerProperties/tab" ) ) )
378 {
379 settings.setValue( QStringLiteral( "Windows/VectorLayerProperties/tab" ),
380 mOptStackedWidget->indexOf( mOptsPage_Style ) );
381 }
382
383 QString title = tr( "Layer Properties — %1" ).arg( mLayer->name() );
384 if ( !mLayer->styleManager()->isDefault( mLayer->styleManager()->currentStyle() ) )
385 title += QStringLiteral( " (%1)" ).arg( mLayer->styleManager()->currentStyle() );
386 restoreOptionsBaseUi( title );
387
388 QList<QgsMapLayer *> dependencySources;
389 const QSet<QgsMapLayerDependency> constDependencies = mLayer->dependencies();
390 for ( const QgsMapLayerDependency &dep : constDependencies )
391 {
392 QgsMapLayer *layer = QgsProject::instance()->mapLayer( dep.layerId() );
393 if ( layer )
394 dependencySources << layer;
395 }
396
397 mLayersDependenciesTreeModel = new QgsLayerTreeFilterProxyModel( this );
398 mLayersDependenciesTreeModel->setLayerTreeModel( new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot(), mLayersDependenciesTreeModel ) );
399 mLayersDependenciesTreeModel->setCheckedLayers( dependencySources );
400 connect( QgsProject::instance(), &QObject::destroyed, this, [ = ] {mLayersDependenciesTreeView->setModel( nullptr );} );
401 mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel );
402
403 connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );
404
405 // auxiliary layer
406 QMenu *menu = new QMenu( this );
407
408 mAuxiliaryLayerActionNew = new QAction( tr( "Create" ), this );
409 menu->addAction( mAuxiliaryLayerActionNew );
410 connect( mAuxiliaryLayerActionNew, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerNew );
411
412 mAuxiliaryLayerActionClear = new QAction( tr( "Clear" ), this );
413 menu->addAction( mAuxiliaryLayerActionClear );
414 connect( mAuxiliaryLayerActionClear, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerClear );
415
416 mAuxiliaryLayerActionDelete = new QAction( tr( "Delete" ), this );
417 menu->addAction( mAuxiliaryLayerActionDelete );
418 connect( mAuxiliaryLayerActionDelete, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerDelete );
419
420 mAuxiliaryLayerActionExport = new QAction( tr( "Export" ), this );
421 menu->addAction( mAuxiliaryLayerActionExport );
422 connect( mAuxiliaryLayerActionExport, &QAction::triggered, this, [ = ] { emit exportAuxiliaryLayer( mLayer->auxiliaryLayer() ); } );
423
424 mAuxiliaryStorageActions->setMenu( menu );
425
426 connect( mAuxiliaryStorageFieldsDeleteBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerDeleteField );
427 connect( mAuxiliaryStorageFieldsAddBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerAddField );
428
429 updateAuxiliaryStoragePage();
430
431 mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#information-properties" ) );
432 mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#source-properties" ) );
433 mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#symbology-properties" ) );
434 mOptsPage_Labels->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#labels-properties" ) );
435 mOptsPage_Masks->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#masks-properties" ) );
436 mOptsPage_Diagrams->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#diagrams-properties" ) );
437 mOptsPage_SourceFields->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#fields-properties" ) );
438 mOptsPage_AttributesForm->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#attributes-form-properties" ) );
439 mOptsPage_Joins->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#joins-properties" ) );
440 mOptsPage_AuxiliaryStorage->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#auxiliary-storage-properties" ) );
441 mOptsPage_Actions->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#actions-properties" ) );
442 mOptsPage_Display->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#display-properties" ) );
443 mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#rendering-properties" ) );
444 mOptsPage_Temporal->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#temporal-properties" ) );
445 mOptsPage_Variables->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#variables-properties" ) );
446 mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#metadata-properties" ) );
447 mOptsPage_DataDependencies->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#dependencies-properties" ) ) ;
448 mOptsPage_Legend->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#legend-properties" ) );
449 mOptsPage_Server->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#qgis-server-properties" ) );
450
451
453}
454
455void QgsVectorLayerProperties::toggleEditing()
456{
457 if ( !mLayer )
458 return;
459
460 emit toggleEditing( mLayer );
461
462 setPbnQueryBuilderEnabled();
463}
464
466{
467 if ( !factory->supportsLayer( mLayer ) || !factory->supportLayerPropertiesDialog() )
468 {
469 return;
470 }
471
472 QgsMapLayerConfigWidget *page = factory->createWidget( mLayer, nullptr, false, this );
473
474 if ( page )
475 {
476 mLayerPropertiesPages << page;
477
478 const QString beforePage = factory->layerPropertiesPagePositionHint();
479 if ( beforePage.isEmpty() )
480 addPage( factory->title(), factory->title(), factory->icon(), page );
481 else
482 insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage );
483 }
484}
485
486void QgsVectorLayerProperties::insertFieldOrExpression()
487{
488 // Convert the selected field to an expression and
489 // insert it into the action at the cursor position
490 QString expression = QStringLiteral( "[% " );
491 expression += mMapTipExpressionFieldWidget->asExpression();
492 expression += QLatin1String( " %]" );
493
494 mMapTipWidget->insertText( expression );
495}
496
497void QgsVectorLayerProperties::addMetadataUrl()
498{
499 const int row = mMetadataUrlModel->rowCount();
500 mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
501 mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
502 mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
503}
504
505void QgsVectorLayerProperties::removeSelectedMetadataUrl()
506{
507 const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
508 if ( selectedRows.empty() )
509 return;
510 mMetadataUrlModel->removeRow( selectedRows[0].row() );
511}
512
513// in raster props, this method is called sync()
514void QgsVectorLayerProperties::syncToLayer()
515{
516 if ( !mSourceWidget )
517 {
518 mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mLayer );
519 if ( mSourceWidget )
520 {
521 QHBoxLayout *layout = new QHBoxLayout();
522 layout->addWidget( mSourceWidget );
523 mSourceGroupBox->setLayout( layout );
524 mSourceGroupBox->show();
525
526 connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [ = ]( bool isValid )
527 {
528 buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
529 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
530 } );
531 }
532 }
533
534 if ( mSourceWidget )
535 mSourceWidget->setSourceUri( mLayer->source() );
536
537 // populate the general information
538 mLayerOrigNameLineEdit->setText( mLayer->name() );
539 mBackupCrs = mLayer->crs();
540 //see if we are dealing with a pg layer here
541 mSubsetGroupBox->setEnabled( true );
542 txtSubsetSQL->setText( mLayer->subsetString() );
543 // if the user is allowed to type an adhoc query, the app will crash if the query
544 // is bad. For this reason, the sql box is disabled and the query must be built
545 // using the query builder, either by typing it in by hand or using the buttons, etc
546 // on the builder. If the ability to enter a query directly into the box is required,
547 // a mechanism to check it must be implemented.
548 txtSubsetSQL->setReadOnly( true );
549 txtSubsetSQL->setCaretWidth( 0 );
550 txtSubsetSQL->setCaretLineVisible( false );
551 setPbnQueryBuilderEnabled();
552
553 mMapTipWidget->setText( mLayer->mapTipTemplate() );
554 mDisplayExpressionWidget->setField( mLayer->displayExpression() );
555
556 // set up the scale based layer visibility stuff....
557 mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
558 mScaleVisibilityGroupBox->setChecked( mLayer->hasScaleBasedVisibility() );
559 mScaleRangeWidget->setMapCanvas( mCanvas );
560
561 mUseReferenceScaleGroupBox->setChecked( mLayer->renderer() && mLayer->renderer()->referenceScale() > 0 );
562 mReferenceScaleWidget->setShowCurrentScaleButton( true );
563 mReferenceScaleWidget->setMapCanvas( mCanvas );
564 if ( mUseReferenceScaleGroupBox->isChecked() )
565 mReferenceScaleWidget->setScale( mLayer->renderer()->referenceScale() );
566 else if ( mCanvas )
567 mReferenceScaleWidget->setScale( mCanvas->scale() );
568
569 // get simplify drawing configuration
570 const QgsVectorSimplifyMethod &simplifyMethod = mLayer->simplifyMethod();
571 mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification );
572 mSimplifyDrawingSpinBox->setValue( simplifyMethod.threshold() );
573 mSimplifyDrawingSpinBox->setClearValue( 1.0 );
574
575 QString remark = QStringLiteral( " (%1)" ).arg( tr( "Not supported" ) );
576 const QgsVectorDataProvider *provider = mLayer->dataProvider();
577 if ( !( provider && ( provider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) )
578 {
579 mSimplifyDrawingAtProvider->setChecked( false );
580 mSimplifyDrawingAtProvider->setEnabled( false );
581 if ( !mSimplifyDrawingAtProvider->text().endsWith( remark ) )
582 mSimplifyDrawingAtProvider->setText( mSimplifyDrawingAtProvider->text().append( remark ) );
583 }
584 else
585 {
586 mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() );
587 mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() );
588 if ( mSimplifyDrawingAtProvider->text().endsWith( remark ) )
589 {
590 QString newText = mSimplifyDrawingAtProvider->text();
591 newText.chop( remark.size() );
592 mSimplifyDrawingAtProvider->setText( newText );
593 }
594 }
595
596 // disable simplification for point layers, now it is not implemented
597 if ( mLayer->geometryType() == Qgis::GeometryType::Point )
598 {
599 mSimplifyDrawingGroupBox->setChecked( false );
600 mSimplifyDrawingGroupBox->setEnabled( false );
601 }
602
603 // Default local simplification algorithm
604 mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), QgsVectorSimplifyMethod::Distance );
605 mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), QgsVectorSimplifyMethod::SnapToGrid );
606 mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), QgsVectorSimplifyMethod::Visvalingam );
607 mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( simplifyMethod.simplifyAlgorithm() ) );
608
609 QStringList myScalesList = Qgis::defaultProjectScales().split( ',' );
610 myScalesList.append( QStringLiteral( "1:1" ) );
611 mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
612 mSimplifyMaximumScaleComboBox->setScale( simplifyMethod.maximumScale() );
613
614 mForceRasterCheckBox->setChecked( mLayer->renderer() && mLayer->renderer()->forceRasterRender() );
615
616 mRefreshLayerCheckBox->setChecked( mLayer->hasAutoRefreshEnabled() );
617 mRefreshLayerIntervalSpinBox->setEnabled( mLayer->hasAutoRefreshEnabled() );
618 mRefreshLayerIntervalSpinBox->setValue( mLayer->autoRefreshInterval() / 1000.0 );
619
620 mRefreshLayerNotificationCheckBox->setChecked( mLayer->isRefreshOnNotifyEnabled() );
621 mNotificationMessageCheckBox->setChecked( !mLayer->refreshOnNotifyMessage().isEmpty() );
622 mNotifyMessagValueLineEdit->setText( mLayer->refreshOnNotifyMessage() );
623
624
625 // load appropriate symbology page (V1 or V2)
626 updateSymbologyPage();
627
628 mActionDialog->init( *mLayer->actions(), mLayer->attributeTableConfig() );
629
630 if ( labelingDialog )
631 labelingDialog->adaptToLayer();
632
633 mSourceFieldsPropertiesDialog->init();
634 mAttributesFormPropertiesDialog->init();
635
636 // set initial state for variable editor
637 updateVariableEditor();
638
639 if ( diagramPropertiesDialog )
640 diagramPropertiesDialog->syncToLayer();
641
642 // sync all plugin dialogs
643 const auto constMLayerPropertiesPages = mLayerPropertiesPages;
644 for ( QgsMapLayerConfigWidget *page : constMLayerPropertiesPages )
645 {
646 page->syncToLayer( mLayer );
647 }
648
649 mMetadataWidget->setMetadata( &mLayer->metadata() );
650
651 mTemporalWidget->syncToLayer();
652
653 mLegendWidget->setLayer( mLayer );
654
655}
656
657void QgsVectorLayerProperties::apply()
658{
659 if ( mSourceWidget )
660 {
661 const QString newSource = mSourceWidget->sourceUri();
662 if ( newSource != mLayer->source() )
663 {
664 mLayer->setDataSource( newSource, mLayer->name(), mLayer->providerType(),
665 QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags() );
666 }
667 }
668
669 if ( labelingDialog )
670 {
671 labelingDialog->writeSettingsToLayer();
672 }
673 mBackupCrs = mLayer->crs();
674 // apply legend settings
675 mLegendWidget->applyToLayer();
676 mLegendConfigEmbeddedWidget->applyToLayer();
677
678 // save metadata
679 mMetadataWidget->acceptMetadata();
680 mMetadataFilled = false;
681
682 // save masking settings
683 if ( mMaskingWidget && mMaskingWidget->hasBeenPopulated() )
684 mMaskingWidget->apply();
685
686 //
687 // Set up sql subset query if applicable
688 //
689 mSubsetGroupBox->setEnabled( true );
690
691 if ( txtSubsetSQL->text() != mLayer->subsetString() )
692 {
693 // set the subset sql for the layer
694 mLayer->setSubsetString( txtSubsetSQL->text() );
695 mMetadataFilled = false;
696 }
697 mOriginalSubsetSQL = mLayer->subsetString();
698
699 // set up the scale based layer visibility stuff....
700 mLayer->setScaleBasedVisibility( mScaleVisibilityGroupBox->isChecked() );
701 mLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
702 mLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
703
704 // provider-specific options
705 if ( mLayer->dataProvider() )
706 {
708 {
709 mLayer->setProviderEncoding( cboProviderEncoding->currentText() );
710 }
711 }
712
713 mLayer->setDisplayExpression( mDisplayExpressionWidget->asExpression() );
714 mLayer->setMapTipTemplate( mMapTipWidget->text() );
715
716 mLayer->actions()->clearActions();
717 const auto constActions = mActionDialog->actions();
718 for ( const QgsAction &action : constActions )
719 {
720 mLayer->actions()->addAction( action );
721 }
722 QgsAttributeTableConfig attributeTableConfig = mLayer->attributeTableConfig();
723 attributeTableConfig.update( mLayer->fields() );
724 attributeTableConfig.setActionWidgetStyle( mActionDialog->attributeTableWidgetStyle() );
725 QVector<QgsAttributeTableConfig::ColumnConfig> columns = attributeTableConfig.columns();
726
727 for ( int i = 0; i < columns.size(); ++i )
728 {
729 if ( columns.at( i ).type == QgsAttributeTableConfig::Action )
730 {
731 columns[i].hidden = !mActionDialog->showWidgetInAttributeTable();
732 }
733 }
734
735 attributeTableConfig.setColumns( columns );
736
737 mLayer->setAttributeTableConfig( attributeTableConfig );
738
739 mLayer->setName( mLayerOrigNameLineEdit->text() );
740
741 mAttributesFormPropertiesDialog->apply();
742 mSourceFieldsPropertiesDialog->apply();
743
744 // Update temporal properties
745 mTemporalWidget->saveTemporalProperties();
746
747 if ( mLayer->renderer() )
748 {
749 QgsRendererPropertiesDialog *dlg = static_cast<QgsRendererPropertiesDialog *>( widgetStackRenderers->currentWidget() );
750 dlg->apply();
751 }
752
753 //apply diagram settings
754 diagramPropertiesDialog->apply();
755
756 // apply all plugin dialogs
757 const auto constMLayerPropertiesPages = mLayerPropertiesPages;
758 for ( QgsMapLayerConfigWidget *page : constMLayerPropertiesPages )
759 {
760 page->apply();
761 }
762
763 //layer title and abstract
764 if ( mLayer->shortName() != mLayerShortNameLineEdit->text() )
765 mMetadataFilled = false;
766 mLayer->setShortName( mLayerShortNameLineEdit->text() );
767
768 if ( mLayer->title() != mLayerTitleLineEdit->text() )
769 mMetadataFilled = false;
770 mLayer->setTitle( mLayerTitleLineEdit->text() );
771
772 if ( mLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
773 mMetadataFilled = false;
774 mLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
775
776 if ( mLayer->keywordList() != mLayerKeywordListLineEdit->text() )
777 mMetadataFilled = false;
778 mLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
779
780 if ( mLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
781 mMetadataFilled = false;
782 mLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
783
784 if ( mLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
785 mMetadataFilled = false;
786 mLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
787
788 //layer attribution
789 if ( mLayer->attribution() != mLayerAttributionLineEdit->text() )
790 mMetadataFilled = false;
791 mLayer->setAttribution( mLayerAttributionLineEdit->text() );
792
793 if ( mLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
794 mMetadataFilled = false;
795 mLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
796
797 // Metadata URL
798 QList<QgsMapLayerServerProperties::MetadataUrl> metaUrls;
799 for ( int row = 0; row < mMetadataUrlModel->rowCount() ; row++ )
800 {
802 metaUrl.url = mMetadataUrlModel->item( row, 0 )->text();
803 metaUrl.type = mMetadataUrlModel->item( row, 1 )->text();
804 metaUrl.format = mMetadataUrlModel->item( row, 2 )->text();
805 metaUrls.append( metaUrl );
806 mMetadataFilled = false;
807 }
808 mLayer->serverProperties()->setMetadataUrls( metaUrls );
809
810 // LegendURL
811 if ( mLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
812 mMetadataFilled = false;
813 mLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
814
815 if ( mLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
816 mMetadataFilled = false;
817 mLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
818
819 //layer simplify drawing configuration
820 QgsVectorSimplifyMethod::SimplifyHints simplifyHints = QgsVectorSimplifyMethod::NoSimplification;
821 if ( mSimplifyDrawingGroupBox->isChecked() )
822 {
824 if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorSimplifyMethod::AntialiasingSimplification;
825 }
826 QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
827 simplifyMethod.setSimplifyHints( simplifyHints );
828 simplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( mSimplifyAlgorithmComboBox->currentData().toInt() ) );
829 simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
830 simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
831 simplifyMethod.setMaximumScale( mSimplifyMaximumScaleComboBox->scale() );
832 mLayer->setSimplifyMethod( simplifyMethod );
833
834 if ( mLayer->renderer() )
835 {
836 mLayer->renderer()->setForceRasterRender( mForceRasterCheckBox->isChecked() );
837 mLayer->renderer()->setReferenceScale( mUseReferenceScaleGroupBox->isChecked() ? mReferenceScaleWidget->scale() : -1 );
838 }
839
840 mLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
841 mLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
842
843 mLayer->setRefreshOnNotifyEnabled( mRefreshLayerNotificationCheckBox->isChecked() );
844 mLayer->setRefreshOnNofifyMessage( mNotificationMessageCheckBox->isChecked() ? mNotifyMessagValueLineEdit->text() : QString() );
845
846 mOldJoins = mLayer->vectorJoins();
847
848 //save variables
849 QgsExpressionContextUtils::setLayerVariables( mLayer, mVariableEditor->variablesInActiveScope() );
850 updateVariableEditor();
851
852 // save dependencies
853 QSet<QgsMapLayerDependency> deps;
854 const auto checkedLayers = mLayersDependenciesTreeModel->checkedLayers();
855 for ( const QgsMapLayer *layer : checkedLayers )
856 deps << QgsMapLayerDependency( layer->id() );
857 if ( ! mLayer->setDependencies( deps ) )
858 {
859 QMessageBox::warning( nullptr, tr( "Save Dependency" ), tr( "This configuration introduces a cycle in data dependencies and will be ignored." ) );
860 }
861
862 mLayer->triggerRepaint();
863 // notify the project we've made a change
865}
866
867void QgsVectorLayerProperties::onCancel()
868{
869 if ( mOldJoins != mLayer->vectorJoins() )
870 {
871 // need to undo changes in vector layer joins - they are applied directly to the layer (not in apply())
872 // so other parts of the properties dialog can use the fields from the joined layers
873
874 const auto constVectorJoins = mLayer->vectorJoins();
875 for ( const QgsVectorLayerJoinInfo &info : constVectorJoins )
876 mLayer->removeJoin( info.joinLayerId() );
877
878 for ( const QgsVectorLayerJoinInfo &info : std::as_const( mOldJoins ) )
879 mLayer->addJoin( info );
880 }
881
882 if ( mOriginalSubsetSQL != mLayer->subsetString() )
883 {
884 // need to undo changes in subset string - they are applied directly to the layer (not in apply())
885 // by QgsQueryBuilder::accept()
886
887 mLayer->setSubsetString( mOriginalSubsetSQL );
888 }
889
890 if ( mOldStyle.xmlData() != mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() ).xmlData() )
891 {
892 // need to reset style to previous - style applied directly to the layer (not in apply())
893 QString myMessage;
894 QDomDocument doc( QStringLiteral( "qgis" ) );
895 int errorLine, errorColumn;
896 doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
897 mLayer->importNamedStyle( doc, myMessage );
898 }
899
900 if ( mBackupCrs != mLayer->crs() )
901 mLayer->setCrs( mBackupCrs );
902}
903
904void QgsVectorLayerProperties::urlClicked( const QUrl &url )
905{
906 QFileInfo file( url.toLocalFile() );
907 if ( file.exists() && !file.isDir() )
908 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
909 else
910 QDesktopServices::openUrl( url );
911}
912
913void QgsVectorLayerProperties::pbnQueryBuilder_clicked()
914{
915 // launch the query builder
917
918 // Set the sql in the query builder to the same in the prop dialog
919 // (in case the user has already changed it)
920 dialog->setSubsetString( txtSubsetSQL->text() );
921 // Open the query builder
922 if ( dialog->exec() )
923 {
924 // if the sql is changed, update it in the prop subset text box
925 txtSubsetSQL->setText( dialog->subsetString() );
926 //TODO If the sql is changed in the prop dialog, the layer extent should be recalculated
927
928 // The datasource for the layer needs to be updated with the new sql since this gets
929 // saved to the project file. This should happen at the map layer level...
930
931 }
932 // delete the query builder object
933 delete dialog;
934}
935
936void QgsVectorLayerProperties::pbnIndex_clicked()
937{
938 QgsVectorDataProvider *pr = mLayer->dataProvider();
939 if ( pr )
940 {
941 setCursor( Qt::WaitCursor );
942 bool errval = pr->createSpatialIndex();
943 setCursor( Qt::ArrowCursor );
944 if ( errval )
945 {
946 pbnIndex->setEnabled( false );
947 pbnIndex->setText( tr( "Spatial Index Exists" ) );
948 QMessageBox::information( this, tr( "Spatial Index" ), tr( "Creation of spatial index successful" ) );
949 }
950 else
951 {
952 QMessageBox::warning( this, tr( "Spatial Index" ), tr( "Creation of spatial index failed" ) );
953 }
954 }
955}
956
957QString QgsVectorLayerProperties::htmlMetadata()
958{
959 return mLayer->htmlMetadata();
960}
961
962void QgsVectorLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
963{
964
965 QgsDatumTransformDialog::run( crs, QgsProject::instance()->crs(), this, mCanvas, tr( "Select Transformation for the vector layer" ) );
966 mLayer->setCrs( crs );
967 mMetadataFilled = false;
968 mMetadataWidget->crsChanged();
969}
970
971void QgsVectorLayerProperties::loadDefaultStyle_clicked()
972{
973 QString msg;
974 bool defaultLoadedFlag = false;
975
976 const QgsVectorDataProvider *provider = mLayer->dataProvider();
977 if ( !provider )
978 return;
980 {
981 QMessageBox askToUser;
982 askToUser.setText( tr( "Load default style from: " ) );
983 askToUser.setIcon( QMessageBox::Question );
984 askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
985 askToUser.addButton( tr( "Local Database" ), QMessageBox::NoRole );
986 askToUser.addButton( tr( "Datasource Database" ), QMessageBox::YesRole );
987
988 switch ( askToUser.exec() )
989 {
990 case 0:
991 return;
992 case 2:
993 msg = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag );
994 if ( !defaultLoadedFlag )
995 {
996 //something went wrong - let them know why
997 QMessageBox::information( this, tr( "Default Style" ), msg );
998 }
999 if ( msg.compare( tr( "Loaded from Provider" ) ) )
1000 {
1001 QMessageBox::information( this, tr( "Default Style" ),
1002 tr( "No default style was found for this layer." ) );
1003 }
1004 else
1005 {
1006 syncToLayer();
1007 }
1008
1009 return;
1010 default:
1011 break;
1012 }
1013 }
1014
1015 QString myMessage = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true );
1016// QString myMessage = layer->loadDefaultStyle( defaultLoadedFlag );
1017 //reset if the default style was loaded OK only
1018 if ( defaultLoadedFlag )
1019 {
1020 // all worked OK so no need to inform user
1021 syncToLayer();
1022 }
1023 else
1024 {
1025 //something went wrong - let them know why
1026 QMessageBox::information( this, tr( "Default Style" ), myMessage );
1027 }
1028}
1029
1030void QgsVectorLayerProperties::saveDefaultStyle_clicked()
1031{
1032 apply();
1033 QString errorMsg;
1034 const QgsVectorDataProvider *provider = mLayer->dataProvider();
1035 if ( !provider )
1036 return;
1037 if ( provider->isSaveAndLoadStyleToDatabaseSupported() )
1038 {
1039 QMessageBox askToUser;
1040 askToUser.setText( tr( "Save default style to: " ) );
1041 askToUser.setIcon( QMessageBox::Question );
1042 askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
1043 askToUser.addButton( tr( "Local Database" ), QMessageBox::NoRole );
1044 askToUser.addButton( tr( "Datasource Database" ), QMessageBox::YesRole );
1045
1046 switch ( askToUser.exec() )
1047 {
1048 case 0:
1049 return;
1050 case 2:
1051 {
1052 QString errorMessage;
1053 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), QString(), errorMessage ) )
1054 {
1055 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1056 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1057 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1058 {
1059 return;
1060 }
1061 }
1062 else if ( !errorMessage.isEmpty() )
1063 {
1064 QMessageBox::warning( nullptr, QObject::tr( "Save style in database" ),
1065 errorMessage );
1066 return;
1067 }
1068
1069 mLayer->saveStyleToDatabase( QString(), QString(), true, QString(), errorMsg );
1070 if ( errorMsg.isNull() )
1071 {
1072 return;
1073 }
1074 break;
1075 }
1076 default:
1077 break;
1078 }
1079 }
1080
1081 bool defaultSavedFlag = false;
1082 // TODO Once the deprecated `saveDefaultStyle()` method is gone, just
1083 // remove the NOWARN_DEPRECATED tags
1085 errorMsg = mLayer->saveDefaultStyle( defaultSavedFlag );
1087 if ( !defaultSavedFlag )
1088 {
1089 QMessageBox::warning( this, tr( "Default Style" ), errorMsg );
1090 }
1091}
1092
1093void QgsVectorLayerProperties::loadMetadata()
1094{
1095 QgsSettings myQSettings; // where we keep last used filter in persistent state
1096 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1097
1098 QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load Layer Metadata from Metadata File" ), myLastUsedDir,
1099 tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1100 if ( myFileName.isNull() )
1101 {
1102 return;
1103 }
1104
1105 QString myMessage;
1106 bool defaultLoadedFlag = false;
1107 myMessage = mLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1108
1109 //reset if the default style was loaded OK only
1110 if ( defaultLoadedFlag )
1111 {
1112 mMetadataWidget->setMetadata( &mLayer->metadata() );
1113 }
1114 else
1115 {
1116 //let the user know what went wrong
1117 QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1118 }
1119
1120 QFileInfo myFI( myFileName );
1121 QString myPath = myFI.path();
1122 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1123
1124 activateWindow(); // set focus back to properties dialog
1125}
1126
1127void QgsVectorLayerProperties::saveMetadataAs()
1128{
1129 QgsSettings myQSettings; // where we keep last used filter in persistent state
1130 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1131
1132 QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1133 myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1134 if ( myOutputFileName.isNull() ) //dialog canceled
1135 {
1136 return;
1137 }
1138
1139 mMetadataWidget->acceptMetadata();
1140
1141 //ensure the user never omitted the extension from the file name
1142 if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1143 {
1145 }
1146
1147 QString myMessage;
1148 bool defaultLoadedFlag = false;
1149 myMessage = mLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1150
1151 //reset if the default style was loaded OK only
1152 if ( defaultLoadedFlag )
1153 {
1154 syncToLayer();
1155 }
1156 else
1157 {
1158 //let the user know what went wrong
1159 QMessageBox::information( this, tr( "Save Metadata" ), myMessage );
1160 }
1161
1162 QFileInfo myFI( myOutputFileName );
1163 QString myPath = myFI.path();
1164 // Persist last used dir
1165 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1166}
1167
1168void QgsVectorLayerProperties::saveDefaultMetadata()
1169{
1170 mMetadataWidget->acceptMetadata();
1171
1172 bool defaultSavedFlag = false;
1173 QString errorMsg = mLayer->saveDefaultMetadata( defaultSavedFlag );
1174 if ( !defaultSavedFlag )
1175 {
1176 QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1177 }
1178}
1179
1180void QgsVectorLayerProperties::loadDefaultMetadata()
1181{
1182 bool defaultLoadedFlag = false;
1183 QString myMessage = mLayer->loadNamedMetadata( mLayer->metadataUri(), defaultLoadedFlag );
1184 //reset if the default metadata was loaded OK only
1185 if ( defaultLoadedFlag )
1186 {
1187 mMetadataWidget->setMetadata( &mLayer->metadata() );
1188 }
1189 else
1190 {
1191 QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1192 }
1193}
1194
1195
1196void QgsVectorLayerProperties::saveStyleAs()
1197{
1198 if ( !mLayer->dataProvider() )
1199 return;
1200 QgsVectorLayerSaveStyleDialog dlg( mLayer );
1201 QgsSettings settings;
1202
1203 if ( dlg.exec() )
1204 {
1205 apply();
1206
1207 bool defaultLoadedFlag = false;
1208 QString errorMessage;
1209
1210 StyleType type = dlg.currentStyleType();
1211 switch ( type )
1212 {
1213 case QML:
1214 case SLD:
1215 {
1216 QString filePath = dlg.outputFilePath();
1217 if ( type == QML )
1218 errorMessage = mLayer->saveNamedStyle( filePath, defaultLoadedFlag, dlg.styleCategories() );
1219 else
1220 {
1221 const QgsSldExportContext sldContext { dlg.sldExportOptions(), Qgis::SldExportVendorExtension::NoVendorExtension, filePath };
1222 errorMessage = mLayer->saveSldStyleV2( defaultLoadedFlag, sldContext );
1223 }
1224
1225 //reset if the default style was loaded OK only
1226 if ( defaultLoadedFlag )
1227 {
1228 syncToLayer();
1229 }
1230 else
1231 {
1232 //let the user know what went wrong
1233 QMessageBox::information( this, tr( "Save Style" ), errorMessage );
1234 }
1235
1236 break;
1237 }
1238 case DB:
1239 {
1240 QString infoWindowTitle = QObject::tr( "Save style to DB (%1)" ).arg( mLayer->providerType() );
1241
1242 QgsVectorLayerSaveStyleDialog::SaveToDbSettings dbSettings = dlg.saveToDbSettings();
1243
1244 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), dbSettings.name, errorMessage ) )
1245 {
1246 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1247 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1248 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1249 {
1250 return;
1251 }
1252 }
1253 else if ( !errorMessage.isEmpty() )
1254 {
1255 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1256 return;
1257 }
1258
1259 mLayer->saveStyleToDatabase( dbSettings.name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, errorMessage, dlg.styleCategories() );
1260
1261 if ( !errorMessage.isNull() )
1262 {
1263 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1264 }
1265 else
1266 {
1267 mMessageBar->pushMessage( infoWindowTitle, tr( "Style saved" ), Qgis::MessageLevel::Success );
1268 }
1269 break;
1270 }
1271 case Local:
1272 {
1273 QString infoWindowTitle = tr( "Save default style to local database" );
1274 errorMessage = mLayer->saveDefaultStyle( defaultLoadedFlag, dlg.styleCategories() );
1275 if ( !defaultLoadedFlag )
1276 {
1277 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1278 }
1279 else
1280 {
1281 mMessageBar->pushMessage( infoWindowTitle, tr( "Style saved" ), Qgis::MessageLevel::Success );
1282 }
1283 break;
1284 }
1285 }
1286 }
1287}
1288
1289void QgsVectorLayerProperties::saveMultipleStylesAs()
1290{
1291 QgsVectorLayerSaveStyleDialog dlg( mLayer );
1292 dlg.setSaveOnlyCurrentStyle( false );
1293 QgsSettings settings;
1294
1295 if ( dlg.exec() )
1296 {
1297 apply();
1298
1299 // Store the original style, that we can restore at the end
1300 const QString originalStyle { mLayer->styleManager()->currentStyle() };
1301 const QListWidget *stylesWidget { dlg.stylesWidget() };
1302
1303 // Collect selected (checked) styles for export/save
1304 QStringList stylesSelected;
1305 for ( int i = 0; i < stylesWidget->count(); i++ )
1306 {
1307 if ( stylesWidget->item( i )->checkState() == Qt::CheckState::Checked )
1308 {
1309 stylesSelected.push_back( stylesWidget->item( i )->text() );
1310 }
1311 }
1312
1313 if ( ! stylesSelected.isEmpty() )
1314 {
1315 int styleIndex = 0;
1316 for ( const QString &styleName : std::as_const( stylesSelected ) )
1317 {
1318 bool defaultLoadedFlag = false;
1319
1320 StyleType type = dlg.currentStyleType();
1321 mLayer->styleManager()->setCurrentStyle( styleName );
1322 switch ( type )
1323 {
1324 case QML:
1325 case SLD:
1326 {
1327 QString message;
1328 const QString filePath { dlg.outputFilePath() };
1329 QString safePath { filePath };
1330 if ( styleIndex > 0 && stylesSelected.count( ) > 1 )
1331 {
1332 int i = 1;
1333 while ( QFile::exists( safePath ) )
1334 {
1335 const QFileInfo fi { filePath };
1336 safePath = QString( filePath ).replace( '.' + fi.completeSuffix(),
1337 QStringLiteral( "_%1.%2" ).arg( QString::number( i ), fi.completeSuffix() ) );
1338 i++;
1339 }
1340 }
1341 if ( type == QML )
1342 message = mLayer->saveNamedStyle( safePath, defaultLoadedFlag, dlg.styleCategories() );
1343 else
1344 message = mLayer->saveSldStyle( safePath, defaultLoadedFlag );
1345
1346 //reset if the default style was loaded OK only
1347 if ( defaultLoadedFlag )
1348 {
1349 syncToLayer();
1350 }
1351 else
1352 {
1353 //let the user know what went wrong
1354 QMessageBox::information( this, tr( "Save Style" ), message );
1355 }
1356
1357 break;
1358 }
1359 case DB:
1360 {
1361 QString infoWindowTitle = QObject::tr( "Save style '%1' to DB (%2)" )
1362 .arg( styleName, mLayer->providerType() );
1363 QString msgError;
1364
1365 QgsVectorLayerSaveStyleDialog::SaveToDbSettings dbSettings = dlg.saveToDbSettings();
1366
1367 // If a name is defined, we add _1 etc. else we use the style name
1368 QString name { dbSettings.name };
1369 if ( name.isEmpty() )
1370 {
1371 name = styleName;
1372 }
1373 else
1374 {
1375 QStringList ids, names, descriptions;
1376 mLayer->listStylesInDatabase( ids, names, descriptions, msgError );
1377 int i = 1;
1378 while ( names.contains( name ) )
1379 {
1380 name = QStringLiteral( "%1 %2" ).arg( name, QString::number( i ) );
1381 i++;
1382 }
1383 }
1384
1385 QString errorMessage;
1386 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), dbSettings.name, errorMessage ) )
1387 {
1388 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1389 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1390 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1391 {
1392 return;
1393 }
1394 }
1395 else if ( !errorMessage.isEmpty() )
1396 {
1397 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1398 return;
1399 }
1400
1401 mLayer->saveStyleToDatabase( name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, msgError, dlg.styleCategories() );
1402
1403 if ( !msgError.isNull() )
1404 {
1405 mMessageBar->pushMessage( infoWindowTitle, msgError, Qgis::MessageLevel::Warning );
1406 }
1407 else
1408 {
1409 mMessageBar->pushMessage( infoWindowTitle, tr( "Style '%1' saved" ).arg( styleName ),
1410 Qgis::MessageLevel::Success );
1411 }
1412 break;
1413 }
1414 case Local:
1415 break;
1416 }
1417 styleIndex ++;
1418 }
1419 // Restore original style
1420 mLayer->styleManager()->setCurrentStyle( originalStyle );
1421 }
1422 } // Nothing selected!
1423}
1424
1425void QgsVectorLayerProperties::aboutToShowStyleMenu()
1426{
1427 // this should be unified with QgsRasterLayerProperties::aboutToShowStyleMenu()
1428 QMenu *m = qobject_cast<QMenu *>( sender() );
1429 m->clear();
1430
1431 m->addAction( mActionLoadStyle );
1432 m->addAction( mActionSaveStyle );
1433
1434 // If we have multiple styles, offer an option to save them at once
1435 if ( mLayer->styleManager()->styles().count() > 1 )
1436 {
1437 mActionSaveStyle->setText( tr( "Save Current Style…" ) );
1438 m->addAction( mActionSaveMultipleStyles );
1439 }
1440 else
1441 {
1442 mActionSaveStyle->setText( tr( "Save Style…" ) );
1443 }
1444
1445 m->addSeparator();
1446 m->addAction( tr( "Save as Default" ), this, &QgsVectorLayerProperties::saveDefaultStyle_clicked );
1447 m->addAction( tr( "Restore Default" ), this, &QgsVectorLayerProperties::loadDefaultStyle_clicked );
1448
1449 // re-add style manager actions!
1450 m->addSeparator();
1452}
1453
1454void QgsVectorLayerProperties::loadStyle()
1455{
1456 QgsSettings settings; // where we keep last used filter in persistent state
1457
1458 QString errorMsg;
1459 QStringList ids, names, descriptions;
1460
1461 //get the list of styles in the db
1462 int sectionLimit = mLayer->listStylesInDatabase( ids, names, descriptions, errorMsg );
1463 QgsMapLayerLoadStyleDialog dlg( mLayer, this );
1464 dlg.initializeLists( ids, names, descriptions, sectionLimit );
1465
1466 if ( dlg.exec() )
1467 {
1468 mOldStyle = mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() );
1469 QgsMapLayer::StyleCategories categories = dlg.styleCategories();
1470 StyleType type = dlg.currentStyleType();
1471 bool defaultLoadedFlag = false;
1472 switch ( type )
1473 {
1474 case QML:
1475 case SLD:
1476 {
1477 QString filePath = dlg.filePath();
1478 if ( type == SLD )
1479 {
1480 errorMsg = mLayer->loadSldStyle( filePath, defaultLoadedFlag );
1481 }
1482 else
1483 {
1484 errorMsg = mLayer->loadNamedStyle( filePath, defaultLoadedFlag, true, categories );
1485 }
1486 //reset if the default style was loaded OK only
1487 if ( defaultLoadedFlag )
1488 {
1489 syncToLayer();
1490 }
1491 else
1492 {
1493 //let the user know what went wrong
1494 QMessageBox::warning( this, tr( "Load Style" ), errorMsg );
1495 }
1496 break;
1497 }
1498 case DB:
1499 {
1500 QString selectedStyleId = dlg.selectedStyleId();
1501
1502 QString qmlStyle = mLayer->getStyleFromDatabase( selectedStyleId, errorMsg );
1503 if ( !errorMsg.isNull() )
1504 {
1505 QMessageBox::warning( this, tr( "Load Styles from Database" ), errorMsg );
1506 return;
1507 }
1508
1509 QDomDocument myDocument( QStringLiteral( "qgis" ) );
1510 myDocument.setContent( qmlStyle );
1511
1512 if ( mLayer->importNamedStyle( myDocument, errorMsg, categories ) )
1513 {
1514 syncToLayer();
1515 }
1516 else
1517 {
1518 QMessageBox::warning( this, tr( "Load Styles from Database" ),
1519 tr( "The retrieved style is not a valid named style. Error message: %1" )
1520 .arg( errorMsg ) );
1521 }
1522 break;
1523 }
1524 case Local:
1525 {
1526 errorMsg = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true, categories );
1527 //reset if the default style was loaded OK only
1528 if ( defaultLoadedFlag )
1529 {
1530 syncToLayer();
1531 }
1532 else
1533 {
1534 QMessageBox::warning( this, tr( "Load Default Style" ), errorMsg );
1535 }
1536 break;
1537 }
1538 }
1539 activateWindow(); // set focus back to properties dialog
1540 }
1541}
1542
1543void QgsVectorLayerProperties::mButtonAddJoin_clicked()
1544{
1545 if ( !mLayer )
1546 return;
1547
1548 QList<QgsMapLayer *> joinedLayers;
1549 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
1550 joinedLayers.reserve( joins.size() );
1551 for ( int i = 0; i < joins.size(); ++i )
1552 {
1553 joinedLayers.append( joins[i].joinLayer() );
1554 }
1555
1556 QgsJoinDialog d( mLayer, joinedLayers );
1557 if ( d.exec() == QDialog::Accepted )
1558 {
1559 QgsVectorLayerJoinInfo info = d.joinInfo();
1560 //create attribute index if possible
1561 if ( d.createAttributeIndex() )
1562 {
1563 QgsVectorLayer *joinLayer = info.joinLayer();
1564 if ( joinLayer )
1565 {
1566 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1567 }
1568 }
1569 mLayer->addJoin( info );
1570 addJoinToTreeWidget( info );
1571 setPbnQueryBuilderEnabled();
1572 mSourceFieldsPropertiesDialog->init();
1573 mAttributesFormPropertiesDialog->init();
1574 }
1575}
1576
1577void QgsVectorLayerProperties::mButtonEditJoin_clicked()
1578{
1579 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1580 mJoinTreeWidget_itemDoubleClicked( currentJoinItem, 0 );
1581}
1582
1583void QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1584{
1585 if ( !mLayer || !item )
1586 {
1587 return;
1588 }
1589
1590 QList<QgsMapLayer *> joinedLayers;
1591 QString joinLayerId = item->data( 0, Qt::UserRole ).toString();
1592 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
1593 int j = -1;
1594 for ( int i = 0; i < joins.size(); ++i )
1595 {
1596 QgsVectorLayer *joinLayer = joins[i].joinLayer();
1597 if ( !joinLayer )
1598 continue; // invalid join (unresolved join layer)
1599
1600 if ( joinLayer->id() == joinLayerId )
1601 {
1602 j = i;
1603 }
1604 else
1605 {
1606 // remove already joined layers from possible list to be displayed in dialog
1607 joinedLayers.append( joinLayer );
1608 }
1609 }
1610 if ( j == -1 )
1611 {
1612 return;
1613 }
1614
1615 QgsJoinDialog d( mLayer, joinedLayers );
1616 d.setWindowTitle( tr( "Edit Vector Join" ) );
1617 d.setJoinInfo( joins[j] );
1618
1619 if ( d.exec() == QDialog::Accepted )
1620 {
1621 QgsVectorLayerJoinInfo info = d.joinInfo();
1622
1623 // remove old join
1624 mLayer->removeJoin( joinLayerId );
1625 int idx = mJoinTreeWidget->indexOfTopLevelItem( item );
1626 mJoinTreeWidget->takeTopLevelItem( idx );
1627
1628 // add the new edited
1629
1630 //create attribute index if possible
1631 if ( d.createAttributeIndex() )
1632 {
1633 QgsVectorLayer *joinLayer = info.joinLayer();
1634 if ( joinLayer )
1635 {
1636 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1637 }
1638 }
1639 mLayer->addJoin( info );
1640 addJoinToTreeWidget( info, idx );
1641
1642 setPbnQueryBuilderEnabled();
1643 mSourceFieldsPropertiesDialog->init();
1644 mAttributesFormPropertiesDialog->init();
1645 }
1646}
1647
1648void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorLayerJoinInfo &join, const int insertIndex )
1649{
1650 QTreeWidgetItem *joinItem = new QTreeWidgetItem();
1651 joinItem->setFlags( Qt::ItemIsEnabled );
1652
1653 QgsVectorLayer *joinLayer = join.joinLayer();
1654 if ( !mLayer || !joinLayer )
1655 {
1656 return;
1657 }
1658
1659 joinItem->setText( 0, tr( "Join layer" ) );
1660 if ( mLayer->auxiliaryLayer() && mLayer->auxiliaryLayer()->id() == join.joinLayerId() )
1661 {
1662 return;
1663 }
1664
1665 joinItem->setText( 1, joinLayer->name() );
1666
1667 QFont f = joinItem->font( 0 );
1668 f.setBold( true );
1669 joinItem->setFont( 0, f );
1670 joinItem->setFont( 1, f );
1671
1672 joinItem->setData( 0, Qt::UserRole, join.joinLayerId() );
1673
1674 QTreeWidgetItem *childJoinField = new QTreeWidgetItem();
1675 childJoinField->setText( 0, tr( "Join field" ) );
1676 childJoinField->setText( 1, join.joinFieldName() );
1677 childJoinField->setFlags( Qt::ItemIsEnabled );
1678 joinItem->addChild( childJoinField );
1679
1680 QTreeWidgetItem *childTargetField = new QTreeWidgetItem();
1681 childTargetField->setText( 0, tr( "Target field" ) );
1682 childTargetField->setText( 1, join.targetFieldName() );
1683 joinItem->addChild( childTargetField );
1684
1685 QTreeWidgetItem *childMemCache = new QTreeWidgetItem();
1686 childMemCache->setText( 0, tr( "Cache join layer in virtual memory" ) );
1687 if ( join.isUsingMemoryCache() )
1688 childMemCache->setText( 1, QChar( 0x2714 ) );
1689 joinItem->addChild( childMemCache );
1690
1691 QTreeWidgetItem *childDynForm = new QTreeWidgetItem();
1692 childDynForm->setText( 0, tr( "Dynamic form" ) );
1693 if ( join.isDynamicFormEnabled() )
1694 childDynForm->setText( 1, QChar( 0x2714 ) );
1695 joinItem->addChild( childDynForm );
1696
1697 QTreeWidgetItem *childEditable = new QTreeWidgetItem();
1698 childEditable->setText( 0, tr( "Editable join layer" ) );
1699 if ( join.isEditable() )
1700 childEditable->setText( 1, QChar( 0x2714 ) );
1701 joinItem->addChild( childEditable );
1702
1703 QTreeWidgetItem *childUpsert = new QTreeWidgetItem();
1704 childUpsert->setText( 0, tr( "Upsert on edit" ) );
1705 if ( join.hasUpsertOnEdit() )
1706 childUpsert->setText( 1, QChar( 0x2714 ) );
1707 joinItem->addChild( childUpsert );
1708
1709 QTreeWidgetItem *childCascade = new QTreeWidgetItem();
1710 childCascade->setText( 0, tr( "Delete cascade" ) );
1711 if ( join.hasCascadedDelete() )
1712 childCascade->setText( 1, QChar( 0x2714 ) );
1713 joinItem->addChild( childCascade );
1714
1715 QTreeWidgetItem *childPrefix = new QTreeWidgetItem();
1716 childPrefix->setText( 0, tr( "Custom field name prefix" ) );
1717 childPrefix->setText( 1, join.prefix() );
1718 joinItem->addChild( childPrefix );
1719
1720 QTreeWidgetItem *childFields = new QTreeWidgetItem();
1721 childFields->setText( 0, tr( "Joined fields" ) );
1722 const QStringList *list = join.joinFieldNamesSubset();
1723 if ( list )
1724 childFields->setText( 1, QLocale().toString( list->count() ) );
1725 else
1726 childFields->setText( 1, tr( "all" ) );
1727 joinItem->addChild( childFields );
1728
1729 if ( insertIndex >= 0 )
1730 mJoinTreeWidget->insertTopLevelItem( insertIndex, joinItem );
1731 else
1732 mJoinTreeWidget->addTopLevelItem( joinItem );
1733
1734 mJoinTreeWidget->setCurrentItem( joinItem );
1735 mJoinTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1736}
1737
1738QgsExpressionContext QgsVectorLayerProperties::createExpressionContext() const
1739{
1740 return mContext;
1741}
1742
1743void QgsVectorLayerProperties::openPanel( QgsPanelWidget *panel )
1744{
1745 QDialog *dlg = new QDialog();
1746 QString key = QStringLiteral( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
1747 QgsSettings settings;
1748 dlg->restoreGeometry( settings.value( key ).toByteArray() );
1749 dlg->setWindowTitle( panel->panelTitle() );
1750 dlg->setLayout( new QVBoxLayout() );
1751 dlg->layout()->addWidget( panel );
1752 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
1753 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
1754 dlg->layout()->addWidget( buttonBox );
1755 dlg->exec();
1756 settings.setValue( key, dlg->saveGeometry() );
1757 panel->acceptPanel();
1758}
1759
1760void QgsVectorLayerProperties::mButtonRemoveJoin_clicked()
1761{
1762 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1763 if ( !mLayer || !currentJoinItem )
1764 {
1765 return;
1766 }
1767
1768 mLayer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
1769 mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
1770 setPbnQueryBuilderEnabled();
1771 mSourceFieldsPropertiesDialog->init();
1772 mAttributesFormPropertiesDialog->init();
1773}
1774
1775
1776void QgsVectorLayerProperties::mButtonAddWmsDimension_clicked()
1777{
1778 if ( !mLayer )
1779 return;
1780
1781 // get wms dimensions name
1782 QStringList alreadyDefinedDimensions;
1783 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1784 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1785 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : dims )
1786 {
1787 alreadyDefinedDimensions << dim.name;
1788 }
1789
1790 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1791 if ( d.exec() == QDialog::Accepted )
1792 {
1794 // save dimension
1795 serverProperties->addWmsDimension( info );
1796 addWmsDimensionInfoToTreeWidget( info );
1797 }
1798}
1799
1800void QgsVectorLayerProperties::mButtonEditWmsDimension_clicked()
1801{
1802 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1803 mWmsDimensionsTreeWidget_itemDoubleClicked( currentWmsDimensionItem, 0 );
1804}
1805
1806void QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1807{
1808 if ( !mLayer || !item )
1809 {
1810 return;
1811 }
1812
1813 QString wmsDimName = item->data( 0, Qt::UserRole ).toString();
1814 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1815 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1816 QStringList alreadyDefinedDimensions;
1817 int j = -1;
1818 for ( int i = 0; i < dims.size(); ++i )
1819 {
1820 QString dimName = dims[i].name;
1821 if ( dimName == wmsDimName )
1822 {
1823 j = i;
1824 }
1825 else
1826 {
1827 alreadyDefinedDimensions << dimName;
1828 }
1829 }
1830 if ( j == -1 )
1831 {
1832 return;
1833 }
1834
1835 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1836 d.setWindowTitle( tr( "Edit WMS Dimension" ) );
1837 d.setInfo( dims[j] );
1838
1839 if ( d.exec() == QDialog::Accepted )
1840 {
1842
1843 // remove old
1844 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1845 serverProperties->removeWmsDimension( wmsDimName );
1846 int idx = mWmsDimensionsTreeWidget->indexOfTopLevelItem( item );
1847 mWmsDimensionsTreeWidget->takeTopLevelItem( idx );
1848
1849 // save new
1850 serverProperties->addWmsDimension( info );
1851 addWmsDimensionInfoToTreeWidget( info, idx );
1852 }
1853}
1854
1855void QgsVectorLayerProperties::addWmsDimensionInfoToTreeWidget( const QgsMapLayerServerProperties::WmsDimensionInfo &wmsDim, const int insertIndex )
1856{
1857 QTreeWidgetItem *wmsDimensionItem = new QTreeWidgetItem();
1858 wmsDimensionItem->setFlags( Qt::ItemIsEnabled );
1859
1860 wmsDimensionItem->setText( 0, tr( "Dimension" ) );
1861 wmsDimensionItem->setText( 1, wmsDim.name );
1862
1863 QFont f = wmsDimensionItem->font( 0 );
1864 f.setBold( true );
1865 wmsDimensionItem->setFont( 0, f );
1866 wmsDimensionItem->setFont( 1, f );
1867
1868 wmsDimensionItem->setData( 0, Qt::UserRole, wmsDim.name );
1869
1870 QTreeWidgetItem *childWmsDimensionField = new QTreeWidgetItem();
1871 childWmsDimensionField->setText( 0, tr( "Field" ) );
1872 childWmsDimensionField->setText( 1, wmsDim.fieldName );
1873 childWmsDimensionField->setFlags( Qt::ItemIsEnabled );
1874 wmsDimensionItem->addChild( childWmsDimensionField );
1875
1876 QTreeWidgetItem *childWmsDimensionEndField = new QTreeWidgetItem();
1877 childWmsDimensionEndField->setText( 0, tr( "End field" ) );
1878 childWmsDimensionEndField->setText( 1, wmsDim.endFieldName );
1879 childWmsDimensionEndField->setFlags( Qt::ItemIsEnabled );
1880 wmsDimensionItem->addChild( childWmsDimensionEndField );
1881
1882 QTreeWidgetItem *childWmsDimensionUnits = new QTreeWidgetItem();
1883 childWmsDimensionUnits->setText( 0, tr( "Units" ) );
1884 childWmsDimensionUnits->setText( 1, wmsDim.units );
1885 childWmsDimensionUnits->setFlags( Qt::ItemIsEnabled );
1886 wmsDimensionItem->addChild( childWmsDimensionUnits );
1887
1888 QTreeWidgetItem *childWmsDimensionUnitSymbol = new QTreeWidgetItem();
1889 childWmsDimensionUnitSymbol->setText( 0, tr( "Unit symbol" ) );
1890 childWmsDimensionUnitSymbol->setText( 1, wmsDim.unitSymbol );
1891 childWmsDimensionUnitSymbol->setFlags( Qt::ItemIsEnabled );
1892 wmsDimensionItem->addChild( childWmsDimensionUnitSymbol );
1893
1894 QTreeWidgetItem *childWmsDimensionDefaultValue = new QTreeWidgetItem();
1895 childWmsDimensionDefaultValue->setText( 0, tr( "Default display" ) );
1896 childWmsDimensionDefaultValue->setText( 1, QgsMapLayerServerProperties::wmsDimensionDefaultDisplayLabels().value( wmsDim.defaultDisplayType ) );
1897 childWmsDimensionDefaultValue->setFlags( Qt::ItemIsEnabled );
1898 wmsDimensionItem->addChild( childWmsDimensionDefaultValue );
1899
1900 QTreeWidgetItem *childWmsDimensionRefValue = new QTreeWidgetItem();
1901 childWmsDimensionRefValue->setText( 0, tr( "Reference value" ) );
1902 childWmsDimensionRefValue->setText( 1, wmsDim.referenceValue.toString() );
1903 childWmsDimensionRefValue->setFlags( Qt::ItemIsEnabled );
1904 wmsDimensionItem->addChild( childWmsDimensionRefValue );
1905
1906 if ( insertIndex >= 0 )
1907 mWmsDimensionsTreeWidget->insertTopLevelItem( insertIndex, wmsDimensionItem );
1908 else
1909 mWmsDimensionsTreeWidget->addTopLevelItem( wmsDimensionItem );
1910
1911 mWmsDimensionsTreeWidget->setCurrentItem( wmsDimensionItem );
1912 mWmsDimensionsTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1913}
1914
1915void QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked()
1916{
1917 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1918 if ( !mLayer || !currentWmsDimensionItem )
1919 {
1920 return;
1921 }
1922
1923 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1924 serverProperties->removeWmsDimension( currentWmsDimensionItem->data( 0, Qt::UserRole ).toString() );
1925 mWmsDimensionsTreeWidget->takeTopLevelItem( mWmsDimensionsTreeWidget->indexOfTopLevelItem( currentWmsDimensionItem ) );
1926}
1927
1928
1929void QgsVectorLayerProperties::updateSymbologyPage()
1930{
1931
1932 //find out the type of renderer in the vectorlayer, create a dialog with these settings and add it to the form
1933 delete mRendererDialog;
1934 mRendererDialog = nullptr;
1935
1936 if ( mLayer->renderer() )
1937 {
1938 mRendererDialog = new QgsRendererPropertiesDialog( mLayer, QgsStyle::defaultStyle(), true, this );
1939 mRendererDialog->setDockMode( false );
1940 QgsSymbolWidgetContext context;
1941 context.setMapCanvas( mCanvas );
1942 context.setMessageBar( mMessageBar );
1943 mRendererDialog->setContext( context );
1944 connect( mRendererDialog, &QgsRendererPropertiesDialog::showPanel, this, &QgsVectorLayerProperties::openPanel );
1945 connect( mRendererDialog, &QgsRendererPropertiesDialog::layerVariablesChanged, this, &QgsVectorLayerProperties::updateVariableEditor );
1946 connect( mRendererDialog, &QgsRendererPropertiesDialog::widgetChanged, this, [ = ] { updateAuxiliaryStoragePage(); } );
1947 }
1948 else
1949 {
1950 mOptsPage_Style->setEnabled( false ); // hide symbology item
1951 }
1952
1953 if ( mRendererDialog )
1954 {
1955 mRendererDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
1956 widgetStackRenderers->addWidget( mRendererDialog );
1957 widgetStackRenderers->setCurrentWidget( mRendererDialog );
1958 widgetStackRenderers->currentWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
1959 }
1960}
1961
1962void QgsVectorLayerProperties::setPbnQueryBuilderEnabled()
1963{
1964 pbnQueryBuilder->setEnabled( mLayer &&
1965 mLayer->dataProvider() &&
1966 mLayer->dataProvider()->supportsSubsetString() &&
1967 !mLayer->isEditable() );
1968
1969 if ( mLayer && mLayer->isEditable() )
1970 {
1971 pbnQueryBuilder->setToolTip( tr( "Stop editing mode to enable this." ) );
1972 }
1973
1974}
1975
1976void QgsVectorLayerProperties::pbnUpdateExtents_clicked()
1977{
1978 mLayer->updateExtents( true ); // force update whatever options activated
1979 mMetadataFilled = false;
1980}
1981
1983{
1985
1986 bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
1987 mBtnStyle->setVisible( ! isMetadataPanel );
1988 mBtnMetadata->setVisible( isMetadataPanel );
1989
1990 if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) && ! mMetadataFilled )
1991 {
1992 //set the metadata contents (which can be expensive)
1993 teMetadataViewer->clear();
1994 teMetadataViewer->setHtml( htmlMetadata() );
1995 mMetadataFilled = true;
1996 }
1997
1998 resizeAlltabs( index );
1999}
2000
2001void QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled( bool checked )
2002{
2003 const QgsVectorDataProvider *provider = mLayer->dataProvider();
2004 if ( !( provider && ( provider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) != 0 ) )
2005 {
2006 mSimplifyDrawingAtProvider->setEnabled( false );
2007 }
2008 else
2009 {
2010 mSimplifyDrawingAtProvider->setEnabled( checked );
2011 }
2012}
2013
2014void QgsVectorLayerProperties::updateVariableEditor()
2015{
2016 QgsExpressionContext context;
2017 mVariableEditor->setContext( &context );
2018 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
2019 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
2020 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
2021 mVariableEditor->reloadContext();
2022 mVariableEditor->setEditableScopeIndex( 2 );
2023}
2024
2025void QgsVectorLayerProperties::showHelp()
2026{
2027 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
2028
2029 if ( helpPage.isValid() )
2030 {
2031 QgsHelp::openHelp( helpPage.toString() );
2032 }
2033 else
2034 {
2035 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html" ) );
2036 }
2037}
2038
2039void QgsVectorLayerProperties::updateAuxiliaryStoragePage()
2040{
2041 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2042
2043 if ( alayer )
2044 {
2045 // set widgets to enable state
2046 mAuxiliaryStorageInformationGrpBox->setEnabled( true );
2047 mAuxiliaryStorageFieldsGrpBox->setEnabled( true );
2048
2049 // update key
2050 mAuxiliaryStorageKeyLineEdit->setText( alayer->joinInfo().targetFieldName() );
2051
2052 // update feature count
2053 const qlonglong features = alayer->featureCount();
2054 mAuxiliaryStorageFeaturesLineEdit->setText( QLocale().toString( features ) );
2055
2056 // update actions
2057 mAuxiliaryLayerActionClear->setEnabled( true );
2058 mAuxiliaryLayerActionDelete->setEnabled( true );
2059 mAuxiliaryLayerActionExport->setEnabled( true );
2060 mAuxiliaryLayerActionNew->setEnabled( false );
2061
2062 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2063 if ( alayer )
2064 {
2065 const int fields = alayer->auxiliaryFields().count();
2066 mAuxiliaryStorageFieldsLineEdit->setText( QLocale().toString( fields ) );
2067
2068 // add fields
2069 mAuxiliaryStorageFieldsTree->clear();
2070 for ( const QgsField &field : alayer->auxiliaryFields() )
2071 {
2073 QTreeWidgetItem *item = new QTreeWidgetItem();
2074
2075 item->setText( 0, prop.origin() );
2076 item->setText( 1, prop.name() );
2077 item->setText( 2, prop.comment() );
2078 item->setText( 3, field.typeName() );
2079 item->setText( 4, field.name() );
2080
2081 mAuxiliaryStorageFieldsTree->addTopLevelItem( item );
2082 }
2083 }
2084 }
2085 else
2086 {
2087 mAuxiliaryStorageInformationGrpBox->setEnabled( false );
2088 mAuxiliaryStorageFieldsGrpBox->setEnabled( false );
2089
2090 mAuxiliaryLayerActionClear->setEnabled( false );
2091 mAuxiliaryLayerActionDelete->setEnabled( false );
2092 mAuxiliaryLayerActionExport->setEnabled( false );
2093 mAuxiliaryLayerActionNew->setEnabled( true );
2094
2095 mAuxiliaryStorageFieldsTree->clear();
2096 mAuxiliaryStorageKeyLineEdit->setText( QString() );
2097 mAuxiliaryStorageFieldsLineEdit->setText( QString() );
2098 mAuxiliaryStorageFeaturesLineEdit->setText( QString() );
2099 }
2100}
2101
2102void QgsVectorLayerProperties::onAuxiliaryLayerNew()
2103{
2104 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2105
2106 if ( alayer )
2107 return;
2108
2109 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
2110 if ( dlg.exec() == QDialog::Accepted )
2111 {
2112 updateAuxiliaryStoragePage();
2113 }
2114}
2115
2116void QgsVectorLayerProperties::onAuxiliaryLayerClear()
2117{
2118 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2119
2120 if ( !alayer )
2121 return;
2122
2123 const QString msg = tr( "Are you sure you want to clear auxiliary data for %1?" ).arg( mLayer->name() );
2124 QMessageBox::StandardButton reply;
2125 reply = QMessageBox::question( this, "Clear Auxiliary Data", msg, QMessageBox::Yes | QMessageBox::No );
2126
2127 if ( reply == QMessageBox::Yes )
2128 {
2129 QApplication::setOverrideCursor( Qt::WaitCursor );
2130 alayer->clear();
2131 QApplication::restoreOverrideCursor();
2132 updateAuxiliaryStoragePage();
2133 mLayer->triggerRepaint();
2134 }
2135}
2136
2137void QgsVectorLayerProperties::onAuxiliaryLayerDelete()
2138{
2139 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2140 if ( !alayer )
2141 return;
2142
2143 const QString msg = tr( "Are you sure you want to delete auxiliary storage for %1?" ).arg( mLayer->name() );
2144 QMessageBox::StandardButton reply;
2145 reply = QMessageBox::question( this, "Delete Auxiliary Storage", msg, QMessageBox::Yes | QMessageBox::No );
2146
2147 if ( reply == QMessageBox::Yes )
2148 {
2149 QApplication::setOverrideCursor( Qt::WaitCursor );
2150 QgsDataSourceUri uri( alayer->source() );
2151
2152 // delete each attribute to correctly update layer settings and data
2153 // defined buttons
2154 while ( alayer->auxiliaryFields().size() > 0 )
2155 {
2156 QgsField aField = alayer->auxiliaryFields()[0];
2157 deleteAuxiliaryField( alayer->fields().indexOf( aField.name() ) );
2158 }
2159
2160 mLayer->setAuxiliaryLayer(); // remove auxiliary layer
2162 QApplication::restoreOverrideCursor();
2163 updateAuxiliaryStoragePage();
2164 mLayer->triggerRepaint();
2165 }
2166}
2167
2168void QgsVectorLayerProperties::onAuxiliaryLayerDeleteField()
2169{
2170 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2171 if ( !alayer )
2172 return;
2173
2174 QList<QTreeWidgetItem *> items = mAuxiliaryStorageFieldsTree->selectedItems();
2175 if ( items.count() < 1 )
2176 return;
2177
2178 // get auxiliary field name and index from item
2179 const QTreeWidgetItem *item = items[0];
2181 def.setOrigin( item->text( 0 ) );
2182 def.setName( item->text( 1 ) );
2183 def.setComment( item->text( 2 ) );
2184
2185 const QString fieldName = QgsAuxiliaryLayer::nameFromProperty( def );
2186
2187 const int index = mLayer->auxiliaryLayer()->fields().indexOf( fieldName );
2188 if ( index < 0 )
2189 return;
2190
2191 // should be only 1 field
2192 const QString msg = tr( "Are you sure you want to delete auxiliary field %1 for %2?" ).arg( item->text( 1 ), item->text( 0 ) );
2193
2194 QMessageBox::StandardButton reply;
2195 const QString title = QObject::tr( "Delete Auxiliary Field" );
2196 reply = QMessageBox::question( this, title, msg, QMessageBox::Yes | QMessageBox::No );
2197
2198 if ( reply == QMessageBox::Yes )
2199 {
2200 QApplication::setOverrideCursor( Qt::WaitCursor );
2201 deleteAuxiliaryField( index );
2202 mLayer->triggerRepaint();
2203 QApplication::restoreOverrideCursor();
2204 }
2205}
2206
2207void QgsVectorLayerProperties::onAuxiliaryLayerAddField()
2208{
2209 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2210 if ( !alayer )
2211 return;
2212
2213 QgsNewAuxiliaryFieldDialog dlg( QgsPropertyDefinition(), mLayer, false );
2214 if ( dlg.exec() == QDialog::Accepted )
2215 {
2216 updateAuxiliaryStoragePage();
2217 }
2218}
2219
2220void QgsVectorLayerProperties::deleteAuxiliaryField( int index )
2221{
2222 if ( !mLayer->auxiliaryLayer() )
2223 return;
2224
2225 int key = mLayer->auxiliaryLayer()->propertyFromIndex( index );
2227
2228 if ( mLayer->auxiliaryLayer()->deleteAttribute( index ) )
2229 {
2230 mLayer->updateFields();
2231
2232 // immediately deactivate data defined button
2233 if ( key >= 0 && def.origin().compare( "labeling", Qt::CaseInsensitive ) == 0
2234 && labelingDialog
2235 && labelingDialog->labelingGui() )
2236 {
2237 labelingDialog->labelingGui()->deactivateField( static_cast<QgsPalLayerSettings::Property>( key ) );
2238 }
2239
2240 updateAuxiliaryStoragePage();
2241 mSourceFieldsPropertiesDialog->init();
2242 }
2243 else
2244 {
2245 const QString title = QObject::tr( "Delete Auxiliary Field" );
2246 const QString errors = mLayer->auxiliaryLayer()->commitErrors().join( QLatin1String( "\n " ) );
2247 const QString msg = QObject::tr( "Unable to remove auxiliary field (%1)" ).arg( errors );
2248 mMessageBar->pushMessage( title, msg, Qgis::MessageLevel::Warning );
2249 }
2250}
@ NoVendorExtension
No vendor extensions.
static QString defaultProjectScales()
A string with default project scales.
Definition: qgis.cpp:271
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.
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 syncToLayer()
Updates the widget to reflect the layer's current diagram settings.
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...
bool forceRasterRender() const
Returns whether the renderer must render as a raster.
Definition: qgsrenderer.h:450
void setForceRasterRender(bool forceRaster)
Sets whether the renderer should be rendered to a raster destination.
Definition: qgsrenderer.h:460
double referenceScale() const
Returns the symbology reference scale.
Definition: qgsrenderer.h:476
void setReferenceScale(double scale)
Sets the symbology reference scale.
Definition: qgsrenderer.h:492
@ SpatialIndexPresent
A valid spatial index exists for the source.
virtual SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:52
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:150
QString name
Definition: qgsfield.h:61
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
static QgsProviderSourceWidgetProviderRegistry * sourceWidgetProviderRegistry()
Returns the registry of provider source widget providers.
Definition: qgsgui.cpp:108
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition: qgsgui.cpp:73
static QgsSubsetStringEditorProviderRegistry * subsetStringEditorProviderRegistry()
Returns the registry of subset string editors of data providers.
Definition: qgsgui.cpp:103
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:38
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
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.
Definition: qgsmapcanvas.h:90
double scale() const
Returns the last reported scale of the canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Factory class for creating custom map layer property pages.
virtual bool supportsLayer(QgsMapLayer *layer) const
Check if the layer is supported for this widget.
virtual QIcon icon() const
The icon that will be shown in the UI for the panel.
virtual QgsMapLayerConfigWidget * createWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, bool dockWidget=true, QWidget *parent=nullptr) const =0
Factory function to create the widget on demand as needed by the dock.
virtual QString title() const
The title of the panel.
virtual bool supportLayerPropertiesDialog() const
Flag if widget is supported for use in layer properties dialog.
virtual QString layerPropertiesPagePositionHint() const
Returns a tab name hinting at where this page should be inserted into the layer properties tab list.
A panel widget that can be shown in the map style dock.
This class models dependencies with or between map layers.
A reusable dialog which allows users to select stored layer styles and categories to load for a map l...
Manages QGIS Server properties for a map layer.
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.
static bool isDefault(const QString &styleName)
Returns true if this is the default style.
QgsMapLayerStyle style(const QString &name) const
Returns data of a stored style - accessed by its unique name.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
QString xmlData() const
Returns XML content of the style.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
void setShortName(const QString &shortName)
Sets the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:288
QString name
Definition: qgsmaplayer.h:76
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:1318
void setRefreshOnNotifyEnabled(bool enabled)
Set whether provider notification is connected to triggerRepaint.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:317
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.
Definition: qgsmaplayer.h:1303
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:79
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Definition: qgsmaplayer.h:420
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:395
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
virtual QString loadNamedMetadata(const QString &uri, bool &resultFlag)
Retrieve a named metadata for this layer if one exists (either as a .qmd file on disk or as a record ...
bool hasAutoRefreshEnabled() const
Returns true if auto refresh is enabled for the layer.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
void setAttributionUrl(const QString &attribUrl)
Sets the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:403
void setAutoRefreshEnabled(bool enabled)
Sets whether auto refresh is enabled for the layer.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:325
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:376
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:350
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:332
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:386
bool isRefreshOnNotifyEnabled() const
Returns true if the refresh on provider nofification is enabled.
Definition: qgsmaplayer.h:1480
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
virtual QString loadSldStyle(const QString &uri, bool &resultFlag)
Attempts to style the layer using the formatting from an SLD type file.
virtual QString saveDefaultMetadata(bool &resultFlag)
Save the current metadata of this layer as the default metadata (either as a .qmd file on disk or as ...
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:367
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:310
virtual QString styleURI() const
Retrieve the style URI for this layer (either as a .qml file on disk or as a record in the users styl...
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:359
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,...
Definition: qgsmaplayer.h:1655
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:69
virtual QString saveSldStyleV2(bool &resultFlag, const QgsSldExportContext &exportContext) const
Saves the properties of this layer to an SLD format file.
void setName(const QString &name)
Set the display name of the layer.
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
QString saveNamedMetadata(const QString &uri, bool &resultFlag)
Save the current metadata of this layer as a named metadata (either as a .qmd file on disk or as a re...
QString refreshOnNotifyMessage() const
Returns the message that should be notified by the provider to triggerRepaint.
Definition: qgsmaplayer.h:1473
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:412
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Updates the data source of the 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.
Definition: qgsmaplayer.h:1308
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1313
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.
virtual QString metadataUri() const
Retrieve the metadata URI for this layer (either as a .qmd file on disk or as a record in the users s...
int autoRefreshInterval
Definition: qgsmaplayer.h:77
virtual QString saveDefaultStyle(bool &resultFlag, StyleCategories categories)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
double maximumScale() const
Returns the maximum map scale (i.e.
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:340
QString mapTipTemplate
Definition: qgsmaplayer.h:83
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:302
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
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.
A base dialog for options and properties dialogs that offers vertical tabs.
void resizeAlltabs(int index)
Resizes all tabs when the dialog is resized.
void addPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QStringList &path=QStringList())
Adds a new page to the dialog pages.
virtual void optionsStackedWidget_CurrentChanged(int index)
Select relevant tab on current page change.
void insertPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QString &before, const QStringList &path=QStringList())
Inserts a new page into the dialog pages.
void restoreOptionsBaseUi(const QString &title=QString())
Restore the base ui.
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.
Definition: qgsproject.cpp:477
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).
Definition: qgsproject.cpp:596
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
Definition for a property.
Definition: qgsproperty.h:46
QString comment() const
Returns the comment of the property.
Definition: qgsproperty.h:167
void setOrigin(const QString &origin)
Sets the origin of the property.
Definition: qgsproperty.h:157
QString name() const
Returns the name of the property.
Definition: qgsproperty.h:138
void setName(const QString &name)
Sets the name of the property.
Definition: qgsproperty.h:143
QString origin() const
Returns the origin of the property.
Definition: qgsproperty.h:150
void setComment(const QString &comment)
Sets comment of the property.
Definition: qgsproperty.h:172
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.
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 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:63
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.
The QgsSldExportContext class holds SLD export options and other information related to SLD export of...
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
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.
This is the base class for vector data providers.
static QStringList availableEncodings()
Returns a list of available encodings.
@ 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.
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
QString encoding() const
Returns the encoding which is used for accessing data.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
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)
QgsVectorLayerProperties(QgsMapCanvas *canvas, QgsMessageBar *messageBar, QgsVectorLayer *lyr=nullptr, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
void addPropertiesPageFactory(const QgsMapLayerConfigWidgetFactory *factory)
Adds a properties page factory to the vector layer properties dialog.
void optionsStackedWidget_CurrentChanged(int index) final
void toggleEditing(QgsMapLayer *)
void exportAuxiliaryLayer(QgsAuxiliaryLayer *layer)
The QgsVectorLayerSaveStyleDialog class provides the UI to save the current style or multiple styles ...
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.
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.
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.
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 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...
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Loads a named style from file/local db/datasource db.
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Returns the named style corresponding to style id provided.
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 subsetString
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
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,...
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
@ GeometrySimplification
The geometries can be simplified using the current map2pixel context state.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
@ NoSimplification
No simplification can be applied.
SimplifyAlgorithm
Types of local simplification algorithms that can be used.
@ 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...
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
The QgsWmsDimensionDialog class provides an interface for WMS/OAPIF (WFS3) dimensions configuration A...
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:4093
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:4092
const QgsField & field
Definition: qgsfield.h:501
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
QString format
Format specification of online resource.
Setting to define QGIS Server WMS Dimension.