QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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#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 );
329 static_cast<Qgis::ProcessingTinInputLayerType>( index.data( QgsProcessingTinInputLayersModel::Type ).toInt() );
330 const int comboIndex = comboType->findData( static_cast< int >( type ) );
331 if ( comboIndex >= 0 )
332 comboType->setCurrentIndex( comboIndex );
333 else
334 comboType->setCurrentIndex( 0 );
335}
336
337void QgsProcessingTinInputLayersDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
338{
339 QComboBox *comboType = qobject_cast<QComboBox *>( editor );
340 Q_ASSERT( comboType );
341 model->setData( index, comboType->currentData(), Qt::EditRole );
342}
343
344QgsProcessingTinInputLayersWidgetWrapper::QgsProcessingTinInputLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent ):
345 QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
346{}
347
348QString QgsProcessingTinInputLayersWidgetWrapper::parameterType() const
349{
350 return QStringLiteral( "tininputlayers" );
351}
352
353QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingTinInputLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
354{
355 return new QgsProcessingTinInputLayersWidgetWrapper( parameter, type );
356}
357
358QStringList QgsProcessingTinInputLayersWidgetWrapper::compatibleParameterTypes() const
359{
360 return QStringList()
362}
363
364QStringList QgsProcessingTinInputLayersWidgetWrapper::compatibleOutputTypes() const {return QStringList();}
365
366QWidget *QgsProcessingTinInputLayersWidgetWrapper::createWidget()
367{
368 mWidget = new QgsProcessingTinInputLayersWidget( widgetContext().project() );
369 connect( mWidget, &QgsProcessingTinInputLayersWidget::changed, this, [ = ]
370 {
371 emit widgetValueHasChanged( this );
372 } );
373
374 return mWidget;
375}
376
377void QgsProcessingTinInputLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
378{
379 if ( !mWidget )
380 return;
381 mWidget->setValue( value );
382 mWidget->setProject( context.project() );
383}
384
385QVariant QgsProcessingTinInputLayersWidgetWrapper::widgetValue() const
386{
387 if ( mWidget )
388 return mWidget->value();
389 else
390 return QVariant();
391}
392
ProcessingTinInputLayerType
Defines the type of input layer for a Processing TIN input.
Definition qgis.h:3600
@ 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).
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QString name
Definition qgsmaplayer.h:80
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.
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.
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.