Skip to content

Commit

Permalink
[processing] Instead of a hidden parameter for verbose model logging,
Browse files Browse the repository at this point in the history
add an explicit log level getter/setter to QgsProcessingContext which
algorithms can use to determine an appropriate level of feedback
to push to users.

Initially the verbose log only triggers the full verbose output
of model executions (which is also used when running models through
the model designer), but the intention is that more algorithms
will fine tune their output based on the logging level.

qgis_process also gains a new --verbose switch to enable verbose
log output.
  • Loading branch information
nyalldawson committed Feb 19, 2021
1 parent 9489afe commit c8d6149
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 18 deletions.
24 changes: 24 additions & 0 deletions python/core/auto_generated/processing/qgsprocessingcontext.sip.in
Expand Up @@ -34,6 +34,12 @@ expression context.
typedef QFlags<QgsProcessingContext::Flag> Flags;


enum LogLevel
{
DefaultLevel,
Verbose,
};

QgsProcessingContext();
%Docstring
Constructor for QgsProcessingContext.
Expand Down Expand Up @@ -558,6 +564,24 @@ function will be used when creating these outputs.
.. seealso:: :py:func:`setPreferredVectorFormat`

.. versionadded:: 3.10
%End

LogLevel logLevel() const;
%Docstring
Returns the logging level for algorithms to use when pushing feedback messages to users.

.. seealso:: :py:func:`setLogLevel`

.. versionadded:: 3.20
%End

void setLogLevel( LogLevel level );
%Docstring
Sets the logging ``level`` for algorithms to use when pushing feedback messages to users.

.. seealso:: :py:func:`logLevel`

.. versionadded:: 3.20
%End

private:
Expand Down
Expand Up @@ -107,6 +107,24 @@ the given ``format``.
.. seealso:: :py:func:`saveLog`

.. versionadded:: 3.2
%End

QgsProcessingContext::LogLevel logLevel() const;
%Docstring
Returns the logging level to use when running algorithms from the dialog.

.. seealso:: :py:func:`setLogLevel`

.. versionadded:: 3.20
%End

void setLogLevel( QgsProcessingContext::LogLevel level );
%Docstring
Sets the logging ``level`` to use when running algorithms from the dialog.

.. seealso:: :py:func:`logLevel`

.. versionadded:: 3.20
%End

public slots:
Expand Down
1 change: 1 addition & 0 deletions python/plugins/processing/gui/AlgorithmDialog.py
Expand Up @@ -119,6 +119,7 @@ def createProcessingParameters(self, include_default=True):
def runAlgorithm(self):
self.feedback = self.createFeedback()
self.context = dataobjects.createContext(self.feedback)
self.context.setLogLevel(self.logLevel())

checkCRS = ProcessingConfig.getSetting(ProcessingConfig.WARN_UNMATCHING_CRS)
try:
Expand Down
2 changes: 2 additions & 0 deletions python/plugins/processing/modeler/ModelerDialog.py
Expand Up @@ -41,6 +41,7 @@
QgsProject,
QgsProcessingModelParameter,
QgsSettings,
QgsProcessingContext
)
from qgis.gui import (QgsProcessingParameterDefinitionDialog,
QgsProcessingParameterWidgetContext,
Expand Down Expand Up @@ -152,6 +153,7 @@ def on_finished(successful, results):
self.setLastRunChildAlgorithmInputs(dlg.results().get('CHILD_INPUTS', {}))

dlg = AlgorithmDialog(self.model().create(), parent=self)
dlg.setLogLevel(QgsProcessingContext.Verbose)
dlg.setParameters(self.model().designerParameterValues())
dlg.algorithmFinished.connect(on_finished)
dlg.exec_()
Expand Down
13 changes: 2 additions & 11 deletions src/core/processing/models/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -42,9 +42,6 @@ QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm( const QString &name, c

void QgsProcessingModelAlgorithm::initAlgorithm( const QVariantMap & )
{
std::unique_ptr< QgsProcessingParameterBoolean > verboseLog = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "VERBOSE_LOG" ), QObject::tr( "Verbose logging" ), false, true );
verboseLog->setFlags( verboseLog->flags() | QgsProcessingParameterDefinition::FlagHidden );
addParameter( verboseLog.release() );
}

