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