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