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