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