QGIS API Documentation 3.32.0-Lima (311a8cb8a6)
qgsvectorlayerproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdlgvectorlayerproperties.cpp
3 Unified property dialog for vector layers
4 -------------------
5 begin : 2004-01-28
6 copyright : (C) 2004 by Gary E.Sherman
7 email : sherman at mrcc.com
8***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19#include <memory>
20#include <limits>
21
22#include "qgsactionmanager.h"
23#include "qgsjoindialog.h"
24#include "qgssldexportcontext.h"
26#include "qgsapplication.h"
32#include "qgslabelingwidget.h"
33#include "qgsmapcanvas.h"
36#include "qgsmetadatawidget.h"
38#include "qgsproject.h"
39#include "qgsvectorlayer.h"
44#include "qgsdatasourceuri.h"
45#include "qgsrenderer.h"
47#include "qgssettings.h"
49#include "qgsstyle.h"
50#include "qgsauxiliarystorage.h"
54#include "qgslabelinggui.h"
57#include "qgsmessagebar.h"
60#include "qgsmaskingwidget.h"
63#include "qgsproviderregistry.h"
65#include "qgslayertreemodel.h"
66#include "qgsmaptip.h"
67#include "qgsgui.h"
68#include "qgsnative.h"
71#include "qgswebview.h"
72#include "qgswebframe.h"
73#if WITH_QTWEBKIT
74#include <QWebElement>
75#endif
76
77#include <QDesktopServices>
78#include <QMessageBox>
79#include <QDir>
80#include <QFile>
81#include <QFileDialog>
82#include <QFileInfo>
83#include <QFontDialog>
84#include <QComboBox>
85#include <QCheckBox>
86#include <QHeaderView>
87#include <QColorDialog>
88#include <QMenu>
89#include <QUrl>
90#include <QRegularExpressionValidator>
91
92
94 QgsMapCanvas *canvas,
95 QgsMessageBar *messageBar,
96 QgsVectorLayer *lyr,
97 QWidget *parent,
98 Qt::WindowFlags fl
99)
100 : QgsOptionsDialogBase( QStringLiteral( "VectorLayerProperties" ), parent, fl )
101 , mCanvas( canvas )
102 , mMessageBar( messageBar )
103 , mLayer( lyr )
104 , mOriginalSubsetSQL( lyr->subsetString() )
105{
106 setupUi( this );
107 connect( pbnQueryBuilder, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnQueryBuilder_clicked );
108 connect( pbnIndex, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnIndex_clicked );
109 connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerProperties::mCrsSelector_crsChanged );
110 connect( pbnUpdateExtents, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnUpdateExtents_clicked );
111 connect( mButtonAddJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddJoin_clicked );
112 connect( mButtonEditJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditJoin_clicked );
113 connect( mJoinTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked );
114 connect( mButtonRemoveJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveJoin_clicked );
115 connect( mButtonAddWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddWmsDimension_clicked );
116 connect( mButtonEditWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditWmsDimension_clicked );
117 connect( mWmsDimensionsTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked );
118 connect( mButtonRemoveWmsDimension, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked );
119 connect( mSimplifyDrawingGroupBox, &QGroupBox::toggled, this, &QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled );
120 connect( buttonRemoveMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::removeSelectedMetadataUrl );
121 connect( buttonAddMetadataUrl, &QPushButton::clicked, this, &QgsVectorLayerProperties::addMetadataUrl );
122 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerProperties::showHelp );
123
124 // QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
125 // switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
126 // and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
127 initOptionsBase( false );
128
129 mBtnStyle = new QPushButton( tr( "Style" ), this );
130 QMenu *menuStyle = new QMenu( this );
131 mActionLoadStyle = new QAction( tr( "Load Style…" ), this );
132 connect( mActionLoadStyle, &QAction::triggered, this, &QgsVectorLayerProperties::loadStyle );
133
134 mActionSaveStyle = new QAction( tr( "Save Current Style…" ), this );
135 connect( mActionSaveStyle, &QAction::triggered, this, &QgsVectorLayerProperties::saveStyleAs );
136
137 mActionSaveMultipleStyles = new QAction( tr( "Save Multiple Styles…" ), this );
138 connect( mActionSaveMultipleStyles, &QAction::triggered, this, &QgsVectorLayerProperties::saveMultipleStylesAs );
139
140 mSourceGroupBox->hide();
141
142 mBtnStyle->setMenu( menuStyle );
143 connect( menuStyle, &QMenu::aboutToShow, this, &QgsVectorLayerProperties::aboutToShowStyleMenu );
144 buttonBox->addButton( mBtnStyle, QDialogButtonBox::ResetRole );
145
146 mBtnMetadata = new QPushButton( tr( "Metadata" ), this );
147 QMenu *menuMetadata = new QMenu( this );
148 mActionLoadMetadata = menuMetadata->addAction( tr( "Load Metadata…" ), this, &QgsVectorLayerProperties::loadMetadata );
149 mActionSaveMetadataAs = menuMetadata->addAction( tr( "Save Metadata…" ), this, &QgsVectorLayerProperties::saveMetadataAs );
150 menuMetadata->addSeparator();
151 menuMetadata->addAction( tr( "Save as Default" ), this, &QgsVectorLayerProperties::saveDefaultMetadata );
152 menuMetadata->addAction( tr( "Restore Default" ), this, &QgsVectorLayerProperties::loadDefaultMetadata );
153 mBtnMetadata->setMenu( menuMetadata );
154 buttonBox->addButton( mBtnMetadata, QDialogButtonBox::ResetRole );
155
156 connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsVectorLayerProperties::syncToLayer );
157
158 connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsVectorLayerProperties::apply );
159 connect( this, &QDialog::accepted, this, &QgsVectorLayerProperties::apply );
160 connect( this, &QDialog::rejected, this, &QgsVectorLayerProperties::onCancel );
161
167
168 mMapTipExpressionFieldWidget->setLayer( lyr );
169 mMapTipExpressionFieldWidget->registerExpressionContextGenerator( this );
170 mDisplayExpressionWidget->setLayer( lyr );
171 mDisplayExpressionWidget->registerExpressionContextGenerator( this );
172 initMapTipPreview();
173
174 connect( mInsertExpressionButton, &QAbstractButton::clicked, this, &QgsVectorLayerProperties::insertFieldOrExpression );
175
176 if ( !mLayer )
177 return;
178
179 connect( mEnableMapTips, &QAbstractButton::toggled, mHtmlMapTipGroupBox, &QWidget::setEnabled );
180 mEnableMapTips->setChecked( mLayer->mapTipsEnabled() );
181
182 QVBoxLayout *layout = nullptr;
183
184 if ( mLayer->isSpatial() )
185 {
186 // Create the Labeling dialog tab
187 layout = new QVBoxLayout( labelingFrame );
188 layout->setContentsMargins( 0, 0, 0, 0 );
189 labelingDialog = new QgsLabelingWidget( mLayer, mCanvas, labelingFrame );
190 labelingDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
191 connect( labelingDialog, &QgsLabelingWidget::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
192 layout->addWidget( labelingDialog );
193 labelingFrame->setLayout( layout );
194
195 // Create the masking dialog tab
196 layout = new QVBoxLayout( mMaskingFrame );
197 layout->setContentsMargins( 0, 0, 0, 0 );
198 mMaskingWidget = new QgsMaskingWidget( mMaskingFrame );
199 mMaskingWidget->setLayer( mLayer );
200 mMaskingWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
201 layout->addWidget( mMaskingWidget );
202 mMaskingFrame->setLayout( layout );
203 }
204 else
205 {
206 labelingDialog = nullptr;
207 mOptsPage_Labels->setEnabled( false ); // disable labeling item
208 mOptsPage_Masks->setEnabled( false ); // disable masking item
209 mGeomGroupBox->setEnabled( false );
210 mGeomGroupBox->setVisible( false );
211 mCrsGroupBox->setEnabled( false );
212 mCrsGroupBox->setVisible( false );
213 }
214
215 // Create the Actions dialog tab
216 QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
217 actionLayout->setContentsMargins( 0, 0, 0, 0 );
218 mActionDialog = new QgsAttributeActionDialog( *mLayer->actions(), actionOptionsFrame );
219 mActionDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
220 actionLayout->addWidget( mActionDialog );
221
222 mSourceFieldsPropertiesDialog = new QgsSourceFieldsProperties( mLayer, mSourceFieldsFrame );
223 mSourceFieldsPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
224 mSourceFieldsFrame->setLayout( new QVBoxLayout( mSourceFieldsFrame ) );
225 mSourceFieldsFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
226 mSourceFieldsFrame->layout()->addWidget( mSourceFieldsPropertiesDialog );
227
228 connect( mSourceFieldsPropertiesDialog, &QgsSourceFieldsProperties::toggleEditing, this, static_cast<void ( QgsVectorLayerProperties::* )()>( &QgsVectorLayerProperties::toggleEditing ) );
229
230 mAttributesFormPropertiesDialog = new QgsAttributesFormProperties( mLayer, mAttributesFormFrame );
231 mAttributesFormPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
232 mAttributesFormFrame->setLayout( new QVBoxLayout( mAttributesFormFrame ) );
233 mAttributesFormFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
234 mAttributesFormFrame->layout()->addWidget( mAttributesFormPropertiesDialog );
235
236 // Metadata tab, before the syncToLayer
237 QVBoxLayout *metadataLayout = new QVBoxLayout( metadataFrame );
238 metadataLayout->setContentsMargins( 0, 0, 0, 0 );
239 mMetadataWidget = new QgsMetadataWidget( this, mLayer );
240 mMetadataWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
241 mMetadataWidget->setMapCanvas( mCanvas );
242 metadataLayout->addWidget( mMetadataWidget );
243 metadataFrame->setLayout( metadataLayout );
244
245 QVBoxLayout *temporalLayout = new QVBoxLayout( temporalFrame );
246 temporalLayout->setContentsMargins( 0, 0, 0, 0 );
247 mTemporalWidget = new QgsVectorLayerTemporalPropertiesWidget( this, mLayer );
248 temporalLayout->addWidget( mTemporalWidget );
249
250 syncToLayer();
251
252 if ( mLayer->dataProvider() )
253 {
254 //enable spatial index button group if supported by provider, or if one already exists
255 QgsVectorDataProvider::Capabilities capabilities = mLayer->dataProvider()->capabilities();
256 if ( !( capabilities & QgsVectorDataProvider::CreateSpatialIndex ) )
257 {
258 pbnIndex->setEnabled( false );
259 }
261 {
262 pbnIndex->setEnabled( false );
263 pbnIndex->setText( tr( "Spatial Index Exists" ) );
264 }
265
266 if ( capabilities & QgsVectorDataProvider::SelectEncoding )
267 {
268 cboProviderEncoding->addItems( QgsVectorDataProvider::availableEncodings() );
269 QString enc = mLayer->dataProvider()->encoding();
270 int encindex = cboProviderEncoding->findText( enc );
271 if ( encindex < 0 )
272 {
273 cboProviderEncoding->insertItem( 0, enc );
274 encindex = 0;
275 }
276 cboProviderEncoding->setCurrentIndex( encindex );
277 }
278 else if ( mLayer->providerType() == QLatin1String( "ogr" ) )
279 {
280 // if OGR_L_TestCapability(OLCStringsAsUTF8) returns true, OGR provider encoding can be set to only UTF-8
281 // so make encoding box grayed out
282 cboProviderEncoding->addItem( mLayer->dataProvider()->encoding() );
283 cboProviderEncoding->setEnabled( false );
284 }
285 else
286 {
287 // other providers do not use mEncoding, so hide the group completely
288 mDataSourceEncodingFrame->hide();
289 }
290 }
291
292 mCrsSelector->setCrs( mLayer->crs() );
293
294 //insert existing join info
295 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
296 for ( const QgsVectorLayerJoinInfo &join : joins )
297 {
298 addJoinToTreeWidget( join );
299 }
300
301 mOldJoins = mLayer->vectorJoins();
302
303 QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
304 diagLayout->setContentsMargins( 0, 0, 0, 0 );
305 diagramPropertiesDialog = new QgsDiagramProperties( mLayer, mDiagramFrame, mCanvas );
306 diagramPropertiesDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
307 connect( diagramPropertiesDialog, &QgsDiagramProperties::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
308 diagLayout->addWidget( diagramPropertiesDialog );
309 mDiagramFrame->setLayout( diagLayout );
310
311 // Legend tab
312 mLegendWidget->setMapCanvas( mCanvas );
313 mLegendWidget->setLayer( mLayer );
314 mLegendConfigEmbeddedWidget->setLayer( mLayer );
315
316 // WMS Name as layer short name
317 mLayerShortNameLineEdit->setText( mLayer->shortName() );
318 // WMS Name validator
319 QValidator *shortNameValidator = new QRegularExpressionValidator( QgsApplication::shortNameRegularExpression(), this );
320 mLayerShortNameLineEdit->setValidator( shortNameValidator );
321
322 //layer title and abstract
323 mLayerTitleLineEdit->setText( mLayer->title() );
324 mLayerAbstractTextEdit->setPlainText( mLayer->abstract() );
325 mLayerKeywordListLineEdit->setText( mLayer->keywordList() );
326 mLayerDataUrlLineEdit->setText( mLayer->dataUrl() );
327 mLayerDataUrlFormatComboBox->setCurrentIndex(
328 mLayerDataUrlFormatComboBox->findText(
329 mLayer->dataUrlFormat()
330 )
331 );
332 //layer attribution
333 mLayerAttributionLineEdit->setText( mLayer->attribution() );
334 mLayerAttributionUrlLineEdit->setText( mLayer->attributionUrl() );
335
336 // Setup the layer metadata URL
337 tableViewMetadataUrl->setSelectionMode( QAbstractItemView::SingleSelection );
338 tableViewMetadataUrl->setSelectionBehavior( QAbstractItemView::SelectRows );
339 tableViewMetadataUrl->horizontalHeader()->setStretchLastSection( true );
340 tableViewMetadataUrl->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
341
342 mMetadataUrlModel = new QStandardItemModel( tableViewMetadataUrl );
343 mMetadataUrlModel->clear();
344 mMetadataUrlModel->setColumnCount( 3 );
345 QStringList metadataUrlHeaders;
346 metadataUrlHeaders << tr( "URL" ) << tr( "Type" ) << tr( "Format" );
347 mMetadataUrlModel->setHorizontalHeaderLabels( metadataUrlHeaders );
348 tableViewMetadataUrl->setModel( mMetadataUrlModel );
349 tableViewMetadataUrl->setItemDelegate( new MetadataUrlItemDelegate( this ) );
350
351 const QList<QgsMapLayerServerProperties::MetadataUrl> &metaUrls = mLayer->serverProperties()->metadataUrls();
352 for ( const QgsMapLayerServerProperties::MetadataUrl &metaUrl : metaUrls )
353 {
354 const int row = mMetadataUrlModel->rowCount();
355 mMetadataUrlModel->setItem( row, 0, new QStandardItem( metaUrl.url ) );
356 mMetadataUrlModel->setItem( row, 1, new QStandardItem( metaUrl.type ) );
357 mMetadataUrlModel->setItem( row, 2, new QStandardItem( metaUrl.format ) );
358 }
359
360 // layer legend url
361 mLayerLegendUrlLineEdit->setText( mLayer->legendUrl() );
362 mLayerLegendUrlFormatComboBox->setCurrentIndex(
363 mLayerLegendUrlFormatComboBox->findText(
364 mLayer->legendUrlFormat()
365 )
366 );
367
368 //insert existing dimension info
369 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
370 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &wmsDims = serverProperties->wmsDimensions();
371 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : wmsDims )
372 {
373 addWmsDimensionInfoToTreeWidget( dim );
374 }
375
376 QString myStyle = QgsApplication::reportStyleSheet();
377 myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
378 teMetadataViewer->clear();
379 teMetadataViewer->document()->setDefaultStyleSheet( myStyle );
380 teMetadataViewer->setHtml( htmlMetadata() );
381 teMetadataViewer->setOpenLinks( false );
382 connect( teMetadataViewer, &QTextBrowser::anchorClicked, this, &QgsVectorLayerProperties::urlClicked );
383 mMetadataFilled = true;
384
385 QgsSettings settings;
386 // if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
387 // this will be read by restoreOptionsBaseUi()
388 if ( !settings.contains( QStringLiteral( "/Windows/VectorLayerProperties/tab" ) ) )
389 {
390 settings.setValue( QStringLiteral( "Windows/VectorLayerProperties/tab" ),
391 mOptStackedWidget->indexOf( mOptsPage_Style ) );
392 }
393
394 QString title = tr( "Layer Properties — %1" ).arg( mLayer->name() );
395 if ( !mLayer->styleManager()->isDefault( mLayer->styleManager()->currentStyle() ) )
396 title += QStringLiteral( " (%1)" ).arg( mLayer->styleManager()->currentStyle() );
397 restoreOptionsBaseUi( title );
398
399 QList<QgsMapLayer *> dependencySources;
400 const QSet<QgsMapLayerDependency> constDependencies = mLayer->dependencies();
401 for ( const QgsMapLayerDependency &dep : constDependencies )
402 {
403 QgsMapLayer *layer = QgsProject::instance()->mapLayer( dep.layerId() );
404 if ( layer )
405 dependencySources << layer;
406 }
407
408 mLayersDependenciesTreeModel = new QgsLayerTreeFilterProxyModel( this );
409 mLayersDependenciesTreeModel->setLayerTreeModel( new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot(), mLayersDependenciesTreeModel ) );
410 mLayersDependenciesTreeModel->setCheckedLayers( dependencySources );
411 connect( QgsProject::instance(), &QObject::destroyed, this, [ = ] {mLayersDependenciesTreeView->setModel( nullptr );} );
412 mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel );
413
414 connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );
415
416 // auxiliary layer
417 QMenu *menu = new QMenu( this );
418
419 mAuxiliaryLayerActionNew = new QAction( tr( "Create" ), this );
420 menu->addAction( mAuxiliaryLayerActionNew );
421 connect( mAuxiliaryLayerActionNew, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerNew );
422
423 mAuxiliaryLayerActionClear = new QAction( tr( "Clear" ), this );
424 menu->addAction( mAuxiliaryLayerActionClear );
425 connect( mAuxiliaryLayerActionClear, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerClear );
426
427 mAuxiliaryLayerActionDelete = new QAction( tr( "Delete" ), this );
428 menu->addAction( mAuxiliaryLayerActionDelete );
429 connect( mAuxiliaryLayerActionDelete, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerDelete );
430
431 mAuxiliaryLayerActionExport = new QAction( tr( "Export" ), this );
432 menu->addAction( mAuxiliaryLayerActionExport );
433 connect( mAuxiliaryLayerActionExport, &QAction::triggered, this, [ = ] { emit exportAuxiliaryLayer( mLayer->auxiliaryLayer() ); } );
434
435 mAuxiliaryStorageActions->setMenu( menu );
436
437 connect( mAuxiliaryStorageFieldsDeleteBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerDeleteField );
438 connect( mAuxiliaryStorageFieldsAddBtn, &QPushButton::clicked, this, &QgsVectorLayerProperties::onAuxiliaryLayerAddField );
439
440 updateAuxiliaryStoragePage();
441
442 mOptsPage_Information->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#information-properties" ) );
443 mOptsPage_Source->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#source-properties" ) );
444 mOptsPage_Style->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#symbology-properties" ) );
445 mOptsPage_Labels->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#labels-properties" ) );
446 mOptsPage_Masks->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#masks-properties" ) );
447 mOptsPage_Diagrams->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#diagrams-properties" ) );
448 mOptsPage_SourceFields->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#fields-properties" ) );
449 mOptsPage_AttributesForm->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#attributes-form-properties" ) );
450 mOptsPage_Joins->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#joins-properties" ) );
451 mOptsPage_AuxiliaryStorage->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#auxiliary-storage-properties" ) );
452 mOptsPage_Actions->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#actions-properties" ) );
453 mOptsPage_Display->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#display-properties" ) );
454 mOptsPage_Rendering->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#rendering-properties" ) );
455 mOptsPage_Temporal->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#temporal-properties" ) );
456 mOptsPage_Variables->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#variables-properties" ) );
457 mOptsPage_Metadata->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#metadata-properties" ) );
458 mOptsPage_DataDependencies->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#dependencies-properties" ) ) ;
459 mOptsPage_Legend->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#legend-properties" ) );
460 mOptsPage_Server->setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#qgis-server-properties" ) );
461
462
464}
465
466void QgsVectorLayerProperties::toggleEditing()
467{
468 if ( !mLayer )
469 return;
470
471 emit toggleEditing( mLayer );
472
473 setPbnQueryBuilderEnabled();
474}
475
477{
478 if ( !factory->supportsLayer( mLayer ) || !factory->supportLayerPropertiesDialog() )
479 {
480 return;
481 }
482
483 QgsMapLayerConfigWidget *page = factory->createWidget( mLayer, nullptr, false, this );
484
485 if ( page )
486 {
487 mLayerPropertiesPages << page;
488
489 const QString beforePage = factory->layerPropertiesPagePositionHint();
490 if ( beforePage.isEmpty() )
491 addPage( factory->title(), factory->title(), factory->icon(), page );
492 else
493 insertPage( factory->title(), factory->title(), factory->icon(), page, beforePage );
494 }
495}
496
497void QgsVectorLayerProperties::insertFieldOrExpression()
498{
499 // Convert the selected field to an expression and
500 // insert it into the action at the cursor position
501 QString expression = QStringLiteral( "[% " );
502 expression += mMapTipExpressionFieldWidget->asExpression();
503 expression += QLatin1String( " %]" );
504
505 mMapTipWidget->insertText( expression );
506}
507
508void QgsVectorLayerProperties::addMetadataUrl()
509{
510 const int row = mMetadataUrlModel->rowCount();
511 mMetadataUrlModel->setItem( row, 0, new QStandardItem( QLatin1String() ) );
512 mMetadataUrlModel->setItem( row, 1, new QStandardItem( QLatin1String() ) );
513 mMetadataUrlModel->setItem( row, 2, new QStandardItem( QLatin1String() ) );
514}
515
516void QgsVectorLayerProperties::removeSelectedMetadataUrl()
517{
518 const QModelIndexList selectedRows = tableViewMetadataUrl->selectionModel()->selectedRows();
519 if ( selectedRows.empty() )
520 return;
521 mMetadataUrlModel->removeRow( selectedRows[0].row() );
522}
523
524// in raster props, this method is called sync()
525void QgsVectorLayerProperties::syncToLayer()
526{
527 if ( !mSourceWidget )
528 {
529 mSourceWidget = QgsGui::sourceWidgetProviderRegistry()->createWidget( mLayer );
530 if ( mSourceWidget )
531 {
532 QHBoxLayout *layout = new QHBoxLayout();
533 layout->addWidget( mSourceWidget );
534 mSourceGroupBox->setLayout( layout );
535 mSourceGroupBox->show();
536
537 connect( mSourceWidget, &QgsProviderSourceWidget::validChanged, this, [ = ]( bool isValid )
538 {
539 buttonBox->button( QDialogButtonBox::Apply )->setEnabled( isValid );
540 buttonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
541 } );
542 }
543 }
544
545 if ( mSourceWidget )
546 mSourceWidget->setSourceUri( mLayer->source() );
547
548 // populate the general information
549 mLayerOrigNameLineEdit->setText( mLayer->name() );
550 mBackupCrs = mLayer->crs();
551 //see if we are dealing with a pg layer here
552 mSubsetGroupBox->setEnabled( true );
553 txtSubsetSQL->setText( mLayer->subsetString() );
554 // if the user is allowed to type an adhoc query, the app will crash if the query
555 // is bad. For this reason, the sql box is disabled and the query must be built
556 // using the query builder, either by typing it in by hand or using the buttons, etc
557 // on the builder. If the ability to enter a query directly into the box is required,
558 // a mechanism to check it must be implemented.
559 txtSubsetSQL->setReadOnly( true );
560 txtSubsetSQL->setCaretWidth( 0 );
561 txtSubsetSQL->setCaretLineVisible( false );
562 setPbnQueryBuilderEnabled();
563
564 mDisplayExpressionWidget->setField( mLayer->displayExpression() );
565 mEnableMapTips->setChecked( mLayer->mapTipsEnabled() );
566 mMapTipWidget->setText( mLayer->mapTipTemplate() );
567
568 // set up the scale based layer visibility stuff....
569 mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
570 mScaleVisibilityGroupBox->setChecked( mLayer->hasScaleBasedVisibility() );
571 mScaleRangeWidget->setMapCanvas( mCanvas );
572
573 mUseReferenceScaleGroupBox->setChecked( mLayer->renderer() && mLayer->renderer()->referenceScale() > 0 );
574 mReferenceScaleWidget->setShowCurrentScaleButton( true );
575 mReferenceScaleWidget->setMapCanvas( mCanvas );
576 if ( mUseReferenceScaleGroupBox->isChecked() )
577 mReferenceScaleWidget->setScale( mLayer->renderer()->referenceScale() );
578 else if ( mCanvas )
579 mReferenceScaleWidget->setScale( mCanvas->scale() );
580
581 // get simplify drawing configuration
582 const QgsVectorSimplifyMethod &simplifyMethod = mLayer->simplifyMethod();
583 mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification );
584 mSimplifyDrawingSpinBox->setValue( simplifyMethod.threshold() );
585 mSimplifyDrawingSpinBox->setClearValue( 1.0 );
586
587 QString remark = QStringLiteral( " (%1)" ).arg( tr( "Not supported" ) );
588 const QgsVectorDataProvider *provider = mLayer->dataProvider();
589 if ( !( provider && ( provider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) )
590 {
591 mSimplifyDrawingAtProvider->setChecked( false );
592 mSimplifyDrawingAtProvider->setEnabled( false );
593 if ( !mSimplifyDrawingAtProvider->text().endsWith( remark ) )
594 mSimplifyDrawingAtProvider->setText( mSimplifyDrawingAtProvider->text().append( remark ) );
595 }
596 else
597 {
598 mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() );
599 mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() );
600 if ( mSimplifyDrawingAtProvider->text().endsWith( remark ) )
601 {
602 QString newText = mSimplifyDrawingAtProvider->text();
603 newText.chop( remark.size() );
604 mSimplifyDrawingAtProvider->setText( newText );
605 }
606 }
607
608 // disable simplification for point layers, now it is not implemented
609 if ( mLayer->geometryType() == Qgis::GeometryType::Point )
610 {
611 mSimplifyDrawingGroupBox->setChecked( false );
612 mSimplifyDrawingGroupBox->setEnabled( false );
613 }
614
615 // Default local simplification algorithm
616 mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), QgsVectorSimplifyMethod::Distance );
617 mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), QgsVectorSimplifyMethod::SnapToGrid );
618 mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), QgsVectorSimplifyMethod::Visvalingam );
619 mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( simplifyMethod.simplifyAlgorithm() ) );
620
621 QStringList myScalesList = Qgis::defaultProjectScales().split( ',' );
622 myScalesList.append( QStringLiteral( "1:1" ) );
623 mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
624 mSimplifyMaximumScaleComboBox->setScale( simplifyMethod.maximumScale() );
625
626 mForceRasterCheckBox->setChecked( mLayer->renderer() && mLayer->renderer()->forceRasterRender() );
627
628 mRefreshLayerCheckBox->setChecked( mLayer->hasAutoRefreshEnabled() );
629 mRefreshLayerIntervalSpinBox->setEnabled( mLayer->hasAutoRefreshEnabled() );
630 mRefreshLayerIntervalSpinBox->setValue( mLayer->autoRefreshInterval() / 1000.0 );
631
632 mRefreshLayerNotificationCheckBox->setChecked( mLayer->isRefreshOnNotifyEnabled() );
633 mNotificationMessageCheckBox->setChecked( !mLayer->refreshOnNotifyMessage().isEmpty() );
634 mNotifyMessagValueLineEdit->setText( mLayer->refreshOnNotifyMessage() );
635
636
637 // load appropriate symbology page (V1 or V2)
638 updateSymbologyPage();
639
640 mActionDialog->init( *mLayer->actions(), mLayer->attributeTableConfig() );
641
642 if ( labelingDialog )
643 labelingDialog->adaptToLayer();
644
645 mSourceFieldsPropertiesDialog->init();
646 mAttributesFormPropertiesDialog->init();
647
648 // set initial state for variable editor
649 updateVariableEditor();
650
651 if ( diagramPropertiesDialog )
652 diagramPropertiesDialog->syncToLayer();
653
654 // sync all plugin dialogs
655 const auto constMLayerPropertiesPages = mLayerPropertiesPages;
656 for ( QgsMapLayerConfigWidget *page : constMLayerPropertiesPages )
657 {
658 page->syncToLayer( mLayer );
659 }
660
661 mMetadataWidget->setMetadata( &mLayer->metadata() );
662
663 mTemporalWidget->syncToLayer();
664
665 mLegendWidget->setLayer( mLayer );
666
667}
668
669void QgsVectorLayerProperties::apply()
670{
671 if ( mSourceWidget )
672 {
673 const QString newSource = mSourceWidget->sourceUri();
674 if ( newSource != mLayer->source() )
675 {
676 mLayer->setDataSource( newSource, mLayer->name(), mLayer->providerType(),
677 QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags() );
678 }
679 }
680
681 if ( labelingDialog )
682 {
683 labelingDialog->writeSettingsToLayer();
684 }
685 mBackupCrs = mLayer->crs();
686 // apply legend settings
687 mLegendWidget->applyToLayer();
688 mLegendConfigEmbeddedWidget->applyToLayer();
689
690 // save metadata
691 mMetadataWidget->acceptMetadata();
692 mMetadataFilled = false;
693
694 // save masking settings
695 if ( mMaskingWidget && mMaskingWidget->hasBeenPopulated() )
696 mMaskingWidget->apply();
697
698 //
699 // Set up sql subset query if applicable
700 //
701 mSubsetGroupBox->setEnabled( true );
702
703 if ( txtSubsetSQL->text() != mLayer->subsetString() )
704 {
705 // set the subset sql for the layer
706 mLayer->setSubsetString( txtSubsetSQL->text() );
707 mMetadataFilled = false;
708 }
709 mOriginalSubsetSQL = mLayer->subsetString();
710
711 // set up the scale based layer visibility stuff....
712 mLayer->setScaleBasedVisibility( mScaleVisibilityGroupBox->isChecked() );
713 mLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
714 mLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
715
716 // provider-specific options
717 if ( mLayer->dataProvider() )
718 {
720 {
721 mLayer->setProviderEncoding( cboProviderEncoding->currentText() );
722 }
723 }
724
725 mLayer->setDisplayExpression( mDisplayExpressionWidget->asExpression() );
726 mLayer->setMapTipsEnabled( mEnableMapTips->isChecked() );
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
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 apply();
1021 }
1022
1023 return;
1024 default:
1025 break;
1026 }
1027 }
1028
1029 QString myMessage = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true );
1030// QString myMessage = layer->loadDefaultStyle( defaultLoadedFlag );
1031 //reset if the default style was loaded OK only
1032 if ( defaultLoadedFlag )
1033 {
1034 // all worked OK so no need to inform user
1035 syncToLayer();
1036 apply();
1037 }
1038 else
1039 {
1040 //something went wrong - let them know why
1041 QMessageBox::information( this, tr( "Default Style" ), myMessage );
1042 }
1043}
1044
1046{
1047 apply();
1048 QString errorMsg;
1049 const QgsVectorDataProvider *provider = mLayer->dataProvider();
1050 if ( !provider )
1051 return;
1052 if ( provider->isSaveAndLoadStyleToDatabaseSupported() )
1053 {
1054 QMessageBox askToUser;
1055 askToUser.setText( tr( "Save default style to: " ) );
1056 askToUser.setIcon( QMessageBox::Question );
1057 askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
1058 askToUser.addButton( tr( "Local Database" ), QMessageBox::NoRole );
1059 askToUser.addButton( tr( "Datasource Database" ), QMessageBox::YesRole );
1060
1061 switch ( askToUser.exec() )
1062 {
1063 case 0:
1064 return;
1065 case 2:
1066 {
1067 QString errorMessage;
1068 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), QString(), errorMessage ) )
1069 {
1070 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1071 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1072 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1073 {
1074 return;
1075 }
1076 }
1077 else if ( !errorMessage.isEmpty() )
1078 {
1079 QMessageBox::warning( nullptr, QObject::tr( "Save style in database" ),
1080 errorMessage );
1081 return;
1082 }
1083
1084 mLayer->saveStyleToDatabase( QString(), QString(), true, QString(), errorMsg );
1085 if ( errorMsg.isNull() )
1086 {
1087 return;
1088 }
1089 break;
1090 }
1091 default:
1092 break;
1093 }
1094 }
1095
1096 bool defaultSavedFlag = false;
1097 // TODO Once the deprecated `saveDefaultStyle()` method is gone, just
1098 // remove the NOWARN_DEPRECATED tags
1100 errorMsg = mLayer->saveDefaultStyle( defaultSavedFlag );
1102 if ( !defaultSavedFlag )
1103 {
1104 QMessageBox::warning( this, tr( "Default Style" ), errorMsg );
1105 }
1106}
1107
1108void QgsVectorLayerProperties::loadMetadata()
1109{
1110 QgsSettings myQSettings; // where we keep last used filter in persistent state
1111 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1112
1113 QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load Layer Metadata from Metadata File" ), myLastUsedDir,
1114 tr( "QGIS Layer Metadata File" ) + " (*.qmd)" );
1115 if ( myFileName.isNull() )
1116 {
1117 return;
1118 }
1119
1120 QString myMessage;
1121 bool defaultLoadedFlag = false;
1122 myMessage = mLayer->loadNamedMetadata( myFileName, defaultLoadedFlag );
1123
1124 //reset if the default style was loaded OK only
1125 if ( defaultLoadedFlag )
1126 {
1127 mMetadataWidget->setMetadata( &mLayer->metadata() );
1128 }
1129 else
1130 {
1131 //let the user know what went wrong
1132 QMessageBox::warning( this, tr( "Load Metadata" ), myMessage );
1133 }
1134
1135 QFileInfo myFI( myFileName );
1136 QString myPath = myFI.path();
1137 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1138
1139 activateWindow(); // set focus back to properties dialog
1140}
1141
1142void QgsVectorLayerProperties::saveMetadataAs()
1143{
1144 QgsSettings myQSettings; // where we keep last used filter in persistent state
1145 QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
1146
1147 QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save Layer Metadata as QMD" ),
1148 myLastUsedDir, tr( "QMD File" ) + " (*.qmd)" );
1149 if ( myOutputFileName.isNull() ) //dialog canceled
1150 {
1151 return;
1152 }
1153
1154 mMetadataWidget->acceptMetadata();
1155
1156 //ensure the user never omitted the extension from the file name
1157 if ( !myOutputFileName.endsWith( QgsMapLayer::extensionPropertyType( QgsMapLayer::Metadata ), Qt::CaseInsensitive ) )
1158 {
1160 }
1161
1162 QString myMessage;
1163 bool defaultLoadedFlag = false;
1164 myMessage = mLayer->saveNamedMetadata( myOutputFileName, defaultLoadedFlag );
1165
1166 //reset if the default style was loaded OK only
1167 if ( defaultLoadedFlag )
1168 {
1169 syncToLayer();
1170 }
1171 else
1172 {
1173 //let the user know what went wrong
1174 QMessageBox::information( this, tr( "Save Metadata" ), myMessage );
1175 }
1176
1177 QFileInfo myFI( myOutputFileName );
1178 QString myPath = myFI.path();
1179 // Persist last used dir
1180 myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
1181}
1182
1183void QgsVectorLayerProperties::saveDefaultMetadata()
1184{
1185 mMetadataWidget->acceptMetadata();
1186
1187 bool defaultSavedFlag = false;
1188 QString errorMsg = mLayer->saveDefaultMetadata( defaultSavedFlag );
1189 if ( !defaultSavedFlag )
1190 {
1191 QMessageBox::warning( this, tr( "Default Metadata" ), errorMsg );
1192 }
1193}
1194
1195void QgsVectorLayerProperties::loadDefaultMetadata()
1196{
1197 bool defaultLoadedFlag = false;
1198 QString myMessage = mLayer->loadNamedMetadata( mLayer->metadataUri(), defaultLoadedFlag );
1199 //reset if the default metadata was loaded OK only
1200 if ( defaultLoadedFlag )
1201 {
1202 mMetadataWidget->setMetadata( &mLayer->metadata() );
1203 }
1204 else
1205 {
1206 QMessageBox::information( this, tr( "Default Metadata" ), myMessage );
1207 }
1208}
1209
1210
1212{
1213 if ( !mLayer->dataProvider() )
1214 return;
1215 QgsVectorLayerSaveStyleDialog dlg( mLayer );
1216 QgsSettings settings;
1217
1218 if ( dlg.exec() )
1219 {
1220 apply();
1221
1222 bool defaultLoadedFlag = false;
1223 QString errorMessage;
1224
1225 StyleType type = dlg.currentStyleType();
1226 switch ( type )
1227 {
1228 case QML:
1229 case SLD:
1230 {
1231 QString filePath = dlg.outputFilePath();
1232 if ( type == QML )
1233 errorMessage = mLayer->saveNamedStyle( filePath, defaultLoadedFlag, dlg.styleCategories() );
1234 else
1235 {
1237 errorMessage = mLayer->saveSldStyleV2( defaultLoadedFlag, sldContext );
1238 }
1239
1240 //reset if the default style was loaded OK only
1241 if ( defaultLoadedFlag )
1242 {
1243 syncToLayer();
1244 }
1245 else
1246 {
1247 //let the user know what went wrong
1248 QMessageBox::information( this, tr( "Save Style" ), errorMessage );
1249 }
1250
1251 break;
1252 }
1253 case DB:
1254 {
1255 QString infoWindowTitle = QObject::tr( "Save style to DB (%1)" ).arg( mLayer->providerType() );
1256
1258
1259 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), dbSettings.name, errorMessage ) )
1260 {
1261 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1262 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1263 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1264 {
1265 return;
1266 }
1267 }
1268 else if ( !errorMessage.isEmpty() )
1269 {
1270 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1271 return;
1272 }
1273
1274 mLayer->saveStyleToDatabase( dbSettings.name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, errorMessage, dlg.styleCategories() );
1275
1276 if ( !errorMessage.isNull() )
1277 {
1278 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1279 }
1280 else
1281 {
1282 mMessageBar->pushMessage( infoWindowTitle, tr( "Style saved" ), Qgis::MessageLevel::Success );
1283 }
1284 break;
1285 }
1286 case Local:
1287 {
1288 QString infoWindowTitle = tr( "Save default style to local database" );
1289 errorMessage = mLayer->saveDefaultStyle( defaultLoadedFlag, dlg.styleCategories() );
1290 if ( !defaultLoadedFlag )
1291 {
1292 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1293 }
1294 else
1295 {
1296 mMessageBar->pushMessage( infoWindowTitle, tr( "Style saved" ), Qgis::MessageLevel::Success );
1297 }
1298 break;
1299 }
1300 }
1301 }
1302}
1303
1304void QgsVectorLayerProperties::saveMultipleStylesAs()
1305{
1306 QgsVectorLayerSaveStyleDialog dlg( mLayer );
1307 dlg.setSaveOnlyCurrentStyle( false );
1308 QgsSettings settings;
1309
1310 if ( dlg.exec() )
1311 {
1312 apply();
1313
1314 // Store the original style, that we can restore at the end
1315 const QString originalStyle { mLayer->styleManager()->currentStyle() };
1316 const QListWidget *stylesWidget { dlg.stylesWidget() };
1317
1318 // Collect selected (checked) styles for export/save
1319 QStringList stylesSelected;
1320 for ( int i = 0; i < stylesWidget->count(); i++ )
1321 {
1322 if ( stylesWidget->item( i )->checkState() == Qt::CheckState::Checked )
1323 {
1324 stylesSelected.push_back( stylesWidget->item( i )->text() );
1325 }
1326 }
1327
1328 if ( ! stylesSelected.isEmpty() )
1329 {
1330 int styleIndex = 0;
1331 for ( const QString &styleName : std::as_const( stylesSelected ) )
1332 {
1333 bool defaultLoadedFlag = false;
1334
1335 StyleType type = dlg.currentStyleType();
1336 mLayer->styleManager()->setCurrentStyle( styleName );
1337 switch ( type )
1338 {
1339 case QML:
1340 case SLD:
1341 {
1342 QString message;
1343 const QString filePath { dlg.outputFilePath() };
1344 QString safePath { filePath };
1345 if ( styleIndex > 0 && stylesSelected.count( ) > 1 )
1346 {
1347 int i = 1;
1348 while ( QFile::exists( safePath ) )
1349 {
1350 const QFileInfo fi { filePath };
1351 safePath = QString( filePath ).replace( '.' + fi.completeSuffix(),
1352 QStringLiteral( "_%1.%2" ).arg( QString::number( i ), fi.completeSuffix() ) );
1353 i++;
1354 }
1355 }
1356 if ( type == QML )
1357 message = mLayer->saveNamedStyle( safePath, defaultLoadedFlag, dlg.styleCategories() );
1358 else
1359 message = mLayer->saveSldStyle( safePath, defaultLoadedFlag );
1360
1361 //reset if the default style was loaded OK only
1362 if ( defaultLoadedFlag )
1363 {
1364 syncToLayer();
1365 }
1366 else
1367 {
1368 //let the user know what went wrong
1369 QMessageBox::information( this, tr( "Save Style" ), message );
1370 }
1371
1372 break;
1373 }
1374 case DB:
1375 {
1376 QString infoWindowTitle = QObject::tr( "Save style '%1' to DB (%2)" )
1377 .arg( styleName, mLayer->providerType() );
1378 QString msgError;
1379
1380 QgsVectorLayerSaveStyleDialog::SaveToDbSettings dbSettings = dlg.saveToDbSettings();
1381
1382 // If a name is defined, we add _1 etc. else we use the style name
1383 QString name { dbSettings.name };
1384 if ( name.isEmpty() )
1385 {
1386 name = styleName;
1387 }
1388 else
1389 {
1390 QStringList ids, names, descriptions;
1391 mLayer->listStylesInDatabase( ids, names, descriptions, msgError );
1392 int i = 1;
1393 while ( names.contains( name ) )
1394 {
1395 name = QStringLiteral( "%1 %2" ).arg( name, QString::number( i ) );
1396 i++;
1397 }
1398 }
1399
1400 QString errorMessage;
1401 if ( QgsProviderRegistry::instance()->styleExists( mLayer->providerType(), mLayer->source(), dbSettings.name, errorMessage ) )
1402 {
1403 if ( QMessageBox::question( nullptr, QObject::tr( "Save style in database" ),
1404 QObject::tr( "A matching style already exists in the database for this layer. Do you want to overwrite it?" ),
1405 QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
1406 {
1407 return;
1408 }
1409 }
1410 else if ( !errorMessage.isEmpty() )
1411 {
1412 mMessageBar->pushMessage( infoWindowTitle, errorMessage, Qgis::MessageLevel::Warning );
1413 return;
1414 }
1415
1416 mLayer->saveStyleToDatabase( name, dbSettings.description, dbSettings.isDefault, dbSettings.uiFileContent, msgError, dlg.styleCategories() );
1417
1418 if ( !msgError.isNull() )
1419 {
1420 mMessageBar->pushMessage( infoWindowTitle, msgError, Qgis::MessageLevel::Warning );
1421 }
1422 else
1423 {
1424 mMessageBar->pushMessage( infoWindowTitle, tr( "Style '%1' saved" ).arg( styleName ),
1425 Qgis::MessageLevel::Success );
1426 }
1427 break;
1428 }
1429 case Local:
1430 break;
1431 }
1432 styleIndex ++;
1433 }
1434 // Restore original style
1435 mLayer->styleManager()->setCurrentStyle( originalStyle );
1436 }
1437 } // Nothing selected!
1438}
1439
1440void QgsVectorLayerProperties::aboutToShowStyleMenu()
1441{
1442 // this should be unified with QgsRasterLayerProperties::aboutToShowStyleMenu()
1443 QMenu *m = qobject_cast<QMenu *>( sender() );
1444 m->clear();
1445
1446 m->addAction( mActionLoadStyle );
1447 m->addAction( mActionSaveStyle );
1448
1449 // If we have multiple styles, offer an option to save them at once
1450 if ( mLayer->styleManager()->styles().count() > 1 )
1451 {
1452 mActionSaveStyle->setText( tr( "Save Current Style…" ) );
1453 m->addAction( mActionSaveMultipleStyles );
1454 }
1455 else
1456 {
1457 mActionSaveStyle->setText( tr( "Save Style…" ) );
1458 }
1459
1460 m->addSeparator();
1461 m->addAction( tr( "Save as Default" ), this, &QgsVectorLayerProperties::saveDefaultStyle );
1462 m->addAction( tr( "Restore Default" ), this, &QgsVectorLayerProperties::loadDefaultStyle );
1463
1464 // re-add style manager actions!
1465 m->addSeparator();
1467}
1468
1470{
1471 QgsSettings settings; // where we keep last used filter in persistent state
1472
1473 QString errorMsg;
1474 QStringList ids, names, descriptions;
1475
1476 //get the list of styles in the db
1477 int sectionLimit = mLayer->listStylesInDatabase( ids, names, descriptions, errorMsg );
1478 QgsMapLayerLoadStyleDialog dlg( mLayer, this );
1479 dlg.initializeLists( ids, names, descriptions, sectionLimit );
1480
1481 if ( dlg.exec() )
1482 {
1483 mOldStyle = mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() );
1484 QgsMapLayer::StyleCategories categories = dlg.styleCategories();
1485 StyleType type = dlg.currentStyleType();
1486 bool defaultLoadedFlag = false;
1487 switch ( type )
1488 {
1489 case QML:
1490 case SLD:
1491 {
1492 QString filePath = dlg.filePath();
1493 if ( type == SLD )
1494 {
1495 errorMsg = mLayer->loadSldStyle( filePath, defaultLoadedFlag );
1496 }
1497 else
1498 {
1499 errorMsg = mLayer->loadNamedStyle( filePath, defaultLoadedFlag, true, categories );
1500 }
1501 //reset if the default style was loaded OK only
1502 if ( defaultLoadedFlag )
1503 {
1504 syncToLayer();
1505 apply();
1506 }
1507 else
1508 {
1509 //let the user know what went wrong
1510 QMessageBox::warning( this, tr( "Load Style" ), errorMsg );
1511 }
1512 break;
1513 }
1514 case DB:
1515 {
1516 QString selectedStyleId = dlg.selectedStyleId();
1517
1518 QString qmlStyle = mLayer->getStyleFromDatabase( selectedStyleId, errorMsg );
1519 if ( !errorMsg.isNull() )
1520 {
1521 QMessageBox::warning( this, tr( "Load Styles from Database" ), errorMsg );
1522 return;
1523 }
1524
1525 QDomDocument myDocument( QStringLiteral( "qgis" ) );
1526 myDocument.setContent( qmlStyle );
1527
1528 if ( mLayer->importNamedStyle( myDocument, errorMsg, categories ) )
1529 {
1530 syncToLayer();
1531 apply();
1532 }
1533 else
1534 {
1535 QMessageBox::warning( this, tr( "Load Styles from Database" ),
1536 tr( "The retrieved style is not a valid named style. Error message: %1" )
1537 .arg( errorMsg ) );
1538 }
1539 break;
1540 }
1541 case Local:
1542 {
1543 errorMsg = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true, categories );
1544 //reset if the default style was loaded OK only
1545 if ( defaultLoadedFlag )
1546 {
1547 syncToLayer();
1548 apply();
1549 }
1550 else
1551 {
1552 QMessageBox::warning( this, tr( "Load Default Style" ), errorMsg );
1553 }
1554 break;
1555 }
1556 }
1557 activateWindow(); // set focus back to properties dialog
1558 }
1559}
1560
1561void QgsVectorLayerProperties::mButtonAddJoin_clicked()
1562{
1563 if ( !mLayer )
1564 return;
1565
1566 QList<QgsMapLayer *> joinedLayers;
1567 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
1568 joinedLayers.reserve( joins.size() );
1569 for ( int i = 0; i < joins.size(); ++i )
1570 {
1571 joinedLayers.append( joins[i].joinLayer() );
1572 }
1573
1574 QgsJoinDialog d( mLayer, joinedLayers );
1575 if ( d.exec() == QDialog::Accepted )
1576 {
1577 QgsVectorLayerJoinInfo info = d.joinInfo();
1578 //create attribute index if possible
1579 if ( d.createAttributeIndex() )
1580 {
1581 QgsVectorLayer *joinLayer = info.joinLayer();
1582 if ( joinLayer )
1583 {
1584 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1585 }
1586 }
1587 mLayer->addJoin( info );
1588 addJoinToTreeWidget( info );
1589 setPbnQueryBuilderEnabled();
1590 mSourceFieldsPropertiesDialog->init();
1591 mAttributesFormPropertiesDialog->init();
1592 }
1593}
1594
1595void QgsVectorLayerProperties::mButtonEditJoin_clicked()
1596{
1597 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1598 mJoinTreeWidget_itemDoubleClicked( currentJoinItem, 0 );
1599}
1600
1601void QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1602{
1603 if ( !mLayer || !item )
1604 {
1605 return;
1606 }
1607
1608 QList<QgsMapLayer *> joinedLayers;
1609 QString joinLayerId = item->data( 0, Qt::UserRole ).toString();
1610 const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
1611 int j = -1;
1612 for ( int i = 0; i < joins.size(); ++i )
1613 {
1614 QgsVectorLayer *joinLayer = joins[i].joinLayer();
1615 if ( !joinLayer )
1616 continue; // invalid join (unresolved join layer)
1617
1618 if ( joinLayer->id() == joinLayerId )
1619 {
1620 j = i;
1621 }
1622 else
1623 {
1624 // remove already joined layers from possible list to be displayed in dialog
1625 joinedLayers.append( joinLayer );
1626 }
1627 }
1628 if ( j == -1 )
1629 {
1630 return;
1631 }
1632
1633 QgsJoinDialog d( mLayer, joinedLayers );
1634 d.setWindowTitle( tr( "Edit Vector Join" ) );
1635 d.setJoinInfo( joins[j] );
1636
1637 if ( d.exec() == QDialog::Accepted )
1638 {
1639 QgsVectorLayerJoinInfo info = d.joinInfo();
1640
1641 // remove old join
1642 mLayer->removeJoin( joinLayerId );
1643 int idx = mJoinTreeWidget->indexOfTopLevelItem( item );
1644 mJoinTreeWidget->takeTopLevelItem( idx );
1645
1646 // add the new edited
1647
1648 //create attribute index if possible
1649 if ( d.createAttributeIndex() )
1650 {
1651 QgsVectorLayer *joinLayer = info.joinLayer();
1652 if ( joinLayer )
1653 {
1654 joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
1655 }
1656 }
1657 mLayer->addJoin( info );
1658 addJoinToTreeWidget( info, idx );
1659
1660 setPbnQueryBuilderEnabled();
1661 mSourceFieldsPropertiesDialog->init();
1662 mAttributesFormPropertiesDialog->init();
1663 }
1664}
1665
1666void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorLayerJoinInfo &join, const int insertIndex )
1667{
1668 QTreeWidgetItem *joinItem = new QTreeWidgetItem();
1669 joinItem->setFlags( Qt::ItemIsEnabled );
1670
1671 QgsVectorLayer *joinLayer = join.joinLayer();
1672 if ( !mLayer || !joinLayer )
1673 {
1674 return;
1675 }
1676
1677 joinItem->setText( 0, tr( "Join layer" ) );
1678 if ( mLayer->auxiliaryLayer() && mLayer->auxiliaryLayer()->id() == join.joinLayerId() )
1679 {
1680 return;
1681 }
1682
1683 joinItem->setText( 1, joinLayer->name() );
1684
1685 QFont f = joinItem->font( 0 );
1686 f.setBold( true );
1687 joinItem->setFont( 0, f );
1688 joinItem->setFont( 1, f );
1689
1690 joinItem->setData( 0, Qt::UserRole, join.joinLayerId() );
1691
1692 QTreeWidgetItem *childJoinField = new QTreeWidgetItem();
1693 childJoinField->setText( 0, tr( "Join field" ) );
1694 childJoinField->setText( 1, join.joinFieldName() );
1695 childJoinField->setFlags( Qt::ItemIsEnabled );
1696 joinItem->addChild( childJoinField );
1697
1698 QTreeWidgetItem *childTargetField = new QTreeWidgetItem();
1699 childTargetField->setText( 0, tr( "Target field" ) );
1700 childTargetField->setText( 1, join.targetFieldName() );
1701 joinItem->addChild( childTargetField );
1702
1703 QTreeWidgetItem *childMemCache = new QTreeWidgetItem();
1704 childMemCache->setText( 0, tr( "Cache join layer in virtual memory" ) );
1705 if ( join.isUsingMemoryCache() )
1706 childMemCache->setText( 1, QChar( 0x2714 ) );
1707 joinItem->addChild( childMemCache );
1708
1709 QTreeWidgetItem *childDynForm = new QTreeWidgetItem();
1710 childDynForm->setText( 0, tr( "Dynamic form" ) );
1711 if ( join.isDynamicFormEnabled() )
1712 childDynForm->setText( 1, QChar( 0x2714 ) );
1713 joinItem->addChild( childDynForm );
1714
1715 QTreeWidgetItem *childEditable = new QTreeWidgetItem();
1716 childEditable->setText( 0, tr( "Editable join layer" ) );
1717 if ( join.isEditable() )
1718 childEditable->setText( 1, QChar( 0x2714 ) );
1719 joinItem->addChild( childEditable );
1720
1721 QTreeWidgetItem *childUpsert = new QTreeWidgetItem();
1722 childUpsert->setText( 0, tr( "Upsert on edit" ) );
1723 if ( join.hasUpsertOnEdit() )
1724 childUpsert->setText( 1, QChar( 0x2714 ) );
1725 joinItem->addChild( childUpsert );
1726
1727 QTreeWidgetItem *childCascade = new QTreeWidgetItem();
1728 childCascade->setText( 0, tr( "Delete cascade" ) );
1729 if ( join.hasCascadedDelete() )
1730 childCascade->setText( 1, QChar( 0x2714 ) );
1731 joinItem->addChild( childCascade );
1732
1733 QTreeWidgetItem *childPrefix = new QTreeWidgetItem();
1734 childPrefix->setText( 0, tr( "Custom field name prefix" ) );
1735 childPrefix->setText( 1, join.prefix() );
1736 joinItem->addChild( childPrefix );
1737
1738 QTreeWidgetItem *childFields = new QTreeWidgetItem();
1739 childFields->setText( 0, tr( "Joined fields" ) );
1740 const QStringList *list = join.joinFieldNamesSubset();
1741 if ( list )
1742 childFields->setText( 1, QLocale().toString( list->count() ) );
1743 else
1744 childFields->setText( 1, tr( "all" ) );
1745 joinItem->addChild( childFields );
1746
1747 if ( insertIndex >= 0 )
1748 mJoinTreeWidget->insertTopLevelItem( insertIndex, joinItem );
1749 else
1750 mJoinTreeWidget->addTopLevelItem( joinItem );
1751
1752 mJoinTreeWidget->setCurrentItem( joinItem );
1753 mJoinTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1754}
1755
1756QgsExpressionContext QgsVectorLayerProperties::createExpressionContext() const
1757{
1758 return mContext;
1759}
1760
1761void QgsVectorLayerProperties::openPanel( QgsPanelWidget *panel )
1762{
1763 QDialog *dlg = new QDialog();
1764 QString key = QStringLiteral( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
1765 QgsSettings settings;
1766 dlg->restoreGeometry( settings.value( key ).toByteArray() );
1767 dlg->setWindowTitle( panel->panelTitle() );
1768 dlg->setLayout( new QVBoxLayout() );
1769 dlg->layout()->addWidget( panel );
1770 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
1771 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
1772 dlg->layout()->addWidget( buttonBox );
1773 dlg->exec();
1774 settings.setValue( key, dlg->saveGeometry() );
1775 panel->acceptPanel();
1776}
1777
1778void QgsVectorLayerProperties::mButtonRemoveJoin_clicked()
1779{
1780 QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
1781 if ( !mLayer || !currentJoinItem )
1782 {
1783 return;
1784 }
1785
1786 mLayer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
1787 mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
1788 setPbnQueryBuilderEnabled();
1789 mSourceFieldsPropertiesDialog->init();
1790 mAttributesFormPropertiesDialog->init();
1791}
1792
1793
1794void QgsVectorLayerProperties::mButtonAddWmsDimension_clicked()
1795{
1796 if ( !mLayer )
1797 return;
1798
1799 // get wms dimensions name
1800 QStringList alreadyDefinedDimensions;
1801 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1802 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1803 for ( const QgsMapLayerServerProperties::WmsDimensionInfo &dim : dims )
1804 {
1805 alreadyDefinedDimensions << dim.name;
1806 }
1807
1808 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1809 if ( d.exec() == QDialog::Accepted )
1810 {
1812 // save dimension
1813 serverProperties->addWmsDimension( info );
1814 addWmsDimensionInfoToTreeWidget( info );
1815 }
1816}
1817
1818void QgsVectorLayerProperties::mButtonEditWmsDimension_clicked()
1819{
1820 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1821 mWmsDimensionsTreeWidget_itemDoubleClicked( currentWmsDimensionItem, 0 );
1822}
1823
1824void QgsVectorLayerProperties::mWmsDimensionsTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
1825{
1826 if ( !mLayer || !item )
1827 {
1828 return;
1829 }
1830
1831 QString wmsDimName = item->data( 0, Qt::UserRole ).toString();
1832 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1833 const QList<QgsMapLayerServerProperties::WmsDimensionInfo> &dims = serverProperties->wmsDimensions();
1834 QStringList alreadyDefinedDimensions;
1835 int j = -1;
1836 for ( int i = 0; i < dims.size(); ++i )
1837 {
1838 QString dimName = dims[i].name;
1839 if ( dimName == wmsDimName )
1840 {
1841 j = i;
1842 }
1843 else
1844 {
1845 alreadyDefinedDimensions << dimName;
1846 }
1847 }
1848 if ( j == -1 )
1849 {
1850 return;
1851 }
1852
1853 QgsWmsDimensionDialog d( mLayer, alreadyDefinedDimensions );
1854 d.setWindowTitle( tr( "Edit WMS Dimension" ) );
1855 d.setInfo( dims[j] );
1856
1857 if ( d.exec() == QDialog::Accepted )
1858 {
1860
1861 // remove old
1862 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1863 serverProperties->removeWmsDimension( wmsDimName );
1864 int idx = mWmsDimensionsTreeWidget->indexOfTopLevelItem( item );
1865 mWmsDimensionsTreeWidget->takeTopLevelItem( idx );
1866
1867 // save new
1868 serverProperties->addWmsDimension( info );
1869 addWmsDimensionInfoToTreeWidget( info, idx );
1870 }
1871}
1872
1873void QgsVectorLayerProperties::addWmsDimensionInfoToTreeWidget( const QgsMapLayerServerProperties::WmsDimensionInfo &wmsDim, const int insertIndex )
1874{
1875 QTreeWidgetItem *wmsDimensionItem = new QTreeWidgetItem();
1876 wmsDimensionItem->setFlags( Qt::ItemIsEnabled );
1877
1878 wmsDimensionItem->setText( 0, tr( "Dimension" ) );
1879 wmsDimensionItem->setText( 1, wmsDim.name );
1880
1881 QFont f = wmsDimensionItem->font( 0 );
1882 f.setBold( true );
1883 wmsDimensionItem->setFont( 0, f );
1884 wmsDimensionItem->setFont( 1, f );
1885
1886 wmsDimensionItem->setData( 0, Qt::UserRole, wmsDim.name );
1887
1888 QTreeWidgetItem *childWmsDimensionField = new QTreeWidgetItem();
1889 childWmsDimensionField->setText( 0, tr( "Field" ) );
1890 childWmsDimensionField->setText( 1, wmsDim.fieldName );
1891 childWmsDimensionField->setFlags( Qt::ItemIsEnabled );
1892 wmsDimensionItem->addChild( childWmsDimensionField );
1893
1894 QTreeWidgetItem *childWmsDimensionEndField = new QTreeWidgetItem();
1895 childWmsDimensionEndField->setText( 0, tr( "End field" ) );
1896 childWmsDimensionEndField->setText( 1, wmsDim.endFieldName );
1897 childWmsDimensionEndField->setFlags( Qt::ItemIsEnabled );
1898 wmsDimensionItem->addChild( childWmsDimensionEndField );
1899
1900 QTreeWidgetItem *childWmsDimensionUnits = new QTreeWidgetItem();
1901 childWmsDimensionUnits->setText( 0, tr( "Units" ) );
1902 childWmsDimensionUnits->setText( 1, wmsDim.units );
1903 childWmsDimensionUnits->setFlags( Qt::ItemIsEnabled );
1904 wmsDimensionItem->addChild( childWmsDimensionUnits );
1905
1906 QTreeWidgetItem *childWmsDimensionUnitSymbol = new QTreeWidgetItem();
1907 childWmsDimensionUnitSymbol->setText( 0, tr( "Unit symbol" ) );
1908 childWmsDimensionUnitSymbol->setText( 1, wmsDim.unitSymbol );
1909 childWmsDimensionUnitSymbol->setFlags( Qt::ItemIsEnabled );
1910 wmsDimensionItem->addChild( childWmsDimensionUnitSymbol );
1911
1912 QTreeWidgetItem *childWmsDimensionDefaultValue = new QTreeWidgetItem();
1913 childWmsDimensionDefaultValue->setText( 0, tr( "Default display" ) );
1914 childWmsDimensionDefaultValue->setText( 1, QgsMapLayerServerProperties::wmsDimensionDefaultDisplayLabels().value( wmsDim.defaultDisplayType ) );
1915 childWmsDimensionDefaultValue->setFlags( Qt::ItemIsEnabled );
1916 wmsDimensionItem->addChild( childWmsDimensionDefaultValue );
1917
1918 QTreeWidgetItem *childWmsDimensionRefValue = new QTreeWidgetItem();
1919 childWmsDimensionRefValue->setText( 0, tr( "Reference value" ) );
1920 childWmsDimensionRefValue->setText( 1, wmsDim.referenceValue.toString() );
1921 childWmsDimensionRefValue->setFlags( Qt::ItemIsEnabled );
1922 wmsDimensionItem->addChild( childWmsDimensionRefValue );
1923
1924 if ( insertIndex >= 0 )
1925 mWmsDimensionsTreeWidget->insertTopLevelItem( insertIndex, wmsDimensionItem );
1926 else
1927 mWmsDimensionsTreeWidget->addTopLevelItem( wmsDimensionItem );
1928
1929 mWmsDimensionsTreeWidget->setCurrentItem( wmsDimensionItem );
1930 mWmsDimensionsTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
1931}
1932
1933void QgsVectorLayerProperties::mButtonRemoveWmsDimension_clicked()
1934{
1935 QTreeWidgetItem *currentWmsDimensionItem = mWmsDimensionsTreeWidget->currentItem();
1936 if ( !mLayer || !currentWmsDimensionItem )
1937 {
1938 return;
1939 }
1940
1941 QgsMapLayerServerProperties *serverProperties = static_cast<QgsMapLayerServerProperties *>( mLayer->serverProperties() );
1942 serverProperties->removeWmsDimension( currentWmsDimensionItem->data( 0, Qt::UserRole ).toString() );
1943 mWmsDimensionsTreeWidget->takeTopLevelItem( mWmsDimensionsTreeWidget->indexOfTopLevelItem( currentWmsDimensionItem ) );
1944}
1945
1946
1947void QgsVectorLayerProperties::updateSymbologyPage()
1948{
1949
1950 //find out the type of renderer in the vectorlayer, create a dialog with these settings and add it to the form
1951 delete mRendererDialog;
1952 mRendererDialog = nullptr;
1953
1954 if ( mLayer->renderer() )
1955 {
1956 mRendererDialog = new QgsRendererPropertiesDialog( mLayer, QgsStyle::defaultStyle(), true, this );
1957 mRendererDialog->setDockMode( false );
1958 QgsSymbolWidgetContext context;
1959 context.setMapCanvas( mCanvas );
1960 context.setMessageBar( mMessageBar );
1961 mRendererDialog->setContext( context );
1962 connect( mRendererDialog, &QgsRendererPropertiesDialog::showPanel, this, &QgsVectorLayerProperties::openPanel );
1963 connect( mRendererDialog, &QgsRendererPropertiesDialog::layerVariablesChanged, this, &QgsVectorLayerProperties::updateVariableEditor );
1964 connect( mRendererDialog, &QgsRendererPropertiesDialog::widgetChanged, this, [ = ] { updateAuxiliaryStoragePage(); } );
1965 }
1966 else
1967 {
1968 mOptsPage_Style->setEnabled( false ); // hide symbology item
1969 }
1970
1971 if ( mRendererDialog )
1972 {
1973 mRendererDialog->layout()->setContentsMargins( 0, 0, 0, 0 );
1974 widgetStackRenderers->addWidget( mRendererDialog );
1975 widgetStackRenderers->setCurrentWidget( mRendererDialog );
1976 widgetStackRenderers->currentWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
1977 }
1978}
1979
1980void QgsVectorLayerProperties::setPbnQueryBuilderEnabled()
1981{
1982 pbnQueryBuilder->setEnabled( mLayer &&
1983 mLayer->dataProvider() &&
1984 mLayer->dataProvider()->supportsSubsetString() &&
1985 !mLayer->isEditable() );
1986
1987 if ( mLayer && mLayer->isEditable() )
1988 {
1989 pbnQueryBuilder->setToolTip( tr( "Stop editing mode to enable this." ) );
1990 }
1991
1992}
1993
1994void QgsVectorLayerProperties::pbnUpdateExtents_clicked()
1995{
1996 mLayer->updateExtents( true ); // force update whatever options activated
1997 mMetadataFilled = false;
1998}
1999
2001{
2003
2004 bool isMetadataPanel = ( index == mOptStackedWidget->indexOf( mOptsPage_Metadata ) );
2005 mBtnStyle->setVisible( ! isMetadataPanel );
2006 mBtnMetadata->setVisible( isMetadataPanel );
2007
2008 if ( index == mOptStackedWidget->indexOf( mOptsPage_Information ) && ! mMetadataFilled )
2009 {
2010 //set the metadata contents (which can be expensive)
2011 teMetadataViewer->clear();
2012 teMetadataViewer->setHtml( htmlMetadata() );
2013 mMetadataFilled = true;
2014 }
2015
2016 resizeAlltabs( index );
2017}
2018
2019void QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled( bool checked )
2020{
2021 const QgsVectorDataProvider *provider = mLayer->dataProvider();
2022 if ( !( provider && ( provider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) != 0 ) )
2023 {
2024 mSimplifyDrawingAtProvider->setEnabled( false );
2025 }
2026 else
2027 {
2028 mSimplifyDrawingAtProvider->setEnabled( checked );
2029 }
2030}
2031
2032void QgsVectorLayerProperties::updateVariableEditor()
2033{
2034 QgsExpressionContext context;
2035 mVariableEditor->setContext( &context );
2036 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
2037 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
2038 mVariableEditor->context()->appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
2039 mVariableEditor->reloadContext();
2040 mVariableEditor->setEditableScopeIndex( 2 );
2041}
2042
2043void QgsVectorLayerProperties::showHelp()
2044{
2045 const QVariant helpPage = mOptionsStackedWidget->currentWidget()->property( "helpPage" );
2046
2047 if ( helpPage.isValid() )
2048 {
2049 QgsHelp::openHelp( helpPage.toString() );
2050 }
2051 else
2052 {
2053 QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html" ) );
2054 }
2055}
2056
2057void QgsVectorLayerProperties::updateAuxiliaryStoragePage()
2058{
2059 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2060
2061 if ( alayer )
2062 {
2063 // set widgets to enable state
2064 mAuxiliaryStorageInformationGrpBox->setEnabled( true );
2065 mAuxiliaryStorageFieldsGrpBox->setEnabled( true );
2066
2067 // update key
2068 mAuxiliaryStorageKeyLineEdit->setText( alayer->joinInfo().targetFieldName() );
2069
2070 // update feature count
2071 const qlonglong features = alayer->featureCount();
2072 mAuxiliaryStorageFeaturesLineEdit->setText( QLocale().toString( features ) );
2073
2074 // update actions
2075 mAuxiliaryLayerActionClear->setEnabled( true );
2076 mAuxiliaryLayerActionDelete->setEnabled( true );
2077 mAuxiliaryLayerActionExport->setEnabled( true );
2078 mAuxiliaryLayerActionNew->setEnabled( false );
2079
2080 const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2081 if ( alayer )
2082 {
2083 const int fields = alayer->auxiliaryFields().count();
2084 mAuxiliaryStorageFieldsLineEdit->setText( QLocale().toString( fields ) );
2085
2086 // add fields
2087 mAuxiliaryStorageFieldsTree->clear();
2088 for ( const QgsField &field : alayer->auxiliaryFields() )
2089 {
2091 QTreeWidgetItem *item = new QTreeWidgetItem();
2092
2093 item->setText( 0, prop.origin() );
2094 item->setText( 1, prop.name() );
2095 item->setText( 2, prop.comment() );
2096 item->setText( 3, field.typeName() );
2097 item->setText( 4, field.name() );
2098
2099 mAuxiliaryStorageFieldsTree->addTopLevelItem( item );
2100 }
2101 }
2102 }
2103 else
2104 {
2105 mAuxiliaryStorageInformationGrpBox->setEnabled( false );
2106 mAuxiliaryStorageFieldsGrpBox->setEnabled( false );
2107
2108 mAuxiliaryLayerActionClear->setEnabled( false );
2109 mAuxiliaryLayerActionDelete->setEnabled( false );
2110 mAuxiliaryLayerActionExport->setEnabled( false );
2111 mAuxiliaryLayerActionNew->setEnabled( true );
2112
2113 mAuxiliaryStorageFieldsTree->clear();
2114 mAuxiliaryStorageKeyLineEdit->setText( QString() );
2115 mAuxiliaryStorageFieldsLineEdit->setText( QString() );
2116 mAuxiliaryStorageFeaturesLineEdit->setText( QString() );
2117 }
2118}
2119
2120void QgsVectorLayerProperties::onAuxiliaryLayerNew()
2121{
2122 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2123
2124 if ( alayer )
2125 return;
2126
2127 QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
2128 if ( dlg.exec() == QDialog::Accepted )
2129 {
2130 updateAuxiliaryStoragePage();
2131 }
2132}
2133
2134void QgsVectorLayerProperties::onAuxiliaryLayerClear()
2135{
2136 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2137
2138 if ( !alayer )
2139 return;
2140
2141 const QString msg = tr( "Are you sure you want to clear auxiliary data for %1?" ).arg( mLayer->name() );
2142 QMessageBox::StandardButton reply;
2143 reply = QMessageBox::question( this, "Clear Auxiliary Data", msg, QMessageBox::Yes | QMessageBox::No );
2144
2145 if ( reply == QMessageBox::Yes )
2146 {
2147 QApplication::setOverrideCursor( Qt::WaitCursor );
2148 alayer->clear();
2149 QApplication::restoreOverrideCursor();
2150 updateAuxiliaryStoragePage();
2151 mLayer->triggerRepaint();
2152 }
2153}
2154
2155void QgsVectorLayerProperties::onAuxiliaryLayerDelete()
2156{
2157 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2158 if ( !alayer )
2159 return;
2160
2161 const QString msg = tr( "Are you sure you want to delete auxiliary storage for %1?" ).arg( mLayer->name() );
2162 QMessageBox::StandardButton reply;
2163 reply = QMessageBox::question( this, "Delete Auxiliary Storage", msg, QMessageBox::Yes | QMessageBox::No );
2164
2165 if ( reply == QMessageBox::Yes )
2166 {
2167 QApplication::setOverrideCursor( Qt::WaitCursor );
2168 QgsDataSourceUri uri( alayer->source() );
2169
2170 // delete each attribute to correctly update layer settings and data
2171 // defined buttons
2172 while ( alayer->auxiliaryFields().size() > 0 )
2173 {
2174 QgsField aField = alayer->auxiliaryFields()[0];
2175 deleteAuxiliaryField( alayer->fields().indexOf( aField.name() ) );
2176 }
2177
2178 mLayer->setAuxiliaryLayer(); // remove auxiliary layer
2180 QApplication::restoreOverrideCursor();
2181 updateAuxiliaryStoragePage();
2182 mLayer->triggerRepaint();
2183 }
2184}
2185
2186void QgsVectorLayerProperties::onAuxiliaryLayerDeleteField()
2187{
2188 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2189 if ( !alayer )
2190 return;
2191
2192 QList<QTreeWidgetItem *> items = mAuxiliaryStorageFieldsTree->selectedItems();
2193 if ( items.count() < 1 )
2194 return;
2195
2196 // get auxiliary field name and index from item
2197 const QTreeWidgetItem *item = items[0];
2199 def.setOrigin( item->text( 0 ) );
2200 def.setName( item->text( 1 ) );
2201 def.setComment( item->text( 2 ) );
2202
2203 const QString fieldName = QgsAuxiliaryLayer::nameFromProperty( def );
2204
2205 const int index = mLayer->auxiliaryLayer()->fields().indexOf( fieldName );
2206 if ( index < 0 )
2207 return;
2208
2209 // should be only 1 field
2210 const QString msg = tr( "Are you sure you want to delete auxiliary field %1 for %2?" ).arg( item->text( 1 ), item->text( 0 ) );
2211
2212 QMessageBox::StandardButton reply;
2213 const QString title = QObject::tr( "Delete Auxiliary Field" );
2214 reply = QMessageBox::question( this, title, msg, QMessageBox::Yes | QMessageBox::No );
2215
2216 if ( reply == QMessageBox::Yes )
2217 {
2218 QApplication::setOverrideCursor( Qt::WaitCursor );
2219 deleteAuxiliaryField( index );
2220 mLayer->triggerRepaint();
2221 QApplication::restoreOverrideCursor();
2222 }
2223}
2224
2225void QgsVectorLayerProperties::onAuxiliaryLayerAddField()
2226{
2227 QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
2228 if ( !alayer )
2229 return;
2230
2231 QgsNewAuxiliaryFieldDialog dlg( QgsPropertyDefinition(), mLayer, false );
2232 if ( dlg.exec() == QDialog::Accepted )
2233 {
2234 updateAuxiliaryStoragePage();
2235 }
2236}
2237
2238void QgsVectorLayerProperties::deleteAuxiliaryField( int index )
2239{
2240 if ( !mLayer->auxiliaryLayer() )
2241 return;
2242
2243 int key = mLayer->auxiliaryLayer()->propertyFromIndex( index );
2245
2246 if ( mLayer->auxiliaryLayer()->deleteAttribute( index ) )
2247 {
2248 mLayer->updateFields();
2249
2250 // immediately deactivate data defined button
2251 if ( key >= 0 && def.origin().compare( "labeling", Qt::CaseInsensitive ) == 0
2252 && labelingDialog
2253 && labelingDialog->labelingGui() )
2254 {
2255 labelingDialog->labelingGui()->deactivateField( static_cast<QgsPalLayerSettings::Property>( key ) );
2256 }
2257
2258 updateAuxiliaryStoragePage();
2259 mSourceFieldsPropertiesDialog->init();
2260 }
2261 else
2262 {
2263 const QString title = QObject::tr( "Delete Auxiliary Field" );
2264 const QString errors = mLayer->auxiliaryLayer()->commitErrors().join( QLatin1String( "\n " ) );
2265 const QString msg = QObject::tr( "Unable to remove auxiliary field (%1)" ).arg( errors );
2266 mMessageBar->pushMessage( title, msg, Qgis::MessageLevel::Warning );
2267 }
2268}
2269
2270bool QgsVectorLayerProperties::eventFilter( QObject *obj, QEvent *ev )
2271{
2272 // If the map tip preview container is resized, resize the map tip
2273 if ( obj == mMapTipPreviewContainer && ev->type() == QEvent::Resize )
2274 {
2275 resizeMapTip();
2276 }
2277 return QgsOptionsDialogBase::eventFilter( obj, ev );
2278}
2279
2280void QgsVectorLayerProperties::initMapTipPreview()
2281{
2282 // HTML editor and preview are in a splitter. By default, the editor takes 2/3 of the space
2283 mMapTipSplitter->setSizes( { 400, 200 } );
2284 // Event filter is used to resize the map tip when the container is resized
2285 mMapTipPreviewContainer->installEventFilter( this );
2286
2287 // Note: there's quite a bit of overlap between this and the code in QgsMapTip::showMapTip
2288 // Create the WebView
2289 mMapTipPreview = new QgsWebView( mMapTipPreviewContainer );
2290
2291#if WITH_QTWEBKIT
2292 mMapTipPreview->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );//Handle link clicks by yourself
2293 mMapTipPreview->setContextMenuPolicy( Qt::NoContextMenu ); //No context menu is allowed if you don't need it
2294 connect( mMapTipPreview, &QWebView::loadFinished, this, &QgsVectorLayerProperties::resizeMapTip );
2295#endif
2296
2297 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
2298 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::JavascriptEnabled, true );
2299 mMapTipPreview->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );
2300
2301 // Disable scrollbars, avoid random resizing issues
2302 mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
2303 mMapTipPreview->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
2304
2305 // Update the map tip preview when the expression or the map tip template changes
2306 connect( mMapTipWidget, &QgsCodeEditorHTML::textChanged, this, &QgsVectorLayerProperties::updateMapTipPreview );
2307 connect( mDisplayExpressionWidget, qOverload< const QString & >( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsVectorLayerProperties::updateMapTipPreview );
2308}
2309
2310void QgsVectorLayerProperties::updateMapTipPreview()
2311{
2312 mMapTipPreview->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
2313 const QString htmlContent = QgsMapTip::vectorMapTipPreviewText( mLayer, mCanvas, mMapTipWidget->text(), mDisplayExpressionWidget->asExpression() );
2314 mMapTipPreview->setHtml( htmlContent );
2315}
2316
2317void QgsVectorLayerProperties::resizeMapTip()
2318{
2319 // Ensure the map tip is not bigger than the container
2320 mMapTipPreview->setMaximumSize( mMapTipPreviewContainer->width(), mMapTipPreviewContainer->height() );
2321#if WITH_QTWEBKIT
2322 // Get the content size
2323 const QWebElement container = mMapTipPreview->page()->mainFrame()->findFirstElement(
2324 QStringLiteral( "#QgsWebViewContainer" ) );
2325 const int width = container.geometry().width();
2326 const int height = container.geometry().height();
2327 mMapTipPreview->resize( width, height );
2328
2329 // Move the map tip to the center of the container
2330 mMapTipPreview->move( ( mMapTipPreviewContainer->width() - mMapTipPreview->width() ) / 2,
2331 ( mMapTipPreviewContainer->height() - mMapTipPreview->height() ) / 2 );
2332
2333#else
2334 mMapTipPreview->adjustSize();
2335#endif
2336}
@ NoVendorExtension
No vendor extensions.
static QString defaultProjectScales()
A string with default project scales.
Definition: qgis.cpp:252
void clearActions()
Removes all actions.
QUuid addAction(Qgis::AttributeActionType type, const QString &name, const QString &command, bool capture=false)
Add an action with the given name and action details.
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:37
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QRegularExpression shortNameRegularExpression()
Returns the short name regular expression for line edit validator.
void init(const QgsActionManager &action, const QgsAttributeTableConfig &attributeTableConfig)
QList< QgsAction > actions() const
QgsAttributeTableConfig::ActionWidgetStyle attributeTableWidgetStyle() const
This is a container for configuration of the attribute table.
@ Action
This column represents an action widget.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void setActionWidgetStyle(ActionWidgetStyle actionWidgetStyle)
Set the style of the action widget.
void setColumns(const QVector< QgsAttributeTableConfig::ColumnConfig > &columns)
Set the list of columns visible in the attribute table.
Class allowing to manage the auxiliary storage for a vector layer.
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
static QgsPropertyDefinition propertyDefinitionFromField(const QgsField &field)
Returns the property definition from an auxiliary field.
bool clear()
Deletes all features from the layer.
bool deleteAttribute(int attr) override
Removes attribute from the layer and commits changes.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
int propertyFromIndex(int index) const
Returns the underlying property key for the field index.
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
QgsPropertyDefinition propertyDefinitionFromIndex(int index) const
Returns the property definition for the underlying field index.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
This class represents a coordinate reference system (CRS).
virtual bool supportsSubsetString() const
Returns true if the provider supports setting of subset strings.
Class for storing the component parts of a RDBMS data source URI (e.g.
static bool run(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr, const QString &windowTitle=QString())
Runs the dialog (if required) prompting for the desired transform to use from sourceCrs to destinatio...
void syncToLayer()
Updates the widget to reflect the layer's current diagram settings.
static void setLayerVariables(QgsMapLayer *layer, const QVariantMap &variables)
Sets all layer context variables.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * atlasScope(const QgsLayoutAtlas *atlas)
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool forceRasterRender() const
Returns whether the renderer must render as a raster.
Definition: qgsrenderer.h:476
void setForceRasterRender(bool forceRaster)
Sets whether the renderer should be rendered to a raster destination.
Definition: qgsrenderer.h:486
double referenceScale() const
Returns the symbology reference scale.
Definition: qgsrenderer.h:502
void setReferenceScale(double scale)
Sets the symbology reference scale.
Definition: qgsrenderer.h:518
@ 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,...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:150
QString name
Definition: qgsfield.h:62
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:113
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition: qgsgui.cpp:78
static QgsSubsetStringEditorProviderRegistry * subsetStringEditorProviderRegistry()
Returns the registry of subset string editors of data providers.
Definition: qgsgui.cpp:108
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...
QgsMapLayer::StyleCategories styleCategories() const
Returns the list of selected style categories the user has opted to load.
void initializeLists(const QStringList &ids, const QStringList &names, const QStringList &descriptions, int sectionLimit)
Initialize list of database stored styles.
QString selectedStyleId()
Returns the ID of the selected database stored style.
QString filePath() const
Returns the full path to the selected layer style source file.
QgsVectorLayerProperties::StyleType currentStyleType() const
Returns the selected vector style type, for vector layers only.
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:289
QString name
Definition: qgsmaplayer.h:76
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:1321
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:1306
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:421
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:396
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:404
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:377
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:351
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:333
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:387
bool isRefreshOnNotifyEnabled() const
Returns true if the refresh on provider nofification is enabled.
Definition: qgsmaplayer.h:1483
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:368
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:311
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:360
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:1681
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:69
virtual QString saveSldStyleV2(bool &resultFlag, const QgsSldExportContext &exportContext) const
Saves the properties of this layer to an SLD format file.
void setName(const QString &name)
Set the display name of the layer.
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
QString saveNamedMetadata(const QString &uri, bool &resultFlag)
Save the current metadata of this layer as a named metadata (either as a .qmd file on disk or as a re...
QString refreshOnNotifyMessage() const
Returns the message that should be notified by the provider to triggerRepaint.
Definition: qgsmaplayer.h:1476
void setMapTipsEnabled(bool enabled)
Enable or disable map tips for this layer.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:413
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:1311
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1316
virtual QString saveNamedStyle(const QString &uri, bool &resultFlag, StyleCategories categories=AllStyleCategories)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
bool mapTipsEnabled
Definition: qgsmaplayer.h:84
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:341
QString mapTipTemplate
Definition: qgsmaplayer.h:83
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:303
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static QString vectorMapTipPreviewText(QgsMapLayer *layer, QgsMapCanvas *mapCanvas, const QString &mapTemplate, const QString &displayExpression)
Returns the html that would be displayed in a maptip for a given layer.
Definition: qgsmaptip.cpp:441
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.
virtual void optionsStackedWidget_CurrentChanged(int index)
Select relevant tab on current page change.
void addPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QStringList &path=QStringList(), const QString &key=QString())
Adds a new page to 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.
void insertPage(const QString &title, const QString &tooltip, const QIcon &icon, QWidget *widget, const QString &before, const QStringList &path=QStringList(), const QString &key=QString())
Inserts a new page into the dialog pages.
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:484
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:603
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
Definition for a property.
Definition: qgsproperty.h:46
QString comment() const
Returns the comment of the property.
Definition: qgsproperty.h:167
void setOrigin(const QString &origin)
Sets the origin of the property.
Definition: qgsproperty.h:157
QString name() const
Returns the name of the property.
Definition: qgsproperty.h:138
void setName(const QString &name)
Sets the name of the property.
Definition: qgsproperty.h:143
QString origin() const
Returns the origin of the property.
Definition: qgsproperty.h:150
void setComment(const QString &comment)
Sets comment of the property.
Definition: qgsproperty.h:172
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderSourceWidget * createWidget(QgsMapLayer *layer, QWidget *parent=nullptr)
Creates a new widget to configure the source of the specified layer.
void validChanged(bool isValid)
Emitted whenever the validation status of the widget changes.
virtual QString sourceUri() const =0
Returns the source URI as currently defined by the widget.
virtual void setSourceUri(const QString &uri)=0
Sets the source uri to show in the widget.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the dialog is shown, e.g., the associated map canvas and expression context...
void apply()
Apply the changes from the dialog to the layer.
void layerVariablesChanged()
Emitted when expression context variables on the associated vector layers have been changed.
void widgetChanged()
Emitted when something on the widget has changed.
void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
void setMetadataUrls(const QList< QgsServerMetadataUrlProperties::MetadataUrl > &metaUrls)
Sets a the list of metadata URL for the layer.
QList< QgsServerMetadataUrlProperties::MetadataUrl > metadataUrls() const
Returns a list of metadataUrl resources associated for the layer.
static QMap< int, QString > wmsDimensionDefaultDisplayLabels()
Returns WMS Dimension default display labels.
bool addWmsDimension(const QgsServerWmsDimensionProperties::WmsDimensionInfo &wmsDimInfo)
Adds a QGIS Server WMS Dimension.
bool removeWmsDimension(const QString &wmsDimName)
Removes a QGIS Server WMS Dimension.
const QList< QgsServerWmsDimensionProperties::WmsDimensionInfo > wmsDimensions() const
Returns the QGIS Server WMS Dimension list.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
bool contains(const QString &key, QgsSettings::Section section=QgsSettings::NoSection) const
Returns true if there exists a setting called key; returns false otherwise.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
The QgsSldExportContext class holds SLD export options and other information related to SLD export of...
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
Interface for a dialog that can edit subset strings.
virtual QString subsetString() const =0
Returns the subset string entered in the dialog.
virtual void setSubsetString(const QString &subsetString)=0
Sets a subset string into the dialog.
QgsSubsetStringEditorInterface * createDialog(QgsVectorLayer *layer, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Creates a new dialog to edit the subset string of the provided layer.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
This is the base class for vector data providers.
static QStringList availableEncodings()
Returns a list of available encodings.
@ SimplifyGeometries
Supports simplification of geometries on provider side according to a distance tolerance.
@ SelectEncoding
Allows user to select encoding.
@ CreateSpatialIndex
Allows creation of spatial index.
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
QString encoding() const
Returns the encoding which is used for accessing data.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
Defines left outer join from our vector layer to some other vector layer.
bool hasCascadedDelete() const
Returns whether a feature deleted on the target layer has to impact the joined layer by deleting the ...
bool isDynamicFormEnabled() const
Returns whether the form has to be dynamically updated with joined fields when a feature is being cre...
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
bool isUsingMemoryCache() const
Returns whether values from the joined layer should be cached in memory to speed up lookups.
QString prefix() const
Returns prefix of fields from the joined layer. If nullptr, joined layer's name will be used.
static QStringList joinFieldNamesSubset(const QgsVectorLayerJoinInfo &info, bool blocklisted=true)
Returns the list of field names to use for joining considering blocklisted fields and subset.
QString joinFieldName() const
Returns name of the field of joined layer that will be used for join.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet)
bool eventFilter(QObject *obj, QEvent *ev) override
QgsVectorLayerProperties(QgsMapCanvas *canvas, QgsMessageBar *messageBar, QgsVectorLayer *lyr=nullptr, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
void loadDefaultStyle()
Loads the default style when appropriate button is pressed.
void addPropertiesPageFactory(const QgsMapLayerConfigWidgetFactory *factory)
Adds a properties page factory to the vector layer properties dialog.
void optionsStackedWidget_CurrentChanged(int index) final
void toggleEditing(QgsMapLayer *)
void saveStyleAs()
Saves a style when appriate button is pressed.
void loadStyle()
Loads a saved style when appropriate button is pressed.
void saveDefaultStyle()
Saves the default style when appropriate button is pressed.
void exportAuxiliaryLayer(QgsAuxiliaryLayer *layer)
The QgsVectorLayerSaveStyleDialog class provides the UI to save the current style or multiple styles ...
Qgis::SldExportOptions sldExportOptions() const
Returns the SLD export options.
QgsMapLayer::StyleCategories styleCategories() const
QgsVectorLayerProperties::StyleType currentStyleType() const
A widget for configuring the temporal properties for a vector layer.
void syncToLayer()
Updates the widget state to match the current layer state.
void saveTemporalProperties()
Save widget temporal properties inputs.
Represents a vector layer which manages a vector based data sets.
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Saves named and sld style of the layer to the style table in the db.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Loads a named style from file/local db/datasource db.
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Returns the named style corresponding to style id provided.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
bool setDependencies(const QSet< QgsMapLayerDependency > &layers) FINAL
Sets the list of dependencies.
void setProviderEncoding(const QString &encoding)
Sets the text encoding of the data provider.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
virtual void updateExtents(bool force=false)
Update the extents for the layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QString subsetString
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
This class contains information how to simplify geometries fetched from a vector layer.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported,...
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
@ GeometrySimplification
The geometries can be simplified using the current map2pixel context state.
@ AntialiasingSimplification
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'.
@ NoSimplification
No simplification can be applied.
SimplifyAlgorithm
Types of local simplification algorithms that can be used.
@ Distance
The simplification uses the distance between points to remove duplicate points.
@ SnapToGrid
The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
The QgsWebView class is a collection of stubs to mimic the API of QWebView on systems where the real ...
Definition: qgswebview.h:66
The QgsWmsDimensionDialog class provides an interface for WMS/OAPIF (WFS3) dimensions configuration A...
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:4572
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:4571
const QgsField & field
Definition: qgsfield.h:554
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.
QString format
Format specification of online resource.
Setting to define QGIS Server WMS Dimension.