/** * Takes a combobox and adds the allowed values of the given property to its * list. * It also sets the displayed value to the correct one based on either the * history * or a script input value * @param propName :: The name of the property * @param optionsBox :: A pointer to a QComoboBox object * @returns A newed QComboBox */ void AlgorithmDialog::fillAndSetComboBox(const QString &propName, QComboBox *optionsBox) const { if (!optionsBox) return; Mantid::Kernel::Property *property = getAlgorithmProperty(propName); if (!property) return; std::vector<std::string> items = property->allowedValues(); std::vector<std::string>::const_iterator vend = items.end(); for (std::vector<std::string>::const_iterator vitr = items.begin(); vitr != vend; ++vitr) { optionsBox->addItem(QString::fromStdString(*vitr)); } // Display the appropriate value QString displayed(""); if (!isForScript()) { displayed = AlgorithmInputHistory::Instance().previousInput(m_algName, propName); } if (displayed.isEmpty()) { displayed = QString::fromStdString(property->value()); } int index = optionsBox->findText(displayed); if (index >= 0) { optionsBox->setCurrentIndex(index); } }
/** Loads and checks the values passed to the algorithm * * @throw invalid_argument if there is an incapatible property value so the algorithm can't continue */ void DetectorEfficiencyCorUser::retrieveProperties() { // Get the workspaces m_inputWS = this->getProperty("InputWorkspace"); m_outputWS = this->getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for the output if (m_outputWS != this->m_inputWS) { m_outputWS = API::WorkspaceFactory::Instance().create(m_inputWS); } // these first three properties are fully checked by validators m_Ei = this->getProperty("IncidentEnergy"); // If we're not given an Ei, see if one has been set. if (m_Ei == EMPTY_DBL()) { Mantid::Kernel::Property* prop = m_inputWS->run().getProperty("Ei"); double val; if (!prop || !Strings::convert(prop->value(), val)) { throw std::invalid_argument( "No Ei value has been set or stored within the run information."); } m_Ei = val; g_log.debug() << "Using stored Ei value " << m_Ei << "\n"; } else { g_log.debug() << "Using user input Ei value: " << m_Ei << "\n"; } }
/** * Check if the control should be enabled for this property * @param propName :: The name of the property */ bool AlgorithmDialog::isWidgetEnabled(const QString &propName) const { // To avoid errors if (propName.isEmpty()) return true; // Otherwise it must be disabled but only if it is valid Mantid::Kernel::Property *property = getAlgorithmProperty(propName); if (!property) return true; if (!isForScript()) { // Regular C++ algo. Let the property tell us, // possibly using validators, if it is to be shown enabled if (property->getSettings()) return property->getSettings()->isEnabled(getAlgorithm().get()); else return true; } else { // Algorithm dialog was called from a script(i.e. Python) // Keep things enabled if requested if (m_enabled.contains(propName)) return true; /** * The control is disabled if * (1) It is contained in the disabled list or * (2) A user passed a value into the dialog */ return !(m_disabled.contains(propName) || m_python_arguments.contains(propName)); } }
/** * Tie together an input widget and a property * @param widget :: The widget that will collect the input * @param property :: The name of the property to tie the given widget to * @param parent_layout :: An optional pointer to a QLayout class that is reponsible for managing the passed widget. * If given, a validator label will be added for the given input widget * @param readHistory :: If true then a history value will be retrieved * * @return A NULL pointer if a valid label was successfully add to a passed parent_layout otherwise it * returns a pointer to the QLabel instance marking the validity */ QWidget* AlgorithmDialog::tie(QWidget* widget, const QString & property, QLayout *parent_layout, bool readHistory) { if( m_tied_properties.contains(property) ) m_tied_properties.remove(property); Mantid::Kernel::Property * prop = getAlgorithmProperty(property); if( prop ) { //Set a few things on the widget widget->setToolTip(QString::fromStdString(prop->documentation())); } widget->setEnabled(isWidgetEnabled(property)); PropertyWidget * propWidget = qobject_cast<PropertyWidget*>(widget); // Save in the hashes m_tied_properties.insert(property, widget); // If the widget's layout has been given then assume that a validator is required, else assume not QWidget* validlbl(NULL); if( parent_layout ) { // Check if the validator is already there validlbl = getValidatorMarker(property); if( validlbl ) { // Find where it was sitting in the layout int item_index; if (propWidget) item_index = parent_layout->indexOf(propWidget->getMainWidget()); else item_index = parent_layout->indexOf(widget); if( QBoxLayout *box = qobject_cast<QBoxLayout*>(parent_layout) ) { box->insertWidget(item_index + 1, validlbl); } else if( QGridLayout *grid = qobject_cast<QGridLayout*>(parent_layout) ) { int row(0), col(0), span(0); grid->getItemPosition(item_index, &row, &col, &span, &span); grid->addWidget(validlbl, row, col+2); } else {} } } else { m_noValidation.append(property); } if( readHistory ) { setPreviousValue(widget, property); } return validlbl; }
/* * Get run property as double * @s - input property name * */ double ConvertToConstantL2::getRunProperty(std::string s) { Mantid::Kernel::Property *prop = m_inputWS->run().getProperty(s); double val; if (!prop || !Strings::convert(prop->value(), val)) { std::string mesg = "Run property " + s + "doesn't exist!"; g_log.error(mesg); throw std::runtime_error(mesg); } return val; }
/** * Get an input value from the form, dealing with blank inputs etc * @param propName :: The name of the property */ QString AlgorithmDialog::getInputValue(const QString &propName) const { QString value = m_propertyValueMap.value(propName); if (value.isEmpty()) { Mantid::Kernel::Property *prop = getAlgorithmProperty(propName); if (prop) return QString::fromStdString(prop->getDefault()); else return ""; } return value; }
/** * Set the input for a text box based on either the history or a script value * @param propName :: The name of the property * @param textField :: The QLineEdit field */ void AlgorithmDialog::fillLineEdit(const QString &propName, QLineEdit *textField) { if (!isForScript()) { textField->setText( AlgorithmInputHistory::Instance().previousInput(m_algName, propName)); } else { Mantid::Kernel::Property *property = getAlgorithmProperty(propName); if (property && property->isValid().empty() && (m_python_arguments.contains(propName) || !property->isDefault())) { textField->setText(QString::fromStdString(property->value())); } } }
/** * Save the property values to the input history */ void AlgorithmDialog::saveInput() { AlgorithmInputHistory::Instance().clearAlgorithmInput(m_algName); QStringList::const_iterator pend = m_algProperties.end(); for (QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr) { Mantid::Kernel::Property *p = getAlgorithmProperty(*pitr); if (p->remember()) { QString pName = *pitr; QString value = m_propertyValueMap.value(pName); AlgorithmInputHistory::Instance().storeNewValue( m_algName, QPair<QString, QString>(pName, value)); } } }
/** Set the properties that have been parsed from the dialog. * * @param skipList :: An optional list of property names whose values will not be set * @returns A boolean that indicates if the validation was successful. */ bool AlgorithmDialog::setPropertyValues(const QStringList & skipList) { QStringList::const_iterator pend = m_algProperties.end(); bool allValid(true); for( QStringList::const_iterator pitr = m_algProperties.begin(); pitr != pend; ++pitr ) { const QString pName = *pitr; if( skipList.contains(pName) ) { // For the load dialog, skips setting some properties Mantid::Kernel::Property *p = getAlgorithmProperty(pName); std::string error = p->isValid(); m_errors[pName] = QString::fromStdString(error).trimmed(); if (!error.empty()) allValid = false; } else { bool thisValid = this->setPropertyValue(pName, false); allValid = allValid && thisValid; } } // Do additional validation on the WHOLE set of properties // But only if the individual validation passed if ( allValid ) { std::map<std::string, std::string> errs = m_algorithm->validateInputs(); for (auto it = errs.begin(); it != errs.end(); it++) { const QString pName = QString::fromStdString(it->first); const QString value = QString::fromStdString(it->second); if (m_errors.contains(pName)) { if (!m_errors[pName].isEmpty()) m_errors[pName] += "\n"; m_errors[pName] += value; } else m_errors[pName] = value; // There is at least one whole-algo error allValid = false; } } // OK all the values have been set once. Time to look for which should be enabled this->showValidators(); return allValid; }
/** * Set the algorithm pointer * @param alg :: A pointer to the algorithm */ void AlgorithmDialog::setAlgorithm(Mantid::API::IAlgorithm_sptr alg) { m_algorithm = alg; m_algName = QString::fromStdString(alg->name()); m_algProperties.clear(); m_tied_properties.clear(); std::vector<Mantid::Kernel::Property *>::const_iterator iend = alg->getProperties().end(); for (std::vector<Mantid::Kernel::Property *>::const_iterator itr = alg->getProperties().begin(); itr != iend; ++itr) { Mantid::Kernel::Property *p = *itr; if (dynamic_cast<Mantid::API::IWorkspaceProperty *>(p) || p->direction() != Mantid::Kernel::Direction::Output) { m_algProperties.append(QString::fromStdString(p->name())); } } m_validators.clear(); m_noValidation.clear(); }
std::string FrameworkManagerProxy::createAlgorithmDocs(const std::string& algName, const int version) { const std::string EOL="\n"; API::IAlgorithm_sptr algm = API::AlgorithmManager::Instance().createUnmanaged(algName, version); algm->initialize(); // Put in the quick overview message std::stringstream buffer; std::string temp = algm->getOptionalMessage(); if (temp.size() > 0) buffer << temp << EOL << EOL; // get a sorted copy of the properties PropertyVector properties(algm->getProperties()); std::sort(properties.begin(), properties.end(), PropertyOrdering()); // generate the sanitized names StringVector names(properties.size()); size_t numProps = properties.size(); for ( size_t i = 0; i < numProps; ++i) { names[i] = removeCharacters(properties[i]->name(), ""); } buffer << "Property descriptions: " << EOL << EOL; // write the actual property descriptions Mantid::Kernel::Property *prop; for ( size_t i = 0; i < numProps; ++i) { prop = properties[i]; buffer << names[i] << "(" << Mantid::Kernel::Direction::asText(prop->direction()); if (!prop->isValid().empty()) buffer << ":req"; buffer << ") *" << prop->type() << "* "; std::set<std::string> allowed = prop->allowedValues(); if (!prop->documentation().empty() || !allowed.empty()) { buffer << " " << prop->documentation(); if (!allowed.empty()) { buffer << " [" << Kernel::Strings::join(allowed.begin(), allowed.end(), ", "); buffer << "]"; } buffer << EOL; if( i < numProps - 1 ) buffer << EOL; } } return buffer.str(); }
/** Set a value for a widget. * * The function needs to know about the types of widgets * that are being used. Currently it knows about QComboBox, QLineEdit and * QCheckBox * @param widget :: A pointer to the widget * @param propName :: The property name */ void AlgorithmDialog::setPreviousValue(QWidget *widget, const QString &propName) { // If is called from a script, check if we have such property if (isForScript() && !getAlgorithmProperty(propName)) return; QString value = getPreviousValue(propName); Mantid::Kernel::Property *property = getAlgorithmProperty(propName); // Do the right thing for the widget type if (QComboBox *opts = qobject_cast<QComboBox *>(widget)) { if (property && value.isEmpty()) { value = QString::fromStdString(property->value()); } int index = opts->findText(value); if (index >= 0) { opts->setCurrentIndex(index); } return; } if (QAbstractButton *checker = qobject_cast<QAbstractButton *>(widget)) { if (value.isEmpty() && dynamic_cast<Mantid::Kernel::PropertyWithValue<bool> *>(property)) value = QString::fromStdString(property->value()); checker->setChecked(value != "0"); return; } if (QDateTimeEdit *dateEdit = qobject_cast<QDateTimeEdit *>(widget)) { // String in ISO8601 format DateAndTime t = DateAndTime::getCurrentTime(); try { t.setFromISO8601(verifyAndSanitizeISO8601(value.toStdString())); } catch (std::exception &) { } dateEdit->setDate(QDate(t.year(), t.month(), t.day())); dateEdit->setTime(QTime(t.hour(), t.minute(), t.second(), 0)); return; } QLineEdit *textfield = qobject_cast<QLineEdit *>(widget); MantidWidget *mtdwidget = qobject_cast<MantidWidget *>(widget); if (textfield || mtdwidget) { if (!isForScript()) { if (textfield) textfield->setText(value); else mtdwidget->setUserInput(value); } else { // Need to check if this is the default value as we don't fill them in if // they are if (m_python_arguments.contains(propName) || !property->isDefault()) { if (textfield) textfield->setText(value); else mtdwidget->setUserInput(value); } } return; } PropertyWidget *propWidget = qobject_cast<PropertyWidget *>(widget); if (propWidget) { propWidget->setPreviousValue(value); return; } // Reaching here means we have a widget type we don't understand. Tell the // developer QMessageBox::warning( this, windowTitle(), QString("Cannot set value for ") + widget->metaObject()->className() + ". Update AlgorithmDialog::setValue() to cope with this widget."); }
/** * A helper function to create the simple API * @param algName :: A string giving the name of the algorithm * @param path :: The path to the .m file that we should create */ void CreateSimpleAPIHelper(const std::string &algName, const std::string &path) { IAlgorithm *alg; try { alg = FrameworkManager::Instance().createAlgorithm(algName); } catch (std::exception &) { std::string err = "An error occurred while writing the "; err += algName + " function definition.\n"; mexErrMsgTxt(err.c_str()); return; } std::string fullpath(path + algName + ".m"); std::ofstream mfile(fullpath.c_str()); typedef std::vector<Mantid::Kernel::Property *> PropertyVector; // parameter list mfile << "function res = " << algName << "(varargin)\n"; // help string PropertyVector orderedProperties(alg->getProperties()); std::sort(orderedProperties.begin(), orderedProperties.end(), PropertyOrdering()); PropertyVector::const_iterator pIter = orderedProperties.begin(); PropertyVector::const_iterator pEnd = orderedProperties.end(); mfile << "%\t" << algName << "("; for (; pIter != pEnd;) { mfile << (*pIter)->name(); if (++pIter != pEnd) mfile << ", "; } mfile << ")\n"; mfile << "%\t\tArgument description:\n"; pIter = orderedProperties.begin(); unsigned int iOpt(0); for (; pIter != pEnd; ++pIter) { Mantid::Kernel::Property *prop = *pIter; mfile << "%\t\tName: " << prop->name() << ", Optional: "; if (prop->isValid() == "") { ++iOpt; mfile << "Yes, Default value: " << santizePropertyValue(prop->value()); } else mfile << "No"; mfile << ", Direction: " << Mantid::Kernel::Direction::asText(prop->direction()); // << ", "; auto allowed = prop->allowedValues(); if (!allowed.empty()) { mfile << ", Allowed values: "; auto sIter = allowed.begin(); auto sEnd = allowed.end(); for (; sIter != sEnd;) { mfile << (*sIter); if (++sIter != sEnd) mfile << ", "; } } mfile << "\n"; } mfile << "%\n%\tNote: All string arguments must be wrapped in single quotes " "''.\n"; // The function definition mfile << "if nargin < " << (orderedProperties.size() - iOpt) << "\n" << "\tfprintf('All mandatory arguments have not been supplied, type " "\"help " << algName << "\" for more information\\n');\n" << "\treturn\n" << "end\n"; mfile << "alg = MantidAlgorithm('" << algName << "');\n" << "argstring = '';\n"; // Build arguments list mfile << "for i = 1:nargin\n" << "\targstring = strcat(argstring,varargin{i});\n" << "\tif i < nargin\n" << "\t\targstring = strcat(argstring, ';');\n" << "\tend\n" << "end\n"; // Run the algorithm mfile << "res = run(alg, argstring);\n"; mfile.close(); }
/** * Reimplemented virtual function to set up the dialog */ void LoadRawDialog::initLayout() { QVBoxLayout *main_layout = new QVBoxLayout(this); // Add the helpful summary message if (isMessageAvailable()) this->addOptionalMessage(main_layout); //------------- Filename property --------------------- QHBoxLayout *prop_line = new QHBoxLayout; prop_line->addWidget(new QLabel("Select a file to load:")); m_pathBox = new QLineEdit; m_pathBox->setMinimumWidth(m_pathBox->fontMetrics().maxWidth() * 13); prop_line->addWidget(m_pathBox); tie(m_pathBox, "Filename", prop_line); QPushButton *browseBtn = new QPushButton("Browse"); connect(browseBtn, SIGNAL(clicked()), this, SLOT(browseClicked())); browseBtn->setEnabled(isWidgetEnabled("Filename")); prop_line->addWidget(browseBtn); main_layout->addLayout(prop_line); //------------- OutputWorkspace property --------------------- m_wsBox = new QLineEdit; prop_line = new QHBoxLayout; prop_line->addWidget(new QLabel("Enter name for workspace:")); prop_line->addWidget(m_wsBox); tie(m_wsBox, "OutputWorkspace", prop_line); prop_line->addStretch(); main_layout->addLayout(prop_line); //------------- Spectra properties --------------------- QGroupBox *groupbox = new QGroupBox("Spectra Options"); prop_line = new QHBoxLayout; QLineEdit *text_field = new QLineEdit; text_field->setMaximumWidth(m_wsBox->fontMetrics().width("888888")); prop_line->addWidget(new QLabel("Start:")); prop_line->addWidget(text_field); tie(text_field, "SpectrumMin", prop_line); text_field = new QLineEdit; text_field->setMaximumWidth(m_wsBox->fontMetrics().width("888888")); prop_line->addWidget(new QLabel("End:")); prop_line->addWidget(text_field); tie(text_field, "SpectrumMax", prop_line); text_field = new QLineEdit; prop_line->addWidget(new QLabel("List:")); prop_line->addWidget(text_field); tie(text_field, "SpectrumList", prop_line); prop_line->addStretch(); groupbox->setLayout(prop_line); main_layout->addWidget(groupbox); //------------- Period properties --------------------- prop_line = new QHBoxLayout; text_field = new QLineEdit; prop_line->addWidget(new QLabel("Periods:")); prop_line->addWidget(text_field); prop_line->addStretch(); tie(text_field, "PeriodList", prop_line); main_layout->addLayout(prop_line); //------------- Cache option , log files options and Monitors Options //--------------------- Mantid::Kernel::Property *cacheProp = getAlgorithmProperty("Cache"); if (cacheProp) { QComboBox *cacheBox = new QComboBox; std::vector<std::string> items = cacheProp->allowedValues(); std::vector<std::string>::const_iterator vend = items.end(); for (std::vector<std::string>::const_iterator vitr = items.begin(); vitr != vend; ++vitr) { cacheBox->addItem(QString::fromStdString(*vitr)); } prop_line = new QHBoxLayout; prop_line->addWidget(new QLabel("Cache file locally:"), 0, Qt::AlignRight); prop_line->addWidget(cacheBox, 0, Qt::AlignLeft); tie(cacheBox, "Cache", prop_line); } prop_line->addStretch(); // If the algorithm version supports the LoadLog property add a check box for // it Mantid::Kernel::Property *loadlogs = getAlgorithmProperty("LoadLogFiles"); if (loadlogs) { QCheckBox *checkbox = new QCheckBox("Load Log Files", this); prop_line->addWidget(checkbox); tie(checkbox, "LoadLogFiles", prop_line); } prop_line->addStretch(); //------------- If the algorithm version supports the LoadMonitors property // add a check box for it ---- Mantid::Kernel::Property *loadMonitors = getAlgorithmProperty("LoadMonitors"); if (loadMonitors) { QComboBox *monitorsBox = new QComboBox; std::vector<std::string> monitoritems = loadMonitors->allowedValues(); std::vector<std::string>::const_iterator mend = monitoritems.end(); for (std::vector<std::string>::const_iterator mitr = monitoritems.begin(); mitr != mend; ++mitr) { monitorsBox->addItem(QString::fromStdString(*mitr)); } prop_line->addWidget(new QLabel("LoadMonitors:"), 0, Qt::AlignRight); prop_line->addWidget(monitorsBox); tie(monitorsBox, "LoadMonitors", prop_line); } if (prop_line) main_layout->addLayout(prop_line); // Buttons main_layout->addLayout(createDefaultButtonLayout("?", "Load", "Cancel")); }