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