QGIS API Documentation 3.99.0-Master (357b655ed83)
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()
342 ? mAlgorithm->displayName()
343 : u"%1 - %2"_s.arg( mAlgorithm->group(), mAlgorithm->displayName() );
344 }
345
346 setWindowTitle( title );
347
348 const QString algHelp = formatHelp( algorithm );
349 if ( algHelp.isEmpty() )
350 textShortHelp->hide();
351 else
352 {
353 textShortHelp->document()->setDefaultStyleSheet( QStringLiteral( ".summary { margin-left: 10px; margin-right: 10px; }\n"
354 "h2 { color: #555555; padding-bottom: 15px; }\n"
355 "a { text - decoration: none; color: #3498db; font-weight: bold; }\n"
356 "p, ul, li { color: #666666; }\n"
357 "b { color: #333333; }\n"
358 "dl dd { margin - bottom: 5px; }" ) );
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}
495
496void QgsProcessingAlgorithmDialogBase::openHelp()
497{
498 QUrl algHelp = mAlgorithm->helpUrl();
499 if ( algHelp.isEmpty() && mAlgorithm->provider() )
500 {
501 algHelp = QgsHelp::helpUrl( 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 if ( !algHelp.isEmpty() )
505 QDesktopServices::openUrl( algHelp );
506}
507
508void QgsProcessingAlgorithmDialogBase::toggleCollapsed()
509{
510 if ( mHelpCollapsed )
511 {
512 splitter->restoreState( mSplitterState );
513 mButtonCollapse->setArrowType( Qt::RightArrow );
514 }
515 else
516 {
517 mSplitterState = splitter->saveState();
518 splitter->setSizes( QList<int>() << 1 << 0 );
519 mButtonCollapse->setArrowType( Qt::LeftArrow );
520 }
521 mHelpCollapsed = !mHelpCollapsed;
522}
523
524void QgsProcessingAlgorithmDialogBase::splitterChanged( int, int )
525{
526 if ( splitter->sizes().at( 1 ) == 0 )
527 {
528 mHelpCollapsed = true;
529 mButtonCollapse->setArrowType( Qt::LeftArrow );
530 }
531 else
532 {
533 mHelpCollapsed = false;
534 mButtonCollapse->setArrowType( Qt::RightArrow );
535 }
536}
537
538void QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged( int )
539{
540 updateRunButtonVisibility();
541}
542
543void QgsProcessingAlgorithmDialogBase::linkClicked( const QUrl &url )
544{
545 QDesktopServices::openUrl( url.toString() );
546}
547
548void QgsProcessingAlgorithmDialogBase::algExecuted( bool successful, const QVariantMap & )
549{
550 mAlgorithmTask = nullptr;
551
552 if ( !successful )
553 {
554 // show dialog to display errors
555 show();
556 raise();
557 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
558 activateWindow();
559 showLog();
560 }
561 else
562 {
563 if ( isFinalized() && successful )
564 {
565 progressBar->setFormat( tr( "Complete" ) );
566 }
567
568 // delete dialog if closed
569 if ( isFinalized() && !isVisible() )
570 {
571 deleteLater();
572 }
573 }
574}
575
576void QgsProcessingAlgorithmDialogBase::taskTriggered( QgsTask *task )
577{
578 if ( task == mAlgorithmTask )
579 {
580 show();
581 raise();
582 setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
583 activateWindow();
584 showLog();
585 }
586}
587
588void QgsProcessingAlgorithmDialogBase::closeClicked()
589{
590 reject();
591 close();
592}
593
594void QgsProcessingAlgorithmDialogBase::urlClicked( const QUrl &url )
595{
596 const QFileInfo file( url.toLocalFile() );
597 if ( file.exists() && !file.isDir() )
598 QgsGui::nativePlatformInterface()->openFileExplorerAndSelectFile( url.toLocalFile() );
599 else
600 QDesktopServices::openUrl( url );
601}
602
603Qgis::ProcessingLogLevel QgsProcessingAlgorithmDialogBase::logLevel() const
604{
605 return mLogLevel;
606}
607
608void QgsProcessingAlgorithmDialogBase::setLogLevel( Qgis::ProcessingLogLevel level )
609{
610 mLogLevel = level;
611}
612
613void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
614{
615 setInfo( error, true );
616 if ( fatalError )
617 resetGui();
618 showLog();
619 processEvents();
620}
621
622void QgsProcessingAlgorithmDialogBase::pushWarning( const QString &warning )
623{
624 setInfo( warning, false, true, true );
625 processEvents();
626}
627
628void QgsProcessingAlgorithmDialogBase::pushInfo( const QString &info )
629{
630 setInfo( info );
631 processEvents();
632}
633
634void QgsProcessingAlgorithmDialogBase::pushFormattedMessage( const QString &html )
635{
636 setInfo( html, false, false );
637 processEvents();
638}
639
640void QgsProcessingAlgorithmDialogBase::pushCommandInfo( const QString &command )
641{
642 txtLog->append( u"<code>%1<code>"_s.arg( formatStringForLog( command.toHtmlEscaped() ) ) );
643 scrollToBottomOfLog();
644 processEvents();
645}
646
647void QgsProcessingAlgorithmDialogBase::pushDebugInfo( const QString &message )
648{
649 txtLog->append( u"<span style=\"color:#777\">%1</span>"_s.arg( formatStringForLog( message.toHtmlEscaped() ) ) );
650 scrollToBottomOfLog();
651 processEvents();
652}
653
654void QgsProcessingAlgorithmDialogBase::pushConsoleInfo( const QString &info )
655{
656 txtLog->append( u"<code style=\"color:#777\">%1</code>"_s.arg( formatStringForLog( info.toHtmlEscaped() ) ) );
657 scrollToBottomOfLog();
658 processEvents();
659}
660
661QDialog *QgsProcessingAlgorithmDialogBase::createProgressDialog()
662{
663 QgsProcessingAlgorithmProgressDialog *dialog = new QgsProcessingAlgorithmProgressDialog( this );
664 dialog->setWindowModality( Qt::ApplicationModal );
665 dialog->setWindowTitle( windowTitle() );
666 dialog->setGeometry( geometry() ); // match size/position to this dialog
667 connect( progressBar, &QProgressBar::valueChanged, dialog->progressBar(), &QProgressBar::setValue );
668 connect( dialog->cancelButton(), &QPushButton::clicked, buttonCancel, &QPushButton::click );
669 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
670 connect( txtLog, &QTextEdit::textChanged, dialog, [this, dialog]() {
671 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
672 QScrollBar *sb = dialog->logTextEdit()->verticalScrollBar();
673 sb->setValue( sb->maximum() );
674 } );
675 return dialog;
676}
677
678void QgsProcessingAlgorithmDialogBase::clearLog()
679{
680 txtLog->clear();
681}
682
683void QgsProcessingAlgorithmDialogBase::saveLog()
684{
685 QgsSettings settings;
686 const QString lastUsedDir = settings.value( u"/Processing/lastUsedLogDirectory"_s, QDir::homePath() ).toString();
687
688 QString filter;
689 const QString txtExt = tr( "Text files" ) + u" (*.txt *.TXT)"_s;
690 const QString htmlExt = tr( "HTML files" ) + u" (*.html *.HTML)"_s;
691
692 const QString path = QFileDialog::getSaveFileName( this, tr( "Save Log to File" ), lastUsedDir, txtExt + ";;" + htmlExt, &filter );
693 // return dialog focus on Mac
694 activateWindow();
695 raise();
696 if ( path.isEmpty() )
697 {
698 return;
699 }
700
701 settings.setValue( u"/Processing/lastUsedLogDirectory"_s, QFileInfo( path ).path() );
702
703 LogFormat format = FormatPlainText;
704 if ( filter == htmlExt )
705 {
706 format = FormatHtml;
707 }
708 saveLogToFile( path, format );
709}
710
711void QgsProcessingAlgorithmDialogBase::copyLogToClipboard()
712{
713 QMimeData *m = new QMimeData();
714 m->setText( txtLog->toPlainText() );
715 m->setHtml( txtLog->toHtml() );
716 QClipboard *cb = QApplication::clipboard();
717
718#ifdef Q_OS_LINUX
719 cb->setMimeData( m, QClipboard::Selection );
720#endif
721 cb->setMimeData( m, QClipboard::Clipboard );
722}
723
724void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
725{
726 if ( !mHelpCollapsed )
727 {
728 QgsSettings settings;
729 settings.setValue( u"/Processing/dialogBaseSplitter"_s, splitter->saveState() );
730 }
731
732 QDialog::closeEvent( e );
733
734 if ( !mAlgorithmTask && isFinalized() )
735 {
736 // when running a background task, the dialog is kept around and deleted only when the task
737 // completes. But if not running a task, we auto cleanup (later - gotta give callers a chance
738 // to retrieve results and execution status).
739 deleteLater();
740 }
741}
742
743void QgsProcessingAlgorithmDialogBase::runAlgorithm()
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 += 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}
867
868void QgsProcessingAlgorithmDialogBase::blockControlsWhileRunning()
869{
870 mButtonRun->setEnabled( false );
871 mButtonChangeParameters->setEnabled( false );
872 if ( mMainWidget )
873 {
874 mMainWidget->setEnabled( false );
875 }
876 blockAdditionalControlsWhileRunning();
877}
878
879void QgsProcessingAlgorithmDialogBase::blockAdditionalControlsWhileRunning()
880{
881}
882
883QgsMessageBar *QgsProcessingAlgorithmDialogBase::messageBar()
884{
885 return mMessageBar;
886}
887
888void QgsProcessingAlgorithmDialogBase::hideShortHelp()
889{
890 textShortHelp->setVisible( false );
891}
892
893void QgsProcessingAlgorithmDialogBase::setCurrentTask( QgsProcessingAlgRunnerTask *task )
894{
895 mAlgorithmTask = task;
896 connect( mAlgorithmTask, &QgsProcessingAlgRunnerTask::executed, this, &QgsProcessingAlgorithmDialogBase::algExecuted );
897 QgsApplication::taskManager()->addTask( mAlgorithmTask );
898}
899
900QString QgsProcessingAlgorithmDialogBase::formatStringForLog( const QString &string )
901{
902 QString s = string;
903 s.replace( '\n', "<br>"_L1 );
904 return s;
905}
906
907bool QgsProcessingAlgorithmDialogBase::isFinalized()
908{
909 return true;
910}
911
912void QgsProcessingAlgorithmDialogBase::applyContextOverrides( QgsProcessingContext *context )
913{
914 if ( !context )
915 return;
916
917 context->setLogLevel( logLevel() );
918
919 if ( mOverrideDefaultContextSettings )
920 {
921 context->setInvalidGeometryCheck( mGeometryCheck );
922 context->setDistanceUnit( mDistanceUnits );
923 context->setAreaUnit( mAreaUnits );
924 context->setTemporaryFolder( mTemporaryFolderOverride );
925 context->setMaximumThreads( mMaximumThreads );
926 }
927}
928
929void QgsProcessingAlgorithmDialogBase::setInfo( const QString &message, bool isError, bool escapeHtml, bool isWarning )
930{
931 constexpr int MESSAGE_COUNT_LIMIT = 10000;
932 // Avoid logging too many messages, which might blow memory.
933 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
934 return;
935 ++mMessageLoggedCount;
936
937 // note -- we have to wrap the message in a span block, or QTextEdit::append sometimes gets confused
938 // and varies between treating it as a HTML string or a plain text string! (see https://github.com/qgis/QGIS/issues/37934)
939 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
940 txtLog->append( u"<span style=\"color:red\">%1</span>"_s.arg( tr( "Message log truncated" ) ) );
941 else if ( isError || isWarning )
942 txtLog->append( u"<span style=\"color:%1\">%2</span>"_s.arg( isError ? u"red"_s : u"#b85a20"_s, escapeHtml ? formatStringForLog( message.toHtmlEscaped() ) : formatStringForLog( message ) ) );
943 else if ( escapeHtml )
944 txtLog->append( u"<span>%1</span"_s.arg( formatStringForLog( message.toHtmlEscaped() ) ) );
945 else
946 txtLog->append( u"<span>%1</span>"_s.arg( formatStringForLog( message ) ) );
947 scrollToBottomOfLog();
948 processEvents();
949}
950
951void QgsProcessingAlgorithmDialogBase::reject()
952{
953 if ( !mAlgorithmTask && isFinalized() )
954 {
955 setAttribute( Qt::WA_DeleteOnClose );
956 }
957 QDialog::reject();
958}
959
960//
961// QgsProcessingAlgorithmProgressDialog
962//
963
964QgsProcessingAlgorithmProgressDialog::QgsProcessingAlgorithmProgressDialog( QWidget *parent )
965 : QDialog( parent )
966{
967 setupUi( this );
968}
969
970QProgressBar *QgsProcessingAlgorithmProgressDialog::progressBar()
971{
972 return mProgressBar;
973}
974
975QPushButton *QgsProcessingAlgorithmProgressDialog::cancelButton()
976{
977 return mButtonBox->button( QDialogButtonBox::Cancel );
978}
979
980QTextEdit *QgsProcessingAlgorithmProgressDialog::logTextEdit()
981{
982 return mTxtLog;
983}
984
985void QgsProcessingAlgorithmProgressDialog::reject()
986{
987}
988
989
990//
991// QgsProcessingContextOptionsWidget
992//
993
994QgsProcessingContextOptionsWidget::QgsProcessingContextOptionsWidget( QWidget *parent )
995 : QgsPanelWidget( parent )
996{
997 setupUi( this );
998 setPanelTitle( tr( "Algorithm Settings" ) );
999
1000 mComboInvalidFeatureFiltering->addItem( tr( "Do not Filter (Better Performance)" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::NoCheck ) );
1001 mComboInvalidFeatureFiltering->addItem( tr( "Skip (Ignore) Features with Invalid Geometries" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::SkipInvalid ) );
1002 mComboInvalidFeatureFiltering->addItem( tr( "Stop Algorithm Execution When a Geometry is Invalid" ), QVariant::fromValue( Qgis::InvalidGeometryCheck::AbortOnInvalid ) );
1003
1004 mTemporaryFolderWidget->setDialogTitle( tr( "Select Temporary Directory" ) );
1005 mTemporaryFolderWidget->setStorageMode( QgsFileWidget::GetDirectory );
1006 mTemporaryFolderWidget->lineEdit()->setPlaceholderText( tr( "Default" ) );
1007
1008 mLogLevelComboBox->addItem( tr( "Default" ), static_cast<int>( Qgis::ProcessingLogLevel::DefaultLevel ) );
1009 mLogLevelComboBox->addItem( tr( "Verbose" ), static_cast<int>( Qgis::ProcessingLogLevel::Verbose ) );
1010 mLogLevelComboBox->addItem( tr( "Verbose (Model Debugging)" ), static_cast<int>( Qgis::ProcessingLogLevel::ModelDebug ) );
1011
1012 mDistanceUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::DistanceUnit::Unknown ) );
1013 for ( Qgis::DistanceUnit unit :
1014 {
1025 } )
1026 {
1027 QString title;
1029 {
1031 }
1032 else
1033 {
1034 title = QgsUnitTypes::toString( unit );
1035 }
1036
1037 mDistanceUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1038 }
1039
1040 mAreaUnitsCombo->addItem( tr( "Default" ), QVariant::fromValue( Qgis::AreaUnit::Unknown ) );
1041 for ( Qgis::AreaUnit unit :
1042 {
1055 } )
1056 {
1057 QString title;
1059 {
1061 }
1062 else
1063 {
1064 title = QgsUnitTypes::toString( unit );
1065 }
1066
1067 mAreaUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1068 }
1069
1070 mThreadsSpinBox->setRange( 1, QThread::idealThreadCount() );
1071
1072 connect( mLogLevelComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1073 connect( mComboInvalidFeatureFiltering, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1074 connect( mDistanceUnitsCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1075 connect( mAreaUnitsCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsPanelWidget::widgetChanged );
1076 connect( mTemporaryFolderWidget, &QgsFileWidget::fileChanged, this, &QgsPanelWidget::widgetChanged );
1077 connect( mThreadsSpinBox, qOverload<int>( &QSpinBox::valueChanged ), this, &QgsPanelWidget::widgetChanged );
1078}
1079
1080void QgsProcessingContextOptionsWidget::setFromContext( const QgsProcessingContext *context )
1081{
1082 whileBlocking( mComboInvalidFeatureFiltering )->setCurrentIndex( mComboInvalidFeatureFiltering->findData( QVariant::fromValue( context->invalidGeometryCheck() ) ) );
1083 whileBlocking( mDistanceUnitsCombo )->setCurrentIndex( mDistanceUnitsCombo->findData( QVariant::fromValue( context->distanceUnit() ) ) );
1084 whileBlocking( mAreaUnitsCombo )->setCurrentIndex( mAreaUnitsCombo->findData( QVariant::fromValue( context->areaUnit() ) ) );
1085 whileBlocking( mTemporaryFolderWidget )->setFilePath( context->temporaryFolder() );
1086 whileBlocking( mThreadsSpinBox )->setValue( context->maximumThreads() );
1087 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast<int>( context->logLevel() ) ) );
1088}
1089
1090Qgis::InvalidGeometryCheck QgsProcessingContextOptionsWidget::invalidGeometryCheck() const
1091{
1092 return mComboInvalidFeatureFiltering->currentData().value<Qgis::InvalidGeometryCheck>();
1093}
1094
1095Qgis::DistanceUnit QgsProcessingContextOptionsWidget::distanceUnit() const
1096{
1097 return mDistanceUnitsCombo->currentData().value<Qgis::DistanceUnit>();
1098}
1099
1100Qgis::AreaUnit QgsProcessingContextOptionsWidget::areaUnit() const
1101{
1102 return mAreaUnitsCombo->currentData().value<Qgis::AreaUnit>();
1103}
1104
1105QString QgsProcessingContextOptionsWidget::temporaryFolder()
1106{
1107 return mTemporaryFolderWidget->filePath();
1108}
1109
1110int QgsProcessingContextOptionsWidget::maximumThreads() const
1111{
1112 return mThreadsSpinBox->value();
1113}
1114
1115void QgsProcessingContextOptionsWidget::setLogLevel( Qgis::ProcessingLogLevel level )
1116{
1117 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData( static_cast<int>( level ) ) );
1118}
1119
1120Qgis::ProcessingLogLevel QgsProcessingContextOptionsWidget::logLevel() const
1121{
1122 return static_cast<Qgis::ProcessingLogLevel>( mLogLevelComboBox->currentData().toInt() );
1123}
1124
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
DistanceUnit
Units of distance.
Definition qgis.h:5120
@ Feet
Imperial feet.
Definition qgis.h:5123
@ Centimeters
Centimeters.
Definition qgis.h:5128
@ Millimeters
Millimeters.
Definition qgis.h:5129
@ Miles
Terrestrial miles.
Definition qgis.h:5126
@ Meters
Meters.
Definition qgis.h:5121
@ Unknown
Unknown distance unit.
Definition qgis.h:5170
@ Yards
Imperial yards.
Definition qgis.h:5125
@ Degrees
Degrees, for planar geographic CRS distance measurements.
Definition qgis.h:5127
@ Inches
Inches.
Definition qgis.h:5130
@ NauticalMiles
Nautical miles.
Definition qgis.h:5124
@ Kilometers
Kilometers.
Definition qgis.h:5122
AreaUnit
Units of area.
Definition qgis.h:5197
@ Acres
Acres.
Definition qgis.h:5204
@ SquareFeet
Square feet.
Definition qgis.h:5200
@ SquareCentimeters
Square centimeters.
Definition qgis.h:5207
@ SquareInches
Square inches.
Definition qgis.h:5209
@ SquareNauticalMiles
Square nautical miles.
Definition qgis.h:5205
@ SquareMillimeters
Square millimeters.
Definition qgis.h:5208
@ SquareYards
Square yards.
Definition qgis.h:5201
@ Hectares
Hectares.
Definition qgis.h:5203
@ SquareKilometers
Square kilometers.
Definition qgis.h:5199
@ SquareMeters
Square meters.
Definition qgis.h:5198
@ Unknown
Unknown areal unit.
Definition qgis.h:5210
@ SquareDegrees
Square degrees, for planar geographic CRS area measurements.
Definition qgis.h:5206
@ SquareMiles
Square miles.
Definition qgis.h:5202
@ Warning
Warning message.
Definition qgis.h:161
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
Definition qgis.h:3466
ProcessingAlgorithmDocumentationFlag
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3689
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3701
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:2296
@ NoCheck
No invalid geometry checking.
Definition qgis.h:2297
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
Definition qgis.h:2299
@ SkipInvalid
Skip any features with invalid geometry. This requires a slow geometry validity check for every featu...
Definition qgis.h:2298
@ NotAvailableInStandaloneTool
Algorithm should not be available from the standalone "qgis_process" tool. Used to flag algorithms wh...
Definition qgis.h:3666
@ SecurityRisk
The algorithm represents a potential security risk if executed with untrusted inputs.
Definition qgis.h:3668
@ DisplayNameIsLiteral
Algorithm's display name is a static literal string, and should not be translated or automatically fo...
Definition qgis.h:3660
@ KnownIssues
Algorithm has known issues.
Definition qgis.h:3662
ProcessingLogLevel
Logging level for algorithms to use when pushing feedback messages.
Definition qgis.h:3727
@ DefaultLevel
Default logging level.
Definition qgis.h:3728
@ Verbose
Verbose logging.
Definition qgis.h:3729
@ ModelDebug
Model debug level logging. Includes verbose logging and other outputs useful for debugging models.
Definition qgis.h:3730
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:7092
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6839