42#include <QSignalMapper>
58 : QWidget(parent), m_mantidDisplayModel(mdb), m_viewOnly(viewOnly), m_updateCount(0), m_treeUpdating(false),
60 m_sortDirection(
SortDirection::Ascending), m_mutex(QMutex::Recursive) {
61 setObjectName(
"exploreMantid");
74 static bool registered_addtional_types =
false;
75 if (!registered_addtional_types) {
76 registered_addtional_types =
true;
77 qRegisterMetaType<TopLevelItems>();
86 m_tree->setDragEnabled(
true);
88 auto presenter = std::make_shared<WorkspacePresenter>(
this);
89 m_presenter = std::dynamic_pointer_cast<ViewNotifiable>(presenter);
106 m_tree->setHeaderLabel(
"Workspaces");
112 m_saveButton->setToolTip(
"Save the selected workspaces");
118 m_groupButton->setToolTip(
"Group together two or more selected workspaces");
120 m_sortButton->setToolTip(
"Sort all workspaces by name, size, or the last time they were modified");
138 auto *layout =
new QVBoxLayout();
139 layout->setMargin(0);
140 layout->addLayout(buttonLayout);
142 layout->addWidget(
m_tree);
143 this->setLayout(layout);
149 QAction *loadFileAction =
new QAction(
"File",
this);
150 QAction *liveDataAction =
new QAction(
"Live Data",
this);
151 connect(loadFileAction, SIGNAL(triggered()),
this, SLOT(
onClickLoad()));
152 connect(liveDataAction, SIGNAL(triggered()),
this, SLOT(
onClickLiveData()));
163 connect(
m_tree, SIGNAL(itemClicked(QTreeWidgetItem *,
int)),
this, SLOT(
clickedWorkspace(QTreeWidgetItem *,
int)));
167 m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
168 connect(
m_tree, SIGNAL(customContextMenuRequested(
const QPoint &)),
this, SLOT(
popupMenu(
const QPoint &)));
170 Qt::QueuedConnection);
188 return std::dynamic_pointer_cast<WorkspacePresenter>(
m_presenter);
195 auto items =
m_tree->selectedItems();
197 names.reserve(
static_cast<size_t>(items.size()));
198 std::transform(items.cbegin(), items.cend(), std::back_inserter(names),
199 [](
auto const &item) { return item->text(0).toStdString(); });
205 auto items =
m_tree->selectedItems();
208 for (
auto &item : items) {
209 names.append(item->text(0));
218 auto items =
m_tree->selectedItems();
219 auto data = items[0]->data(0, Qt::UserRole).value<
Workspace_sptr>();
225 return QMessageBox::question(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message),
226 QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes;
230 QMessageBox::critical(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message));
234 QObject *sender = QObject::sender();
239 QString fn = MantidQt::API::AlgorithmInputHistory::Instance().previousInput(
"Load",
"Filename");
245 QMetaObject::invokeMethod(
dynamic_cast<QObject *
>(
m_mantidDisplayModel),
"showAlgorithmDialog", Qt::QueuedConnection,
246 Q_ARG(QString,
"Load"));
250 QMetaObject::invokeMethod(
dynamic_cast<QObject *
>(
m_mantidDisplayModel),
"showAlgorithmDialog", Qt::QueuedConnection,
251 Q_ARG(QString,
"StartLiveData"));
259 for (
const auto &ws : wsNames)
260 names.append(QString::fromStdString(ws));
273 QString qs_oldName = QString::fromStdString(oldName);
274 QString qs_newName = QString::fromStdString(newName);
276 QMutexLocker renameMapLock(&
m_mutex);
280 if (!oldNames.isEmpty()) {
281 for (
const auto &
name : oldNames)
296 return askUserYesNo(
"Delete Workspaces",
"Are you sure you want to delete the selected Workspaces?\n\nThis prompt "
297 "can be disabled from:\nFile->Settings->General");
302 for (
const auto &ws : wsNames)
303 names.append(QString::fromStdString(ws));
335 static int counter = 1;
374 const QAction *sendingAction =
dynamic_cast<QAction *
>(sender());
378 QString actionName = sendingAction->text();
380 if (actionName.compare(
"Nexus") == 0)
382 else if (actionName.compare(
"ASCII") == 0)
387 if (selectedNames.size() > 1) {
390 }
else if (selectedNames.size() == 1) {
400 if (!wsName.empty()) {
401 presets[
"InputWorkspace"] = QString::fromStdString(wsName);
404 std::string algorithmName;
408 algorithmName =
"SaveNexus";
411 algorithmName =
"SaveAscii";
420 if (items.size() < 2)
427 if (res != QFileDialog::Accepted)
432 std::string algorithmName;
433 std::string fileExtension;
437 algorithmName =
"SaveAscii";
438 fileExtension =
".dat";
442 algorithmName =
"SaveNexus";
443 fileExtension =
".nxs";
447 IAlgorithm_sptr saveAlg = AlgorithmManager::Instance().create(algorithmName);
448 saveAlg->initialize();
450 for (
auto &wsName : wsNames) {
451 std::string filename = folder +
"/" + wsName + fileExtension;
453 saveAlg->setProperty(
"InputWorkspace", wsName);
454 saveAlg->setProperty(
"Filename", filename);
456 }
catch (std::exception &ex) {
457 docklog.error() <<
"Error saving workspace " << wsName <<
": " << ex.what() <<
'\n';
465 const QString text = QString::fromStdString(filterText).trimmed();
466 QRegExp filterRegEx(text, Qt::CaseInsensitive);
469 QTreeWidgetItemIterator unhideIter(
m_tree);
470 while (*unhideIter) {
471 (*unhideIter)->setHidden(
false);
476 if (!text.isEmpty()) {
480 QStringList expanded;
481 int n =
m_tree->topLevelItemCount();
482 for (
int i = 0; i <
n; ++i) {
483 auto item =
m_tree->topLevelItem(i);
484 if (item->isExpanded()) {
485 expanded << item->text(0);
489 item->setExpanded(
true);
494 QTreeWidgetItemIterator it(
m_tree, QTreeWidgetItemIterator::All);
496 QTreeWidgetItem *item = (*it);
497 QVariant userData = item->data(0, Qt::UserRole);
499 if (!userData.isNull()) {
503 if (item->text(0).contains(filterRegEx)) {
509 visibleGroups.append(item);
510 item->setHidden(
false);
513 if (item->parent() ==
nullptr) {
515 item->setHidden(
false);
519 item->setHidden(
false);
520 if (item->parent()->isHidden()) {
523 item->parent()->setHidden(
false);
524 expanded << item->parent()->text(0);
529 item->setHidden(
true);
538 for (
auto group : visibleGroups) {
539 for (
int i = 0; i <
group->childCount(); i++) {
540 QTreeWidgetItem *child =
group->child(i);
541 if (child->isHidden()) {
544 child->setHidden(
false);
550 for (
int i = 0; i <
n; ++i) {
551 auto item =
m_tree->topLevelItem(i);
552 item->setExpanded(expanded.contains(item->text(0)));
557 if (hiddenCount > 0) {
558 QString headerString = QString(
"Workspaces (%1 filtered)").arg(QString::number(hiddenCount));
559 m_tree->headerItem()->setText(0, headerString);
561 m_tree->headerItem()->setText(0,
"Workspaces");
572 item->setIcon(0, QIcon(WORKSPACE_ICONS.getIcon(wsID)));
573 }
catch (std::runtime_error &) {
574 docklog.warning() <<
"Cannot find icon for workspace ID '" << wsID <<
"'\n";
582 m_showData =
new QAction(tr(
"Show Data"),
this);
585 m_showInst =
new QAction(tr(
"Show Instrument"),
this);
588 m_plotSpec =
new QAction(tr(
"Plot Spectrum..."),
this);
591 m_plotSpecErr =
new QAction(tr(
"Plot Spectrum with Errors..."),
this);
597 m_colorFill =
new QAction(tr(
"Color Fill Plot"),
this);
603 m_showBoxData =
new QAction(tr(
"Show Box Data Table"),
this);
618 icon.addFile(QString::fromUtf8(
":/SliceViewer/icons/SliceViewerWindow_icon.png"), QSize(), QIcon::Normal,
624 m_showLogs =
new QAction(tr(
"Sample Logs..."),
this);
630 m_showHist =
new QAction(tr(
"Show History"),
this);
636 m_rename =
new QAction(tr(
"Rename"),
this);
639 m_delete =
new QAction(tr(
"Delete"),
this);
653 m_clearUB =
new QAction(tr(
"Clear UB Matrix"),
this);
662 QMenu *sortMenu =
new QMenu(
this);
664 QAction *ascendingSortAction =
new QAction(
"Ascending",
this);
665 QAction *descendingSortAction =
new QAction(
"Descending",
this);
666 QAction *byNameChoice =
new QAction(
"Name",
this);
667 QAction *byLastModifiedChoice =
new QAction(
"Last Modified",
this);
668 QAction *byMemorySize =
new QAction(
"Size",
this);
670 ascendingSortAction->setCheckable(
true);
671 ascendingSortAction->setEnabled(
true);
673 descendingSortAction->setCheckable(
true);
674 descendingSortAction->setEnabled(
true);
676 QActionGroup *sortDirectionGroup =
new QActionGroup(sortMenu);
677 sortDirectionGroup->addAction(ascendingSortAction);
678 sortDirectionGroup->addAction(descendingSortAction);
679 sortDirectionGroup->setExclusive(
true);
680 ascendingSortAction->setChecked(
true);
682 byNameChoice->setCheckable(
true);
683 byNameChoice->setEnabled(
true);
685 byLastModifiedChoice->setCheckable(
true);
686 byLastModifiedChoice->setEnabled(
true);
688 byMemorySize->setCheckable(
true);
689 byMemorySize->setEnabled(
true);
691 QActionGroup *sortChoiceGroup =
new QActionGroup(sortMenu);
692 sortChoiceGroup->addAction(byNameChoice);
693 sortChoiceGroup->addAction(byLastModifiedChoice);
694 sortChoiceGroup->addAction(byMemorySize);
695 sortChoiceGroup->setExclusive(
true);
696 byNameChoice->setChecked(
true);
698 connect(ascendingSortAction, SIGNAL(triggered()),
this, SLOT(
sortAscending()));
699 connect(descendingSortAction, SIGNAL(triggered()),
this, SLOT(
sortDescending()));
700 connect(byNameChoice, SIGNAL(triggered()),
this, SLOT(
chooseByName()));
704 sortMenu->addActions(sortDirectionGroup->actions());
705 sortMenu->addSeparator();
706 sortMenu->addActions(sortChoiceGroup->actions());
715 QVariant userData = item->data(0, Qt::UserRole);
716 if (userData.isNull())
720 while (item->childCount() > 0) {
721 auto *widgetItem = item->takeChild(0);
727 if (
auto group = std::dynamic_pointer_cast<WorkspaceGroup>(
workspace)) {
728 auto members =
group->getAllItems();
729 auto visibleNames = AnalysisDataService::Instance().getObjectNames();
730 for (
const auto &ws : members) {
731 if (std::find(visibleNames.begin(), visibleNames.end(), ws->getName()) != visibleNames.end()) {
732 auto *node =
addTreeEntry(std::make_pair(ws->getName(), ws), item);
735 node->setSelected(
true);
742 }
catch (std::runtime_error &e) {
743 details = QString(
"Error: %1").arg(e.what());
745 QStringList rows = details.split(QLatin1Char(
'\n'), Qt::SkipEmptyParts);
746 rows.append(QString(
"Memory used: ") +
workspace->getMemorySizeAsStr().c_str());
748 auto iend = rows.constEnd();
749 for (
auto itr = rows.constBegin(); itr != iend; ++itr) {
751 data->setFlags(Qt::NoItemFlags);
753 item->addChild(data);
779 foreach (QTreeWidgetItem *item, selected) {
785 auto iend = topLevelItems.end();
786 for (
auto it = topLevelItems.begin(); it != iend; ++it) {
788 QString
name = node->text(0);
789 if (expanded.contains(
name))
790 node->setExpanded(
true);
793 node->setSelected(
true);
811 QTreeWidgetItem *parent) {
813 node->setData(0, Qt::UserRole, QVariant::fromValue(item.second));
817 const std::string wsID = item.second->id();
819 idNode->setFlags(Qt::NoItemFlags);
820 node->addChild(idNode);
824 parent->addChild(node);
826 m_tree->addTopLevelItem(node);
838 if (!renamed.isEmpty()) {
839 return std::any_of(renamed.cbegin(), renamed.cend(),
840 [&](
const auto &oldName) { return m_selectedNames.contains(oldName); });
849 auto items =
m_tree->selectedItems();
852 if (items.size() == 1) {
854 auto wsSptr = items.first()->data(0, Qt::UserRole).value<
Workspace_sptr>();
855 auto grpSptr = std::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
863 }
else if (items.size() >= 2) {
866 m_groupButton->setToolTip(
"Group together two or more selected workspaces");
867 }
else if (items.size() == 0) {
870 m_groupButton->setToolTip(
"Group together two or more selected workspaces");
880 if (items.size() > 0) {
881 auto item = *(items.begin());
900 m_showInst->setEnabled(matrixWS->getInstrument() && !matrixWS->getInstrument()->getName().empty() &&
901 matrixWS->getAxis(1)->isSpectra());
902 menu->addSeparator();
908 bool multipleBins =
false;
910 multipleBins = (matrixWS->blocksize() > 1);
912 const size_t numHist = matrixWS->getNumberHistograms();
913 for (
size_t i = 0; i < numHist; ++i) {
914 if (matrixWS->y(i).size() > 1) {
928 m_colorFill->setEnabled((matrixWS->axes() > 1 && matrixWS->getNumberHistograms() > 1));
930 menu->addSeparator();
973 menu->addSeparator();
992 menu->addSeparator();
1014 QMenu *clearMenu =
new QMenu(tr(
"Clear Options"),
this);
1019 menu->addMenu(clearMenu);
1024 Workspace_sptr ws = AnalysisDataService::Instance().retrieve(wsName);
1027 hasUB = wsIMD->hasOrientedLattice();
1041 if (menuEntryName.isEmpty())
1042 menuEntryName = algorithmString;
1045 QAction *saveAction =
new QAction(menuEntryName,
this);
1046 saveAction->setData(QVariant(algorithmString));
1074 return askUserYesNo(
"Clear Workspaces",
"This will delete all the workspaces, are you sure?");
1092 if (selectedNames.empty())
1108 if (qButtonName ==
"Group") {
1110 }
else if (qButtonName ==
"Ungroup") {
1133 QStringList expanded;
1134 int n =
m_tree->topLevelItemCount();
1135 for (
int i = 0; i <
n; ++i) {
1136 auto item =
m_tree->topLevelItem(i);
1137 if (item->isExpanded()) {
1138 expanded << item->text(0);
1175 m_tree->selectionModel()->clear();
1177 QMenu *menu(
nullptr);
1184 menu =
new QMenu(
this);
1185 menu->setObjectName(
"WorkspaceContextMenu");
1190 if (
auto matrixWS = std::dynamic_pointer_cast<const Mantid::API::MatrixWorkspace>(ws)) {
1192 }
else if (
auto mdeventWS = std::dynamic_pointer_cast<const IMDEventWorkspace>(ws)) {
1194 }
else if (
auto mdWS = std::dynamic_pointer_cast<const IMDWorkspace>(ws)) {
1196 }
else if (
auto peaksWS = std::dynamic_pointer_cast<const IPeaksWorkspace>(ws)) {
1198 }
else if (
auto groupWS = std::dynamic_pointer_cast<const WorkspaceGroup>(ws)) {
1200 }
else if (std::dynamic_pointer_cast<const Mantid::API::ITableWorkspace>(ws)) {
1209 std::vector<std::string> programNames =
1210 (Mantid::Kernel::ConfigService::Instance().getKeys(
"workspace.sendto.name"));
1211 bool firstPass(
true);
1213 for (
const auto &programName : programNames) {
1214 std::string visible =
1215 Mantid::Kernel::ConfigService::Instance().getString(
"workspace.sendto." + programName +
".visible");
1216 std::string target =
1217 Mantid::Kernel::ConfigService::Instance().getString(
"workspace.sendto." + programName +
".target");
1218 if (Mantid::Kernel::ConfigService::Instance().isExecutable(target) && visible ==
"Yes") {
1219 bool compatible(
true);
1220 std::string saveUsing(
1221 Mantid::Kernel::ConfigService::Instance().getString(
"workspace.sendto." + programName +
".saveusing"));
1224 alg->setPropertyValue(
"InputWorkspace",
selectedWsName.toStdString());
1225 }
catch (std::exception &) {
1236 QString
name = QString::fromStdString(programName);
1259 menu->addSeparator();
1264 menu->popup(QCursor::pos());
1287 std::map<std::string, std::string> programKeysAndDetails;
1288 programKeysAndDetails[
"name"] =
m_programName.toStdString();
1292 std::vector<std::string> programKeys = (Mantid::Kernel::ConfigService::Instance().getKeys(
1293 (
"workspace.sendto." + programKeysAndDetails.find(
"name")->second)));
1295 for (
const auto &programKey : programKeys) {
1297 programKeysAndDetails[programKey] = (Mantid::Kernel::ConfigService::Instance().getString(
1298 (
"workspace.sendto." + programKeysAndDetails.find(
"name")->second +
"." + programKey)));
1302 if ((programKeysAndDetails.count(
"name") != 0) && (programKeysAndDetails.count(
"target") != 0) &&
1303 (programKeysAndDetails.count(
"saveusing") != 0)) {
1304 std::string expTarget = Poco::Path::expand(programKeysAndDetails.find(
"target")->second);
1306 QFileInfo target = QString::fromStdString(expTarget);
1307 if (target.exists()) {
1310 QString saveUsing = QString::fromStdString(programKeysAndDetails.find(
"saveusing")->second);
1316 Property *prop = alg->getProperty(
"Filename");
1324 alg->setPropertyValue(
"fileName",
"auto_save_" +
selectedWsName.toStdString() + ext);
1327 alg->setPropertyValue(
"InputWorkspace",
selectedWsName.toStdString());
1330 if (programKeysAndDetails.count(
"saveparameters") != 0) {
1331 QString saveParametersGrouped = QString::fromStdString(programKeysAndDetails.find(
"saveparameters")->second);
1332 QStringList saveParameters = saveParametersGrouped.split(
',');
1335 for (
int i = 0; i < saveParameters.size(); i++) {
1336 QStringList sPNameAndDetail = saveParameters[i].split(
'=');
1337 std::string saveParameterName = sPNameAndDetail[0].trimmed().toStdString();
1338 std::string saveParameterDetail = sPNameAndDetail[1].trimmed().toStdString();
1339 if (saveParameterDetail ==
"True")
1340 alg->setProperty(saveParameterName,
true);
1341 else if (saveParameterDetail ==
"False")
1342 alg->setProperty(saveParameterName,
false);
1345 alg->setPropertyValue(saveParameterName, saveParameterDetail);
1354 QString savedFile = QString::fromStdString(alg->getProperty(
"Filename"));
1355 QStringList arguments;
1358 if (programKeysAndDetails.count(
"arguments") != 0) {
1359 QString temp = QString::fromStdString(programKeysAndDetails.find(
"arguments")->second);
1360 temp.replace(QString(
"[file]"), savedFile);
1362 arguments = temp.split(
",");
1364 arguments.insert(0, savedFile);
1367 std::vector<std::string> argumentsV;
1369 for (
int i = 0; i < arguments.size(); i++) {
1370 argumentsV.assign(1, (arguments[i].toStdString()));
1375 Mantid::Kernel::ConfigService::Instance().launchProcess(expTarget, argumentsV);
1376 }
catch (std::runtime_error &) {
1377 QMessageBox::information(
this,
"Error",
1378 "User tried to open program from: " + QString::fromStdString(expTarget) +
1379 " There was an error opening the program. "
1380 "Please check the target and arguments list "
1381 "to ensure that these are correct");
1383 }
catch (std::exception &) {
1384 QMessageBox::information(
this,
"Mantid - Send to Program",
1385 "A file property wasn't found. Please check that the correct" +
1386 QString(
"save algorithm was used.\n(View -> Preferences -> "
1387 "Mantid -> SendTo -> Edit -> SaveUsing)"));
1390 QMessageBox::information(
this,
"Target Path Error",
1391 "User tried to open program from: " + QString::fromStdString(expTarget) +
1392 " The target file path for the program "
1393 "can't be found. Please check that the full "
1412 const bool isAdvanced = type ==
"Advanced";
1416 if (userInput.plots.empty()) {
1419 bool showErrorBars = ((type ==
"Errors") || (type ==
"Advanced" && userInput.errors));
1422 if (userInput.tiled) {
1424 }
else if (userInput.simple || userInput.waterfall) {
1425 if (userInput.isAdvanced) {
1426 const auto advancedUserInput = userInput.advanced.value();
1428 userInput.waterfall, advancedUserInput.logName, advancedUserInput.customLogValues);
1431 userInput.waterfall);
1434 }
else if (userInput.surface) {
1435 const auto advancedUserInput = userInput.advanced.value();
1437 advancedUserInput.axisName, advancedUserInput.logName,
1438 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1439 }
else if (userInput.contour) {
1440 const auto advancedUserInput = userInput.advanced.value();
1442 advancedUserInput.axisName, advancedUserInput.logName,
1443 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1458 auto items =
m_tree->selectedItems();
1464 QStringList allWsNames;
1466 for (
auto &item : items) {
1469 if (
auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws)) {
1470 for (
const auto &
name : wsGroup->getNames())
1471 allWsNames.append(QString::fromStdString(
name));
1473 allWsNames.append(item->text(0));
1477 allWsNames.removeDuplicates();
1484 case Qt::Key_Delete:
1485 case Qt::Key_Backspace:
1500 QMessageBox::information(
this,
"Error", QString(
"Cannot create detectors tables for workspace ") + ws);
IPeaksWorkspace_sptr workspace
This class should be the basis for all customised algorithm dialogs.
Defines a mapping between a workspace ID and a pixmap to use for an icon.
A specialized class for dealing with file properties.
const std::string & getDefaultExt() const
Returns the main file extension that's used.
The Logger class is in charge of the publishing messages from the framework through various channels.
Base class for properties.
EXPORT_OPT_MANTIDQT_COMMON QPixmap getQPixmap(const std::string &name)
Function that returns a QPixmap given a string name.
std::shared_ptr< const IMDEventWorkspace > IMDEventWorkspace_const_sptr
Shared pointer to Mantid::API::IMDEventWorkspace (const version)
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const IMDWorkspace > IMDWorkspace_const_sptr
Shared pointer to the IMDWorkspace base class (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< const IPeaksWorkspace > IPeaksWorkspace_const_sptr
shared pointer to Mantid::API::IPeaksWorkspace (const version)