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