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