mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
1583 lines
54 KiB
C++
1583 lines
54 KiB
C++
/***************************************************************************
|
|
qgsdlgvectorlayerproperties.cpp
|
|
Unified property dialog for vector layers
|
|
-------------------
|
|
begin : 2004-01-28
|
|
copyright : (C) 2004 by Gary E.Sherman
|
|
email : sherman at mrcc.com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <memory>
|
|
#include <limits>
|
|
|
|
#include "qgisapp.h"
|
|
#include "qgsactionmanager.h"
|
|
#include "qgsjoindialog.h"
|
|
#include "qgsapplication.h"
|
|
#include "qgsattributeactiondialog.h"
|
|
#include "qgsapplydialog.h"
|
|
#include "qgscoordinatetransform.h"
|
|
#include "qgsdiagramproperties.h"
|
|
#include "qgsdiagramrenderer.h"
|
|
#include "qgsexpressionbuilderdialog.h"
|
|
#include "qgsfieldcalculator.h"
|
|
#include "qgsfieldsproperties.h"
|
|
#include "qgslabelingwidget.h"
|
|
#include "qgsprojectionselectiondialog.h"
|
|
#include "qgslogger.h"
|
|
#include "qgsmapcanvas.h"
|
|
#include "qgsmaplayerconfigwidgetfactory.h"
|
|
#include "qgsmaplayerstyleguiutils.h"
|
|
#include "qgsmetadatawidget.h"
|
|
#include "qgspluginmetadata.h"
|
|
#include "qgspluginregistry.h"
|
|
#include "qgsproject.h"
|
|
#include "qgssavestyletodbdialog.h"
|
|
#include "qgsloadstylefromdbdialog.h"
|
|
#include "qgsvectorlayer.h"
|
|
#include "qgsvectorlayerjoininfo.h"
|
|
#include "qgsvectorlayerproperties.h"
|
|
#include "qgsconfig.h"
|
|
#include "qgsvectordataprovider.h"
|
|
#include "qgsquerybuilder.h"
|
|
#include "qgsdatasourceuri.h"
|
|
#include "qgsrenderer.h"
|
|
#include "qgsexpressioncontext.h"
|
|
#include "qgssettings.h"
|
|
#include "qgsrendererpropertiesdialog.h"
|
|
#include "qgsstyle.h"
|
|
#include "qgsauxiliarystorage.h"
|
|
#include "qgsnewauxiliarylayerdialog.h"
|
|
|
|
#include "layertree/qgslayertreelayer.h"
|
|
#include "qgslayertree.h"
|
|
|
|
#include <QMessageBox>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileDialog>
|
|
#include <QFileInfo>
|
|
#include <QFontDialog>
|
|
#include <QComboBox>
|
|
#include <QCheckBox>
|
|
#include <QHeaderView>
|
|
#include <QColorDialog>
|
|
|
|
#include "qgsrendererpropertiesdialog.h"
|
|
#include "qgsstyle.h"
|
|
|
|
QgsVectorLayerProperties::QgsVectorLayerProperties(
|
|
QgsVectorLayer *lyr,
|
|
QWidget *parent,
|
|
Qt::WindowFlags fl
|
|
)
|
|
: QgsOptionsDialogBase( QStringLiteral( "VectorLayerProperties" ), parent, fl )
|
|
, mLayer( lyr )
|
|
, mOriginalSubsetSQL( lyr->subsetString() )
|
|
, mAuxiliaryLayerActionNew( nullptr )
|
|
, mAuxiliaryLayerActionClear( nullptr )
|
|
{
|
|
setupUi( this );
|
|
connect( mLayerOrigNameLineEdit, &QLineEdit::textEdited, this, &QgsVectorLayerProperties::mLayerOrigNameLineEdit_textEdited );
|
|
connect( pbnQueryBuilder, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnQueryBuilder_clicked );
|
|
connect( pbnIndex, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnIndex_clicked );
|
|
connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerProperties::mCrsSelector_crsChanged );
|
|
connect( pbnUpdateExtents, &QPushButton::clicked, this, &QgsVectorLayerProperties::pbnUpdateExtents_clicked );
|
|
connect( mButtonAddJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonAddJoin_clicked );
|
|
connect( mButtonEditJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonEditJoin_clicked );
|
|
connect( mJoinTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked );
|
|
connect( mButtonRemoveJoin, &QPushButton::clicked, this, &QgsVectorLayerProperties::mButtonRemoveJoin_clicked );
|
|
connect( mSimplifyDrawingGroupBox, &QGroupBox::toggled, this, &QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled );
|
|
connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsVectorLayerProperties::showHelp );
|
|
|
|
// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
|
|
// switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
|
|
// and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
|
|
initOptionsBase( false );
|
|
|
|
QPushButton *b = new QPushButton( tr( "Style" ) );
|
|
QMenu *m = new QMenu( this );
|
|
mActionLoadStyle = m->addAction( tr( "Load Style" ), this, SLOT( loadStyle_clicked() ) );
|
|
mActionSaveStyleAs = m->addAction( tr( "Save Style" ), this, SLOT( saveStyleAs_clicked() ) );
|
|
m->addSeparator();
|
|
m->addAction( tr( "Save as Default" ), this, SLOT( saveDefaultStyle_clicked() ) );
|
|
m->addAction( tr( "Restore Default" ), this, SLOT( loadDefaultStyle_clicked() ) );
|
|
b->setMenu( m );
|
|
connect( m, &QMenu::aboutToShow, this, &QgsVectorLayerProperties::aboutToShowStyleMenu );
|
|
buttonBox->addButton( b, QDialogButtonBox::ResetRole );
|
|
|
|
connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsVectorLayerProperties::syncToLayer );
|
|
|
|
connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsVectorLayerProperties::apply );
|
|
connect( this, &QDialog::accepted, this, &QgsVectorLayerProperties::apply );
|
|
connect( this, &QDialog::rejected, this, &QgsVectorLayerProperties::onCancel );
|
|
|
|
connect( mOptionsStackedWidget, &QStackedWidget::currentChanged, this, &QgsVectorLayerProperties::mOptionsStackedWidget_CurrentChanged );
|
|
|
|
mContext << QgsExpressionContextUtils::globalScope()
|
|
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
|
|
<< QgsExpressionContextUtils::atlasScope( nullptr )
|
|
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
|
|
<< QgsExpressionContextUtils::layerScope( mLayer );
|
|
|
|
mMapTipExpressionFieldWidget->setLayer( lyr );
|
|
mMapTipExpressionFieldWidget->registerExpressionContextGenerator( this );
|
|
mDisplayExpressionWidget->setLayer( lyr );
|
|
mDisplayExpressionWidget->registerExpressionContextGenerator( this );
|
|
|
|
connect( mInsertExpressionButton, &QAbstractButton::clicked, this, &QgsVectorLayerProperties::insertFieldOrExpression );
|
|
|
|
if ( !mLayer )
|
|
return;
|
|
|
|
QVBoxLayout *layout = nullptr;
|
|
|
|
if ( mLayer->isSpatial() )
|
|
{
|
|
// Create the Labeling dialog tab
|
|
layout = new QVBoxLayout( labelingFrame );
|
|
layout->setMargin( 0 );
|
|
labelingDialog = new QgsLabelingWidget( mLayer, QgisApp::instance()->mapCanvas(), labelingFrame );
|
|
labelingDialog->layout()->setContentsMargins( -1, 0, -1, 0 );
|
|
connect( labelingDialog, &QgsLabelingWidget::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
|
|
layout->addWidget( labelingDialog );
|
|
labelingFrame->setLayout( layout );
|
|
}
|
|
else
|
|
{
|
|
labelingDialog = nullptr;
|
|
mOptsPage_Labels->setEnabled( false ); // disable labeling item
|
|
}
|
|
|
|
// Create the Actions dialog tab
|
|
QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
|
|
actionLayout->setMargin( 0 );
|
|
mActionDialog = new QgsAttributeActionDialog( *mLayer->actions(), actionOptionsFrame );
|
|
mActionDialog->layout()->setMargin( 0 );
|
|
actionLayout->addWidget( mActionDialog );
|
|
|
|
// Create the menu for the save style button to choose the output format
|
|
mSaveAsMenu = new QMenu( this );
|
|
mSaveAsMenu->addAction( tr( "QGIS Layer Style File..." ) );
|
|
mSaveAsMenu->addAction( tr( "SLD File..." ) );
|
|
|
|
//Only if the provider support loading & saving styles to db add new choices
|
|
if ( mLayer->dataProvider()->isSaveAndLoadStyleToDatabaseSupported() )
|
|
{
|
|
//for loading
|
|
mLoadStyleMenu = new QMenu( this );
|
|
mLoadStyleMenu->addAction( tr( "Load from file..." ) );
|
|
mLoadStyleMenu->addAction( tr( "Database styles manager" ) );
|
|
//mActionLoadStyle->setContextMenuPolicy( Qt::PreventContextMenu );
|
|
mActionLoadStyle->setMenu( mLoadStyleMenu );
|
|
|
|
connect( mLoadStyleMenu, &QMenu::triggered,
|
|
this, &QgsVectorLayerProperties::loadStyleMenuTriggered );
|
|
|
|
//for saving
|
|
QString providerName = mLayer->providerType();
|
|
if ( providerName == QLatin1String( "ogr" ) )
|
|
{
|
|
providerName = mLayer->dataProvider()->storageType();
|
|
if ( providerName == QLatin1String( "GPKG" ) )
|
|
providerName = QStringLiteral( "GeoPackage" );
|
|
}
|
|
mSaveAsMenu->addAction( tr( "Save in database (%1)" ).arg( providerName ) );
|
|
}
|
|
|
|
connect( mSaveAsMenu, &QMenu::triggered,
|
|
this, &QgsVectorLayerProperties::saveStyleAsMenuTriggered );
|
|
|
|
mFieldsPropertiesDialog = new QgsFieldsProperties( mLayer, mFieldsFrame );
|
|
mFieldsPropertiesDialog->layout()->setMargin( 0 );
|
|
mFieldsFrame->setLayout( new QVBoxLayout( mFieldsFrame ) );
|
|
mFieldsFrame->layout()->setMargin( 0 );
|
|
mFieldsFrame->layout()->addWidget( mFieldsPropertiesDialog );
|
|
|
|
connect( mFieldsPropertiesDialog, &QgsFieldsProperties::toggleEditing, this, static_cast<void ( QgsVectorLayerProperties::* )()>( &QgsVectorLayerProperties::toggleEditing ) );
|
|
connect( this, static_cast<void ( QgsVectorLayerProperties::* )( QgsMapLayer * )>( &QgsVectorLayerProperties::toggleEditing ),
|
|
QgisApp::instance(), [ = ]( QgsMapLayer * layer ) { QgisApp::instance()->toggleEditing( layer ); } );
|
|
|
|
syncToLayer();
|
|
|
|
if ( mLayer->dataProvider() )//enable spatial index button group if supported by provider
|
|
{
|
|
int capabilities = mLayer->dataProvider()->capabilities();
|
|
if ( !( capabilities & QgsVectorDataProvider::CreateSpatialIndex ) )
|
|
{
|
|
pbnIndex->setEnabled( false );
|
|
}
|
|
|
|
if ( capabilities & QgsVectorDataProvider::SelectEncoding )
|
|
{
|
|
cboProviderEncoding->addItems( QgsVectorDataProvider::availableEncodings() );
|
|
QString enc = mLayer->dataProvider()->encoding();
|
|
int encindex = cboProviderEncoding->findText( enc );
|
|
if ( encindex < 0 )
|
|
{
|
|
cboProviderEncoding->insertItem( 0, enc );
|
|
encindex = 0;
|
|
}
|
|
cboProviderEncoding->setCurrentIndex( encindex );
|
|
}
|
|
else if ( mLayer->dataProvider()->name() == QLatin1String( "ogr" ) )
|
|
{
|
|
// if OGR_L_TestCapability(OLCStringsAsUTF8) returns true, OGR provider encoding can be set to only UTF-8
|
|
// so make encoding box grayed out
|
|
cboProviderEncoding->addItem( mLayer->dataProvider()->encoding() );
|
|
cboProviderEncoding->setEnabled( false );
|
|
}
|
|
else
|
|
{
|
|
// other providers do not use mEncoding, so hide the group completely
|
|
mDataSourceEncodingFrame->hide();
|
|
}
|
|
}
|
|
|
|
mCrsSelector->setCrs( mLayer->crs() );
|
|
|
|
//insert existing join info
|
|
const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
|
|
for ( int i = 0; i < joins.size(); ++i )
|
|
{
|
|
addJoinToTreeWidget( joins[i] );
|
|
}
|
|
|
|
mOldJoins = mLayer->vectorJoins();
|
|
|
|
QVBoxLayout *diagLayout = new QVBoxLayout( mDiagramFrame );
|
|
diagLayout->setMargin( 0 );
|
|
diagramPropertiesDialog = new QgsDiagramProperties( mLayer, mDiagramFrame, QgisApp::instance()->mapCanvas() );
|
|
diagramPropertiesDialog->layout()->setContentsMargins( -1, 0, -1, 0 );
|
|
connect( diagramPropertiesDialog, &QgsDiagramProperties::auxiliaryFieldCreated, this, [ = ] { updateAuxiliaryStoragePage(); } );
|
|
diagLayout->addWidget( diagramPropertiesDialog );
|
|
mDiagramFrame->setLayout( diagLayout );
|
|
|
|
// Metadata tab
|
|
QVBoxLayout *metadataLayout = new QVBoxLayout( metadataFrame );
|
|
metadataLayout->setMargin( 0 );
|
|
mMetadataWidget = new QgsMetadataWidget( this, mLayer );
|
|
mMetadataWidget->layout()->setContentsMargins( -1, 0, -1, 0 );
|
|
metadataLayout->addWidget( mMetadataWidget );
|
|
metadataFrame->setLayout( metadataLayout );
|
|
|
|
// Legend tab
|
|
mLegendConfigEmbeddedWidget->setLayer( mLayer );
|
|
|
|
// WMS Name as layer short name
|
|
mLayerShortNameLineEdit->setText( mLayer->shortName() );
|
|
// WMS Name validator
|
|
QValidator *shortNameValidator = new QRegExpValidator( QgsApplication::shortNameRegExp(), this );
|
|
mLayerShortNameLineEdit->setValidator( shortNameValidator );
|
|
|
|
//layer title and abstract
|
|
mLayerTitleLineEdit->setText( mLayer->title() );
|
|
mLayerAbstractTextEdit->setPlainText( mLayer->abstract() );
|
|
mLayerKeywordListLineEdit->setText( mLayer->keywordList() );
|
|
mLayerDataUrlLineEdit->setText( mLayer->dataUrl() );
|
|
mLayerDataUrlFormatComboBox->setCurrentIndex(
|
|
mLayerDataUrlFormatComboBox->findText(
|
|
mLayer->dataUrlFormat()
|
|
)
|
|
);
|
|
//layer attribution and metadataUrl
|
|
mLayerAttributionLineEdit->setText( mLayer->attribution() );
|
|
mLayerAttributionUrlLineEdit->setText( mLayer->attributionUrl() );
|
|
mLayerMetadataUrlLineEdit->setText( mLayer->metadataUrl() );
|
|
mLayerMetadataUrlTypeComboBox->setCurrentIndex(
|
|
mLayerMetadataUrlTypeComboBox->findText(
|
|
mLayer->metadataUrlType()
|
|
)
|
|
);
|
|
mLayerMetadataUrlFormatComboBox->setCurrentIndex(
|
|
mLayerMetadataUrlFormatComboBox->findText(
|
|
mLayer->metadataUrlFormat()
|
|
)
|
|
);
|
|
mLayerLegendUrlLineEdit->setText( mLayer->legendUrl() );
|
|
mLayerLegendUrlFormatComboBox->setCurrentIndex(
|
|
mLayerLegendUrlFormatComboBox->findText(
|
|
mLayer->legendUrlFormat()
|
|
)
|
|
);
|
|
|
|
QString myStyle = QgsApplication::reportStyleSheet();
|
|
myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
|
|
teMetadataViewer->clear();
|
|
teMetadataViewer->document()->setDefaultStyleSheet( myStyle );
|
|
teMetadataViewer->setHtml( htmlMetadata() );
|
|
mMetadataFilled = true;
|
|
|
|
QgsSettings settings;
|
|
// if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
|
|
// this will be read by restoreOptionsBaseUi()
|
|
if ( !settings.contains( QStringLiteral( "/Windows/VectorLayerProperties/tab" ) ) )
|
|
{
|
|
settings.setValue( QStringLiteral( "Windows/VectorLayerProperties/tab" ),
|
|
mOptStackedWidget->indexOf( mOptsPage_Style ) );
|
|
}
|
|
|
|
QString title = QString( tr( "Layer Properties - %1" ) ).arg( mLayer->name() );
|
|
restoreOptionsBaseUi( title );
|
|
|
|
mLayersDependenciesTreeGroup.reset( QgsProject::instance()->layerTreeRoot()->clone() );
|
|
QgsLayerTreeLayer *layer = mLayersDependenciesTreeGroup->findLayer( mLayer->id() );
|
|
if ( layer )
|
|
{
|
|
layer->parent()->takeChild( layer );
|
|
}
|
|
mLayersDependenciesTreeModel.reset( new QgsLayerTreeModel( mLayersDependenciesTreeGroup.get() ) );
|
|
// use visibility as selection
|
|
mLayersDependenciesTreeModel->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility );
|
|
|
|
mLayersDependenciesTreeGroup->setItemVisibilityChecked( false );
|
|
|
|
QSet<QString> dependencySources;
|
|
Q_FOREACH ( const QgsMapLayerDependency &dep, mLayer->dependencies() )
|
|
{
|
|
dependencySources << dep.layerId();
|
|
}
|
|
Q_FOREACH ( QgsLayerTreeLayer *layer, mLayersDependenciesTreeGroup->findLayers() )
|
|
{
|
|
layer->setItemVisibilityChecked( dependencySources.contains( layer->layerId() ) );
|
|
}
|
|
|
|
mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel.get() );
|
|
|
|
connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );
|
|
|
|
// auxiliary layer
|
|
QMenu *menu = new QMenu( this );
|
|
|
|
mAuxiliaryLayerActionNew = new QAction( tr( "Create" ), this );
|
|
menu->addAction( mAuxiliaryLayerActionNew );
|
|
connect( mAuxiliaryLayerActionNew, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerNew );
|
|
|
|
mAuxiliaryLayerActionClear = new QAction( tr( "Clear" ), this );
|
|
menu->addAction( mAuxiliaryLayerActionClear );
|
|
connect( mAuxiliaryLayerActionClear, &QAction::triggered, this, &QgsVectorLayerProperties::onAuxiliaryLayerClear );
|
|
|
|
mAuxiliaryStorageActions->setMenu( menu );
|
|
|
|
updateAuxiliaryStoragePage();
|
|
}
|
|
|
|
void QgsVectorLayerProperties::toggleEditing()
|
|
{
|
|
if ( !mLayer )
|
|
return;
|
|
|
|
emit toggleEditing( mLayer );
|
|
|
|
setPbnQueryBuilderEnabled();
|
|
}
|
|
|
|
void QgsVectorLayerProperties::addPropertiesPageFactory( QgsMapLayerConfigWidgetFactory *factory )
|
|
{
|
|
if ( !factory->supportLayerPropertiesDialog() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QListWidgetItem *item = new QListWidgetItem();
|
|
item->setIcon( factory->icon() );
|
|
item->setText( factory->title() );
|
|
item->setToolTip( factory->title() );
|
|
|
|
mOptionsListWidget->addItem( item );
|
|
|
|
QgsMapLayerConfigWidget *page = factory->createWidget( mLayer, nullptr, false, this );
|
|
mLayerPropertiesPages << page;
|
|
mOptionsStackedWidget->addWidget( page );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::insertFieldOrExpression()
|
|
{
|
|
// Convert the selected field to an expression and
|
|
// insert it into the action at the cursor position
|
|
QString expression = QStringLiteral( "[% \"" );
|
|
expression += mMapTipExpressionFieldWidget->asExpression();
|
|
expression += QLatin1String( "\" %]" );
|
|
|
|
mMapTipWidget->insertText( expression );
|
|
}
|
|
|
|
// in raster props, this method is called sync()
|
|
void QgsVectorLayerProperties::syncToLayer()
|
|
{
|
|
// populate the general information
|
|
mLayerOrigNameLineEdit->setText( mLayer->originalName() );
|
|
txtDisplayName->setText( mLayer->name() );
|
|
pbnQueryBuilder->setWhatsThis( tr( "This button opens the query "
|
|
"builder and allows you to create a subset of features to display on "
|
|
"the map canvas rather than displaying all features in the layer" ) );
|
|
txtSubsetSQL->setWhatsThis( tr( "The query used to limit the features in the "
|
|
"layer is shown here. To enter or modify the query, click on the Query Builder button" ) );
|
|
|
|
//see if we are dealing with a pg layer here
|
|
mSubsetGroupBox->setEnabled( true );
|
|
txtSubsetSQL->setText( mLayer->subsetString() );
|
|
// if the user is allowed to type an adhoc query, the app will crash if the query
|
|
// is bad. For this reason, the sql box is disabled and the query must be built
|
|
// using the query builder, either by typing it in by hand or using the buttons, etc
|
|
// on the builder. If the ability to enter a query directly into the box is required,
|
|
// a mechanism to check it must be implemented.
|
|
txtSubsetSQL->setEnabled( false );
|
|
setPbnQueryBuilderEnabled();
|
|
|
|
mMapTipWidget->setText( mLayer->mapTipTemplate() );
|
|
mDisplayExpressionWidget->setField( mLayer->displayExpression() );
|
|
|
|
// set up the scale based layer visibility stuff....
|
|
mScaleRangeWidget->setScaleRange( mLayer->minimumScale(), mLayer->maximumScale() );
|
|
mScaleVisibilityGroupBox->setChecked( mLayer->hasScaleBasedVisibility() );
|
|
mScaleRangeWidget->setMapCanvas( QgisApp::instance()->mapCanvas() );
|
|
|
|
// get simplify drawing configuration
|
|
const QgsVectorSimplifyMethod &simplifyMethod = mLayer->simplifyMethod();
|
|
mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification );
|
|
mSimplifyDrawingSpinBox->setValue( simplifyMethod.threshold() );
|
|
|
|
QString remark = QStringLiteral( " (%1)" ).arg( tr( "Not supported" ) );
|
|
if ( !( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) )
|
|
{
|
|
mSimplifyDrawingAtProvider->setChecked( false );
|
|
mSimplifyDrawingAtProvider->setEnabled( false );
|
|
if ( !mSimplifyDrawingAtProvider->text().endsWith( remark ) )
|
|
mSimplifyDrawingAtProvider->setText( mSimplifyDrawingAtProvider->text().append( remark ) );
|
|
}
|
|
else
|
|
{
|
|
mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() );
|
|
mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() );
|
|
if ( mSimplifyDrawingAtProvider->text().endsWith( remark ) )
|
|
{
|
|
QString newText = mSimplifyDrawingAtProvider->text();
|
|
newText.chop( remark.size() );
|
|
mSimplifyDrawingAtProvider->setText( newText );
|
|
}
|
|
}
|
|
|
|
// disable simplification for point layers, now it is not implemented
|
|
if ( mLayer->geometryType() == QgsWkbTypes::PointGeometry )
|
|
{
|
|
mSimplifyDrawingGroupBox->setChecked( false );
|
|
mSimplifyDrawingGroupBox->setEnabled( false );
|
|
}
|
|
|
|
// Default local simplification algorithm
|
|
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
|
|
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
|
|
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
|
|
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( ( int )simplifyMethod.simplifyAlgorithm() ) );
|
|
|
|
QStringList myScalesList = PROJECT_SCALES.split( ',' );
|
|
myScalesList.append( QStringLiteral( "1:1" ) );
|
|
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
|
|
mSimplifyMaximumScaleComboBox->setScale( simplifyMethod.maximumScale() );
|
|
|
|
mForceRasterCheckBox->setChecked( mLayer->renderer() && mLayer->renderer()->forceRasterRender() );
|
|
|
|
mRefreshLayerCheckBox->setChecked( mLayer->hasAutoRefreshEnabled() );
|
|
mRefreshLayerIntervalSpinBox->setEnabled( mLayer->hasAutoRefreshEnabled() );
|
|
mRefreshLayerIntervalSpinBox->setValue( mLayer->autoRefreshInterval() / 1000.0 );
|
|
|
|
mRefreshLayerNotificationCheckBox->setChecked( mLayer->isRefreshOnNotifyEnabled() );
|
|
mNotificationMessageCheckBox->setChecked( !mLayer->refreshOnNotifyMessage().isEmpty() );
|
|
mNotifyMessagValueLineEdit->setText( mLayer->refreshOnNotifyMessage() );
|
|
|
|
|
|
// load appropriate symbology page (V1 or V2)
|
|
updateSymbologyPage();
|
|
|
|
mActionDialog->init( *mLayer->actions(), mLayer->attributeTableConfig() );
|
|
|
|
if ( labelingDialog )
|
|
labelingDialog->adaptToLayer();
|
|
|
|
mFieldsPropertiesDialog->init();
|
|
|
|
// set initial state for variable editor
|
|
updateVariableEditor();
|
|
|
|
// updates the init python code and ui
|
|
updateFieldsPropertiesDialog();
|
|
|
|
} // syncToLayer()
|
|
|
|
|
|
|
|
void QgsVectorLayerProperties::apply()
|
|
{
|
|
if ( labelingDialog )
|
|
{
|
|
labelingDialog->writeSettingsToLayer();
|
|
}
|
|
|
|
// apply legend settings
|
|
mLegendConfigEmbeddedWidget->applyToLayer();
|
|
|
|
// save metadata
|
|
mMetadataWidget->acceptMetadata();
|
|
mMetadataFilled = false;
|
|
|
|
//
|
|
// Set up sql subset query if applicable
|
|
//
|
|
mSubsetGroupBox->setEnabled( true );
|
|
|
|
if ( txtSubsetSQL->toPlainText() != mLayer->subsetString() )
|
|
{
|
|
// set the subset sql for the layer
|
|
mLayer->setSubsetString( txtSubsetSQL->toPlainText() );
|
|
mMetadataFilled = false;
|
|
}
|
|
mOriginalSubsetSQL = mLayer->subsetString();
|
|
|
|
// set up the scale based layer visibility stuff....
|
|
mLayer->setScaleBasedVisibility( mScaleVisibilityGroupBox->isChecked() );
|
|
mLayer->setMaximumScale( mScaleRangeWidget->maximumScale() );
|
|
mLayer->setMinimumScale( mScaleRangeWidget->minimumScale() );
|
|
|
|
// provider-specific options
|
|
if ( mLayer->dataProvider() )
|
|
{
|
|
if ( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::SelectEncoding )
|
|
{
|
|
mLayer->setProviderEncoding( cboProviderEncoding->currentText() );
|
|
}
|
|
}
|
|
|
|
mLayer->setDisplayExpression( mDisplayExpressionWidget->currentField() );
|
|
mLayer->setMapTipTemplate( mMapTipWidget->text() );
|
|
|
|
mLayer->actions()->clearActions();
|
|
Q_FOREACH ( const QgsAction &action, mActionDialog->actions() )
|
|
{
|
|
mLayer->actions()->addAction( action );
|
|
}
|
|
QgsAttributeTableConfig attributeTableConfig = mLayer->attributeTableConfig();
|
|
attributeTableConfig.update( mLayer->fields() );
|
|
attributeTableConfig.setActionWidgetStyle( mActionDialog->attributeTableWidgetStyle() );
|
|
QVector<QgsAttributeTableConfig::ColumnConfig> columns = attributeTableConfig.columns();
|
|
|
|
for ( int i = 0; i < columns.size(); ++i )
|
|
{
|
|
if ( columns.at( i ).type == QgsAttributeTableConfig::Action )
|
|
{
|
|
columns[i].hidden = !mActionDialog->showWidgetInAttributeTable();
|
|
}
|
|
}
|
|
|
|
attributeTableConfig.setColumns( columns );
|
|
|
|
mLayer->setAttributeTableConfig( attributeTableConfig );
|
|
|
|
mLayer->setName( mLayerOrigNameLineEdit->text() );
|
|
|
|
// Apply fields settings
|
|
mFieldsPropertiesDialog->apply();
|
|
|
|
if ( mLayer->renderer() )
|
|
{
|
|
QgsRendererPropertiesDialog *dlg = static_cast<QgsRendererPropertiesDialog *>( widgetStackRenderers->currentWidget() );
|
|
dlg->apply();
|
|
}
|
|
|
|
//apply diagram settings
|
|
diagramPropertiesDialog->apply();
|
|
|
|
// apply all plugin dialogs
|
|
Q_FOREACH ( QgsMapLayerConfigWidget *page, mLayerPropertiesPages )
|
|
{
|
|
page->apply();
|
|
}
|
|
|
|
//layer title and abstract
|
|
if ( mLayer->shortName() != mLayerShortNameLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setShortName( mLayerShortNameLineEdit->text() );
|
|
|
|
if ( mLayer->title() != mLayerTitleLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setTitle( mLayerTitleLineEdit->text() );
|
|
|
|
if ( mLayer->abstract() != mLayerAbstractTextEdit->toPlainText() )
|
|
mMetadataFilled = false;
|
|
mLayer->setAbstract( mLayerAbstractTextEdit->toPlainText() );
|
|
|
|
if ( mLayer->keywordList() != mLayerKeywordListLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setKeywordList( mLayerKeywordListLineEdit->text() );
|
|
|
|
if ( mLayer->dataUrl() != mLayerDataUrlLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setDataUrl( mLayerDataUrlLineEdit->text() );
|
|
|
|
if ( mLayer->dataUrlFormat() != mLayerDataUrlFormatComboBox->currentText() )
|
|
mMetadataFilled = false;
|
|
mLayer->setDataUrlFormat( mLayerDataUrlFormatComboBox->currentText() );
|
|
|
|
//layer attribution and metadataUrl
|
|
if ( mLayer->attribution() != mLayerAttributionLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setAttribution( mLayerAttributionLineEdit->text() );
|
|
|
|
if ( mLayer->attributionUrl() != mLayerAttributionUrlLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setAttributionUrl( mLayerAttributionUrlLineEdit->text() );
|
|
|
|
if ( mLayer->metadataUrl() != mLayerMetadataUrlLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setMetadataUrl( mLayerMetadataUrlLineEdit->text() );
|
|
|
|
if ( mLayer->metadataUrlType() != mLayerMetadataUrlTypeComboBox->currentText() )
|
|
mMetadataFilled = false;
|
|
mLayer->setMetadataUrlType( mLayerMetadataUrlTypeComboBox->currentText() );
|
|
|
|
if ( mLayer->metadataUrlFormat() != mLayerMetadataUrlFormatComboBox->currentText() )
|
|
mMetadataFilled = false;
|
|
mLayer->setMetadataUrlFormat( mLayerMetadataUrlFormatComboBox->currentText() );
|
|
|
|
// LegendURL
|
|
if ( mLayer->legendUrl() != mLayerLegendUrlLineEdit->text() )
|
|
mMetadataFilled = false;
|
|
mLayer->setLegendUrl( mLayerLegendUrlLineEdit->text() );
|
|
|
|
if ( mLayer->legendUrlFormat() != mLayerLegendUrlFormatComboBox->currentText() )
|
|
mMetadataFilled = false;
|
|
mLayer->setLegendUrlFormat( mLayerLegendUrlFormatComboBox->currentText() );
|
|
|
|
//layer simplify drawing configuration
|
|
QgsVectorSimplifyMethod::SimplifyHints simplifyHints = QgsVectorSimplifyMethod::NoSimplification;
|
|
if ( mSimplifyDrawingGroupBox->isChecked() )
|
|
{
|
|
simplifyHints |= QgsVectorSimplifyMethod::GeometrySimplification;
|
|
if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorSimplifyMethod::AntialiasingSimplification;
|
|
}
|
|
QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
|
|
simplifyMethod.setSimplifyHints( simplifyHints );
|
|
simplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( mSimplifyAlgorithmComboBox->currentData().toInt() ) );
|
|
simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
|
|
simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
|
|
simplifyMethod.setMaximumScale( mSimplifyMaximumScaleComboBox->scale() );
|
|
mLayer->setSimplifyMethod( simplifyMethod );
|
|
|
|
if ( mLayer->renderer() )
|
|
mLayer->renderer()->setForceRasterRender( mForceRasterCheckBox->isChecked() );
|
|
|
|
mLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
|
|
mLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );
|
|
|
|
mLayer->setRefreshOnNotifyEnabled( mRefreshLayerNotificationCheckBox->isChecked() );
|
|
mLayer->setRefreshOnNofifyMessage( mNotificationMessageCheckBox->isChecked() ? mNotifyMessagValueLineEdit->text() : QString() );
|
|
|
|
mOldJoins = mLayer->vectorJoins();
|
|
|
|
//save variables
|
|
QgsExpressionContextUtils::setLayerVariables( mLayer, mVariableEditor->variablesInActiveScope() );
|
|
updateVariableEditor();
|
|
|
|
// save dependencies
|
|
QSet<QgsMapLayerDependency> deps;
|
|
Q_FOREACH ( const QgsLayerTreeLayer *layer, mLayersDependenciesTreeGroup->findLayers() )
|
|
{
|
|
if ( layer->isVisible() )
|
|
deps << QgsMapLayerDependency( layer->layerId() );
|
|
}
|
|
if ( ! mLayer->setDependencies( deps ) )
|
|
{
|
|
QMessageBox::warning( nullptr, tr( "Dependency cycle" ), tr( "This configuration introduces a cycle in data dependencies and will be ignored" ) );
|
|
}
|
|
|
|
// update symbology
|
|
emit refreshLegend( mLayer->id() );
|
|
|
|
mLayer->triggerRepaint();
|
|
// notify the project we've made a change
|
|
QgsProject::instance()->setDirty( true );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::onCancel()
|
|
{
|
|
if ( mOldJoins != mLayer->vectorJoins() )
|
|
{
|
|
// need to undo changes in vector layer joins - they are applied directly to the layer (not in apply())
|
|
// so other parts of the properties dialog can use the fields from the joined layers
|
|
|
|
Q_FOREACH ( const QgsVectorLayerJoinInfo &info, mLayer->vectorJoins() )
|
|
mLayer->removeJoin( info.joinLayerId() );
|
|
|
|
Q_FOREACH ( const QgsVectorLayerJoinInfo &info, mOldJoins )
|
|
mLayer->addJoin( info );
|
|
}
|
|
|
|
if ( mOriginalSubsetSQL != mLayer->subsetString() )
|
|
{
|
|
// need to undo changes in subset string - they are applied directly to the layer (not in apply())
|
|
// by QgsQueryBuilder::accept()
|
|
|
|
mLayer->setSubsetString( mOriginalSubsetSQL );
|
|
}
|
|
|
|
if ( mOldStyle.xmlData() != mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() ).xmlData() )
|
|
{
|
|
// need to reset style to previous - style applied directly to the layer (not in apply())
|
|
QString myMessage;
|
|
QDomDocument doc( QStringLiteral( "qgis" ) );
|
|
int errorLine, errorColumn;
|
|
doc.setContent( mOldStyle.xmlData(), false, &myMessage, &errorLine, &errorColumn );
|
|
mLayer->importNamedStyle( doc, myMessage );
|
|
syncToLayer();
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::pbnQueryBuilder_clicked()
|
|
{
|
|
// launch the query builder
|
|
QgsQueryBuilder *qb = new QgsQueryBuilder( mLayer, this );
|
|
|
|
// Set the sql in the query builder to the same in the prop dialog
|
|
// (in case the user has already changed it)
|
|
qb->setSql( txtSubsetSQL->toPlainText() );
|
|
// Open the query builder
|
|
if ( qb->exec() )
|
|
{
|
|
// if the sql is changed, update it in the prop subset text box
|
|
txtSubsetSQL->setText( qb->sql() );
|
|
//TODO If the sql is changed in the prop dialog, the layer extent should be recalculated
|
|
|
|
// The datasource for the layer needs to be updated with the new sql since this gets
|
|
// saved to the project file. This should happen at the map layer level...
|
|
|
|
}
|
|
// delete the query builder object
|
|
delete qb;
|
|
}
|
|
|
|
void QgsVectorLayerProperties::pbnIndex_clicked()
|
|
{
|
|
QgsVectorDataProvider *pr = mLayer->dataProvider();
|
|
if ( pr )
|
|
{
|
|
setCursor( Qt::WaitCursor );
|
|
bool errval = pr->createSpatialIndex();
|
|
setCursor( Qt::ArrowCursor );
|
|
if ( errval )
|
|
{
|
|
QMessageBox::information( this, tr( "Spatial Index" ), tr( "Creation of spatial index successful" ) );
|
|
}
|
|
else
|
|
{
|
|
// TODO: Remind the user to use OGR >= 1.2.6 and Shapefile
|
|
QMessageBox::information( this, tr( "Spatial Index" ), tr( "Creation of spatial index failed" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
QString QgsVectorLayerProperties::htmlMetadata()
|
|
{
|
|
return mLayer->htmlMetadata();
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mLayerOrigNameLineEdit_textEdited( const QString &text )
|
|
{
|
|
txtDisplayName->setText( mLayer->capitalizeLayerName( text ) );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs )
|
|
{
|
|
mLayer->setCrs( crs );
|
|
mMetadataFilled = false;
|
|
}
|
|
|
|
void QgsVectorLayerProperties::loadDefaultStyle_clicked()
|
|
{
|
|
QString msg;
|
|
bool defaultLoadedFlag = false;
|
|
|
|
if ( mLayer->dataProvider()->isSaveAndLoadStyleToDatabaseSupported() )
|
|
{
|
|
QMessageBox askToUser;
|
|
askToUser.setText( tr( "Load default style from: " ) );
|
|
askToUser.setIcon( QMessageBox::Question );
|
|
askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
|
|
askToUser.addButton( tr( "Local database" ), QMessageBox::NoRole );
|
|
askToUser.addButton( tr( "Datasource database" ), QMessageBox::YesRole );
|
|
|
|
switch ( askToUser.exec() )
|
|
{
|
|
case 0:
|
|
return;
|
|
case 2:
|
|
msg = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag );
|
|
if ( !defaultLoadedFlag )
|
|
{
|
|
//something went wrong - let them know why
|
|
QMessageBox::information( this, tr( "Default Style" ), msg );
|
|
}
|
|
if ( msg.compare( tr( "Loaded from Provider" ) ) )
|
|
{
|
|
QMessageBox::information( this, tr( "Default Style" ),
|
|
tr( "No default style was found for this layer" ) );
|
|
}
|
|
else
|
|
{
|
|
syncToLayer();
|
|
}
|
|
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
QString myMessage = mLayer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true );
|
|
// QString myMessage = layer->loadDefaultStyle( defaultLoadedFlag );
|
|
//reset if the default style was loaded OK only
|
|
if ( defaultLoadedFlag )
|
|
{
|
|
// all worked OK so no need to inform user
|
|
syncToLayer();
|
|
}
|
|
else
|
|
{
|
|
//something went wrong - let them know why
|
|
QMessageBox::information( this, tr( "Default Style" ), myMessage );
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::saveDefaultStyle_clicked()
|
|
{
|
|
apply();
|
|
QString errorMsg;
|
|
if ( mLayer->dataProvider()->isSaveAndLoadStyleToDatabaseSupported() )
|
|
{
|
|
QMessageBox askToUser;
|
|
askToUser.setText( tr( "Save default style to: " ) );
|
|
askToUser.setIcon( QMessageBox::Question );
|
|
askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
|
|
askToUser.addButton( tr( "Local database" ), QMessageBox::NoRole );
|
|
askToUser.addButton( tr( "Datasource database" ), QMessageBox::YesRole );
|
|
|
|
switch ( askToUser.exec() )
|
|
{
|
|
case 0:
|
|
return;
|
|
case 2:
|
|
mLayer->saveStyleToDatabase( QLatin1String( "" ), QLatin1String( "" ), true, QLatin1String( "" ), errorMsg );
|
|
if ( errorMsg.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool defaultSavedFlag = false;
|
|
errorMsg = mLayer->saveDefaultStyle( defaultSavedFlag );
|
|
if ( !defaultSavedFlag )
|
|
{
|
|
QMessageBox::warning( this, tr( "Default Style" ), errorMsg );
|
|
}
|
|
}
|
|
|
|
|
|
void QgsVectorLayerProperties::loadStyle_clicked()
|
|
{
|
|
QgsSettings myQSettings; // where we keep last used filter in persistent state
|
|
QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
|
|
|
|
QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer properties from style file" ), myLastUsedDir,
|
|
tr( "QGIS Layer Style File" ) + " (*.qml);;" + tr( "SLD File" ) + " (*.sld)" );
|
|
if ( myFileName.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
mOldStyle = mLayer->styleManager()->style( mLayer->styleManager()->currentStyle() );
|
|
|
|
QString myMessage;
|
|
bool defaultLoadedFlag = false;
|
|
|
|
if ( myFileName.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
|
|
{
|
|
// load from SLD
|
|
myMessage = mLayer->loadSldStyle( myFileName, defaultLoadedFlag );
|
|
}
|
|
else
|
|
{
|
|
myMessage = mLayer->loadNamedStyle( myFileName, defaultLoadedFlag );
|
|
}
|
|
//reset if the default style was loaded OK only
|
|
if ( defaultLoadedFlag )
|
|
{
|
|
syncToLayer();
|
|
}
|
|
else
|
|
{
|
|
//let the user know what went wrong
|
|
QMessageBox::warning( this, tr( "Load Style" ), myMessage );
|
|
}
|
|
|
|
QFileInfo myFI( myFileName );
|
|
QString myPath = myFI.path();
|
|
myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
|
|
|
|
activateWindow(); // set focus back to properties dialog
|
|
}
|
|
|
|
|
|
void QgsVectorLayerProperties::saveStyleAs_clicked()
|
|
{
|
|
saveStyleAs( QML );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::saveStyleAsMenuTriggered( QAction *action )
|
|
{
|
|
QMenu *menu = qobject_cast<QMenu *>( sender() );
|
|
if ( !menu )
|
|
return;
|
|
|
|
int index = mSaveAsMenu->actions().indexOf( action );
|
|
if ( index < 0 )
|
|
return;
|
|
|
|
saveStyleAs( static_cast< StyleType >( index ) );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::saveStyleAs( StyleType styleType )
|
|
{
|
|
QgsSettings myQSettings; // where we keep last used filter in persistent state
|
|
QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
|
|
|
|
if ( styleType == DB )
|
|
{
|
|
QString infoWindowTitle = QObject::tr( "Save style to DB (%1)" ).arg( mLayer->providerType() );
|
|
QString msgError;
|
|
|
|
QgsSaveStyleToDbDialog askToUser;
|
|
//Ask the user for a name and a description about the style
|
|
if ( askToUser.exec() == QDialog::Accepted )
|
|
{
|
|
QString styleName = askToUser.getName();
|
|
QString styleDesc = askToUser.getDescription();
|
|
QString uiFileContent = askToUser.getUIFileContent();
|
|
bool isDefault = askToUser.isDefault();
|
|
|
|
apply();
|
|
|
|
mLayer->saveStyleToDatabase( styleName, styleDesc, isDefault, uiFileContent, msgError );
|
|
|
|
if ( !msgError.isNull() )
|
|
{
|
|
QgisApp::instance()->messageBar()->pushMessage( infoWindowTitle, msgError, QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() );
|
|
}
|
|
else
|
|
{
|
|
QgisApp::instance()->messageBar()->pushMessage( infoWindowTitle, tr( "Style saved" ), QgsMessageBar::INFO, QgisApp::instance()->messageTimeout() );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
QString format, extension;
|
|
if ( styleType == SLD )
|
|
{
|
|
format = tr( "SLD File" ) + " (*.sld)";
|
|
extension = QStringLiteral( ".sld" );
|
|
}
|
|
else
|
|
{
|
|
format = tr( "QGIS Layer Style File" ) + " (*.qml)";
|
|
extension = QStringLiteral( ".qml" );
|
|
}
|
|
|
|
QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save layer properties as style file" ),
|
|
myLastUsedDir, format );
|
|
if ( myOutputFileName.isNull() ) //dialog canceled
|
|
{
|
|
return;
|
|
}
|
|
|
|
apply(); // make sure the style to save is uptodate
|
|
|
|
QString myMessage;
|
|
bool defaultLoadedFlag = false;
|
|
|
|
//ensure the user never omitted the extension from the file name
|
|
if ( !myOutputFileName.endsWith( extension, Qt::CaseInsensitive ) )
|
|
{
|
|
myOutputFileName += extension;
|
|
}
|
|
|
|
if ( styleType == SLD )
|
|
{
|
|
// convert to SLD
|
|
myMessage = mLayer->saveSldStyle( myOutputFileName, defaultLoadedFlag );
|
|
}
|
|
else
|
|
{
|
|
myMessage = mLayer->saveNamedStyle( myOutputFileName, defaultLoadedFlag );
|
|
}
|
|
|
|
//reset if the default style was loaded OK only
|
|
if ( defaultLoadedFlag )
|
|
{
|
|
syncToLayer();
|
|
}
|
|
else
|
|
{
|
|
//let the user know what went wrong
|
|
QMessageBox::information( this, tr( "Saved Style" ), myMessage );
|
|
}
|
|
|
|
QFileInfo myFI( myOutputFileName );
|
|
QString myPath = myFI.path();
|
|
// Persist last used dir
|
|
myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::loadStyleMenuTriggered( QAction *action )
|
|
{
|
|
QMenu *menu = qobject_cast<QMenu *>( sender() );
|
|
if ( !menu )
|
|
return;
|
|
|
|
int index = mLoadStyleMenu->actions().indexOf( action );
|
|
|
|
if ( index == 0 ) //Load from filesystem
|
|
{
|
|
loadStyle_clicked();
|
|
}
|
|
else if ( index == 1 ) //Load from database
|
|
{
|
|
showListOfStylesFromDatabase();
|
|
}
|
|
|
|
}
|
|
|
|
void QgsVectorLayerProperties::aboutToShowStyleMenu()
|
|
{
|
|
// this should be unified with QgsRasterLayerProperties::aboutToShowStyleMenu()
|
|
|
|
QMenu *m = qobject_cast<QMenu *>( sender() );
|
|
if ( !m )
|
|
return;
|
|
|
|
// first get rid of previously added style manager actions (they are dynamic)
|
|
bool gotFirstSeparator = false;
|
|
QList<QAction *> actions = m->actions();
|
|
for ( int i = 0; i < actions.count(); ++i )
|
|
{
|
|
if ( actions[i]->isSeparator() )
|
|
{
|
|
if ( gotFirstSeparator )
|
|
{
|
|
// remove all actions after second separator (including it)
|
|
while ( actions.count() != i )
|
|
delete actions.takeAt( i );
|
|
break;
|
|
}
|
|
else
|
|
gotFirstSeparator = true;
|
|
}
|
|
}
|
|
|
|
// re-add style manager actions!
|
|
m->addSeparator();
|
|
QgsMapLayerStyleGuiUtils::instance()->addStyleManagerActions( m, mLayer );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::showListOfStylesFromDatabase()
|
|
{
|
|
QString errorMsg;
|
|
QStringList ids, names, descriptions;
|
|
|
|
//get the list of styles in the db
|
|
int sectionLimit = mLayer->listStylesInDatabase( ids, names, descriptions, errorMsg );
|
|
if ( !errorMsg.isNull() )
|
|
{
|
|
QMessageBox::warning( this, tr( "Error occurred retrieving styles from database" ), errorMsg );
|
|
return;
|
|
}
|
|
|
|
QgsLoadStyleFromDBDialog dialog;
|
|
dialog.setLayer( mLayer );
|
|
dialog.initializeLists( ids, names, descriptions, sectionLimit );
|
|
|
|
if ( dialog.exec() == QDialog::Accepted )
|
|
{
|
|
QString selectedStyleId = dialog.getSelectedStyleId();
|
|
|
|
QString qmlStyle = mLayer->getStyleFromDatabase( selectedStyleId, errorMsg );
|
|
if ( !errorMsg.isNull() )
|
|
{
|
|
QMessageBox::warning( this, tr( "Error occurred retrieving styles from database" ), errorMsg );
|
|
return;
|
|
}
|
|
|
|
QDomDocument myDocument( QStringLiteral( "qgis" ) );
|
|
myDocument.setContent( qmlStyle );
|
|
|
|
if ( mLayer->importNamedStyle( myDocument, errorMsg ) )
|
|
{
|
|
syncToLayer();
|
|
}
|
|
else
|
|
{
|
|
QMessageBox::warning( this, tr( "Error occurred retrieving styles from database" ),
|
|
tr( "The retrieved style is not a valid named style. Error message: %1" )
|
|
.arg( errorMsg ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mButtonAddJoin_clicked()
|
|
{
|
|
if ( !mLayer )
|
|
return;
|
|
|
|
QList<QgsMapLayer *> joinedLayers;
|
|
const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
|
|
joinedLayers.reserve( joins.size() );
|
|
for ( int i = 0; i < joins.size(); ++i )
|
|
{
|
|
joinedLayers.append( joins[i].joinLayer() );
|
|
}
|
|
|
|
QgsJoinDialog d( mLayer, joinedLayers );
|
|
if ( d.exec() == QDialog::Accepted )
|
|
{
|
|
QgsVectorLayerJoinInfo info = d.joinInfo();
|
|
//create attribute index if possible
|
|
if ( d.createAttributeIndex() )
|
|
{
|
|
QgsVectorLayer *joinLayer = info.joinLayer();
|
|
if ( joinLayer )
|
|
{
|
|
joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
|
|
}
|
|
}
|
|
mLayer->addJoin( info );
|
|
addJoinToTreeWidget( info );
|
|
setPbnQueryBuilderEnabled();
|
|
mFieldsPropertiesDialog->init();
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mButtonEditJoin_clicked()
|
|
{
|
|
QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
|
|
mJoinTreeWidget_itemDoubleClicked( currentJoinItem, 0 );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mJoinTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int )
|
|
{
|
|
if ( !mLayer || !item )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QList<QgsMapLayer *> joinedLayers;
|
|
QString joinLayerId = item->data( 0, Qt::UserRole ).toString();
|
|
const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
|
|
int j = -1;
|
|
for ( int i = 0; i < joins.size(); ++i )
|
|
{
|
|
QgsVectorLayer *joinLayer = joins[i].joinLayer();
|
|
if ( !joinLayer )
|
|
continue; // invalid join (unresolved join layer)
|
|
|
|
if ( joinLayer->id() == joinLayerId )
|
|
{
|
|
j = i;
|
|
}
|
|
else
|
|
{
|
|
// remove already joined layers from possible list to be displayed in dialog
|
|
joinedLayers.append( joinLayer );
|
|
}
|
|
}
|
|
if ( j == -1 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QgsJoinDialog d( mLayer, joinedLayers );
|
|
d.setJoinInfo( joins[j] );
|
|
|
|
if ( d.exec() == QDialog::Accepted )
|
|
{
|
|
QgsVectorLayerJoinInfo info = d.joinInfo();
|
|
|
|
// remove old join
|
|
mLayer->removeJoin( joinLayerId );
|
|
int idx = mJoinTreeWidget->indexOfTopLevelItem( item );
|
|
mJoinTreeWidget->takeTopLevelItem( idx );
|
|
|
|
// add the new edited
|
|
|
|
//create attribute index if possible
|
|
if ( d.createAttributeIndex() )
|
|
{
|
|
QgsVectorLayer *joinLayer = info.joinLayer();
|
|
if ( joinLayer )
|
|
{
|
|
joinLayer->dataProvider()->createAttributeIndex( joinLayer->fields().indexFromName( info.joinFieldName() ) );
|
|
}
|
|
}
|
|
mLayer->addJoin( info );
|
|
addJoinToTreeWidget( info, idx );
|
|
|
|
setPbnQueryBuilderEnabled();
|
|
mFieldsPropertiesDialog->init();
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorLayerJoinInfo &join, const int insertIndex )
|
|
{
|
|
QTreeWidgetItem *joinItem = new QTreeWidgetItem();
|
|
joinItem->setFlags( Qt::ItemIsEnabled );
|
|
|
|
QgsVectorLayer *joinLayer = join.joinLayer();
|
|
if ( !mLayer || !joinLayer )
|
|
{
|
|
return;
|
|
}
|
|
|
|
joinItem->setText( 0, QStringLiteral( "Join layer" ) );
|
|
if ( mLayer->auxiliaryLayer() && mLayer->auxiliaryLayer()->id() == join.joinLayerId() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
joinItem->setText( 1, joinLayer->name() );
|
|
|
|
QFont f = joinItem->font( 0 );
|
|
f.setBold( true );
|
|
joinItem->setFont( 0, f );
|
|
joinItem->setFont( 1, f );
|
|
|
|
joinItem->setData( 0, Qt::UserRole, join.joinLayerId() );
|
|
|
|
QTreeWidgetItem *childJoinField = new QTreeWidgetItem();
|
|
childJoinField->setText( 0, QStringLiteral( "Join field" ) );
|
|
childJoinField->setText( 1, join.joinFieldName() );
|
|
childJoinField->setFlags( Qt::ItemIsEnabled );
|
|
joinItem->addChild( childJoinField );
|
|
|
|
QTreeWidgetItem *childTargetField = new QTreeWidgetItem();
|
|
childTargetField->setText( 0, QStringLiteral( "Target field" ) );
|
|
childTargetField->setText( 1, join.targetFieldName() );
|
|
joinItem->addChild( childTargetField );
|
|
|
|
QTreeWidgetItem *childMemCache = new QTreeWidgetItem();
|
|
childMemCache->setText( 0, QStringLiteral( "Cache join layer in virtual memory" ) );
|
|
if ( join.isUsingMemoryCache() )
|
|
childMemCache->setText( 1, QChar( 0x2714 ) );
|
|
joinItem->addChild( childMemCache );
|
|
|
|
QTreeWidgetItem *childDynForm = new QTreeWidgetItem();
|
|
childDynForm->setText( 0, QStringLiteral( "Dynamic form" ) );
|
|
if ( join.isDynamicFormEnabled() )
|
|
childDynForm->setText( 1, QChar( 0x2714 ) );
|
|
joinItem->addChild( childDynForm );
|
|
|
|
QTreeWidgetItem *childEditable = new QTreeWidgetItem();
|
|
childEditable->setText( 0, QStringLiteral( "Editable join layer" ) );
|
|
if ( join.isEditable() )
|
|
childEditable->setText( 1, QChar( 0x2714 ) );
|
|
joinItem->addChild( childEditable );
|
|
|
|
QTreeWidgetItem *childUpsert = new QTreeWidgetItem();
|
|
childUpsert->setText( 0, QStringLiteral( "Upsert on edit" ) );
|
|
if ( join.hasUpsertOnEdit() )
|
|
childUpsert->setText( 1, QChar( 0x2714 ) );
|
|
joinItem->addChild( childUpsert );
|
|
|
|
QTreeWidgetItem *childCascade = new QTreeWidgetItem();
|
|
childCascade->setText( 0, QStringLiteral( "Delete cascade" ) );
|
|
if ( join.hasCascadedDelete() )
|
|
childCascade->setText( 1, QChar( 0x2714 ) );
|
|
joinItem->addChild( childCascade );
|
|
|
|
QTreeWidgetItem *childPrefix = new QTreeWidgetItem();
|
|
childPrefix->setText( 0, QStringLiteral( "Custom field name prefix" ) );
|
|
childPrefix->setText( 1, join.prefix() );
|
|
joinItem->addChild( childPrefix );
|
|
|
|
QTreeWidgetItem *childFields = new QTreeWidgetItem();
|
|
childFields->setText( 0, QStringLiteral( "Joined fields" ) );
|
|
const QStringList *list = join.joinFieldNamesSubset();
|
|
if ( list )
|
|
childFields->setText( 1, QStringLiteral( "%1" ).arg( list->count() ) );
|
|
else
|
|
childFields->setText( 1, tr( "all" ) );
|
|
joinItem->addChild( childFields );
|
|
|
|
if ( insertIndex >= 0 )
|
|
mJoinTreeWidget->insertTopLevelItem( insertIndex, joinItem );
|
|
else
|
|
mJoinTreeWidget->addTopLevelItem( joinItem );
|
|
|
|
mJoinTreeWidget->setCurrentItem( joinItem );
|
|
mJoinTreeWidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
|
|
}
|
|
|
|
QgsExpressionContext QgsVectorLayerProperties::createExpressionContext() const
|
|
{
|
|
return mContext;
|
|
}
|
|
|
|
void QgsVectorLayerProperties::openPanel( QgsPanelWidget *panel )
|
|
{
|
|
QDialog *dlg = new QDialog();
|
|
QString key = QStringLiteral( "/UI/paneldialog/%1" ).arg( panel->panelTitle() );
|
|
QgsSettings settings;
|
|
dlg->restoreGeometry( settings.value( key ).toByteArray() );
|
|
dlg->setWindowTitle( panel->panelTitle() );
|
|
dlg->setLayout( new QVBoxLayout() );
|
|
dlg->layout()->addWidget( panel );
|
|
QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok );
|
|
connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
|
|
dlg->layout()->addWidget( buttonBox );
|
|
dlg->exec();
|
|
settings.setValue( key, dlg->saveGeometry() );
|
|
panel->acceptPanel();
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mButtonRemoveJoin_clicked()
|
|
{
|
|
QTreeWidgetItem *currentJoinItem = mJoinTreeWidget->currentItem();
|
|
if ( !mLayer || !currentJoinItem )
|
|
{
|
|
return;
|
|
}
|
|
|
|
mLayer->removeJoin( currentJoinItem->data( 0, Qt::UserRole ).toString() );
|
|
mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
|
|
setPbnQueryBuilderEnabled();
|
|
mFieldsPropertiesDialog->init();
|
|
}
|
|
|
|
|
|
void QgsVectorLayerProperties::updateSymbologyPage()
|
|
{
|
|
|
|
//find out the type of renderer in the vectorlayer, create a dialog with these settings and add it to the form
|
|
delete mRendererDialog;
|
|
mRendererDialog = nullptr;
|
|
|
|
if ( mLayer->renderer() )
|
|
{
|
|
mRendererDialog = new QgsRendererPropertiesDialog( mLayer, QgsStyle::defaultStyle(), true, this );
|
|
mRendererDialog->setDockMode( false );
|
|
mRendererDialog->setMapCanvas( QgisApp::instance()->mapCanvas() );
|
|
connect( mRendererDialog, &QgsRendererPropertiesDialog::showPanel, this, &QgsVectorLayerProperties::openPanel );
|
|
connect( mRendererDialog, &QgsRendererPropertiesDialog::layerVariablesChanged, this, &QgsVectorLayerProperties::updateVariableEditor );
|
|
|
|
// display the menu to choose the output format (fix #5136)
|
|
mActionSaveStyleAs->setText( tr( "Save Style" ) );
|
|
mActionSaveStyleAs->setMenu( mSaveAsMenu );
|
|
disconnect( mActionSaveStyleAs, &QAction::triggered, this, &QgsVectorLayerProperties::saveStyleAs_clicked );
|
|
}
|
|
else
|
|
{
|
|
mOptsPage_Style->setEnabled( false ); // hide symbology item
|
|
}
|
|
|
|
if ( mRendererDialog )
|
|
{
|
|
mRendererDialog->layout()->setMargin( 0 );
|
|
widgetStackRenderers->addWidget( mRendererDialog );
|
|
widgetStackRenderers->setCurrentWidget( mRendererDialog );
|
|
widgetStackRenderers->currentWidget()->layout()->setMargin( 0 );
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::setPbnQueryBuilderEnabled()
|
|
{
|
|
pbnQueryBuilder->setEnabled( mLayer &&
|
|
mLayer->dataProvider() &&
|
|
mLayer->dataProvider()->supportsSubsetString() &&
|
|
!mLayer->isEditable() );
|
|
|
|
if ( mLayer && mLayer->isEditable() )
|
|
{
|
|
pbnQueryBuilder->setToolTip( tr( "Stop editing mode to enable this." ) );
|
|
}
|
|
|
|
}
|
|
|
|
void QgsVectorLayerProperties::pbnUpdateExtents_clicked()
|
|
{
|
|
mLayer->updateExtents( true ); // force update whatever options activated
|
|
mMetadataFilled = false;
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mOptionsStackedWidget_CurrentChanged( int indx )
|
|
{
|
|
if ( indx != mOptStackedWidget->indexOf( mOptsPage_Information ) || mMetadataFilled )
|
|
return;
|
|
|
|
//set the metadata contents (which can be expensive)
|
|
teMetadataViewer->clear();
|
|
teMetadataViewer->setHtml( htmlMetadata() );
|
|
mMetadataFilled = true;
|
|
}
|
|
|
|
void QgsVectorLayerProperties::mSimplifyDrawingGroupBox_toggled( bool checked )
|
|
{
|
|
if ( !( mLayer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) )
|
|
{
|
|
mSimplifyDrawingAtProvider->setEnabled( false );
|
|
}
|
|
else
|
|
{
|
|
mSimplifyDrawingAtProvider->setEnabled( checked );
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::updateVariableEditor()
|
|
{
|
|
QgsExpressionContext context;
|
|
mVariableEditor->setContext( &context );
|
|
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
|
|
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
|
|
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
|
|
mVariableEditor->reloadContext();
|
|
mVariableEditor->setEditableScopeIndex( 2 );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::updateFieldsPropertiesDialog()
|
|
{
|
|
QgsEditFormConfig cfg = mLayer->editFormConfig();
|
|
mFieldsPropertiesDialog->setEditFormInit( cfg.uiForm(), cfg.initFunction(), cfg.initCode(), cfg.initFilePath(), cfg.initCodeSource() );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::showHelp()
|
|
{
|
|
QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html" ) );
|
|
}
|
|
|
|
void QgsVectorLayerProperties::updateAuxiliaryStoragePage( bool reset )
|
|
{
|
|
const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
|
|
|
|
if ( alayer )
|
|
{
|
|
// set widgets to enable state
|
|
mAuxiliaryStorageInformationGrpBox->setEnabled( true );
|
|
mAuxiliaryStorageFieldsGrpBox->setEnabled( true );
|
|
|
|
// update key
|
|
mAuxiliaryStorageKeyLineEdit->setText( alayer->joinInfo().targetFieldName() );
|
|
|
|
// update feature count
|
|
int features = alayer->featureCount();
|
|
mAuxiliaryStorageFeaturesLineEdit->setText( QString::number( features ) );
|
|
|
|
// update actions
|
|
mAuxiliaryLayerActionNew->setEnabled( false );
|
|
|
|
const QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
|
|
if ( alayer )
|
|
{
|
|
const int fields = alayer->auxiliaryFields().count();
|
|
mAuxiliaryStorageFieldsLineEdit->setText( QString::number( fields ) );
|
|
|
|
// add fields
|
|
mAuxiliaryStorageFieldsTree->clear();
|
|
Q_FOREACH ( const QgsAuxiliaryField &field, alayer->auxiliaryFields() )
|
|
{
|
|
const QgsPropertyDefinition prop = field.propertyDefinition();
|
|
QTreeWidgetItem *item = new QTreeWidgetItem();
|
|
|
|
if ( prop.origin() == QgsPropertyDefinition::Pal )
|
|
item->setText( 0, "Pal" );
|
|
else if ( prop.origin() == QgsPropertyDefinition::Diagram )
|
|
item->setText( 0, "Diagram" );
|
|
else
|
|
item->setText( 0, "Unknown" );
|
|
|
|
item->setText( 1, prop.name() );
|
|
item->setText( 2, field.typeName() );
|
|
|
|
mAuxiliaryStorageFieldsTree->addTopLevelItem( item );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mAuxiliaryStorageInformationGrpBox->setEnabled( false );
|
|
mAuxiliaryStorageFieldsGrpBox->setEnabled( false );
|
|
|
|
if ( mLayer->isSpatial() )
|
|
mAuxiliaryLayerActionNew->setEnabled( true );
|
|
|
|
mAuxiliaryStorageFieldsTree->clear();
|
|
mAuxiliaryStorageKeyLineEdit->setText( QString() );
|
|
mAuxiliaryStorageFieldsLineEdit->setText( QString() );
|
|
mAuxiliaryStorageFeaturesLineEdit->setText( QString() );
|
|
}
|
|
|
|
if ( reset && labelingDialog )
|
|
{
|
|
labelingDialog->resetSettings(); // update data defined buttons
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::onAuxiliaryLayerNew()
|
|
{
|
|
QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
|
|
|
|
if ( alayer || !mLayer->isSpatial() )
|
|
return;
|
|
|
|
QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
|
|
if ( dlg.exec() == QDialog::Accepted )
|
|
{
|
|
updateAuxiliaryStoragePage( true );
|
|
}
|
|
}
|
|
|
|
void QgsVectorLayerProperties::onAuxiliaryLayerClear()
|
|
{
|
|
QgsAuxiliaryLayer *alayer = mLayer->auxiliaryLayer();
|
|
|
|
if ( !alayer )
|
|
return;
|
|
|
|
const QString msg = tr( "Are you sure you want to clear auxiliary data for %1" ).arg( mLayer->name() );
|
|
QMessageBox::StandardButton reply;
|
|
reply = QMessageBox::question( this, "Clear auxiliary data", msg, QMessageBox::Yes | QMessageBox::No );
|
|
|
|
if ( reply == QMessageBox::Yes )
|
|
{
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
alayer->clear();
|
|
QApplication::restoreOverrideCursor();
|
|
updateAuxiliaryStoragePage( true );
|
|
mLayer->triggerRepaint();
|
|
}
|
|
}
|