Mantid
Loading...
Searching...
No Matches
DataSelector.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 +
12#include "MantidAPI/Workspace.h"
15
16#include <QFileInfo>
17
18#include <QDebug>
19#include <QDropEvent>
20#include <QMimeData>
21#include <QUrl>
22
23using namespace Mantid::API;
24
25namespace {
26auto &ads = AnalysisDataService::Instance();
27
28std::string cutLastOf(const std::string &str, const std::string &delimiter) {
29 const auto cutIndex = str.rfind(delimiter);
30 if (cutIndex != std::string::npos)
31 return str.substr(0, cutIndex);
32 return str;
33}
34
35std::string extractLastOf(const std::string &str, const std::string &delimiter) {
36 const auto cutIndex = str.rfind(delimiter);
37 if (cutIndex != std::string::npos)
38 return str.substr(cutIndex + 1, str.size() - cutIndex);
39 return str;
40}
41
42bool fileFound(std::string const &file) { return !FileFinder::Instance().getFullPath(file).empty(); }
43
44std::string loadAlgName(const std::string &filePath) {
45 const auto suffix = extractLastOf(filePath, ".");
46 return suffix == "dave" ? "LoadDaveGrp" : "Load";
47}
48
49void makeGroup(std::string const &workspaceName) {
50 if (!ads.retrieveWS<WorkspaceGroup>(workspaceName)) {
51 const auto groupAlg = AlgorithmManager::Instance().createUnmanaged("GroupWorkspaces");
52 groupAlg->initialize();
53 groupAlg->setProperty("InputWorkspaces", workspaceName);
54 groupAlg->setProperty("OutputWorkspace", workspaceName);
55 groupAlg->execute();
56 }
57}
58
59} // namespace
60
62
64 : API::MantidWidget(parent), m_loadProperties(), m_algRunner(), m_showLoad(true), m_alwaysLoadAsGroup(false) {
65 m_uiForm.setupUi(this);
66 connect(m_uiForm.cbInputType, SIGNAL(currentIndexChanged(int)), this, SLOT(handleViewChanged(int)));
67 connect(m_uiForm.pbLoadFile, SIGNAL(clicked()), this, SIGNAL(loadClicked()));
68
69 // data selected changes
70 connect(m_uiForm.rfFileInput, SIGNAL(filesFoundChanged()), this, SLOT(handleFileInput()));
71 connect(m_uiForm.wsWorkspaceInput, SIGNAL(currentIndexChanged(int)), this, SLOT(handleWorkspaceInput()));
72 connect(m_uiForm.pbLoadFile, SIGNAL(clicked()), this, SLOT(handleFileInput()));
73
74 connect(&m_algRunner, SIGNAL(algorithmComplete(bool)), this, SLOT(handleAutoLoadComplete(bool)));
75 this->setAcceptDrops(true);
76 m_uiForm.rfFileInput->setAcceptDrops(false);
77}
78
80
85bool DataSelector::isOptional() const { return m_isOptional; }
86
91void DataSelector::isOptional(bool optional) {
93 m_uiForm.rfFileInput->isOptional(optional);
94 m_uiForm.wsWorkspaceInput->setOptional(optional);
95}
96
101 // Get filename and check it's not empty
102 QString filename = m_uiForm.rfFileInput->getUserInput().toString();
103
104 if (filename.isEmpty()) {
105 return;
106 }
107
108 if (autoLoadFile(filename)) {
109 emit filesAutoLoaded();
110 }
111}
112
116void DataSelector::setSelectorIndex(int index) { m_uiForm.cbInputType->setCurrentIndex(index); }
117
121void DataSelector::setTypeSelectorVisible(bool visible) { m_uiForm.cbInputType->setVisible(visible); }
122
129 int index = m_uiForm.stackedDataSelect->currentIndex();
130 return (index == 0);
131}
132
139
148bool DataSelector::isValid(bool const autoLoad) {
149 bool isValid = false;
150
151 if (isFileSelectorVisible()) {
152 isValid = m_uiForm.rfFileInput->isValid();
153
154 // check to make sure the user hasn't deleted the auto-loaded file
155 // since choosing it.
156 if (isValid && autoLoad) {
157 auto const wsName = getCurrentDataName().toStdString();
158
159 isValid = !wsName.empty();
160 if (isValid && !ads.doesExist(wsName)) {
161 // attempt to reload if we can
162 // don't use algorithm runner because we need to know instantly.
163 auto const filepath = m_uiForm.rfFileInput->getUserInput().toString().toStdString();
164 if (!filepath.empty())
165 executeLoadAlgorithm(filepath, wsName);
166
167 isValid = ads.doesExist(wsName);
168
169 if (!isValid) {
170 m_uiForm.rfFileInput->setFileProblem("The specified workspace is "
171 "missing from the analysis data "
172 "service");
173 }
174 } else {
175 if (!ads.doesExist(wsName)) {
176 return isValid;
177 }
178 auto const workspaceTypes = m_uiForm.wsWorkspaceInput->getWorkspaceTypes();
179 auto const workspace = ads.retrieveWS<Workspace>(wsName);
180 isValid = workspaceTypes.empty() || workspaceTypes.indexOf(QString::fromStdString(workspace->id())) != -1;
181 if (!isValid) {
182 m_uiForm.rfFileInput->setFileProblem("The specified workspace type (" +
183 QString::fromStdString(workspace->id()) +
184 ") is "
185 "not one of the allowed types: " +
186 workspaceTypes.join(", "));
187 }
188 }
189 }
190 } else {
191 isValid = m_uiForm.wsWorkspaceInput->isValid();
192 }
193
194 return isValid;
195}
196
202 QString problem = "";
203 if (isFileSelectorVisible()) {
204 problem = m_uiForm.rfFileInput->getFileProblem();
205 if (problem.compare("") == 0) {
206 problem = "Input field is empty";
207 }
208 } else {
209 problem = "A valid workspace has not been selected";
210 }
211
212 return problem;
213}
214
224bool DataSelector::autoLoadFile(const QString &filepath) {
225 const auto baseName = getWsNameFromFiles().toStdString();
226 return executeLoadAlgorithm(filepath.toStdString(), baseName);
227}
228
236bool DataSelector::executeLoadAlgorithm(std::string const &filename, std::string const &outputWorkspace) {
237 const auto loadAlg = AlgorithmManager::Instance().createUnmanaged(loadAlgName(filename));
238 loadAlg->initialize();
239 try {
240 loadAlg->setProperty("Filename", filename);
241 loadAlg->setProperty("OutputWorkspace", outputWorkspace);
242 } catch (std::exception const &ex) {
243 m_uiForm.rfFileInput->setFileProblem(ex.what());
244 return false;
245 }
246 loadAlg->updatePropertyValues(m_loadProperties);
247
249 return true;
250}
251
258void DataSelector::setLoadProperty(std::string const &propertyName, bool const value) {
260}
261
268void DataSelector::setLoadProperty(std::string const &propertyName, std::string const &value) {
270}
271
278 m_uiForm.rfFileInput->setFileProblem(error ? "Could not load file. See log for details." : "");
279
280 if (error) {
281 return;
282 }
284 makeGroup(getWsNameFromFiles().toStdString());
285 }
287}
288
293 if (m_uiForm.stackedDataSelect->currentIndex() > 0) {
294 // Get text of name of workspace to use
295 QString filename = m_uiForm.wsWorkspaceInput->currentText();
296 if (filename.isEmpty())
297 return;
298
299 // emit that we got a valid workspace/file to work with
300 emit dataReady(filename);
301 }
302}
303
310 // Index indicates which view is visible.
311 m_uiForm.stackedDataSelect->setCurrentIndex(index);
312
313 // 0 is always file view
314 switch (index) {
315 case 0:
316 emit fileViewVisible();
317 break;
318 case 1:
321 break;
322 }
323}
324
330QString DataSelector::getFullFilePath() const { return m_uiForm.rfFileInput->getUserInput().toString(); }
331
338 QString filepath = DataSelector::getFullFilePath();
339 QFileInfo qfio(filepath);
340 QString baseName = qfio.completeBaseName();
341
342 // make up a name for the group workspace, if multiple files are specified
343 if (m_uiForm.rfFileInput->allowMultipleFiles() && filepath.count(",") > 0) {
344 baseName += "_group";
345 }
346
347 return baseName;
348}
349
362QString DataSelector::getCurrentDataName(bool const autoLoad) const {
363 QString filename("");
364
365 int index = m_uiForm.stackedDataSelect->currentIndex();
366
367 switch (index) {
368 case 0:
369 // the file selector is visible
370 if (m_uiForm.rfFileInput->isValid()) {
371 if (m_uiForm.rfFileInput->allowMultipleFiles() && !autoLoad) {
372 // if multiple files are allowed, auto-loading is not on, return the
373 // full user input
374 filename = getFullFilePath();
375 } else {
376 filename = getWsNameFromFiles();
377 }
378 }
379 break;
380 case 1:
381 // the workspace selector is visible
382 filename = m_uiForm.wsWorkspaceInput->currentText();
383 break;
384 }
385
386 return filename;
387}
388
394QString DataSelector::getLoadBtnText() const { return m_uiForm.pbLoadFile->text(); }
395
401void DataSelector::setLoadBtnText(const QString &text) { m_uiForm.pbLoadFile->setText(text); }
402
409void DataSelector::setAlwaysLoadAsGroup(bool const loadAsGroup) { m_alwaysLoadAsGroup = loadAsGroup; }
410
413}
414
416 m_uiForm.rfFileInput->restoreSettings(settings);
417}
418
419API::FileFinderSettings DataSelector::captureSettings() const { return m_uiForm.rfFileInput->captureSettings(); }
420
421void DataSelector::saveSettings(QSettings &settings, const API::FileFinderSettings &values) const {
422 m_uiForm.rfFileInput->saveSettings(settings, values);
423}
424
431
439 m_uiForm.pbLoadFile->setEnabled(load);
440 m_uiForm.pbLoadFile->setVisible(load);
441 m_showLoad = load;
442}
443
448void DataSelector::dropEvent(QDropEvent *de) {
449 const QMimeData *mimeData = de->mimeData();
450 auto before_action = de->dropAction();
451
452 auto const dragData = mimeData->text().toStdString();
453
454 if (de->mimeData() && ads.doesExist(dragData)) {
455 m_uiForm.wsWorkspaceInput->dropEvent(de);
456 if (de->dropAction() == before_action) {
457 setWorkspaceSelectorIndex(mimeData->text());
458 m_uiForm.cbInputType->setCurrentIndex(1);
459 return;
460 }
461 de->setDropAction(before_action);
462 }
463
464 m_uiForm.rfFileInput->dropEvent(de);
465 if (de->dropAction() == before_action) {
466 m_uiForm.cbInputType->setCurrentIndex(0);
467 }
468
469 auto const filepath = m_uiForm.rfFileInput->getText().toStdString();
470 if (de->mimeData() && !ads.doesExist(dragData) && !filepath.empty()) {
471 auto const file = extractLastOf(filepath, "/");
472 if (fileFound(file)) {
473 auto const workspaceName = cutLastOf(file, ".");
474 executeLoadAlgorithm(filepath, workspaceName);
475
476 setWorkspaceSelectorIndex(QString::fromStdString(workspaceName));
477 m_uiForm.cbInputType->setCurrentIndex(1);
478 }
479 }
480}
481
487void DataSelector::setWorkspaceSelectorIndex(QString const &workspaceName) {
488 auto const index = m_uiForm.wsWorkspaceInput->findText(workspaceName);
489 m_uiForm.wsWorkspaceInput->setCurrentIndex(index != -1 ? index : 0);
490}
491
496void DataSelector::dragEnterEvent(QDragEnterEvent *de) {
497 const QMimeData *mimeData = de->mimeData();
498 if (mimeData->hasText() || mimeData->hasUrls())
499 de->acceptProposedAction();
500}
501
502} // namespace MantidQt::MantidWidgets
double value
The value of the point.
Definition FitMW.cpp:51
double error
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
Immutable snapshot of the persistent state used by FileFinderWidget.
static FileFinderSettings readSettings(const QSettings &settings)
Query last_directory from const storage without changing this widget or writing settings.
virtual void startAlgorithm(Mantid::API::IAlgorithm_sptr alg)
Begin asynchronous execution of an algorithm and observe its execution.
Mantid::API::AlgorithmRuntimeProps m_loadProperties
Extra load properties to set on the load algorithm before execution.
bool isWorkspaceSelectorVisible() const
Get whether the workspace selector is currently being shown.
bool executeLoadAlgorithm(std::string const &filename, std::string const &outputWorkspace)
Execute load algorithm.
void setLoadProperty(std::string const &propertyName, bool const value)
Set an extra property on the load algorithm before execution.
virtual bool isValid(bool const autoLoad=true)
Checks if widget is in a valid state.
void setShowLoad(bool load)
Set if the load button should be shown.
void setTypeSelectorVisible(bool visible)
Sets if the option to choose selector is visible.
bool m_alwaysLoadAsGroup
Flag to always load data, placing it inside a WorkspaceGroup, even if there is 1 entry.
Ui::DataSelector m_uiForm
Member containing the widgets child widgets.
void handleViewChanged(int index)
Slot called when the current view is changed.
void dropEvent(QDropEvent *) override
Called when an item is dropped.
void saveSettings(QSettings &settings, const API::FileFinderSettings &values) const
Persist the supplied snapshot to mutable storage positioned at the target group.
void setWorkspaceSelectorIndex(QString const &workspaceName)
Set the index of the combobox containing the loaded workspace.
void fileViewVisible()
Signal emitted when file input is visible.
bool isFileSelectorVisible() const
Get whether the file selector is currently being shown.
void setLoadBtnText(const QString &)
Sets the load button text.
API::FileFinderSettings captureSettings() const
Capture the current state of the child file finder without persistent I/O.
void filesAutoLoaded()
Signal emitted when files are found and autoloaded.
QString getWsNameFromFiles() const
Get the workspace name from the list of files.
virtual QString getCurrentDataName(bool const autoLoad=true) const
Get the currently available file or workspace name.
QString getFullFilePath() const
Get the current file path in the FileFinderWidget widget.
void dragEnterEvent(QDragEnterEvent *) override
Called when an item is dragged onto a control.
void setAlwaysLoadAsGroup(bool const loadAsGroup)
Sets the DataSelector to always load data inside a WorkspaceGroup.
bool willShowLoad()
Check if the widget will show the load button.
static API::FileFinderSettings readSettings(const QSettings &settings)
Query file-finder settings from const storage without changing this widget or writing settings.
bool m_showLoad
Flag to show or hide the load button. By default this is set to true.
void handleAutoLoadComplete(bool error)
Slot called if the widget fails to auto load the file.
QString getProblem() const
Get file problem, empty string means no error.
bool autoLoadFile(const QString &filenames)
Attempt to automatically load a file.
bool isOptional() const
Gets if optional.
DataSelector(QWidget *parent=nullptr)
MantidQt::API::QtAlgorithmRunner m_algRunner
Algorithm Runner used to run the load algorithm.
void handleWorkspaceInput()
Slot called when workspace input is available.
void restoreSettings(const API::FileFinderSettings &settings)
Restore the child file finder from an in-memory snapshot without persistent I/O.
void dataReady(const QString &wsname)
Signal emitted when data is ready from a workspace selector or file browser.
QString getLoadBtnText() const
Gets the load button text.
void setSelectorIndex(int index)
Sets which selector (file or workspace) is visible.
void loadClicked()
Signal emitted when the load button is clicked.
void workspaceViewVisible()
Signal emitted when workspace selector is visible.
void handleFileInput()
Slot called when file input is available.
Class to hold a set of workspaces.
Base Workspace Abstract Class.
Definition Workspace.h:30
void MANTID_API_DLL update(std::string const &property, std::string const &value, IAlgorithmRuntimeProps &properties)