QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgsprocessingdxflayerswidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingdxflayerswidgetwrapper.cpp
3  ---------------------
4  Date : September 2020
5  Copyright : (C) 2020 by Alexander Bruy
6  Email : alexander dot bruy 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 
18 #include <QBoxLayout>
19 #include <QLineEdit>
20 #include <QMessageBox>
21 #include <QPushButton>
22 #include <QStandardItemModel>
23 #include <QToolButton>
24 
25 #include "qgspanelwidget.h"
27 #include "qgsprocessingoutputs.h"
29 
31 
32 //
33 // QgsProcessingDxfLayerDetailsWidget
34 //
35 
36 QgsProcessingDxfLayerDetailsWidget::QgsProcessingDxfLayerDetailsWidget( const QVariant &value, QgsProject *project )
37 {
38  setupUi( this );
39 
40  mFieldsComboBox->setAllowEmptyFieldName( true );
41 
42  mContext.setProject( project );
43 
44  const QgsDxfExport::DxfLayer layer = QgsProcessingParameterDxfLayers::variantMapAsLayer( value.toMap(), mContext );
45  mLayer = layer.layer();
46 
47  if ( !mLayer )
48  return;
49 
50  mFieldsComboBox->setLayer( mLayer );
51  mFieldsComboBox->setCurrentIndex( layer.layerOutputAttributeIndex() );
52 
53  connect( mFieldsComboBox, &QgsFieldComboBox::fieldChanged, this, &QgsPanelWidget::widgetChanged );
54 }
55 
56 QVariant QgsProcessingDxfLayerDetailsWidget::value() const
57 {
58  const int index = mLayer->fields().lookupField( mFieldsComboBox->currentField() );
59  const QgsDxfExport::DxfLayer layer( mLayer, index );
61 }
62 
63 
64 //
65 // QgsProcessingDxfLayersPanelWidget
66 //
67 
68 QgsProcessingDxfLayersPanelWidget::QgsProcessingDxfLayersPanelWidget(
69  const QVariant &value,
70  QgsProject *project,
71  QWidget *parent )
72  : QgsProcessingMultipleSelectionPanelWidget( QVariantList(), QVariantList(), parent )
73  , mProject( project )
74 {
75  connect( listView(), &QListView::doubleClicked, this, &QgsProcessingDxfLayersPanelWidget::configureLayer );
76 
77  QPushButton *configureLayerButton = new QPushButton( tr( "Configure Layer…" ) );
78  connect( configureLayerButton, &QPushButton::clicked, this, &QgsProcessingDxfLayersPanelWidget::configureLayer );
79  buttonBox()->addButton( configureLayerButton, QDialogButtonBox::ActionRole );
80 
81  // populate the list: first layers already selected, then layers from project not yet selected
82  mContext.setProject( project );
83 
84  QSet<const QgsVectorLayer *> seenVectorLayers;
85  const QVariantList valueList = value.toList();
86  for ( const QVariant &v : valueList )
87  {
89  if ( !layer.layer() )
90  continue; // skip any invalid layers
91 
92  addOption( v, titleForLayer( layer ), true );
93  seenVectorLayers.insert( layer.layer() );
94  }
95 
96  const QList<QgsVectorLayer *> options = QgsProcessingUtils::compatibleVectorLayers( project, QList< int >() );
97  for ( const QgsVectorLayer *layer : options )
98  {
99  if ( seenVectorLayers.contains( layer ) )
100  continue;
101 
102  QVariantMap vm;
103  vm["layer"] = layer->id();
104  vm["attributeIndex"] = -1;
105 
106  const QString title = layer->name();
107  addOption( vm, title, false );
108  }
109 }
110 
111 void QgsProcessingDxfLayersPanelWidget::configureLayer()
112 {
113  const QModelIndexList selection = listView()->selectionModel()->selectedIndexes();
114  if ( selection.size() != 1 )
115  {
116  QMessageBox::warning( this, tr( "Configure Layer" ), tr( "Please select a single layer." ) );
117  return;
118  }
119 
120  QStandardItem *item = mModel->itemFromIndex( selection[0] );
121  const QVariant value = item->data( Qt::UserRole );
122 
124  if ( panel && panel->dockMode() )
125  {
126  QgsProcessingDxfLayerDetailsWidget *widget = new QgsProcessingDxfLayerDetailsWidget( value, mProject );
127  widget->setPanelTitle( tr( "Configure Layer" ) );
128  widget->buttonBox()->hide();
129 
130  connect( widget, &QgsProcessingDxfLayerDetailsWidget::widgetChanged, this, [ = ]()
131  {
132  setItemValue( item, widget->value() );
133  } );
134  panel->openPanel( widget );
135  }
136  else
137  {
138  QDialog dlg;
139  dlg.setWindowTitle( tr( "Configure Layer" ) );
140  QVBoxLayout *vLayout = new QVBoxLayout();
141  QgsProcessingDxfLayerDetailsWidget *widget = new QgsProcessingDxfLayerDetailsWidget( value, mProject );
142  vLayout->addWidget( widget );
143  connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
144  connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
145  dlg.setLayout( vLayout );
146  if ( dlg.exec() )
147  {
148  setItemValue( item, widget->value() );
149  }
150  }
151 }
152 
153 void QgsProcessingDxfLayersPanelWidget::setItemValue( QStandardItem *item, const QVariant &value )
154 {
155  mContext.setProject( mProject );
156 
157  const QgsDxfExport::DxfLayer layer = QgsProcessingParameterDxfLayers::variantMapAsLayer( value.toMap(), mContext );
158 
159  item->setText( titleForLayer( layer ) );
160  item->setData( value, Qt::UserRole );
161 }
162 
163 QString QgsProcessingDxfLayersPanelWidget::titleForLayer( const QgsDxfExport::DxfLayer &layer )
164 {
165  QString title = layer.layer()->name();
166 
167  if ( layer.layerOutputAttributeIndex() != -1 )
168  title += tr( " [split attribute: %1]" ).arg( layer.splitLayerAttribute() );
169 
170  return title;
171 }
172 
173 
174 //
175 // QgsProcessingDxfLayersWidget
176 //
177 
178 QgsProcessingDxfLayersWidget::QgsProcessingDxfLayersWidget( QWidget *parent )
179  : QWidget( parent )
180 {
181  QHBoxLayout *hl = new QHBoxLayout();
182  hl->setContentsMargins( 0, 0, 0, 0 );
183 
184  mLineEdit = new QLineEdit();
185  mLineEdit->setEnabled( false );
186  hl->addWidget( mLineEdit, 1 );
187 
188  mToolButton = new QToolButton();
189  mToolButton->setText( QString( QChar( 0x2026 ) ) );
190  hl->addWidget( mToolButton );
191 
192  setLayout( hl );
193 
194  updateSummaryText();
195 
196  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingDxfLayersWidget::showDialog );
197 }
198 
199 void QgsProcessingDxfLayersWidget::setValue( const QVariant &value )
200 {
201  if ( value.isValid() )
202  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
203  else
204  mValue.clear();
205 
206  updateSummaryText();
207  emit changed();
208 }
209 
210 void QgsProcessingDxfLayersWidget::setProject( QgsProject *project )
211 {
212  mProject = project;
213 }
214 
215 void QgsProcessingDxfLayersWidget::showDialog()
216 {
218  if ( panel && panel->dockMode() )
219  {
220  QgsProcessingDxfLayersPanelWidget *widget = new QgsProcessingDxfLayersPanelWidget( mValue, mProject );
221  widget->setPanelTitle( tr( "Input layers" ) );
222  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
223  {
224  setValue( widget->selectedOptions() );
225  } );
226  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
227  panel->openPanel( widget );
228  }
229  else
230  {
231  QDialog dlg;
232  dlg.setWindowTitle( tr( "Input layers" ) );
233  QVBoxLayout *vLayout = new QVBoxLayout();
234  QgsProcessingDxfLayersPanelWidget *widget = new QgsProcessingDxfLayersPanelWidget( mValue, mProject );
235  vLayout->addWidget( widget );
236  widget->buttonBox()->addButton( QDialogButtonBox::Cancel );
237  connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
238  connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
239  dlg.setLayout( vLayout );
240  if ( dlg.exec() )
241  {
242  setValue( widget->selectedOptions() );
243  }
244  }
245 }
246 
247 void QgsProcessingDxfLayersWidget::updateSummaryText()
248 {
249  mLineEdit->setText( tr( "%1 vector layers selected" ).arg( mValue.count() ) );
250 }
251 
252 
253 //
254 // QgsProcessingDxfLayersWidgetWrapper
255 //
256 
257 QgsProcessingDxfLayersWidgetWrapper::QgsProcessingDxfLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
258  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
259 {
260 }
261 
262 QString QgsProcessingDxfLayersWidgetWrapper::parameterType() const
263 {
265 }
266 
267 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDxfLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
268 {
269  return new QgsProcessingDxfLayersWidgetWrapper( parameter, type );
270 }
271 
272 QWidget *QgsProcessingDxfLayersWidgetWrapper::createWidget()
273 {
274  mPanel = new QgsProcessingDxfLayersWidget( nullptr );
275  mPanel->setProject( widgetContext().project() );
276  connect( mPanel, &QgsProcessingDxfLayersWidget::changed, this, [ = ]
277  {
278  emit widgetValueHasChanged( this );
279  } );
280  return mPanel;
281 }
282 
283 void QgsProcessingDxfLayersWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
284 {
286  if ( mPanel )
287  {
288  mPanel->setProject( context.project() );
289  }
290 }
291 
292 void QgsProcessingDxfLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
293 {
294  Q_UNUSED( context )
295  if ( mPanel )
296  {
297  mPanel->setValue( value );
298  }
299 }
300 
301 QVariant QgsProcessingDxfLayersWidgetWrapper::widgetValue() const
302 {
303  return mPanel ? mPanel->value() : QVariant();
304 }
305 
306 QStringList QgsProcessingDxfLayersWidgetWrapper::compatibleParameterTypes() const
307 {
308  return QStringList()
315 }
316 
317 QStringList QgsProcessingDxfLayersWidgetWrapper::compatibleOutputTypes() const
318 {
319  return QStringList()
325 }
326 
A widget wrapper for Processing parameter value widgets.
virtual void setWidgetContext(const QgsProcessingParameterWidgetContext &context)
Sets the context in which the Processing parameter widget is shown, e.g., the parent model algorithm,...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QString name
Definition: qgsmaplayer.h:76
Base class for any widget that can be shown as a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
void widgetChanged()
Emitted when the widget state changes.
void acceptPanel()
Accept the panel.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
Contains information about the context in which a processing algorithm is executed.
WidgetType
Types of dialogs which Processing widgets can be created for.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the output class.
static QString typeName()
Returns the type name for the output class.
Base class for the definition of processing parameters.
static QVariantMap layerAsVariantMap(const QgsDxfExport::DxfLayer &layer)
Converts a single input layer to QVariant representation (a QVariantMap)
static QgsDxfExport::DxfLayer variantMapAsLayer(const QVariantMap &layerVariantMap, QgsProcessingContext &context)
Converts a QVariant value (a QVariantMap) to a single input layer.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
static QString typeName()
Returns the type name for the parameter class.
Contains settings which reflect the context in which a Processing parameter widget is shown,...
QgsProject * project() const
Returns the project associated with the widget.
static QList< QgsVectorLayer * > compatibleVectorLayers(QgsProject *project, const QList< int > &sourceTypes=QList< int >(), bool sort=true)
Returns a list of vector layers from a project which are compatible with the processing framework.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
Represents a vector layer which manages a vector based data sets.
Layers and optional attribute index to split into multiple layers using attribute value as layer name...
Definition: qgsdxfexport.h:74
QgsVectorLayer * layer() const
Returns the layer.
Definition: qgsdxfexport.h:81
QString splitLayerAttribute() const
If the split layer attribute is set, the vector layer will be split into several dxf layers,...
int layerOutputAttributeIndex() const
Returns the attribute index used to split into multiple layers.
Definition: qgsdxfexport.h:88