QGIS API Documentation 3.40.0-Bratislava (b56115d8743)
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 = mAlgorithm->group().isEmpty()
337 ? QgsStringUtils::capitalize( mAlgorithm->displayName(), Qgis::Capitalization::TitleCase )
338 : QStringLiteral( "%1 - %2" ).arg( QgsStringUtils::capitalize( mAlgorithm->group(), Qgis::Capitalization::TitleCase ), QgsStringUtils::capitalize( mAlgorithm->displayName(), Qgis::Capitalization::TitleCase ) );
339 }
340 else
341 {
342 title = mAlgorithm->group().isEmpty()
343 ? mAlgorithm->displayName()
344 : QStringLiteral( "%1 - %2" ).arg( mAlgorithm->group(), mAlgorithm->displayName() );
345 }
346
347 setWindowTitle( title );
348
349 const QString algHelp = formatHelp( algorithm );
350 if ( algHelp.isEmpty() )
351 textShortHelp->hide();
352 else
353 {
354 textShortHelp->document()->setDefaultStyleSheet( QStringLiteral( ".summary { margin-left: 10px; margin-right: 10px; }\n"
355 "h2 { color: #555555; padding-bottom: 15px; }\n"
356 "a { text - decoration: none; color: #3498db; font-weight: bold; }\n"
357 "p, ul, li { color: #666666; }\n"
358 "b { color: #333333; }\n"
359 "dl dd { margin - bottom: 5px; }" ) );
360 textShortHelp->setHtml( algHelp );
361 connect( textShortHelp, &QTextBrowser::anchorClicked, this, &QgsProcessingAlgorithmDialogBase::linkClicked );
362 textShortHelp->show();
363 }
364
365 if ( algorithm->helpUrl().isEmpty() && ( !algorithm->provider() || algorithm->provider()->helpId().isEmpty() ) )
366 {
367 mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Help ) );
368 }
369
370 const QString warning = algorithm->provider() ? algorithm->provider()->warningMessage() : QString();
371 if ( !warning.isEmpty() )
372 {
373 mMessageBar->pushMessage( warning, Qgis::MessageLevel::Warning );
374 }
375}
376
377QgsProcessingAlgorithm *QgsProcessingAlgorithmDialogBase::algorithm()
378{
379 return mAlgorithm.get();
380}
381
382void QgsProcessingAlgorithmDialogBase::setMainWidget( QgsPanelWidget *widget )
383{
384 if ( mMainWidget )
385 {
386 mMainWidget->deleteLater();
387 }
388
389 mPanelStack->setMainPanel( widget );
390 widget->setDockMode( true );
391
392 mMainWidget = widget;
393 connect( mMainWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
394}
395
396QgsPanelWidget *QgsProcessingAlgorithmDialogBase::mainWidget()
397{
398 return mMainWidget;
399}
400
401void QgsProcessingAlgorithmDialogBase::saveLogToFile( const QString &path, const LogFormat format )
402{
403 QFile logFile( path );
404 if ( !logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
405 {
406 return;
407 }
408 QTextStream fout( &logFile );
409
410 switch ( format )
411 {
412 case FormatPlainText:
413 fout << txtLog->toPlainText();
414 break;
415
416 case FormatHtml:
417 fout << txtLog->toHtml();
418 break;
419 }
420}
421
422QgsProcessingFeedback *QgsProcessingAlgorithmDialogBase::createFeedback()
423{
424 auto feedback = std::make_unique< QgsProcessingAlgorithmDialogFeedback >();
425 connect( feedback.get(), &QgsProcessingFeedback::progressChanged, this, &QgsProcessingAlgorithmDialogBase::setPercentage );
426 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::commandInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushCommandInfo );
427 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::consoleInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushConsoleInfo );
428 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::debugInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushDebugInfo );
429 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::errorReported, this, &QgsProcessingAlgorithmDialogBase::reportError );
430 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::warningPushed, this, &QgsProcessingAlgorithmDialogBase::pushWarning );
431 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::infoPushed, this, &QgsProcessingAlgorithmDialogBase::pushInfo );
432 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::formattedMessagePushed, this, &QgsProcessingAlgorithmDialogBase::pushFormattedMessage );
433 connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::progressTextChanged, this, &QgsProcessingAlgorithmDialogBase::setProgressText );
434 connect( buttonCancel, &QPushButton::clicked, feedback.get(), &QgsProcessingFeedback::cancel );
435 return feedback.release();
436}
437
438QDialogButtonBox *QgsProcessingAlgorithmDialogBase::buttonBox()
439{
440 return mButtonBox;
441}
442
443QTabWidget *QgsProcessingAlgorithmDialogBase::tabWidget()
444{
445 return mTabWidget;
446}
447
448void QgsProcessingAlgorithmDialogBase::showLog()
449{
450 mTabWidget->setCurrentIndex( 1 );
451}
452
453void QgsProcessingAlgorithmDialogBase::showParameters()
454{
455 mTabWidget->setCurrentIndex( 0 );
456}
457
458QPushButton *QgsProcessingAlgorithmDialogBase::runButton()
459{
460 return mButtonRun;
461}
462
463QPushButton *QgsProcessingAlgorithmDialogBase::cancelButton()
464{
465 return buttonCancel;
466}
467
468QPushButton *QgsProcessingAlgorithmDialogBase::changeParametersButton()
469{
470 return mButtonChangeParameters;
471}
472
473void QgsProcessingAlgorithmDialogBase::clearProgress()
474{
475 progressBar->setMaximum( 0 );
476}
477
478void QgsProcessingAlgorithmDialogBase::setExecuted( bool executed )
479{
480 mExecuted = executed;
481}
482
483void QgsProcessingAlgorithmDialogBase::setExecutedAnyResult( bool executedAnyResult )
484{
485 mExecutedAnyResult = executedAnyResult;
486}
487
488void QgsProcessingAlgorithmDialogBase::setResults( const QVariantMap &results )
489{
490 mResults = results;
491}
492
493void QgsProcessingAlgorithmDialogBase::finished( bool, const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
494{
495
496}
497
498void QgsProcessingAlgorithmDialogBase::openHelp()
499{
500 QUrl algHelp = mAlgorithm->helpUrl();
501 if ( algHelp.isEmpty() && mAlgorithm->provider() )
502 {
503 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() ) ) );
504 }
505
506 if ( !algHelp.isEmpty() )
507 QDesktopServices::openUrl( algHelp );
508}
509
510void QgsProcessingAlgorithmDialogBase::toggleCollapsed()
511{
512 if ( mHelpCollapsed )
513 {
514 splitter->restoreState( mSplitterState );
515 mButtonCollapse->setArrowType( Qt::RightArrow );
516 }
517 else
518 {
519 mSplitterState = splitter->saveState();
520 splitter->setSizes( QList<int>() << 1 << 0 );
521 mButtonCollapse->setArrowType( Qt::LeftArrow );
522 }
523 mHelpCollapsed = !mHelpCollapsed;
524}
525
526void QgsProcessingAlgorithmDialogBase::splitterChanged( int, int )
527{
528 if ( splitter->sizes().at( 1 ) == 0 )
529 {
530 mHelpCollapsed = true;
531 mButtonCollapse->setArrowType( Qt::LeftArrow );
532 }
533 else
534 {
535 mHelpCollapsed = false;
536 mButtonCollapse->setArrowType( Qt::RightArrow );
537 }
538}
539
540void QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged( int )
541{
542 updateRunButtonVisibility();
543}
544
545void QgsProcessingAlgorithmDialogBase::linkClicked( const QUrl &url )
546{
547 QDesktopServices::openUrl( url.toString() );
548}
549
550void QgsProcessingAlgorithmDialogBase::algExecuted( bool successful, const QVariantMap & )
551{
552 mAlgorithmTask = nullptr;
553
554 if ( !successful )
555 {
556 // show dialog to display errors
557 show();
558 raise();
559 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
560 activateWindow();
561 showLog();
562 }
563 else
564 {
565 if ( isFinalized() && successful )
566 {
567 progressBar->setFormat( tr( "Complete" ) );
568 }
569
570 // delete dialog if closed
571 if ( isFinalized() && !isVisible() )
572 {
573 deleteLater();
574 }
575 }
576}
577
578void QgsProcessingAlgorithmDialogBase::taskTriggered( QgsTask *task )
579{
580 if ( task == mAlgorithmTask )
581 {
582 show();
583 raise();
584 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
585 activateWindow();
586 showLog();
587 }
588}
589
590void QgsProcessingAlgorithmDialogBase::closeClicked()
591{
592 reject();
593 close();
594}
595
596void QgsProcessingAlgorithmDialogBase::urlClicked( const QUrl &url )
597{
598 const QFileInfo file( url.toLocalFile() );
599 if ( file.exists() && !file.isDir() )
600 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
601 else
602 QDesktopServices::openUrl( url );
603}
604
605Qgis::ProcessingLogLevel QgsProcessingAlgorithmDialogBase::logLevel() const
606{
607 return mLogLevel;
608}
609
610void QgsProcessingAlgorithmDialogBase::setLogLevel( Qgis::ProcessingLogLevel level )
611{
612 mLogLevel = level;
613}
614
615void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
616{
617 setInfo( error, true );
618 if ( fatalError )
619 resetGui();
620 showLog();
621 processEvents();
622}
623
624void QgsProcessingAlgorithmDialogBase::pushWarning( const QString &warning )
625{
626 setInfo( warning, false, true, true );
627 processEvents();
628}
629
630void QgsProcessingAlgorithmDialogBase::pushInfo( const QString &info )
631{
632 setInfo( info );
633 processEvents();
634}
635
636void QgsProcessingAlgorithmDialogBase::pushFormattedMessage( const QString &html )
637{
638 setInfo( html, false, false );
639 processEvents();
640}
641
642void QgsProcessingAlgorithmDialogBase::pushCommandInfo( const QString &command )
643{
644 txtLog->append( QStringLiteral( "<code>%1<code>" ).arg( formatStringForLog( command.toHtmlEscaped() ) ) );
645 scrollToBottomOfLog();
646 processEvents();
647}
648
649void QgsProcessingAlgorithmDialogBase::pushDebugInfo( const QString &message )
650{
651 txtLog->append( QStringLiteral( "<span style=\"color:#777\">%1</span>" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
652 scrollToBottomOfLog();
653 processEvents();
654}
655
656void QgsProcessingAlgorithmDialogBase::pushConsoleInfo( const QString &info )
657{
658 txtLog->append( QStringLiteral( "<code style=\"color:#777\">%1</code>" ).arg( formatStringForLog( info.toHtmlEscaped() ) ) );
659 scrollToBottomOfLog();
660 processEvents();
661}
662
663QDialog *QgsProcessingAlgorithmDialogBase::createProgressDialog()
664{
665 QgsProcessingAlgorithmProgressDialog *dialog = new QgsProcessingAlgorithmProgressDialog( this );
666 dialog->setWindowModality( Qt::ApplicationModal );
667 dialog->setWindowTitle( windowTitle() );
668 dialog->setGeometry( geometry() ); // match size/position to this dialog
669 connect( progressBar, &QProgressBar::valueChanged, dialog->progressBar(), &QProgressBar::setValue );
670 connect( dialog->cancelButton(), &QPushButton::clicked, buttonCancel, &QPushButton::click );
671 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
672 connect( txtLog, &QTextEdit::textChanged, dialog, [this, dialog]()
673 {
674 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
675 QScrollBar *sb = dialog->logTextEdit()->verticalScrollBar();
676 sb->setValue( sb->maximum() );
677 } );
678 return dialog;
679}
680
681void QgsProcessingAlgorithmDialogBase::clearLog()
682{
683 txtLog->clear();
684}
685
686void QgsProcessingAlgorithmDialogBase::saveLog()
687{
688 QgsSettings settings;
689 const QString lastUsedDir = settings.value( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QDir::homePath() ).toString();
690
691 QString filter;
692 const QString txtExt = tr( "Text files" ) + QStringLiteral( " (*.txt *.TXT)" );
693 const QString htmlExt = tr( "HTML files" ) + QStringLiteral( " (*.html *.HTML)" );
694
695 const QString path = QFileDialog::getSaveFileName( this, tr( "Save Log to File" ), lastUsedDir, txtExt + ";;" + htmlExt, &filter );
696 // return dialog focus on Mac
697 activateWindow();
698 raise();
699 if ( path.isEmpty() )
700 {
701 return;
702 }
703
704 settings.setValue( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QFileInfo( path ).path() );
705
706 LogFormat format = FormatPlainText;
707 if ( filter == htmlExt )
708 {
709 format = FormatHtml;
710 }
711 saveLogToFile( path, format );
712}
713
714void QgsProcessingAlgorithmDialogBase::copyLogToClipboard()
715{
716 QMimeData *m = new QMimeData();
717 m->setText( txtLog->toPlainText() );
718 m->setHtml( txtLog->toHtml() );
719 QClipboard *cb = QApplication::clipboard();
720
721#ifdef Q_OS_LINUX
722 cb->setMimeData( m, QClipboard::Selection );
723#endif
724 cb->setMimeData( m, QClipboard::Clipboard );
725}
726
727void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
728{
729 if ( !mHelpCollapsed )
730 {
731 QgsSettings settings;
732 settings.setValue( QStringLiteral( "/Processing/dialogBaseSplitter" ), splitter->saveState() );
733 }
734
735 QDialog::closeEvent( e );
736
737 if ( !mAlgorithmTask && isFinalized() )
738 {
739 // when running a background task, the dialog is kept around and deleted only when the task
740 // completes. But if not running a task, we auto cleanup (later - gotta give callers a chance
741 // to retrieve results and execution status).
742 deleteLater();
743 }
744}
745
746void QgsProcessingAlgorithmDialogBase::runAlgorithm()
747{
748
749}
750
751void QgsProcessingAlgorithmDialogBase::setPercentage( double percent )
752{
753 // delay setting maximum progress value until we know algorithm reports progress
754 if ( progressBar->maximum() == 0 )
755 progressBar->setMaximum( 100 );
756 progressBar->setValue( percent );
757 processEvents();
758}
759
760void QgsProcessingAlgorithmDialogBase::setProgressText( const QString &text )
761{
762 lblProgress->setText( text );
763 setInfo( text, false );
764 scrollToBottomOfLog();
765 processEvents();
766}
767
768QString QgsProcessingAlgorithmDialogBase::formatHelp( QgsProcessingAlgorithm *algorithm )
769{
770 QString result;
771 const QString text = algorithm->shortHelpString();
772 if ( !text.isEmpty() )
773 {
774 const QStringList paragraphs = text.split( '\n' );
775 QString help;
776 for ( const QString &paragraph : paragraphs )
777 {
778 help += QStringLiteral( "<p>%1</p>" ).arg( paragraph );
779 }
780 result = QStringLiteral( "<h2>%1</h2>%2" ).arg( algorithm->displayName(), help );
781 }
782 else if ( !algorithm->shortDescription().isEmpty() )
783 {
784 result = QStringLiteral( "<h2>%1</h2><p>%2</p>" ).arg( algorithm->displayName(), algorithm->shortDescription() );
785 }
786
788 {
789 QStringList flags;
790 for ( Qgis::ProcessingAlgorithmDocumentationFlag flag : qgsEnumList< Qgis::ProcessingAlgorithmDocumentationFlag>() )
791 {
792 if ( algorithm->documentationFlags() & flag )
793 {
795 }
796 }
797 result += QStringLiteral( "<ul><li><i>%1</i></li></ul>" ).arg( flags.join( QLatin1String( "</i></li><li><i>" ) ) );
798 }
800 {
801 result += QStringLiteral( "<p><b>%1</b></p>" ).arg(
802 tr( "Warning: This algorithm is a potential security risk if executed with unchecked inputs, and may result in system damage or data leaks." )
803 );
804 }
806 {
807 result += QStringLiteral( "<p><b>%1</b></p>" ).arg(
808 tr( "Warning: This algorithm has known issues. The results must be carefully validated by the user." )
809 );
810 }
811
812 return result;
813}
814
815void QgsProcessingAlgorithmDialogBase::processEvents()
816{
817 if ( mAlgorithmTask )
818 {
819 // no need to call this - the algorithm is running in a thread.
820 // in fact, calling it causes a crash on Windows when the algorithm
821 // is running in a background thread... unfortunately we need something
822 // like this for non-threadable algorithms, otherwise there's no chance
823 // for users to hit cancel or see progress updates...
824 return;
825 }
826
827 // So that we get a chance of hitting the Abort button
828#ifdef Q_OS_LINUX
829 // One iteration is actually enough on Windows to get good interactivity
830 // whereas on Linux we must allow for far more iterations.
831 // For safety limit the number of iterations
832 int nIters = 0;
833 while ( ++nIters < 100 )
834#endif
835 {
836 QCoreApplication::processEvents();
837 }
838}
839
840void QgsProcessingAlgorithmDialogBase::scrollToBottomOfLog()
841{
842 QScrollBar *sb = txtLog->verticalScrollBar();
843 sb->setValue( sb->maximum() );
844}
845
846void QgsProcessingAlgorithmDialogBase::resetGui()
847{
848 lblProgress->clear();
849 progressBar->setMaximum( 100 );
850 progressBar->setValue( 0 );
851 mButtonRun->setEnabled( true );
852 mButtonChangeParameters->setEnabled( true );
853 mButtonClose->setEnabled( true );
854 if ( mMainWidget )
855 {
856 mMainWidget->setEnabled( true );
857 }
858 updateRunButtonVisibility();
859 resetAdditionalGui();
860}
861
862void QgsProcessingAlgorithmDialogBase::updateRunButtonVisibility()
863{
864 // Activate run button if current tab is Parameters
865 const bool runButtonVisible = mTabWidget->currentIndex() == 0;
866 mButtonRun->setVisible( runButtonVisible );
867 if ( runButtonVisible )
868 progressBar->resetFormat();
869 mButtonChangeParameters->setVisible( !runButtonVisible && mExecutedAnyResult && mButtonChangeParameters->isEnabled() );
870}
871
872void QgsProcessingAlgorithmDialogBase::resetAdditionalGui()
873{
874
875}
876
877void QgsProcessingAlgorithmDialogBase::blockControlsWhileRunning()
878{
879 mButtonRun->setEnabled( false );
880 mButtonChangeParameters->setEnabled( false );
881 if ( mMainWidget )
882 {
883 mMainWidget->setEnabled( false );
884 }
885 blockAdditionalControlsWhileRunning();
886}
887
888void QgsProcessingAlgorithmDialogBase::blockAdditionalControlsWhileRunning()
889{
890
891}
892
893QgsMessageBar *QgsProcessingAlgorithmDialogBase::messageBar()
894{
895 return mMessageBar;
896}
897
898void QgsProcessingAlgorithmDialogBase::hideShortHelp()
899{
900 textShortHelp->setVisible( false );
901}
902
903void QgsProcessingAlgorithmDialogBase::setCurrentTask( QgsProcessingAlgRunnerTask *task )
904{
905 mAlgorithmTask = task;
906 connect( mAlgorithmTask, &QgsProcessingAlgRunnerTask::executed, this, &QgsProcessingAlgorithmDialogBase::algExecuted );
907 QgsApplication::taskManager()->addTask( mAlgorithmTask );
908}
909
910QString QgsProcessingAlgorithmDialogBase::formatStringForLog( const QString &string )
911{
912 QString s = string;
913 s.replace( '\n', QLatin1String( "<br>" ) );
914 return s;
915}
916
917bool QgsProcessingAlgorithmDialogBase::isFinalized()
918{
919 return true;
920}
921
922void QgsProcessingAlgorithmDialogBase::applyContextOverrides( QgsProcessingContext *context )
923{
924 if ( !context )
925 return;
926
927 context->setLogLevel( logLevel() );
928
929 if ( mOverrideDefaultContextSettings )
930 {
931 context->setInvalidGeometryCheck( mGeometryCheck );
932 context->setDistanceUnit( mDistanceUnits );
933 context->setAreaUnit( mAreaUnits );
934 context->setTemporaryFolder( mTemporaryFolderOverride );
935 context->setMaximumThreads( mMaximumThreads );
936 }
937}
938
939void QgsProcessingAlgorithmDialogBase::setInfo( const QString &message, bool isError, bool escapeHtml, bool isWarning )
940{
941 constexpr int MESSAGE_COUNT_LIMIT = 10000;
942 // Avoid logging too many messages, which might blow memory.
943 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
944 return;
945 ++mMessageLoggedCount;
946
947 // note -- we have to wrap the message in a span block, or QTextEdit::append sometimes gets confused
948 // and varies between treating it as a HTML string or a plain text string! (see https://github.com/qgis/QGIS/issues/37934)
949 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
950 txtLog->append( QStringLiteral( "<span style=\"color:red\">%1</span>" ).arg( tr( "Message log truncated" ) ) );
951 else if ( isError || isWarning )
952 txtLog->append( QStringLiteral( "<span style=\"color:%1\">%2</span>" ).arg( isError ? QStringLiteral( "red" ) : QStringLiteral( "#b85a20" ), escapeHtml ? formatStringForLog( message.toHtmlEscaped() ) : formatStringForLog( message ) ) );
953 else if ( escapeHtml )
954 txtLog->append( QStringLiteral( "<span>%1</span" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
955 else
956 txtLog->append( QStringLiteral( "<span>%1</span>" ).arg( formatStringForLog( message ) ) );
957 scrollToBottomOfLog();
958 processEvents();
959}
960
961void QgsProcessingAlgorithmDialogBase::reject()
962{
963 if ( !mAlgorithmTask && isFinalized() )
964 {
965 setAttribute( Qt::WA_DeleteOnClose );
966 }
967 QDialog::reject();
968}
969
970//
971// QgsProcessingAlgorithmProgressDialog
972//
973
974QgsProcessingAlgorithmProgressDialog::QgsProcessingAlgorithmProgressDialog( QWidget *parent )
975 : QDialog( parent )
976{
977 setupUi( this );
978}
979
980QProgressBar *QgsProcessingAlgorithmProgressDialog::progressBar()
981{
982 return mProgressBar;
983}
984
985QPushButton *QgsProcessingAlgorithmProgressDialog::cancelButton()
986{
987 return mButtonBox->button( QDialogButtonBox::Cancel );
988}
989
990QTextEdit *QgsProcessingAlgorithmProgressDialog::logTextEdit()
991{
992 return mTxtLog;
993}
994
995void QgsProcessingAlgorithmProgressDialog::reject()
996{
997
998}
999
1000
1001//
1002// QgsProcessingContextOptionsWidget
1003//
1004
1005QgsProcessingContextOptionsWidget::QgsProcessingContextOptionsWidget( QWidget *parent )
1006 : QgsPanelWidget( parent )
1007{
1008 setupUi( this );
1009 setPanelTitle( tr( "Algorithm Settings" ) );
1010
1011 mComboInvalidFeatureFiltering->addItem( tr( "Do not Filter (Better Performance)" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::NoCheck ) );
1012 mComboInvalidFeatureFiltering->addItem( tr( "Skip (Ignore) Features with Invalid Geometries" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::SkipInvalid ) );
1013 mComboInvalidFeatureFiltering->addItem( tr( "Stop Algorithm Execution When a Geometry is Invalid" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::AbortOnInvalid ) );
1014
1015 mTemporaryFolderWidget->setDialogTitle( tr( "Select Temporary Directory" ) );
1016 mTemporaryFolderWidget->setStorageMode( QgsFileWidget::GetDirectory );
1017 mTemporaryFolderWidget->lineEdit()->setPlaceholderText( tr( "Default" ) );
1018
1019 mLogLevelComboBox->addItem( tr( "Default" ), static_cast< int >( Qgis::ProcessingLogLevel::DefaultLevel ) );
1020 mLogLevelComboBox->addItem( tr( "Verbose" ), static_cast< int >( Qgis::ProcessingLogLevel::Verbose ) );
1021 mLogLevelComboBox->addItem( tr( "Verbose (Model Debugging)" ), static_cast< int >( Qgis::ProcessingLogLevel::ModelDebug ) );
1022
1023 mDistanceUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::DistanceUnit::Unknown ) );
1024 for ( Qgis::DistanceUnit unit :
1025 {
1036 } )
1037 {
1038 QString title;
1040 {
1042 }
1043 else
1044 {
1045 title = QgsUnitTypes::toString( unit );
1046 }
1047
1048 mDistanceUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1049 }
1050
1051 mAreaUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::AreaUnit::Unknown ) );
1052 for ( Qgis::AreaUnit unit :
1053 {
1066 } )
1067 {
1068 QString title;
1070 {
1072 }
1073 else
1074 {
1075 title = QgsUnitTypes::toString( unit );
1076 }
1077
1078 mAreaUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1079 }
1080
1081 mThreadsSpinBox->setRange( 1, QThread::idealThreadCount() );
1082
1083 connect( mLogLevelComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1084 connect( mComboInvalidFeatureFiltering, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1085 connect( mDistanceUnitsCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1086 connect( mAreaUnitsCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1087 connect( mTemporaryFolderWidget, &QgsFileWidget::fileChanged, this, &QgsPanelWidget::widgetChanged );
1088 connect( mThreadsSpinBox, qOverload< int >( &QSpinBox::valueChanged ), this, &QgsPanelWidget::widgetChanged );
1089}
1090
1091void QgsProcessingContextOptionsWidget::setFromContext( const QgsProcessingContext *context )
1092{
1093 whileBlocking( mComboInvalidFeatureFiltering )->setCurrentIndex( mComboInvalidFeatureFiltering->findData( QVariant::fromValue( context->invalidGeometryCheck() ) ) );
1094 whileBlocking( mDistanceUnitsCombo )->setCurrentIndex( mDistanceUnitsCombo->findData( QVariant::fromValue( context->distanceUnit() ) ) );
1095 whileBlocking( mAreaUnitsCombo )->setCurrentIndex( mAreaUnitsCombo->findData( QVariant::fromValue( context->areaUnit() ) ) );
1096 whileBlocking( mTemporaryFolderWidget )->setFilePath( context->temporaryFolder() );
1097 whileBlocking( mThreadsSpinBox )->setValue( context->maximumThreads() );
1098 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast< int >( context->logLevel() ) ) );
1099}
1100
1101Qgis::InvalidGeometryCheck QgsProcessingContextOptionsWidget::invalidGeometryCheck() const
1102{
1103 return mComboInvalidFeatureFiltering->currentData().value< Qgis::InvalidGeometryCheck >();
1104}
1105
1106Qgis::DistanceUnit QgsProcessingContextOptionsWidget::distanceUnit() const
1107{
1108 return mDistanceUnitsCombo->currentData().value< Qgis::DistanceUnit >();
1109}
1110
1111Qgis::AreaUnit QgsProcessingContextOptionsWidget::areaUnit() const
1112{
1113 return mAreaUnitsCombo->currentData().value< Qgis::AreaUnit >();
1114}
1115
1116QString QgsProcessingContextOptionsWidget::temporaryFolder()
1117{
1118 return mTemporaryFolderWidget->filePath();
1119}
1120
1121int QgsProcessingContextOptionsWidget::maximumThreads() const
1122{
1123 return mThreadsSpinBox->value();
1124}
1125
1126void QgsProcessingContextOptionsWidget::setLogLevel( Qgis::ProcessingLogLevel level )
1127{
1128 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast< int >( level ) ) );
1129}
1130
1131Qgis::ProcessingLogLevel QgsProcessingContextOptionsWidget::logLevel() const
1132{
1133 return static_cast< Qgis::ProcessingLogLevel >( mLogLevelComboBox->currentData().toInt() );
1134}
1135
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
DistanceUnit
Units of distance.
Definition qgis.h:4669
@ 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:4746
@ 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:3348
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3359
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:2072
@ 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:3385
@ 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:208
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
Definition qgsgui.h:271
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
Definition qgsgui.cpp:83
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Definition qgsgui.cpp:232
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:6074
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5821