QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
qgsprocessingmultipleselectiondialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingmultipleselectiondialog.cpp
3 ------------------------------------
4 Date : February 2019
5 Copyright : (C) 2019 Nyall Dawson
6 Email : nyall dot dawson 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
19#include "qgsannotationlayer.h"
20#include "qgsfileutils.h"
21#include "qgsgui.h"
22#include "qgsguiutils.h"
23#include "qgsiconutils.h"
24#include "qgsmaplayerfactory.h"
25#include "qgsmeshlayer.h"
26#include "qgsmimedatautils.h"
27#include "qgspluginlayer.h"
28#include "qgspointcloudlayer.h"
29#include "qgsproject.h"
30#include "qgsrasterlayer.h"
31#include "qgssettings.h"
32#include "qgstiledscenelayer.h"
33#include "qgsvectorlayer.h"
34#include "qgsvectortilelayer.h"
35
36#include <QDirIterator>
37#include <QDragEnterEvent>
38#include <QFileDialog>
39#include <QLineEdit>
40#include <QPushButton>
41#include <QStandardItem>
42#include <QStandardItemModel>
43#include <QString>
44#include <QToolButton>
45
46#include "moc_qgsprocessingmultipleselectiondialog.cpp"
47
48using namespace Qt::StringLiterals;
49
51
52QgsProcessingMultipleSelectionPanelWidget::QgsProcessingMultipleSelectionPanelWidget( const QVariantList &availableOptions, const QVariantList &selectedOptions, QWidget *parent )
53 : QgsPanelWidget( parent )
54 , mValueFormatter( []( const QVariant &v ) -> QString {
55 if ( v.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
56 return v.value<QgsProcessingModelChildParameterSource>().staticValue().toString();
57 else
58 return v.toString();
59 } )
60{
61 setupUi( this );
62
64
65 mSelectionList->setSelectionBehavior( QAbstractItemView::SelectRows );
66 mSelectionList->setSelectionMode( QAbstractItemView::ExtendedSelection );
67 mSelectionList->setDragDropMode( QAbstractItemView::InternalMove );
68 mSelectionList->setIconSize( QSize( QgsGuiUtils::scaleIconSize( 16 ), QgsGuiUtils::scaleIconSize( 16 ) ) );
69
70 mModel = new QStandardItemModel( this );
71 mSelectionList->setModel( mModel );
72
73 mButtonSelectAll = new QPushButton( tr( "Select All" ) );
74 mButtonBox->addButton( mButtonSelectAll, QDialogButtonBox::ActionRole );
75
76 mButtonClearSelection = new QPushButton( tr( "Clear Selection" ) );
77 mButtonBox->addButton( mButtonClearSelection, QDialogButtonBox::ActionRole );
78
79 mButtonToggleSelection = new QPushButton( tr( "Toggle Selection" ) );
80 mButtonBox->addButton( mButtonToggleSelection, QDialogButtonBox::ActionRole );
81
82 connect( mButtonSelectAll, &QPushButton::clicked, this, [this] { selectAll( true ); } );
83 connect( mButtonClearSelection, &QPushButton::clicked, this, [this] { selectAll( false ); } );
84 connect( mButtonToggleSelection, &QPushButton::clicked, this, &QgsProcessingMultipleSelectionPanelWidget::toggleSelection );
85
86 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsProcessingMultipleSelectionPanelWidget::acceptClicked );
87 populateList( availableOptions, selectedOptions );
88
89 connect( mModel, &QStandardItemModel::itemChanged, this, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged );
90
91 // When user moves an item, a new item is created and another one is removed, so we need to fire selectionChanged
92 // see https://github.com/qgis/QGIS/issues/44270
93 connect( mModel, &QStandardItemModel::rowsRemoved, this, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged );
94}
95
96void QgsProcessingMultipleSelectionPanelWidget::setValueFormatter( const std::function<QString( const QVariant & )> &formatter )
97{
98 mValueFormatter = formatter;
99 // update item text using new formatter
100 for ( int i = 0; i < mModel->rowCount(); ++i )
101 {
102 mModel->item( i )->setText( mValueFormatter( mModel->item( i )->data( Qt::UserRole ) ) );
103 }
104}
105
106QVariantList QgsProcessingMultipleSelectionPanelWidget::selectedOptions() const
107{
108 QVariantList options;
109 options.reserve( mModel->rowCount() );
110 bool hasModelSources = false;
111 for ( int i = 0; i < mModel->rowCount(); ++i )
112 {
113 QStandardItem *item = mModel->item( i );
114 if ( !item )
115 {
116 continue;
117 }
118
119 if ( item->checkState() == Qt::Checked )
120 {
121 const QVariant option = item->data( Qt::UserRole );
122
123 if ( option.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
124 hasModelSources = true;
125
126 options << option;
127 }
128 }
129
130 if ( hasModelSources )
131 {
132 // if any selected value is a QgsProcessingModelChildParameterSource, then we need to upgrade them all
133 QVariantList originalOptions = options;
134 options.clear();
135 for ( const QVariant &option : originalOptions )
136 {
137 if ( option.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() )
138 options << option;
139 else
140 options << QVariant::fromValue( QgsProcessingModelChildParameterSource::fromStaticValue( option ) );
141 }
142 }
143
144 return options;
145}
146
147
148void QgsProcessingMultipleSelectionPanelWidget::selectAll( const bool checked )
149{
150 const QList<QStandardItem *> items = currentItems();
151 for ( QStandardItem *item : items )
152 {
153 item->setCheckState( checked ? Qt::Checked : Qt::Unchecked );
154 }
155}
156
157void QgsProcessingMultipleSelectionPanelWidget::toggleSelection()
158{
159 const QList<QStandardItem *> items = currentItems();
160 for ( QStandardItem *item : items )
161 {
162 item->setCheckState( item->checkState() == Qt::Unchecked ? Qt::Checked : Qt::Unchecked );
163 }
164}
165
166QList<QStandardItem *> QgsProcessingMultipleSelectionPanelWidget::currentItems()
167{
168 QList<QStandardItem *> items;
169 const QModelIndexList selection = mSelectionList->selectionModel()->selectedIndexes();
170 if ( selection.size() > 1 )
171 {
172 items.reserve( selection.size() );
173 for ( const QModelIndex &index : selection )
174 {
175 items << mModel->itemFromIndex( index );
176 }
177 }
178 else
179 {
180 items.reserve( mModel->rowCount() );
181 for ( int i = 0; i < mModel->rowCount(); ++i )
182 {
183 items << mModel->item( i );
184 }
185 }
186 return items;
187}
188
189void QgsProcessingMultipleSelectionPanelWidget::populateList( const QVariantList &availableOptions, const QVariantList &selectedOptions )
190{
191 QVariantList remainingOptions = availableOptions;
192
193 // we add selected options first, keeping the existing order of options
194 for ( const QVariant &option : selectedOptions )
195 {
196 // if isinstance(t, QgsProcessingModelChildParameterSource):
197 // item = QStandardItem(t.staticValue())
198 // else:
199
200 addOption( option, mValueFormatter( option ), true );
201 remainingOptions.removeAll( option );
202 }
203
204 for ( const QVariant &option : std::as_const( remainingOptions ) )
205 {
206 addOption( option, mValueFormatter( option ), false );
207 }
208}
209
210QList<int> QgsProcessingMultipleSelectionPanelWidget::existingMapLayerFromMimeData( const QMimeData *data ) const
211{
213 QList<int> indexes;
214 for ( const QgsMimeDataUtils::Uri &u : uriList )
215 {
216 // is this uri from the current project?
217 if ( QgsMapLayer *layer = u.mapLayer() )
218 {
219 for ( int i = 0; i < mModel->rowCount(); ++i )
220 {
221 // try to match project layers to current layers
222 QString userRole = mModel->item( i )->data( Qt::UserRole ).toString();
223 if ( userRole == layer->id() || userRole == layer->source() )
224 {
225 indexes.append( i );
226 }
227 }
228 }
229 }
230 return indexes;
231}
232
233void QgsProcessingMultipleSelectionPanelWidget::dragEnterEvent( QDragEnterEvent *event )
234{
235 if ( !( event->possibleActions() & Qt::CopyAction ) )
236 return;
237
238 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData() );
239 if ( !indexes.isEmpty() )
240 {
241 // dragged an acceptable layer, phew
242 event->setDropAction( Qt::CopyAction );
243 event->accept();
244 }
245}
246
247void QgsProcessingMultipleSelectionPanelWidget::dropEvent( QDropEvent *event )
248{
249 if ( !( event->possibleActions() & Qt::CopyAction ) )
250 return;
251
252 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData() );
253 if ( !indexes.isEmpty() )
254 {
255 // dropped an acceptable layer, phew
256 setFocus( Qt::MouseFocusReason );
257 event->setDropAction( Qt::CopyAction );
258 event->accept();
259
260 for ( const int i : indexes )
261 {
262 mModel->item( i )->setCheckState( Qt::Checked );
263 }
264 emit selectionChanged();
265 }
266}
267
268void QgsProcessingMultipleSelectionPanelWidget::addOption( const QVariant &value, const QString &title, bool selected, bool updateExistingTitle, QIcon icon )
269{
270 // don't add duplicate options
271 for ( int i = 0; i < mModel->rowCount(); ++i )
272 {
273 if ( mModel->item( i )->data( Qt::UserRole ) == value || ( mModel->item( i )->data( Qt::UserRole ).userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() && value.userType() == qMetaTypeId<QgsProcessingModelChildParameterSource>() && mModel->item( i )->data( Qt::UserRole ).value<QgsProcessingModelChildParameterSource>() == value.value<QgsProcessingModelChildParameterSource>() ) )
274 {
275 if ( updateExistingTitle )
276 mModel->item( i )->setText( title );
277 return;
278 }
279 }
280
281 auto item = std::make_unique<QStandardItem>( title );
282 item->setData( value, Qt::UserRole );
283 item->setCheckState( selected ? Qt::Checked : Qt::Unchecked );
284 item->setCheckable( true );
285 item->setDropEnabled( false );
286 if ( !icon.isNull() )
287 item->setData( icon, Qt::DecorationRole );
288 mModel->appendRow( item.release() );
289}
290
291//
292// QgsProcessingMultipleSelectionDialog
293//
294
295
296QgsProcessingMultipleSelectionDialog::QgsProcessingMultipleSelectionDialog( const QVariantList &availableOptions, const QVariantList &selectedOptions, QWidget *parent, Qt::WindowFlags flags )
297 : QDialog( parent, flags )
298{
299 setWindowTitle( tr( "Multiple Selection" ) );
300 QVBoxLayout *vLayout = new QVBoxLayout();
301 mWidget = new QgsProcessingMultipleSelectionPanelWidget( availableOptions, selectedOptions );
302 vLayout->addWidget( mWidget );
303 mWidget->buttonBox()->addButton( QDialogButtonBox::Cancel );
304 connect( mWidget->buttonBox(), &QDialogButtonBox::accepted, this, &QDialog::accept );
305 connect( mWidget->buttonBox(), &QDialogButtonBox::rejected, this, &QDialog::reject );
306 setLayout( vLayout );
307}
308
309void QgsProcessingMultipleSelectionDialog::setValueFormatter( const std::function<QString( const QVariant & )> &formatter )
310{
311 mWidget->setValueFormatter( formatter );
312}
313
314QVariantList QgsProcessingMultipleSelectionDialog::selectedOptions() const
315{
316 return mWidget->selectedOptions();
317}
318
319
320//
321// QgsProcessingMultipleInputPanelWidget
322//
323
324QgsProcessingMultipleInputPanelWidget::QgsProcessingMultipleInputPanelWidget( const QgsProcessingParameterMultipleLayers *parameter, const QVariantList &selectedOptions, const QList<QgsProcessingModelChildParameterSource> &modelSources, QgsProcessingModelAlgorithm *model, QWidget *parent )
325 : QgsProcessingMultipleSelectionPanelWidget( QVariantList(), selectedOptions, parent )
326 , mParameter( parameter )
327{
328 QPushButton *addFileButton = new QPushButton( tr( "Add File(s)…" ) );
329 connect( addFileButton, &QPushButton::clicked, this, &QgsProcessingMultipleInputPanelWidget::addFiles );
330 buttonBox()->addButton( addFileButton, QDialogButtonBox::ActionRole );
331
332 QPushButton *addDirButton = new QPushButton( tr( "Add Directory…" ) );
333 connect( addDirButton, &QPushButton::clicked, this, &QgsProcessingMultipleInputPanelWidget::addDirectory );
334 buttonBox()->addButton( addDirButton, QDialogButtonBox::ActionRole );
335 setAcceptDrops( true );
336
337 // Populate "layers" from model sources
338 for ( const QgsProcessingModelChildParameterSource &source : modelSources )
339 {
340 addOption( QVariant::fromValue( source ), source.friendlyIdentifier( model ), false, true );
341 }
342}
343
344void QgsProcessingMultipleInputPanelWidget::setProject( QgsProject *project )
345{
346 if ( mParameter->layerType() != Qgis::ProcessingSourceType::File )
347 populateFromProject( project );
348}
349
350void QgsProcessingMultipleInputPanelWidget::addFiles()
351{
352 QgsSettings settings;
353 QString path = settings.value( u"/Processing/LastInputPath"_s, QDir::homePath() ).toString();
354
355 QString filter;
356 if ( const QgsFileFilterGenerator *generator = dynamic_cast<const QgsFileFilterGenerator *>( mParameter ) )
357 filter = generator->createFileFilter();
358 else
359 filter = QObject::tr( "All files (*.*)" );
360
361 const QStringList filenames = QFileDialog::getOpenFileNames( this, tr( "Select File(s)" ), path, filter );
362 if ( filenames.empty() )
363 return;
364
365 settings.setValue( u"/Processing/LastInputPath"_s, QFileInfo( filenames.at( 0 ) ).path() );
366
367 for ( const QString &file : filenames )
368 {
369 addOption( file, file, true );
370 }
371
372 emit selectionChanged();
373}
374
375void QgsProcessingMultipleInputPanelWidget::addDirectory()
376{
377 QgsSettings settings;
378 const QString path = settings.value( u"/Processing/LastInputPath"_s, QDir::homePath() ).toString();
379
380 const QString dir = QFileDialog::getExistingDirectory( this, tr( "Select Directory" ), path );
381 if ( dir.isEmpty() )
382 return;
383
384 settings.setValue( u"/Processing/LastInputPath"_s, dir );
385
386 QStringList nameFilters;
387 if ( const QgsFileFilterGenerator *generator = dynamic_cast<const QgsFileFilterGenerator *>( mParameter ) )
388 {
389 const QStringList extensions = QgsFileUtils::extensionsFromFilter( generator->createFileFilter() );
390 for ( const QString &extension : extensions )
391 {
392 nameFilters << u"*.%1"_s.arg( extension );
393 nameFilters << u"*.%1"_s.arg( extension.toUpper() );
394 nameFilters << u"*.%1"_s.arg( extension.toLower() );
395 }
396 }
397
398 QDirIterator it( dir, nameFilters, QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories );
399 while ( it.hasNext() )
400 {
401 const QString fullPath = it.next();
402 if ( fullPath.endsWith( ".dbf"_L1, Qt::CaseInsensitive ) )
403 {
404 if ( QFileInfo::exists( u"%1.shp"_s.arg( fullPath.chopped( 4 ) ) ) || QFileInfo::exists( u"%1.SHP"_s.arg( fullPath.chopped( 4 ) ) ) )
405 {
406 // Skip DBFs that are sidecar files to a Shapefile
407 continue;
408 }
409 }
410 else if ( fullPath.endsWith( ".aux.xml"_L1, Qt::CaseInsensitive ) || fullPath.endsWith( ".shp.xml"_L1, Qt::CaseInsensitive ) )
411 {
412 // Skip XMLs that are sidecar files to datasets
413 continue;
414 }
415 addOption( fullPath, fullPath, true );
416 }
417 emit selectionChanged();
418}
419
420QList<int> QgsProcessingMultipleInputPanelWidget::existingMapLayerFromMimeData( const QMimeData *data, QgsMimeDataUtils::UriList &handledUrls ) const
421{
422 handledUrls.clear();
424 QList<int> indexes;
425 for ( const QgsMimeDataUtils::Uri &u : uriList )
426 {
427 // is this uri from the current project?
428 bool matched = false;
429 if ( QgsMapLayer *layer = u.mapLayer() )
430 {
431 for ( int i = 0; i < mModel->rowCount(); ++i )
432 {
433 // try to match project layers to current layers
434 const QString userRole = mModel->item( i )->data( Qt::UserRole ).toString();
435 if ( userRole == layer->id() || userRole == layer->source() )
436 {
437 indexes.append( i );
438 matched = true;
439 }
440 }
441 }
442
443 if ( matched )
444 {
445 handledUrls.append( u );
446 }
447 }
448 return indexes;
449}
450
451
452QStringList QgsProcessingMultipleInputPanelWidget::compatibleUrisFromMimeData( const QgsProcessingParameterMultipleLayers *parameter, const QMimeData *data, const QgsMimeDataUtils::UriList &skipUrls )
453{
454 QStringList skipUrlData;
455 skipUrlData.reserve( skipUrls.size() );
456 for ( const QgsMimeDataUtils::Uri &u : skipUrls )
457 {
458 skipUrlData.append( u.data() );
459 }
460
461 QStringList res;
462
464 for ( const QgsMimeDataUtils::Uri &u : uriList )
465 {
466 if ( skipUrlData.contains( u.data() ) )
467 continue;
468
469 // clang analyzer is not happy because of the multiple duplicate return branches, but it makes the code more readable
470 // NOLINTBEGIN(bugprone-branch-clone)
478 {
479 bool acceptable = false;
480 switch ( QgsWkbTypes::geometryType( u.wkbType ) )
481 {
483 acceptable = true;
484 break;
485
488 acceptable = true;
489 break;
490
493 acceptable = true;
494 break;
495
498 acceptable = true;
499 break;
500
503 acceptable = true;
504 break;
505 }
506 if ( acceptable )
507 res.append( u.providerKey != "ogr"_L1 ? QgsProcessingUtils::encodeProviderKeyAndUri( u.providerKey, u.uri ) : u.uri );
508 }
510 && u.layerType == QgsMapLayerFactory::typeToString( Qgis::LayerType::Raster ) && u.providerKey == "gdal"_L1 )
511 res.append( u.uri );
513 && u.layerType == QgsMapLayerFactory::typeToString( Qgis::LayerType::Mesh ) && u.providerKey == "mdal"_L1 )
514 res.append( u.uri );
517 res.append( u.uri );
520 res.append( u.uri );
521 // NOLINTEND(bugprone-branch-clone)
522 }
523 if ( !uriList.isEmpty() )
524 return res;
525
526 // second chance -- files dragged from file explorer, outside of QGIS
527 QStringList rawPaths;
528 if ( data->hasUrls() )
529 {
530 const QList<QUrl> urls = data->urls();
531 rawPaths.reserve( urls.count() );
532 for ( const QUrl &url : urls )
533 {
534 const QString local = url.toLocalFile();
535 if ( !rawPaths.contains( local ) )
536 rawPaths.append( local );
537 }
538 }
539 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
540 rawPaths.append( data->text() );
541
542 for ( const QString &path : std::as_const( rawPaths ) )
543 {
544 QFileInfo file( path );
545 if ( file.isFile() )
546 {
547 // TODO - we should check to see if it's a valid extension for the parameter, but that's non-trivial
548 res.append( path );
549 }
550 }
551
552 return res;
553}
554
555void QgsProcessingMultipleInputPanelWidget::dragEnterEvent( QDragEnterEvent *event )
556{
557 if ( !( event->possibleActions() & Qt::CopyAction ) )
558 return;
559
560 // maybe dragging layers from the project
561 QgsMimeDataUtils::UriList handledUris;
562 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData(), handledUris );
563 if ( !indexes.isEmpty() )
564 {
565 // dragged an acceptable layer, phew
566 event->setDropAction( Qt::CopyAction );
567 event->accept();
568 return;
569 }
570
571 // maybe dragging layers from browser or file explorer
572 const QStringList uris = compatibleUrisFromMimeData( mParameter, event->mimeData(), handledUris );
573 if ( !uris.isEmpty() )
574 {
575 // dragged an acceptable layer, phew
576 event->setDropAction( Qt::CopyAction );
577 event->accept();
578 }
579}
580
581void QgsProcessingMultipleInputPanelWidget::dropEvent( QDropEvent *event )
582{
583 if ( !( event->possibleActions() & Qt::CopyAction ) )
584 return;
585
586 QgsMimeDataUtils::UriList handledUris;
587 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData(), handledUris );
588 if ( !indexes.isEmpty() )
589 {
590 // dropped an acceptable layer, phew
591 setFocus( Qt::MouseFocusReason );
592 event->setDropAction( Qt::CopyAction );
593 event->accept();
594
595 for ( const int i : indexes )
596 {
597 mModel->item( i )->setCheckState( Qt::Checked );
598 }
599 emit selectionChanged();
600 }
601
602 // maybe dragging layers from browser or file explorer
603 const QStringList uris = compatibleUrisFromMimeData( mParameter, event->mimeData(), handledUris );
604 if ( !uris.isEmpty() )
605 {
606 for ( const QString &uri : uris )
607 {
608 addOption( uri, uri, true );
609 }
610 emit selectionChanged();
611 }
612}
613
614void QgsProcessingMultipleInputPanelWidget::populateFromProject( QgsProject *project )
615{
616 connect( project, &QgsProject::layerRemoved, this, [&]( const QString &layerId ) {
617 for ( int i = 0; i < mModel->rowCount(); ++i )
618 {
619 const QStandardItem *item = mModel->item( i );
620 if ( item->data( Qt::UserRole ) == layerId )
621 {
622 bool isChecked = ( item->checkState() == Qt::Checked );
623 mModel->removeRow( i );
624
625 if ( isChecked )
626 emit selectionChanged();
627
628 break;
629 }
630 }
631 } );
632
633 QgsSettings settings;
634 auto addLayer = [&]( const QgsMapLayer *layer ) {
635 const QString authid = layer->crs().authid();
636 QString title;
637 if ( settings.value( u"Processing/Configuration/SHOW_CRS_DEF"_s, true ).toBool() && !authid.isEmpty() )
638 title = u"%1 [%2]"_s.arg( layer->name(), authid );
639 else
640 title = layer->name();
641
642 QIcon icon = QgsIconUtils::iconForLayer( layer );
643
644 QString id = layer->id();
645 if ( layer == project->mainAnnotationLayer() )
646 id = u"main"_s;
647
648 for ( int i = 0; i < mModel->rowCount(); ++i )
649 {
650 // try to match project layers to current layers, also assign its icon if found
651 if ( mModel->item( i )->data( Qt::UserRole ) == layer->id() )
652 {
653 id = layer->id();
654 mModel->item( i )->setData( QgsIconUtils::iconForLayer( layer ), Qt::DecorationRole );
655 break;
656 }
657 else if ( mModel->item( i )->data( Qt::UserRole ) == layer->source() )
658 {
659 id = layer->source();
660 mModel->item( i )->setData( QgsIconUtils::iconForLayer( layer ), Qt::DecorationRole );
661 break;
662 }
663 }
664
665 addOption( id, title, false, true, icon );
666 };
667
668 switch ( mParameter->layerType() )
669 {
671 break;
672
674 {
675 const QList<QgsRasterLayer *> options = QgsProcessingUtils::compatibleRasterLayers( project, false );
676 for ( const QgsRasterLayer *layer : options )
677 {
678 addLayer( layer );
679 }
680 break;
681 }
682
684 {
685 const QList<QgsMeshLayer *> options = QgsProcessingUtils::compatibleMeshLayers( project, false );
686 for ( const QgsMeshLayer *layer : options )
687 {
688 addLayer( layer );
689 }
690
691 break;
692 }
693
695 {
696 const QList<QgsPluginLayer *> options = QgsProcessingUtils::compatiblePluginLayers( project, false );
697 for ( const QgsPluginLayer *layer : options )
698 {
699 addLayer( layer );
700 }
701
702 break;
703 }
704
706 {
707 const QList<QgsAnnotationLayer *> options = QgsProcessingUtils::compatibleAnnotationLayers( project, false );
708 for ( const QgsAnnotationLayer *layer : options )
709 {
710 addLayer( layer );
711 }
712
713 break;
714 }
715
717 {
718 const QList<QgsPointCloudLayer *> options = QgsProcessingUtils::compatiblePointCloudLayers( project, false );
719 for ( const QgsPointCloudLayer *layer : options )
720 {
721 addLayer( layer );
722 }
723
724 break;
725 }
726
728 {
729 const QList<QgsVectorTileLayer *> options = QgsProcessingUtils::compatibleVectorTileLayers( project, false );
730 for ( const QgsVectorTileLayer *layer : options )
731 {
732 addLayer( layer );
733 }
734
735 break;
736 }
737
739 {
740 const QList<QgsTiledSceneLayer *> options = QgsProcessingUtils::compatibleTiledSceneLayers( project, false );
741 for ( const QgsTiledSceneLayer *layer : options )
742 {
743 addLayer( layer );
744 }
745
746 break;
747 }
748
751 {
752 const QList<QgsVectorLayer *> options = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() << static_cast<int>( mParameter->layerType() ) );
753 for ( const QgsVectorLayer *layer : options )
754 {
755 addLayer( layer );
756 }
757
758 break;
759 }
760
762 {
763 const QList<QgsVectorLayer *> vectors = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() );
764 for ( const QgsVectorLayer *layer : vectors )
765 {
766 addLayer( layer );
767 }
768 const QList<QgsRasterLayer *> rasters = QgsProcessingUtils::compatibleRasterLayers( project );
769 for ( const QgsRasterLayer *layer : rasters )
770 {
771 addLayer( layer );
772 }
773 const QList<QgsMeshLayer *> meshes = QgsProcessingUtils::compatibleMeshLayers( project );
774 for ( const QgsMeshLayer *layer : meshes )
775 {
776 addLayer( layer );
777 }
778 const QList<QgsPluginLayer *> plugins = QgsProcessingUtils::compatiblePluginLayers( project );
779 for ( const QgsPluginLayer *layer : plugins )
780 {
781 addLayer( layer );
782 }
783 const QList<QgsPointCloudLayer *> pointClouds = QgsProcessingUtils::compatiblePointCloudLayers( project );
784 for ( const QgsPointCloudLayer *layer : pointClouds )
785 {
786 addLayer( layer );
787 }
788 const QList<QgsAnnotationLayer *> annotations = QgsProcessingUtils::compatibleAnnotationLayers( project );
789 for ( const QgsAnnotationLayer *layer : annotations )
790 {
791 addLayer( layer );
792 }
793
794 break;
795 }
796
800 {
801 const QList<QgsVectorLayer *> vectors = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() << static_cast<int>( mParameter->layerType() ) );
802 for ( const QgsVectorLayer *layer : vectors )
803 {
804 addLayer( layer );
805 }
806 break;
807 }
808 }
809}
810
811//
812// QgsProcessingMultipleInputDialog
813//
814
815QgsProcessingMultipleInputDialog::QgsProcessingMultipleInputDialog( const QgsProcessingParameterMultipleLayers *parameter, const QVariantList &selectedOptions, const QList<QgsProcessingModelChildParameterSource> &modelSources, QgsProcessingModelAlgorithm *model, QWidget *parent, Qt::WindowFlags flags )
816 : QDialog( parent, flags )
817{
818 setWindowTitle( tr( "Multiple Selection" ) );
819 QVBoxLayout *vLayout = new QVBoxLayout();
820 mWidget = new QgsProcessingMultipleInputPanelWidget( parameter, selectedOptions, modelSources, model, nullptr );
821 vLayout->addWidget( mWidget );
822 mWidget->buttonBox()->addButton( QDialogButtonBox::Cancel );
823 connect( mWidget->buttonBox(), &QDialogButtonBox::accepted, this, &QDialog::accept );
824 connect( mWidget->buttonBox(), &QDialogButtonBox::rejected, this, &QDialog::reject );
825 setLayout( vLayout );
826 setAcceptDrops( true );
827}
828
829QVariantList QgsProcessingMultipleInputDialog::selectedOptions() const
830{
831 return mWidget->selectedOptions();
832}
833
834void QgsProcessingMultipleInputDialog::setProject( QgsProject *project )
835{
836 mWidget->setProject( project );
837}
838
839
@ File
Files (i.e. non map layer sources, such as text files).
Definition qgis.h:3609
@ Plugin
Plugin layers.
Definition qgis.h:3612
@ TiledScene
Tiled scene layers.
Definition qgis.h:3616
@ Annotation
Annotation layers.
Definition qgis.h:3614
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3610
@ VectorTile
Vector tile layers.
Definition qgis.h:3615
@ MapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer).
Definition qgis.h:3603
@ Mesh
Mesh layers.
Definition qgis.h:3611
@ Raster
Raster layers.
Definition qgis.h:3608
@ VectorAnyGeometry
Any vector layer with geometry.
Definition qgis.h:3604
@ VectorPoint
Vector point layers.
Definition qgis.h:3605
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3607
@ VectorLine
Vector line layers.
Definition qgis.h:3606
@ PointCloud
Point cloud layers.
Definition qgis.h:3613
@ Point
Points.
Definition qgis.h:366
@ Line
Lines.
Definition qgis.h:367
@ Polygon
Polygons.
Definition qgis.h:368
@ Unknown
Unknown types.
Definition qgis.h:369
@ Null
No geometry.
Definition qgis.h:370
@ Vector
Vector layer.
Definition qgis.h:194
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:198
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:197
@ Raster
Raster layer.
Definition qgis.h:195
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:200
Represents a map layer containing a set of georeferenced annotations, e.g.
Abstract interface for classes which generate a file filter string.
static QStringList extensionsFromFilter(const QString &filter)
Returns a list of the extensions contained within a file filter string.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:224
static QIcon iconForLayer(const QgsMapLayer *layer)
Returns the icon corresponding to a specified map layer.
static QString typeToString(Qgis::LayerType type)
Converts a map layer type to a string value.
Base class for all map layer types.
Definition qgsmaplayer.h:83
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
Base class for any widget that can be shown as an inline panel.
Base class for plugin layers.
Represents a map layer supporting display of point clouds.
A parameter for processing algorithms which accepts multiple map layers.
Qgis::ProcessingSourceType layerType() const
Returns the layer type for layers acceptable by the parameter.
static QList< QgsTiledSceneLayer * > compatibleTiledSceneLayers(QgsProject *project, bool sort=true)
Returns a list of tiled scene layers from a project which are compatible with the processing framewor...
static QList< QgsAnnotationLayer * > compatibleAnnotationLayers(QgsProject *project, bool sort=true)
Returns a list of annotation layers from a project which are compatible with the processing framework...
static QString encodeProviderKeyAndUri(const QString &providerKey, const QString &uri)
Encodes a provider key and layer uri to a single string, for use with decodeProviderKeyAndUri().
static QList< QgsRasterLayer * > compatibleRasterLayers(QgsProject *project, bool sort=true)
Returns a list of raster layers from a project which are compatible with the processing framework.
static QList< QgsPluginLayer * > compatiblePluginLayers(QgsProject *project, bool sort=true)
Returns a list of plugin layers from a project which are compatible with the processing framework.
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.
static QList< QgsVectorTileLayer * > compatibleVectorTileLayers(QgsProject *project, bool sort=true)
Returns a list of vector tile layers from a project which are compatible with the processing framewor...
static QList< QgsPointCloudLayer * > compatiblePointCloudLayers(QgsProject *project, bool sort=true)
Returns a list of point cloud layers from a project which are compatible with the processing framewor...
static QList< QgsMeshLayer * > compatibleMeshLayers(QgsProject *project, bool sort=true)
Returns a list of mesh 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:113
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
void layerRemoved(const QString &layerId)
Emitted after a layer was removed from the registry.
Represents a raster layer.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Represents a map layer supporting display of tiled scene objects.
Represents a vector layer which manages a vector based dataset.
Implements a map layer that is dedicated to rendering of vector tiles.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...