QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsprocessingalgorithmdialogbase.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingalgorithmdialogbase.cpp
3  ------------------------------------
4  Date : November 2017
5  Copyright : (C) 2017 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 #include "qgssettings.h"
18 #include "qgshelp.h"
19 #include "qgsmessagebar.h"
20 #include "qgsgui.h"
23 #include "qgstaskmanager.h"
25 #include "qgsstringutils.h"
26 #include "qgsapplication.h"
27 #include "qgspanelwidget.h"
28 #include <QToolButton>
29 #include <QDesktopServices>
30 #include <QScrollBar>
31 #include <QApplication>
32 #include <QClipboard>
33 #include <QFileDialog>
34 #include <QMimeData>
35 
36 
38 
39 QgsProcessingAlgorithmDialogFeedback::QgsProcessingAlgorithmDialogFeedback()
40  : QgsProcessingFeedback( false )
41 {}
42 
43 void QgsProcessingAlgorithmDialogFeedback::setProgressText( const QString &text )
44 {
46  emit progressTextChanged( text );
47 }
48 
49 void QgsProcessingAlgorithmDialogFeedback::reportError( const QString &error, bool fatalError )
50 {
51  QgsProcessingFeedback::reportError( error, fatalError );
52  emit errorReported( error, fatalError );
53 }
54 
55 void QgsProcessingAlgorithmDialogFeedback::pushWarning( const QString &warning )
56 {
58  emit warningPushed( warning );
59 }
60 
61 void QgsProcessingAlgorithmDialogFeedback::pushInfo( const QString &info )
62 {
64  emit infoPushed( info );
65 }
66 
67 void QgsProcessingAlgorithmDialogFeedback::pushCommandInfo( const QString &info )
68 {
70  emit commandInfoPushed( info );
71 }
72 
73 void QgsProcessingAlgorithmDialogFeedback::pushDebugInfo( const QString &info )
74 {
76  emit debugInfoPushed( info );
77 }
78 
79 void QgsProcessingAlgorithmDialogFeedback::pushConsoleInfo( const QString &info )
80 {
82  emit consoleInfoPushed( info );
83 }
84 
85 //
86 // QgsProcessingAlgorithmDialogBase
87 //
88 
89 QgsProcessingAlgorithmDialogBase::QgsProcessingAlgorithmDialogBase( QWidget *parent, Qt::WindowFlags flags )
90  : QDialog( parent, flags )
91 {
92  setupUi( this );
93 
94  //don't collapse parameters panel
95  splitter->setCollapsible( 0, false );
96 
97  // add collapse button to splitter
98  QSplitterHandle *splitterHandle = splitter->handle( 1 );
99  QVBoxLayout *handleLayout = new QVBoxLayout();
100  handleLayout->setContentsMargins( 0, 0, 0, 0 );
101  mButtonCollapse = new QToolButton( splitterHandle );
102  mButtonCollapse->setAutoRaise( true );
103  mButtonCollapse->setFixedSize( 12, 12 );
104  mButtonCollapse->setCursor( Qt::ArrowCursor );
105  handleLayout->addWidget( mButtonCollapse );
106  handleLayout->addStretch();
107  splitterHandle->setLayout( handleLayout );
108 
110 
111  QgsSettings settings;
112  splitter->restoreState( settings.value( QStringLiteral( "/Processing/dialogBaseSplitter" ), QByteArray() ).toByteArray() );
113  mSplitterState = splitter->saveState();
114  splitterChanged( 0, 0 );
115 
116  // Rename OK button to Run
117  mButtonRun = mButtonBox->button( QDialogButtonBox::Ok );
118  mButtonRun->setText( tr( "Run" ) );
119 
120  // Rename Yes button. Yes is used to ensure same position of Run and Change Parameters with respect to Close button.
121  mButtonChangeParameters = mButtonBox->button( QDialogButtonBox::Yes );
122  mButtonChangeParameters->setText( tr( "Change Parameters" ) );
123 
124  buttonCancel->setEnabled( false );
125  mButtonClose = mButtonBox->button( QDialogButtonBox::Close );
126 
127  connect( mButtonRun, &QPushButton::clicked, this, &QgsProcessingAlgorithmDialogBase::runAlgorithm );
128  connect( mButtonChangeParameters, &QPushButton::clicked, this, &QgsProcessingAlgorithmDialogBase::showParameters );
129  connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsProcessingAlgorithmDialogBase::closeClicked );
130  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsProcessingAlgorithmDialogBase::openHelp );
131  connect( mButtonCollapse, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::toggleCollapsed );
132  connect( splitter, &QSplitter::splitterMoved, this, &QgsProcessingAlgorithmDialogBase::splitterChanged );
133 
134  connect( mButtonSaveLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::saveLog );
135  connect( mButtonCopyLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::copyLogToClipboard );
136  connect( mButtonClearLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::clearLog );
137 
138  connect( mTabWidget, &QTabWidget::currentChanged, this, &QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged );
139 
140  mMessageBar = new QgsMessageBar();
141  mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
142  verticalLayout->insertWidget( 0, mMessageBar );
143 
144  connect( QgsApplication::taskManager(), &QgsTaskManager::taskTriggered, this, &QgsProcessingAlgorithmDialogBase::taskTriggered );
145 }
146 
147 QgsProcessingAlgorithmDialogBase::~QgsProcessingAlgorithmDialogBase() = default;
148 
149 void QgsProcessingAlgorithmDialogBase::setAlgorithm( QgsProcessingAlgorithm *algorithm )
150 {
151  mAlgorithm.reset( algorithm );
152  QString title;
154  {
155  title = QgsStringUtils::capitalize( mAlgorithm->displayName(), QgsStringUtils::TitleCase );
156  }
157  else
158  {
159  title = mAlgorithm->displayName();
160  }
161  setWindowTitle( title );
162 
163  QString algHelp = formatHelp( algorithm );
164  if ( algHelp.isEmpty() )
165  textShortHelp->hide();
166  else
167  {
168  textShortHelp->document()->setDefaultStyleSheet( QStringLiteral( ".summary { margin-left: 10px; margin-right: 10px; }\n"
169  "h2 { color: #555555; padding-bottom: 15px; }\n"
170  "a { text - decoration: none; color: #3498db; font-weight: bold; }\n"
171  "p { color: #666666; }\n"
172  "b { color: #333333; }\n"
173  "dl dd { margin - bottom: 5px; }" ) );
174  textShortHelp->setHtml( algHelp );
175  connect( textShortHelp, &QTextBrowser::anchorClicked, this, &QgsProcessingAlgorithmDialogBase::linkClicked );
176  }
177 
178  if ( algorithm->helpUrl().isEmpty() && algorithm->provider()->helpId().isEmpty() )
179  {
180  mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Help ) );
181  }
182 
183  const QString warning = algorithm->provider()->warningMessage();
184  if ( !warning.isEmpty() )
185  {
186  mMessageBar->pushMessage( warning, Qgis::Warning );
187  }
188 }
189 
191 {
192  return mAlgorithm.get();
193 }
194 
195 void QgsProcessingAlgorithmDialogBase::setMainWidget( QgsPanelWidget *widget )
196 {
197  if ( mMainWidget )
198  {
199  mMainWidget->deleteLater();
200  }
201 
202  mPanelStack->setMainPanel( widget );
203  widget->setDockMode( true );
204 
205  mMainWidget = widget;
206  connect( mMainWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
207 }
208 
209 QgsPanelWidget *QgsProcessingAlgorithmDialogBase::mainWidget()
210 {
211  return mMainWidget;
212 }
213 
214 void QgsProcessingAlgorithmDialogBase::saveLogToFile( const QString &path, const LogFormat format )
215 {
216  QFile logFile( path );
217  if ( !logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
218  {
219  return;
220  }
221  QTextStream fout( &logFile );
222 
223  switch ( format )
224  {
225  case FormatPlainText:
226  fout << txtLog->toPlainText();
227  break;
228 
229  case FormatHtml:
230  fout << txtLog->toHtml();
231  break;
232  }
233 }
234 
235 QgsProcessingFeedback *QgsProcessingAlgorithmDialogBase::createFeedback()
236 {
237  auto feedback = qgis::make_unique< QgsProcessingAlgorithmDialogFeedback >();
238  connect( feedback.get(), &QgsProcessingFeedback::progressChanged, this, &QgsProcessingAlgorithmDialogBase::setPercentage );
239  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::commandInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushCommandInfo );
240  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::consoleInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushConsoleInfo );
241  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::debugInfoPushed, this, &QgsProcessingAlgorithmDialogBase::pushDebugInfo );
242  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::errorReported, this, &QgsProcessingAlgorithmDialogBase::reportError );
243  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::warningPushed, this, &QgsProcessingAlgorithmDialogBase::pushWarning );
244  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::infoPushed, this, &QgsProcessingAlgorithmDialogBase::pushInfo );
245  connect( feedback.get(), &QgsProcessingAlgorithmDialogFeedback::progressTextChanged, this, &QgsProcessingAlgorithmDialogBase::setProgressText );
246  connect( buttonCancel, &QPushButton::clicked, feedback.get(), &QgsProcessingFeedback::cancel );
247  return feedback.release();
248 }
249 
250 QDialogButtonBox *QgsProcessingAlgorithmDialogBase::buttonBox()
251 {
252  return mButtonBox;
253 }
254 
255 QTabWidget *QgsProcessingAlgorithmDialogBase::tabWidget()
256 {
257  return mTabWidget;
258 }
259 
260 void QgsProcessingAlgorithmDialogBase::showLog()
261 {
262  mTabWidget->setCurrentIndex( 1 );
263 }
264 
265 void QgsProcessingAlgorithmDialogBase::showParameters()
266 {
267  mTabWidget->setCurrentIndex( 0 );
268 }
269 
270 QPushButton *QgsProcessingAlgorithmDialogBase::runButton()
271 {
272  return mButtonRun;
273 }
274 
275 QPushButton *QgsProcessingAlgorithmDialogBase::cancelButton()
276 {
277  return buttonCancel;
278 }
279 
280 QPushButton *QgsProcessingAlgorithmDialogBase::changeParametersButton()
281 {
282  return mButtonChangeParameters;
283 }
284 
285 void QgsProcessingAlgorithmDialogBase::clearProgress()
286 {
287  progressBar->setMaximum( 0 );
288 }
289 
290 void QgsProcessingAlgorithmDialogBase::setExecuted( bool executed )
291 {
292  mExecuted = executed;
293 }
294 
295 void QgsProcessingAlgorithmDialogBase::setExecutedAnyResult( bool executedAnyResult )
296 {
297  mExecutedAnyResult = executedAnyResult;
298 }
299 
300 void QgsProcessingAlgorithmDialogBase::setResults( const QVariantMap &results )
301 {
302  mResults = results;
303 }
304 
305 void QgsProcessingAlgorithmDialogBase::finished( bool, const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
306 {
307 
308 }
309 
310 void QgsProcessingAlgorithmDialogBase::openHelp()
311 {
312  QUrl algHelp = mAlgorithm->helpUrl();
313  if ( algHelp.isEmpty() )
314  {
315  algHelp = QgsHelp::helpUrl( QStringLiteral( "processing_algs/%1/%2.html#%3" ).arg( mAlgorithm->provider()->helpId(), mAlgorithm->groupId(), QStringLiteral( "%1%2" ).arg( mAlgorithm->provider()->helpId() ).arg( mAlgorithm->name() ) ) );
316  }
317 
318  if ( !algHelp.isEmpty() )
319  QDesktopServices::openUrl( algHelp );
320 }
321 
322 void QgsProcessingAlgorithmDialogBase::toggleCollapsed()
323 {
324  if ( mHelpCollapsed )
325  {
326  splitter->restoreState( mSplitterState );
327  mButtonCollapse->setArrowType( Qt::RightArrow );
328  }
329  else
330  {
331  mSplitterState = splitter->saveState();
332  splitter->setSizes( QList<int>() << 1 << 0 );
333  mButtonCollapse->setArrowType( Qt::LeftArrow );
334  }
335  mHelpCollapsed = !mHelpCollapsed;
336 }
337 
338 void QgsProcessingAlgorithmDialogBase::splitterChanged( int, int )
339 {
340  if ( splitter->sizes().at( 1 ) == 0 )
341  {
342  mHelpCollapsed = true;
343  mButtonCollapse->setArrowType( Qt::LeftArrow );
344  }
345  else
346  {
347  mHelpCollapsed = false;
348  mButtonCollapse->setArrowType( Qt::RightArrow );
349  }
350 }
351 
352 void QgsProcessingAlgorithmDialogBase::mTabWidget_currentChanged( int )
353 {
354  updateRunButtonVisibility();
355 }
356 
357 void QgsProcessingAlgorithmDialogBase::linkClicked( const QUrl &url )
358 {
359  QDesktopServices::openUrl( url.toString() );
360 }
361 
362 void QgsProcessingAlgorithmDialogBase::algExecuted( bool successful, const QVariantMap & )
363 {
364  mAlgorithmTask = nullptr;
365 
366  if ( !successful )
367  {
368  // show dialog to display errors
369  show();
370  raise();
371  setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
372  activateWindow();
373  showLog();
374  }
375  else
376  {
377  // delete dialog if closed
378  if ( !isVisible() )
379  {
380  deleteLater();
381  }
382  }
383 }
384 
385 void QgsProcessingAlgorithmDialogBase::taskTriggered( QgsTask *task )
386 {
387  if ( task == mAlgorithmTask )
388  {
389  show();
390  raise();
391  setWindowState( ( windowState() & ~Qt::WindowMinimized ) | Qt::WindowActive );
392  activateWindow();
393  showLog();
394  }
395 }
396 
397 void QgsProcessingAlgorithmDialogBase::closeClicked()
398 {
399  reject();
400  close();
401 }
402 
403 void QgsProcessingAlgorithmDialogBase::reportError( const QString &error, bool fatalError )
404 {
405  setInfo( error, true );
406  if ( fatalError )
407  resetGui();
408  showLog();
409  processEvents();
410 }
411 
412 void QgsProcessingAlgorithmDialogBase::pushWarning( const QString &warning )
413 {
414  setInfo( warning, false, true, true );
415  processEvents();
416 }
417 
418 void QgsProcessingAlgorithmDialogBase::pushInfo( const QString &info )
419 {
420  setInfo( info );
421  processEvents();
422 }
423 
424 void QgsProcessingAlgorithmDialogBase::pushCommandInfo( const QString &command )
425 {
426  txtLog->append( QStringLiteral( "<code>%1<code>" ).arg( formatStringForLog( command.toHtmlEscaped() ) ) );
427  scrollToBottomOfLog();
428  processEvents();
429 }
430 
431 void QgsProcessingAlgorithmDialogBase::pushDebugInfo( const QString &message )
432 {
433  txtLog->append( QStringLiteral( "<span style=\"color:#777\">%1</span>" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
434  scrollToBottomOfLog();
435  processEvents();
436 }
437 
438 void QgsProcessingAlgorithmDialogBase::pushConsoleInfo( const QString &info )
439 {
440  txtLog->append( QStringLiteral( "<code style=\"color:#777\">%1</code>" ).arg( formatStringForLog( info.toHtmlEscaped() ) ) );
441  scrollToBottomOfLog();
442  processEvents();
443 }
444 
445 QDialog *QgsProcessingAlgorithmDialogBase::createProgressDialog()
446 {
447  QgsProcessingAlgorithmProgressDialog *dialog = new QgsProcessingAlgorithmProgressDialog( this );
448  dialog->setWindowModality( Qt::ApplicationModal );
449  dialog->setWindowTitle( windowTitle() );
450  dialog->setGeometry( geometry() ); // match size/position to this dialog
451  connect( progressBar, &QProgressBar::valueChanged, dialog->progressBar(), &QProgressBar::setValue );
452  connect( dialog->cancelButton(), &QPushButton::clicked, buttonCancel, &QPushButton::click );
453  dialog->logTextEdit()->setHtml( txtLog->toHtml() );
454  connect( txtLog, &QTextEdit::textChanged, dialog, [this, dialog]()
455  {
456  dialog->logTextEdit()->setHtml( txtLog->toHtml() );
457  QScrollBar *sb = dialog->logTextEdit()->verticalScrollBar();
458  sb->setValue( sb->maximum() );
459  } );
460  return dialog;
461 }
462 
463 void QgsProcessingAlgorithmDialogBase::clearLog()
464 {
465  txtLog->clear();
466 }
467 
468 void QgsProcessingAlgorithmDialogBase::saveLog()
469 {
470  QgsSettings settings;
471  QString lastUsedDir = settings.value( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QDir::homePath() ).toString();
472 
473  QString filter;
474  const QString txtExt = tr( "Text files" ) + QStringLiteral( " (*.txt *.TXT)" );
475  const QString htmlExt = tr( "HTML files" ) + QStringLiteral( " (*.html *.HTML)" );
476 
477  QString path = QFileDialog::getSaveFileName( this, tr( "Save Log to File" ), lastUsedDir, txtExt + ";;" + htmlExt, &filter );
478  if ( path.isEmpty() )
479  {
480  return;
481  }
482 
483  settings.setValue( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QFileInfo( path ).path() );
484 
485  LogFormat format = FormatPlainText;
486  if ( filter == htmlExt )
487  {
488  format = FormatHtml;
489  }
490  saveLogToFile( path, format );
491 }
492 
493 void QgsProcessingAlgorithmDialogBase::copyLogToClipboard()
494 {
495  QMimeData *m = new QMimeData();
496  m->setText( txtLog->toPlainText() );
497  m->setHtml( txtLog->toHtml() );
498  QClipboard *cb = QApplication::clipboard();
499 
500 #ifdef Q_OS_LINUX
501  cb->setMimeData( m, QClipboard::Selection );
502 #endif
503  cb->setMimeData( m, QClipboard::Clipboard );
504 }
505 
506 void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
507 {
508  if ( !mHelpCollapsed )
509  {
510  QgsSettings settings;
511  settings.setValue( QStringLiteral( "/Processing/dialogBaseSplitter" ), splitter->saveState() );
512  }
513 
514  QDialog::closeEvent( e );
515 
516  if ( !mAlgorithmTask )
517  {
518  // when running a background task, the dialog is kept around and deleted only when the task
519  // completes. But if not running a task, we auto cleanup (later - gotta give callers a chance
520  // to retrieve results and execution status).
521  deleteLater();
522  }
523 }
524 
525 void QgsProcessingAlgorithmDialogBase::runAlgorithm()
526 {
527 
528 }
529 
530 void QgsProcessingAlgorithmDialogBase::setPercentage( double percent )
531 {
532  // delay setting maximum progress value until we know algorithm reports progress
533  if ( progressBar->maximum() == 0 )
534  progressBar->setMaximum( 100 );
535  progressBar->setValue( percent );
536  processEvents();
537 }
538 
539 void QgsProcessingAlgorithmDialogBase::setProgressText( const QString &text )
540 {
541  lblProgress->setText( text );
542  setInfo( text, false );
543  scrollToBottomOfLog();
544  processEvents();
545 }
546 
547 QString QgsProcessingAlgorithmDialogBase::formatHelp( QgsProcessingAlgorithm *algorithm )
548 {
549  QString text = algorithm->shortHelpString();
550  if ( !text.isEmpty() )
551  {
552  QStringList paragraphs = text.split( '\n' );
553  QString help;
554  for ( const QString &paragraph : paragraphs )
555  {
556  help += QStringLiteral( "<p>%1</p>" ).arg( paragraph );
557  }
558  return QStringLiteral( "<h2>%1</h2>%2" ).arg( algorithm->displayName(), help );
559  }
560  else if ( !algorithm->shortDescription().isEmpty() )
561  {
562  return QStringLiteral( "<h2>%1</h2><p>%2</p>" ).arg( algorithm->displayName(), algorithm->shortDescription() );
563  }
564  else
565  return QString();
566 }
567 
568 void QgsProcessingAlgorithmDialogBase::processEvents()
569 {
570  if ( mAlgorithmTask )
571  {
572  // no need to call this - the algorithm is running in a thread.
573  // in fact, calling it causes a crash on Windows when the algorithm
574  // is running in a background thread... unfortunately we need something
575  // like this for non-threadable algorithms, otherwise there's no chance
576  // for users to hit cancel or see progress updates...
577  return;
578  }
579 
580  // So that we get a chance of hitting the Abort button
581 #ifdef Q_OS_LINUX
582  // One iteration is actually enough on Windows to get good interactivity
583  // whereas on Linux we must allow for far more iterations.
584  // For safety limit the number of iterations
585  int nIters = 0;
586  while ( ++nIters < 100 )
587 #endif
588  {
589  QCoreApplication::processEvents();
590  }
591 }
592 
593 void QgsProcessingAlgorithmDialogBase::scrollToBottomOfLog()
594 {
595  QScrollBar *sb = txtLog->verticalScrollBar();
596  sb->setValue( sb->maximum() );
597 }
598 
599 void QgsProcessingAlgorithmDialogBase::resetGui()
600 {
601  lblProgress->clear();
602  progressBar->setMaximum( 100 );
603  progressBar->setValue( 0 );
604  mButtonRun->setEnabled( true );
605  mButtonChangeParameters->setEnabled( true );
606  mButtonClose->setEnabled( true );
607  if ( mMainWidget )
608  {
609  mMainWidget->setEnabled( true );
610  }
611  updateRunButtonVisibility();
612  resetAdditionalGui();
613 }
614 
615 void QgsProcessingAlgorithmDialogBase::updateRunButtonVisibility()
616 {
617  // Activate run button if current tab is Parameters
618  bool runButtonVisible = mTabWidget->currentIndex() == 0;
619  mButtonRun->setVisible( runButtonVisible );
620  mButtonChangeParameters->setVisible( !runButtonVisible && mExecutedAnyResult && mButtonChangeParameters->isEnabled() );
621 }
622 
623 void QgsProcessingAlgorithmDialogBase::resetAdditionalGui()
624 {
625 
626 }
627 
628 void QgsProcessingAlgorithmDialogBase::blockControlsWhileRunning()
629 {
630  mButtonRun->setEnabled( false );
631  mButtonChangeParameters->setEnabled( false );
632  if ( mMainWidget )
633  {
634  mMainWidget->setEnabled( false );
635  }
636  blockAdditionalControlsWhileRunning();
637 }
638 
639 void QgsProcessingAlgorithmDialogBase::blockAdditionalControlsWhileRunning()
640 {
641 
642 }
643 
644 QgsMessageBar *QgsProcessingAlgorithmDialogBase::messageBar()
645 {
646  return mMessageBar;
647 }
648 
649 void QgsProcessingAlgorithmDialogBase::hideShortHelp()
650 {
651  textShortHelp->setVisible( false );
652 }
653 
654 void QgsProcessingAlgorithmDialogBase::setCurrentTask( QgsProcessingAlgRunnerTask *task )
655 {
656  mAlgorithmTask = task;
657  connect( mAlgorithmTask, &QgsProcessingAlgRunnerTask::executed, this, &QgsProcessingAlgorithmDialogBase::algExecuted );
658  QgsApplication::taskManager()->addTask( mAlgorithmTask );
659 }
660 
661 QString QgsProcessingAlgorithmDialogBase::formatStringForLog( const QString &string )
662 {
663  QString s = string;
664  s.replace( '\n', QLatin1String( "<br>" ) );
665  return s;
666 }
667 
668 void QgsProcessingAlgorithmDialogBase::setInfo( const QString &message, bool isError, bool escapeHtml, bool isWarning )
669 {
670  // note -- we have to wrap the message in a span block, or QTextEdit::append sometimes gets confused
671  // and varies between treating it as a HTML string or a plain text string! (see https://github.com/qgis/QGIS/issues/37934)
672  if ( isError || isWarning )
673  txtLog->append( QStringLiteral( "<span style=\"color:%1\">%2</span>" ).arg( isError ? QStringLiteral( "red" ) : QStringLiteral( "#b85a20" ), escapeHtml ? formatStringForLog( message.toHtmlEscaped() ) : formatStringForLog( message ) ) );
674  else if ( escapeHtml )
675  txtLog->append( QStringLiteral( "<span>%1</span" ).arg( formatStringForLog( message.toHtmlEscaped() ) ) );
676  else
677  txtLog->append( QStringLiteral( "<span>%1</span>" ).arg( formatStringForLog( message ) ) );
678  scrollToBottomOfLog();
679  processEvents();
680 }
681 
682 void QgsProcessingAlgorithmDialogBase::reject()
683 {
684  if ( !mAlgorithmTask )
685  {
686  setAttribute( Qt::WA_DeleteOnClose );
687  }
688  QDialog::reject();
689 }
690 
691 //
692 // QgsProcessingAlgorithmProgressDialog
693 //
694 
695 QgsProcessingAlgorithmProgressDialog::QgsProcessingAlgorithmProgressDialog( QWidget *parent )
696  : QDialog( parent )
697 {
698  setupUi( this );
699 }
700 
701 QProgressBar *QgsProcessingAlgorithmProgressDialog::progressBar()
702 {
703  return mProgressBar;
704 }
705 
706 QPushButton *QgsProcessingAlgorithmProgressDialog::cancelButton()
707 {
708  return mButtonBox->button( QDialogButtonBox::Cancel );
709 }
710 
711 QTextEdit *QgsProcessingAlgorithmProgressDialog::logTextEdit()
712 {
713  return mTxtLog;
714 }
715 
716 void QgsProcessingAlgorithmProgressDialog::reject()
717 {
718 
719 }
720 
721 
722 
@ Warning
Definition: qgis.h:91
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 ...
Definition: qgsfeedback.h:85
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:156
@ HigDialogTitleIsTitleCase
Dialog titles should be title case.
Definition: qgsgui.h:205
static QgsGui::HigFlags higFlags()
Returns the platform's HIG flags.
Definition: qgsgui.cpp:175
static QUrl helpUrl(const QString &key)
Returns URI of the help topic for the given key.
Definition: qgshelp.cpp:41
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
Base class for any widget that can be shown as a inline panel.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
QgsTask task which runs a QgsProcessingAlgorithm in a background task.
void executed(bool successful, const QVariantMap &results)
Emitted when the algorithm has finished execution.
Abstract base class for processing algorithms.
virtual QString helpUrl() const
Returns a url pointing to the algorithm's help page.
virtual QString shortHelpString() const
Returns a localised short helper string for the algorithm.
virtual QString shortDescription() const
Returns an optional translated short description of the algorithm.
@ FlagDisplayNameIsLiteral
Algorithm's display name is a static literal string, and should not be translated or automatically fo...
virtual QString displayName() const =0
Returns the translated algorithm name, which should be used for any user-visible display of the algor...
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
Contains information about the context in which a processing algorithm is executed.
QgsProcessingAlgorithm::Flags flags() const override
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Base class for providing feedback from a processing algorithm.
virtual void pushCommandInfo(const QString &info)
Pushes an informational message containing a command from the algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
virtual void pushDebugInfo(const QString &info)
Pushes an informational message containing debugging helpers from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
virtual void pushConsoleInfo(const QString &info)
Pushes a console feedback message from the algorithm.
virtual void setProgressText(const QString &text)
Sets a progress report text string.
virtual QString helpId() const
Returns the provider help id string, used for creating QgsHelp urls for algorithms belong to this pro...
virtual QString warningMessage() const
Returns an optional warning message to show users when running algorithms from this provider.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QString capitalize(const QString &string, Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
@ TitleCase
Simple title case conversion - does not fully grammatically parse the text and uses simple rules only...
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.
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