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