QGIS API Documentation 3.43.0-Master (e01d6d7c4c0)
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#include "moc_qgsprocessingtininputlayerswidget.cpp"
18#include "qgsproject.h"
20
22
23QgsProcessingTinInputLayersWidget::QgsProcessingTinInputLayersWidget( QgsProject *project )
24 : mInputLayersModel( project )
25{
26 setupUi( this );
27 mComboLayers->setFilters( Qgis::LayerFilter::VectorLayer );
28
29 connect( mComboLayers, &QgsMapLayerComboBox::layerChanged, this, &QgsProcessingTinInputLayersWidget::onLayerChanged );
30 connect( mButtonAdd, &QToolButton::clicked, this, &QgsProcessingTinInputLayersWidget::onCurrentLayerAdded );
31 connect( mButtonRemove, &QToolButton::clicked, this, &QgsProcessingTinInputLayersWidget::onLayersRemove );
32 connect( &mInputLayersModel, &QgsProcessingTinInputLayersModel::dataChanged, this, &QgsProcessingTinInputLayersWidget::changed );
33
34 onLayerChanged( mComboLayers->currentLayer() );
35
36 mTableView->setModel( &mInputLayersModel );
37 mTableView->setItemDelegateForColumn( 1, new QgsProcessingTinInputLayersDelegate( mTableView ) );
38}
39
40QVariant QgsProcessingTinInputLayersWidget::value() const
41{
42 const QList<QgsProcessingParameterTinInputLayers::InputLayer> &layers = mInputLayersModel.layers();
43 QVariantList list;
44
45 for ( const QgsProcessingParameterTinInputLayers::InputLayer &layer : layers )
46 {
47 QVariantMap layerMap;
48 layerMap[QStringLiteral( "source" )] = layer.source;
49 layerMap[QStringLiteral( "type" )] = static_cast<int>( layer.type );
50 layerMap[QStringLiteral( "attributeIndex" )] = layer.attributeIndex;
51 list.append( layerMap );
52 }
53
54 return list;
55}
56
57void QgsProcessingTinInputLayersWidget::setValue( const QVariant &value )
58{
59 mInputLayersModel.clear();
60 if ( !value.isValid() || value.userType() != QMetaType::Type::QVariantList )
61 return;
62
63 const QVariantList list = value.toList();
64
65 for ( const QVariant &layerValue : list )
66 {
67 if ( layerValue.userType() != QMetaType::Type::QVariantMap )
68 continue;
69 const QVariantMap layerMap = layerValue.toMap();
71 layer.source = layerMap.value( QStringLiteral( "source" ) ).toString();
72 layer.type = static_cast<Qgis::ProcessingTinInputLayerType>( layerMap.value( QStringLiteral( "type" ) ).toInt() );
73 layer.attributeIndex = layerMap.value( QStringLiteral( "attributeIndex" ) ).toInt();
74 mInputLayersModel.addLayer( layer );
75 }
76
77 emit changed();
78}
79
80void QgsProcessingTinInputLayersWidget::setProject( QgsProject *project )
81{
82 mInputLayersModel.setProject( project );
83}
84
85void QgsProcessingTinInputLayersWidget::onLayerChanged( QgsMapLayer *layer )
86{
87 QgsVectorLayer *newLayer = qobject_cast<QgsVectorLayer *>( layer );
88
89 if ( !newLayer || !newLayer->isValid() )
90 return;
91
92 QgsVectorDataProvider *provider = newLayer->dataProvider();
93
94 if ( !provider )
95 return;
96
97 mComboFields->setLayer( newLayer );
98 mComboFields->setCurrentIndex( 0 );
99 mCheckBoxUseZCoordinate->setEnabled( QgsWkbTypes::hasZ( provider->wkbType() ) );
100}
101
102void QgsProcessingTinInputLayersWidget::onCurrentLayerAdded()
103{
104 QgsVectorLayer *currentLayer = qobject_cast<QgsVectorLayer *>( mComboLayers->currentLayer() );
105 if ( !currentLayer )
106 return;
108 layer.source = mComboLayers->currentLayer()->id();
109
110 switch ( currentLayer->geometryType() )
111 {
114 break;
118 break;
121 return;
122 break;
123 }
124 if ( mCheckBoxUseZCoordinate->isChecked() && mCheckBoxUseZCoordinate->isEnabled() )
125 layer.attributeIndex = -1;
126 else
127 layer.attributeIndex = mComboFields->currentIndex();
128
129 mInputLayersModel.addLayer( layer );
130
131 emit changed();
132}
133
134void QgsProcessingTinInputLayersWidget::QgsProcessingTinInputLayersWidget::onLayersRemove()
135{
136 mInputLayersModel.removeLayer( mTableView->selectionModel()->currentIndex().row() );
137
138 emit changed();
139}
140
141QgsProcessingTinInputLayersModel::QgsProcessingTinInputLayersModel( QgsProject *project )
142 : mProject( project )
143{}
144
145int QgsProcessingTinInputLayersModel::rowCount( const QModelIndex &parent ) const
146{
147 Q_UNUSED( parent );
148 return mInputLayers.count();
149}
150
151int QgsProcessingTinInputLayersModel::columnCount( const QModelIndex &parent ) const
152{
153 Q_UNUSED( parent );
154 return 3;
155}
156
157QVariant QgsProcessingTinInputLayersModel::data( const QModelIndex &index, int role ) const
158{
159 if ( !index.isValid() )
160 return QVariant();
161
162 if ( index.row() >= mInputLayers.count() )
163 return QVariant();
164
165 switch ( role )
166 {
167 case Qt::DisplayRole:
168 {
169 QgsVectorLayer *layer = QgsProject::instance()->mapLayer<QgsVectorLayer *>( mInputLayers.at( index.row() ).source );
170 switch ( index.column() )
171 {
172 case 0:
173 if ( layer )
174 return layer->name();
175 else
176 return QVariant();
177 break;
178 case 1:
179 switch ( mInputLayers.at( index.row() ).type )
180 {
182 return tr( "Vertices" );
183 break;
185 return tr( "Break Lines" );
186 break;
187 default:
188 return QString();
189 break;
190 }
191 break;
192 case 2:
193 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
194 if ( attributeindex < 0 )
195 return tr( "Z coordinate" );
196 else
197 {
198 if ( attributeindex < layer->fields().count() )
199 return layer->fields().at( attributeindex ).name();
200 else
201 return tr( "Invalid field" );
202 }
203 break;
204 }
205 }
206 break;
207 case Qt::ForegroundRole:
208 if ( index.column() == 2 )
209 {
210 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
211 if ( attributeindex < 0 )
212 return QColor( Qt::darkGray );
213 }
214 break;
215 case Qt::FontRole:
216 if ( index.column() == 2 )
217 {
218 const int attributeindex = mInputLayers.at( index.row() ).attributeIndex;
219 if ( attributeindex < 0 )
220 {
221 QFont font;
222 font.setItalic( true );
223 return font;
224 }
225 }
226 break;
227 case Type:
228 if ( index.column() == 1 )
229 return static_cast<int>( mInputLayers.at( index.row() ).type );
230 break;
231 default:
232 break;
233 }
234 return QVariant();
235}
236
237bool QgsProcessingTinInputLayersModel::setData( const QModelIndex &index, const QVariant &value, int role )
238{
239 if ( index.column() == 1 && role == Qt::EditRole )
240 {
241 mInputLayers[index.row()].type = static_cast<Qgis::ProcessingTinInputLayerType>( value.toInt() );
242 emit dataChanged( QAbstractTableModel::index( index.row(), 1 ), QAbstractTableModel::index( index.row(), 1 ) );
243 return true;
244 }
245 return false;
246}
247
248Qt::ItemFlags QgsProcessingTinInputLayersModel::flags( const QModelIndex &index ) const
249{
250 if ( !index.isValid() )
251 return Qt::NoItemFlags;
252
253 if ( index.column() == 1 )
254 return QAbstractTableModel::flags( index ) | Qt::ItemIsEditable;
255
256 return QAbstractTableModel::flags( index );
257}
258
259QVariant QgsProcessingTinInputLayersModel::headerData( int section, Qt::Orientation orientation, int role ) const
260{
261 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
262 {
263 switch ( section )
264 {
265 case 0:
266 return tr( "Vector Layer" );
267 break;
268 case 1:
269 return tr( "Type" );
270 break;
271 case 2:
272 return tr( "Z Value Attribute" );
273 break;
274 default:
275 return QVariant();
276 break;
277 }
278 }
279
280 return QVariant();
281}
282
283void QgsProcessingTinInputLayersModel::addLayer( QgsProcessingParameterTinInputLayers::InputLayer &layer )
284{
285 beginInsertRows( QModelIndex(), mInputLayers.count() - 1, mInputLayers.count() - 1 );
286 mInputLayers.append( layer );
287 endInsertRows();
288}
289
290void QgsProcessingTinInputLayersModel::removeLayer( int index )
291{
292 if ( index < 0 || index >= mInputLayers.count() )
293 return;
294 beginRemoveRows( QModelIndex(), index, index );
295 mInputLayers.removeAt( index );
296 endRemoveRows();
297}
298
299void QgsProcessingTinInputLayersModel::clear()
300{
301 mInputLayers.clear();
302}
303
304QList<QgsProcessingParameterTinInputLayers::InputLayer> QgsProcessingTinInputLayersModel::layers() const
305{
306 return mInputLayers;
307}
308
309void QgsProcessingTinInputLayersModel::setProject( QgsProject *project )
310{
311 mProject = project;
312}
313
314QWidget *QgsProcessingTinInputLayersDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
315{
316 Q_UNUSED( option );
317 Q_UNUSED( index );
318 QComboBox *comboType = new QComboBox( parent );
319 comboType->addItem( tr( "Vertices" ), static_cast<int>( Qgis::ProcessingTinInputLayerType::Vertices ) );
320 comboType->addItem( tr( "Break Lines" ), static_cast<int>( Qgis::ProcessingTinInputLayerType::BreakLines ) );
321 return comboType;
322}
323
324void QgsProcessingTinInputLayersDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
325{
326 QComboBox *comboType = qobject_cast<QComboBox *>( editor );
327 Q_ASSERT( comboType );
328 const Qgis::ProcessingTinInputLayerType type = static_cast<Qgis::ProcessingTinInputLayerType>( index.data( QgsProcessingTinInputLayersModel::Type ).toInt() );
329 const int comboIndex = comboType->findData( static_cast<int>( type ) );
330 if ( comboIndex >= 0 )
331 comboType->setCurrentIndex( comboIndex );
332 else
333 comboType->setCurrentIndex( 0 );
334}
335
336void QgsProcessingTinInputLayersDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
337{
338 QComboBox *comboType = qobject_cast<QComboBox *>( editor );
339 Q_ASSERT( comboType );
340 model->setData( index, comboType->currentData(), Qt::EditRole );
341}
342
343QgsProcessingTinInputLayersWidgetWrapper::QgsProcessingTinInputLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type, QWidget *parent )
344 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
345{}
346
347QString QgsProcessingTinInputLayersWidgetWrapper::parameterType() const
348{
349 return QStringLiteral( "tininputlayers" );
350}
351
352QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingTinInputLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, Qgis::ProcessingMode type )
353{
354 return new QgsProcessingTinInputLayersWidgetWrapper( parameter, type );
355}
356
357QWidget *QgsProcessingTinInputLayersWidgetWrapper::createWidget()
358{
359 mWidget = new QgsProcessingTinInputLayersWidget( widgetContext().project() );
360 connect( mWidget, &QgsProcessingTinInputLayersWidget::changed, this, [=] {
361 emit widgetValueHasChanged( this );
362 } );
363
364 return mWidget;
365}
366
367void QgsProcessingTinInputLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
368{
369 if ( !mWidget )
370 return;
371 mWidget->setValue( value );
372 mWidget->setProject( context.project() );
373}
374
375QVariant QgsProcessingTinInputLayersWidgetWrapper::widgetValue() const
376{
377 if ( mWidget )
378 return mWidget->value();
379 else
380 return QVariant();
381}
382
ProcessingTinInputLayerType
Defines the type of input layer for a Processing TIN input.
Definition qgis.h:3744
@ BreakLines
Input that adds vertices and break lines.
@ Vertices
Input that adds only vertices.
ProcessingMode
Types of modes which Processing widgets can be created for.
Definition qgis.h:3537
@ Polygon
Polygons.
@ Unknown
Unknown types.
@ Null
No geometry.
A widget wrapper for Processing parameter value widgets.
QString name
Definition qgsfield.h:62
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:77
QString name
Definition qgsmaplayer.h:81
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:107
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.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
static 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.