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