QGIS API Documentation 3.99.0-Master (a8882ad4560)
Loading...
Searching...
No Matches
qgsprocessingfeedback.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingfeedback.cpp
3 -------------------------
4 begin : June 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <gdal_version.h>
21#include <ogr_api.h>
22#include <proj.h>
23
24#include "qgsgeos.h"
25#include "qgsmessagelog.h"
27
28#include "moc_qgsprocessingfeedback.cpp"
29
30#ifdef HAVE_PDAL_QGIS
31#include <pdal/pdal.hpp>
32#endif
33
34#ifdef WITH_SFCGAL
35#include <SFCGAL/capi/sfcgal_c.h>
36#endif
37
38#ifdef WITH_GEOGRAPHICLIB
39#include <GeographicLib/Constants.hpp>
40#endif
41
43 : mLogFeedback( logFeedback )
44{
45
46}
47
48void QgsProcessingFeedback::setProgressText( const QString &text )
49{
50 mHtmlLog.append( text.toHtmlEscaped().replace( '\n', "<br>"_L1 ) + u"<br/>"_s );
51 mTextLog.append( text + '\n' );
52}
53
54void QgsProcessingFeedback::log( const QString &htmlMessage, const QString &textMessage )
55{
56 constexpr int MESSAGE_COUNT_LIMIT = 10000;
57 // Avoid logging too many messages, which might blow memory.
58 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
59 return;
60 ++mMessageLoggedCount;
61 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
62 {
63 mHtmlLog.append( u"<span style=\"color:red\">%1</span><br/>"_s.arg( tr( "Message log truncated" ) ) );
64 mTextLog.append( tr( "Message log truncated" ) + '\n' );
65 }
66 else
67 {
68 mHtmlLog.append( htmlMessage );
69 mTextLog.append( textMessage );
70 }
71}
72
73
74void QgsProcessingFeedback::reportError( const QString &error, bool )
75{
76 if ( mLogFeedback )
77 QgsMessageLog::logMessage( error, tr( "Processing" ), Qgis::MessageLevel::Critical );
78
79 log( u"<span style=\"color:red\">%1</span><br/>"_s.arg( error.toHtmlEscaped() ).replace( '\n', "<br>"_L1 ),
80 error + '\n' );
81}
82
83void QgsProcessingFeedback::pushWarning( const QString &warning )
84{
85 if ( mLogFeedback )
86 QgsMessageLog::logMessage( warning, tr( "Processing" ), Qgis::MessageLevel::Warning );
87
88 log( u"<span style=\"color:#b85a20;\">%1</span><br/>"_s.arg( warning.toHtmlEscaped() ).replace( '\n', "<br>"_L1 ) + u"<br/>"_s,
89 warning + '\n' );
90}
91
92void QgsProcessingFeedback::pushInfo( const QString &info )
93{
94 if ( mLogFeedback )
95 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
96
97 mHtmlLog.append( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) + u"<br/>"_s );
98 mTextLog.append( info + '\n' );
99}
100
101void QgsProcessingFeedback::pushFormattedMessage( const QString &html, const QString &text )
102{
103 if ( mLogFeedback )
104 QgsMessageLog::logMessage( text, tr( "Processing" ), Qgis::MessageLevel::Info );
105
106 mHtmlLog.append( html + u"<br/>"_s );
107 mTextLog.append( text + '\n' );
108}
109
110void QgsProcessingFeedback::pushCommandInfo( const QString &info )
111{
112 if ( mLogFeedback )
113 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
114
115 log( u"<code>%1</code><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
116 info + '\n' );
117}
118
119void QgsProcessingFeedback::pushDebugInfo( const QString &info )
120{
121 if ( mLogFeedback )
122 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
123
124 log( u"<span style=\"color:#777\">%1</span><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
125 info + '\n' );
126}
127
128void QgsProcessingFeedback::pushConsoleInfo( const QString &info )
129{
130 if ( mLogFeedback )
131 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
132
133 log( u"<code style=\"color:#777\">%1</code><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
134 info + '\n' );
135}
136
138{
139 pushDebugInfo( tr( "QGIS version: %1" ).arg( Qgis::version() ) );
140 if ( QString( Qgis::devVersion() ) != "exported"_L1 )
141 {
142 pushDebugInfo( tr( "QGIS code revision: %1" ).arg( Qgis::devVersion() ) );
143 }
144 pushDebugInfo( tr( "Qt version: %1" ).arg( qVersion() ) );
145 pushDebugInfo( tr( "Python version: %1" ).arg( PYTHON_VERSION ) );
146 pushDebugInfo( tr( "GDAL version: %1" ).arg( GDALVersionInfo( "RELEASE_NAME" ) ) );
147 pushDebugInfo( tr( "GEOS version: %1" ).arg( GEOSversion() ) );
148
149 const PJ_INFO info = proj_info();
150 pushDebugInfo( tr( "PROJ version: %1" ).arg( info.release ) );
151
152#ifdef HAVE_PDAL_QGIS
153#if PDAL_VERSION_MAJOR_INT > 1 || (PDAL_VERSION_MAJOR_INT == 1 && PDAL_VERSION_MINOR_INT >= 7)
154 pushDebugInfo( tr( "PDAL version: %1" ).arg( QString::fromStdString( pdal::Config::fullVersionString() ) ) );
155#else
156 pushDebugInfo( tr( "PDAL version: %1" ).arg( QString::fromStdString( pdal::GetFullVersionString() ) ) );
157#endif
158#endif
159
160#ifdef WITH_SFCGAL
161 pushDebugInfo( tr( "SFCGAL version: %1" ).arg( sfcgal_version() ) );
162#else
163 pushDebugInfo( tr( "No support for SFCGAL" ) );
164#endif
165
166#ifdef WITH_GEOGRAPHICLIB
167 pushDebugInfo( tr( "GeographicLib version: %1.%2.%3" ).arg( GEOGRAPHICLIB_VERSION_MAJOR ).arg( GEOGRAPHICLIB_VERSION_MINOR ).arg( GEOGRAPHICLIB_VERSION_PATCH ) );
168#else
169 pushDebugInfo( tr( "No support for GeographicLib" ) );
170#endif
171
172 if ( provider && !provider->versionInfo().isEmpty() )
173 {
174 pushDebugInfo( tr( "%1 version: %2" ).arg( provider->name(), provider->versionInfo() ) );
175 }
176}
177
179{
180 if ( results.empty() )
181 return;
182
183 pushInfo( tr( "Results:" ) );
184
185 const QList< const QgsProcessingOutputDefinition * > outputs = algorithm->outputDefinitions();
186 for ( const QgsProcessingOutputDefinition *output : outputs )
187 {
188 const QString outputName = output->name();
189 if ( outputName == "CHILD_RESULTS"_L1 || outputName == "CHILD_INPUTS"_L1 )
190 continue;
191
192 if ( !results.contains( outputName ) )
193 continue;
194
195 bool ok = false;
196 const QString textValue = output->valueAsString( results.value( output->name() ), context, ok );
197 const QString formattedValue = output->valueAsFormattedString( results.value( output->name() ), context, ok );
198 if ( ok )
199 {
200 pushFormattedMessage( u"<code>&nbsp;&nbsp;%1: %2</code>"_s.arg( output->name(), formattedValue ),
201 u" %1: %2"_s.arg( output->name(), textValue ) );
202 }
203 }
204}
205
207{
208 return mHtmlLog;
209}
210
212{
213 return mTextLog;
214}
215
216
218 : mChildSteps( childAlgorithmCount )
219 , mFeedback( feedback )
220{
221 if ( mFeedback )
222 {
223 connect( mFeedback, &QgsFeedback::canceled, this, &QgsFeedback::cancel, Qt::DirectConnection );
224 connect( this, &QgsFeedback::progressChanged, this, &QgsProcessingMultiStepFeedback::updateOverallProgress );
225 }
226
227 // initialize with equal weights
228 const double equalWeight = mChildSteps > 0 ? 1.0 / mChildSteps : 0.0;
229 for ( int i = 0; i < mChildSteps; ++i )
230 {
231 mStepWeights << equalWeight;
232 }
233}
234
236{
237 mCurrentStep = step;
238
239 // calculate the base progress (sum of all previous steps)
240 mCurrentStepBaseProgress = 0.0;
241 for ( int i = 0; i < mCurrentStep && i < mStepWeights.count(); ++i )
242 {
243 mCurrentStepBaseProgress += mStepWeights.at( i ) * 100.0;
244 }
245
246 if ( mFeedback )
247 mFeedback->setProgress( mCurrentStepBaseProgress );
248}
249
250void QgsProcessingMultiStepFeedback::setStepWeights( const QList<double> &weights )
251{
252 if ( weights.size() != mChildSteps )
253 {
254 return;
255 }
256
257 const double totalWeight = std::reduce( weights.begin(), weights.end() );
258
259 mStepWeights.clear();
260 if ( totalWeight > 0.0 )
261 {
262 for ( double w : weights )
263 {
264 mStepWeights << ( w / totalWeight );
265 }
266 }
267 else
268 {
269 // fallback to equal weights if total weight is 0
270 const double equalWeight = mChildSteps > 0 ? 1.0 / mChildSteps : 0.0;
271 for ( int i = 0; i < mChildSteps; ++i )
272 {
273 mStepWeights << equalWeight;
274 }
275 }
276}
277
279{
280 if ( mFeedback )
281 mFeedback->setProgressText( text );
282}
283
284void QgsProcessingMultiStepFeedback::reportError( const QString &error, bool fatalError )
285{
286 if ( mFeedback )
287 mFeedback->reportError( error, fatalError );
288}
289
291{
292 if ( mFeedback )
293 mFeedback->pushWarning( warning );
294}
295
297{
298 if ( mFeedback )
299 mFeedback->pushInfo( info );
300}
301
303{
304 if ( mFeedback )
305 mFeedback->pushCommandInfo( info );
306}
307
309{
310 if ( mFeedback )
311 mFeedback->pushDebugInfo( info );
312}
313
315{
316 if ( mFeedback )
317 mFeedback->pushConsoleInfo( info );
318}
319
320void QgsProcessingMultiStepFeedback::pushFormattedMessage( const QString &html, const QString &text )
321{
322 if ( mFeedback )
323 mFeedback->pushFormattedMessage( html, text );
324}
325
327{
328 if ( mFeedback )
329 return mFeedback->htmlLog();
330 return QString();
331}
332
334{
335 if ( mFeedback )
336 return mFeedback->textLog();
337 return QString();
338}
339
340void QgsProcessingMultiStepFeedback::updateOverallProgress( double progress )
341{
342 if ( !mFeedback )
343 return;
344
345 const double currentStepWeight = mStepWeights.value( mCurrentStep, 0 );
346
347 mFeedback->setProgress( mCurrentStepBaseProgress + progress * currentStepWeight );
348}
static QString version()
Version string.
Definition qgis.cpp:678
@ Warning
Warning message.
Definition qgis.h:161
@ Critical
Critical/error message.
Definition qgis.h:162
@ Info
Information message.
Definition qgis.h:160
static QString devVersion()
The development version.
Definition qgis.cpp:695
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
void canceled()
Internal routines can connect to this signal if they use event loop.
void cancel()
Tells the internal routines that the current operation should be canceled. This should be run by the ...
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
double progress() const
Returns the current progress reported by the feedback object.
Definition qgsfeedback.h:79
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())
Adds a message to the log instance (and creates it if necessary).
Abstract base class for processing algorithms.
Contains information about the context in which a processing algorithm is executed.
virtual void pushCommandInfo(const QString &info)
Pushes an informational message containing a command from the algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
void pushVersionInfo(const QgsProcessingProvider *provider=nullptr)
Pushes a summary of the QGIS (and underlying library) version information to the log.
virtual QString textLog() const
Returns the plain text contents of the log, which contains all messages pushed to the feedback object...
QgsProcessingFeedback(bool logFeedback=true)
Constructor for QgsProcessingFeedback.
void pushFormattedResults(const QgsProcessingAlgorithm *algorithm, QgsProcessingContext &context, const QVariantMap &results)
Pushes a summary of the execution results to the log.
virtual QString htmlLog() const
Returns the HTML formatted contents of the log, which contains all messages pushed to the feedback ob...
virtual void pushDebugInfo(const QString &info)
Pushes an informational message containing debugging helpers from the algorithm.
virtual void pushFormattedMessage(const QString &html, const QString &text)
Pushes a pre-formatted message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
virtual void pushConsoleInfo(const QString &info)
Pushes a console feedback message from the algorithm.
virtual void setProgressText(const QString &text)
Sets a progress report text string.
QgsProcessingMultiStepFeedback(int steps, QgsProcessingFeedback *feedback)
Constructor for QgsProcessingMultiStepFeedback, for a process with the specified number of steps.
void pushDebugInfo(const QString &info) override
Pushes an informational message containing debugging helpers from the algorithm.
void pushFormattedMessage(const QString &html, const QString &text) override
Pushes a pre-formatted message from the algorithm.
void pushConsoleInfo(const QString &info) override
Pushes a console feedback message from the algorithm.
void pushInfo(const QString &info) override
Pushes a general informational message from the algorithm.
void pushWarning(const QString &warning) override
Pushes a warning informational message from the algorithm.
void setProgressText(const QString &text) override
Sets a progress report text string.
void setCurrentStep(int step)
Sets the step which is being executed.
void setStepWeights(const QList< double > &weights)
Sets the relative weights for each step.
void reportError(const QString &error, bool fatalError=false) override
Reports that the algorithm encountered an error while executing.
QString textLog() const override
Returns the plain text contents of the log, which contains all messages pushed to the feedback object...
void pushCommandInfo(const QString &info) override
Pushes an informational message containing a command from the algorithm.
QString htmlLog() const override
Returns the HTML formatted contents of the log, which contains all messages pushed to the feedback ob...
Base class for the definition of processing outputs.
Abstract base class for processing providers.
virtual QString versionInfo() const
Returns a version information string for the provider, or an empty string if this is not applicable (...
virtual QString name() const =0
Returns the provider name, which is used to describe the provider within the GUI.
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