QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
qgsprocessingtininputlayerswidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingtininputlayerswidget.cpp
3 ---------------------
4 Date : August 2020
5 Copyright : (C) 2020 by Vincent Cloarec
6 Email : vcloarec at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
19#include "qgsproject.h"
20
21#include <QString>
22
23#include "moc_qgsprocessingtininputlayerswidget.cpp"
24
25using namespace Qt::StringLiterals;
26
28
29QgsProcessingTinInputLayersWidget::QgsProcessingTinInputLayersWidget( QgsProject *project )
30 : mInputLayersModel( project )
31{
32 setupUi( this );
33 mComboLayers->setFilters( Qgis::LayerFilter::VectorLayer );
34
35 connect( mComboLayers, &QgsMapLayerComboBox::layerChanged, this, &QgsProcessingTinInputLayersWidget::onLayerChanged );
36 connect( mButtonAdd, &QToolButton::clicked, this, &QgsProcessingTinInputLayersWidget::onCurrentLayerAdded );
37 connect( mButtonRemove, &QToolButton::clicked, this, &QgsProcessingTinInputLayersWidget::onLayersRemove );
38 connect( &mInputLayersModel, &QgsProcessingTinInputLayersModel::dataChanged, this, &QgsProcessingTinInputLayersWidget::changed );
39
40 onLayerChanged( mComboLayers->currentLayer() );
41
42 mTableView->setModel( &mInputLayersModel );
43 mTableView->setItemDelegateForColumn( 1, new QgsProcessingTinInputLayersDelegate( mTableView ) );
44}
45
46QVariant QgsProcessingTinInputLayersWidget::value() const
47{
48 const QList<QgsProcessingParameterTinInputLayers::InputLayer> &layers = mInputLayersModel.layers();
49 QVariantList list;
50
51 for ( const QgsProcessingParameterTinInputLayers::InputLayer &layer : layers )
52 {
53 QVariantMap layerMap;
54 layerMap[u"source"_s] = layer.source;
55 layerMap[u"type"_s] = static_cast<int>( layer.type );
56 layerMap[u"attributeIndex"_s] = layer.attributeIndex;
57 list.append( layerMap );
58 }
59
60 return list;
61}
62
63void QgsProcessingTinInputLayersWidget::setValue( const QVariant &value )
64{
65 mInputLayersModel.clear();
66 if ( !value.isValid() || value.userType() != QMetaType::Type::QVariantList )
67 return;
68
69 const QVariantList list = value.toList();
70
71 for ( const QVariant &layerValue : list )
72 {
73 if ( layerValue.userType() != QMetaType::Type::QVariantMap )
74 continue;
75 const QVariantMap layerMap = layerValue.toMap();
77 layer.source = layerMap.value( u"source"_s ).toString();
78 layer.type = static_cast<Qgis::ProcessingTinInputLayerType>( layerMap.value( u"type"_s ).toInt() );
79 layer.attributeIndex = layerMap.value( u"attributeIndex"_s ).toInt();
80 mInputLayersModel.addLayer( layer );
81 }
82
83 emit changed();
84}
85
86void QgsProcessingTinInputLayersWidget::setProject( QgsProject *project )
87{
88 mInputLayersModel.setProject( project );
89}
90
91void QgsProcessingTinInputLayersWidget::onLayerChanged( QgsMapLayer *layer )
92{
93 QgsVectorLayer *newLayer = qobject_cast<QgsVectorLayer *>( layer );
94
95 if ( !newLayer || !newLayer->isValid() )
96 return;
97
98 QgsVectorDataProvider *provider = newLayer->dataProvider();
99
100 if ( !provider )
101 return;
102
103 mComboFields->setLayer( newLayer );
104 mComboFields->setCurrentIndex( 0 );
105 mCheckBoxUseZCoordinate->setEnabled( QgsWkbTypes::hasZ( provider->wkbType() ) );
106}
107
108void QgsProcessingTinInputLayersWidget::onCurrentLayerAdded()
109{
110 QgsVectorLayer *currentLayer = qobject_cast<QgsVectorLayer *>( mComboLayers->currentLayer() );
111 if ( !currentLayer )
112 return;
114 layer.source = mComboLayers->currentLayer()->id();
115
116 switch ( currentLayer->geometryType() )
117 {
120 break;
124 break;
127 return;
128 break;
129 }
130 if ( mCheckBoxUseZCoordinate->isChecked() && mCheckBoxUseZCoordinate->isEnabled() )
131 layer.attributeIndex = -1;
132 else
133 layer.attributeIndex = mComboFields->currentIndex();
134
135 mInputLayersModel.addLayer( layer );
136
137 emit changed();
138}
139
140void QgsProcessingTinInputLayersWidget::QgsProcessingTinInputLayersWidget::onLayersRemove()
141{
142 mInputLayersModel.removeLayer( mTableView->selectionModel()->currentIndex().row() );
143
144 emit changed();
145}
146
147QgsProcessingTinInputLayersModel::QgsProcessingTinInputLayersModel( QgsProject *project )
148 : mProject( project )
149{}
150
151int QgsProcessingTinInputLayersModel::rowCount( const QModelIndex &parent ) const
152{
153 Q_UNUSED( parent );
154 return mInputLayers.count();
155}
156
157int QgsProcessingTinInputLayersModel::columnCount( const QModelIndex &parent ) const
158{
159 Q_UNUSED( parent );
160 return 3;
161}
162
163QVariant QgsProcessingTinInputLayersModel::data( const QModelIndex &index, int role ) const
164{
165 if ( !index.isValid() )
166 return QVariant();
167
168 if ( index.row() >= mInputLayers.count() )
169 return QVariant();
170
171 switch ( role )
172 {
173 case Qt::DisplayRole:
174 {
175 QgsVectorLayer *layer = QgsProject::instance()->mapLayer<QgsVectorLayer *>( mInputLayers.at( index.row() ).source );
176 switch ( index.column() )
177 {
178 case 0:
179 if ( layer )
180 return layer->name();
181 else
182 return QVariant();
183 break;
184 case 1:
185 switch ( mInputLayers.at( index.row() ).type )
186 {
188 return tr( "Vertices" );
189 break;
191 return tr( "Break Lines" );
192 break;
193 default:
194 return QString();
195 break;
196 }
197 break;
198 case 2:
199 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
200 if ( attributeindex < 0 )
201 return tr( "Z coordinate" );
202 else
203 {
204 if ( attributeindex < layer->fields().count() )
205 return layer->fields().at( attributeindex ).name();
206 else
207 return tr( "Invalid field" );
208 }
209 break;
210 }
211 }
212 break;
213 case Qt::ForegroundRole:
214 if ( index.column() == 2 )
215 {
216 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
217 if ( attributeindex < 0 )
218 return QColor( Qt::darkGray );
219 }
220 break;
221 case Qt::FontRole:
222 if ( index.column() == 2 )
223 {
224 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
225 if ( attributeindex < 0 )
226 {
227 QFont font;
228 font.setItalic( true );
229 return font;
230 }
231 }
232 break;
233 case Type:
234 if ( index.column() == 1 )
235 return static_cast<int>( mInputLayers.at( index.row() ).type );
236 break;
237 default:
238 break;
239 }
240 return QVariant();
241}
242
243bool QgsProcessingTinInputLayersModel::setData( const QModelIndex &index, const QVariant &value, int role )
244{
245 if ( index.column() == 1 && role == Qt::EditRole )
246 {
247 mInputLayers[index.row()].type = static_cast<Qgis::ProcessingTinInputLayerType>( value.toInt() );
248 emit dataChanged( QAbstractTableModel::index( index.row(), 1 ), QAbstractTableModel::index( index.row(), 1 ) );
249 return true;
250 }
251 return false;
252}
253
254Qt::ItemFlags QgsProcessingTinInputLayersModel::flags( const QModelIndex &index ) const
255{
256 if ( !index.isValid() )
257 return Qt::NoItemFlags;
258
259 if ( index.column() == 1 )
260 return QAbstractTableModel::flags( index ) | Qt::ItemIsEditable;
261
262 return QAbstractTableModel::flags( index );
263}
264
265QVariant QgsProcessingTinInputLayersModel::headerData( int section, Qt::Orientation orientation, int role ) const
266{
267 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
268 {
269 switch ( section )
270 {
271 case 0:
272 return tr( "Vector Layer" );
273 break;
274 case 1:
275 return tr( "Type" );
276 break;
277 case 2:
278 return tr( "Z Value Attribute" );
279 break;
280 default:
281 return QVariant();
282 break;
283 }
284 }
285
286 return QVariant();
287}
288
289void QgsProcessingTinInputLayersModel::addLayer( QgsProcessingParameterTinInputLayers::InputLayer &layer )
290{
291 beginInsertRows( QModelIndex(), mInputLayers.count() - 1, mInputLayers.count() - 1 );
292 mInputLayers.append( layer );
293 endInsertRows();
294}
295
296void QgsProcessingTinInputLayersModel::removeLayer( int index )
297{
298 if ( index < 0 || index >= mInputLayers.count() )
299 return;
300 beginRemoveRows( QModelIndex(), index, index );
301 mInputLayers.removeAt( index );
302 endRemoveRows();
303}
304
305void QgsProcessingTinInputLayersModel::clear()
306{
307 mInputLayers.clear();
308}
309
310QList<QgsProcessingParameterTinInputLayers::InputLayer> QgsProcessingTinInputLayersModel::layers() const
311{
312 return mInputLayers;
313}
314
315void QgsProcessingTinInputLayersModel::setProject( QgsProject *project )
316{
317 mProject = project;
318}
319
320QWidget *QgsProcessingTinInputLayersDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
321{
322 Q_UNUSED( option );
323 Q_UNUSED( index );
324 QComboBox *comboType = new QComboBox( parent );
325 comboType->addItem( tr( "Vertices" ), static_cast<int>( Qgis::ProcessingTinInputLayerType::Vertices ) );
326 comboType->addItem( tr( "Break Lines" ), static_cast<int>( Qgis::ProcessingTinInputLayerType::BreakLines ) );
327 return comboType;
328}
329
330void QgsProcessingTinInputLayersDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
331{
332 QComboBox *comboType = qobject_cast<QComboBox *>( editor );
333 Q_ASSERT( comboType );
334 const Qgis::ProcessingTinInputLayerType type = static_cast<Qgis::ProcessingTinInputLayerType>( index.data( QgsProcessingTinInputLayersModel::Type ).toInt() );
335 const int comboIndex = comboType->findData( static_cast<int>( type ) );
336 if ( comboIndex >= 0 )
337 comboType->setCurrentIndex( comboIndex );
338 else
339 comboType->setCurrentIndex( 0 );
340}
341
342void QgsProcessingTinInputLayersDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
343{
344 QComboBox *comboType = qobject_cast<QComboBox *>( editor );
345 Q_ASSERT( comboType );
346 model->setData( index, comboType->currentData(), Qt::EditRole );
347}
348
349QgsProcessingTinInputLayersWidgetWrapper::QgsProcessingTinInputLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type, QWidget *parent )
350 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
351{}
352
353QString QgsProcessingTinInputLayersWidgetWrapper::parameterType() const
354{
355 return u"tininputlayers"_s;
356}
357
358QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingTinInputLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type )
359{
360 return new QgsProcessingTinInputLayersWidgetWrapper( parameter, type );
361}
362
363QWidget *QgsProcessingTinInputLayersWidgetWrapper::createWidget()
364{
365 mWidget = new QgsProcessingTinInputLayersWidget( widgetContext().project() );
366 connect( mWidget, &QgsProcessingTinInputLayersWidget::changed, this, [this] {
367 emit widgetValueHasChanged( this );
368 } );
369
370 return mWidget;
371}
372
373void QgsProcessingTinInputLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
374{
375 if ( !mWidget )
376 return;
377 mWidget->setValue( value );
378 mWidget->setProject( context.project() );
379}
380
381QVariant QgsProcessingTinInputLayersWidgetWrapper::widgetValue() const
382{
383 if ( mWidget )
384 return mWidget->value();
385 else
386 return QVariant();
387}
388
ProcessingTinInputLayerType
Defines the type of input layer for a Processing TIN input.
Definition qgis.h:3949
@ BreakLines
Input that adds vertices and break lines.
Definition qgis.h:3952
@ Vertices
Input that adds only vertices.
Definition qgis.h:3950
ProcessingMode
Types of modes which Processing widgets can be created for.
Definition qgis.h:3742
@ 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
A widget wrapper for Processing parameter value widgets.
QString name
Definition qgsfield.h:65
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QString name
Definition qgsmaplayer.h:87
Contains information about the context in which a processing algorithm is executed.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Base class for the definition of processing parameters.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:113
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.
Base class for vector data providers.
Qgis::WkbType wkbType() const override=0
Returns the geometry type which is returned by this layer.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
Used to store input layer Id and other associated parameters.
Qgis::ProcessingTinInputLayerType type
The source of the input layer.