Mantid
Loading...
Searching...
No Matches
UserInputValidator.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
12#include <QLabel>
13#include <QLineEdit>
14#include <QString>
15#include <QValidator>
16
17#include <algorithm>
18#include <cmath>
19
20using namespace Mantid::API;
21using namespace MantidQt::MantidWidgets;
22
23namespace // anonymous
24{
25template <typename T> void sortPair(std::pair<T, T> &pair) {
26 if (pair.first > pair.second) {
27 T temp = pair.first;
28 pair.first = pair.second;
29 pair.second = temp;
30 }
31}
32
33bool doesExistInADS(std::string const &workspaceName) {
34 return AnalysisDataService::Instance().doesExist(workspaceName);
35}
36
37boost::optional<std::string> containsInvalidWorkspace(const WorkspaceGroup_const_sptr &group) {
38 if (group->isEmpty())
39 return "The group workspace " + group->getName() + " is empty.";
40
41 const auto it =
42 std::find_if(std::cbegin(*group), std::cend(*group), [](const auto &workspace) { return !workspace; });
43 if (it != std::cend(*group))
44 return "The group workspace " + group->getName() + " contains an invalid workspace.";
45 return boost::none;
46}
47
48} // anonymous namespace
49
51UserInputValidator::UserInputValidator() : m_errorMessages(), m_error(false) {}
52
64bool UserInputValidator::checkFieldIsNotEmpty(const QString &name, QLineEdit *field, QLabel *errorLabel) {
65 if (field->text().trimmed().isEmpty()) {
66 setErrorLabel(errorLabel, false);
67 addErrorMessage(name + " has been left blank.");
68 return false;
69 } else {
70 setErrorLabel(errorLabel, true);
71 return true;
72 }
73}
74
84bool UserInputValidator::checkFieldIsValid(const QString &errorMessage, QLineEdit *field, QLabel *errorLabel) {
85 int dummyPos = 0;
86 QString text = field->text();
87 QValidator::State fieldState = field->validator()->validate(text, dummyPos);
88
89 if (fieldState == QValidator::Acceptable) {
90 setErrorLabel(errorLabel, true);
91 return true;
92 } else {
93 setErrorLabel(errorLabel, false);
94 addErrorMessage(errorMessage);
95 return false;
96 }
97}
98
108bool UserInputValidator::checkWorkspaceSelectorIsNotEmpty(const QString &name, WorkspaceSelector *workspaceSelector) {
109 if (workspaceSelector->currentText() == "") {
110 addErrorMessage("No " + name + " workspace has been selected.");
111 return false;
112 }
113
114 return true;
115}
116
125 if (!widget->isValid()) {
126 addErrorMessage(name + " file error: " + widget->getFileProblem());
127 return false;
128 }
129
130 return true;
131}
132
141bool UserInputValidator::checkDataSelectorIsValid(const QString &name, DataSelector *widget, bool silent) {
142 if (!widget->isValid()) {
143 addErrorMessage(name + " error: " + widget->getProblem(), silent);
144 return false;
145 }
146
147 return true;
148}
149
157bool UserInputValidator::checkValidRange(const QString &name, std::pair<double, double> range) {
158 if (range.second == range.first) {
159 addErrorMessage(name + " must have a non-zero width.");
160 return false;
161 }
162
163 if (range.second < range.first) {
164 addErrorMessage("The start of " + name + " must be less than the end.");
165 return false;
166 }
167
168 return true;
169}
170
178bool UserInputValidator::checkRangesDontOverlap(std::pair<double, double> rangeA, std::pair<double, double> rangeB) {
179 sortPair(rangeA);
180 sortPair(rangeB);
181
182 if (!(rangeA.second < rangeB.first || rangeB.second < rangeA.first)) {
183 QString message = QString("The ranges must not overlap: [%1,%2], [%3,%4].")
184 .arg(rangeA.first)
185 .arg(rangeA.second)
186 .arg(rangeB.first)
187 .arg(rangeB.second);
188 addErrorMessage(message);
189 return false;
190 }
191
192 return true;
193}
194
205bool UserInputValidator::checkRangeIsEnclosed(const QString &outerName, std::pair<double, double> outer,
206 const QString &innerName, std::pair<double, double> inner) {
207 sortPair(inner);
208 sortPair(outer);
209
210 if (inner.first < outer.first || inner.second > outer.second) {
211 addErrorMessage(outerName + " must completely enclose " + innerName + ".");
212 return false;
213 }
214
215 return true;
216}
217
230bool UserInputValidator::checkBins(double lower, double binWidth, double upper, double tolerance) {
231 double range = upper - lower;
232 if (range < 0) {
233 addErrorMessage("The start of a binning range must be less than the end.");
234 return false;
235 }
236 if (range == 0) {
237 addErrorMessage("Binning ranges must be non-zero.");
238 return false;
239 }
240 if (binWidth == 0) {
241 addErrorMessage("Bin width must be non-zero.");
242 return false;
243 }
244 if (binWidth < 0) {
245 addErrorMessage("Bin width must be a positive value.");
246 return false;
247 }
248
249 while (range > tolerance)
250 range -= binWidth;
251
252 if (std::abs(range) > tolerance) {
253 addErrorMessage("Bin width must allow for even splitting of the range.");
254 return false;
255 }
256
257 return true;
258}
259
269bool UserInputValidator::checkNotEqual(const QString &name, double x, double y, double tolerance) {
270 double delta = x - y;
271
272 if (std::abs(delta) <= tolerance) {
273 std::stringstream msg;
274 msg << name.toStdString() << " (" << x << ")"
275 << " should not be equal to " << y << ".";
276 QString msgStr = QString::fromStdString(msg.str());
277 addErrorMessage(msgStr);
278 return false;
279 }
280
281 return true;
282}
283
291bool UserInputValidator::checkWorkspaceExists(QString const &workspaceName, bool silent) {
292 if (workspaceName.isEmpty())
293 return false;
294
295 if (!doesExistInADS(workspaceName.toStdString())) {
296 addErrorMessage(workspaceName + " could not be found.", silent);
297 return false;
298 }
299 return true;
300}
301
309bool UserInputValidator::checkWorkspaceNumberOfHistograms(QString const &workspaceName, std::size_t const &validSize) {
310 if (checkWorkspaceExists(workspaceName))
311 return checkWorkspaceNumberOfHistograms(getADSWorkspace(workspaceName.toStdString()), validSize);
312 return false;
313}
314
323 std::size_t const &validSize) {
324 if (workspace->getNumberHistograms() != validSize) {
325 addErrorMessage(QString::fromStdString(workspace->getName()) + " should contain " +
326 QString::fromStdString(std::to_string(validSize)) + " spectra.");
327 return false;
328 }
329 return true;
330}
331
339bool UserInputValidator::checkWorkspaceNumberOfBins(QString const &workspaceName, std::size_t const &validSize) {
340 if (checkWorkspaceExists(workspaceName))
341 return checkWorkspaceNumberOfBins(getADSWorkspace(workspaceName.toStdString()), validSize);
342 return false;
343}
344
353 std::size_t const &validSize) {
354 if (workspace->x(0).size() != validSize) {
355 addErrorMessage(QString::fromStdString(workspace->getName()) + " should contain " +
356 QString::fromStdString(std::to_string(validSize)) + " bins.");
357 return false;
358 }
359 return true;
360}
361
371bool UserInputValidator::checkWorkspaceGroupIsValid(QString const &groupName, QString const &inputType, bool silent) {
372 if (checkWorkspaceType<WorkspaceGroup>(groupName, inputType, "WorkspaceGroup", silent)) {
373 if (auto const group = getADSWorkspace<WorkspaceGroup>(groupName.toStdString())) {
374 if (auto const error = containsInvalidWorkspace(group)) {
375 addErrorMessage(QString::fromStdString(error.get()), silent);
376 return false;
377 }
378 return true;
379 }
380 }
381 return false;
382}
383
390void UserInputValidator::addErrorMessage(const QString &message, bool silent) {
391 if (!silent && !m_errorMessages.contains(message))
392 m_errorMessages.append(message);
393 m_error = true;
394}
395
402 if (m_errorMessages.isEmpty())
403 return "";
404
405 return "Please correct the following:\n" + m_errorMessages.join("\n");
406}
407
414
421void UserInputValidator::setErrorLabel(QLabel *errorLabel, bool valid) {
422 // Do nothing if no error label was provided
423 if (errorLabel == nullptr)
424 return;
425
426 if (!valid) {
427 // Set the label to be red
428 QPalette palette = errorLabel->palette();
429 palette.setColor(errorLabel->foregroundRole(), Qt::red);
430 errorLabel->setPalette(palette);
431
432 errorLabel->setText("*");
433 } else {
434 errorLabel->setText("");
435 }
436
437 // Only show the label if input is invalid
438 errorLabel->setVisible(!valid);
439}
440} // namespace MantidQt::CustomInterfaces
double error
Definition: IndexPeaks.cpp:133
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
double tolerance
double lower
lower and upper bounds on the multiplier, if known
double upper
This class defines a widget for file searching.
QString getFileProblem()
Get file problem, empty string means no error.
bool isValid() const
Is the input within the widget valid?
bool m_error
True if there has been an error.
bool checkFileFinderWidgetIsValid(const QString &name, FileFinderWidget *widget)
Check that the given FileFinderWidget widget has valid files.
bool checkBins(double lower, double binWidth, double upper, double tolerance=0.00000001)
Check that the given range can be split evenly into bins of the given width.
bool checkWorkspaceExists(QString const &workspaceName, bool silent=false)
Checks that a workspace exists in the ADS.
std::shared_ptr< T > getADSWorkspace(std::string const &workspaceName)
Gets a workspace from the ADS.
QString generateErrorMessage()
Returns an error message which contains all the error messages raised by the check functions.
bool checkWorkspaceGroupIsValid(QString const &groupName, QString const &inputType, bool silent=false)
Checks that a workspace group contains valid matrix workspace's.
bool checkFieldIsNotEmpty(const QString &name, QLineEdit *field, QLabel *errorLabel=nullptr)
Check that the given QLineEdit field is not empty.
bool checkRangesDontOverlap(std::pair< double, double > rangeA, std::pair< double, double > rangeB)
Check that the given ranges dont overlap.
bool checkDataSelectorIsValid(const QString &name, DataSelector *widget, bool silent=false)
Check that the given DataSelector widget has valid input.
void addErrorMessage(const QString &message, bool silent=false)
Add a custom error message to the list.
bool isAllInputValid()
Checks to see if all input is valid.
bool checkNotEqual(const QString &name, double x, double y=0.0, double tolerance=0.00000001)
Checks two values are not equal.
bool checkWorkspaceNumberOfHistograms(QString const &workspaceName, std::size_t const &validSize)
Checks the number of histograms in a workspace.
QStringList m_errorMessages
Any raised error messages.
bool checkWorkspaceSelectorIsNotEmpty(const QString &name, WorkspaceSelector *workspaceSelector)
Check that the given WorkspaceSelector is not empty.
bool checkWorkspaceNumberOfBins(QString const &workspaceName, std::size_t const &validSize)
Checks the number of bins in a workspace.
void setErrorLabel(QLabel *errorLabel, bool valid)
Sets a validation label.
bool checkFieldIsValid(const QString &errorMessage, QLineEdit *field, QLabel *errorLabel=nullptr)
Check that the given QLineEdit field is valid as per any validators it might have.
bool checkRangeIsEnclosed(const QString &outerName, std::pair< double, double > outer, const QString &innerName, std::pair< double, double > inner)
Check that the given "outer" range completely encloses the given "inner" range.
bool checkValidRange(const QString &name, std::pair< double, double > range)
Check that the given start and end range is valid.
This class defines a widget for selecting a workspace of file path by using a combination of two chil...
Definition: DataSelector.h:35
virtual bool isValid()
Checks if widget is in a valid state.
QString getProblem() const
Get file problem, empty string means no error.
This class defines a widget for selecting a workspace present in the AnalysisDataService.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< const WorkspaceGroup > WorkspaceGroup_const_sptr
shared pointer to Mantid::API::WorkspaceGroup, pointer to const version
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::string to_string(const wide_integer< Bits, Signed > &n)