From e2d6b54f357ef27743b747cbb54f108215bea443 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 19 Apr 2024 11:16:24 +1000 Subject: [PATCH] Add "View Log" action for child algorithms This action shows the log of that child step, regardless of whether or not it failed. This is handy for debugging model errors after testing, when you've already closed the algorithm window...! --- .../qgsmodelcomponentgraphicitem.sip.in | 7 +++++ .../models/qgsmodelgraphicsscene.sip.in | 7 +++++ .../qgsmodelcomponentgraphicitem.sip.in | 7 +++++ .../models/qgsmodelgraphicsscene.sip.in | 7 +++++ src/core/processing/qgsprocessingfeedback.cpp | 4 ++- .../models/qgsmodelcomponentgraphicitem.cpp | 27 +++++++++++++++++-- .../models/qgsmodelcomponentgraphicitem.h | 7 +++++ .../models/qgsmodeldesignerdialog.cpp | 19 +++++++++++++ .../models/qgsmodeldesignerdialog.h | 1 + .../models/qgsmodelgraphicsscene.cpp | 4 +++ .../processing/models/qgsmodelgraphicsscene.h | 7 +++++ 11 files changed, 94 insertions(+), 3 deletions(-) diff --git a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in index e8265886976..86f58913e85 100644 --- a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in +++ b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in @@ -407,6 +407,13 @@ Sets the ``results`` obtained for this child algorithm for the last model execut %Docstring Emitted when the user opts to view previous results from this child algorithm. +.. versionadded:: 3.38 +%End + + void showLog(); +%Docstring +Emitted when the user opts to view the previous log from this child algorithm. + .. versionadded:: 3.38 %End diff --git a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in index b97e646a511..5e0271b16f8 100644 --- a/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in +++ b/python/PyQt6/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in @@ -178,6 +178,13 @@ If ``None``, no item is selected. %Docstring Emitted when the user opts to view previous results from the child algorithm with matching ID. +.. versionadded:: 3.38 +%End + + void showLog( const QString &childId ); +%Docstring +Emitted when the user opts to view the previous log from the child algorithm with matching ID. + .. versionadded:: 3.38 %End diff --git a/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in b/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in index 72a74d0a9ae..105283cfb8a 100644 --- a/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in +++ b/python/gui/auto_generated/processing/models/qgsmodelcomponentgraphicitem.sip.in @@ -407,6 +407,13 @@ Sets the ``results`` obtained for this child algorithm for the last model execut %Docstring Emitted when the user opts to view previous results from this child algorithm. +.. versionadded:: 3.38 +%End + + void showLog(); +%Docstring +Emitted when the user opts to view the previous log from this child algorithm. + .. versionadded:: 3.38 %End diff --git a/python/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in b/python/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in index 230cd0d7584..91a6a9e6e90 100644 --- a/python/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in +++ b/python/gui/auto_generated/processing/models/qgsmodelgraphicsscene.sip.in @@ -178,6 +178,13 @@ If ``None``, no item is selected. %Docstring Emitted when the user opts to view previous results from the child algorithm with matching ID. +.. versionadded:: 3.38 +%End + + void showLog( const QString &childId ); +%Docstring +Emitted when the user opts to view the previous log from the child algorithm with matching ID. + .. versionadded:: 3.38 %End diff --git a/src/core/processing/qgsprocessingfeedback.cpp b/src/core/processing/qgsprocessingfeedback.cpp index af3bfeb7c0a..06c26d72f14 100644 --- a/src/core/processing/qgsprocessingfeedback.cpp +++ b/src/core/processing/qgsprocessingfeedback.cpp @@ -33,8 +33,10 @@ QgsProcessingFeedback::QgsProcessingFeedback( bool logFeedback ) } -void QgsProcessingFeedback::setProgressText( const QString & ) +void QgsProcessingFeedback::setProgressText( const QString &text ) { + mHtmlLog.append( text.toHtmlEscaped().replace( '\n', QLatin1String( "
" ) ) + QStringLiteral( "
" ) ); + mTextLog.append( text + '\n' ); } void QgsProcessingFeedback::log( const QString &htmlMessage, const QString &textMessage ) diff --git a/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp b/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp index 251fa4c4dbb..a9b0f6da59d 100644 --- a/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp +++ b/src/gui/processing/models/qgsmodelcomponentgraphicitem.cpp @@ -901,10 +901,33 @@ void QgsModelChildAlgorithmGraphicItem::contextMenuEvent( QGraphicsSceneContextM QAction *viewOutputLayersAction = popupmenu->addAction( QObject::tr( "View Output Layers" ) ); viewOutputLayersAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionShowSelectedLayers.svg" ) ) ); connect( viewOutputLayersAction, &QAction::triggered, this, &QgsModelChildAlgorithmGraphicItem::showPreviousResults ); - if ( mResults.outputs().empty() ) - viewOutputLayersAction->setEnabled( false ); + // enable this action only when the child succeeded + switch ( mResults.executionStatus() ) + { + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::NotExecuted: + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::Failed: + viewOutputLayersAction->setEnabled( false ); + break; + + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::Success: + break; + } } } + + QAction *viewLogAction = popupmenu->addAction( QObject::tr( "View Log…" ) ); + connect( viewLogAction, &QAction::triggered, this, &QgsModelChildAlgorithmGraphicItem::showLog ); + // enable this action even when the child failed + switch ( mResults.executionStatus() ) + { + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::NotExecuted: + viewLogAction->setEnabled( false ); + break; + + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::Success: + case Qgis::ProcessingModelChildAlgorithmExecutionStatus::Failed: + break; + } } popupmenu->exec( event->screenPos() ); diff --git a/src/gui/processing/models/qgsmodelcomponentgraphicitem.h b/src/gui/processing/models/qgsmodelcomponentgraphicitem.h index 27849685eb9..296619661c7 100644 --- a/src/gui/processing/models/qgsmodelcomponentgraphicitem.h +++ b/src/gui/processing/models/qgsmodelcomponentgraphicitem.h @@ -475,6 +475,13 @@ class GUI_EXPORT QgsModelChildAlgorithmGraphicItem : public QgsModelComponentGra */ void showPreviousResults(); + /** + * Emitted when the user opts to view the previous log from this child algorithm. + * + * \since QGIS 3.38 + */ + void showLog(); + protected: QColor fillColor( State state ) const override; diff --git a/src/gui/processing/models/qgsmodeldesignerdialog.cpp b/src/gui/processing/models/qgsmodeldesignerdialog.cpp index e23dd69819e..d6271795ccd 100644 --- a/src/gui/processing/models/qgsmodeldesignerdialog.cpp +++ b/src/gui/processing/models/qgsmodeldesignerdialog.cpp @@ -513,6 +513,7 @@ void QgsModelDesignerDialog::setModelScene( QgsModelGraphicsScene *scene ) connect( mScene, &QgsModelGraphicsScene::componentAboutToChange, this, [ = ]( const QString & description, int id ) { beginUndoCommand( description, id ); } ); connect( mScene, &QgsModelGraphicsScene::componentChanged, this, [ = ] { endUndoCommand(); } ); connect( mScene, &QgsModelGraphicsScene::showPreviousResults, this, &QgsModelDesignerDialog::showPreviousResults ); + connect( mScene, &QgsModelGraphicsScene::showLog, this, &QgsModelDesignerDialog::showLog ); mView->centerOn( center ); @@ -1120,6 +1121,24 @@ void QgsModelDesignerDialog::showPreviousResults( const QString &childId ) } } +void QgsModelDesignerDialog::showLog( const QString &childId ) +{ + const QString childDescription = mModel->childAlgorithm( childId ).description(); + + const QgsProcessingModelChildAlgorithmResult result = mChildResults.value( childId ); + if ( result.htmlLog().isEmpty() ) + { + mMessageBar->pushWarning( QString(), tr( "No log is available for %1" ).arg( childDescription ) ); + return; + } + + QgsMessageViewer m( this, QgsGuiUtils::ModalDialogFlags, false ); + m.setWindowTitle( childDescription ); + m.setCheckBoxVisible( false ); + m.setMessageAsHtml( result.htmlLog() ); + m.exec(); +} + void QgsModelDesignerDialog::validate() { QStringList issues; diff --git a/src/gui/processing/models/qgsmodeldesignerdialog.h b/src/gui/processing/models/qgsmodeldesignerdialog.h index 74ba526497f..462e3aeb092 100644 --- a/src/gui/processing/models/qgsmodeldesignerdialog.h +++ b/src/gui/processing/models/qgsmodeldesignerdialog.h @@ -186,6 +186,7 @@ class GUI_EXPORT QgsModelDesignerDialog : public QMainWindow, public Ui::QgsMode void editHelp(); void run(); void showPreviousResults( const QString &childId ); + void showLog( const QString &childId ); private: diff --git a/src/gui/processing/models/qgsmodelgraphicsscene.cpp b/src/gui/processing/models/qgsmodelgraphicsscene.cpp index 2ac1a0aeb52..8cede3fe365 100644 --- a/src/gui/processing/models/qgsmodelgraphicsscene.cpp +++ b/src/gui/processing/models/qgsmodelgraphicsscene.cpp @@ -149,6 +149,10 @@ void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, Qgs { emit showPreviousResults( childId ); } ); + connect( item, &QgsModelChildAlgorithmGraphicItem::showLog, this, [this, childId] + { + emit showLog( childId ); + } ); addCommentItemForComponent( model, it.value(), item ); } diff --git a/src/gui/processing/models/qgsmodelgraphicsscene.h b/src/gui/processing/models/qgsmodelgraphicsscene.h index 84044323a68..e3fa979cf72 100644 --- a/src/gui/processing/models/qgsmodelgraphicsscene.h +++ b/src/gui/processing/models/qgsmodelgraphicsscene.h @@ -194,6 +194,13 @@ class GUI_EXPORT QgsModelGraphicsScene : public QGraphicsScene */ void showPreviousResults( const QString &childId ); + /** + * Emitted when the user opts to view the previous log from the child algorithm with matching ID. + * + * \since QGIS 3.38 + */ + void showLog( const QString &childId ); + protected: /**