Mantid
Loading...
Searching...
No Matches
AlgorithmDialog.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
11#include "MantidKernel/Logger.h"
12
19
20#include <QCheckBox>
21#include <QCloseEvent>
22#include <QComboBox>
23#include <QDateTimeEdit>
24#include <QHBoxLayout>
25#include <QIcon>
26#include <QLabel>
27#include <QLineEdit>
28#include <QMessageBox>
29#include <QPushButton>
30
31#include <Poco/ActiveResult.h>
32
33using namespace MantidQt::API;
36using Mantid::Types::Core::DateAndTime;
37
38namespace {
39Mantid::Kernel::Logger g_log("AlgorithmDialog");
40}
41
42//------------------------------------------------------
43// Public member functions
44//------------------------------------------------------
49 : QDialog(parent), m_algorithm(), m_algName(""), m_algProperties(), m_propertyValueMap(), m_tied_properties(),
50 m_forScript(false), m_python_arguments(), m_enabled(), m_disabled(), m_strMessage(""), m_keepOpen(false),
51 m_msgAvailable(false), m_isInitialized(false), m_autoParseOnInit(true), m_validators(), m_noValidation(),
52 m_inputws_opts(), m_outputws_fields(), m_wsbtn_tracker(), m_keepOpenCheckBox(nullptr), m_okButton(nullptr),
53 m_exitButton(nullptr), m_observers(), m_btnTimer(), m_statusTracked(false) {
54 m_btnTimer.setSingleShot(true);
55}
56
61 m_observers.clear();
62 if (m_statusTracked) {
64 }
65}
66
72void AlgorithmDialog::setShowKeepOpen(const bool showOption) {
74 // if hidden then turn it off
75 if (!showOption) {
76 m_keepOpenCheckBox->setCheckState(Qt::CheckState::Unchecked);
77 }
78 m_keepOpenCheckBox->setVisible(showOption);
79 }
80}
86 bool retval = true;
88 retval = m_keepOpenCheckBox->isVisible();
89 }
90 return retval;
91}
92
101 if (isInitialized())
102 return;
103
104 // Set a common title
105 setWindowTitle(QString::fromStdString(getAlgorithm()->name()) + " input dialog");
106 // Set the icon
107 setWindowIcon(QIcon(":/mantidplot.png"));
108
109 // These containers are for ensuring the 'replace input workspace; button
110 // works correctly
111 // Store all combo boxes that relate to an input workspace
112 m_inputws_opts.clear();
113 // Store all line edit fields that relate to an output workspace name
114 m_outputws_fields.clear();
115 // Keep track of the input workspace that has been used to fill the output
116 // workspace. Each button click
117 // cycles through all of the input workspaces
118 m_wsbtn_tracker.clear();
119
120 // This derived class function creates the layout of the widget. It can also
121 // add default input if the
122 // dialog has been written this way
123 this->initLayout();
124
125 if (m_autoParseOnInit) {
126 // Check if there is any default input
127 this->parse();
128 // Unless told not to, try to set these values. This will validate the
129 // defaults and mark those that are invalid, if any.
130 this->setPropertyValues();
131 }
132
133 executeOnAccept(true);
134
135 connect(this, SIGNAL(algCompletedSignal()), this, SLOT(algorithmCompleted()));
136
137 m_isInitialized = true;
138}
139
145
146//------------------------------------------------------
147// Protected member functions
148//------------------------------------------------------
154
155//-------------------------------------------------------------------------------------------------
160 AlgorithmInputHistory::Instance().clearAlgorithmInput(m_algName);
161 QStringList::const_iterator pend = m_algProperties.end();
162 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
164 if (p->remember()) {
165 QString pName = *pitr;
166 QString value = m_propertyValueMap.value(pName);
167 AlgorithmInputHistory::Instance().storeNewValue(m_algName, QPair<QString, QString>(pName, value));
168 }
169 }
170}
171
172//-------------------------------------------------------------------------------------------------
178 m_algorithm = alg;
179 m_algName = QString::fromStdString(alg->name());
180 m_algProperties.clear();
181 m_tied_properties.clear();
182 std::vector<Mantid::Kernel::Property *>::const_iterator iend = alg->getProperties().end();
183 for (std::vector<Mantid::Kernel::Property *>::const_iterator itr = alg->getProperties().begin(); itr != iend; ++itr) {
184 Mantid::Kernel::Property *p = *itr;
186 m_algProperties.append(QString::fromStdString(p->name()));
187 }
188 }
189
190 m_validators.clear();
191 m_noValidation.clear();
192}
193
199
205 if (m_algProperties.contains(propName)) {
206 return m_algorithm->getProperty(propName.toStdString());
207 } else
208 return nullptr;
209}
210
215bool AlgorithmDialog::requiresUserInput(const QString &propName) const { return m_algProperties.contains(propName); }
216
217//-------------------------------------------------------------------------------------------------
222QString AlgorithmDialog::getInputValue(const QString &propName) const {
223 QString value = m_propertyValueMap.value(propName);
224 if (value.isEmpty()) {
226 if (prop)
227 return QString::fromStdString(prop->getDefault());
228 else
229 return "";
230 }
231
232 return value;
233}
234
235//-------------------------------------------------------------------------------------------------
241QLabel *AlgorithmDialog::getValidatorMarker(const QString &propname) {
242 if (m_noValidation.contains(propname))
243 return nullptr;
244 QLabel *validLbl(nullptr);
245 if (!m_validators.contains(propname)) {
246 validLbl = new QLabel("*", this);
247 QPalette pal = validLbl->palette();
248 pal.setColor(QPalette::WindowText, Qt::darkRed);
249 validLbl->setPalette(pal);
250 validLbl->setVisible(true);
251 m_validators[propname] = validLbl;
252 } else {
253 validLbl = m_validators.value(propname);
254 }
255 return validLbl;
256}
257
258//-------------------------------------------------------------------------------------------------
262void AlgorithmDialog::storePropertyValue(const QString &name, const QString &value) {
263 if (name.isEmpty())
264 return;
265 m_propertyValueMap.insert(name, value);
266}
267
268//-------------------------------------------------------------------------------------------------
273void AlgorithmDialog::removePropertyValue(const QString &name) {
274 if (name.isEmpty())
275 return;
276 m_propertyValueMap.remove(name);
277}
278
279//-------------------------------------------------------------------------------------------------
282 // Do nothing for non-generic algorithm dialogs
283 QStringList::const_iterator pend = m_algProperties.end();
284 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
285 const QString propName = *pitr;
286
287 // Find the widget for this property.
288 if (m_tied_properties.contains(propName)) {
289 // Show/hide the validator label (that red star)
290 QString error = "";
291 if (m_errors.contains(propName))
292 error = m_errors[propName];
293
294 QLabel *validator = getValidatorMarker(propName);
295 // If there's no validator then assume it's handling its own validation
296 // notification
297 if (validator && validator->parent()) {
298 validator->setToolTip(error);
299 validator->setVisible(error.length() != 0);
300 }
301 } // widget is tied
302 } // for each property
303}
304
305//-------------------------------------------------------------------------------------------------
316bool AlgorithmDialog::setPropertyValue(const QString &pName, bool validateOthers) {
317 // Mantid::Kernel::Property *p = getAlgorithmProperty(pName);
318 QString value = getInputValue(pName);
319
320 std::string error("");
321 try {
322 // error = p->setValue(value.toStdString());
323 getAlgorithm()->setPropertyValue(pName.toStdString(), value.toStdString());
324 } catch (std::exception &err_details) {
325 error = err_details.what();
326 }
327 // Save the error string for later
328 m_errors[pName] = QString::fromStdString(error).trimmed();
329
330 // Go through all the other properties' validators
331 if (validateOthers)
332 this->showValidators();
333
334 // Prop was valid if the error string is empty
335 return error.empty();
336}
337
338//-------------------------------------------------------------------------------------------------
345bool AlgorithmDialog::setPropertyValues(const QStringList &skipList) {
346 QStringList::const_iterator pend = m_algProperties.end();
347 bool allValid(true);
348 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
349 const QString pName = *pitr;
350 if (skipList.contains(pName)) {
351 // For the load dialog, skips setting some properties
353 std::string error = p->isValid();
354 m_errors[pName] = QString::fromStdString(error).trimmed();
355 if (!error.empty())
356 allValid = false;
357 } else {
358 bool thisValid = this->setPropertyValue(pName, false);
359 allValid = allValid && thisValid;
360 }
361 }
362
363 // Do additional validation on the WHOLE set of properties
364 // But only if the individual validation passed
365 if (allValid) {
366 std::map<std::string, std::string> errs = m_algorithm->validateInputs();
367 for (auto &err : errs) {
368 // only count as an error if the named property exists
369 if (m_algorithm->existsProperty(err.first)) {
370 const QString pName = QString::fromStdString(err.first);
371 const QString value = QString::fromStdString(err.second);
372 if (m_errors.contains(pName)) {
373 if (!m_errors[pName].isEmpty())
374 m_errors[pName] += "\n";
375 m_errors[pName] += value;
376 } else
377 m_errors[pName] = value;
378 // There is at least one whole-algo error
379 allValid = false;
380 }
381 }
382 }
383
384 // OK all the values have been set once. Time to look for which should be
385 // enabled
386 this->showValidators();
387
388 return allValid;
389}
390
391//-------------------------------------------------------------------------------------------------
396const QString &AlgorithmDialog::getOptionalMessage() const { return m_strMessage; }
397
398//-------------------------------------------------------------------------------------------------
403void AlgorithmDialog::addOptionalMessage(QVBoxLayout *mainLay) {
404 QLabel *inputMessage = new QLabel(this);
405 inputMessage->setFrameStyle(static_cast<int>(QFrame::Panel) | static_cast<int>(QFrame::Sunken));
406 QPalette pal = inputMessage->palette();
407 pal.setColor(inputMessage->backgroundRole(), QColor(255, 255, 224)); // Light yellow
408 pal.setColor(inputMessage->foregroundRole(), Qt::black);
409 inputMessage->setPalette(pal);
410 inputMessage->setAutoFillBackground(true);
411 inputMessage->setWordWrap(true);
412 inputMessage->setAlignment(Qt::AlignJustify);
413 inputMessage->setMargin(3);
414 inputMessage->setText(getOptionalMessage());
415 auto *msgArea = new QHBoxLayout;
416 msgArea->addWidget(inputMessage);
417 mainLay->addLayout(msgArea, 0);
418}
419
420//-------------------------------------------------------------------------------------------------
427
428/*
429 * Is there a message string available
430 * @returns A boolean indicating whether the message string is empty
431 */
432bool AlgorithmDialog::isMessageAvailable() const { return !m_strMessage.isEmpty(); }
433
434//-------------------------------------------------------------------------------------------------
439bool AlgorithmDialog::isWidgetEnabled(const QString &propName) const {
440 // To avoid errors
441 if (propName.isEmpty())
442 return true;
443
444 // Otherwise it must be disabled but only if it is valid
446 if (!property)
447 return true;
448
449 if (!isForScript()) {
450 // Regular C++ algo. Let the property tell us,
451 // possibly using validators, if it is to be shown enabled
452 if (property->getSettings())
453 return property->getSettings()->isEnabled(getAlgorithm().get());
454 else
455 return true;
456 } else {
457 // Algorithm dialog was called from a script(i.e. Python)
458 // Keep things enabled if requested
459 if (m_enabled.contains(propName))
460 return true;
461
468 return !(m_disabled.contains(propName) || m_python_arguments.contains(propName));
469 }
470}
471
472//-------------------------------------------------------------------------------------------------
477void AlgorithmDialog::untie(const QString &property) {
478 if (m_tied_properties.contains(property)) {
479 m_tied_properties.remove(property);
480 }
481}
482
483//-------------------------------------------------------------------------------------------------
497QWidget *AlgorithmDialog::tie(QWidget *widget, const QString &property, QLayout *parent_layout, bool readHistory) {
498 if (m_tied_properties.contains(property))
499 m_tied_properties.remove(property);
500
502 if (prop) { // Set a few things on the widget
503 widget->setToolTip(QString::fromStdString(prop->documentation()));
504 }
505 widget->setEnabled(isWidgetEnabled(property));
506
507 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
508
509 // Save in the hashes
510 m_tied_properties.insert(property, widget);
511
512 // If the widget's layout has been given then assume that a validator is
513 // required, else assume not
514 QWidget *validlbl(nullptr);
515 if (parent_layout) {
516 // Check if the validator is already there
517 validlbl = getValidatorMarker(property);
518 if (validlbl) {
519 // Find where it was sitting in the layout
520 int item_index;
521 if (propWidget)
522 item_index = parent_layout->indexOf(propWidget->getMainWidget());
523 else
524 item_index = parent_layout->indexOf(widget);
525
526 if (QBoxLayout *box = qobject_cast<QBoxLayout *>(parent_layout)) {
527 box->insertWidget(item_index + 1, validlbl);
528 } else if (QGridLayout *grid = qobject_cast<QGridLayout *>(parent_layout)) {
529 int row(0), col(0), span(0);
530 grid->getItemPosition(item_index, &row, &col, &span, &span);
531 grid->addWidget(validlbl, row, col + 2);
532 } else {
533 }
534 }
535 } else {
536 m_noValidation.append(property);
537 }
538
539 if (readHistory) {
540 setPreviousValue(widget, property);
541 }
542
543 // If the widget is a line edit and has no value then set the placeholder text
544 // to the default value.
545 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
546 if ((textfield)) {
547 if (prop) {
549 }
550 }
551
552 return validlbl;
553}
554
555//-------------------------------------------------------------------------------------------------
562QString AlgorithmDialog::openFileDialog(const QString &propName) {
563 if (propName.isEmpty())
564 return "";
566}
567
568//-------------------------------------------------------------------------------------------------
579void AlgorithmDialog::fillAndSetComboBox(const QString &propName, QComboBox *optionsBox) const {
580 if (!optionsBox)
581 return;
583 if (!property)
584 return;
585
586 std::vector<std::string> items = property->allowedValues();
587 std::vector<std::string>::const_iterator vend = items.end();
588 for (std::vector<std::string>::const_iterator vitr = items.begin(); vitr != vend; ++vitr) {
589 optionsBox->addItem(QString::fromStdString(*vitr));
590 }
591
592 // Display the appropriate value
593 QString displayed("");
594 if (!isForScript()) {
595 displayed = AlgorithmInputHistory::Instance().previousInput(m_algName, propName);
596 }
597 if (displayed.isEmpty()) {
598 displayed = QString::fromStdString(property->value());
599 }
600
601 int index = optionsBox->findText(displayed);
602 if (index >= 0) {
603 optionsBox->setCurrentIndex(index);
604 }
605}
606
607//-------------------------------------------------------------------------------------------------
613void AlgorithmDialog::fillLineEdit(const QString &propName, QLineEdit *textField) {
614 if (!isForScript()) {
615 textField->setText(AlgorithmInputHistory::Instance().previousInput(m_algName, propName));
616 } else {
618 if (property && property->isValid().empty() && (m_python_arguments.contains(propName) || !property->isDefault())) {
619 textField->setText(QString::fromStdString(property->value()));
620 }
621 }
622}
623
624//-------------------------------------------------------------------------------------------------
626QLayout *AlgorithmDialog::createDefaultButtonLayout(const QString &helpText, const QString &loadText,
627 const QString &cancelText, const QString &keepOpenText) {
628 m_okButton = new QPushButton(loadText);
629 connect(m_okButton, SIGNAL(clicked()), this, SLOT(accept()));
630 m_okButton->setDefault(true);
631
632 m_exitButton = new QPushButton(cancelText);
633 connect(m_exitButton, SIGNAL(clicked()), this, SLOT(reject()));
634
635 auto *buttonRowLayout = new QHBoxLayout;
636 buttonRowLayout->addWidget(createHelpButton(helpText));
637 buttonRowLayout->addStretch();
638
639 m_keepOpenCheckBox = new QCheckBox(keepOpenText);
640 m_keepOpenCheckBox->setLayoutDirection(Qt::LayoutDirection::RightToLeft);
641 connect(m_keepOpenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(keepOpenChanged(int)));
642 buttonRowLayout->addWidget(m_keepOpenCheckBox);
643 if (keepOpenText.isEmpty()) {
644 setShowKeepOpen(false);
645 }
646
647 buttonRowLayout->addWidget(m_okButton);
648 buttonRowLayout->addWidget(m_exitButton);
649
650 return buttonRowLayout;
651}
652
653//-------------------------------------------------------------------------------------------------
659QPushButton *AlgorithmDialog::createHelpButton(const QString &helpText) const {
660 auto *help = new QPushButton(helpText);
661 connect(help, SIGNAL(clicked()), this, SLOT(helpClicked()));
662 return help;
663}
664
669void AlgorithmDialog::flagInputWS(QWidget *inputWidget) { m_inputws_opts.push_back(inputWidget); }
670
671//-----------------------------------------------------------
672// Protected slots
673//-----------------------------------------------------------
679 // Get property values
680 parse();
681
682 // Try and set and validate the properties and
683 if (setPropertyValues()) {
684 // Store input for next time
685 saveInput();
686 if (!this->m_keepOpen) {
687 QDialog::accept();
688 } else {
690 }
691 } else {
692 QMessageBox::critical(this, "",
693 "One or more properties are invalid. The invalid properties are\n"
694 "marked with a *, hold your mouse over the * for more information.");
695 }
696}
697
699 emit closeEventCalled();
700 QDialog::reject();
701}
702
703//-------------------------------------------------------------------------------------------------
704
709 // determine the version to show
710 int version(-1); // the latest version
711 if (m_algorithm)
712 version = m_algorithm->version();
713
714 // bring up the help window
716}
717
718//-------------------------------------------------------------------------------------------------
719
723void AlgorithmDialog::keepOpenChanged(int state) { m_keepOpen = (state == Qt::Checked); }
724
725//-------------------------------------------------------------------------------------------------
726
732 // Clear any previous trackers so we know what state we are in
733 this->stopObserving(algToExec);
734
735 try {
736 // Add any custom AlgorithmObservers to the algorithm
737 for (auto &observer : m_observers) {
738 observer->observeAll(algToExec);
739 }
740
741 // Only need to observe finish events if we are staying open
742 if (m_keepOpenCheckBox && m_keepOpenCheckBox->isChecked()) {
743 this->observeFinish(algToExec);
744 this->observeError(algToExec);
745 m_statusTracked = true;
746 // Disable close button for a short period. If it is clicked to soon then
747 // Mantid crashes - https://github.com/mantidproject/mantid/issues/13836
748 if (m_exitButton) {
749 m_exitButton->setEnabled(false);
750 m_btnTimer.setInterval(1000);
751 connect(&m_btnTimer, SIGNAL(timeout()), this, SLOT(enableExitButton()));
752 } else {
753 m_statusTracked = false;
754 }
755 }
756 algToExec->executeAsync();
757 m_btnTimer.start();
758
759 if (m_okButton) {
760 m_okButton->setEnabled(false);
761 }
762 } catch (Poco::NoThreadAvailableException &) {
763 g_log.error() << "No thread was available to run the " << algToExec->name() << " algorithm in the background.\n";
764 }
765}
766
767//-------------------------------------------------------------------------------------------------
768
770 using namespace Mantid::API;
771 AlgorithmManager::Instance().removeById(m_algorithm->getAlgorithmID());
772}
773
775
776//------------------------------------------------------
777// Private member functions
778//------------------------------------------------------
783 QHashIterator<QString, QWidget *> itr(m_tied_properties);
784 while (itr.hasNext()) {
785 itr.next();
786 // Need to do different things depending on the type of the widget. getValue
787 // sorts this out
788 storePropertyValue(itr.key(), getValue(itr.value()));
789 }
790
791 // Now call parseInput, which can be overridden in an inheriting class
792 parseInput();
793}
794
795//-------------------------------------------------------------------------------------------------
802 if (presetValues.isEmpty())
803 return;
804 QHashIterator<QString, QString> itr(presetValues);
805 m_python_arguments.clear();
806 while (itr.hasNext()) {
807 itr.next();
808 QString name = itr.key();
809 m_python_arguments.append(name);
810 QString value = itr.value();
812 }
814}
815
816//------------------------------------------------------------------------------------------------
822void AlgorithmDialog::addEnabledAndDisableLists(const QStringList &enabled, const QStringList &disabled) {
823 m_enabled = enabled;
824 m_disabled = disabled;
825}
826
827//------------------------------------------------------------------------------------------------
834bool AlgorithmDialog::requestedToKeepEnabled(const QString &propName) const {
835 bool enabled(true);
836 if (m_disabled.contains(propName)) {
837 enabled = false;
838 } else if (m_enabled.contains(propName)) // Definitely enable
839 {
840 enabled = true;
841 } else // Nothing was specified
842 {
843 enabled = false;
844 }
845 return enabled;
846}
847
848//------------------------------------------------------------------------------------------------
852void AlgorithmDialog::isForScript(bool forScript) { m_forScript = forScript; }
853
854//------------------------------------------------------------------------------------------------
859 if (on) {
860 connect(this, SIGNAL(accepted()), this, SLOT(executeAlgorithmAsync()));
861 connect(this, SIGNAL(rejected()), this, SLOT(removeAlgorithmFromManager()));
862 } else {
863 disconnect(this, SIGNAL(accepted()), this, SLOT(executeAlgorithmAsync()));
864 disconnect(this, SIGNAL(rejected()), this, SLOT(removeAlgorithmFromManager()));
865 }
866}
867
868//-------------------------------------------------------------------------------------------------
871void AlgorithmDialog::setOptionalMessage(const QString &message) {
872 m_strMessage = message;
873 if (message.isEmpty())
874 m_strMessage = QString::fromStdString(getAlgorithm()->summary());
875 if (m_strMessage.isEmpty())
876 m_msgAvailable = false;
877 else
878 m_msgAvailable = true;
879}
880
881//-------------------------------------------------------------------------------------------------
889QString AlgorithmDialog::getValue(QWidget *widget) {
890 if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) {
891 return opts->currentText().trimmed();
892 } else if (QLineEdit *textfield = qobject_cast<QLineEdit *>(widget)) {
893 return textfield->text().trimmed();
894 } else if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) {
895 if (checker->isChecked())
896 return QString("1");
897 else
898 return QString("0");
899 } else if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) {
900 // String in ISO8601 format /* add toUTC() to go from local time */
901 QString value = dateEdit->dateTime().toString(Qt::ISODate);
902 return value;
903 } else if (MantidWidget *mtd_widget = qobject_cast<MantidWidget *>(widget)) {
904 return mtd_widget->getUserInput().toString().trimmed();
905 } else if (PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget)) {
906 return propWidget->getValue().trimmed();
907 } else {
908 QMessageBox::warning(this, windowTitle(),
909 QString("Cannot parse input from ") + widget->metaObject()->className() +
910 ". Update AlgorithmDialog::getValue() to cope with this widget.");
911 return "";
912 }
913}
914
915QString AlgorithmDialog::getPreviousValue(const QString &propName) const {
916 QString value;
917
918 if (!isForScript()) {
919 value = m_propertyValueMap.value(propName);
920 if (value.isEmpty())
921 value = AlgorithmInputHistory::Instance().previousInput(m_algName, propName);
922 } else if (getAlgorithmProperty(propName)) {
923 value = m_propertyValueMap.value(propName);
924 }
925
926 return value;
927}
928
929//------------------------------------------------------------------------------------------------
938void AlgorithmDialog::setPreviousValue(QWidget *widget, const QString &propName) {
939 // If is called from a script, check if we have such property
940 if (isForScript() && !getAlgorithmProperty(propName))
941 return;
942
943 QString value = getPreviousValue(propName);
944
946
947 // Do the right thing for the widget type
948 if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) {
949 if (property && value.isEmpty()) {
950 value = QString::fromStdString(property->value());
951 }
952 int index = opts->findText(value);
953 if (index >= 0) {
954 opts->setCurrentIndex(index);
955 }
956 return;
957 }
958 if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) {
959 if (value.isEmpty() && dynamic_cast<Mantid::Kernel::PropertyWithValue<bool> *>(property))
960 value = QString::fromStdString(property->value());
961 checker->setChecked(value != "0");
962 return;
963 }
964 if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) {
965 // String in ISO8601 format
966 DateAndTime t = DateAndTime::getCurrentTime();
967 try {
968 t.setFromISO8601(verifyAndSanitizeISO8601(value.toStdString()));
969 } catch (std::exception &) {
970 }
971 dateEdit->setDate(QDate(t.year(), t.month(), t.day()));
972 dateEdit->setTime(QTime(t.hour(), t.minute(), t.second(), 0));
973 return;
974 }
975
976 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
977 MantidWidget *mtdwidget = qobject_cast<MantidWidget *>(widget);
978 if (textfield || mtdwidget) {
979 if (!isForScript()) {
980 if (textfield)
981 textfield->setText(value);
982 else
983 mtdwidget->setUserInput(value);
984 } else {
985 // Need to check if this is the default value as we don't fill them in if
986 // they are
987 if (m_python_arguments.contains(propName) || !property->isDefault()) {
988 if (textfield)
989 textfield->setText(value);
990 else
991 mtdwidget->setUserInput(value);
992 }
993 }
994 return;
995 }
996
997 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
998 if (propWidget) {
999 propWidget->setPreviousValue(value);
1000
1001 return;
1002 }
1003
1004 // Reaching here means we have a widget type we don't understand. Tell the
1005 // developer
1006 QMessageBox::warning(this, windowTitle(),
1007 QString("Cannot set value for ") + widget->metaObject()->className() +
1008 ". Update AlgorithmDialog::setValue() to cope with this widget.");
1009}
1010
1019 m_observers.emplace_back(observer);
1020 // turn off the keep open option - it would only confuse things if someone is
1021 // watching
1022 setShowKeepOpen(false);
1023}
1024
1031 UNUSED_ARG(alg);
1032 emit algCompletedSignal();
1033}
1034
1041void AlgorithmDialog::errorHandle(const IAlgorithm *alg, const std::string &what) {
1042 UNUSED_ARG(alg);
1043 UNUSED_ARG(what);
1044 emit algCompletedSignal();
1045}
1046
1050void AlgorithmDialog::closeEvent(QCloseEvent *evt) {
1051 emit closeEventCalled();
1052 if (m_exitButton) {
1053 if (m_exitButton->isEnabled()) {
1054 evt->accept();
1055 } else {
1056 evt->ignore();
1057 }
1058 } else {
1059 QDialog::closeEvent(evt);
1060 }
1061}
1062
1068 if (m_okButton)
1069 m_okButton->setEnabled(true);
1070}
double value
The value of the point.
Definition: FitMW.cpp:51
double error
Definition: IndexPeaks.cpp:133
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
bool isMessageAvailable() const
Is there a message string available.
void addEnabledAndDisableLists(const QStringList &enabled, const QStringList &disabled)
Set comma-separated-list of enabled parameter names.
QStringList m_enabled
A list of property names that should have their widgets enabled.
void algCompletedSignal()
Emitted when alg completes and dialog is staying open.
virtual void executeAlgorithmAsync()
Executes the algorithm in a separate thread.
void setAlgorithm(const Mantid::API::IAlgorithm_sptr &)
The following methods were made public for testing in GenericDialogDemo.cpp.
bool requestedToKeepEnabled(const QString &propName) const
Test if the given name's widget has been explicity asked to be enabled.
QPushButton * createHelpButton(const QString &helpText=QString("?")) const
Create a help button for this algorithm.
virtual void algorithmCompleted()
Keep the running algorithm has completed.
virtual void removeAlgorithmFromManager()
Removes the algorithm from the manager.
bool m_statusTracked
A flag to track whether the status of the algorithm is being tracked.
bool setPropertyValues(const QStringList &skipList=QStringList())
Set properties on this algorithm by pulling values from the tied widgets.
void setShowKeepOpen(const bool showOption)
Set if the keep open option is shown.
QString getPreviousValue(const QString &propName) const
Get the property value from either the previous input store or from Python argument.
QStringList m_python_arguments
A list of property names that have been passed from Python.
virtual void parseInput()
Parse out the values entered into the dialog boxes.
QString m_strMessage
The message string to be displayed at the top of the widget; if it exists.
bool isWidgetEnabled(const QString &propName) const
Check is a given property should have its control enabled or not.
~AlgorithmDialog() override
Destructor.
QString getInputValue(const QString &propName) const
Get an input value from the form, dealing with blank inputs etc.
QHash< QString, QWidget * > m_tied_properties
A list pointers to the widget for each property.
QVector< QWidget * > m_inputws_opts
Store a list of the names of input workspace boxes.
QStringList m_disabled
A list of property names that the user has requested to be disabled (overrides those in enabled)
bool isForScript() const
Get the usage boolean value.
bool requiresUserInput(const QString &propName) const
Return a true if the given property requires user input.
bool m_forScript
A boolean indicating whether this is for a script or not.
void setOptionalMessage(const QString &message)
Set an optional message to be displayed at the top of the dialog.
void enableExitButton()
Enable to exit button.
void executeOnAccept(bool on)
If true then execute the algorithm on acceptance.
virtual void initLayout()=0
This does the work and must be overridden in each deriving class.
QString getValue(QWidget *widget)
Retrieve a text value for a property from a widget.
bool m_autoParseOnInit
Flag if the input should be parsed automatically on initialization.
void fillAndSetComboBox(const QString &propName, QComboBox *optionsBox) const
Fill a combo box for the named algorithm's allowed values.
Mantid::API::IAlgorithm_sptr m_algorithm
The algorithm associated with this dialog.
bool setPropertyValue(const QString &pName, bool validateOthers)
Sets the value of a single property, using the value previously stored using storePropertyValue()
AlgorithmDialog(QWidget *parent=nullptr)
DefaultConstructor.
void reject() override
A default slot that can be used for a rejected button.
void errorHandle(const Mantid::API::IAlgorithm *alg, const std::string &what) override
Handle completion of algorithm started while staying open.
bool m_msgAvailable
Is the message string empty or not.
QString openFileDialog(const QString &propName)
Open a file dialog to select a file.
QHash< QString, QString > m_errors
A map where key = property name; value = the error for this property (i.e.
QHash< QString, QString > m_propertyValueMap
A map of property <name, value> pairs that have been taken from the dialog.
QString m_algName
The name of the algorithm.
bool m_keepOpen
Whether to keep the dialog box open after alg execution.
virtual void helpClicked()
Help button clicked;.
QLabel * getValidatorMarker(const QString &propname)
Get a property validator label.
std::vector< Mantid::API::AlgorithmObserver * > m_observers
A list of AlgorithmObservers to add to the algorithm prior to execution.
void closeEvent(QCloseEvent *evt) override
Only allow close when close is enabled.
QLayout * createDefaultButtonLayout(const QString &helpText=QString("?"), const QString &loadText=QString("Run"), const QString &cancelText=QString("Close"), const QString &keepOpenText=QString("Keep Open"))
Create a row layout of buttons with specified text.
void initializeLayout()
Create the layout of the widget. Can only be called once.
void storePropertyValue(const QString &name, const QString &value)
Adds a property (name,value) pair to the stored map.
QVector< QLineEdit * > m_outputws_fields
Store a list of output workspace text edits.
void addAlgorithmObserver(Mantid::API::AlgorithmObserver *observer)
Add an AlgorithmObserver to the algorithm.
void parse()
Parse out the input from the dialog.
void removePropertyValue(const QString &name)
Removes a property (name, value) pair from the stored map.
void fillLineEdit(const QString &propName, QLineEdit *field)
Fill in the necessary input for a text field.
QWidget * tie(QWidget *widget, const QString &property, QLayout *parent_layout=nullptr, bool readHistory=true)
Tie a widget to a property.
QTimer m_btnTimer
Enable the close button when the timer fires.
void setPresetValues(const QHash< QString, QString > &presetValues)
Set a list of suggested values.
Mantid::API::IAlgorithm_sptr getAlgorithm() const
Get the algorithm pointer.
void setPreviousValue(QWidget *widget, const QString &property)
Set a value based on any old input that we have.
void flagInputWS(QWidget *inputWidget)
Flag an input workspace combobox with its property name.
void addOptionalMessage(QVBoxLayout *mainLay)
Add the optional message to the given layout.
QStringList m_algProperties
The properties associated with this dialog.
Mantid::Kernel::Property * getAlgorithmProperty(const QString &propName) const
Get a pointer to the named property.
QStringList m_noValidation
A list of property names whose widgets handle their own validation.
virtual void saveInput()
Save the input history of an accepted dialog.
void showValidators()
Show the validators for all the properties.
void untie(const QString &property)
Untie a widget to a property.
void accept() override
A default slot that can be used for an OK button.
bool isShowKeepOpen() const
Set if the keep open option is shown.
virtual void keepOpenChanged(int state)
Keep open checkbox clicked;.
bool isInitialized() const
Is this dialog initialized.
void finishHandle(const Mantid::API::IAlgorithm *alg) override
Handle completion of algorithm started while staying open.
bool m_isInitialized
Whether the layout has been initialized.
QHash< QPushButton *, int > m_wsbtn_tracker
A map to keep track of replace workspace button presses.
const QString & getOptionalMessage() const
Get the message string.
QHash< QString, QLabel * > m_validators
A list of labels to use as validation markers.
static QString openFileDialog(Mantid::Kernel::Property *baseProp)
Open the file dialog for a given property.
static void showAlgorithm(const std::string &name=std::string(), const int version=-1)
Definition: HelpWindow.cpp:50
This is the base class all customised widgets that do not wish to be tied to a specific Mantid algori...
Definition: MantidWidget.h:27
virtual void setUserInput(const QVariant &value)
Sets a value on a mantid widget through a common interface.
Definition: MantidWidget.h:39
Base class for widgets that will set Mantid::Kernel::Property* types.
virtual QWidget * getMainWidget()=0
static void setFieldPlaceholderText(Mantid::Kernel::Property *prop, QLineEdit *field)
Set the placeholder text of the given field based on the default value of the given property.
void setPreviousValue(const QString &previousValue)
Set this widget's previously-entered value.
Observes Algorithm notifications: start,progress,finish,error.
void observeFinish(const IAlgorithm_const_sptr &alg)
Connect to algorithm alg and observe its finish notification.
void stopObserving(const IAlgorithm_const_sptr &alg)
Disconnect from algorithm alg.
void observeError(const IAlgorithm_const_sptr &alg)
Connect to algorithm alg and observe its error notification.
IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:45
An interface that is implemented by WorkspaceProperty.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
The concrete, templated class for properties.
Base class for properties.
Definition: Property.h:94
unsigned int direction() const
returns the direction of the property
Definition: Property.h:172
const std::string & documentation() const
Get the property's documentation string.
Definition: Property.cpp:65
bool remember() const
Whether to save input values.
Definition: Property.cpp:109
virtual std::string isValid() const
Overridden function that checks whether the property, if not overriden returns "".
Definition: Property.cpp:82
const std::string & name() const
Get the property's name.
Definition: Property.cpp:60
virtual std::string getDefault() const =0
Get the default value for the property which is the value the property was initialised with.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
MANTID_KERNEL_DLL std::string verifyAndSanitizeISO8601(const std::string &date, bool displayWarnings=true)
Verifies whether or not a string conforms to ISO8601.
@ Output
An output workspace.
Definition: Property.h:54