QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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(
326 const QVariantList &selectedOptions,
327 const QList<QgsProcessingModelChildParameterSource> &modelSources,
328 QgsProcessingModelAlgorithm *model,
329 QWidget *parent
330)
331 : QgsProcessingMultipleSelectionPanelWidget( QVariantList(), selectedOptions, parent )
332 , mParameter( parameter )
333{
334 QPushButton *addFileButton = new QPushButton( tr( "Add File(s)…" ) );
335 connect( addFileButton, &QPushButton::clicked, this, &QgsProcessingMultipleInputPanelWidget::addFiles );
336 buttonBox()->addButton( addFileButton, QDialogButtonBox::ActionRole );
337
338 QPushButton *addDirButton = new QPushButton( tr( "Add Directory…" ) );
339 connect( addDirButton, &QPushButton::clicked, this, &QgsProcessingMultipleInputPanelWidget::addDirectory );
340 buttonBox()->addButton( addDirButton, QDialogButtonBox::ActionRole );
341 setAcceptDrops( true );
342
343 // Populate "layers" from model sources
344 for ( const QgsProcessingModelChildParameterSource &source : modelSources )
345 {
346 addOption( QVariant::fromValue( source ), source.friendlyIdentifier( model ), false, true );
347 }
348}
349
350void QgsProcessingMultipleInputPanelWidget::setProject( QgsProject *project )
351{
352 if ( mParameter->layerType() != Qgis::ProcessingSourceType::File )
353 populateFromProject( project );
354}
355
356void QgsProcessingMultipleInputPanelWidget::addFiles()
357{
358 QgsSettings settings;
359 QString path = settings.value( u"/Processing/LastInputPath"_s, QDir::homePath() ).toString();
360
361 QString filter;
362 if ( const QgsFileFilterGenerator *generator = dynamic_cast<const QgsFileFilterGenerator *>( mParameter ) )
363 filter = generator->createFileFilter();
364 else
365 filter = QObject::tr( "All files (*.*)" );
366
367 const QStringList filenames = QFileDialog::getOpenFileNames( this, tr( "Select File(s)" ), path, filter );
368 if ( filenames.empty() )
369 return;
370
371 settings.setValue( u"/Processing/LastInputPath"_s, QFileInfo( filenames.at( 0 ) ).path() );
372
373 for ( const QString &file : filenames )
374 {
375 addOption( file, file, true );
376 }
377
378 emit selectionChanged();
379}
380
381void QgsProcessingMultipleInputPanelWidget::addDirectory()
382{
383 QgsSettings settings;
384 const QString path = settings.value( u"/Processing/LastInputPath"_s, QDir::homePath() ).toString();
385
386 const QString dir = QFileDialog::getExistingDirectory( this, tr( "Select Directory" ), path );
387 if ( dir.isEmpty() )
388 return;
389
390 settings.setValue( u"/Processing/LastInputPath"_s, dir );
391
392 QStringList nameFilters;
393 if ( const QgsFileFilterGenerator *generator = dynamic_cast<const QgsFileFilterGenerator *>( mParameter ) )
394 {
395 const QStringList extensions = QgsFileUtils::extensionsFromFilter( generator->createFileFilter() );
396 for ( const QString &extension : extensions )
397 {
398 nameFilters << u"*.%1"_s.arg( extension );
399 nameFilters << u"*.%1"_s.arg( extension.toUpper() );
400 nameFilters << u"*.%1"_s.arg( extension.toLower() );
401 }
402 }
403
404 QDirIterator it( dir, nameFilters, QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories );
405 while ( it.hasNext() )
406 {
407 const QString fullPath = it.next();
408 if ( fullPath.endsWith( ".dbf"_L1, Qt::CaseInsensitive ) )
409 {
410 if ( QFileInfo::exists( u"%1.shp"_s.arg( fullPath.chopped( 4 ) ) ) || QFileInfo::exists( u"%1.SHP"_s.arg( fullPath.chopped( 4 ) ) ) )
411 {
412 // Skip DBFs that are sidecar files to a Shapefile
413 continue;
414 }
415 }
416 else if ( fullPath.endsWith( ".aux.xml"_L1, Qt::CaseInsensitive ) || fullPath.endsWith( ".shp.xml"_L1, Qt::CaseInsensitive ) )
417 {
418 // Skip XMLs that are sidecar files to datasets
419 continue;
420 }
421 addOption( fullPath, fullPath, true );
422 }
423 emit selectionChanged();
424}
425
426QList<int> QgsProcessingMultipleInputPanelWidget::existingMapLayerFromMimeData( const QMimeData *data, QgsMimeDataUtils::UriList &handledUrls ) const
427{
428 handledUrls.clear();
430 QList<int> indexes;
431 for ( const QgsMimeDataUtils::Uri &u : uriList )
432 {
433 // is this uri from the current project?
434 bool matched = false;
435 if ( QgsMapLayer *layer = u.mapLayer() )
436 {
437 for ( int i = 0; i < mModel->rowCount(); ++i )
438 {
439 // try to match project layers to current layers
440 const QString userRole = mModel->item( i )->data( Qt::UserRole ).toString();
441 if ( userRole == layer->id() || userRole == layer->source() )
442 {
443 indexes.append( i );
444 matched = true;
445 }
446 }
447 }
448
449 if ( matched )
450 {
451 handledUrls.append( u );
452 }
453 }
454 return indexes;
455}
456
457
458QStringList QgsProcessingMultipleInputPanelWidget::compatibleUrisFromMimeData( const QgsProcessingParameterMultipleLayers *parameter, const QMimeData *data, const QgsMimeDataUtils::UriList &skipUrls )
459{
460 QStringList skipUrlData;
461 skipUrlData.reserve( skipUrls.size() );
462 for ( const QgsMimeDataUtils::Uri &u : skipUrls )
463 {
464 skipUrlData.append( u.data() );
465 }
466
467 QStringList res;
468
470 for ( const QgsMimeDataUtils::Uri &u : uriList )
471 {
472 if ( skipUrlData.contains( u.data() ) )
473 continue;
474
475 // clang analyzer is not happy because of the multiple duplicate return branches, but it makes the code more readable
476 // NOLINTBEGIN(bugprone-branch-clone)
484 {
485 bool acceptable = false;
486 switch ( QgsWkbTypes::geometryType( u.wkbType ) )
487 {
489 acceptable = true;
490 break;
491
497 acceptable = true;
498 break;
499
505 acceptable = true;
506 break;
507
513 acceptable = true;
514 break;
515
518 acceptable = true;
519 break;
520 }
521 if ( acceptable )
522 res.append( u.providerKey != "ogr"_L1 ? QgsProcessingUtils::encodeProviderKeyAndUri( u.providerKey, u.uri ) : u.uri );
523 }
526 && u.providerKey == "gdal"_L1 )
527 res.append( u.uri );
530 && u.providerKey == "mdal"_L1 )
531 res.append( u.uri );
534 res.append( u.uri );
537 res.append( u.uri );
538 // NOLINTEND(bugprone-branch-clone)
539 }
540 if ( !uriList.isEmpty() )
541 return res;
542
543 // second chance -- files dragged from file explorer, outside of QGIS
544 QStringList rawPaths;
545 if ( data->hasUrls() )
546 {
547 const QList<QUrl> urls = data->urls();
548 rawPaths.reserve( urls.count() );
549 for ( const QUrl &url : urls )
550 {
551 const QString local = url.toLocalFile();
552 if ( !rawPaths.contains( local ) )
553 rawPaths.append( local );
554 }
555 }
556 if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
557 rawPaths.append( data->text() );
558
559 for ( const QString &path : std::as_const( rawPaths ) )
560 {
561 QFileInfo file( path );
562 if ( file.isFile() )
563 {
564 // TODO - we should check to see if it's a valid extension for the parameter, but that's non-trivial
565 res.append( path );
566 }
567 }
568
569 return res;
570}
571
572void QgsProcessingMultipleInputPanelWidget::dragEnterEvent( QDragEnterEvent *event )
573{
574 if ( !( event->possibleActions() & Qt::CopyAction ) )
575 return;
576
577 // maybe dragging layers from the project
578 QgsMimeDataUtils::UriList handledUris;
579 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData(), handledUris );
580 if ( !indexes.isEmpty() )
581 {
582 // dragged an acceptable layer, phew
583 event->setDropAction( Qt::CopyAction );
584 event->accept();
585 return;
586 }
587
588 // maybe dragging layers from browser or file explorer
589 const QStringList uris = compatibleUrisFromMimeData( mParameter, event->mimeData(), handledUris );
590 if ( !uris.isEmpty() )
591 {
592 // dragged an acceptable layer, phew
593 event->setDropAction( Qt::CopyAction );
594 event->accept();
595 }
596}
597
598void QgsProcessingMultipleInputPanelWidget::dropEvent( QDropEvent *event )
599{
600 if ( !( event->possibleActions() & Qt::CopyAction ) )
601 return;
602
603 QgsMimeDataUtils::UriList handledUris;
604 const QList<int> indexes = existingMapLayerFromMimeData( event->mimeData(), handledUris );
605 if ( !indexes.isEmpty() )
606 {
607 // dropped an acceptable layer, phew
608 setFocus( Qt::MouseFocusReason );
609 event->setDropAction( Qt::CopyAction );
610 event->accept();
611
612 for ( const int i : indexes )
613 {
614 mModel->item( i )->setCheckState( Qt::Checked );
615 }
616 emit selectionChanged();
617 }
618
619 // maybe dragging layers from browser or file explorer
620 const QStringList uris = compatibleUrisFromMimeData( mParameter, event->mimeData(), handledUris );
621 if ( !uris.isEmpty() )
622 {
623 for ( const QString &uri : uris )
624 {
625 addOption( uri, uri, true );
626 }
627 emit selectionChanged();
628 }
629}
630
631void QgsProcessingMultipleInputPanelWidget::populateFromProject( QgsProject *project )
632{
633 connect( project, &QgsProject::layerRemoved, this, [&]( const QString &layerId ) {
634 for ( int i = 0; i < mModel->rowCount(); ++i )
635 {
636 const QStandardItem *item = mModel->item( i );
637 if ( item->data( Qt::UserRole ) == layerId )
638 {
639 bool isChecked = ( item->checkState() == Qt::Checked );
640 mModel->removeRow( i );
641
642 if ( isChecked )
643 emit selectionChanged();
644
645 break;
646 }
647 }
648 } );
649
650 QgsSettings settings;
651 auto addLayer = [&]( const QgsMapLayer *layer ) {
652 const QString authid = layer->crs().authid();
653 QString title;
654 if ( settings.value( u"Processing/Configuration/SHOW_CRS_DEF"_s, true ).toBool() && !authid.isEmpty() )
655 title = u"%1 [%2]"_s.arg( layer->name(), authid );
656 else
657 title = layer->name();
658
659 QIcon icon = QgsIconUtils::iconForLayer( layer );
660
661 QString id = layer->id();
662 if ( layer == project->mainAnnotationLayer() )
663 id = u"main"_s;
664
665 for ( int i = 0; i < mModel->rowCount(); ++i )
666 {
667 // try to match project layers to current layers, also assign its icon if found
668 if ( mModel->item( i )->data( Qt::UserRole ) == layer->id() )
669 {
670 id = layer->id();
671 mModel->item( i )->setData( QgsIconUtils::iconForLayer( layer ), Qt::DecorationRole );
672 break;
673 }
674 else if ( mModel->item( i )->data( Qt::UserRole ) == layer->source() )
675 {
676 id = layer->source();
677 mModel->item( i )->setData( QgsIconUtils::iconForLayer( layer ), Qt::DecorationRole );
678 break;
679 }
680 }
681
682 addOption( id, title, false, true, icon );
683 };
684
685 switch ( mParameter->layerType() )
686 {
688 break;
689
691 {
692 const QList<QgsRasterLayer *> options = QgsProcessingUtils::compatibleRasterLayers( project, false );
693 for ( const QgsRasterLayer *layer : options )
694 {
695 addLayer( layer );
696 }
697 break;
698 }
699
701 {
702 const QList<QgsMeshLayer *> options = QgsProcessingUtils::compatibleMeshLayers( project, false );
703 for ( const QgsMeshLayer *layer : options )
704 {
705 addLayer( layer );
706 }
707
708 break;
709 }
710
712 {
713 const QList<QgsPluginLayer *> options = QgsProcessingUtils::compatiblePluginLayers( project, false );
714 for ( const QgsPluginLayer *layer : options )
715 {
716 addLayer( layer );
717 }
718
719 break;
720 }
721
723 {
724 const QList<QgsAnnotationLayer *> options = QgsProcessingUtils::compatibleAnnotationLayers( project, false );
725 for ( const QgsAnnotationLayer *layer : options )
726 {
727 addLayer( layer );
728 }
729
730 break;
731 }
732
734 {
735 const QList<QgsPointCloudLayer *> options = QgsProcessingUtils::compatiblePointCloudLayers( project, false );
736 for ( const QgsPointCloudLayer *layer : options )
737 {
738 addLayer( layer );
739 }
740
741 break;
742 }
743
745 {
746 const QList<QgsVectorTileLayer *> options = QgsProcessingUtils::compatibleVectorTileLayers( project, false );
747 for ( const QgsVectorTileLayer *layer : options )
748 {
749 addLayer( layer );
750 }
751
752 break;
753 }
754
756 {
757 const QList<QgsTiledSceneLayer *> options = QgsProcessingUtils::compatibleTiledSceneLayers( project, false );
758 for ( const QgsTiledSceneLayer *layer : options )
759 {
760 addLayer( layer );
761 }
762
763 break;
764 }
765
768 {
769 const QList<QgsVectorLayer *> options = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() << static_cast<int>( mParameter->layerType() ) );
770 for ( const QgsVectorLayer *layer : options )
771 {
772 addLayer( layer );
773 }
774
775 break;
776 }
777
779 {
780 const QList<QgsVectorLayer *> vectors = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() );
781 for ( const QgsVectorLayer *layer : vectors )
782 {
783 addLayer( layer );
784 }
785 const QList<QgsRasterLayer *> rasters = QgsProcessingUtils::compatibleRasterLayers( project );
786 for ( const QgsRasterLayer *layer : rasters )
787 {
788 addLayer( layer );
789 }
790 const QList<QgsMeshLayer *> meshes = QgsProcessingUtils::compatibleMeshLayers( project );
791 for ( const QgsMeshLayer *layer : meshes )
792 {
793 addLayer( layer );
794 }
795 const QList<QgsPluginLayer *> plugins = QgsProcessingUtils::compatiblePluginLayers( project );
796 for ( const QgsPluginLayer *layer : plugins )
797 {
798 addLayer( layer );
799 }
800 const QList<QgsPointCloudLayer *> pointClouds = QgsProcessingUtils::compatiblePointCloudLayers( project );
801 for ( const QgsPointCloudLayer *layer : pointClouds )
802 {
803 addLayer( layer );
804 }
805 const QList<QgsAnnotationLayer *> annotations = QgsProcessingUtils::compatibleAnnotationLayers( project );
806 for ( const QgsAnnotationLayer *layer : annotations )
807 {
808 addLayer( layer );
809 }
810
811 break;
812 }
813
817 {
818 const QList<QgsVectorLayer *> vectors = QgsProcessingUtils::compatibleVectorLayers( project, QList<int>() << static_cast<int>( mParameter->layerType() ) );
819 for ( const QgsVectorLayer *layer : vectors )
820 {
821 addLayer( layer );
822 }
823 break;
824 }
825 }
826}
827
828//
829// QgsProcessingMultipleInputDialog
830//
831
832QgsProcessingMultipleInputDialog::QgsProcessingMultipleInputDialog(
834 const QVariantList &selectedOptions,
835 const QList<QgsProcessingModelChildParameterSource> &modelSources,
836 QgsProcessingModelAlgorithm *model,
837 QWidget *parent,
838 Qt::WindowFlags flags
839)
840 : QDialog( parent, flags )
841{
842 setWindowTitle( tr( "Multiple Selection" ) );
843 QVBoxLayout *vLayout = new QVBoxLayout();
844 mWidget = new QgsProcessingMultipleInputPanelWidget( parameter, selectedOptions, modelSources, model, nullptr );
845 vLayout->addWidget( mWidget );
846 mWidget->buttonBox()->addButton( QDialogButtonBox::Cancel );
847 connect( mWidget->buttonBox(), &QDialogButtonBox::accepted, this, &QDialog::accept );
848 connect( mWidget->buttonBox(), &QDialogButtonBox::rejected, this, &QDialog::reject );
849 setLayout( vLayout );
850 setAcceptDrops( true );
851}
852
853QVariantList QgsProcessingMultipleInputDialog::selectedOptions() const
854{
855 return mWidget->selectedOptions();
856}
857
858void QgsProcessingMultipleInputDialog::setProject( QgsProject *project )
859{
860 mWidget->setProject( project );
861}
862
863
@ File
Files (i.e. non map layer sources, such as text files).
Definition qgis.h:3652
@ Plugin
Plugin layers.
Definition qgis.h:3655
@ TiledScene
Tiled scene layers.
Definition qgis.h:3659
@ Annotation
Annotation layers.
Definition qgis.h:3657
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3653
@ VectorTile
Vector tile layers.
Definition qgis.h:3658
@ MapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer).
Definition qgis.h:3646
@ Mesh
Mesh layers.
Definition qgis.h:3654
@ Raster
Raster layers.
Definition qgis.h:3651
@ VectorAnyGeometry
Any vector layer with geometry.
Definition qgis.h:3647
@ VectorPoint
Vector point layers.
Definition qgis.h:3648
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3650
@ VectorLine
Vector line layers.
Definition qgis.h:3649
@ PointCloud
Point cloud layers.
Definition qgis.h:3656
@ Point
Points.
Definition qgis.h:380
@ Line
Lines.
Definition qgis.h:381
@ Polygon
Polygons.
Definition qgis.h:382
@ Unknown
Unknown types.
Definition qgis.h:383
@ Null
No geometry.
Definition qgis.h:384
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
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,...