QString QgsProcessingModelAlgorithm::name() const
Expand Down Expand Up @@ -288,7 +285,7 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
QVariantMap childResults;
QVariantMap childInputs;

const bool verboseLog = parameterAsBool( parameters, QStringLiteral( "VERBOSE_LOG" ), context );
const bool verboseLog = context.logLevel() == QgsProcessingContext::Verbose;

QVariantMap finalResults;
QSet< QString > executed;
Expand Down Expand Up @@ -1348,9 +1345,6 @@ QVariant QgsProcessingModelAlgorithm::toVariant() const
QVariantMap paramDefMap;
for ( const QgsProcessingParameterDefinition *def : mParameters )
{
if ( def->name() == QLatin1String( "VERBOSE_LOG" ) )
continue;

paramDefMap.insert( def->name(), def->toVariantMap() );
}
map.insert( QStringLiteral( "parameterDefinitions" ), paramDefMap );
Expand Down Expand Up @@ -1948,10 +1942,7 @@ void QgsProcessingModelAlgorithm::setVariables( const QVariantMap &variables )

QVariantMap QgsProcessingModelAlgorithm::designerParameterValues() const
{
QVariantMap res = mDesignerParameterValues;
// when running through the designer, we show a detailed verbose log to aid in model debugging
res.insert( QStringLiteral( "VERBOSE_LOG" ), true );
return res;
return mDesignerParameterValues;
}

///@endcond
10 changes: 10 additions & 0 deletions src/core/processing/qgsprocessingcontext.cpp
Expand Up @@ -128,6 +128,16 @@ QgsMapLayer *QgsProcessingContext::takeResultLayer( const QString &id )
return tempLayerStore.takeMapLayer( tempLayerStore.mapLayer( id ) );
}

QgsProcessingContext::LogLevel QgsProcessingContext::logLevel() const
{
return mLogLevel;
}

void QgsProcessingContext::setLogLevel( LogLevel level )
{
mLogLevel = level;
}

QgsDateTimeRange QgsProcessingContext::currentTimeRange() const
{
return mCurrentTimeRange;
Expand Down
30 changes: 30 additions & 0 deletions src/core/processing/qgsprocessingcontext.h
Expand Up @@ -51,6 +51,17 @@ class CORE_EXPORT QgsProcessingContext
};
Q_DECLARE_FLAGS( Flags, Flag )

/**
* Logging level for algorithms to use when pushing feedback messages.
*
* \since QGIS 3.20
*/
enum LogLevel
{
DefaultLevel = 0, //!< Default logging level
Verbose, //!< Verbose logging
};

/**
* Constructor for QgsProcessingContext.
*/
Expand Down Expand Up @@ -84,6 +95,7 @@ class CORE_EXPORT QgsProcessingContext
mEllipsoid = other.mEllipsoid;
mDistanceUnit = other.mDistanceUnit;
mAreaUnit = other.mAreaUnit;
mLogLevel = other.mLogLevel;
}

/**
Expand Down Expand Up @@ -625,6 +637,22 @@ class CORE_EXPORT QgsProcessingContext
*/
void setPreferredRasterFormat( const QString &format ) { mPreferredRasterFormat = format; }

/**
* Returns the logging level for algorithms to use when pushing feedback messages to users.
*
* \see setLogLevel()
* \since QGIS 3.20
*/
LogLevel logLevel() const;

/**
* Sets the logging \a level for algorithms to use when pushing feedback messages to users.
*
* \see logLevel()
* \since QGIS 3.20
*/
void setLogLevel( LogLevel level );

private:

