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