QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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( QgsMapLayerProxyModel::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" )] = 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<QgsProcessingParameterTinInputLayers::Type>( 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 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<QgsProcessingParameterTinInputLayers::Type>( 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" ), QgsProcessingParameterTinInputLayers::Vertices );
319 comboType->addItem( tr( "Break Lines" ), QgsProcessingParameterTinInputLayers::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<QgsProcessingParameterTinInputLayers::Type>( index.data( QgsProcessingTinInputLayersModel::Type ).toInt() );
329 const int comboIndex = comboType->findData( 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
A widget wrapper for Processing parameter value widgets.
QString name
Definition: qgsfield.h:60
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:73
QString name
Definition: qgsmaplayer.h:76
bool isValid
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.
WidgetType
Types of dialogs which Processing widgets can be created for.
Base class for the definition of processing parameters.
@ BreakLines
Input that adds vertices and break lines.
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:104
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
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.
QgsWkbTypes::Type 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.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
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.
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
Used to store input layer Id and other associated parameters.