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