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