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