48#include <QActionGroup>
51#include <QKeySequence>
57#include <QSvgGenerator>
63#include "moc_qgsmodeldesignerdialog.cpp"
65using namespace Qt::StringLiterals;
70QgsModelerToolboxModel::QgsModelerToolboxModel( QObject *parent )
74Qt::ItemFlags QgsModelerToolboxModel::flags(
const QModelIndex &index )
const
76 Qt::ItemFlags f = QgsProcessingToolboxProxyModel::flags( index );
77 const QModelIndex sourceIndex = mapToSource( index );
78 if ( toolboxModel()->isAlgorithm( sourceIndex ) || toolboxModel()->isParameter( sourceIndex ) )
80 f = f | Qt::ItemIsDragEnabled;
85Qt::DropActions QgsModelerToolboxModel::supportedDragActions()
const
87 return Qt::CopyAction;
90QgsModelDesignerDialog::QgsModelDesignerDialog( QWidget *parent, Qt::WindowFlags flags )
91 : QMainWindow( parent, flags )
92 , mToolsActionGroup( new QActionGroup( this ) )
100 setAttribute( Qt::WA_DeleteOnClose );
101 setDockOptions( dockOptions() | QMainWindow::GroupedDragging );
102 setWindowFlags( Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint );
106 mModel = std::make_unique<QgsProcessingModelAlgorithm>();
109 mUndoStack =
new QUndoStack(
this );
110 connect( mUndoStack, &QUndoStack::indexChanged,
this, [
this] {
111 if ( mIgnoreUndoStackChanges )
114 mBlockUndoCommands++;
115 updateVariablesGui();
116 mGroupEdit->setText( mModel->group() );
117 mNameEdit->setText( mModel->displayName() );
118 mBlockUndoCommands--;
123 mConfigWidgetDock->setWindowTitle( tr(
"Configuration" ) );
124 mConfigWidgetDock->setObjectName( u
"ModelConfigDock"_s );
127 mConfigWidgetDock->setWidget( mConfigWidget );
128 mConfigWidgetDock->setFeatures( QDockWidget::NoDockWidgetFeatures );
129 addDockWidget( Qt::RightDockWidgetArea, mConfigWidgetDock );
131 mPropertiesDock->setFeatures( QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
132 mInputsDock->setFeatures( QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
133 mAlgorithmsDock->setFeatures( QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
134 mVariablesDock->setFeatures( QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
136 mToolboxTree->header()->setVisible(
false );
137 mToolboxSearchEdit->setShowSearchIcon(
true );
138 mToolboxSearchEdit->setPlaceholderText( tr(
"Search…" ) );
139 connect( mToolboxSearchEdit, &QgsFilterLineEdit::textChanged, mToolboxTree, &QgsProcessingToolboxTreeView::setFilterString );
141 mInputsTreeWidget->header()->setVisible(
false );
142 mInputsTreeWidget->setAlternatingRowColors(
true );
143 mInputsTreeWidget->setDragDropMode( QTreeWidget::DragOnly );
144 mInputsTreeWidget->setDropIndicatorShown(
true );
146 mNameEdit->setPlaceholderText( tr(
"Enter model name here" ) );
147 mGroupEdit->setPlaceholderText( tr(
"Enter group name here" ) );
150 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
151 mainLayout->insertWidget( 0, mMessageBar );
153 mView->setAcceptDrops(
true );
156 connect( mActionClose, &QAction::triggered,
this, &QWidget::close );
157 connect( mActionNew, &QAction::triggered,
this, &QgsModelDesignerDialog::newModel );
158 connect( mActionZoomIn, &QAction::triggered,
this, &QgsModelDesignerDialog::zoomIn );
159 connect( mActionZoomOut, &QAction::triggered,
this, &QgsModelDesignerDialog::zoomOut );
160 connect( mActionZoomActual, &QAction::triggered,
this, &QgsModelDesignerDialog::zoomActual );
161 connect( mActionZoomToItems, &QAction::triggered,
this, &QgsModelDesignerDialog::zoomFull );
162 connect( mActionExportImage, &QAction::triggered,
this, &QgsModelDesignerDialog::exportToImage );
163 connect( mActionExportPdf, &QAction::triggered,
this, &QgsModelDesignerDialog::exportToPdf );
164 connect( mActionExportSvg, &QAction::triggered,
this, &QgsModelDesignerDialog::exportToSvg );
165 connect( mActionExportPython, &QAction::triggered,
this, &QgsModelDesignerDialog::exportAsPython );
166 connect( mActionSave, &QAction::triggered,
this, [
this] { saveModel(
false ); } );
167 connect( mActionSaveAs, &QAction::triggered,
this, [
this] { saveModel(
true ); } );
168 connect( mActionDeleteComponents, &QAction::triggered,
this, &QgsModelDesignerDialog::deleteSelected );
169 connect( mActionSnapSelected, &QAction::triggered, mView, &QgsModelGraphicsView::snapSelected );
170 connect( mActionValidate, &QAction::triggered,
this, &QgsModelDesignerDialog::validate );
171 connect( mActionReorderInputs, &QAction::triggered,
this, &QgsModelDesignerDialog::reorderInputs );
172 connect( mActionReorderOutputs, &QAction::triggered,
this, &QgsModelDesignerDialog::reorderOutputs );
173 connect( mActionEditHelp, &QAction::triggered,
this, &QgsModelDesignerDialog::editHelp );
174 connect( mReorderInputsButton, &QPushButton::clicked,
this, &QgsModelDesignerDialog::reorderInputs );
175 connect( mActionRun, &QAction::triggered,
this, [
this] { run(); } );
176 connect( mActionRunSelectedSteps, &QAction::triggered,
this, &QgsModelDesignerDialog::runSelectedSteps );
178 mActionSnappingEnabled->setChecked( settings.
value( u
"/Processing/Modeler/enableSnapToGrid"_s,
false ).toBool() );
179 connect( mActionSnappingEnabled, &QAction::toggled,
this, [
this](
bool enabled ) {
180 mView->snapper()->setSnapToGrid( enabled );
183 mView->snapper()->setSnapToGrid( mActionSnappingEnabled->isChecked() );
185 connect( mView, &QgsModelGraphicsView::itemFocused,
this, &QgsModelDesignerDialog::onItemFocused );
187 connect( mActionSelectAll, &QAction::triggered,
this, [
this] { mScene->selectAll(); } );
189 QStringList docksTitle = settings.
value( u
"ModelDesigner/hiddenDocksTitle"_s, QStringList(),
QgsSettings::App ).toStringList();
190 QStringList docksActive = settings.
value( u
"ModelDesigner/hiddenDocksActive"_s, QStringList(),
QgsSettings::App ).toStringList();
191 if ( !docksTitle.isEmpty() )
193 for (
const auto &title : docksTitle )
195 mPanelStatus.insert( title, PanelStatus(
true, docksActive.contains( title ) ) );
198 mActionHidePanels->setChecked( !docksTitle.isEmpty() );
199 connect( mActionHidePanels, &QAction::toggled,
this, &QgsModelDesignerDialog::setPanelVisibility );
201 mUndoAction = mUndoStack->createUndoAction(
this );
203 mUndoAction->setShortcuts( QKeySequence::Undo );
204 mRedoAction = mUndoStack->createRedoAction(
this );
206 mRedoAction->setShortcuts( QKeySequence::Redo );
208 mMenuEdit->insertAction( mActionDeleteComponents, mRedoAction );
209 mMenuEdit->insertAction( mActionDeleteComponents, mUndoAction );
210 mMenuEdit->insertSeparator( mActionDeleteComponents );
211 mToolbar->insertAction( mActionZoomIn, mUndoAction );
212 mToolbar->insertAction( mActionZoomIn, mRedoAction );
213 mToolbar->insertSeparator( mActionZoomIn );
215 mGroupMenu =
new QMenu( tr(
"Zoom To" ),
this );
216 mMenuView->insertMenu( mActionZoomIn, mGroupMenu );
217 connect( mGroupMenu, &QMenu::aboutToShow,
this, &QgsModelDesignerDialog::populateZoomToMenu );
221 mActionCut =
new QAction( tr(
"Cu&t" ),
this );
222 mActionCut->setShortcuts( QKeySequence::Cut );
223 mActionCut->setStatusTip( tr(
"Cut" ) );
225 connect( mActionCut, &QAction::triggered,
this, [
this] { mView->copySelectedItems( QgsModelGraphicsView::ClipboardCut ); } );
227 mActionCopy =
new QAction( tr(
"&Copy" ),
this );
228 mActionCopy->setShortcuts( QKeySequence::Copy );
229 mActionCopy->setStatusTip( tr(
"Copy" ) );
231 connect( mActionCopy, &QAction::triggered,
this, [
this] { mView->copySelectedItems( QgsModelGraphicsView::ClipboardCopy ); } );
233 mActionPaste =
new QAction( tr(
"&Paste" ),
this );
234 mActionPaste->setShortcuts( QKeySequence::Paste );
235 mActionPaste->setStatusTip( tr(
"Paste" ) );
237 connect( mActionPaste, &QAction::triggered,
this, [
this] { mView->pasteItems( QgsModelGraphicsView::PasteModeCursor ); } );
238 mMenuEdit->insertAction( mActionDeleteComponents, mActionCut );
239 mMenuEdit->insertAction( mActionDeleteComponents, mActionCopy );
240 mMenuEdit->insertAction( mActionDeleteComponents, mActionPaste );
241 mMenuEdit->insertSeparator( mActionDeleteComponents );
243 mAlgorithmsModel =
new QgsModelerToolboxModel(
this );
244 mToolboxTree->setToolboxProxyModel( mAlgorithmsModel );
247 if ( settings.
value( u
"Processing/Configuration/SHOW_ALGORITHMS_KNOWN_ISSUES"_s,
false ).toBool() )
251 mToolboxTree->setFilters( filters );
252 mToolboxTree->setDragDropMode( QTreeWidget::DragOnly );
253 mToolboxTree->setDropIndicatorShown(
true );
255 connect( mView, &QgsModelGraphicsView::algorithmDropped,
this, [
this](
const QString &algorithmId,
const QPointF &pos ) { addAlgorithm( algorithmId, pos ); } );
256 connect( mView, &QgsModelGraphicsView::inputDropped,
this, &QgsModelDesignerDialog::addInput );
258 connect( mToolboxTree, &QgsProcessingToolboxTreeView::doubleClicked,
this, [
this](
const QModelIndex & ) {
259 if ( mToolboxTree->selectedAlgorithm() )
260 addAlgorithm( mToolboxTree->selectedAlgorithm()->id(), QPointF() );
261 if ( mToolboxTree->selectedParameterType() )
262 addInput( mToolboxTree->selectedParameterType()->id(), QPointF() );
265 connect( mInputsTreeWidget, &QgsModelDesignerInputsTreeWidget::doubleClicked,
this, [
this](
const QModelIndex & ) {
266 const QString parameterType = mInputsTreeWidget->currentItem()->data( 0, Qt::UserRole ).toString();
267 addInput( parameterType, QPointF() );
271 QShortcut *ctrlEquals =
new QShortcut( QKeySequence( u
"Ctrl+="_s ),
this );
272 connect( ctrlEquals, &QShortcut::activated,
this, &QgsModelDesignerDialog::zoomIn );
275 mUndoDock->setObjectName( u
"UndoDock"_s );
276 mUndoView =
new QUndoView( mUndoStack,
this );
277 mUndoDock->setWidget( mUndoView );
278 mUndoDock->setFeatures( QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
279 addDockWidget( Qt::DockWidgetArea::LeftDockWidgetArea, mUndoDock );
281 tabifyDockWidget( mUndoDock, mPropertiesDock );
282 tabifyDockWidget( mVariablesDock, mPropertiesDock );
283 mPropertiesDock->raise();
284 tabifyDockWidget( mInputsDock, mAlgorithmsDock );
285 mInputsDock->raise();
290 beginUndoCommand( tr(
"Change Model Variables" ) );
291 mModel->setVariables( mVariablesEditor->variablesInActiveScope() );
295 connect( mNameEdit, &QLineEdit::textChanged,
this, [
this](
const QString &name ) {
298 beginUndoCommand( tr(
"Change Model Name" ), QString(), QgsModelUndoCommand::CommandOperation::NameChanged );
299 mModel->setName( name );
304 connect( mGroupEdit, &QLineEdit::textChanged,
this, [
this](
const QString &group ) {
307 beginUndoCommand( tr(
"Change Model Group" ), QString(), QgsModelUndoCommand::CommandOperation::GroupChanged );
308 mModel->setGroup( group );
316 QToolButton *toolbuttonExportToScript =
new QToolButton();
317 toolbuttonExportToScript->setPopupMode( QToolButton::InstantPopup );
318 toolbuttonExportToScript->addAction( mActionExportAsScriptAlgorithm );
319 toolbuttonExportToScript->setDefaultAction( mActionExportAsScriptAlgorithm );
320 mToolbar->insertWidget( mActionExportImage, toolbuttonExportToScript );
321 connect( mActionExportAsScriptAlgorithm, &QAction::triggered,
this, &QgsModelDesignerDialog::exportAsScriptAlgorithm );
323 mActionShowComments->setChecked( settings.
value( u
"/Processing/Modeler/ShowComments"_s,
true ).toBool() );
324 connect( mActionShowComments, &QAction::toggled,
this, &QgsModelDesignerDialog::toggleComments );
326 mActionShowFeatureCount->setChecked( settings.
value( u
"/Processing/Modeler/ShowFeatureCount"_s,
true ).toBool() );
327 connect( mActionShowFeatureCount, &QAction::toggled,
this, &QgsModelDesignerDialog::toggleFeatureCount );
330 mPanTool->setAction( mActionPan );
332 mToolsActionGroup->addAction( mActionPan );
333 connect( mActionPan, &QAction::triggered, mPanTool, [
this] { mView->setTool( mPanTool ); } );
338 mSelectTool->setAction( mActionSelectMoveItem );
340 mToolsActionGroup->addAction( mActionSelectMoveItem );
341 connect( mActionSelectMoveItem, &QAction::triggered, mSelectTool, [
this] { mView->setTool( mSelectTool ); } );
343 mView->setTool( mSelectTool );
346 connect( mView, &QgsModelGraphicsView::macroCommandStarted,
this, [
this](
const QString &text ) {
347 mIgnoreUndoStackChanges++;
348 mUndoStack->beginMacro( text );
349 mIgnoreUndoStackChanges--;
351 connect( mView, &QgsModelGraphicsView::macroCommandEnded,
this, [
this] {
352 mIgnoreUndoStackChanges++;
353 mUndoStack->endMacro();
354 mIgnoreUndoStackChanges--;
356 connect( mView, &QgsModelGraphicsView::commandBegun,
this, [
this](
const QString &text ) { beginUndoCommand( text ); } );
357 connect( mView, &QgsModelGraphicsView::commandEnded,
this, [
this] { endUndoCommand(); } );
358 connect( mView, &QgsModelGraphicsView::commandAborted,
this, [
this] { abortUndoCommand(); } );
359 connect( mView, &QgsModelGraphicsView::deleteSelectedItems,
this, [
this] { deleteSelected(); } );
361 connect( mActionAddGroupBox, &QAction::triggered,
this, [
this] {
362 const QPointF viewCenter = mView->mapToScene( mView->viewport()->rect().center() );
363 QgsProcessingModelGroupBox group;
364 group.setPosition( viewCenter );
365 group.setDescription( tr(
"New Group" ) );
367 beginUndoCommand( tr(
"Add Group Box" ) );
368 model()->addGroupBox( group );
376 restoreState( settings.
value( u
"ModelDesigner/state"_s, QByteArray(),
QgsSettings::App ).toByteArray() );
379QgsModelDesignerDialog::~QgsModelDesignerDialog()
382 if ( !mPanelStatus.isEmpty() )
384 QStringList docksTitle;
385 QStringList docksActive;
387 for (
const auto &panel : mPanelStatus.toStdMap() )
389 if ( panel.second.isVisible )
390 docksTitle << panel.first;
391 if ( panel.second.isActive )
392 docksActive << panel.first;
406 mIgnoreUndoStackChanges++;
409void QgsModelDesignerDialog::closeEvent( QCloseEvent *event )
411 if ( checkForUnsavedChanges() )
417void QgsModelDesignerDialog::beginUndoCommand(
const QString &text,
const QString &
id, QgsModelUndoCommand::CommandOperation operation )
419 if ( mBlockUndoCommands || !mUndoStack )
422 if ( mActiveCommand )
427 mActiveCommand = std::make_unique<QgsModelUndoCommand>( mModel.get(), text,
id );
431 mActiveCommand = std::make_unique<QgsModelUndoCommand>( mModel.get(), text, operation );
435void QgsModelDesignerDialog::endUndoCommand()
437 if ( mBlockUndoCommands || !mActiveCommand || !mUndoStack )
440 mActiveCommand->saveAfterState();
441 mIgnoreUndoStackChanges++;
442 mUndoStack->push( mActiveCommand.release() );
443 mIgnoreUndoStackChanges--;
447void QgsModelDesignerDialog::abortUndoCommand()
449 if ( mActiveCommand )
450 mActiveCommand->setObsolete(
true );
453QgsProcessingModelAlgorithm *QgsModelDesignerDialog::model()
458void QgsModelDesignerDialog::setModel( QgsProcessingModelAlgorithm *model )
460 mModel.reset( model );
462 mGroupEdit->setText( mModel->group() );
463 mNameEdit->setText( mModel->displayName() );
464 repaintModel(
true );
465 updateVariablesGui();
469 mIgnoreUndoStackChanges++;
471 mIgnoreUndoStackChanges--;
477 QMetaObject::invokeMethod(
this, &QgsModelDesignerDialog::zoomFull, Qt::QueuedConnection );
480void QgsModelDesignerDialog::loadModel(
const QString &path )
482 auto alg = std::make_unique<QgsProcessingModelAlgorithm>();
483 if ( alg->fromFile( path ) )
486 alg->setSourceFilePath( path );
487 setModel( alg.release() );
492 QMessageBox::critical(
496 "The selected model could not be loaded.\n"
497 "See the log for more information."
503void QgsModelDesignerDialog::setModelScene( QgsModelGraphicsScene *scene )
505 QgsModelGraphicsScene *oldScene = mScene;
508 mScene->setParent(
this );
509 mScene->setLastRunResult( mLastResult, mLayerStore );
510 mScene->setModel( mModel.get() );
511 mScene->setMessageBar( mMessageBar );
514 const bool showFeatureCount = settings.
value( u
"/Processing/Modeler/ShowFeatureCount"_s,
true ).toBool();
515 if ( !showFeatureCount )
516 mScene->setFlag( QgsModelGraphicsScene::FlagHideFeatureCount );
518 mView->setModelScene( mScene );
520 mSelectTool->resetCache();
521 mSelectTool->setScene( mScene );
523 connect( mScene, &QgsModelGraphicsScene::rebuildRequired,
this, [
this] {
524 if ( mBlockRepaints )
529 connect( mScene, &QgsModelGraphicsScene::componentAboutToChange,
this, [
this](
const QString &description,
const QString &
id ) { beginUndoCommand( description,
id ); } );
530 connect( mScene, &QgsModelGraphicsScene::componentChanged,
this, [
this] { endUndoCommand(); } );
531 connect( mScene, &QgsModelGraphicsScene::runFromChild,
this, &QgsModelDesignerDialog::runFromChild );
532 connect( mScene, &QgsModelGraphicsScene::runSelected,
this, &QgsModelDesignerDialog::runSelectedSteps );
533 connect( mScene, &QgsModelGraphicsScene::showChildAlgorithmOutputs,
this, &QgsModelDesignerDialog::showChildAlgorithmOutputs );
534 connect( mScene, &QgsModelGraphicsScene::showChildAlgorithmLog,
this, &QgsModelDesignerDialog::showChildAlgorithmLog );
537 oldScene->deleteLater();
540QgsModelGraphicsScene *QgsModelDesignerDialog::modelScene()
545void QgsModelDesignerDialog::activate()
549 setWindowState( windowState() & ~Qt::WindowMinimized );
555 mProcessingContextGenerator = generator;
558void QgsModelDesignerDialog::updateVariablesGui()
560 mBlockUndoCommands++;
562 auto variablesScope = std::make_unique<QgsExpressionContextScope>( tr(
"Model Variables" ) );
563 const QVariantMap modelVars = mModel->variables();
564 for (
auto it = modelVars.constBegin(); it != modelVars.constEnd(); ++it )
566 variablesScope->setVariable( it.key(), it.value() );
569 variablesContext.
appendScope( variablesScope.release() );
570 mVariablesEditor->setContext( &variablesContext );
571 mVariablesEditor->setEditableScopeIndex( 0 );
573 mBlockUndoCommands--;
576void QgsModelDesignerDialog::setDirty(
bool dirty )
582bool QgsModelDesignerDialog::validateSave( SaveAction action )
586 case QgsModelDesignerDialog::SaveAction::SaveAsFile:
588 case QgsModelDesignerDialog::SaveAction::SaveInProject:
589 if ( mNameEdit->text().trimmed().isEmpty() )
591 mMessageBar->pushWarning( QString(), tr(
"Please enter a model name before saving" ) );
600bool QgsModelDesignerDialog::checkForUnsavedChanges()
604 QMessageBox::StandardButton ret = QMessageBox::
605 question(
this, tr(
"Save Model?" ), tr(
"There are unsaved changes in this model. Do you want to keep those?" ), QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard, QMessageBox::Cancel );
608 case QMessageBox::Save:
609 return saveModel(
false );
611 case QMessageBox::Discard:
626 mLastResult.mergeWith( result );
628 mScene->setLastRunResult( mLastResult, mLayerStore );
631void QgsModelDesignerDialog::setModelName(
const QString &name )
633 mNameEdit->setText( name );
636void QgsModelDesignerDialog::zoomIn()
638 mView->setTransformationAnchor( QGraphicsView::NoAnchor );
639 QPointF point = mView->mapToScene( QPoint( mView->viewport()->width() / 2.0, mView->viewport()->height() / 2 ) );
641 const double factor = settings.
value( u
"/qgis/zoom_favor"_s, 2.0 ).toDouble();
642 mView->scale( factor, factor );
643 mView->centerOn( point );
646void QgsModelDesignerDialog::zoomOut()
648 mView->setTransformationAnchor( QGraphicsView::NoAnchor );
649 QPointF point = mView->mapToScene( QPoint( mView->viewport()->width() / 2.0, mView->viewport()->height() / 2 ) );
651 const double factor = 1.0 / settings.
value( u
"/qgis/zoom_favor"_s, 2.0 ).toDouble();
652 mView->scale( factor, factor );
653 mView->centerOn( point );
656void QgsModelDesignerDialog::zoomActual()
658 QPointF point = mView->mapToScene( QPoint( mView->viewport()->width() / 2.0, mView->viewport()->height() / 2 ) );
659 mView->resetTransform();
660 mView->scale( mScreenHelper->screenDpi() / 96, mScreenHelper->screenDpi() / 96 );
661 mView->centerOn( point );
664void QgsModelDesignerDialog::zoomFull()
666 QRectF totalRect = mView->scene()->itemsBoundingRect();
667 totalRect.adjust( -10, -10, 10, 10 );
668 mView->fitInView( totalRect, Qt::KeepAspectRatio );
671void QgsModelDesignerDialog::newModel()
673 if ( !checkForUnsavedChanges() )
676 auto alg = std::make_unique<QgsProcessingModelAlgorithm>();
678 setModel( alg.release() );
681void QgsModelDesignerDialog::exportToImage()
684 QString lastExportDir = settings.
value( u
"lastModelDesignerExportDir"_s, QDir::homePath(),
QgsSettings::App ).toString();
686 QString filename = QFileDialog::getSaveFileName(
this, tr(
"Save Model as Image" ), lastExportDir, tr(
"PNG files (*.png *.PNG)" ) );
690 if ( filename.isEmpty() )
695 const QFileInfo saveFileInfo( filename );
698 repaintModel(
false );
700 QRectF totalRect = mView->scene()->itemsBoundingRect();
701 totalRect.adjust( -10, -10, 10, 10 );
702 const QRectF imageRect = QRectF( 0, 0, totalRect.width(), totalRect.height() );
704 QImage img( totalRect.width(), totalRect.height(), QImage::Format_ARGB32_Premultiplied );
705 img.fill( Qt::white );
707 painter.setRenderHint( QPainter::Antialiasing );
708 painter.begin( &img );
709 mView->scene()->render( &painter, imageRect, totalRect );
712 img.save( filename );
715 ->pushMessage( QString(), tr(
"Successfully exported model as image to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( filename ).toString(), QDir::toNativeSeparators( filename ) ),
Qgis::MessageLevel::Success, 0 );
716 repaintModel(
true );
719void QgsModelDesignerDialog::exportToPdf()
722 QString lastExportDir = settings.
value( u
"lastModelDesignerExportDir"_s, QDir::homePath(),
QgsSettings::App ).toString();
724 QString filename = QFileDialog::getSaveFileName(
this, tr(
"Save Model as PDF" ), lastExportDir, tr(
"PDF files (*.pdf *.PDF)" ) );
728 if ( filename.isEmpty() )
733 const QFileInfo saveFileInfo( filename );
736 repaintModel(
false );
738 QRectF totalRect = mView->scene()->itemsBoundingRect();
739 totalRect.adjust( -10, -10, 10, 10 );
740 const QRectF printerRect = QRectF( 0, 0, totalRect.width(), totalRect.height() );
742 QPdfWriter pdfWriter( filename );
744 const double scaleFactor = 96 / 25.4;
746 QPageLayout pageLayout( QPageSize( totalRect.size() / scaleFactor, QPageSize::Millimeter ), QPageLayout::Portrait, QMarginsF( 0, 0, 0, 0 ) );
747 pageLayout.setMode( QPageLayout::FullPageMode );
748 pdfWriter.setPageLayout( pageLayout );
750 QPainter painter( &pdfWriter );
751 mView->scene()->render( &painter, printerRect, totalRect );
755 ->pushMessage( QString(), tr(
"Successfully exported model as PDF to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( filename ).toString(), QDir::toNativeSeparators( filename ) ),
Qgis::MessageLevel::Success, 0 );
756 repaintModel(
true );
759void QgsModelDesignerDialog::exportToSvg()
762 QString lastExportDir = settings.
value( u
"lastModelDesignerExportDir"_s, QDir::homePath(),
QgsSettings::App ).toString();
764 QString filename = QFileDialog::getSaveFileName(
this, tr(
"Save Model as SVG" ), lastExportDir, tr(
"SVG files (*.svg *.SVG)" ) );
768 if ( filename.isEmpty() )
773 const QFileInfo saveFileInfo( filename );
776 repaintModel(
false );
778 QRectF totalRect = mView->scene()->itemsBoundingRect();
779 totalRect.adjust( -10, -10, 10, 10 );
780 const QRectF svgRect = QRectF( 0, 0, totalRect.width(), totalRect.height() );
783 svg.setFileName( filename );
784 svg.setSize( QSize( totalRect.width(), totalRect.height() ) );
785 svg.setViewBox( svgRect );
786 svg.setTitle( mModel->displayName() );
788 QPainter painter( &svg );
789 mView->scene()->render( &painter, svgRect, totalRect );
793 ->pushMessage( QString(), tr(
"Successfully exported model as SVG to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( filename ).toString(), QDir::toNativeSeparators( filename ) ),
Qgis::MessageLevel::Success, 0 );
794 repaintModel(
true );
797void QgsModelDesignerDialog::exportAsPython()
800 QString lastExportDir = settings.
value( u
"lastModelDesignerExportDir"_s, QDir::homePath(),
QgsSettings::App ).toString();
802 QString filename = QFileDialog::getSaveFileName(
this, tr(
"Save Model as Python Script" ), lastExportDir, tr(
"Processing scripts (*.py *.PY)" ) );
806 if ( filename.isEmpty() )
811 const QFileInfo saveFileInfo( filename );
816 QFile outFile( filename );
817 if ( !outFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
821 QTextStream fout( &outFile );
826 ->pushMessage( QString(), tr(
"Successfully exported model as Python script to <a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( filename ).toString(), QDir::toNativeSeparators( filename ) ),
Qgis::MessageLevel::Success, 0 );
829void QgsModelDesignerDialog::toggleComments(
bool show )
833 repaintModel(
true );
836void QgsModelDesignerDialog::toggleFeatureCount(
bool show )
840 repaintModel(
true );
843void QgsModelDesignerDialog::updateWindowTitle()
845 QString title = tr(
"Model Designer" );
846 if ( !mModel->name().isEmpty() )
847 title = mModel->group().isEmpty() ? u
"%1: %2"_s.arg( title, mModel->name() ) : u
"%1: %2 - %3"_s.arg( title, mModel->group(), mModel->name() );
850 title.prepend(
'*' );
852 setWindowTitle( title );
855void QgsModelDesignerDialog::deleteSelected()
857 QList<QgsModelComponentGraphicItem *> items = mScene->selectedComponentItems();
861 if ( items.size() == 1 )
863 items.at( 0 )->deleteComponent();
867 std::sort( items.begin(), items.end(), []( QgsModelComponentGraphicItem *p1, QgsModelComponentGraphicItem *p2 ) {
872 if ( dynamic_cast<QgsModelCommentGraphicItem *>( p1 ) && dynamic_cast<QgsModelCommentGraphicItem *>( p2 ) )
874 else if ( dynamic_cast<QgsModelCommentGraphicItem *>( p1 ) )
876 else if ( dynamic_cast<QgsModelCommentGraphicItem *>( p2 ) )
879 else if ( dynamic_cast<QgsModelGroupBoxGraphicItem *>( p1 ) && dynamic_cast<QgsModelGroupBoxGraphicItem *>( p2 ) )
881 else if ( dynamic_cast<QgsModelGroupBoxGraphicItem *>( p1 ) )
883 else if ( dynamic_cast<QgsModelGroupBoxGraphicItem *>( p2 ) )
886 else if ( dynamic_cast<QgsModelOutputGraphicItem *>( p1 ) && dynamic_cast<QgsModelOutputGraphicItem *>( p2 ) )
888 else if ( dynamic_cast<QgsModelOutputGraphicItem *>( p1 ) )
890 else if ( dynamic_cast<QgsModelOutputGraphicItem *>( p2 ) )
893 else if ( dynamic_cast<QgsModelChildAlgorithmGraphicItem *>( p1 ) && dynamic_cast<QgsModelChildAlgorithmGraphicItem *>( p2 ) )
895 else if ( dynamic_cast<QgsModelChildAlgorithmGraphicItem *>( p1 ) )
897 else if ( dynamic_cast<QgsModelChildAlgorithmGraphicItem *>( p2 ) )
904 beginUndoCommand( tr(
"Delete Components" ) );
906 QVariant prevState = mModel->toVariant();
907 mBlockUndoCommands++;
908 mBlockRepaints =
true;
910 while ( !items.empty() )
912 QgsModelComponentGraphicItem *toDelete =
nullptr;
913 for ( QgsModelComponentGraphicItem *item : items )
915 if ( item->canDeleteComponent() )
928 toDelete->deleteComponent();
929 items.removeAll( toDelete );
934 mModel->loadVariant( prevState );
935 QMessageBox::warning(
937 QObject::tr(
"Could not remove components" ),
939 "Components depend on the selected items.\n"
940 "Try to remove them before trying deleting these components."
943 mBlockUndoCommands--;
944 mActiveCommand.reset();
948 mBlockUndoCommands--;
952 mBlockRepaints =
false;
956void QgsModelDesignerDialog::populateZoomToMenu()
959 for (
const QgsProcessingModelGroupBox &box : model()->groupBoxes() )
961 if ( QgsModelComponentGraphicItem *item = mScene->groupBoxItem( box.uuid() ) )
963 QAction *zoomAction =
new QAction( box.description(), mGroupMenu );
964 connect( zoomAction, &QAction::triggered,
this, [
this, item] {
965 QRectF groupRect = item->mapToScene( item->boundingRect() ).boundingRect();
966 groupRect.adjust( -10, -10, 10, 10 );
967 mView->fitInView( groupRect, Qt::KeepAspectRatio );
968 mView->centerOn( item );
970 mGroupMenu->addAction( zoomAction );
975void QgsModelDesignerDialog::setPanelVisibility(
bool hidden )
977 const QList<QDockWidget *> docks = findChildren<QDockWidget *>();
978 const QList<QTabBar *> tabBars = findChildren<QTabBar *>();
982 mPanelStatus.clear();
984 for ( QDockWidget *dock : docks )
986 mPanelStatus.insert( dock->windowTitle(), PanelStatus( dock->isVisible(),
false ) );
987 dock->setVisible(
false );
991 for ( QTabBar *tabBar : tabBars )
993 QString currentTabTitle = tabBar->tabText( tabBar->currentIndex() );
994 mPanelStatus[currentTabTitle].isActive =
true;
1000 for ( QDockWidget *dock : docks )
1002 if ( mPanelStatus.contains( dock->windowTitle() ) )
1004 dock->setVisible( mPanelStatus.value( dock->windowTitle() ).isVisible );
1009 for ( QTabBar *tabBar : tabBars )
1012 for (
int i = 0; i < tabBar->count(); ++i )
1014 QString tabTitle = tabBar->tabText( i );
1015 if ( mPanelStatus.contains( tabTitle ) && mPanelStatus.value( tabTitle ).isActive )
1017 tabBar->setCurrentIndex( i );
1021 mPanelStatus.clear();
1025void QgsModelDesignerDialog::editHelp()
1027 QgsProcessingHelpEditorDialog dialog(
this );
1028 dialog.setWindowTitle( tr(
"Edit Model Help" ) );
1029 dialog.setAlgorithm( mModel.get() );
1030 if ( dialog.exec() )
1032 beginUndoCommand( tr(
"Edit Model Help" ) );
1033 mModel->setHelpContent( dialog.helpContent() );
1038void QgsModelDesignerDialog::runSelectedSteps()
1040 QSet<QString> children;
1041 const QList<QgsModelComponentGraphicItem *> items = mScene->selectedComponentItems();
1042 for ( QgsModelComponentGraphicItem *item : items )
1044 if ( QgsProcessingModelChildAlgorithm *childAlgorithm =
dynamic_cast<QgsProcessingModelChildAlgorithm *
>( item->component() ) )
1046 children.insert( childAlgorithm->childId() );
1050 if ( children.isEmpty() )
1052 mMessageBar->pushWarning( QString(), tr(
"No steps are selected" ) );
1059void QgsModelDesignerDialog::runFromChild(
const QString &
id )
1061 QSet<QString> children = mModel->dependentChildAlgorithms(
id );
1062 children.insert(
id );
1066void QgsModelDesignerDialog::run(
const QSet<QString> &childAlgorithmSubset )
1069 const bool isValid = model()->validate( errors );
1072 QMessageBox messageBox;
1073 messageBox.setWindowTitle( tr(
"Model is Invalid" ) );
1074 messageBox.setIcon( QMessageBox::Icon::Warning );
1075 messageBox.setText( tr(
"This model is not valid and contains one or more issues. Are you sure you want to run it in this state?" ) );
1076 messageBox.setStandardButtons( QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::Cancel );
1077 messageBox.setDefaultButton( QMessageBox::StandardButton::Cancel );
1079 QString errorString;
1080 for (
const QString &error : std::as_const( errors ) )
1082 QString cleanedError = error;
1083 const thread_local QRegularExpression re( u
"<[^>]*>"_s );
1084 cleanedError.replace( re, QString() );
1085 errorString += u
"• %1\n"_s.arg( cleanedError );
1088 messageBox.setDetailedText( errorString );
1089 if ( messageBox.exec() == QMessageBox::StandardButton::Cancel )
1093 if ( !childAlgorithmSubset.isEmpty() )
1095 for (
const QString &child : childAlgorithmSubset )
1098 const QSet<QString> requirements = mModel->dependsOnChildAlgorithms( child );
1099 for (
const QString &requirement : requirements )
1101 if ( !mLastResult.executedChildIds().contains( requirement ) )
1103 QMessageBox messageBox;
1104 messageBox.setWindowTitle( tr(
"Run Model" ) );
1105 messageBox.setIcon( QMessageBox::Icon::Warning );
1106 messageBox.setText( tr(
"Prerequisite parts of this model have not yet been run (try running the full model first)." ) );
1107 messageBox.setStandardButtons( QMessageBox::StandardButton::Ok );
1115 std::unique_ptr<QgsProcessingAlgorithmDialogBase> dialog( createExecutionDialog() );
1120 dialog->setParameters( mModel->designerParameterValues() );
1122 connect( dialog.get(), &QgsProcessingAlgorithmDialogBase::algorithmAboutToRun,
this, [
this, &childAlgorithmSubset](
QgsProcessingContext *context ) {
1123 if ( !childAlgorithmSubset.empty() )
1126 auto modelConfig = std::make_unique<QgsProcessingModelInitialRunConfig>();
1127 modelConfig->setChildAlgorithmSubset( childAlgorithmSubset );
1128 modelConfig->setPreviouslyExecutedChildAlgorithms( mLastResult.executedChildIds() );
1129 modelConfig->setInitialChildInputs( mLastResult.rawChildInputs() );
1130 modelConfig->setInitialChildOutputs( mLastResult.rawChildOutputs() );
1134 const QMap<QString, QgsMapLayer *> previousOutputLayers = mLayerStore.temporaryLayerStore()->mapLayers();
1135 auto previousResultStore = std::make_unique<QgsMapLayerStore>();
1136 for ( auto it = previousOutputLayers.constBegin(); it != previousOutputLayers.constEnd(); ++it )
1138 std::unique_ptr<QgsMapLayer> clone( it.value()->clone() );
1139 clone->setId( it.value()->id() );
1140 previousResultStore->addMapLayer( clone.release() );
1142 previousResultStore->moveToThread( nullptr );
1143 modelConfig->setPreviousLayerStore( std::move( previousResultStore ) );
1144 context->setModelInitialRunConfig( std::move( modelConfig ) );
1148 connect( dialog.get(), &QgsProcessingAlgorithmDialogBase::algorithmFinished,
this, [
this, &dialog](
bool,
const QVariantMap & ) {
1149 QgsProcessingContext *context = dialog->processingContext();
1151 mLayerStore.temporaryLayerStore()->removeAllMapLayers();
1152 mLayerStore.takeResultsFrom( *context );
1154 mModel->setDesignerParameterValues( dialog->createProcessingParameters( QgsProcessingParametersGenerator::Flag::SkipDefaultValueParameters ) );
1155 setLastRunResult( context->modelResult() );
1161void QgsModelDesignerDialog::showChildAlgorithmOutputs(
const QString &childId )
1163 const QString childDescription = mModel->childAlgorithm( childId ).description();
1166 const QVariantMap childAlgorithmOutputs = result.
outputs();
1167 if ( childAlgorithmOutputs.isEmpty() )
1169 mMessageBar->pushWarning( QString(), tr(
"No results are available for %1" ).arg( childDescription ) );
1176 mMessageBar->pushCritical( QString(), tr(
"Results cannot be shown for an invalid model component" ) );
1180 const QList<const QgsProcessingParameterDefinition *> outputParams =
algorithm->destinationParameterDefinitions();
1181 if ( outputParams.isEmpty() )
1184 QgsDebugError(
"Cannot show results for algorithms with no outputs" );
1188 bool foundResults =
false;
1191 const QVariant output = childAlgorithmOutputs.value( outputParam->name() );
1192 if ( !output.isValid() )
1195 if ( output.type() == QVariant::String )
1199 QgsDebugMsgLevel( u
"Loading previous result for %1: %2"_s.arg( outputParam->name(), output.toString() ), 2 );
1201 std::unique_ptr<QgsMapLayer> layer( resultLayer->clone() );
1204 if ( outputParams.size() > 1 )
1205 baseName = tr(
"%1 — %2" ).arg( childDescription, outputParam->name() );
1207 baseName = childDescription;
1211 QString name = baseName;
1216 name = tr(
"%1 (%2)" ).arg( baseName ).arg( counter );
1219 layer->setName( name );
1222 foundResults =
true;
1227 QgsDebugError( u
"Could not load previous result for %1: %2"_s.arg( outputParam->name(), output.toString() ) );
1232 if ( !foundResults )
1234 mMessageBar->pushWarning( QString(), tr(
"No results are available for %1" ).arg( childDescription ) );
1239void QgsModelDesignerDialog::showChildAlgorithmLog(
const QString &childId )
1241 const QString childDescription = mModel->childAlgorithm( childId ).description();
1244 if ( result.
htmlLog().isEmpty() )
1246 mMessageBar->pushWarning( QString(), tr(
"No log is available for %1" ).arg( childDescription ) );
1251 m.setWindowTitle( childDescription );
1252 m.setCheckBoxVisible(
false );
1253 m.setMessageAsHtml( result.
htmlLog() );
1257void QgsModelDesignerDialog::onItemFocused( QgsModelComponentGraphicItem *item )
1264 if ( !item || !item->component() )
1266 mConfigWidget->showComponentConfig(
nullptr, *context, widgetContext );
1270 mConfigWidget->showComponentConfig( item->component(), *context, widgetContext );
1274void QgsModelDesignerDialog::validate()
1277 if ( model()->validate( issues ) )
1279 mMessageBar->pushSuccess( QString(), tr(
"Model is valid!" ) );
1284 QPushButton *detailsButton =
new QPushButton( tr(
"Details" ) );
1285 connect( detailsButton, &QPushButton::clicked, detailsButton, [detailsButton, issues] {
1287 dialog->
setTitle( tr(
"Model is Invalid" ) );
1289 QString longMessage = tr(
"<p>This model is not valid:</p>" ) + u
"<ul>"_s;
1290 for (
const QString &issue : issues )
1292 longMessage += u
"<li>%1</li>"_s.arg( issue );
1294 longMessage +=
"</ul>"_L1;
1299 messageWidget->layout()->addWidget( detailsButton );
1300 mMessageBar->clearWidgets();
1305void QgsModelDesignerDialog::reorderInputs()
1307 QgsModelInputReorderDialog dlg(
this );
1308 dlg.setModel( mModel.get() );
1311 const QStringList inputOrder = dlg.inputOrder();
1312 beginUndoCommand( tr(
"Reorder Inputs" ) );
1313 mModel->setParameterOrder( inputOrder );
1318void QgsModelDesignerDialog::reorderOutputs()
1320 QgsModelOutputReorderDialog dlg(
this );
1321 dlg.setModel( mModel.get() );
1324 const QStringList outputOrder = dlg.outputOrder();
1325 beginUndoCommand( tr(
"Reorder Outputs" ) );
1326 mModel->setOutputOrder( outputOrder );
1327 mModel->setOutputGroup( dlg.outputGroup() );
1332bool QgsModelDesignerDialog::isDirty()
const
1334 return mHasChanged && mUndoStack->index() != -1;
1337void QgsModelDesignerDialog::fillInputsTree()
1340 auto parametersItem = std::make_unique<QTreeWidgetItem>();
1341 parametersItem->setText( 0, tr(
"Parameters" ) );
1344 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
1351 auto paramItem = std::make_unique<QTreeWidgetItem>();
1352 paramItem->setText( 0, param->name() );
1353 paramItem->setData( 0, Qt::UserRole, param->id() );
1354 paramItem->setIcon( 0, icon );
1355 paramItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
1356 paramItem->setToolTip( 0, param->description() );
1357 parametersItem->addChild( paramItem.release() );
1360 mInputsTreeWidget->addTopLevelItem( parametersItem.release() );
1361 mInputsTreeWidget->topLevelItem( 0 )->setExpanded(
true );
1369QgsModelChildDependenciesWidget::QgsModelChildDependenciesWidget( QWidget *parent, QgsProcessingModelAlgorithm *model,
const QString &childId )
1372 , mChildId( childId )
1374 QHBoxLayout *hl =
new QHBoxLayout();
1375 hl->setContentsMargins( 0, 0, 0, 0 );
1377 mLineEdit =
new QLineEdit();
1378 mLineEdit->setEnabled(
false );
1379 hl->addWidget( mLineEdit, 1 );
1381 mToolButton =
new QToolButton();
1382 mToolButton->setText( QString( QChar( 0x2026 ) ) );
1383 hl->addWidget( mToolButton );
1387 mLineEdit->setText( tr(
"%1 dependencies selected" ).arg( 0 ) );
1389 connect( mToolButton, &QToolButton::clicked,
this, &QgsModelChildDependenciesWidget::showDialog );
1392void QgsModelChildDependenciesWidget::setValue(
const QList<QgsProcessingModelChildDependency> &value )
1396 updateSummaryText();
1399void QgsModelChildDependenciesWidget::showDialog()
1401 const QList<QgsProcessingModelChildDependency> available = mModel->availableDependenciesForChildAlgorithm( mChildId );
1403 QVariantList availableOptions;
1404 for (
const QgsProcessingModelChildDependency &dep : available )
1405 availableOptions << QVariant::fromValue( dep );
1406 QVariantList selectedOptions;
1407 for (
const QgsProcessingModelChildDependency &dep : mValue )
1408 selectedOptions << QVariant::fromValue( dep );
1413 QgsProcessingMultipleSelectionPanelWidget *widget =
new QgsProcessingMultipleSelectionPanelWidget( availableOptions, selectedOptions );
1414 widget->setPanelTitle( tr(
"Algorithm Dependencies" ) );
1416 widget->setValueFormatter( [
this](
const QVariant &v ) -> QString {
1417 const QgsProcessingModelChildDependency dep = v.value<QgsProcessingModelChildDependency>();
1419 const QString description = mModel->childAlgorithm( dep.childId ).description();
1420 if ( dep.conditionalBranch.isEmpty() )
1423 return tr(
"Condition “%1” from algorithm “%2”" ).arg( dep.conditionalBranch, description );
1426 connect( widget, &QgsProcessingMultipleSelectionPanelWidget::selectionChanged,
this, [
this, widget]() {
1427 QList<QgsProcessingModelChildDependency> res;
1428 for (
const QVariant &v : widget->selectedOptions() )
1430 res << v.value<QgsProcessingModelChildDependency>();
1439void QgsModelChildDependenciesWidget::updateSummaryText()
1441 mLineEdit->setText( tr(
"%n dependencies selected",
nullptr, mValue.count() ) );
@ ExposeToModeler
Is this parameter available in the modeler. Is set to on by default.
@ Warning
Warning message.
@ Critical
Critical/error message.
@ Success
Used for reporting a successful operation.
@ ModelDebug
Model debug level logging. Includes verbose logging and other outputs useful for debugging models.
static QgsProcessingRegistry * processingRegistry()
Returns the application's processing registry, used for managing processing providers,...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
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...
Base class for all map layer types.
Represents an item shown within a QgsMessageBar widget.
A bar for displaying non-blocking messages to the user.
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=nullptr)
Creates message bar item widget containing a message text to be displayed on the bar.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
A generic message view for displaying QGIS messages.
void setMessage(const QString &message, Qgis::StringFormat format) override
Sets message, it won't be displayed until.
void setTitle(const QString &title) override
Sets title for the messages.
void showMessage(bool blocking=true) override
display the message to the user and deletes itself
Abstract base class for processing algorithms.
An interface for objects which can create Processing contexts.
Contains information about the context in which a processing algorithm is executed.
Encapsulates the results of running a child algorithm within a model.
QString htmlLog() const
Returns the HTML formatted contents of logged messages which occurred while running the child.
QVariantMap outputs() const
Returns the outputs generated by the child algorithm.
Encapsulates the results of running a Processing model.
QMap< QString, QgsProcessingModelChildAlgorithmResult > childResults() const
Returns the map of child algorithm results.
Base class for the definition of processing parameters.
Makes metadata of processing parameters available.
Contains settings which reflect the context in which a Processing parameter widget is shown.
void setModelDesignerDialog(QgsModelDesignerDialog *dialog)
Sets the associated model designer dialog, if applicable.
void registerProcessingContextGenerator(QgsProcessingContextGenerator *generator)
Registers a Processing context generator class that will be used to retrieve a Processing context for...
QList< QgsProcessingParameterType * > parameterTypes() const
Returns a list with all known parameter types.
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType, QgsProcessing::LayerOptionsFlags flags=QgsProcessing::LayerOptionsFlags())
Interprets a string as a map layer within the supplied context.
@ PythonQgsProcessingAlgorithmSubclass
Full Python QgsProcessingAlgorithm subclass.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsMapLayer * addMapLayer(QgsMapLayer *mapLayer, bool addToLegend=true, bool takeOwnership=true)
Add a layer to the map of loaded layers.
A utility class for dynamic handling of changes to screen properties.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)