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