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