QGIS API Documentation 3.39.0-Master (47f7b3a4989)
Loading...
Searching...
No Matches
qgsprocessingalgorithmdialogbase.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprocessingalgorithmdialogbase.cpp
3 ------------------------------------
4 Date : November 2017
5 Copyright : (C) 2017 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "qgssettings.h"
18#include "qgshelp.h"
19#include "qgsmessagebar.h"
20#include "qgsgui.h"
23#include "qgstaskmanager.h"
25#include "qgsstringutils.h"
26#include "qgsapplication.h"
27#include "qgspanelwidget.h"
28#include "qgsjsonutils.h"
29#include "qgsunittypes.h"
30#include "qgsnative.h"
31#include <QToolButton>
32#include <QDesktopServices>
33#include <QScrollBar>
34#include <QApplication>
35#include <QClipboard>
36#include <QFileDialog>
37#include <QMimeData>
38#include <QMenu>
39#include <nlohmann/json.hpp>
40
41
43
44QgsProcessingAlgorithmDialogFeedback::QgsProcessingAlgorithmDialogFeedback()
45 : QgsProcessingFeedback( false )
46{}
47
48void QgsProcessingAlgorithmDialogFeedback::setProgressText( const QString &text )
49{
51 emit progressTextChanged( text );
52}
53
54void QgsProcessingAlgorithmDialogFeedback::reportError( const QString &error, bool fatalError )
55{
56 QgsProcessingFeedback::reportError( error, fatalError );
57 emit errorReported( error, fatalError );
58}
59
60void QgsProcessingAlgorithmDialogFeedback::pushWarning( const QString &warning )
61{
63 emit warningPushed( warning );
64}
65
66void QgsProcessingAlgorithmDialogFeedback::pushInfo( const QString &info )
67{
69 emit infoPushed( info );
70}
71
72void QgsProcessingAlgorithmDialogFeedback::pushCommandInfo( const QString &info )
73{
75 emit commandInfoPushed( info );
76}
77
78void QgsProcessingAlgorithmDialogFeedback::pushDebugInfo( const QString &info )
79{
81 emit debugInfoPushed( info );
82}
83
84void QgsProcessingAlgorithmDialogFeedback::pushConsoleInfo( const QString &info )
85{
87 emit consoleInfoPushed( info );
88}
89
90void QgsProcessingAlgorithmDialogFeedback::pushFormattedMessage( const QString &html, const QString &text )
91{
93 emit formattedMessagePushed( html );
94}
95
96//
97// QgsProcessingAlgorithmDialogBase
98//
99
100QgsProcessingAlgorithmDialogBase::QgsProcessingAlgorithmDialogBase( QWidget *parent, Qt::WindowFlags flags, DialogMode mode )
101 : QDialog( parent, flags )
102 , mMode( mode )
103{
104 setupUi( this );
105
106 //don't collapse parameters panel
107 splitter->setCollapsible( 0, false );
108
109 // add collapse button to splitter
110 QSplitterHandle *splitterHandle = splitter->handle( 1 );
111 QVBoxLayout *handleLayout = new QVBoxLayout();
112 handleLayout->setContentsMargins( 0, 0, 0, 0 );
113 mButtonCollapse = new QToolButton( splitterHandle );
114 mButtonCollapse->setAutoRaise( true );
115 mButtonCollapse->setFixedSize( 12, 12 );
116 mButtonCollapse->setCursor( Qt::ArrowCursor );
117 handleLayout->addWidget( mButtonCollapse );
118 handleLayout->addStretch();
119 splitterHandle->setLayout( handleLayout );
120
122
123 txtLog->setOpenLinks( false );
124 connect( txtLog, &QTextBrowser::anchorClicked, this, &QgsProcessingAlgorithmDialogBase::urlClicked );
125
126 const QgsSettings settings;
127 splitter->restoreState( settings.value( QStringLiteral( "/Processing/dialogBaseSplitter" ), QByteArray() ).toByteArray() );
128 mSplitterState = splitter->saveState();
129 splitterChanged( 0, 0 );
130
131 // Rename OK button to Run
132 mButtonRun = mButtonBox->button( QDialogButtonBox::Ok );
133 mButtonRun->setText( tr( "Run" ) );
134
135 // Rename Yes button. Yes is used to ensure same position of Run and Change Parameters with respect to Close button.
136 mButtonChangeParameters = mButtonBox->button( QDialogButtonBox::Yes );
137 mButtonChangeParameters->setText( tr( "Change Parameters" ) );
138
139 buttonCancel->setEnabled( false );
140 mButtonClose = mButtonBox->button( QDialogButtonBox::Close );
141
142 switch ( mMode )
143 {
144 case DialogMode::Single:
145 {
146 mAdvancedButton = new QPushButton( tr( "Advanced" ) );
147 mAdvancedMenu = new QMenu( this );
148 mAdvancedButton->setMenu( mAdvancedMenu );
149
150 mContextSettingsAction = new QAction( tr( "Algorithm Settingsā€¦" ), mAdvancedMenu );
151 mContextSettingsAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/settings.svg" ) ) );
152 mAdvancedMenu->addAction( mContextSettingsAction );
153
154 connect( mContextSettingsAction, &QAction::triggered, this, [this]
155 {
156 if ( QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( mMainWidget ) )
157 {
158 mTabWidget->setCurrentIndex( 0 );
159
160 if ( !mContextOptionsWidget )
161 {
162 mContextOptionsWidget = new QgsProcessingContextOptionsWidget();
163 mContextOptionsWidget->setFromContext( processingContext() );
164 mContextOptionsWidget->setLogLevel( mLogLevel );
165 panel->openPanel( mContextOptionsWidget );
166
167 connect( mContextOptionsWidget, &QgsPanelWidget::widgetChanged, this, [ = ]
168 {
169 mOverrideDefaultContextSettings = true;
170 mGeometryCheck = mContextOptionsWidget->invalidGeometryCheck();
171 mDistanceUnits = mContextOptionsWidget->distanceUnit();
172 mAreaUnits = mContextOptionsWidget->areaUnit();
173 mTemporaryFolderOverride = mContextOptionsWidget->temporaryFolder();
174 mMaximumThreads = mContextOptionsWidget->maximumThreads();
175 mLogLevel = mContextOptionsWidget->logLevel();
176 } );
177 }
178 }
179 } );
180 mAdvancedMenu->addSeparator();
181
182 QAction *copyAsPythonCommand = new QAction( tr( "Copy as Python Command" ), mAdvancedMenu );
183 copyAsPythonCommand->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconPythonFile.svg" ) ) );
184
185 mAdvancedMenu->addAction( copyAsPythonCommand );
186 connect( copyAsPythonCommand, &QAction::triggered, this, [this]
187 {
188 if ( const QgsProcessingAlgorithm *alg = algorithm() )
189 {
190 QgsProcessingContext *context = processingContext();
191 if ( !context )
192 return;
193
194 const QString command = alg->asPythonCommand( createProcessingParameters(), *context );
195 QMimeData *m = new QMimeData();
196 m->setText( command );
197 QClipboard *cb = QApplication::clipboard();
198
199#ifdef Q_OS_LINUX
200 cb->setMimeData( m, QClipboard::Selection );
201#endif
202 cb->setMimeData( m, QClipboard::Clipboard );
203 }
204 } );
205
206 mCopyAsQgisProcessCommand = new QAction( tr( "Copy as qgis_process Command" ), mAdvancedMenu );
207 mCopyAsQgisProcessCommand->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionTerminal.svg" ) ) );
208 mAdvancedMenu->addAction( mCopyAsQgisProcessCommand );
209
210 connect( mCopyAsQgisProcessCommand, &QAction::triggered, this, [this]
211 {
212 if ( const QgsProcessingAlgorithm *alg = algorithm() )
213 {
214 QgsProcessingContext *context = processingContext();
215 if ( !context )
216 return;
217
218 bool ok = false;
219 const QString command = alg->asQgisProcessCommand( createProcessingParameters(), *context, ok );
220 if ( ! ok )
221 {
222 mMessageBar->pushMessage( tr( "Current settings cannot be specified as arguments to qgis_process (Pipe parameters as JSON to qgis_process instead)" ), Qgis::MessageLevel::Warning );
223 }
224 else
225 {
226 QMimeData *m = new QMimeData();
227 m->setText( command );
228 QClipboard *cb = QApplication::clipboard();
229
230#ifdef Q_OS_LINUX
231 cb->setMimeData( m, QClipboard::Selection );
232#endif
233 cb->setMimeData( m, QClipboard::Clipboard );
234 }
235 }
236 } );
237
238 mAdvancedMenu->addSeparator();
239
240 QAction *copyAsJson = new QAction( tr( "Copy as JSON" ), mAdvancedMenu );
241 copyAsJson->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionEditCopy.svg" ) ) );
242
243 mAdvancedMenu->addAction( copyAsJson );
244 connect( copyAsJson, &QAction::triggered, this, [this]
245 {
246 if ( const QgsProcessingAlgorithm *alg = algorithm() )
247 {
248 QgsProcessingContext *context = processingContext();
249 if ( !context )
250 return;
251
252 const QVariantMap properties = alg->asMap( createProcessingParameters(), *context );
253 const QString json = QString::fromStdString( QgsJsonUtils::jsonFromVariant( properties ).dump( 2 ) );
254
255 QMimeData *m = new QMimeData();
256 m->setText( json );
257 QClipboard *cb = QApplication::clipboard();
258
259#ifdef Q_OS_LINUX
260 cb->setMimeData( m, QClipboard::Selection );
261#endif
262 cb->setMimeData( m, QClipboard::Clipboard );
263 }
264 } );
265
266 mPasteJsonAction = new QAction( tr( "Paste Settings" ), mAdvancedMenu );
267 mPasteJsonAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionEditPaste.svg" ) ) );
268
269 mAdvancedMenu->addAction( mPasteJsonAction );
270 connect( mPasteJsonAction, &QAction::triggered, this, [this]
271 {
272 const QString text = QApplication::clipboard()->text();
273 if ( text.isEmpty() )
274 return;
275
276 const QVariantMap parameterValues = QgsJsonUtils::parseJson( text ).toMap().value( QStringLiteral( "inputs" ) ).toMap();
277 if ( parameterValues.isEmpty() )
278 return;
279
280 bool ok = false;
281 QString error;
282 const QVariantMap preparedValues = QgsProcessingUtils::preprocessQgisProcessParameters( parameterValues, ok, error );
283
284 setParameters( preparedValues );
285 } );
286
287 mButtonBox->addButton( mAdvancedButton, QDialogButtonBox::ResetRole );
288 break;
289 }
290
291 case DialogMode::Batch:
292 break;
293 }
294
295 if ( mAdvancedMenu )
296 {
297 connect( mAdvancedMenu, &QMenu::aboutToShow, this, [ = ]
298 {
299 mCopyAsQgisProcessCommand->setEnabled( algorithm()
301 mPasteJsonAction->setEnabled( !QApplication::clipboard()->text().isEmpty() );
302 } );
303 }
304
305 connect( mButtonRun, &QPushButton::clicked, this, &QgsProcessingAlgorithmDialogBase::runAlgorithm );
306 connect( mButtonChangeParameters, &QPushButton::clicked, this, &QgsProcessingAlgorithmDialogBase::showParameters );
307 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsProcessingAlgorithmDialogBase::closeClicked );
308 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsProcessingAlgorithmDialogBase::openHelp );
309 connect( mButtonCollapse, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::toggleCollapsed );
310 connect( splitter, &QSplitter::splitterMoved, this, &QgsProcessingAlgorithmDialogBase::splitterChanged );
311
312 connect( mButtonSaveLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::saveLog );
313 connect( mButtonCopyLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::copyLogToClipboard );
314 connect( mButtonClearLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::clearLog );
315
316 connect( mTabWidget, &QTabWidget::currentChanged, this, &QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged );
317
318 mMessageBar = new QgsMessageBar();
319 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
320 verticalLayout->insertWidget( 0, mMessageBar );
321
322 connect( QgsApplication::taskManager(), &QgsTaskManager::taskTriggered, this, &QgsProcessingAlgorithmDialogBase::taskTriggered );
323}
324
325QgsProcessingAlgorithmDialogBase::~QgsProcessingAlgorithmDialogBase() = default;
326
327void QgsProcessingAlgorithmDialogBase::setParameters( const QVariantMap & )
328{}
329
330void QgsProcessingAlgorithmDialogBase::setAlgorithm( QgsProcessingAlgorithm *algorithm )
331{
332 mAlgorithm.reset( algorithm );
333 QString title;
335 {
336 title = QStringLiteral( "%1 - %2" ).arg( QgsStringUtils::capitalize( mAlgorithm->group(), Qgis::Capitalization::TitleCase ), QgsStringUtils::capitalize( mAlgorithm->displayName(), Qgis::Capitalization::TitleCase ) );
337 }
338 else
339 {
340 title = QStringLiteral( "%1 - %2" ).arg( mAlgorithm->group(), mAlgorithm->displayName() );
341 }
342
343 setWindowTitle( title );
344
345 const QString algHelp = formatHelp( algorithm );
346 if ( algHelp.isEmpty() )
347 textShortHelp->hide();
348 else
349 {
350 textShortHelp->document()->setDefaultStyleSheet( QStringLiteral( ".summary { margin-left: 10px; margin-right: 10px; }\n"
351 "h2 { color: #555555; padding-bottom: 15px; }\n"
352 "a { text - decoration: none; color: #3498db; font-weight: bold; }\n"
353 "p { color: #666666; }\n"
354 "b { color: #333333; }\n"
355 "dl dd { margin - bottom: 5px; }" ) );
356 textShortHelp->setHtml( algHelp );
357 connect( textShortHelp, &QTextBrowser::anchorClicked, this, &QgsProcessingAlgorithmDialogBase::linkClicked );
358 textShortHelp->show();
359 }
360
361 if ( algorithm->helpUrl().isEmpty() && ( !algorithm->provider() || algorithm->provider()->helpId().isEmpty() ) )
362 {
363 mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Help ) );
364 }
365
366 const QString warning = algorithm->provider() ? algorithm->provider()->warningMessage() : QString();
367 if ( !warning.isEmpty() )
368 {
369 mMessageBar->pushMessage( warning, Qgis::MessageLevel::Warning );
370 }
371}
372
373QgsProcessingAlgorithm *QgsProcessingAlgorithmDialogBase::algorithm()
374{
375 return mAlgorithm.get();
376}
377
378void QgsProcessingAlgorithmDialogBase::setMainWidget( QgsPanelWidget *widget )
379{
380 if ( mMainWidget )
381 {
382 mMainWidget->deleteLater();
383 }
384
385 mPanelStack->setMainPanel( widget );
386 widget->setDockMode( true );
387
388 mMainWidget = widget;
389 connect( mMainWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
390}
391
392QgsPanelWidget *QgsProcessingAlgorithmDialogBase::mainWidget()
393{
394 return mMainWidget;
395}
396
397void QgsProcessingAlgorithmDialogBase::saveLogToFile( const QString &path, const LogFormat format )
398{
399 QFile logFile( path );
400 if ( !logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
401 {
402 return;
403 }
404 QTextStream fout( &logFile );
405
406 switch ( format )
407 {
408 case FormatPlainText:
409 fout << txtLog->toPlainText();
410 break;
411
412 case FormatHtml:
413 fout << txtLog->toHtml();
414 break;
415 }
416}
417
418QgsProcessingFeedback *QgsProcessingAlgorithmDialogBase::createFeedback()
419{
420 auto feedback = std::make_unique< QgsProcessingAlgorithmDialogFeedback >();
421 connect( feedback.get(), &QgsProcessingFeedback::progressChanged, this, &QgsProcessingAlgorithmDialogBase::setPercentage );
422 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::commandInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushCommandInfo );
423 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::consoleInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushConsoleInfo );
424 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::debugInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushDebugInfo );
425 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::errorReported, this, &QgsProcessingAlgorithmDialogBase::reportError );
426 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::warningPushed, this, &QgsProcessingAlgorithmDialogBase::pushWarning );
427 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::infoPushed, this, &QgsProcessingAlgorithmDialogBase::pushInfo );
428 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::formattedMessagePushed, this, &QgsProcessingAlgorithmDialogBase::pushFormattedMessage );
429 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::progressTextChanged, this, &QgsProcessingAlgorithmDialogBase::setProgressText );
430 connect( buttonCancel, &QPushButton::clicked, feedback.get(), &QgsProcessingFeedback::cancel );
431 return feedback.release();
432}
433
434QDialogButtonBox *QgsProcessingAlgorithmDialogBase::buttonBox()
435{
436 return mButtonBox;
437}
438
439QTabWidget *QgsProcessingAlgorithmDialogBase::tabWidget()
440{
441 return mTabWidget;
442}
443
444void QgsProcessingAlgorithmDialogBase::showLog()
445{
446 mTabWidget->setCurrentIndex( 1 );
447}
448
449void QgsProcessingAlgorithmDialogBase::showParameters()
450{
451 mTabWidget->setCurrentIndex( 0 );
452}
453
454QPushButton *QgsProcessingAlgorithmDialogBase::runButton()
455{
456 return mButtonRun;
457}
458
459QPushButton *QgsProcessingAlgorithmDialogBase::cancelButton()
460{
461 return buttonCancel;
462}
463
464QPushButton *QgsProcessingAlgorithmDialogBase::changeParametersButton()
465{
466 return mButtonChangeParameters;
467}
468
469void QgsProcessingAlgorithmDialogBase::clearProgress()
470{
471 progressBar->setMaximum( 0 );
472}
473
474void QgsProcessingAlgorithmDialogBase::setExecuted( bool executed )
475{
476 mExecuted = executed;
477}
478
479void QgsProcessingAlgorithmDialogBase::setExecutedAnyResult( bool executedAnyResult )
480{
481 mExecutedAnyResult = executedAnyResult;
482}
483
484void QgsProcessingAlgorithmDialogBase::setResults( const QVariantMap &results )
485{
486 mResults = results;
487}
488
489void QgsProcessingAlgorithmDialogBase::finished( bool, const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
490{
491
492}
493
494void QgsProcessingAlgorithmDialogBase::openHelp()
495{
496 QUrl algHelp = mAlgorithm->helpUrl();
497 if ( algHelp.isEmpty() && mAlgorithm->provider() )
498 {
499 algHelp = QgsHelp::helpUrl( QStringLiteral( "processing_algs/%1/%2.html#%3" ).arg( mAlgorithm->provider()->helpId(), mAlgorithm->groupId(), QStringLiteral( "%1%2" ).arg( mAlgorithm->provider()->helpId() ).arg( mAlgorithm->name() ) ) );
500 }
501
502 if ( !algHelp.isEmpty() )
503 QDesktopServices::openUrl( algHelp );
504}
505
506void QgsProcessingAlgorithmDialogBase::toggleCollapsed()
507{
508 if ( mHelpCollapsed )
509 {
510 splitter->restoreState( mSplitterState );
511 mButtonCollapse->setArrowType( Qt::RightArrow );
512 }
513 else
514 {
515 mSplitterState = splitter->saveState();
516 splitter->setSizes( QList<int>() << 1 << 0 );
517 mButtonCollapse->setArrowType( Qt::LeftArrow );
518 }
519 mHelpCollapsed = !mHelpCollapsed;
520}
521
522void QgsProcessingAlgorithmDialogBase::splitterChanged( int, int )
523{
524 if ( splitter->sizes().at( 1 ) == 0 )
525 {
526 mHelpCollapsed = true;
527 mButtonCollapse->setArrowType( Qt::LeftArrow );
528 }
529 else
530 {
531 mHelpCollapsed = false;
532 mButtonCollapse->setArrowType( Qt::RightArrow );
533 }
534}
535
536void QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged( int )
537{
538 updateRunButtonVisibility();
539}
540
541void QgsProcessingAlgorithmDialogBase::linkClicked( const QUrl &url )
542{
543 QDesktopServices::openUrl( url.toString() );
544}
545
546void QgsProcessingAlgorithmDialogBase::algExecuted( bool successful, const QVariantMap & )
547{
548 mAlgorithmTask = nullptr;
549
550 if ( !successful )
551 {
552 // show dialog to display errors
553 show();
554 raise();
555 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
556 activateWindow();
557 showLog();
558 }
559 else
560 {
561 if ( isFinalized() && successful )
562 {
563 progressBar->setFormat( tr( "Complete" ) );
564 }
565
566 // delete dialog if closed
567 if ( isFinalized() && !isVisible() )
568 {
569 deleteLater();
570 }
571 }
572}
573
574void QgsProcessingAlgorithmDialogBase::taskTriggered( QgsTask *task )
575{
576 if ( task == mAlgorithmTask )
577 {
578 show();
579 raise();
580 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
581 activateWindow();
582 showLog();
583 }
584}
585
586void QgsProcessingAlgorithmDialogBase::closeClicked()
587{
588 reject();
589 close();
590}
591
592void QgsProcessingAlgorithmDialogBase::urlClicked( const QUrl &url )
593{
594 const QFileInfo file( url.toLocalFile() );
595 if ( file.exists() && !file.isDir() )
596 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
597 else
598 QDesktopServices::openUrl( url );
599}
600
601Qgis::ProcessingLogLevel QgsProcessingAlgorithmDialogBase::logLevel() const
602{
603 return mLogLevel;
604}
605
606void QgsProcessingAlgorithmDialogBase::setLogLevel( Qgis::ProcessingLogLevel level )
607{
608 mLogLevel = level;
609}
610
611void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
612{
613 setInfo( error, true );
614 if ( fatalError )
615 resetGui();
616 showLog();
617 processEvents();
618}
619
620void QgsProcessingAlgorithmDialogBase::pushWarning( const QString &warning )
621{
622 setInfo( warning, false, true, true );
623 processEvents();
624}
625
626void QgsProcessingAlgorithmDialogBase::pushInfo( const QString &info )
627{
628 setInfo( info );
629 processEvents();
630}
631
632void QgsProcessingAlgorithmDialogBase::pushFormattedMessage( const QString &html )
633{
634 setInfo( html, false, false );
635 processEvents();
636}
637
638void QgsProcessingAlgorithmDialogBase::pushCommandInfo( const QString &command )
639{
640 txtLog->append( QStringLiteral( "<code>%1<code>" ).arg( formatStringForLog( command.toHtmlEscaped() ) ) );
641 scrollToBottomOfLog();
642 processEvents();
643}
644
645void QgsProcessingAlgorithmDialogBase::pushDebugInfo( const QString &message )
646{
647 txtLog->append( QStringLiteral( "<span style=\"color:#777\">%1</span>" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
648 scrollToBottomOfLog();
649 processEvents();
650}
651
652void QgsProcessingAlgorithmDialogBase::pushConsoleInfo( const QString &info )
653{
654 txtLog->append( QStringLiteral( "<code style=\"color:#777\">%1</code>" ).arg( formatStringForLog( info.toHtmlEscaped() ) ) );
655 scrollToBottomOfLog();
656 processEvents();
657}
658
659QDialog *QgsProcessingAlgorithmDialogBase::createProgressDialog()
660{
661 QgsProcessingAlgorithmProgressDialog *dialog = new QgsProcessingAlgorithmProgressDialog( this );
662 dialog->setWindowModality( Qt::ApplicationModal );
663 dialog->setWindowTitle( windowTitle() );
664 dialog->setGeometry( geometry() ); // match size/position to this dialog
665 connect( progressBar, &QProgressBar::valueChanged, dialog->progressBar(), &QProgressBar::setValue );
666 connect( dialog->cancelButton(), &QPushButton::clicked, buttonCancel, &QPushButton::click );
667 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
668 connect( txtLog, &QTextEdit::textChanged, dialog, [this, dialog]()
669 {
670 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
671 QScrollBar *sb = dialog->logTextEdit()->verticalScrollBar();
672 sb->setValue( sb->maximum() );
673 } );
674 return dialog;
675}
676
677void QgsProcessingAlgorithmDialogBase::clearLog()
678{
679 txtLog->clear();
680}
681
682void QgsProcessingAlgorithmDialogBase::saveLog()
683{
684 QgsSettings settings;
685 const QString lastUsedDir = settings.value( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QDir::homePath() ).toString();
686
687 QString filter;
688 const QString txtExt = tr( "Text files" ) + QStringLiteral( " (*.txt *.TXT)" );
689 const QString htmlExt = tr( "HTML files" ) + QStringLiteral( " (*.html *.HTML)" );
690
691 const QString path = QFileDialog::getSaveFileName( this, tr( "Save Log to File" ), lastUsedDir, txtExt + ";;" + htmlExt, &filter );
692 // return dialog focus on Mac
693 activateWindow();
694 raise();
695 if ( path.isEmpty() )
696 {
697 return;
698 }
699
700 settings.setValue( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QFileInfo( path ).path() );
701
702 LogFormat format = FormatPlainText;
703 if ( filter == htmlExt )
704 {
705 format = FormatHtml;
706 }
707 saveLogToFile( path, format );
708}
709
710void QgsProcessingAlgorithmDialogBase::copyLogToClipboard()
711{
712 QMimeData *m = new QMimeData();
713 m->setText( txtLog->toPlainText() );
714 m->setHtml( txtLog->toHtml() );
715 QClipboard *cb = QApplication::clipboard();
716
717#ifdef Q_OS_LINUX
718 cb->setMimeData( m, QClipboard::Selection );
719#endif
720 cb->setMimeData( m, QClipboard::Clipboard );
721}
722
723void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
724{
725 if ( !mHelpCollapsed )
726 {
727 QgsSettings settings;
728 settings.setValue( QStringLiteral( "/Processing/dialogBaseSplitter" ), splitter->saveState() );
729 }
730
731 QDialog::closeEvent( e );
732
733 if ( !mAlgorithmTask && isFinalized() )
734 {
735 // when running a background task, the dialog is kept around and deleted only when the task
736 // completes. But if not running a task, we auto cleanup (later - gotta give callers a chance
737 // to retrieve results and execution status).
738 deleteLater();
739 }
740}
741
742void QgsProcessingAlgorithmDialogBase::runAlgorithm()
743{
744
745}
746
747void QgsProcessingAlgorithmDialogBase::setPercentage( double percent )
748{
749 // delay setting maximum progress value until we know algorithm reports progress
750 if ( progressBar->maximum() == 0 )
751 progressBar->setMaximum( 100 );
752 progressBar->setValue( percent );
753 processEvents();
754}
755
756void QgsProcessingAlgorithmDialogBase::setProgressText( const QString &text )
757{
758 lblProgress->setText( text );
759 setInfo( text, false );
760 scrollToBottomOfLog();
761 processEvents();
762}
763
764QString QgsProcessingAlgorithmDialogBase::formatHelp( QgsProcessingAlgorithm *algorithm )
765{
766 const QString text = algorithm->shortHelpString();
767 if ( !text.isEmpty() )
768 {
769 const QStringList paragraphs = text.split( '\n' );
770 QString help;
771 for ( const QString &paragraph : paragraphs )
772 {
773 help += QStringLiteral( "<p>%1</p>" ).arg( paragraph );
774 }
775 return QStringLiteral( "<h2>%1</h2>%2" ).arg( algorithm->displayName(), help );
776 }
777 else if ( !algorithm->shortDescription().isEmpty() )
778 {
779 return QStringLiteral( "<h2>%1</h2><p>%2</p>" ).arg( algorithm->displayName(), algorithm->shortDescription() );
780 }
781 else
782 return QString();
783}
784
785void QgsProcessingAlgorithmDialogBase::processEvents()
786{
787 if ( mAlgorithmTask )
788 {
789 // no need to call this - the algorithm is running in a thread.
790 // in fact, calling it causes a crash on Windows when the algorithm
791 // is running in a background thread... unfortunately we need something
792 // like this for non-threadable algorithms, otherwise there's no chance
793 // for users to hit cancel or see progress updates...
794 return;
795 }
796
797 // So that we get a chance of hitting the Abort button
798#ifdef Q_OS_LINUX
799 // One iteration is actually enough on Windows to get good interactivity
800 // whereas on Linux we must allow for far more iterations.
801 // For safety limit the number of iterations
802 int nIters = 0;
803 while ( ++nIters < 100 )
804#endif
805 {
806 QCoreApplication::processEvents();
807 }
808}
809
810void QgsProcessingAlgorithmDialogBase::scrollToBottomOfLog()
811{
812 QScrollBar *sb = txtLog->verticalScrollBar();
813 sb->setValue( sb->maximum() );
814}
815
816void QgsProcessingAlgorithmDialogBase::resetGui()
817{
818 lblProgress->clear();
819 progressBar->setMaximum( 100 );
820 progressBar->setValue( 0 );
821 mButtonRun->setEnabled( true );
822 mButtonChangeParameters->setEnabled( true );
823 mButtonClose->setEnabled( true );
824 if ( mMainWidget )
825 {
826 mMainWidget->setEnabled( true );
827 }
828 updateRunButtonVisibility();
829 resetAdditionalGui();
830}
831
832void QgsProcessingAlgorithmDialogBase::updateRunButtonVisibility()
833{
834 // Activate run button if current tab is Parameters
835 const bool runButtonVisible = mTabWidget->currentIndex() == 0;
836 mButtonRun->setVisible( runButtonVisible );
837 if ( runButtonVisible )
838 progressBar->resetFormat();
839 mButtonChangeParameters->setVisible( !runButtonVisible && mExecutedAnyResult && mButtonChangeParameters->isEnabled() );
840}
841
842void QgsProcessingAlgorithmDialogBase::resetAdditionalGui()
843{
844
845}
846
847void QgsProcessingAlgorithmDialogBase::blockControlsWhileRunning()
848{
849 mButtonRun->setEnabled( false );
850 mButtonChangeParameters->setEnabled( false );
851 if ( mMainWidget )
852 {
853 mMainWidget->setEnabled( false );
854 }
855 blockAdditionalControlsWhileRunning();
856}
857
858void QgsProcessingAlgorithmDialogBase::blockAdditionalControlsWhileRunning()
859{
860
861}
862
863QgsMessageBar *QgsProcessingAlgorithmDialogBase::messageBar()
864{
865 return mMessageBar;
866}
867
868void QgsProcessingAlgorithmDialogBase::hideShortHelp()
869{
870 textShortHelp->setVisible( false );
871}
872
873void QgsProcessingAlgorithmDialogBase::setCurrentTask( QgsProcessingAlgRunnerTask *task )
874{
875 mAlgorithmTask = task;
876 connect( mAlgorithmTask, &QgsProcessingAlgRunnerTask::executed, this, &QgsProcessingAlgorithmDialogBase::algExecuted );
877 QgsApplication::taskManager()->addTask( mAlgorithmTask );
878}
879
880QString QgsProcessingAlgorithmDialogBase::formatStringForLog( const QString &string )
881{
882 QString s = string;
883 s.replace( '\n', QLatin1String( "<br>" ) );
884 return s;
885}
886
887bool QgsProcessingAlgorithmDialogBase::isFinalized()
888{
889 return true;
890}
891
892void QgsProcessingAlgorithmDialogBase::applyContextOverrides( QgsProcessingContext *context )
893{
894 if ( !context )
895 return;
896
897 context->setLogLevel( logLevel() );
898
899 if ( mOverrideDefaultContextSettings )
900 {
901 context->setInvalidGeometryCheck( mGeometryCheck );
902 context->setDistanceUnit( mDistanceUnits );
903 context->setAreaUnit( mAreaUnits );
904 context->setTemporaryFolder( mTemporaryFolderOverride );
905 context->setMaximumThreads( mMaximumThreads );
906 }
907}
908
909void QgsProcessingAlgorithmDialogBase::setInfo( const QString &message, bool isError, bool escapeHtml, bool isWarning )
910{
911 constexpr int MESSAGE_COUNT_LIMIT = 10000;
912 // Avoid logging too many messages, which might blow memory.
913 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
914 return;
915 ++mMessageLoggedCount;
916
917 // note -- we have to wrap the message in a span block, or QTextEdit::append sometimes gets confused
918 // and varies between treating it as a HTML string or a plain text string! (see https://github.com/qgis/QGIS/issues/37934)
919 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
920 txtLog->append( QStringLiteral( "<span style=\"color:red\">%1</span>" ).arg( tr( "Message log truncated" ) ) );
921 else if ( isError || isWarning )
922 txtLog->append( QStringLiteral( "<span style=\"color:%1\">%2</span>" ).arg( isError ? QStringLiteral( "red" ) : QStringLiteral( "#b85a20" ), escapeHtml ? formatStringForLog( message.toHtmlEscaped() ) : formatStringForLog( message ) ) );
923 else if ( escapeHtml )
924 txtLog->append( QStringLiteral( "<span>%1</span" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
925 else
926 txtLog->append( QStringLiteral( "<span>%1</span>" ).arg( formatStringForLog( message ) ) );
927 scrollToBottomOfLog();
928 processEvents();
929}
930
931void QgsProcessingAlgorithmDialogBase::reject()
932{
933 if ( !mAlgorithmTask && isFinalized() )
934 {
935 setAttribute( Qt::WA_DeleteOnClose );
936 }
937 QDialog::reject();
938}
939
940//
941// QgsProcessingAlgorithmProgressDialog
942//
943
944QgsProcessingAlgorithmProgressDialog::QgsProcessingAlgorithmProgressDialog( QWidget *parent )
945 : QDialog( parent )
946{
947 setupUi( this );
948}
949
950QProgressBar *QgsProcessingAlgorithmProgressDialog::progressBar()
951{
952 return mProgressBar;
953}
954
955QPushButton *QgsProcessingAlgorithmProgressDialog::cancelButton()
956{
957 return mButtonBox->button( QDialogButtonBox::Cancel );
958}
959
960QTextEdit *QgsProcessingAlgorithmProgressDialog::logTextEdit()
961{
962 return mTxtLog;
963}
964
965void QgsProcessingAlgorithmProgressDialog::reject()
966{
967
968}
969
970
971//
972// QgsProcessingContextOptionsWidget
973//
974
975QgsProcessingContextOptionsWidget::QgsProcessingContextOptionsWidget( QWidget *parent )
976 : QgsPanelWidget( parent )
977{
978 setupUi( this );
979 setPanelTitle( tr( "Algorithm Settings" ) );
980
981 mComboInvalidFeatureFiltering->addItem( tr( "Do not Filter (Better Performance)" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::NoCheck ) );
982 mComboInvalidFeatureFiltering->addItem( tr( "Skip (Ignore) Features with Invalid Geometries" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::SkipInvalid ) );
983 mComboInvalidFeatureFiltering->addItem( tr( "Stop Algorithm Execution When a Geometry is Invalid" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::AbortOnInvalid ) );
984
985 mTemporaryFolderWidget->setDialogTitle( tr( "Select Temporary Directory" ) );
986 mTemporaryFolderWidget->setStorageMode( QgsFileWidget::GetDirectory );
987 mTemporaryFolderWidget->lineEdit()->setPlaceholderText( tr( "Default" ) );
988
989 mLogLevelComboBox->addItem( tr( "Default" ), static_cast< int >( Qgis::ProcessingLogLevel::DefaultLevel ) );
990 mLogLevelComboBox->addItem( tr( "Verbose" ), static_cast< int >( Qgis::ProcessingLogLevel::Verbose ) );
991 mLogLevelComboBox->addItem( tr( "Verbose (Model Debugging)" ), static_cast< int >( Qgis::ProcessingLogLevel::ModelDebug ) );
992
993 mDistanceUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::DistanceUnit::Unknown ) );
994 for ( Qgis::DistanceUnit unit :
995 {
1006 } )
1007 {
1008 QString title;
1010 {
1012 }
1013 else
1014 {
1015 title = QgsUnitTypes::toString( unit );
1016 }
1017
1018 mDistanceUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1019 }
1020
1021 mAreaUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::AreaUnit::Unknown ) );
1022 for ( Qgis::AreaUnit unit :
1023 {
1036 } )
1037 {
1038 QString title;
1040 {
1042 }
1043 else
1044 {
1045 title = QgsUnitTypes::toString( unit );
1046 }
1047
1048 mAreaUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1049 }
1050
1051 mThreadsSpinBox->setRange( 1, QThread::idealThreadCount() );
1052
1053 connect( mLogLevelComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1054 connect( mComboInvalidFeatureFiltering, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1055 connect( mDistanceUnitsCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1056 connect( mAreaUnitsCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1057 connect( mTemporaryFolderWidget, &QgsFileWidget::fileChanged, this, &QgsPanelWidget::widgetChanged );
1058 connect( mThreadsSpinBox, qOverload< int >( &QSpinBox::valueChanged ), this, &QgsPanelWidget::widgetChanged );
1059}
1060
1061void QgsProcessingContextOptionsWidget::setFromContext( const QgsProcessingContext *context )
1062{
1063 whileBlocking( mComboInvalidFeatureFiltering )->setCurrentIndex( mComboInvalidFeatureFiltering->findData( QVariant::fromValue( context->invalidGeometryCheck() ) ) );
1064 whileBlocking( mDistanceUnitsCombo )->setCurrentIndex( mDistanceUnitsCombo->findData( QVariant::fromValue( context->distanceUnit() ) ) );
1065 whileBlocking( mAreaUnitsCombo )->setCurrentIndex( mAreaUnitsCombo->findData( QVariant::fromValue( context->areaUnit() ) ) );
1066 whileBlocking( mTemporaryFolderWidget )->setFilePath( context->temporaryFolder() );
1067 whileBlocking( mThreadsSpinBox )->setValue( context->maximumThreads() );
1068 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast< int >( context->logLevel() ) ) );
1069}
1070
1071Qgis::InvalidGeometryCheck QgsProcessingContextOptionsWidget::invalidGeometryCheck() const
1072{
1073 return mComboInvalidFeatureFiltering->currentData().value< Qgis::InvalidGeometryCheck >();
1074}
1075
1076Qgis::DistanceUnit QgsProcessingContextOptionsWidget::distanceUnit() const
1077{
1078 return mDistanceUnitsCombo->currentData().value< Qgis::DistanceUnit >();
1079}
1080
1081Qgis::AreaUnit QgsProcessingContextOptionsWidget::areaUnit() const
1082{
1083 return mAreaUnitsCombo->currentData().value< Qgis::AreaUnit >();
1084}
1085
1086QString QgsProcessingContextOptionsWidget::temporaryFolder()
1087{
1088 return mTemporaryFolderWidget->filePath();
1089}
1090
1091int QgsProcessingContextOptionsWidget::maximumThreads() const
1092{
1093 return mThreadsSpinBox->value();
1094}
1095
1096void QgsProcessingContextOptionsWidget::setLogLevel( Qgis::ProcessingLogLevel level )
1097{
1098 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast< int >( level ) ) );
1099}
1100
1101Qgis::ProcessingLogLevel QgsProcessingContextOptionsWidget::logLevel() const
1102{
1103 return static_cast< Qgis::ProcessingLogLevel >( mLogLevelComboBox->currentData().toInt() );
1104}
1105
DistanceUnit
Units of distance.
Definition qgis.h:4363
@ Feet
Imperial feet.
@ Centimeters
Centimeters.
@ Millimeters
Millimeters.
@ Miles
Terrestrial miles.
@ Unknown
Unknown distance unit.
@ Yards
Imperial yards.
@ Degrees
Degrees, for planar geographic CRS distance measurements.
@ Inches
Inches (since QGIS 3.32)
@ NauticalMiles
Nautical miles.
@ Kilometers
Kilometers.
AreaUnit
Units of area.
Definition qgis.h:4401
@ SquareFeet
Square feet.
@ SquareCentimeters
Square centimeters.
@ SquareInches
Square inches (since QGIS 3.32)
@ SquareNauticalMiles
Square nautical miles.
@ SquareMillimeters
Square millimeters.
@ SquareYards
Square yards.
@ Hectares
Hectares.
@ SquareKilometers
Square kilometers.
@ SquareMeters
Square meters.
@ Unknown
Unknown areal unit.
@ SquareDegrees
Square degrees, for planar geographic CRS area measurements.
@ SquareMiles
Square miles.
@ Warning
Warning message.
Definition qgis.h:101
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:1875
@ NoCheck
No invalid geometry checking.
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
@ SkipInvalid
Skip any features with invalid geometry. This requires a slow geometry validity check for every featu...
@ NotAvailableInStandaloneTool
Algorithm should not be available from the standalone "qgis_process" tool. Used to flag algorithms wh...
@ DisplayNameIsLiteral
Algorithm's display name is a static literal string, and should not be translated or automatically fo...
ProcessingLogLevel
Logging level for algorithms to use when pushing feedback messages.
Definition qgis.h:3102
@ DefaultLevel
Default logging level.
@ Verbose
Verbose logging.
@ ModelDebug
Model debug level logging. Includes verbose logging and other outputs useful for debugging models (si...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
void cancel()
Tells the internal routines that the current operation should be canceled. This should be run by the ...
@ GetDirectory
Select a directory.
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:194
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
Definition qgsgui.h:255
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition qgsgui.cpp:79
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Definition qgsgui.cpp:218
static QUrl helpUrl(const QString &key)
Returns URI of the help topic for the given key.
Definition qgshelp.cpp:44
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned and ...
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
A bar for displaying non-blocking messages to the user.
Base class for any widget that can be shown as a inline panel.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
void widgetChanged()
Emitted when the widget state changes.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
QgsTask task which runs a QgsProcessingAlgorithm in a background task.
void executed(bool successful, const QVariantMap &results)
Emitted when the algorithm has finished execution.
Abstract base class for processing algorithms.
virtual QString helpUrl() const
Returns a url pointing to the algorithm's help page.
virtual QString shortHelpString() const
Returns a localised short helper string for the algorithm.
virtual QString shortDescription() const
Returns an optional translated short description of the algorithm.
virtual QString displayName() const =0
Returns the translated algorithm name, which should be used for any user-visible display of the algor...
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
Contains information about the context in which a processing algorithm is executed.
Qgis::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
void setLogLevel(Qgis::ProcessingLogLevel level)
Sets the logging level for algorithms to use when pushing feedback messages to users.
void setMaximumThreads(int threads)
Sets the (optional) number of threads to use when running algorithms.
void setDistanceUnit(Qgis::DistanceUnit unit)
Sets the unit to use for distance calculations.
void setInvalidGeometryCheck(Qgis::InvalidGeometryCheck check)
Sets the behavior used for checking invalid geometries in input layers.
void setAreaUnit(Qgis::AreaUnit areaUnit)
Sets the unit to use for area calculations.
Qgis::DistanceUnit distanceUnit() const
Returns the distance unit to use for distance calculations.
Qgis::ProcessingLogLevel logLevel() const
Returns the logging level for algorithms to use when pushing feedback messages to users.
Qgis::InvalidGeometryCheck invalidGeometryCheck() const
Returns the behavior used for checking invalid geometries in input layers.
void setTemporaryFolder(const QString &folder)
Sets the (optional) temporary folder to use when running algorithms.
QString temporaryFolder() const
Returns the (optional) temporary folder to use when running algorithms.
int maximumThreads() const
Returns the (optional) number of threads to use when running algorithms.
Qgis::ProcessingAlgorithmFlags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Base class for providing feedback from a processing algorithm.
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.
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.
virtual QString helpId() const
Returns the provider help id string, used for creating QgsHelp urls for algorithms belong to this pro...
virtual QString warningMessage() const
Returns an optional warning message to show users when running algorithms from this provider.
static QVariantMap preprocessQgisProcessParameters(const QVariantMap &parameters, bool &ok, QString &error)
Pre-processes a set of parameter values for the qgis_process command.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QString capitalize(const QString &string, Qgis::Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskTriggered(QgsTask *task)
Emitted when a task is triggered.
Abstract base class for long running background tasks.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
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
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5369