QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
Loading...
Searching...
No Matches
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#include "moc_qgsprocessingdxflayerswidgetwrapper.cpp"
18
19#include <QBoxLayout>
20#include <QLineEdit>
21#include <QMessageBox>
22#include <QPushButton>
23#include <QStandardItemModel>
24#include <QToolButton>
25
26#include "qgspanelwidget.h"
30
32
33//
34// QgsProcessingDxfLayerDetailsWidget
35//
36
37QgsProcessingDxfLayerDetailsWidget::QgsProcessingDxfLayerDetailsWidget( const QVariant &value, QgsProject *project )
38{
39 setupUi( this );
40
41 mFieldsComboBox->setAllowEmptyFieldName( true );
42
43 mContext.setProject( project );
44
46 mLayer = layer.layer();
47
48 if ( !mLayer )
49 return;
50
51 mFieldsComboBox->setLayer( mLayer );
52
53 if ( mLayer->fields().exists( layer.layerOutputAttributeIndex() ) )
54 mFieldsComboBox->setField( mLayer->fields().at( layer.layerOutputAttributeIndex() ).name() );
55
56 mOverriddenName->setText( layer.overriddenName() );
57
58 if ( mLayer->geometryType() == Qgis::GeometryType::Point )
59 {
60 // Data defined blocks are only available for point layers
61 mGroupBoxBlocks->setVisible( true );
62 mGroupBoxBlocks->setChecked( layer.buildDataDefinedBlocks() );
63 mSpinBoxBlocks->setValue( layer.dataDefinedBlocksMaximumNumberOfClasses() );
64 }
65 else
66 {
67 mGroupBoxBlocks->setVisible( false );
68 }
69
70 connect( mFieldsComboBox, &QgsFieldComboBox::fieldChanged, this, &QgsPanelWidget::widgetChanged );
71 connect( mOverriddenName, &QLineEdit::textChanged, this, &QgsPanelWidget::widgetChanged );
72 connect( mGroupBoxBlocks, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
73 connect( mSpinBoxBlocks, &QSpinBox::textChanged, this, &QgsPanelWidget::widgetChanged );
74}
75
76QVariant QgsProcessingDxfLayerDetailsWidget::value() const
77{
78 const int index = mLayer->fields().lookupField( mFieldsComboBox->currentField() );
79 const QgsDxfExport::DxfLayer layer( mLayer, index, mGroupBoxBlocks->isChecked(), mSpinBoxBlocks->value(), mOverriddenName->text().trimmed() );
81}
82
83
84//
85// QgsProcessingDxfLayersPanelWidget
86//
87
88QgsProcessingDxfLayersPanelWidget::QgsProcessingDxfLayersPanelWidget(
89 const QVariant &value,
90 QgsProject *project,
91 QWidget *parent )
92 : QgsProcessingMultipleSelectionPanelWidget( QVariantList(), QVariantList(), parent )
93 , mProject( project )
94{
95 connect( listView(), &QListView::doubleClicked, this, &QgsProcessingDxfLayersPanelWidget::configureLayer );
96
97 QPushButton *configureLayerButton = new QPushButton( tr( "Configure Layer…" ) );
98 connect( configureLayerButton, &QPushButton::clicked, this, &QgsProcessingDxfLayersPanelWidget::configureLayer );
99 buttonBox()->addButton( configureLayerButton, QDialogButtonBox::ActionRole );
100
101 // populate the list: first layers already selected, then layers from project not yet selected
102 mContext.setProject( project );
103
104 QSet<const QgsVectorLayer *> seenVectorLayers;
105 const QVariantList valueList = value.toList();
106 for ( const QVariant &v : valueList )
107 {
109 if ( !layer.layer() )
110 continue; // skip any invalid layers
111
112 addOption( v, titleForLayer( layer ), true );
113 seenVectorLayers.insert( layer.layer() );
114 }
115
116 const QList<QgsVectorLayer *> options = QgsProcessingUtils::compatibleVectorLayers( project, QList< int >() << static_cast<int>( Qgis::ProcessingSourceType::VectorAnyGeometry ) );
117 for ( const QgsVectorLayer *layer : options )
118 {
119 if ( seenVectorLayers.contains( layer ) )
120 continue;
121
122 QVariantMap vm;
123 vm["layer"] = layer->id();
124 vm["attributeIndex"] = -1;
125 vm["overriddenLayerName"] = QString();
126 vm["buildDataDefinedBlocks"] = DEFAULT_DXF_DATA_DEFINED_BLOCKS;
127 vm["dataDefinedBlocksMaximumNumberOfClasses"] = -1;
128
129 const QString title = layer->name();
130 addOption( vm, title, false );
131 }
132}
133
134void QgsProcessingDxfLayersPanelWidget::configureLayer()
135{
136 const QModelIndexList selection = listView()->selectionModel()->selectedIndexes();
137 if ( selection.size() != 1 )
138 {
139 QMessageBox::warning( this, tr( "Configure Layer" ), tr( "Please select a single layer." ) );
140 return;
141 }
142
143 QStandardItem *item = mModel->itemFromIndex( selection[0] );
144 const QVariant value = item->data( Qt::UserRole );
145
147 if ( panel && panel->dockMode() )
148 {
149 QgsProcessingDxfLayerDetailsWidget *widget = new QgsProcessingDxfLayerDetailsWidget( value, mProject );
150 widget->setPanelTitle( tr( "Configure Layer" ) );
151 widget->buttonBox()->hide();
152
153 connect( widget, &QgsProcessingDxfLayerDetailsWidget::widgetChanged, this, [ = ]()
154 {
155 setItemValue( item, widget->value() );
156 } );
157 panel->openPanel( widget );
158 }
159 else
160 {
161 QDialog dlg;
162 dlg.setWindowTitle( tr( "Configure Layer" ) );
163 QVBoxLayout *vLayout = new QVBoxLayout();
164 QgsProcessingDxfLayerDetailsWidget *widget = new QgsProcessingDxfLayerDetailsWidget( value, mProject );
165 vLayout->addWidget( widget );
166 connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
167 connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
168 dlg.setLayout( vLayout );
169 if ( dlg.exec() )
170 {
171 setItemValue( item, widget->value() );
172 }
173 }
174}
175
176void QgsProcessingDxfLayersPanelWidget::setItemValue( QStandardItem *item, const QVariant &value )
177{
178 mContext.setProject( mProject );
179
180 const QgsDxfExport::DxfLayer layer = QgsProcessingParameterDxfLayers::variantMapAsLayer( value.toMap(), mContext );
181
182 item->setText( titleForLayer( layer ) );
183 item->setData( value, Qt::UserRole );
184}
185
186QString QgsProcessingDxfLayersPanelWidget::titleForLayer( const QgsDxfExport::DxfLayer &layer )
187{
188 QString title = layer.layer()->name();
189
190 // if both options are set, the split attribute takes precedence,
191 // so hide overridden message to give users a hint on the result.
192 if ( layer.layerOutputAttributeIndex() != -1 )
193 {
194 title += tr( " [split attribute: %1]" ).arg( layer.splitLayerAttribute() );
195 }
196 else
197 {
198 if ( !layer.overriddenName().isEmpty() )
199 {
200 title += tr( " [overridden name: %1]" ).arg( layer.overriddenName() );
201 }
202 }
203
204 return title;
205}
206
207
208//
209// QgsProcessingDxfLayersWidget
210//
211
212QgsProcessingDxfLayersWidget::QgsProcessingDxfLayersWidget( QWidget *parent )
213 : QWidget( parent )
214{
215 QHBoxLayout *hl = new QHBoxLayout();
216 hl->setContentsMargins( 0, 0, 0, 0 );
217
218 mLineEdit = new QLineEdit();
219 mLineEdit->setEnabled( false );
220 hl->addWidget( mLineEdit, 1 );
221
222 mToolButton = new QToolButton();
223 mToolButton->setText( QString( QChar( 0x2026 ) ) );
224 hl->addWidget( mToolButton );
225
226 setLayout( hl );
227
228 updateSummaryText();
229
230 connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingDxfLayersWidget::showDialog );
231}
232
233void QgsProcessingDxfLayersWidget::setValue( const QVariant &value )
234{
235 if ( value.isValid() )
236 mValue = value.userType() == QMetaType::Type::QVariantList ? value.toList() : QVariantList() << value;
237 else
238 mValue.clear();
239
240 updateSummaryText();
241 emit changed();
242}
243
244void QgsProcessingDxfLayersWidget::setProject( QgsProject *project )
245{
246 mProject = project;
247}
248
249void QgsProcessingDxfLayersWidget::showDialog()
250{
252 if ( panel && panel->dockMode() )
253 {
254 QgsProcessingDxfLayersPanelWidget *widget = new QgsProcessingDxfLayersPanelWidget( mValue, mProject );
255 widget->setPanelTitle( tr( "Input layers" ) );
256 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged, this, [ = ]()
257 {
258 setValue( widget->selectedOptions() );
259 } );
260 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked, widget, &QgsPanelWidget::acceptPanel );
261 panel->openPanel( widget );
262 }
263 else
264 {
265 QDialog dlg;
266 dlg.setWindowTitle( tr( "Input layers" ) );
267 QVBoxLayout *vLayout = new QVBoxLayout();
268 QgsProcessingDxfLayersPanelWidget *widget = new QgsProcessingDxfLayersPanelWidget( mValue, mProject );
269 vLayout->addWidget( widget );
270 widget->buttonBox()->addButton( QDialogButtonBox::Cancel );
271 connect( widget->buttonBox(), &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
272 connect( widget->buttonBox(), &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
273 dlg.setLayout( vLayout );
274 if ( dlg.exec() )
275 {
276 setValue( widget->selectedOptions() );
277 }
278 }
279}
280
281void QgsProcessingDxfLayersWidget::updateSummaryText()
282{
283 mLineEdit->setText( tr( "%n vector layer(s) selected", nullptr, mValue.count() ) );
284}
285
286
287//
288// QgsProcessingDxfLayersWidgetWrapper
289//
290
291QgsProcessingDxfLayersWidgetWrapper::QgsProcessingDxfLayersWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
292 : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
293{
294}
295
296QString QgsProcessingDxfLayersWidgetWrapper::parameterType() const
297{
299}
300
301QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingDxfLayersWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
302{
303 return new QgsProcessingDxfLayersWidgetWrapper( parameter, type );
304}
305
306QWidget *QgsProcessingDxfLayersWidgetWrapper::createWidget()
307{
308 mPanel = new QgsProcessingDxfLayersWidget( nullptr );
309 mPanel->setProject( widgetContext().project() );
310 connect( mPanel, &QgsProcessingDxfLayersWidget::changed, this, [ = ]
311 {
312 emit widgetValueHasChanged( this );
313 } );
314 return mPanel;
315}
316
317void QgsProcessingDxfLayersWidgetWrapper::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
318{
320 if ( mPanel )
321 {
322 mPanel->setProject( context.project() );
323 }
324}
325
326void QgsProcessingDxfLayersWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
327{
328 Q_UNUSED( context )
329 if ( mPanel )
330 {
331 mPanel->setValue( value );
332 }
333}
334
335QVariant QgsProcessingDxfLayersWidgetWrapper::widgetValue() const
336{
337 return mPanel ? mPanel->value() : QVariant();
338}
339
340QStringList QgsProcessingDxfLayersWidgetWrapper::compatibleParameterTypes() const
341{
342 return QStringList()
349}
350
351QStringList QgsProcessingDxfLayersWidgetWrapper::compatibleOutputTypes() const
352{
353 return QStringList()
359}
360
@ VectorAnyGeometry
Any vector layer with geometry.
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:80
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:107
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...
QString overriddenName() const
Returns the overridden layer name to be used in the exported DXF.
bool buildDataDefinedBlocks() const
Flag if data defined point block symbols should be created.
QgsVectorLayer * layer() const
Returns the layer.
int dataDefinedBlocksMaximumNumberOfClasses() const
Returns the maximum number of data defined symbol classes for which blocks are created.
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.