QGIS API Documentation  3.27.0-Master (11ef3e5184)
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  mModel->insertRow( selection[0].row() + 1, item->clone() );
183 }
184 
185 void QgsProcessingVectorTileWriterLayersPanelWidget::setItemValue( QStandardItem *item, const QVariant &value )
186 {
187  mContext.setProject( mProject );
188 
190 
191  item->setText( titleForLayer( layer ) );
192  item->setData( value, Qt::UserRole );
193 }
194 
195 QString QgsProcessingVectorTileWriterLayersPanelWidget::titleForLayer( const QgsVectorTileWriter::Layer &layer )
196 {
197  QString title = layer.layer()->name();
198 
199  // add more details
200  if ( layer.minZoom() >= 0 && layer.maxZoom() >= 0 )
201  title += tr( " [zoom %1...%2]" ).arg( layer.minZoom() ).arg( layer.maxZoom() );
202  else if ( layer.minZoom() >= 0 )
203  title += tr( " [zoom >= %1]" ).arg( layer.minZoom() );
204  else if ( layer.maxZoom() >= 0 )
205  title += tr( " [zoom <= %1]" ).arg( layer.maxZoom() );
206 
207  if ( !layer.layerName().isEmpty() )
208  title += tr( " [name: %1]" ).arg( layer.layerName() );
209  if ( !layer.filterExpression().isEmpty() )
210  title += tr( " [with filter]" );
211 
212  return title;
213 }
214 
215 
216 //
217 // QgsProcessingVectorTileWriterLayersWidget
218 //
219 
220 
221 QgsProcessingVectorTileWriterLayersWidget::QgsProcessingVectorTileWriterLayersWidget( QWidget *parent )
222  : QWidget( parent )
223 {
224  QHBoxLayout *hl = new QHBoxLayout();
225  hl->setContentsMargins( 0, 0, 0, 0 );
226 
227  mLineEdit = new QLineEdit();
228  mLineEdit->setEnabled( false );
229  hl->addWidget( mLineEdit, 1 );
230 
231  mToolButton = new QToolButton();
232  mToolButton->setText( QString( QChar( 0x2026 ) ) );
233  hl->addWidget( mToolButton );
234 
235  setLayout( hl );
236 
237  updateSummaryText();
238 
239  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingVectorTileWriterLayersWidget::showDialog );
240 }
241 
242 void QgsProcessingVectorTileWriterLayersWidget::setValue( const QVariant &value )
243 {
244  if ( value.isValid() )
245  mValue = value.type() == QVariant::List ? value.toList() : QVariantList() << value;
246  else
247  mValue.clear();
248 
249  updateSummaryText();
250  emit changed();
251 }
252 
253 void QgsProcessingVectorTileWriterLayersWidget::setProject( QgsProject *project )
254 {
255  mProject = project;
256 }
257 
258 void QgsProcessingVectorTileWriterLayersWidget::showDialog()
259 {
261  if ( panel && panel->dockMode() )
262  {
263  QgsProcessingVectorTileWriterLayersPanelWidget *widget = new QgsProcessingVectorTileWriterLayersPanelWidget( mValue, mProject );
264  widget->setPanelTitle( tr( "Input layers" ) );
265  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
266  {
267  setValue( widget->selectedOptions() );
268  } );
269  connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
270  panel->openPanel( widget );
271  }
272  else
273  {
274  QDialog dlg;
275  dlg.setWindowTitle( tr( "Input layers" ) );
276  QVBoxLayout *vLayout = new QVBoxLayout();
277  QgsProcessingVectorTileWriterLayersPanelWidget *widget = new QgsProcessingVectorTileWriterLayersPanelWidget( mValue, mProject );
278  vLayout->addWidget( widget );
279  widget->buttonBox()->addButton( QDialogButtonBox::Cancel );
280  connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
281  connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
282  dlg.setLayout( vLayout );
283  if ( dlg.exec() )
284  {
285  setValue( widget->selectedOptions() );
286  }
287  }
288 }
289 
290 void QgsProcessingVectorTileWriterLayersWidget::updateSummaryText()
291 {
292  mLineEdit->setText( tr( "%n vector layer(s) selected", nullptr, mValue.count() ) );
293 }
294 
295 //
296 // QgsProcessingVectorTileWriterLayersWidgetWrapper
297 //
298 
299 QgsProcessingVectorTileWriterLayersWidgetWrapper::QgsProcessingVectorTileWriterLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
300  : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
301 {
302 }
303 
304 QString QgsProcessingVectorTileWriterLayersWidgetWrapper::parameterType() const
305 {
307 }
308 
309 QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingVectorTileWriterLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
310 {
311  return new QgsProcessingVectorTileWriterLayersWidgetWrapper( parameter, type );
312 }
313 
314 QWidget *QgsProcessingVectorTileWriterLayersWidgetWrapper::createWidget()
315 {
316  mPanel = new QgsProcessingVectorTileWriterLayersWidget( nullptr );
317  mPanel->setProject( widgetContext().project() );
318  connect( mPanel, &QgsProcessingVectorTileWriterLayersWidget::changed, this, [ = ]
319  {
320  emit widgetValueHasChanged( this );
321  } );
322  return mPanel;
323 }
324 
325 void QgsProcessingVectorTileWriterLayersWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
326 {
328  if ( mPanel )
329  {
330  mPanel->setProject( context.project() );
331  }
332 }
333 
334 void QgsProcessingVectorTileWriterLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
335 {
336  Q_UNUSED( context )
337  if ( mPanel )
338  {
339  mPanel->setValue( value );
340  }
341 }
342 
343 QVariant QgsProcessingVectorTileWriterLayersWidgetWrapper::widgetValue() const
344 {
345  return mPanel ? mPanel->value() : QVariant();
346 }
347 
348 QStringList QgsProcessingVectorTileWriterLayersWidgetWrapper::compatibleParameterTypes() const
349 {
350  return QStringList();
351 }
352 
353 QStringList QgsProcessingVectorTileWriterLayersWidgetWrapper::compatibleOutputTypes() const
354 {
355  return QStringList();
356 }
357 
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:104
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....