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