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