18#include <nlohmann/json.hpp>
36#include <QApplication>
38#include <QDesktopServices>
47#include "moc_qgsprocessingalgorithmwidgetbase.cpp"
49using namespace Qt::StringLiterals;
57QgsProcessingFeedbackGenerator::~QgsProcessingFeedbackGenerator()
64QgsProcessingAlgorithmWidgetBase::QgsProcessingAlgorithmWidgetBase(
73 splitter->setCollapsible( 0,
false );
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 );
89 txtLog->setOpenLinks(
false );
90 connect( txtLog, &QTextBrowser::anchorClicked,
this, &QgsProcessingAlgorithmWidgetBase::urlClicked );
93 splitter->restoreState( settings.
value( u
"/Processing/dialogBaseSplitter"_s, QByteArray() ).toByteArray() );
94 mSplitterState = splitter->saveState();
95 splitterChanged( 0, 0 );
98 mButtonRun = mButtonBox->button( QDialogButtonBox::Ok );
99 mButtonRun->setText( tr(
"Run" ) );
102 mButtonChangeParameters = mButtonBox->button( QDialogButtonBox::Yes );
103 mButtonChangeParameters->setText( tr(
"Change Parameters" ) );
105 connect( buttonCancel, &QPushButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::cancel );
106 buttonCancel->setEnabled(
false );
107 mButtonClose = mButtonBox->button( QDialogButtonBox::Close );
110 parentWindow = qobject_cast< QMainWindow * >( QApplication::activeWindow() );
112 bool defaultIsDocked =
false;
113 QString dockId = u
"ProcessingAlgorithm"_s;
114 if ( flags.testFlags( QgsProcessingAlgorithmWidgetBase::WidgetFlag::NoDocking ) )
117 dockId = u
"ProcessingAlgorithmNonDockable"_s;
121 dockId = u
"ProcessingAlgorithmForceDocked"_s;
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 );
130 case QgsProcessingAlgorithmWidgetBase::WidgetMode::Single:
132 mAdvancedButton =
new QPushButton( tr(
"Advanced" ) );
133 mAdvancedMenu =
new QMenu(
this );
134 mAdvancedButton->setMenu( mAdvancedMenu );
136 mContextSettingsAction =
new QAction( tr(
"Algorithm Settingsā¦" ), mAdvancedMenu );
138 mAdvancedMenu->addAction( mContextSettingsAction );
140 connect( mContextSettingsAction, &QAction::triggered,
this, [
this] {
143 mTabWidget->setCurrentIndex( 0 );
145 if ( !mContextOptionsWidget )
147 mContextOptionsWidget =
new QgsProcessingContextOptionsWidget();
148 mContextOptionsWidget->setFromContext( processingContext() );
149 mContextOptionsWidget->setLogLevel( mLogLevel );
150 panel->openPanel( mContextOptionsWidget );
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();
164 mAdvancedMenu->addSeparator();
166 QAction *copyAsPythonCommand =
new QAction( tr(
"Copy as Python Command" ), mAdvancedMenu );
169 mAdvancedMenu->addAction( copyAsPythonCommand );
170 connect( copyAsPythonCommand, &QAction::triggered,
this, [
this] {
177 const QString command = alg->asPythonCommand( createProcessingParameters(), *context );
178 QMimeData *m =
new QMimeData();
179 m->setText( command );
180 QClipboard *cb = QApplication::clipboard();
182 if ( cb->supportsSelection() )
184 cb->setMimeData( m, QClipboard::Selection );
186 cb->setMimeData( m, QClipboard::Clipboard );
190 mCopyAsQgisProcessCommand =
new QAction( tr(
"Copy as qgis_process Command" ), mAdvancedMenu );
192 mAdvancedMenu->addAction( mCopyAsQgisProcessCommand );
194 connect( mCopyAsQgisProcessCommand, &QAction::triggered,
this, [
this] {
202 const QString command = alg->asQgisProcessCommand( createProcessingParameters(), *context, ok );
205 mMessageBar->pushMessage( tr(
"Current settings cannot be specified as arguments to qgis_process (Pipe parameters as JSON to qgis_process instead)" ),
Qgis::MessageLevel::Warning );
209 QMimeData *m =
new QMimeData();
210 m->setText( command );
211 QClipboard *cb = QApplication::clipboard();
213 if ( cb->supportsSelection() )
215 cb->setMimeData( m, QClipboard::Selection );
217 cb->setMimeData( m, QClipboard::Clipboard );
222 mAdvancedMenu->addSeparator();
224 QAction *copyAsJson =
new QAction( tr(
"Copy as JSON" ), mAdvancedMenu );
227 mAdvancedMenu->addAction( copyAsJson );
228 connect( copyAsJson, &QAction::triggered,
this, [
this] {
235 const QVariantMap properties = alg->asMap( createProcessingParameters(), *context );
238 QMimeData *m =
new QMimeData();
240 QClipboard *cb = QApplication::clipboard();
242 if ( cb->supportsSelection() )
244 cb->setMimeData( m, QClipboard::Selection );
246 cb->setMimeData( m, QClipboard::Clipboard );
250 mPasteJsonAction =
new QAction( tr(
"Paste Settings" ), mAdvancedMenu );
253 mAdvancedMenu->addAction( mPasteJsonAction );
254 connect( mPasteJsonAction, &QAction::triggered,
this, [
this] {
255 const QString text = QApplication::clipboard()->text();
256 if ( text.isEmpty() )
260 if ( parameterValues.isEmpty() )
267 setParameters( preparedValues );
270 mButtonBox->addButton( mAdvancedButton, QDialogButtonBox::ResetRole );
274 case QgsProcessingAlgorithmWidgetBase::WidgetMode::Batch:
280 connect( mAdvancedMenu, &QMenu::aboutToShow,
this, [
this] {
282 mPasteJsonAction->setEnabled( !QApplication::clipboard()->text().isEmpty() );
286 connect( mButtonRun, &QPushButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::runAlgorithm );
287 connect( mButtonChangeParameters, &QPushButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::showParameters );
288 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QgsProcessingAlgorithmWidgetBase::closeClicked );
289 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsProcessingAlgorithmWidgetBase::openHelp );
290 connect( mButtonCollapse, &QToolButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::toggleCollapsed );
291 connect( splitter, &QSplitter::splitterMoved,
this, &QgsProcessingAlgorithmWidgetBase::splitterChanged );
293 connect( mButtonSaveLog, &QToolButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::saveLog );
294 connect( mButtonCopyLog, &QToolButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::copyLogToClipboard );
295 connect( mButtonClearLog, &QToolButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::clearLog );
297 connect( mTabWidget, &QTabWidget::currentChanged,
this, &QgsProcessingAlgorithmWidgetBase::mTabWidget_currentChanged );
300 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
301 verticalLayout->insertWidget( 0, mMessageBar );
306QgsProcessingAlgorithmWidgetBase::~QgsProcessingAlgorithmWidgetBase()
308 delete mDockableWidgetHelper;
311void QgsProcessingAlgorithmWidgetBase::setParameters(
const QVariantMap & )
314void QgsProcessingAlgorithmWidgetBase::setTitle(
const QString &title )
316 mDockableWidgetHelper->setWindowTitle( title );
319void QgsProcessingAlgorithmWidgetBase::exec()
325 mDockableWidgetHelper->setSettingKeyDockId( u
"ProcessingAlgorithmNonDockable"_s );
326 mDockableWidgetHelper->toggleDockMode(
false );
327 mDockableWidgetHelper->dialog()->exec();
336 title = mAlgorithm->group().isEmpty()
338 : u
"%1 - %2"_s.arg(
QgsStringUtils::capitalize( mAlgorithm->group(),
Qgis::Capitalization::TitleCase ),
QgsStringUtils::capitalize( mAlgorithm->displayName(),
Qgis::Capitalization::TitleCase ) );
342 title = mAlgorithm->group().isEmpty() ? mAlgorithm->displayName() : u
"%1 - %2"_s.arg( mAlgorithm->group(), mAlgorithm->displayName() );
344 mDockableWidgetHelper->setWindowTitle( title );
346 const QString algHelp = formatHelp(
algorithm );
347 if ( algHelp.isEmpty() )
348 textShortHelp->hide();
351 textShortHelp->document()->setDefaultStyleSheet( QStringLiteral(
352 ".summary { margin-left: 10px; margin-right: 10px; }\n"
353 "h2 { color: #555555; padding-bottom: 15px; }\n"
354 "a { text - decoration: none; color: #3498db; font-weight: bold; }\n"
355 "p, ul, li { color: #666666; }\n"
356 "b { color: #333333; }\n"
357 "dl dd { margin - bottom: 5px; }"
359 textShortHelp->setHtml( algHelp );
360 connect( textShortHelp, &QTextBrowser::anchorClicked,
this, &QgsProcessingAlgorithmWidgetBase::linkClicked );
361 textShortHelp->show();
366 mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Help ) );
369 const QString warning =
algorithm->provider() ?
algorithm->provider()->warningMessage() : QString();
370 if ( !warning.isEmpty() )
378 return mAlgorithm.get();
381void QgsProcessingAlgorithmWidgetBase::setMainWidget(
QgsPanelWidget *widget )
385 mMainWidget->deleteLater();
388 mPanelStack->setMainPanel( widget );
391 mMainWidget = widget;
400void QgsProcessingAlgorithmWidgetBase::saveLogToFile(
const QString &path,
const LogFormat format )
402 QFile logFile( path );
403 if ( !logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
407 QTextStream fout( &logFile );
411 case QgsProcessingAlgorithmWidgetBase::LogFormat::FormatPlainText:
412 fout << txtLog->toPlainText();
415 case QgsProcessingAlgorithmWidgetBase::LogFormat::FormatHtml:
416 fout << txtLog->toHtml();
421void QgsProcessingAlgorithmWidgetBase::registerProcessingFeedbackGenerator( QgsProcessingFeedbackGenerator *factory )
423 mFeedbackFactory = factory;
428 std::unique_ptr< QgsProcessingFeedback > feedback;
429 if ( mFeedbackFactory )
431 feedback.reset( mFeedbackFactory->createFeedback() );
435 feedback = std::make_unique< QgsProcessingFeedback >();
447 return feedback.release();
450QDialogButtonBox *QgsProcessingAlgorithmWidgetBase::buttonBox()
455QTabWidget *QgsProcessingAlgorithmWidgetBase::tabWidget()
460void QgsProcessingAlgorithmWidgetBase::showLog()
462 mTabWidget->setCurrentIndex( 1 );
465void QgsProcessingAlgorithmWidgetBase::showParameters()
467 mTabWidget->setCurrentIndex( 0 );
470QPushButton *QgsProcessingAlgorithmWidgetBase::runButton()
475QPushButton *QgsProcessingAlgorithmWidgetBase::cancelButton()
480QPushButton *QgsProcessingAlgorithmWidgetBase::changeParametersButton()
482 return mButtonChangeParameters;
485void QgsProcessingAlgorithmWidgetBase::clearProgress()
487 progressBar->setMaximum( 0 );
490void QgsProcessingAlgorithmWidgetBase::setExecuted(
bool executed )
492 mExecuted = executed;
495void QgsProcessingAlgorithmWidgetBase::setExecutedAnyResult(
bool executedAnyResult )
497 mExecutedAnyResult = executedAnyResult;
500void QgsProcessingAlgorithmWidgetBase::setResults(
const QVariantMap &results )
508void QgsProcessingAlgorithmWidgetBase::openHelp()
510 QUrl algHelp = mAlgorithm->helpUrl();
511 if ( algHelp.isEmpty() && mAlgorithm->provider() )
514 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(
"_",
"-" ) ) )
518 if ( !algHelp.isEmpty() )
519 QDesktopServices::openUrl( algHelp );
522void QgsProcessingAlgorithmWidgetBase::toggleCollapsed()
524 if ( mHelpCollapsed )
526 splitter->restoreState( mSplitterState );
527 mButtonCollapse->setArrowType( Qt::RightArrow );
531 mSplitterState = splitter->saveState();
532 splitter->setSizes( QList<int>() << 1 << 0 );
533 mButtonCollapse->setArrowType( Qt::LeftArrow );
535 mHelpCollapsed = !mHelpCollapsed;
538void QgsProcessingAlgorithmWidgetBase::splitterChanged(
int,
int )
540 if ( splitter->sizes().at( 1 ) == 0 )
542 mHelpCollapsed =
true;
543 mButtonCollapse->setArrowType( Qt::LeftArrow );
547 mHelpCollapsed =
false;
548 mButtonCollapse->setArrowType( Qt::RightArrow );
552void QgsProcessingAlgorithmWidgetBase::mTabWidget_currentChanged(
int )
554 updateRunButtonVisibility();
557void QgsProcessingAlgorithmWidgetBase::linkClicked(
const QUrl &url )
559 QDesktopServices::openUrl( url.toString() );
562void QgsProcessingAlgorithmWidgetBase::algExecuted(
bool successful,
const QVariantMap & )
564 mAlgorithmTask =
nullptr;
574 if ( isFinalized() && successful )
576 progressBar->setFormat( tr(
"Complete" ) );
580 if ( isFinalized() && !isVisible() )
587void QgsProcessingAlgorithmWidgetBase::taskTriggered(
QgsTask *task )
589 if ( task == mAlgorithmTask )
596void QgsProcessingAlgorithmWidgetBase::showWidget()
598 mDockableWidgetHelper->setUserVisible(
true );
601void QgsProcessingAlgorithmWidgetBase::closeClicked()
603 disconnect( mDockableWidgetHelper, &QgsDockableWidgetHelper::closed,
this, &QgsProcessingAlgorithmWidgetBase::closeClicked );
607 mDockableWidgetHelper->setUserVisible(
false );
616void QgsProcessingAlgorithmWidgetBase::urlClicked(
const QUrl &url )
618 const QFileInfo file( url.toLocalFile() );
619 if ( file.exists() && !file.isDir() )
622 QDesktopServices::openUrl( url );
635void QgsProcessingAlgorithmWidgetBase::reportError(
const QString &error,
bool fatalError )
637 setInfo( error,
true );
644void QgsProcessingAlgorithmWidgetBase::pushWarning(
const QString &warning )
646 setInfo( warning,
false,
true,
true );
650void QgsProcessingAlgorithmWidgetBase::pushInfo(
const QString &info )
656void QgsProcessingAlgorithmWidgetBase::pushFormattedMessage(
const QString &html )
658 setInfo( html,
false,
false );
662void QgsProcessingAlgorithmWidgetBase::pushCommandInfo(
const QString &command )
664 txtLog->append( u
"<code>%1<code>"_s.arg( formatStringForLog( command.toHtmlEscaped() ) ) );
665 scrollToBottomOfLog();
669void QgsProcessingAlgorithmWidgetBase::pushDebugInfo(
const QString &message )
671 txtLog->append( u
"<span style=\"color:#777\">%1</span>"_s.arg( formatStringForLog( message.toHtmlEscaped() ) ) );
672 scrollToBottomOfLog();
676void QgsProcessingAlgorithmWidgetBase::pushConsoleInfo(
const QString &info )
678 txtLog->append( u
"<code style=\"color:#777\">%1</code>"_s.arg( formatStringForLog( info.toHtmlEscaped() ) ) );
679 scrollToBottomOfLog();
683QDialog *QgsProcessingAlgorithmWidgetBase::createProgressDialog()
685 QgsProcessingAlgorithmProgressDialog *dialog =
new QgsProcessingAlgorithmProgressDialog(
this );
686 dialog->setWindowModality( Qt::ApplicationModal );
687 dialog->setWindowTitle( windowTitle() );
688 dialog->setGeometry( geometry() );
689 connect( progressBar, &QProgressBar::valueChanged, dialog->progressBar(), &QProgressBar::setValue );
690 connect( dialog->cancelButton(), &QPushButton::clicked,
this, &QgsProcessingAlgorithmWidgetBase::cancel );
691 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
692 connect( txtLog, &QTextEdit::textChanged, dialog, [
this, dialog]() {
693 dialog->logTextEdit()->setHtml( txtLog->toHtml() );
694 QScrollBar *sb = dialog->logTextEdit()->verticalScrollBar();
695 sb->setValue( sb->maximum() );
700void QgsProcessingAlgorithmWidgetBase::clearLog()
705void QgsProcessingAlgorithmWidgetBase::saveLog()
708 const QString lastUsedDir = settings.
value( u
"/Processing/lastUsedLogDirectory"_s, QDir::homePath() ).toString();
711 const QString txtExt = tr(
"Text files" ) + u
" (*.txt *.TXT)"_s;
712 const QString htmlExt = tr(
"HTML files" ) + u
" (*.html *.HTML)"_s;
714 const QString path = QFileDialog::getSaveFileName(
this, tr(
"Save Log to File" ), lastUsedDir, txtExt +
";;" + htmlExt, &filter );
718 if ( path.isEmpty() )
723 settings.
setValue( u
"/Processing/lastUsedLogDirectory"_s, QFileInfo( path ).path() );
725 LogFormat format = QgsProcessingAlgorithmWidgetBase::LogFormat::FormatPlainText;
726 if ( filter == htmlExt )
728 format = QgsProcessingAlgorithmWidgetBase::LogFormat::FormatHtml;
730 saveLogToFile( path, format );
733void QgsProcessingAlgorithmWidgetBase::copyLogToClipboard()
735 QMimeData *m =
new QMimeData();
736 m->setText( txtLog->toPlainText() );
737 m->setHtml( txtLog->toHtml() );
738 QClipboard *cb = QApplication::clipboard();
740 if ( cb->supportsSelection() )
742 cb->setMimeData( m, QClipboard::Selection );
744 cb->setMimeData( m, QClipboard::Clipboard );
747void QgsProcessingAlgorithmWidgetBase::closeEvent( QCloseEvent *e )
749 if ( !mHelpCollapsed )
752 settings.
setValue( u
"/Processing/dialogBaseSplitter"_s, splitter->saveState() );
755 QWidget::closeEvent( e );
757 if ( !mAlgorithmTask && isFinalized() )
766void QgsProcessingAlgorithmWidgetBase::runAlgorithm()
769void QgsProcessingAlgorithmWidgetBase::setPercentage(
double percent )
772 if ( progressBar->maximum() == 0 )
773 progressBar->setMaximum( 100 );
774 progressBar->setValue( percent );
778void QgsProcessingAlgorithmWidgetBase::setProgressText(
const QString &text )
780 lblProgress->setText( text );
781 setInfo( text,
false );
782 scrollToBottomOfLog();
789 const QString text =
algorithm->shortHelpString();
790 if ( !text.isEmpty() )
792 const QStringList paragraphs = text.split(
'\n' );
794 for (
const QString ¶graph : paragraphs )
796 help += u
"<p>%1</p>"_s.arg( paragraph );
798 result = u
"<h2>%1</h2>%2"_s.arg(
algorithm->displayName(), help );
800 else if ( !
algorithm->shortDescription().isEmpty() )
802 result = u
"<h2>%1</h2><p>%2</p>"_s.arg(
algorithm->displayName(),
algorithm->shortDescription() );
810 if (
algorithm->documentationFlags() & flag )
815 result += u
"<ul><li><i>%1</i></li></ul>"_s.arg( flags.join(
"</i></li><li><i>"_L1 ) );
819 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." ) );
823 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." ) );
829void QgsProcessingAlgorithmWidgetBase::processEvents()
831 if ( mAlgorithmTask )
847 while ( ++nIters < 100 )
850 QCoreApplication::processEvents();
854void QgsProcessingAlgorithmWidgetBase::scrollToBottomOfLog()
856 QScrollBar *sb = txtLog->verticalScrollBar();
857 sb->setValue( sb->maximum() );
860void QgsProcessingAlgorithmWidgetBase::resetGui()
862 lblProgress->clear();
863 progressBar->setMaximum( 100 );
864 progressBar->setValue( 0 );
865 mButtonRun->setEnabled(
true );
866 mButtonChangeParameters->setEnabled(
true );
867 mButtonClose->setEnabled(
true );
870 mMainWidget->setEnabled(
true );
872 updateRunButtonVisibility();
873 resetAdditionalGui();
876void QgsProcessingAlgorithmWidgetBase::updateRunButtonVisibility()
879 const bool runButtonVisible = mTabWidget->currentIndex() == 0;
880 mButtonRun->setVisible( runButtonVisible );
881 if ( runButtonVisible )
882 progressBar->resetFormat();
883 mButtonChangeParameters->setVisible( !runButtonVisible && mExecutedAnyResult && mButtonChangeParameters->isEnabled() );
886void QgsProcessingAlgorithmWidgetBase::resetAdditionalGui()
889void QgsProcessingAlgorithmWidgetBase::blockControlsWhileRunning()
891 mButtonRun->setEnabled(
false );
892 mButtonChangeParameters->setEnabled(
false );
895 mMainWidget->setEnabled(
false );
897 blockAdditionalControlsWhileRunning();
900void QgsProcessingAlgorithmWidgetBase::blockAdditionalControlsWhileRunning()
908void QgsProcessingAlgorithmWidgetBase::hideShortHelp()
910 textShortHelp->setVisible(
false );
915 mAlgorithmTask = task;
920void QgsProcessingAlgorithmWidgetBase::disconnectCurrentTask()
922 if ( mAlgorithmTask )
925 mAlgorithmTask =
nullptr;
929QString QgsProcessingAlgorithmWidgetBase::formatStringForLog(
const QString &
string )
932 s.replace(
'\n',
"<br>"_L1 );
936bool QgsProcessingAlgorithmWidgetBase::isFinalized()
941bool QgsProcessingAlgorithmWidgetBase::isRunning()
946void QgsProcessingAlgorithmWidgetBase::cancel()
948 emit cancelRequested();
958 if ( mOverrideDefaultContextSettings )
968void QgsProcessingAlgorithmWidgetBase::setInfo(
const QString &message,
bool isError,
bool escapeHtml,
bool isWarning )
970 constexpr int MESSAGE_COUNT_LIMIT = 10000;
972 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
974 ++mMessageLoggedCount;
978 if ( mMessageLoggedCount == MESSAGE_COUNT_LIMIT )
979 txtLog->append( u
"<span style=\"color:red\">%1</span>"_s.arg( tr(
"Message log truncated" ) ) );
980 else if ( isError || isWarning )
981 txtLog->append( u
"<span style=\"color:%1\">%2</span>"_s.arg( isError ? u
"red"_s : u
"#b85a20"_s, escapeHtml ? formatStringForLog( message.toHtmlEscaped() ) : formatStringForLog( message ) ) );
982 else if ( escapeHtml )
983 txtLog->append( u
"<span>%1</span"_s.arg( formatStringForLog( message.toHtmlEscaped() ) ) );
985 txtLog->append( u
"<span>%1</span>"_s.arg( formatStringForLog( message ) ) );
986 scrollToBottomOfLog();
990void QgsProcessingAlgorithmWidgetBase::reject()
992 if ( !mAlgorithmTask && isFinalized() )
994 setAttribute( Qt::WA_DeleteOnClose );
997 mDockableWidgetHelper->reject();
1000void QgsProcessingAlgorithmWidgetBase::forceClose()
1002 disconnectCurrentTask();
1010QgsProcessingAlgorithmProgressDialog::QgsProcessingAlgorithmProgressDialog( QWidget *parent )
1016QProgressBar *QgsProcessingAlgorithmProgressDialog::progressBar()
1018 return mProgressBar;
1021QPushButton *QgsProcessingAlgorithmProgressDialog::cancelButton()
1023 return mButtonBox->button( QDialogButtonBox::Cancel );
1026QTextEdit *QgsProcessingAlgorithmProgressDialog::logTextEdit()
1031void QgsProcessingAlgorithmProgressDialog::reject()
1039QgsProcessingContextOptionsWidget::QgsProcessingContextOptionsWidget( QWidget *parent )
1043 setPanelTitle( tr(
"Algorithm Settings" ) );
1049 mTemporaryFolderWidget->setDialogTitle( tr(
"Select Temporary Directory" ) );
1051 mTemporaryFolderWidget->lineEdit()->setPlaceholderText( tr(
"Default" ) );
1081 mDistanceUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1110 mAreaUnitsCombo->addItem( title, QVariant::fromValue( unit ) );
1113 mThreadsSpinBox->setRange( 1, QThread::idealThreadCount() );
1125 whileBlocking( mComboInvalidFeatureFiltering )->setCurrentIndex( mComboInvalidFeatureFiltering->findData( QVariant::fromValue( context->
invalidGeometryCheck() ) ) );
1126 whileBlocking( mDistanceUnitsCombo )->setCurrentIndex( mDistanceUnitsCombo->findData( QVariant::fromValue( context->
distanceUnit() ) ) );
1127 whileBlocking( mAreaUnitsCombo )->setCurrentIndex( mAreaUnitsCombo->findData( QVariant::fromValue( context->
areaUnit() ) ) );
1130 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData(
static_cast<int>( context->
logLevel() ) ) );
1143Qgis::AreaUnit QgsProcessingContextOptionsWidget::areaUnit()
const
1148QString QgsProcessingContextOptionsWidget::temporaryFolder()
1150 return mTemporaryFolderWidget->filePath();
1153int QgsProcessingContextOptionsWidget::maximumThreads()
const
1155 return mThreadsSpinBox->value();
1160 whileBlocking( mLogLevelComboBox )->setCurrentIndex( mLogLevelComboBox->findData(
static_cast<int>( level ) ) );
Provides global constants and enumerations for use throughout the application.
DistanceUnit
Units of distance.
@ Centimeters
Centimeters.
@ Millimeters
Millimeters.
@ Miles
Terrestrial miles.
@ Unknown
Unknown distance unit.
@ Degrees
Degrees, for planar geographic CRS distance measurements.
@ NauticalMiles
Nautical miles.
@ SquareCentimeters
Square centimeters.
@ SquareInches
Square inches.
@ SquareNauticalMiles
Square nautical miles.
@ SquareMillimeters
Square millimeters.
@ SquareYards
Square yards.
@ SquareKilometers
Square kilometers.
@ SquareMeters
Square meters.
@ Unknown
Unknown areal unit.
@ SquareDegrees
Square degrees, for planar geographic CRS area measurements.
@ SquareMiles
Square miles.
@ Warning
Warning message.
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
ProcessingAlgorithmDocumentationFlag
Flags describing algorithm behavior for documentation purposes.
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
@ NoCheck
No invalid geometry checking.
@ AbortOnInvalid
Close iterator on encountering any features with invalid geometry. This requires a slow geometry vali...
@ SkipInvalid
Skip any features with invalid geometry. This requires a slow geometry validity check for every featu...
@ NotAvailableInStandaloneTool
Algorithm should not be available from the standalone "qgis_process" tool. Used to flag algorithms wh...
@ SecurityRisk
The algorithm represents a potential security risk if executed with untrusted inputs.
@ DisplayNameIsLiteral
Algorithm's display name is a static literal string, and should not be translated or automatically fo...
@ KnownIssues
Algorithm has known issues.
DockableWidgetInitialState
Dockable widget initial states.
@ ForceDocked
Force the widget to be docked.
@ ForceDialog
Force the widget to be shown in a dialog.
ProcessingLogLevel
Logging level for algorithms to use when pushing feedback messages.
@ DefaultLevel
Default logging level.
@ Verbose
Verbose logging.
@ ModelDebug
Model debug level logging. Includes verbose logging and other outputs useful for debugging models.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
void cancel()
Tells the internal routines that the current operation should be canceled. This should be run by the ...
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...
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
static QUrl helpUrl(const QString &key)
Returns URI of the help topic for the given key.
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.
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 ¶meters, 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.
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.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.