QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgsprocessingvectortilewriterlayerswidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingvectortilewriterlayerswidgetwrapper.cpp
3  ---------------------
4  Date : April 2020
5  Copyright : (C) 2020 by Martin Dobias
6  Email : wonder dot sk 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"
26 
27 #include "qgsvectortilewriter.h"
28 
30 
32 
33 //
34 // QgsProcessingVectorTileWriteLayerDetailsWidget
35 //
36 
37 QgsProcessingVectorTileWriteLayerDetailsWidget::QgsProcessingVectorTileWriteLayerDetailsWidget( const QVariant &value, QgsProject *project )
38 {
39  setupUi( this );
40 
41  mContext.setProject( project );
42 
44  mLayer = layer.layer();
45 
46  if ( !mLayer )
47  return;
48 
49  mSpinMinZoom->setClearValue( -1, tr( "Not set" ) );
50  mSpinMaxZoom->setClearValue( -1, tr( "Not set" ) );
51  mEditFilterExpression->setMultiLine( true );
52  mEditFilterExpression->setLayer( mLayer );
53 
54  mSpinMinZoom->setValue( layer.minZoom() );
55  mSpinMaxZoom->setValue( layer.maxZoom() );
56  mEditLayerName->setText( layer.layerName() );
57  mEditLayerName->setPlaceholderText( mLayer->name() );
58  mEditFilterExpression->setExpression( layer.filterExpression() );
59 
60  connect( mSpinMinZoom, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsPanelWidget::widgetChanged );
61  connect( mSpinMaxZoom, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsPanelWidget::widgetChanged );
62  connect( mEditLayerName, &QLineEdit::textChanged, this, &QgsPanelWidget::widgetChanged );
63  connect( mEditFilterExpression, &QgsExpressionLineEdit::expressionChanged, this, &QgsPanelWidget::widgetChanged );
64 }
65 
66 QVariant QgsProcessingVectorTileWriteLayerDetailsWidget::value() const
67 {
68  QgsVectorTileWriter::Layer layer( mLayer );
69  layer.setMinZoom( mSpinMinZoom->value() );
70  layer.setMaxZoom( mSpinMaxZoom->value() );
71  layer.setLayerName( mEditLayerName->text() );
72  layer.setFilterExpression( mEditFilterExpression->expression() );
74 }
75 
76 //
77 // QgsProcessingVectorTileWriterLayersPanelWidget
78 //
79 
80 
81 QgsProcessingVectorTileWriterLayersPanelWidget::QgsProcessingVectorTileWriterLayersPanelWidget(
82  const QVariant &value,
83  QgsProject *project,
84  QWidget *parent )
85  : QgsProcessingMultipleSelectionPanelWidget( QVariantList(), QVariantList(), parent )
86  , mProject( project )
87 {
88 
89  connect( listView(), &QListView::doubleClicked, this, &QgsProcessingVectorTileWriterLayersPanelWidget::configureLayer );
90 
91  QPushButton *configureLayerButton = new QPushButton( tr( "Configure Layer…" ) );
92  connect( configureLayerButton, &QPushButton::clicked, this, &QgsProcessingVectorTileWriterLayersPanelWidget::configureLayer );
93  buttonBox()->addButton( configureLayerButton, QDialogButtonBox::ActionRole );
94 
95  QPushButton *copyLayerButton = new QPushButton( tr( "Copy Layer" ) );
96  connect( copyLayerButton, &QPushButton::clicked, this, &QgsProcessingVectorTileWriterLayersPanelWidget::copyLayer );
97  buttonBox()->addButton( copyLayerButton, QDialogButtonBox::ActionRole );
98 
99  // populate the list: first layers already selected, then layers from project not yet selected
100  mContext.setProject( project );
101 
102  QSet<const QgsVectorLayer *> seenVectorLayers;
103  const QVariantList valueList = value.toList();
104  for ( const QVariant &v : valueList )
105  {
107  if ( !layer.layer() )
108  continue; // skip any invalid layers
109 
110  addOption( v, titleForLayer( layer ), true );
111 
112  seenVectorLayers.insert( layer.layer() );
113  }
114 
115  const QList<QgsVectorLayer *> options = QgsProcessingUtils::compatibleVectorLayers( project, QList< int >() );
116  for ( const QgsVectorLayer *layer : options )
117  {
118  if ( seenVectorLayers.contains( layer ) )
119  continue;
120 
121  QVariantMap vm;
122  vm["layer"] = layer->id();
123 
124  const QString title = layer->name();
125 
126  addOption( vm, title, false );
127  }
128 }
129 
130 void QgsProcessingVectorTileWriterLayersPanelWidget::configureLayer()
131 {
132  const QModelIndexList selection = listView()->selectionModel()->selectedIndexes();
133  if ( selection.size() != 1 )
134  {
135  QMessageBox::warning( this, tr( "Configure Layer" ), tr( "Please select a single layer." ) );
136  return;
137  }
138 
139  QStandardItem *item = mModel->itemFromIndex( selection[0] );
140  const QVariant value = item->data( Qt::UserRole );
141 
143  if ( panel && panel->dockMode() )
144  {
145  QgsProcessingVectorTileWriteLayerDetailsWidget *widget = new QgsProcessingVectorTileWriteLayerDetailsWidget( value, mProject );
146  widget->setPanelTitle( tr( "Configure Layer" ) );
147  widget->buttonBox()->hide();
148 
149  connect( widget, &QgsProcessingVectorTileWriteLayerDetailsWidget::widgetChanged, this, [ = ]()
150  {
151  setItemValue( item, widget->value() );
152  } );
153  panel->openPanel( widget );
154  }
155  else
156  {
157  QDialog dlg;
158  dlg.setWindowTitle( tr( "Configure Layer" ) );
159  QVBoxLayout *vLayout = new QVBoxLayout();
160  QgsProcessingVectorTileWriteLayerDetailsWidget *widget = new QgsProcessingVectorTileWriteLayerDetailsWidget( value, mProject );
161  vLayout->addWidget( widget );
162  connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
163  connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
164  dlg.setLayout( vLayout );
165  if ( dlg.exec() )
166  {
167  setItemValue( item, widget->value() );
168  }
169  }
170 }
171 
172 void QgsProcessingVectorTileWriterLayersPanelWidget::copyLayer()
173 {
174  const QModelIndexList selection = listView()->selectionModel()->selectedIndexes();
175  if ( selection.size() != 1 )
176  {
177  QMessageBox::warning( this, tr( "Copy Layer" ), tr( "Please select a single layer." ) );
178  return;
179  }
180 
181  QStandardItem *item = mModel->itemFromIndex( selection[0] );
182  const QVariant value = item->data( Qt::UserRole );
183  mModel->insertRow( selection[0].row() + 1, item->clone() );
184 }
185 
186 void QgsProcessingVectorTileWriterLayersPanelWidget::setItemValue( QStandardItem *item, const QVariant &value )
187 {
188  mContext.setProject( mProject );
189 
191 
192  item->setText( titleForLayer( layer ) );
193  item->setData( value, Qt::UserRole );
194 }
195 
196 QString QgsProcessingVectorTileWriterLayersPanelWidget::titleForLayer( const QgsVectorTileWriter::Layer &layer )
197 {
198  QString title = layer.layer()->name();
199 
200  // add more details
201  if ( layer.minZoom() >= 0 && layer.maxZoom() >= 0 )
202  title += tr( " [zoom %1...%2]" ).arg( layer.minZoom() ).arg( layer.maxZoom() );
203  else if ( layer.minZoom() >= 0 )
204  title += tr( " [zoom >= %1]" ).arg( layer.minZoom() );
205  else if ( layer.maxZoom() >= 0 )
206  title += tr( " [zoom <= %1]" ).arg( layer.maxZoom() );
207 
208  if ( !layer.layerName().isEmpty() )
209  title += tr( " [name: %1]" ).arg( layer.layerName() );
210  if ( !layer.filterExpression().isEmpty() )
211  title += tr( " [with filter]" );
212 
213  return title;
214 }
215 
216 
217 //
218 // QgsProcessingVectorTileWriterLayersWidget
219 //
220 
221 
222 QgsProcessingVectorTileWriterLayersWidget::QgsProcessingVectorTileWriterLayersWidget( QWidget *parent )
223  : QWidget( parent )
224 {
225  QHBoxLayout *hl = new QHBoxLayout();
226  hl->setContentsMargins( 0, 0, 0, 0 );
227 
228  mLineEdit = new QLineEdit();
229  mLineEdit->setEnabled( false );
230  hl->addWidget( mLineEdit, 1 );
231 
232  mToolButton = new QToolButton();
233  mToolButton->setText( QString( QChar( 0x2026 ) ) );
234  hl->addWidget( mToolButton );
235 
236  setLayout( hl );
237 
238  updateSummaryText();
239 
240  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingVectorTileWriterLayersWidget::showDialog );
241 }
242 
243 void QgsProcessingVectorTileWriterLayersWidget::setValue( const QVariant &value )
244 {
245  if ( value.isValid() )
246  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
247  else
248  mValue.clear();
249 
250  updateSummaryText();
251  emit changed();
252 }
253 
254 void QgsProcessingVectorTileWriterLayersWidget::setProject( QgsProject *project )
255 {
256  mProject = project;
257 }
258 
259 void QgsProcessingVectorTileWriterLayersWidget::showDialog()
260 {
262  if ( panel && panel->dockMode() )
263  {
264  QgsProcessingVectorTileWriterLayersPanelWidget *widget = new QgsProcessingVectorTileWriterLayersPanelWidget( mValue, mProject );
265  widget->setPanelTitle( tr( "Input layers" ) );
266  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
267  {
268  setValue( widget->selectedOptions() );
269  } );
270  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
271  panel->openPanel( widget );
272  }
273  else
274  {
275  QDialog dlg;
276  dlg.setWindowTitle( tr( "Input layers" ) );
277  QVBoxLayout *vLayout = new QVBoxLayout();
278  QgsProcessingVectorTileWriterLayersPanelWidget *widget = new QgsProcessingVectorTileWriterLayersPanelWidget( mValue, mProject );
279  vLayout->addWidget( widget );
280  widget->buttonBox()->addButton( QDialogButtonBox::Cancel );
281  connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
282  connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
283  dlg.setLayout( vLayout );
284  if ( dlg.exec() )
285  {
286  setValue( widget->selectedOptions() );
287  }
288  }
289 }
290 
291 void QgsProcessingVectorTileWriterLayersWidget::updateSummaryText()
292 {
293  mLineEdit->setText( tr( "%1 vector layers selected" ).arg( mValue.count() ) );
294 }
295 
296 //
297 // QgsProcessingVectorTileWriterLayersWidgetWrapper
298 //
299 
300 QgsProcessingVectorTileWriterLayersWidgetWrapper::QgsProcessingVectorTileWriterLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
301  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
302 {
303 }
304 
305 QString QgsProcessingVectorTileWriterLayersWidgetWrapper::parameterType() const
306 {
308 }
309 
310 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorTileWriterLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
311 {
312  return new QgsProcessingVectorTileWriterLayersWidgetWrapper( parameter, type );
313 }
314 
315 QWidget *QgsProcessingVectorTileWriterLayersWidgetWrapper::createWidget()
316 {
317  mPanel = new QgsProcessingVectorTileWriterLayersWidget( nullptr );
318  mPanel->setProject( widgetContext().project() );
319  connect( mPanel, &QgsProcessingVectorTileWriterLayersWidget::changed, this, [ = ]
320  {
321  emit widgetValueHasChanged( this );
322  } );
323  return mPanel;
324 }
325 
326 void QgsProcessingVectorTileWriterLayersWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
327 {
329  if ( mPanel )
330  {
331  mPanel->setProject( context.project() );
332  }
333 }
334 
335 void QgsProcessingVectorTileWriterLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
336 {
337  Q_UNUSED( context )
338  if ( mPanel )
339  {
340  mPanel->setValue( value );
341  }
342 }
343 
344 QVariant QgsProcessingVectorTileWriterLayersWidgetWrapper::widgetValue() const
345 {
346  return mPanel ? mPanel->value() : QVariant();
347 }
348 
349 QStringList QgsProcessingVectorTileWriterLayersWidgetWrapper::compatibleParameterTypes() const
350 {
351  return QStringList();
352 }
353 
354 QStringList QgsProcessingVectorTileWriterLayersWidgetWrapper::compatibleOutputTypes() const
355 {
356  return QStringList();
357 }
358 
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 expressionChanged(const QString &expression)
Emitted when the expression is changed.
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.
Base class for the definition of processing parameters.
static QgsVectorTileWriter::Layer variantMapAsLayer(const QVariantMap &layerVariantMap, QgsProcessingContext &context)
Converts a QVariant value (a QVariantMap) to a single input layer.
static QVariantMap layerAsVariantMap(const QgsVectorTileWriter::Layer &layer)
Converts a single input layer to QVariant representation (a QVariantMap)
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.
Configuration of a single input vector layer to be included in the output.
QString layerName() const
Returns layer name in the output. If not set, layer()->name() will be used.
QgsVectorLayer * layer() const
Returns vector layer of this entry.
void setLayerName(const QString &name)
Sets layer name in the output. If not set, layer()->name() will be used.
void setMaxZoom(int maxzoom)
Sets maximum zoom level at which this layer will be used. Negative value means no max....
void setFilterExpression(const QString &expr)
Sets filter expression. If not empty, only features matching the expression will be used.
void setMinZoom(int minzoom)
Sets minimum zoom level at which this layer will be used. Negative value means no min....
QString filterExpression() const
Returns filter expression. If not empty, only features matching the expression will be used.
int maxZoom() const
Returns maximum zoom level at which this layer will be used. Negative value means no max....
int minZoom() const
Returns minimum zoom level at which this layer will be used. Negative value means no min....