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 QString value = getInputValue(pName);
319
320 std::string error("");
321 try {
322 getAlgorithm()->setPropertyValue(pName.toStdString(), value.toStdString());
323 } catch (std::exception &err_details) {
324 error = err_details.what();
325 }
326 // Save the error string for later
327 m_errors[pName] = QString::fromStdString(error).trimmed();
328
329 // Go through all the other properties' validators
330 if (validateOthers)
331 this->showValidators();
332
333 // Prop was valid if the error string is empty
334 return error.empty();
335}
336
337//-------------------------------------------------------------------------------------------------
344bool AlgorithmDialog::setPropertyValues(const QStringList &skipList) {
345 QStringList::const_iterator pend = m_algProperties.end();
346 bool allValid(true);
347 for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) {
348 const QString pName = *pitr;
349 if (skipList.contains(pName)) {
350 // For the load dialog, skips setting some properties
352 std::string error = p->isValid();
353 m_errors[pName] = QString::fromStdString(error).trimmed();
354 if (!error.empty())
355 allValid = false;
356 } else {
357 bool thisValid = this->setPropertyValue(pName, false);
358 allValid = allValid && thisValid;
359 }
360 }
361
362 // Do additional validation on the WHOLE set of properties
363 // But only if the individual validation passed
364 if (allValid) {
365 std::map<std::string, std::string> errs = m_algorithm->validateInputs();
366 for (auto &err : errs) {
367 // only count as an error if the named property exists
368 if (m_algorithm->existsProperty(err.first)) {
369 const QString pName = QString::fromStdString(err.first);
370 const QString value = QString::fromStdString(err.second);
371 if (m_errors.contains(pName)) {
372 if (!m_errors[pName].isEmpty())
373 m_errors[pName] += "\n";
374 m_errors[pName] += value;
375 } else
376 m_errors[pName] = value;
377 // There is at least one whole-algo error
378 allValid = false;
379 }
380 }
381 }
382
383 // OK all the values have been set once. Time to look for which should be
384 // enabled
385 this->showValidators();
386
387 return allValid;
388}
389
390//-------------------------------------------------------------------------------------------------
395const QString &AlgorithmDialog::getOptionalMessage() const { return m_strMessage; }
396
397//-------------------------------------------------------------------------------------------------
402void AlgorithmDialog::addOptionalMessage(QVBoxLayout *mainLay) {
403 QLabel *inputMessage = new QLabel(this);
404 inputMessage->setFrameStyle(static_cast<int>(QFrame::Panel) | static_cast<int>(QFrame::Sunken));
405 QPalette pal = inputMessage->palette();
406 pal.setColor(inputMessage->backgroundRole(), QColor(255, 255, 224)); // Light yellow
407 pal.setColor(inputMessage->foregroundRole(), Qt::black);
408 inputMessage->setPalette(pal);
409 inputMessage->setAutoFillBackground(true);
410 inputMessage->setWordWrap(true);
411 inputMessage->setAlignment(Qt::AlignJustify);
412 inputMessage->setMargin(3);
413 inputMessage->setText(getOptionalMessage());
414 auto *msgArea = new QHBoxLayout;
415 msgArea->addWidget(inputMessage);
416 mainLay->addLayout(msgArea, 0);
417}
418
419//-------------------------------------------------------------------------------------------------
426
427/*
428 * Is there a message string available
429 * @returns A boolean indicating whether the message string is empty
430 */
431bool AlgorithmDialog::isMessageAvailable() const { return !m_strMessage.isEmpty(); }
432
433//-------------------------------------------------------------------------------------------------
438bool AlgorithmDialog::isWidgetEnabled(const QString &propName) const {
439 // TODO: these "to avoid errors" prechecks mask defects.
440 // They really should be removed!!
441
442 // To avoid errors
443 if (propName.isEmpty())
444 return true;
445
446 if (!isForScript()) {
447 // Not called from a script:
448 // use the property's settings to determine if it should be enabled.
449 return m_algorithm->isPropertyEnabled(propName.toStdString());
450 } else {
451 // Called from a script:
452 // use the enabled / disabled lists to determine if it should be enabled.
453 if (m_enabled.contains(propName))
454 return true;
455
462 return !(m_disabled.contains(propName) || m_python_arguments.contains(propName));
463 }
464}
465
466//-------------------------------------------------------------------------------------------------
471void AlgorithmDialog::untie(const QString &property) {
472 if (m_tied_properties.contains(property)) {
473 m_tied_properties.remove(property);
474 }
475}
476
477//-------------------------------------------------------------------------------------------------
491QWidget *AlgorithmDialog::tie(QWidget *widget, const QString &property, QLayout *parent_layout, bool readHistory) {
492 if (m_tied_properties.contains(property))
493 m_tied_properties.remove(property);
494
496 if (prop) { // Set a few things on the widget
497 widget->setToolTip(QString::fromStdString(prop->documentation()));
498 }
499 widget->setEnabled(isWidgetEnabled(property));
500
501 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
502
503 // Save in the hashes
504 m_tied_properties.insert(property, widget);
505
506 // If the widget's layout has been given then assume that a validator is
507 // required, else assume not
508 QWidget *validlbl(nullptr);
509 if (parent_layout) {
510 // Check if the validator is already there
511 validlbl = getValidatorMarker(property);
512 if (validlbl) {
513 // Find where it was sitting in the layout
514 int item_index;
515 if (propWidget)
516 item_index = parent_layout->indexOf(propWidget->getMainWidget());
517 else
518 item_index = parent_layout->indexOf(widget);
519
520 if (QBoxLayout *box = qobject_cast<QBoxLayout *>(parent_layout)) {
521 box->insertWidget(item_index + 1, validlbl);
522 } else if (QGridLayout *grid = qobject_cast<QGridLayout *>(parent_layout)) {
523 int row(0), col(0), span(0);
524 grid->getItemPosition(item_index, &row, &col, &span, &span);
525 grid->addWidget(validlbl, row, col + 2);
526 } else {
527 }
528 }
529 } else {
530 m_noValidation.append(property);
531 }
532
533 if (readHistory) {
534 setPreviousValue(widget, property);
535 }
536
537 // If the widget is a line edit and has no value then set the placeholder text
538 // to the default value.
539 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
540 if ((textfield)) {
541 if (prop) {
543 }
544 }
545
546 return validlbl;
547}
548
549//-------------------------------------------------------------------------------------------------
556QString AlgorithmDialog::openFileDialog(const QString &propName) {
557 if (propName.isEmpty())
558 return "";
560}
561
562//-------------------------------------------------------------------------------------------------
572void AlgorithmDialog::fillAndSetComboBox(const QString &propName, QComboBox *optionsBox) const {
573 if (!optionsBox)
574 return;
575 const Mantid::Kernel::Property *property = getAlgorithmProperty(propName);
576 if (!property)
577 return;
578
579 std::vector<std::string> items = property->allowedValues();
580 std::vector<std::string>::const_iterator vend = items.end();
581 for (std::vector<std::string>::const_iterator vitr = items.begin(); vitr != vend; ++vitr) {
582 optionsBox->addItem(QString::fromStdString(*vitr));
583 }
584
585 // Display the appropriate value
586 QString displayed("");
587 if (!isForScript()) {
588 displayed = AlgorithmInputHistory::Instance().previousInput(m_algName, propName);
589 }
590 if (displayed.isEmpty()) {
591 displayed = QString::fromStdString(property->value());
592 }
593
594 int index = optionsBox->findText(displayed);
595 if (index >= 0) {
596 optionsBox->setCurrentIndex(index);
597 }
598}
599
600//-------------------------------------------------------------------------------------------------
606void AlgorithmDialog::fillLineEdit(const QString &propName, QLineEdit *textField) {
607 if (!isForScript()) {
608 textField->setText(AlgorithmInputHistory::Instance().previousInput(m_algName, propName));
609 } else {
610 const Mantid::Kernel::Property *property = getAlgorithmProperty(propName);
611 if (property && property->isValid().empty() && (m_python_arguments.contains(propName) || !property->isDefault())) {
612 textField->setText(QString::fromStdString(property->value()));
613 }
614 }
615}
616
617//-------------------------------------------------------------------------------------------------
619QLayout *AlgorithmDialog::createDefaultButtonLayout(const QString &helpText, const QString &loadText,
620 const QString &cancelText, const QString &keepOpenText) {
621 m_okButton = new QPushButton(loadText);
622 connect(m_okButton, SIGNAL(clicked()), this, SLOT(accept()));
623 m_okButton->setDefault(true);
624
625 m_exitButton = new QPushButton(cancelText);
626 connect(m_exitButton, SIGNAL(clicked()), this, SLOT(reject()));
627
628 auto *buttonRowLayout = new QHBoxLayout;
629 buttonRowLayout->addWidget(createHelpButton(helpText));
630 buttonRowLayout->addStretch();
631
632 m_keepOpenCheckBox = new QCheckBox(keepOpenText);
633 m_keepOpenCheckBox->setLayoutDirection(Qt::LayoutDirection::RightToLeft);
634 connect(m_keepOpenCheckBox, SIGNAL(stateChanged(int)), this, SLOT(keepOpenChanged(int)));
635 buttonRowLayout->addWidget(m_keepOpenCheckBox);
636 if (keepOpenText.isEmpty()) {
637 setShowKeepOpen(false);
638 }
639
640 buttonRowLayout->addWidget(m_okButton);
641 buttonRowLayout->addWidget(m_exitButton);
642
643 return buttonRowLayout;
644}
645
646//-------------------------------------------------------------------------------------------------
652QPushButton *AlgorithmDialog::createHelpButton(const QString &helpText) const {
653 auto *help = new QPushButton(helpText);
654 connect(help, SIGNAL(clicked()), this, SLOT(helpClicked()));
655 return help;
656}
657
662void AlgorithmDialog::flagInputWS(QWidget *inputWidget) { m_inputws_opts.push_back(inputWidget); }
663
664//-----------------------------------------------------------
665// Protected slots
666//-----------------------------------------------------------
672 // Get property values
673 parse();
674
675 // Try and set and validate the properties and
676 if (setPropertyValues()) {
677 // Store input for next time
678 saveInput();
679 if (!this->m_keepOpen) {
680 QDialog::accept();
681 } else {
683 }
684 } else {
685 QMessageBox::critical(this, "",
686 "One or more properties are invalid. The invalid properties are\n"
687 "marked with a *, hold your mouse over the * for more information.");
688 }
689}
690
692 emit closeEventCalled();
693 QDialog::reject();
694}
695
696//-------------------------------------------------------------------------------------------------
697
702 // determine the version to show
703 int version(-1); // the latest version
704 if (m_algorithm)
705 version = m_algorithm->version();
706
707 // bring up the help window
709}
710
711//-------------------------------------------------------------------------------------------------
712
716void AlgorithmDialog::keepOpenChanged(int state) { m_keepOpen = (state == Qt::Checked); }
717
718//-------------------------------------------------------------------------------------------------
719
725 // Clear any previous trackers so we know what state we are in
726 this->stopObserving(algToExec);
727
728 try {
729 // Add any custom AlgorithmObservers to the algorithm
730 for (auto &observer : m_observers) {
731 observer->observeAll(algToExec);
732 }
733
734 // Only need to observe finish events if we are staying open
735 if (m_keepOpenCheckBox && m_keepOpenCheckBox->isChecked()) {
736 this->observeFinish(algToExec);
737 this->observeError(algToExec);
738 m_statusTracked = true;
739 // Disable close button for a short period. If it is clicked to soon then
740 // Mantid crashes - https://github.com/mantidproject/mantid/issues/13836
741 if (m_exitButton) {
742 m_exitButton->setEnabled(false);
743 m_btnTimer.setInterval(1000);
744 connect(&m_btnTimer, SIGNAL(timeout()), this, SLOT(enableExitButton()));
745 }
746 }
747 algToExec->executeAsync();
748 m_btnTimer.start();
749
750 if (m_okButton) {
751 m_okButton->setEnabled(false);
752 }
753 } catch (Poco::NoThreadAvailableException &) {
754 g_log.error() << "No thread was available to run the " << algToExec->name() << " algorithm in the background.\n";
755 }
756}
757
758//-------------------------------------------------------------------------------------------------
759
761 using namespace Mantid::API;
762 AlgorithmManager::Instance().removeById(m_algorithm->getAlgorithmID());
763}
764
766
768
769//------------------------------------------------------
770// Private member functions
771//------------------------------------------------------
776 QHashIterator<QString, QWidget *> itr(m_tied_properties);
777 while (itr.hasNext()) {
778 itr.next();
779 // Need to do different things depending on the type of the widget. getValue
780 // sorts this out
781 storePropertyValue(itr.key(), getValue(itr.value()));
782 }
783
784 // Now call parseInput, which can be overridden in an inheriting class
785 parseInput();
786}
787
788//-------------------------------------------------------------------------------------------------
795 if (presetValues.isEmpty())
796 return;
797 QHashIterator<QString, QString> itr(presetValues);
798 m_python_arguments.clear();
799 while (itr.hasNext()) {
800 itr.next();
801 QString name = itr.key();
802 m_python_arguments.append(name);
803 QString value = itr.value();
805 }
807}
808
809//------------------------------------------------------------------------------------------------
815void AlgorithmDialog::addEnabledAndDisableLists(const QStringList &enabled, const QStringList &disabled) {
816 m_enabled = enabled;
817 m_disabled = disabled;
818}
819
820//------------------------------------------------------------------------------------------------
827bool AlgorithmDialog::requestedToKeepEnabled(const QString &propName) const {
828 bool enabled(true);
829 if (m_disabled.contains(propName)) {
830 enabled = false;
831 } else if (m_enabled.contains(propName)) // Definitely enable
832 {
833 enabled = true;
834 } else // Nothing was specified
835 {
836 enabled = false;
837 }
838 return enabled;
839}
840
841//------------------------------------------------------------------------------------------------
845void AlgorithmDialog::isForScript(bool forScript) { m_forScript = forScript; }
846
847//------------------------------------------------------------------------------------------------
852 if (on) {
853 connect(this, SIGNAL(accepted()), this, SLOT(executeAlgorithmAsync()));
854 connect(this, SIGNAL(rejected()), this, SLOT(removeAlgorithmFromManager()));
855 } else {
856 disconnect(this, SIGNAL(accepted()), this, SLOT(executeAlgorithmAsync()));
857 disconnect(this, SIGNAL(rejected()), this, SLOT(removeAlgorithmFromManager()));
858 }
859}
860
861//-------------------------------------------------------------------------------------------------
864void AlgorithmDialog::setOptionalMessage(const QString &message) {
865 m_strMessage = message;
866 if (message.isEmpty())
867 m_strMessage = QString::fromStdString(getAlgorithm()->summary());
868 if (m_strMessage.isEmpty())
869 m_msgAvailable = false;
870 else
871 m_msgAvailable = true;
872}
873
874//-------------------------------------------------------------------------------------------------
882QString AlgorithmDialog::getValue(QWidget *widget) {
883 if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) {
884 return opts->currentText().trimmed();
885 } else if (QLineEdit *textfield = qobject_cast<QLineEdit *>(widget)) {
886 return textfield->text().trimmed();
887 } else if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) {
888 if (checker->isChecked())
889 return QString("1");
890 else
891 return QString("0");
892 } else if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) {
893 // String in ISO8601 format /* add toUTC() to go from local time */
894 QString value = dateEdit->dateTime().toString(Qt::ISODate);
895 return value;
896 } else if (const MantidWidget *mtd_widget = qobject_cast<MantidWidget *>(widget)) {
897 return mtd_widget->getUserInput().toString().trimmed();
898 } else if (const PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget)) {
899 return propWidget->getValue().trimmed();
900 } else {
901 QMessageBox::warning(this, windowTitle(),
902 QString("Cannot parse input from ") + widget->metaObject()->className() +
903 ". Update AlgorithmDialog::getValue() to cope with this widget.");
904 return "";
905 }
906}
907
908QString AlgorithmDialog::getPreviousValue(const QString &propName) const {
909 QString value;
910
911 if (!isForScript()) {
912 value = m_propertyValueMap.value(propName);
913 if (value.isEmpty())
914 value = AlgorithmInputHistory::Instance().previousInput(m_algName, propName);
915 } else if (getAlgorithmProperty(propName)) {
916 value = m_propertyValueMap.value(propName);
917 }
918
919 return value;
920}
921
922//------------------------------------------------------------------------------------------------
931void AlgorithmDialog::setPreviousValue(QWidget *widget, const QString &propName) {
932 // If is called from a script, check if we have such property
933 if (isForScript() && !getAlgorithmProperty(propName))
934 return;
935
936 QString value = getPreviousValue(propName);
938
939 if (!isInitialized() && property->isDynamicDefault() && value == "")
940 // The property initialization order is non-deterministic: upstream properties may or may
941 // not be initialized prior to dependent properties.
942 // For this reason, we do not allow resetting a value derived from an upstream property
943 // back to default. Setting it to a non-default value indicates it actually had a
944 // previously-saved value that was not derived.
945 // (In present usage, `isInitialized()` will always be `false` here, but there's no harm
946 // in generalizing this method's applicability!)
947 return;
948
949 // Do the right thing for the widget type
950 if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) {
951 if (property && value.isEmpty()) {
952 value = QString::fromStdString(property->value());
953 }
954 int index = opts->findText(value);
955 if (index >= 0) {
956 opts->setCurrentIndex(index);
957 }
958 return;
959 }
960 if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) {
961 if (value.isEmpty() && dynamic_cast<Mantid::Kernel::PropertyWithValue<bool> *>(property))
962 value = QString::fromStdString(property->value());
963 checker->setChecked(value != "0");
964 return;
965 }
966 if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) {
967 // String in ISO8601 format
968 DateAndTime t = DateAndTime::getCurrentTime();
969 try {
970 t.setFromISO8601(verifyAndSanitizeISO8601(value.toStdString()));
971 } catch (std::exception &) {
972 }
973 dateEdit->setDate(QDate(t.year(), t.month(), t.day()));
974 dateEdit->setTime(QTime(t.hour(), t.minute(), t.second(), 0));
975 return;
976 }
977
978 QLineEdit *textfield = qobject_cast<QLineEdit *>(widget);
979 MantidWidget *mtdwidget = qobject_cast<MantidWidget *>(widget);
980 if (textfield || mtdwidget) {
981 if (!isForScript()) {
982 if (textfield)
983 textfield->setText(value);
984 else
985 mtdwidget->setUserInput(value);
986 } else {
987 // Need to check if this is the default value as we don't fill them in if
988 // they are
989 if (m_python_arguments.contains(propName) || !property->isDefault()) {
990 if (textfield)
991 textfield->setText(value);
992 else
993 mtdwidget->setUserInput(value);
994 }
995 }
996 return;
997 }
998
999 PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget);
1000 if (propWidget) {
1001 // Only non dynamic-default values reach this clause:
1002 // dynamic-default values are set in `AlgorithmPropertiesWidget::hideOrDisableProperties`.
1003 propWidget->setPrevious_isDynamicDefault(false);
1004 propWidget->setPreviousValue(value);
1005 return;
1006 }
1007
1008 // Reaching here means we have a widget type we don't understand. Tell the
1009 // developer
1010 QMessageBox::warning(this, windowTitle(),
1011 QString("Cannot set value for ") + widget->metaObject()->className() +
1012 ". Update AlgorithmDialog::setValue() to cope with this widget.");
1013}
1014
1023 m_observers.emplace_back(observer);
1024 // turn off the keep open option - it would only confuse things if someone is
1025 // watching
1026 setShowKeepOpen(false);
1027}
1028
1035 UNUSED_ARG(alg);
1036 emit algCompletedSignal();
1037}
1038
1045void AlgorithmDialog::errorHandle(const IAlgorithm *alg, const std::string &what) {
1046 UNUSED_ARG(alg);
1047 UNUSED_ARG(what);
1048 emit algCompletedSignal();
1049}
1050
1054void AlgorithmDialog::closeEvent(QCloseEvent *evt) {
1055 emit closeEventCalled();
1056 if (m_exitButton) {
1057 if (m_exitButton->isEnabled()) {
1058 evt->accept();
1059 } else {
1060 evt->ignore();
1061 }
1062 } else {
1063 QDialog::closeEvent(evt);
1064 }
1065}
1066
1072 if (m_okButton)
1073 m_okButton->setEnabled(true);
1074}
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:382
unsigned int direction() const
returns the direction of the property
Definition Property.h:176
const std::string & documentation() const
Get the property's documentation string.
Definition Property.cpp:78
bool remember() const
Whether to save input values.
Definition Property.cpp:124
virtual std::string isValid() const
Overridden function that checks whether the property, if not overriden returns "".
Definition Property.cpp:95
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:63
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