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