1 /***************************************************************************
2 qgsvectorlayerdigitizingproperties.cpp
3 --------------------------------------
4 copyright : (C) 2018 by Matthias Kuhn
5 email : matthias@opengis.ch
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "qgsvectorlayerdigitizingproperties.h"
18 #include "qgsanalysis.h"
19 #include "qgscollapsiblegroupbox.h"
20 #include "qgsdoublespinbox.h"
21 #include "qgsgeometrycheckfactory.h"
22 #include "qgsgeometrycheckregistry.h"
23 #include "qgsgeometrycheck.h"
24 #include "qgsgeometryoptions.h"
25 #include "qgsmaplayercombobox.h"
26 #include "qgsproject.h"
27
28 #include <QFormLayout>
29
QgsVectorLayerDigitizingPropertiesPage(QgsMapLayer * layer,QgsMapCanvas * canvas,QWidget * parent)30 QgsVectorLayerDigitizingPropertiesPage::QgsVectorLayerDigitizingPropertiesPage( QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent )
31 : QgsMapLayerConfigWidget( layer, canvas, parent )
32 {
33 setupUi( this );
34
35 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayer );
36
37 if ( vlayer && vlayer->isSpatial() )
38 {
39 mRemoveDuplicateNodesCheckbox->setEnabled( true );
40 mGeometryPrecisionLineEdit->setEnabled( true );
41 mGeometryPrecisionLineEdit->setValidator( new QDoubleValidator( mGeometryPrecisionLineEdit ) );
42
43 const double precision( vlayer->geometryOptions()->geometryPrecision() );
44 const bool ok = true;
45 QString precisionStr( QLocale().toString( precision, ok ) );
46 if ( precision == 0.0 || ! ok )
47 precisionStr = QString();
48 mGeometryPrecisionLineEdit->setText( precisionStr );
49
50 mRemoveDuplicateNodesManuallyActivated = vlayer->geometryOptions()->removeDuplicateNodes();
51 mRemoveDuplicateNodesCheckbox->setChecked( mRemoveDuplicateNodesManuallyActivated );
52 if ( !precisionStr.isNull() )
53 mRemoveDuplicateNodesCheckbox->setEnabled( false );
54 connect( mGeometryPrecisionLineEdit, &QLineEdit::textChanged, this, [this]
55 {
56 if ( !mGeometryPrecisionLineEdit->text().isEmpty() )
57 {
58 if ( mRemoveDuplicateNodesCheckbox->isEnabled() )
59 mRemoveDuplicateNodesManuallyActivated = mRemoveDuplicateNodesCheckbox->isChecked();
60 mRemoveDuplicateNodesCheckbox->setEnabled( false );
61 mRemoveDuplicateNodesCheckbox->setChecked( true );
62 }
63 else
64 {
65 mRemoveDuplicateNodesCheckbox->setEnabled( true );
66 mRemoveDuplicateNodesCheckbox->setChecked( mRemoveDuplicateNodesManuallyActivated );
67 }
68 } );
69
70 mPrecisionUnitsLabel->setText( QStringLiteral( "[%1]" ).arg( QgsUnitTypes::toAbbreviatedString( vlayer->crs().mapUnits() ) ) );
71
72 QLayout *geometryCheckLayout = new QVBoxLayout();
73 const QList<QgsGeometryCheckFactory *> geometryCheckFactories = QgsAnalysis::instance()->geometryCheckRegistry()->geometryCheckFactories( vlayer, QgsGeometryCheck::FeatureNodeCheck, QgsGeometryCheck::Flag::AvailableInValidation );
74 const QStringList activeChecks = vlayer->geometryOptions()->geometryChecks();
75 for ( const QgsGeometryCheckFactory *factory : geometryCheckFactories )
76 {
77 QCheckBox *cb = new QCheckBox( factory->description() );
78 cb->setChecked( activeChecks.contains( factory->id() ) );
79 mGeometryCheckFactoriesGroupBoxes.insert( cb, factory->id() );
80 geometryCheckLayout->addWidget( cb );
81 }
82 mGeometryValidationGroupBox->setLayout( geometryCheckLayout );
83 mGeometryValidationGroupBox->setVisible( !geometryCheckFactories.isEmpty() );
84
85 QLayout *topologyCheckLayout = new QVBoxLayout();
86 const QList<QgsGeometryCheckFactory *> topologyCheckFactories = QgsAnalysis::instance()->geometryCheckRegistry()->geometryCheckFactories( vlayer, QgsGeometryCheck::LayerCheck, QgsGeometryCheck::Flag::AvailableInValidation );
87
88 for ( const QgsGeometryCheckFactory *factory : topologyCheckFactories )
89 {
90 QCheckBox *cb = new QCheckBox( factory->description() );
91 cb->setChecked( activeChecks.contains( factory->id() ) );
92 mGeometryCheckFactoriesGroupBoxes.insert( cb, factory->id() );
93 topologyCheckLayout->addWidget( cb );
94 if ( factory->id() == QLatin1String( "QgsGeometryGapCheck" ) )
95 {
96 const QVariantMap gapCheckConfig = vlayer->geometryOptions()->checkConfiguration( QStringLiteral( "QgsGeometryGapCheck" ) );
97
98 mGapCheckAllowExceptionsActivatedCheckBox = new QgsCollapsibleGroupBox( tr( "Allowed Gaps" ) );
99 mGapCheckAllowExceptionsActivatedCheckBox->setCheckable( true );
100 mGapCheckAllowExceptionsActivatedCheckBox->setChecked( gapCheckConfig.value( QStringLiteral( "allowedGapsEnabled" ), false ).toBool() );
101 QGridLayout *layout = new QGridLayout();
102 mGapCheckAllowExceptionsActivatedCheckBox->setLayout( layout );
103 topologyCheckLayout->addWidget( mGapCheckAllowExceptionsActivatedCheckBox );
104 mGapCheckAllowExceptionsLayerComboBox = new QgsMapLayerComboBox();
105 mGapCheckAllowExceptionsLayerComboBox->setFilters( QgsMapLayerProxyModel::PolygonLayer );
106 mGapCheckAllowExceptionsLayerComboBox->setExceptedLayerList( QList<QgsMapLayer *> { vlayer } );
107 mGapCheckAllowExceptionsLayerComboBox->setLayer( QgsProject::instance()->mapLayer( gapCheckConfig.value( QStringLiteral( "allowedGapsLayer" ) ).toString() ) );
108 layout->addWidget( new QLabel( tr( "Layer" ) ), 0, 0 );
109 layout->addWidget( mGapCheckAllowExceptionsLayerComboBox, 0, 1 );
110 mGapCheckAllowExceptionsBufferSpinBox = new QgsDoubleSpinBox();
111 mGapCheckAllowExceptionsBufferSpinBox->setInputMethodHints( Qt::ImhFormattedNumbersOnly );
112 mGapCheckAllowExceptionsBufferSpinBox->setSuffix( QgsUnitTypes::toAbbreviatedString( vlayer->crs().mapUnits() ) );
113 mGapCheckAllowExceptionsBufferSpinBox->setValue( gapCheckConfig.value( QStringLiteral( "allowedGapsBuffer" ) ).toDouble() );
114 layout->addWidget( new QLabel( tr( "Buffer" ) ), 0, 2 );
115 layout->addWidget( mGapCheckAllowExceptionsBufferSpinBox, 0, 3 );
116 }
117 }
118 mTopologyChecksGroupBox->setLayout( topologyCheckLayout );
119 mTopologyChecksGroupBox->setVisible( !topologyCheckFactories.isEmpty() );
120 }
121 else
122 {
123 mRemoveDuplicateNodesCheckbox->setEnabled( false );
124 mGeometryPrecisionLineEdit->setEnabled( false );
125 mGeometryAutoFixesGroupBox->setEnabled( false );
126 }
127
128 setProperty( "helpPage", QStringLiteral( "working_with_vector/vector_properties.html#digitizing-properties" ) );
129 }
130
apply()131 void QgsVectorLayerDigitizingPropertiesPage::apply()
132 {
133 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayer );
134 if ( !vlayer )
135 {
136 return;
137 }
138
139 vlayer->geometryOptions()->setRemoveDuplicateNodes( mRemoveDuplicateNodesCheckbox->isChecked() );
140 bool ok = true;
141 double precision( QLocale().toDouble( mGeometryPrecisionLineEdit->text(), &ok ) );
142 if ( ! ok )
143 precision = 0.0;
144 vlayer->geometryOptions()->setGeometryPrecision( precision );
145
146 QStringList activeChecks;
147 QHash<QCheckBox *, QString>::const_iterator it;
148 for ( it = mGeometryCheckFactoriesGroupBoxes.constBegin(); it != mGeometryCheckFactoriesGroupBoxes.constEnd(); ++it )
149 {
150 if ( it.key()->isChecked() )
151 activeChecks << it.value();
152 }
153 vlayer->geometryOptions()->setGeometryChecks( activeChecks );
154
155 if ( mGapCheckAllowExceptionsActivatedCheckBox )
156 {
157 QVariantMap gapCheckConfig;
158 gapCheckConfig.insert( QStringLiteral( "allowedGapsEnabled" ), mGapCheckAllowExceptionsActivatedCheckBox->isChecked() );
159 QgsMapLayer *currentLayer = mGapCheckAllowExceptionsLayerComboBox->currentLayer();
160 gapCheckConfig.insert( QStringLiteral( "allowedGapsLayer" ), currentLayer ? currentLayer->id() : QString() );
161 gapCheckConfig.insert( QStringLiteral( "allowedGapsBuffer" ), mGapCheckAllowExceptionsBufferSpinBox->value() );
162
163 vlayer->geometryOptions()->setCheckConfiguration( QStringLiteral( "QgsGeometryGapCheck" ), gapCheckConfig );
164 }
165 }
166
167
QgsVectorLayerDigitizingPropertiesFactory(QObject * parent)168 QgsVectorLayerDigitizingPropertiesFactory::QgsVectorLayerDigitizingPropertiesFactory( QObject *parent )
169 : QObject( parent )
170 {
171 setIcon( QIcon( ":/images/themes/default/propertyicons/digitizing.svg" ) );
172 setTitle( tr( "Digitizing" ) );
173 }
174
createWidget(QgsMapLayer * layer,QgsMapCanvas * canvas,bool dockWidget,QWidget * parent) const175 QgsMapLayerConfigWidget *QgsVectorLayerDigitizingPropertiesFactory::createWidget( QgsMapLayer *layer, QgsMapCanvas *canvas, bool dockWidget, QWidget *parent ) const
176 {
177 Q_UNUSED( dockWidget )
178 return new QgsVectorLayerDigitizingPropertiesPage( layer, canvas, parent );
179 }
180
supportsLayer(QgsMapLayer * layer) const181 bool QgsVectorLayerDigitizingPropertiesFactory::supportsLayer( QgsMapLayer *layer ) const
182 {
183 return layer->type() == QgsMapLayerType::VectorLayer;
184 }
185