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