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