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