QGIS API Documentation 3.99.0-Master (d270888f95f)
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 <QString>
29
30#include "moc_qgsprocessingfeedback.cpp"
31
32using namespace Qt::StringLiterals;
33
34#ifdef HAVE_PDAL_QGIS
35#include <pdal/pdal.hpp>
36#endif
37
38#ifdef WITH_SFCGAL
39#include <SFCGAL/capi/sfcgal_c.h>
40#endif
41
42#ifdef WITH_GEOGRAPHICLIB
43#include <GeographicLib/Constants.hpp>
44#endif
45
47 : mLogFeedback( logFeedback )
48{
49
50}
51
52void QgsProcessingFeedback::setProgressText( const QString &text )
53{
54 mHtmlLog.append( text.toHtmlEscaped().replace( '\n', "<br>"_L1 ) + u"<br/>"_s );
55 mTextLog.append( text + '\n' );
56}
57
58void QgsProcessingFeedback::log( const QString &htmlMessage, const QString &textMessage )
59{
60 constexpr int MESSAGE_COUNT_LIMIT = 10000;
61 // Avoid logging too many messages, which might blow memory.
62 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
63 return;
64 ++mMessageLoggedCount;
65 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
66 {
67 mHtmlLog.append( u"<span style=\"color:red\">%1</span><br/>"_s.arg( tr( "Message log truncated" ) ) );
68 mTextLog.append( tr( "Message log truncated" ) + '\n' );
69 }
70 else
71 {
72 mHtmlLog.append( htmlMessage );
73 mTextLog.append( textMessage );
74 }
75}
76
77
78void QgsProcessingFeedback::reportError( const QString &error, bool )
79{
80 if ( mLogFeedback )
81 QgsMessageLog::logMessage( error, tr( "Processing" ), Qgis::MessageLevel::Critical );
82
83 log( u"<span style=\"color:red\">%1</span><br/>"_s.arg( error.toHtmlEscaped() ).replace( '\n', "<br>"_L1 ),
84 error + '\n' );
85}
86
87void QgsProcessingFeedback::pushWarning( const QString &warning )
88{
89 if ( mLogFeedback )
90 QgsMessageLog::logMessage( warning, tr( "Processing" ), Qgis::MessageLevel::Warning );
91
92 log( u"<span style=\"color:#b85a20;\">%1</span><br/>"_s.arg( warning.toHtmlEscaped() ).replace( '\n', "<br>"_L1 ) + u"<br/>"_s,
93 warning + '\n' );
94}
95
96void QgsProcessingFeedback::pushInfo( const QString &info )
97{
98 if ( mLogFeedback )
99 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
100
101 mHtmlLog.append( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) + u"<br/>"_s );
102 mTextLog.append( info + '\n' );
103}
104
105void QgsProcessingFeedback::pushFormattedMessage( const QString &html, const QString &text )
106{
107 if ( mLogFeedback )
108 QgsMessageLog::logMessage( text, tr( "Processing" ), Qgis::MessageLevel::Info );
109
110 mHtmlLog.append( html + u"<br/>"_s );
111 mTextLog.append( text + '\n' );
112}
113
114void QgsProcessingFeedback::pushCommandInfo( const QString &info )
115{
116 if ( mLogFeedback )
117 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
118
119 log( u"<code>%1</code><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
120 info + '\n' );
121}
122
123void QgsProcessingFeedback::pushDebugInfo( const QString &info )
124{
125 if ( mLogFeedback )
126 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
127
128 log( u"<span style=\"color:#777\">%1</span><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
129 info + '\n' );
130}
131
132void QgsProcessingFeedback::pushConsoleInfo( const QString &info )
133{
134 if ( mLogFeedback )
135 QgsMessageLog::logMessage( info, tr( "Processing" ), Qgis::MessageLevel::Info );
136
137 log( u"<code style=\"color:#777\">%1</code><br/>"_s.arg( info.toHtmlEscaped().replace( '\n', "<br>"_L1 ) ),
138 info + '\n' );
139}
140
142{
143 pushDebugInfo( tr( "QGIS version: %1" ).arg( Qgis::version() ) );
144 if ( QString( Qgis::devVersion() ) != "exported"_L1 )
145 {
146 pushDebugInfo( tr( "QGIS code revision: %1" ).arg( Qgis::devVersion() ) );
147 }
148 pushDebugInfo( tr( "Qt version: %1" ).arg( qVersion() ) );
149 pushDebugInfo( tr( "Python version: %1" ).arg( PYTHON_VERSION ) );
150 pushDebugInfo( tr( "GDAL version: %1" ).arg( GDALVersionInfo( "RELEASE_NAME" ) ) );
151 pushDebugInfo( tr( "GEOS version: %1" ).arg( GEOSversion() ) );
152
153 const PJ_INFO info = proj_info();
154 pushDebugInfo( tr( "PROJ version: %1" ).arg( info.release ) );
155
156#ifdef HAVE_PDAL_QGIS
157#if PDAL_VERSION_MAJOR_INT > 1 || (PDAL_VERSION_MAJOR_INT == 1 && PDAL_VERSION_MINOR_INT >= 7)
158 pushDebugInfo( tr( "PDAL version: %1" ).arg( QString::fromStdString( pdal::Config::fullVersionString() ) ) );
159#else
160 pushDebugInfo( tr( "PDAL version: %1" ).arg( QString::fromStdString( pdal::GetFullVersionString() ) ) );
161#endif
162#endif
163
164#ifdef WITH_SFCGAL
165 pushDebugInfo( tr( "SFCGAL version: %1" ).arg( sfcgal_version() ) );
166#else
167 pushDebugInfo( tr( "No support for SFCGAL" ) );
168#endif
169
170#ifdef WITH_GEOGRAPHICLIB
171 pushDebugInfo( tr( "GeographicLib version: %1.%2.%3" ).arg( GEOGRAPHICLIB_VERSION_MAJOR ).arg( GEOGRAPHICLIB_VERSION_MINOR ).arg( GEOGRAPHICLIB_VERSION_PATCH ) );
172#else
173 pushDebugInfo( tr( "No support for GeographicLib" ) );
174#endif
175
176 if ( provider && !provider->versionInfo().isEmpty() )
177 {
178 pushDebugInfo( tr( "%1 version: %2" ).arg( provider->name(), provider->versionInfo() ) );
179 }
180}
181
183{
184 if ( results.empty() )
185 return;
186
187 pushInfo( tr( "Results:" ) );
188
189 const QList< const QgsProcessingOutputDefinition * > outputs = algorithm->outputDefinitions();
190 for ( const QgsProcessingOutputDefinition *output : outputs )
191 {
192 const QString outputName = output->name();
193 if ( outputName == "CHILD_RESULTS"_L1 || outputName == "CHILD_INPUTS"_L1 )
194 continue;
195
196 if ( !results.contains( outputName ) )
197 continue;
198
199 bool ok = false;
200 const QString textValue = output->valueAsString( results.value( output->name() ), context, ok );
201 const QString formattedValue = output->valueAsFormattedString( results.value( output->name() ), context, ok );
202 if ( ok )
203 {
204 pushFormattedMessage( u"<code>&nbsp;&nbsp;%1: %2</code>"_s.arg( output->name(), formattedValue ),
205 u" %1: %2"_s.arg( output->name(), textValue ) );
206 }
207 }
208}
209
211{
212 return mHtmlLog;
213}
214
216{
217 return mTextLog;
218}
219
220
222 : mChildSteps( childAlgorithmCount )
223 , mFeedback( feedback )
224{
225 if ( mFeedback )
226 {
227 connect( mFeedback, &QgsFeedback::canceled, this, &QgsFeedback::cancel, Qt::DirectConnection );
228 connect( this, &QgsFeedback::progressChanged, this, &QgsProcessingMultiStepFeedback::updateOverallProgress );
229 }
230
231 // initialize with equal weights
232 const double equalWeight = mChildSteps > 0 ? 1.0 / mChildSteps : 0.0;
233 for ( int i = 0; i < mChildSteps; ++i )
234 {
235 mStepWeights << equalWeight;
236 }
237}
238
240{
241 mCurrentStep = step;
242
243 // calculate the base progress (sum of all previous steps)
244 mCurrentStepBaseProgress = 0.0;
245 for ( int i = 0; i < mCurrentStep && i < mStepWeights.count(); ++i )
246 {
247 mCurrentStepBaseProgress += mStepWeights.at( i ) * 100.0;
248 }
249
250 if ( mFeedback )
251 mFeedback->setProgress( mCurrentStepBaseProgress );
252}
253
254void QgsProcessingMultiStepFeedback::setStepWeights( const QList<double> &weights )
255{
256 if ( weights.size() != mChildSteps )
257 {
258 return;
259 }
260
261 const double totalWeight = std::reduce( weights.begin(), weights.end() );
262
263 mStepWeights.clear();
264 if ( totalWeight > 0.0 )
265 {
266 for ( double w : weights )
267 {
268 mStepWeights << ( w / totalWeight );
269 }
270 }
271 else
272 {
273 // fallback to equal weights if total weight is 0
274 const double equalWeight = mChildSteps > 0 ? 1.0 / mChildSteps : 0.0;
275 for ( int i = 0; i < mChildSteps; ++i )
276 {
277 mStepWeights << equalWeight;
278 }
279 }
280}
281
283{
284 if ( mFeedback )
285 mFeedback->setProgressText( text );
286}
287
288void QgsProcessingMultiStepFeedback::reportError( const QString &error, bool fatalError )
289{
290 if ( mFeedback )
291 mFeedback->reportError( error, fatalError );
292}
293
295{
296 if ( mFeedback )
297 mFeedback->pushWarning( warning );
298}
299
301{
302 if ( mFeedback )
303 mFeedback->pushInfo( info );
304}
305
307{
308 if ( mFeedback )
309 mFeedback->pushCommandInfo( info );
310}
311
313{
314 if ( mFeedback )
315 mFeedback->pushDebugInfo( info );
316}
317
319{
320 if ( mFeedback )
321 mFeedback->pushConsoleInfo( info );
322}
323
324void QgsProcessingMultiStepFeedback::pushFormattedMessage( const QString &html, const QString &text )
325{
326 if ( mFeedback )
327 mFeedback->pushFormattedMessage( html, text );
328}
329
331{
332 if ( mFeedback )
333 return mFeedback->htmlLog();
334 return QString();
335}
336
338{
339 if ( mFeedback )
340 return mFeedback->textLog();
341 return QString();
342}
343
344void QgsProcessingMultiStepFeedback::updateOverallProgress( double progress )
345{
346 if ( !mFeedback )
347 return;
348
349 const double currentStepWeight = mStepWeights.value( mCurrentStep, 0 );
350
351 mFeedback->setProgress( mCurrentStepBaseProgress + progress * currentStepWeight );
352}
static QString version()
Version string.
Definition qgis.cpp:682
@ 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:699
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