QgsProcessingContext::Flags mFlags = QgsProcessingContext::Flags();
Expand Down Expand Up @@ -654,6 +682,8 @@ class CORE_EXPORT QgsProcessingContext
QString mPreferredVectorFormat;
QString mPreferredRasterFormat;

LogLevel mLogLevel = DefaultLevel;

#ifdef SIP_RUN
QgsProcessingContext( const QgsProcessingContext &other );
#endif
Expand Down
10 changes: 10 additions & 0 deletions src/gui/processing/qgsprocessingalgorithmdialogbase.cpp
Expand Up @@ -399,6 +399,16 @@ void QgsProcessingAlgorithmDialogBase::closeClicked()
close();
}

QgsProcessingContext::LogLevel QgsProcessingAlgorithmDialogBase::logLevel() const
{
return mLogLevel;
}

void QgsProcessingAlgorithmDialogBase::setLogLevel( QgsProcessingContext::LogLevel level )
{
mLogLevel = level;
}

void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
{
setInfo( error, true );
Expand Down
18 changes: 18 additions & 0 deletions src/gui/processing/qgsprocessingalgorithmdialogbase.h
Expand Up @@ -163,6 +163,22 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, public QgsPr
*/
void saveLogToFile( const QString &path, LogFormat format = FormatPlainText );

/**
* Returns the logging level to use when running algorithms from the dialog.
*
* \see setLogLevel()
* \since QGIS 3.20
*/
QgsProcessingContext::LogLevel logLevel() const;

/**
* Sets the logging \a level to use when running algorithms from the dialog.
*
* \see logLevel()
* \since QGIS 3.20
*/
void setLogLevel( QgsProcessingContext::LogLevel level );

public slots:

/**
Expand Down Expand Up @@ -399,6 +415,8 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, public QgsPr

bool mHelpCollapsed = false;

QgsProcessingContext::LogLevel mLogLevel = QgsProcessingContext::DefaultLevel;

QString formatHelp( QgsProcessingAlgorithm *algorithm );
void scrollToBottomOfLog();
void processEvents();
Expand Down
16 changes: 13 additions & 3 deletions src/process/qgsprocess.cpp
Expand Up @@ -240,6 +240,14 @@ int QgsProcessingExec::run( const QStringList &constArgs )
args.removeAt( jsonIndex );
}

const int verboseIndex = args.indexOf( QLatin1String( "--verbose" ) );
QgsProcessingContext::LogLevel logLevel = QgsProcessingContext::DefaultLevel;
if ( verboseIndex >= 0 )
{
logLevel = QgsProcessingContext::Verbose;
args.removeAt( verboseIndex );
}

if ( args.size() == 1 )
{
showUsage( args.at( 0 ) );
Expand Down Expand Up @@ -418,7 +426,7 @@ int QgsProcessingExec::run( const QStringList &constArgs )
}
}

return execute( algId, params, ellipsoid, distanceUnit, areaUnit, useJson, projectPath );
return execute( algId, params, ellipsoid, distanceUnit, areaUnit, logLevel, useJson, projectPath );
}
else
{
Expand All @@ -433,9 +441,10 @@ void QgsProcessingExec::showUsage( const QString &appName )

msg << "QGIS Processing Executor - " << VERSION << " '" << RELEASE_NAME << "' ("
<< Qgis::version() << ")\n"
<< "Usage: " << appName << " [--json] [command] [algorithm id or path to model file] [parameters]\n"
<< "Usage: " << appName << " [--json] [--verbose] [command] [algorithm id or path to model file] [parameters]\n"
<< "\nOptions:\n"
<< "\t--json\t\tOutput results as JSON objects\n"
<< "\t--verbose\tOutput verbose logs\n"
<< "\nAvailable commands:\n"
<< "\tplugins\t\tlist available and active plugins\n"
<< "\tplugins enable\tenables an installed plugin. The plugin name must be specified, e.g. \"plugins enable cartography_tools\"\n"
Expand Down Expand Up @@ -822,7 +831,7 @@ int QgsProcessingExec::showAlgorithmHelp( const QString &id, bool useJson )
return 0;
}

int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, bool useJson, const QString &projectPath )
int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, QgsProcessingContext::LogLevel logLevel, bool useJson, const QString &projectPath )
{
QVariantMap json;
if ( useJson )
Expand Down Expand Up @@ -952,6 +961,7 @@ int QgsProcessingExec::execute( const QString &id, const QVariantMap &params, co
context.setDistanceUnit( distanceUnit );
context.setAreaUnit( areaUnit );
context.setProject( project.get() );
context.setLogLevel( logLevel );

const QgsProcessingParameterDefinitions defs = alg->parameterDefinitions();
QList< const QgsProcessingParameterDefinition * > missingParams;
Expand Down
2 changes: 2 additions & 0 deletions src/process/qgsprocess.h
Expand Up @@ -21,6 +21,7 @@
#include "qgspythonrunner.h"
#include "qgspythonutils.h"
#include "qgsunittypes.h"
#include "qgsprocessingcontext.h"
#include <QElapsedTimer>

class QgsApplication;
Expand Down Expand Up @@ -81,6 +82,7 @@ class QgsProcessingExec
const QString &ellipsoid,
QgsUnitTypes::DistanceUnit distanceUnit,
QgsUnitTypes::AreaUnit areaUnit,
QgsProcessingContext::LogLevel logLevel,
bool useJson,
const QString &projectPath = QString() );

Expand Down
7 changes: 4 additions & 3 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -989,6 +989,9 @@ void TestQgsProcessing::context()
QCOMPARE( context.distanceUnit(), QgsUnitTypes::DistanceFeet );
QCOMPARE( context.areaUnit(), QgsUnitTypes::AreaHectares );

context.setLogLevel( QgsProcessingContext::Verbose );
QCOMPARE( static_cast< int >( context.logLevel() ), static_cast< int >( QgsProcessingContext::Verbose ) );

context.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
QCOMPARE( context.invalidGeometryCheck(), QgsFeatureRequest::GeometrySkipInvalid );

Expand All @@ -1002,6 +1005,7 @@ void TestQgsProcessing::context()
QCOMPARE( context2.invalidGeometryCheck(), context.invalidGeometryCheck() );
QCOMPARE( context2.flags(), context.flags() );
QCOMPARE( context2.project(), context.project() );
QCOMPARE( static_cast< int >( context2.logLevel() ), static_cast< int >( QgsProcessingContext::Verbose ) );
// layers from temporaryLayerStore must not be copied by copyThreadSafeSettings
QVERIFY( context2.temporaryLayerStore()->mapLayers().isEmpty() );

Expand Down Expand Up @@ -9427,9 +9431,6 @@ void TestQgsProcessing::modelerAlgorithm()
lastParams.insert( QStringLiteral( "a" ), 2 );
lastParams.insert( QStringLiteral( "b" ), 4 );
alg.setDesignerParameterValues( lastParams );

// we expect the result to add in some custom parameters -- namely the verbose log switch
lastParams.insert( QStringLiteral( "VERBOSE_LOG" ), true );
QCOMPARE( alg.designerParameterValues(), lastParams );

// child algorithms
Expand Down
1 change: 0 additions & 1 deletion tests/src/gui/testprocessinggui.cpp
Expand Up @@ -377,7 +377,6 @@ void TestProcessingGui::testModelUndo()
// the last used parameter values setting should not be affected by undo stack changes
QVariantMap params;
params.insert( QStringLiteral( "a" ), 1 );
params.insert( QStringLiteral( "VERBOSE_LOG" ), true );
model.setDesignerParameterValues( params );
command.undo();
QCOMPARE( model.designerParameterValues(), params );
Expand Down

0 comments on commit c8d6149

Please sign in to comment.