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