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
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 // normalize default (or default-derived) values to empty string.
167 QString value = p->isDefault() || p->isDynamicDefault() ? "" : m_propertyValueMap.value(pName);
168 AlgorithmInputHistory::Instance().storeNewValue(m_algName, QPair<QString, QString>(pName, value));
169 }
170 }
171}
172
173//-------------------------------------------------------------------------------------------------
179 m_algorithm = alg;
180 m_algName = QString::fromStdString(alg->name());
181 m_algProperties.clear();
182 m_tied_properties.clear();
183 std::vector<Mantid::Kernel::Property *>::const_iterator iend = alg->getProperties().end();
184 for (std::vector<Mantid::Kernel::Property *>::const_iterator itr = alg->getProperties().begin(); itr != iend; ++itr) {
185 Mantid::Kernel::Property *p = *itr;
187 m_algProperties.append(QString::fromStdString(p->name()));
188 }
189 }
190
191 m_validators.clear();
192 m_noValidation.clear();
193}
194
200
206 if (m_algProperties.contains(propName)) {
207 return m_algorithm->getProperty(propName.toStdString());
208 } else
209 return nullptr;
210}
211
216bool AlgorithmDialog::requiresUserInput(const QString &propName) const { return m_algProperties.contains(propName); }
217
218//-------------------------------------------------------------------------------------------------
223QString AlgorithmDialog::getInputValue(const QString &propName) const {
224 QString value = m_propertyValueMap.value(propName);
225 if (value.isEmpty()) {
226 const Mantid::Kernel::Property *prop = getAlgorithmProperty(propName);
227 if (prop)
228 return QString::fromStdString(prop->getDefault());
229 else
230 return "";
231 }
232
233 return value;
234}
235
236//-------------------------------------------------------------------------------------------------
242QLabel *AlgorithmDialog::getValidatorMarker(const QString &propname) {
243 if (m_noValidation.contains(propname))
244 return nullptr;
245 QLabel *validLbl(nullptr);
246 if (!m_validators.contains(propname)) {
247 validLbl = new QLabel("*", this);
248 QPalette pal = validLbl->palette();
249 pal.setColor(QPalette::WindowText, Qt::darkRed);
250 validLbl->setPalette(pal);
251 validLbl->setVisible(true);
252 m_validators[propname] = validLbl;
253 } else {
254 validLbl = m_validators.value(propname);
255 }
256 return validLbl;
257}
258
259//-------------------------------------------------------------------------------------------------
263void AlgorithmDialog::storePropertyValue(const QString &name, const QString &value) {
264 if (name.isEmpty())
265 return;
267}
268
269//-------------------------------------------------------------------------------------------------
275 if (name.isEmpty())
276 return;
277 m_propertyValueMap.remove(name);
278}
279
280//-------------------------------------------------------------------------------------------------
283 // Do nothing for non-generic algorithm dialogs
284 QStringList::const_iterator pend = m_algProperties.end();
285 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
286 const QString propName = *pitr;
287
288 // Find the widget for this property.
289 if (m_tied_properties.contains(propName)) {
290 // Show/hide the validator label (that red star)
291 QString error = "";
292 if (m_errors.contains(propName))
293 error = m_errors[propName];
294
295 QLabel *validator = getValidatorMarker(propName);
296 // If there's no validator then assume it's handling its own validation
297 // notification
298 if (validator && validator->parent()) {
299 validator->setToolTip(error);
300 validator->setVisible(error.length() != 0);
301 }
302 } // widget is tied
303 } // for each property
304}
305
306//-------------------------------------------------------------------------------------------------
317bool AlgorithmDialog::setPropertyValue(const QString &pName, bool validateOthers) {
318 // Mantid::Kernel::Property *p = getAlgorithmProperty(pName);
319 QString value = getInputValue(pName);
320
321 std::string error("");
322 try {
323 // error = p->setValue(value.toStdString());
324 getAlgorithm()->setPropertyValue(pName.toStdString(), value.toStdString());
325 } catch (std::exception &err_details) {
326 error = err_details.what();
327 }
328 // Save the error string for later
329 m_errors[pName] = QString::fromStdString(error).trimmed();
330
331 // Go through all the other properties' validators
332 if (validateOthers)
333 this->showValidators();
334
335 // Prop was valid if the error string is empty
336 return error.empty();
337}
338
339//-------------------------------------------------------------------------------------------------
346bool AlgorithmDialog::setPropertyValues(const QStringList &skipList) {
347 QStringList::const_iterator pend = m_algProperties.end();
348 bool allValid(true);
349 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
350 const QString pName = *pitr;
351 if (skipList.contains(pName)) {
352 // For the load dialog, skips setting some properties
354 std::string error = p->isValid();
355 m_errors[pName] = QString::fromStdString(error).trimmed();
356 if (!error.empty())
357 allValid = false;
358 } else {
359 bool thisValid = this->setPropertyValue(pName, false);
360 allValid = allValid && thisValid;
361 }
362 }
363
364 // Do additional validation on the WHOLE set of properties
365 // But only if the individual validation passed
366 if (allValid) {
367 std::map<std::string, std::string> errs = m_algorithm->validateInputs();
368 for (auto &err : errs) {
369 // only count as an error if the named property exists
370 if (m_algorithm->existsProperty(err.first)) {
371 const QString pName = QString::fromStdString(err.first);
372 const QString value = QString::fromStdString(err.second);
373 if (m_errors.contains(pName)) {
374 if (!m_errors[pName].isEmpty())
375 m_errors[pName] += "\n";
376 m_errors[pName] += value;
377 } else
378 m_errors[pName] = value;
379 // There is at least one whole-algo error
380 allValid = false;
381 }
382 }
383 }
384
385 // OK all the values have been set once. Time to look for which should be
386 // enabled
387 this->showValidators();
388
389 return allValid;
390}
391
392//-------------------------------------------------------------------------------------------------
397const QString &AlgorithmDialog::getOptionalMessage() const { return m_strMessage; }
398
399//-------------------------------------------------------------------------------------------------
404void AlgorithmDialog::addOptionalMessage(QVBoxLayout *mainLay) {
405 QLabel *inputMessage = new QLabel(this);
406 inputMessage->setFrameStyle(static_cast<int>(QFrame::Panel) | static_cast<int>(QFrame::Sunken));
407 QPalette pal = inputMessage->palette();
408 pal.setColor(inputMessage->backgroundRole(), QColor(255, 255, 224)); // Light yellow
409 pal.setColor(inputMessage->foregroundRole(), Qt::black);
410 inputMessage->setPalette(pal);
411 inputMessage->setAutoFillBackground(true);
412 inputMessage->setWordWrap(true);
413 inputMessage->setAlignment(Qt::AlignJustify);
414 inputMessage->setMargin(3);
415 inputMessage->setText(getOptionalMessage());
416 auto *msgArea = new QHBoxLayout;
417 msgArea->addWidget(inputMessage);
418 mainLay->addLayout(msgArea, 0);
419}
420
421//-------------------------------------------------------------------------------------------------
428
429/*
430 * Is there a message string available
431 * @returns A boolean indicating whether the message string is empty
432 */
433bool AlgorithmDialog::isMessageAvailable() const { return !m_strMessage.isEmpty(); }
434
435//-------------------------------------------------------------------------------------------------
440bool AlgorithmDialog::isWidgetEnabled(const QString &propName) const {
441 // To avoid errors
442 if (propName.isEmpty())
443 return true;
444
445 // Otherwise it must be disabled but only if it is valid
447 if (!property)
448 return true;
449
450 if (!isForScript()) {
451 // Regular C++ algo. Let the property tell us,
452 // possibly using validators, if it is to be shown enabled
453 if (property->getSettings())
454 return property->getSettings()->isEnabled(getAlgorithm().get());
455 else
456 return true;
457 } else {
458 // Algorithm dialog was called from a script(i.e. Python)
459 // Keep things enabled if requested
460 if (m_enabled.contains(propName))
461 return true;
462
469 return !(m_disabled.contains(propName) || m_python_arguments.contains(propName));
470 }
471}
472
473//-------------------------------------------------------------------------------------------------
478void AlgorithmDialog::untie(const QString &property) {
479 if (m_tied_properties.contains(property)) {
480 m_tied_properties.remove(property);
481 }
482}
483
484//-------------------------------------------------------------------------------------------------
498QWidget *AlgorithmDialog::tie(QWidget *widget, const QString &property, QLayout *parent_layout, bool readHistory) {
499 if (m_tied_properties.contains(property))
500 m_tied_properties.remove(property);
501
503 if (prop) { // Set a few things on the widget
504 widget->setToolTip(QString::fromStdString(prop->documentation()));
505 }
506 widget->setEnabled(isWidgetEnabled(property));
507
508 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
509
510 // Save in the hashes
511 m_tied_properties.insert(property, widget);
512
513 // If the widget's layout has been given then assume that a validator is
514 // required, else assume not
515 QWidget *validlbl(nullptr);
516 if (parent_layout) {
517 // Check if the validator is already there
518 validlbl = getValidatorMarker(property);
519 if (validlbl) {
520 // Find where it was sitting in the layout
521 int item_index;
522 if (propWidget)
523 item_index = parent_layout->indexOf(propWidget->getMainWidget());
524 else
525 item_index = parent_layout->indexOf(widget);
526
527 if (QBoxLayout *box = qobject_cast<QBoxLayout *>(parent_layout)) {
528 box->insertWidget(item_index + 1, validlbl);
529 } else if (QGridLayout *grid = qobject_cast<QGridLayout *>(parent_layout)) {
530 int row(0), col(0), span(0);
531 grid->getItemPosition(item_index, &row, &col, &span, &span);
532 grid->addWidget(validlbl, row, col + 2);
533 } else {
534 }
535 }
536 } else {
537 m_noValidation.append(property);
538 }
539
540 if (readHistory) {
541 setPreviousValue(widget, property);
542 }
543
544 // If the widget is a line edit and has no value then set the placeholder text
545 // to the default value.
546 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
547 if ((textfield)) {
548 if (prop) {
550 }
551 }
552
553 return validlbl;
554}
555
556//-------------------------------------------------------------------------------------------------
563QString AlgorithmDialog::openFileDialog(const QString &propName) {
564 if (propName.isEmpty())
565 return "";
567}
568
569//-------------------------------------------------------------------------------------------------
579void AlgorithmDialog::fillAndSetComboBox(const QString &propName, QComboBox *optionsBox) const {
580 if (!optionsBox)
581 return;
582 const Mantid::Kernel::Property *property = getAlgorithmProperty(propName);
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 {
617 const Mantid::Kernel::Property *property = getAlgorithmProperty(propName);
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 }
753 }
754 algToExec->executeAsync();
755 m_btnTimer.start();
756
757 if (m_okButton) {
758 m_okButton->setEnabled(false);
759 }
760 } catch (Poco::NoThreadAvailableException &) {
761 g_log.error() << "No thread was available to run the " << algToExec->name() << " algorithm in the background.\n";
762 }
763}
764
765//-------------------------------------------------------------------------------------------------
766
768 using namespace Mantid::API;
769 AlgorithmManager::Instance().removeById(m_algorithm->getAlgorithmID());
770}
771
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 (const MantidWidget *mtd_widget = qobject_cast<MantidWidget *>(widget)) {
904 return mtd_widget->getUserInput().toString().trimmed();
905 } else if (const 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);
945
946 if (!isInitialized() && property->isDynamicDefault() && value == "")
947 // The property initialization order is non-deterministic: upstream properties may or may
948 // not be initialized prior to dependent properties.
949 // For this reason, we do not allow resetting a value derived from an upstream property
950 // back to default. Setting it to a non-default value indicates it actually had a
951 // previously-saved value that was not derived.
952 // (In present usage, `isInitialized()` will always be `false` here, but there's no harm
953 // in generalizing this method's applicability!)
954 return;
955
956 // Do the right thing for the widget type
957 if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) {
958 if (property && value.isEmpty()) {
959 value = QString::fromStdString(property->value());
960 }
961 int index = opts->findText(value);
962 if (index >= 0) {
963 opts->setCurrentIndex(index);
964 }
965 return;
966 }
967 if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) {
968 if (value.isEmpty() && dynamic_cast<Mantid::Kernel::PropertyWithValue<bool> *>(property))
969 value = QString::fromStdString(property->value());
970 checker->setChecked(value != "0");
971 return;
972 }
973 if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) {
974 // String in ISO8601 format
975 DateAndTime t = DateAndTime::getCurrentTime();
976 try {
977 t.setFromISO8601(verifyAndSanitizeISO8601(value.toStdString()));
978 } catch (std::exception &) {
979 }
980 dateEdit->setDate(QDate(t.year(), t.month(), t.day()));
981 dateEdit->setTime(QTime(t.hour(), t.minute(), t.second(), 0));
982 return;
983 }
984
985 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
986 MantidWidget *mtdwidget = qobject_cast<MantidWidget *>(widget);
987 if (textfield || mtdwidget) {
988 if (!isForScript()) {
989 if (textfield)
990 textfield->setText(value);
991 else
992 mtdwidget->setUserInput(value);
993 } else {
994 // Need to check if this is the default value as we don't fill them in if
995 // they are
996 if (m_python_arguments.contains(propName) || !property->isDefault()) {
997 if (textfield)
998 textfield->setText(value);
999 else
1000 mtdwidget->setUserInput(value);
1001 }
1002 }
1003 return;
1004 }
1005
1006 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
1007 if (propWidget) {
1008 // Only non dynamic-default values reach this clause:
1009 // dynamic-default values are set in `AlgorithmPropertiesWidget::hideOrDisableProperties`.
1010 propWidget->setPrevious_isDynamicDefault(false);
1011 propWidget->setPreviousValue(value);
1012 return;
1013 }
1014
1015 // Reaching here means we have a widget type we don't understand. Tell the
1016 // developer
1017 QMessageBox::warning(this, windowTitle(),
1018 QString("Cannot set value for ") + widget->metaObject()->className() +
1019 ". Update AlgorithmDialog::setValue() to cope with this widget.");
1020}
1021
1030 m_observers.emplace_back(observer);
1031 // turn off the keep open option - it would only confuse things if someone is
1032 // watching
1033 setShowKeepOpen(false);
1034}
1035
1042 UNUSED_ARG(alg);
1043 emit algCompletedSignal();
1044}
1045
1052void AlgorithmDialog::errorHandle(const IAlgorithm *alg, const std::string &what) {
1053 UNUSED_ARG(alg);
1054 UNUSED_ARG(what);
1055 emit algCompletedSignal();
1056}
1057
1061void AlgorithmDialog::closeEvent(QCloseEvent *evt) {
1062 emit closeEventCalled();
1063 if (m_exitButton) {
1064 if (m_exitButton->isEnabled()) {
1065 evt->accept();
1066 } else {
1067 evt->ignore();
1068 }
1069 } else {
1070 QDialog::closeEvent(evt);
1071 }
1072}
1073
1079 if (m_okButton)
1080 m_okButton->setEnabled(true);
1081}
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double error
std::map< DeltaEMode::Type, std::string > index
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
void disableExitButton()
Disable the exit button.
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)
This is the base class all customised widgets that do not wish to be tied to a specific Mantid algori...
virtual void setUserInput(const QVariant &value)
Sets a value on a mantid widget through a common interface.
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 setPrevious_isDynamicDefault(bool flag)
Set the isDynamicDefault flag associated with the previously-entered value.
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:51
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
The concrete, templated class for properties.
Base class for properties.
Definition Property.h:94
bool isDynamicDefault() const
Returns a flag indicating that the property's value has been set programmatically,...
Definition Property.cpp:380
unsigned int direction() const
returns the direction of the property
Definition Property.h:177
const std::string & documentation() const
Get the property's documentation string.
Definition Property.cpp:76
bool remember() const
Whether to save input values.
Definition Property.cpp:121
virtual std::string isValid() const
Overridden function that checks whether the property, if not overriden returns "".
Definition Property.cpp:93
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
const std::string & name() const
Get the property's name.
Definition Property.cpp:61
virtual std::string getDefault() const =0
Get the default value for the property which is the value the property was initialised with.
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