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