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