Mantid
Loading...
Searching...
No Matches
WorkspaceTreeWidget.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 +
9
22
24#include "MantidAPI/Axis.h"
31
32#include <cctype>
33#include <cstdlib>
34#include <cstring>
35#include <filesystem>
36#include <memory>
37
38#include <QActionGroup>
39#include <QFileDialog>
40#include <QKeyEvent>
41#include <QMainWindow>
42#include <QMenu>
43#include <QMessageBox>
44#include <QPushButton>
45#include <QRegularExpression>
46#include <QSignalMapper>
47
48using namespace MantidQt::API;
49using namespace Mantid::API;
50using namespace Mantid::Kernel;
51
52namespace {
54Mantid::Kernel::Logger docklog("MantidDockWidget");
55
56WorkspaceIcons WORKSPACE_ICONS = WorkspaceIcons();
57
60std::string expandEnvironmentVariables(const std::string &target) {
61 std::string result = target;
62 size_t pos = 0;
63
64#ifdef _WIN32
65 // Windows style: %VAR%
66 while ((pos = result.find('%', pos)) != std::string::npos) {
67 size_t end = result.find('%', pos + 1);
68 if (end == std::string::npos)
69 break;
70
71 std::string varName = result.substr(pos + 1, end - pos - 1);
72 const char *envValue = std::getenv(varName.c_str());
73
74 if (envValue) {
75 result.replace(pos, end - pos + 1, envValue);
76 pos += std::strlen(envValue);
77 } else {
78 pos = end + 1;
79 }
80 }
81#else
82 // Unix style: $VAR or ${VAR}
83 pos = 0;
84 while ((pos = result.find('$', pos)) != std::string::npos) {
85 size_t start = pos;
86 size_t end;
87 std::string varName;
88
89 if (pos + 1 < result.length() && result[pos + 1] == '{') {
90 // ${VAR} format
91 end = result.find('}', pos + 2);
92 if (end == std::string::npos) {
93 pos++;
94 continue;
95 }
96 varName = result.substr(pos + 2, end - pos - 2);
97 end++; // include the closing brace
98 } else {
99 // $VAR format - find end of variable name
100 end = pos + 1;
101 while (end < result.length() && (std::isalnum(result[end]) || result[end] == '_')) {
102 end++;
103 }
104 varName = result.substr(pos + 1, end - pos - 1);
105 }
106
107 if (!varName.empty()) {
108 const char *envValue = std::getenv(varName.c_str());
109 if (envValue) {
110 result.replace(start, end - start, envValue);
111 pos = start + std::strlen(envValue);
112 } else {
113 pos = end;
114 }
115 } else {
116 pos++;
117 }
118 }
119#endif
120
121 return result;
122}
123} // namespace
124
125namespace MantidQt::MantidWidgets {
126
128 : QWidget(parent), m_mantidDisplayModel(mdb), m_viewOnly(viewOnly), m_updateCount(0), m_treeUpdating(false),
129 m_promptDelete(false), m_saveFileType(SaveFileType::Nexus), m_sortCriteria(SortCriteria::ByName),
130 m_sortDirection(SortDirection::Ascending) {
131 setObjectName("exploreMantid"); // this is needed for QMainWindow::restoreState()
132 m_saveMenu = new QMenu(this);
133
135
137
138 // Dialog box used for user to specify folder to save multiple workspaces into
139 m_saveFolderDialog = new QFileDialog(this);
140 m_saveFolderDialog->setFileMode(QFileDialog::Directory);
141 m_saveFolderDialog->setOption(QFileDialog::ShowDirsOnly);
142
143 // To be able to use them in queued signals they need to be registered
144 static bool registered_addtional_types = false;
145 if (!registered_addtional_types) {
146 registered_addtional_types = true;
147 qRegisterMetaType<TopLevelItems>();
148 }
149
150 // SET UP SORT
153
155
156 m_tree->setDragEnabled(true);
157
158 auto presenter = std::make_shared<WorkspacePresenter>(this);
159 m_presenter = std::dynamic_pointer_cast<ViewNotifiable>(presenter);
160 presenter->init();
161
162 if (m_viewOnly)
164}
165
167
172void WorkspaceTreeWidget::dropEvent(QDropEvent *de) { m_tree->dropEvent(de); }
173
176 m_tree->setHeaderLabel("Workspaces");
177
178 auto *buttonLayout = new FlowLayout();
179 m_loadButton = new QPushButton("Load");
180 m_loadButton->setToolTip("Load a file or live data");
181 m_saveButton = new QPushButton("Save");
182 m_saveButton->setToolTip("Save the selected workspaces");
183 m_deleteButton = new QPushButton("Delete");
184 m_deleteButton->setToolTip("Delete the selected workspaces");
185 m_clearButton = new QPushButton("Clear");
186 m_clearButton->setToolTip("Delete all workspaces");
187 m_groupButton = new QPushButton("Group");
188 m_groupButton->setToolTip("Group together two or more selected workspaces");
189 m_sortButton = new QPushButton("Sort");
190 m_sortButton->setToolTip("Sort all workspaces by name, size, or the last time they were modified");
191
192 m_groupButton->setEnabled(false);
193 m_deleteButton->setEnabled(false);
194 m_clearButton->setEnabled(false);
195 m_saveButton->setEnabled(false);
196
197 buttonLayout->addWidget(m_loadButton);
198 buttonLayout->addWidget(m_deleteButton);
199 buttonLayout->addWidget(m_clearButton);
200 buttonLayout->addWidget(m_groupButton);
201 buttonLayout->addWidget(m_sortButton);
202 buttonLayout->addWidget(m_saveButton);
203
205 m_workspaceFilter->setPlaceholderText("Filter Workspaces");
206 m_workspaceFilter->setToolTip("Type here to filter the workspaces");
207
208 auto *layout = new QVBoxLayout();
209 layout->setContentsMargins(0, 0, 0, 0);
210 layout->addLayout(buttonLayout);
211 layout->addWidget(m_workspaceFilter);
212 layout->addWidget(m_tree);
213 this->setLayout(layout);
214}
215
217 m_loadMenu = new QMenu(this);
218
219 QAction *loadFileAction = new QAction("File", this);
220 QAction *liveDataAction = new QAction("Live Data", this);
221 connect(loadFileAction, SIGNAL(triggered()), this, SLOT(onClickLoad()));
222 connect(liveDataAction, SIGNAL(triggered()), this, SLOT(onClickLiveData()));
223
224 m_loadMenu->addAction(loadFileAction);
225 m_loadMenu->addAction(liveDataAction);
226 m_loadButton->setMenu(m_loadMenu);
227}
228
230 connect(m_workspaceFilter, SIGNAL(textChanged(const QString &)), this, SLOT(filterWorkspaceTree(const QString &)));
231 connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(onClickDeleteWorkspaces()));
232 connect(m_clearButton, SIGNAL(clicked()), this, SLOT(onClickClearWorkspaces()));
233 connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(clickedWorkspace(QTreeWidgetItem *, int)));
234 connect(m_tree, SIGNAL(itemSelectionChanged()), this, SLOT(workspaceSelected()));
235 connect(m_groupButton, SIGNAL(clicked()), this, SLOT(onClickGroupButton()));
236
237 m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
238 connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
239 connect(this, SIGNAL(signalUpdateTree(const TopLevelItems &)), this, SLOT(handleUpdateTree(const TopLevelItems &)),
240 Qt::QueuedConnection);
241
242 connect(this, SIGNAL(signalClearView()), this, SLOT(handleClearView()), Qt::QueuedConnection);
243 connect(m_tree, SIGNAL(itemSelectionChanged()), this, SLOT(onTreeSelectionChanged()));
244 connect(m_tree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(populateChildData(QTreeWidgetItem *)));
245}
246
253void WorkspaceTreeWidget::setTreeUpdating(const bool state) { m_treeUpdating = state; }
254
256
258 return std::dynamic_pointer_cast<WorkspacePresenter>(m_presenter);
259}
260
265 auto items = m_tree->selectedItems();
266 StringList names;
267 names.reserve(static_cast<size_t>(items.size()));
268 std::transform(items.cbegin(), items.cend(), std::back_inserter(names),
269 [](auto const &item) { return item->text(0).toStdString(); });
270
271 return names;
272}
273
275 auto items = m_tree->selectedItems();
276 QStringList names;
277
278 for (auto &item : items) {
279 names.append(item->text(0));
280 }
281 return names;
282}
283
288 auto items = m_tree->selectedItems();
289 auto data = items[0]->data(0, Qt::UserRole).value<Workspace_sptr>();
290
291 return data;
292}
293
294bool WorkspaceTreeWidget::askUserYesNo(const std::string &caption, const std::string &message) const {
295 return QMessageBox::question(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message),
296 QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes;
297}
298
299void WorkspaceTreeWidget::showCriticalUserMessage(const std::string &caption, const std::string &message) const {
300 QMessageBox::critical(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message));
301}
302
304 QObject *sender = QObject::sender();
305 const auto *dlg = reinterpret_cast<MantidQt::API::AlgorithmDialog *>(sender);
306 if (!dlg)
307 return; // should never happen
308
309 QString fn = MantidQt::API::AlgorithmInputHistory::Instance().previousInput("Load", "Filename");
310
312}
313
315 QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel), "showAlgorithmDialog", Qt::QueuedConnection,
316 Q_ARG(QString, "Load"));
317}
318
320 QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel), "showAlgorithmDialog", Qt::QueuedConnection,
321 Q_ARG(QString, "StartLiveData"));
322}
323
325
327 QStringList names;
328
329 for (const auto &ws : wsNames)
330 names.append(QString::fromStdString(ws));
331
333}
334
342void WorkspaceTreeWidget::recordWorkspaceRename(const std::string &oldName, const std::string &newName) {
343 QString qs_oldName = QString::fromStdString(oldName);
344 QString qs_newName = QString::fromStdString(newName);
345
346 QMutexLocker renameMapLock(&m_mutex);
347 // check if old_name has been recently a new name
348 QList<QString> oldNames = m_renameMap.keys(qs_oldName);
349 // non-empty list of oldNames become new_name
350 if (!oldNames.isEmpty()) {
351 for (const auto &name : oldNames)
352 m_renameMap[name] = qs_newName;
353 } else {
354 // record a new rename pair
355 m_renameMap[qs_oldName] = qs_newName;
356 }
357}
358
360
362
364
366 return askUserYesNo("Delete Workspaces", "Are you sure you want to delete the selected Workspaces?\n\nThis prompt "
367 "can be disabled from:\nFile->Settings->General");
368}
369
371 QStringList names;
372 for (const auto &ws : wsNames)
373 names.append(QString::fromStdString(ws));
375}
376
378
383
388
393
398
403
405 static int counter = 1;
406
407 item->setSortPos(counter);
408
409 counter++;
410}
411
413
415
417 if (isTreeUpdating())
418 return;
420 m_tree->setSortOrder(direction == SortDirection::Ascending ? Qt::AscendingOrder : Qt::DescendingOrder);
421 m_tree->sort();
422}
423
425 switch (criteria) {
432 default:
433 // Handle if someone adds a new Enum and it falls through by defaulting to
434 // name
436 }
437}
438
442
444 const QAction *sendingAction = dynamic_cast<QAction *>(sender());
445 if (!sendingAction)
446 return;
447
448 QString actionName = sendingAction->text();
449
450 if (actionName.compare("Nexus") == 0)
452 else if (actionName.compare("ASCII") == 0)
454
455 auto selectedNames = getSelectedWorkspaceNames();
456
457 if (selectedNames.size() > 1) {
458 // Save multiple workspaces
459 saveWorkspaces(selectedNames);
460 } else if (selectedNames.size() == 1) {
461 // Save single workspace
463 }
464}
465
467
468void WorkspaceTreeWidget::saveWorkspace(const std::string &wsName, SaveFileType type) {
470 if (!wsName.empty()) {
471 presets["InputWorkspace"] = QString::fromStdString(wsName);
472 }
473 int version = -1;
474 std::string algorithmName;
475
476 switch (type) {
478 algorithmName = "SaveNexus";
479 break;
481 algorithmName = "SaveAscii";
482 break;
483 }
484
485 m_mantidDisplayModel->showAlgorithmDialog(QString::fromStdString(algorithmName), presets, nullptr, version);
486}
487
489 QList<QTreeWidgetItem *> items = m_tree->selectedItems();
490 if (items.size() < 2)
491 return;
492
493 m_saveFolderDialog->setWindowTitle("Select save folder");
494 m_saveFolderDialog->setLabelText(QFileDialog::Accept, "Select");
495
496 auto res = m_saveFolderDialog->exec();
497 if (res != QFileDialog::Accepted)
498 return;
499
500 auto folder = m_saveFolderDialog->selectedFiles()[0].toStdString();
501
502 std::string algorithmName;
503 std::string fileExtension;
504
505 switch (m_saveFileType) {
507 algorithmName = "SaveAscii";
508 fileExtension = ".dat";
509 break;
511 default:
512 algorithmName = "SaveNexus";
513 fileExtension = ".nxs";
514 break;
515 }
516
517 IAlgorithm_sptr saveAlg = AlgorithmManager::Instance().create(algorithmName);
518 saveAlg->initialize();
519
520 for (auto &wsName : wsNames) {
521 std::string filename = folder + "/" + wsName + fileExtension;
522 try {
523 saveAlg->setProperty("InputWorkspace", wsName);
524 saveAlg->setProperty("Filename", filename);
525 saveAlg->execute();
526 } catch (std::exception &ex) {
527 docklog.error() << "Error saving workspace " << wsName << ": " << ex.what() << '\n';
528 }
529 }
530}
531
532std::string WorkspaceTreeWidget::getFilterText() const { return m_workspaceFilter->text().toStdString(); }
533
534void WorkspaceTreeWidget::filterWorkspaces(const std::string &filterText) {
535 const QString text = QString::fromStdString(filterText).trimmed();
536 QRegularExpression filterRegEx(text, QRegularExpression::CaseInsensitiveOption);
537
538 // show all items
539 QTreeWidgetItemIterator unhideIter(m_tree);
540 while (*unhideIter) {
541 (*unhideIter)->setHidden(false);
542 ++unhideIter;
543 }
544
545 int hiddenCount = 0;
546 if (!text.isEmpty()) {
547 QList<QTreeWidgetItem *> visibleGroups;
548 // Loop over everything (currently loaded) and top level
549 // find out what is already expanded
550 QStringList expanded;
551 int n = m_tree->topLevelItemCount();
552 for (int i = 0; i < n; ++i) {
553 auto item = m_tree->topLevelItem(i);
554 if (item->isExpanded()) {
555 expanded << item->text(0);
556 } else {
557 // expand everything that is at the top level (as we lazy load this is
558 // required)
559 item->setExpanded(true);
560 }
561 }
562
563 // filter based on the string
564 QTreeWidgetItemIterator it(m_tree, QTreeWidgetItemIterator::All);
565 while (*it) {
566 QTreeWidgetItem *item = (*it);
567 QVariant userData = item->data(0, Qt::UserRole);
568
569 if (!userData.isNull()) {
570 Workspace_sptr workspace = userData.value<Workspace_sptr>();
571 if (workspace) {
572 // I am a workspace
573 if (item->text(0).contains(filterRegEx)) {
574 // my name does match the filter
575 if (workspace->isGroup()) {
576 // I am a group, I will want my children to be visible
577 // but I cannot do that until this iterator has finished
578 // store this pointer in a list for processing later
579 visibleGroups.append(item);
580 item->setHidden(false);
581 }
582
583 if (item->parent() == nullptr) {
584 // No parent, I am a top level workspace - show me
585 item->setHidden(false);
586 } else {
587 // I am a child workspace of a group
588 // I match, so I want my parent to remain visible as well.
589 item->setHidden(false);
590 if (item->parent()->isHidden()) {
591 // I was previously hidden, show me and set to be expanded
592 --hiddenCount;
593 item->parent()->setHidden(false);
594 expanded << item->parent()->text(0);
595 }
596 }
597 } else {
598 // my name does not match the filter - hide me
599 item->setHidden(true);
600 ++hiddenCount;
601 }
602 }
603 }
604 ++it;
605 }
606
607 // make children of visible groups visible
608 for (auto group : visibleGroups) {
609 for (int i = 0; i < group->childCount(); i++) {
610 QTreeWidgetItem *child = group->child(i);
611 if (child->isHidden()) {
612 // I was previously hidden, show me
613 --hiddenCount;
614 child->setHidden(false);
615 }
616 }
617 }
618
619 // set the expanded state
620 for (int i = 0; i < n; ++i) {
621 auto item = m_tree->topLevelItem(i);
622 item->setExpanded(expanded.contains(item->text(0)));
623 }
624 }
625
626 // display a message if items are hidden
627 if (hiddenCount > 0) {
628 QString headerString = QString("Workspaces (%1 filtered)").arg(QString::number(hiddenCount));
629 m_tree->headerItem()->setText(0, headerString);
630 } else {
631 m_tree->headerItem()->setText(0, "Workspaces");
632 }
633}
634
640void WorkspaceTreeWidget::setItemIcon(QTreeWidgetItem *item, const std::string &wsID) {
641 try {
642 item->setIcon(0, QIcon(WORKSPACE_ICONS.getIcon(wsID)));
643 } catch (std::runtime_error &) {
644 docklog.warning() << "Cannot find icon for workspace ID '" << wsID << "'\n";
645 }
646}
647
652 m_showData = new QAction(tr("Show Data"), this);
653 connect(m_showData, SIGNAL(triggered()), this, SLOT(onClickShowData()));
654
655 m_showInst = new QAction(tr("Show Instrument"), this);
656 connect(m_showInst, SIGNAL(triggered()), this, SLOT(onClickShowInstrument()));
657
658 m_plotSpec = new QAction(tr("Plot Spectrum..."), this);
659 connect(m_plotSpec, SIGNAL(triggered()), this, SLOT(onClickPlotSpectra()));
660
661 m_plotSpecErr = new QAction(tr("Plot Spectrum with Errors..."), this);
662 connect(m_plotSpecErr, SIGNAL(triggered()), this, SLOT(onClickPlotSpectraErr()));
663
664 m_plotAdvanced = new QAction(tr("Plot Advanced..."), this);
665 connect(m_plotAdvanced, SIGNAL(triggered()), this, SLOT(onClickPlotAdvanced()));
666
667 m_colorFill = new QAction(tr("Color Fill Plot"), this);
668 connect(m_colorFill, SIGNAL(triggered()), this, SLOT(onClickDrawColorFillPlot()));
669
670 m_showDetectors = new QAction(tr("Show Detectors"), this);
671 connect(m_showDetectors, SIGNAL(triggered()), this, SLOT(onClickShowDetectorTable()));
672
673 m_showBoxData = new QAction(tr("Show Box Data Table"), this);
674 connect(m_showBoxData, SIGNAL(triggered()), this, SLOT(onClickShowBoxData()));
675
676 m_showMDPlot = new QAction(tr("Plot MD"), this);
677 connect(m_showMDPlot, SIGNAL(triggered()), this, SLOT(onClickShowMDPlot()));
678
679 m_showListData = new QAction(tr("List Data"), this);
680 connect(m_showListData, SIGNAL(triggered()), this, SLOT(onClickShowListData()));
681
682 m_showSpectrumViewer = new QAction(tr("Show Spectrum Viewer"), this);
683 connect(m_showSpectrumViewer, SIGNAL(triggered()), this, SLOT(onClickShowSpectrumViewer()));
684
685 m_showSliceViewer = new QAction(tr("Show Slice Viewer"), this);
686 {
687 QIcon icon;
688 icon.addFile(QString::fromUtf8(":/SliceViewer/icons/SliceViewerWindow_icon.png"), QSize(), QIcon::Normal,
689 QIcon::Off);
690 m_showSliceViewer->setIcon(icon);
691 }
692 connect(m_showSliceViewer, SIGNAL(triggered()), this, SLOT(onClickShowSliceViewer()));
693
694 m_showLogs = new QAction(tr("Sample Logs..."), this);
695 connect(m_showLogs, SIGNAL(triggered()), this, SLOT(onClickShowFileLog()));
696
697 m_showSampleMaterial = new QAction(tr("Sample Material..."), this);
698 connect(m_showSampleMaterial, SIGNAL(triggered()), this, SLOT(onClickShowSampleMaterial()));
699
700 m_showHist = new QAction(tr("Show History"), this);
701 connect(m_showHist, SIGNAL(triggered()), this, SLOT(onClickShowAlgHistory()));
702
703 m_saveNexus = new QAction(tr("Save NeXus"), this);
704 connect(m_saveNexus, SIGNAL(triggered()), this, SLOT(onClickSaveNexusWorkspace()));
705
706 m_rename = new QAction(tr("Rename"), this);
707 connect(m_rename, SIGNAL(triggered()), this, SLOT(renameWorkspace()));
708
709 m_delete = new QAction(tr("Delete"), this);
710 connect(m_delete, SIGNAL(triggered()), this, SLOT(onClickDeleteWorkspaces()));
711
712 m_showTransposed = new QAction(tr("Show Transposed"), this);
713 connect(m_showTransposed, SIGNAL(triggered()), this, SLOT(onClickShowTransposed()));
714
715 m_convertToMatrixWorkspace = new QAction(tr("Convert to MatrixWorkspace"), this);
716 m_convertToMatrixWorkspace->setIcon(QIcon(getQPixmap("mantid_matrix_xpm")));
717 connect(m_convertToMatrixWorkspace, SIGNAL(triggered()), this, SLOT(onClickConvertToMatrixWorkspace()));
718
719 m_convertMDHistoToMatrixWorkspace = new QAction(tr("Convert to MatrixWorkspace"), this);
720 m_convertMDHistoToMatrixWorkspace->setIcon(QIcon(getQPixmap("mantid_matrix_xpm")));
721 connect(m_convertMDHistoToMatrixWorkspace, SIGNAL(triggered()), this, SLOT(onClickConvertMDHistoToMatrixWorkspace()));
722
723 m_clearUB = new QAction(tr("Clear UB Matrix"), this);
724 connect(m_clearUB, SIGNAL(triggered()), this, SLOT(onClickClearUB()));
725}
726
732 QMenu *sortMenu = new QMenu(this);
733
734 QAction *ascendingSortAction = new QAction("Ascending", this);
735 QAction *descendingSortAction = new QAction("Descending", this);
736 QAction *byNameChoice = new QAction("Name", this);
737 QAction *byLastModifiedChoice = new QAction("Last Modified", this);
738 QAction *byMemorySize = new QAction("Size", this);
739
740 ascendingSortAction->setCheckable(true);
741 ascendingSortAction->setEnabled(true);
742
743 descendingSortAction->setCheckable(true);
744 descendingSortAction->setEnabled(true);
745
746 QActionGroup *sortDirectionGroup = new QActionGroup(sortMenu);
747 sortDirectionGroup->addAction(ascendingSortAction);
748 sortDirectionGroup->addAction(descendingSortAction);
749 sortDirectionGroup->setExclusive(true);
750 ascendingSortAction->setChecked(true);
751
752 byNameChoice->setCheckable(true);
753 byNameChoice->setEnabled(true);
754
755 byLastModifiedChoice->setCheckable(true);
756 byLastModifiedChoice->setEnabled(true);
757
758 byMemorySize->setCheckable(true);
759 byMemorySize->setEnabled(true);
760
761 QActionGroup *sortChoiceGroup = new QActionGroup(sortMenu);
762 sortChoiceGroup->addAction(byNameChoice);
763 sortChoiceGroup->addAction(byLastModifiedChoice);
764 sortChoiceGroup->addAction(byMemorySize);
765 sortChoiceGroup->setExclusive(true);
766 byNameChoice->setChecked(true);
767
768 connect(ascendingSortAction, SIGNAL(triggered()), this, SLOT(sortAscending()));
769 connect(descendingSortAction, SIGNAL(triggered()), this, SLOT(sortDescending()));
770 connect(byNameChoice, SIGNAL(triggered()), this, SLOT(chooseByName()));
771 connect(byLastModifiedChoice, SIGNAL(triggered()), this, SLOT(chooseByLastModified()));
772 connect(byMemorySize, SIGNAL(triggered()), this, SLOT(chooseByMemorySize()));
773
774 sortMenu->addActions(sortDirectionGroup->actions());
775 sortMenu->addSeparator();
776 sortMenu->addActions(sortChoiceGroup->actions());
777 m_sortButton->setMenu(sortMenu);
778}
779
784void WorkspaceTreeWidget::populateChildData(QTreeWidgetItem *item) {
785 QVariant userData = item->data(0, Qt::UserRole);
786 if (userData.isNull())
787 return;
788
789 // Clear it first
790 while (item->childCount() > 0) {
791 auto *widgetItem = item->takeChild(0);
792 delete widgetItem;
793 }
794
795 Workspace_sptr workspace = userData.value<Workspace_sptr>();
796
797 if (auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace)) {
798 auto members = group->getAllItems();
799 auto visibleNames = AnalysisDataService::Instance().getObjectNames();
800 for (const auto &ws : members) {
801 if (std::find(visibleNames.begin(), visibleNames.end(), ws->getName()) != visibleNames.end()) {
802 auto *node = addTreeEntry(std::make_pair(ws->getName(), ws), item);
804 if (shouldBeSelected(node->text(0)))
805 node->setSelected(true);
806 }
807 }
808 } else {
809 QString details;
810 try {
811 details = workspace->toString().c_str();
812 } catch (std::runtime_error &e) {
813 details = QString("Error: %1").arg(e.what());
814 }
815 QStringList rows = details.split(QLatin1Char('\n'), Qt::SkipEmptyParts);
816 rows.append(QString("Memory used: ") + workspace->getMemorySizeAsStr().c_str());
817
818 auto iend = rows.constEnd();
819 for (auto itr = rows.constBegin(); itr != iend; ++itr) {
820 MantidTreeWidgetItem *data = new MantidTreeWidgetItem(QStringList(*itr), m_tree);
821 data->setFlags(Qt::NoItemFlags);
823 item->addChild(data);
824 }
825 }
826}
827
837
843void WorkspaceTreeWidget::populateTopLevel(const TopLevelItems &topLevelItems, const QStringList &expanded) {
844 {
845 QMutexLocker lock(&m_mutex);
846 // collect names of selected workspaces
847 QList<QTreeWidgetItem *> selected = m_tree->selectedItems();
848 m_selectedNames.clear(); // just in case
849 for (QTreeWidgetItem *item : selected) {
850 m_selectedNames << item->text(0);
851 }
852
853 // populate the tree from scratch
854 m_tree->clear();
855 auto iend = topLevelItems.end();
856 for (auto it = topLevelItems.begin(); it != iend; ++it) {
857 auto *node = addTreeEntry(*it);
858 QString name = node->text(0);
859 if (expanded.contains(name))
860 node->setExpanded(true);
861 // see if item must be selected
863 node->setSelected(true);
864 }
865
866 m_selectedNames.clear();
867 m_renameMap.clear();
868 }
869 // apply any filtering
871}
872
880MantidTreeWidgetItem *WorkspaceTreeWidget::addTreeEntry(const std::pair<std::string, Mantid::API::Workspace_sptr> &item,
881 QTreeWidgetItem *parent) {
882 MantidTreeWidgetItem *node = new MantidTreeWidgetItem(QStringList(item.first.c_str()), m_tree);
883 node->setData(0, Qt::UserRole, QVariant::fromValue(item.second));
884
885 // A a child ID item so that it becomes expandable. Using the correct ID is
886 // needed when plotting from non-expanded groups.
887 const std::string wsID = item.second->id();
888 auto *idNode = new MantidTreeWidgetItem(QStringList(wsID.c_str()), m_tree);
889 idNode->setFlags(Qt::NoItemFlags);
890 node->addChild(idNode);
891 setItemIcon(node, wsID);
892
893 if (parent) {
894 parent->addChild(node);
895 } else {
896 m_tree->addTopLevelItem(node);
897 }
898 return node;
899}
900
905bool WorkspaceTreeWidget::shouldBeSelected(const QString &name) const {
906 QMutexLocker lock(&m_mutex);
907 QStringList renamed = m_renameMap.keys(name);
908 if (!renamed.isEmpty()) {
909 return std::any_of(renamed.cbegin(), renamed.cend(),
910 [&](const auto &oldName) { return m_selectedNames.contains(oldName); });
911 } else if (m_selectedNames.contains(name)) {
912 return true;
913 }
914 return false;
915}
916
918 // get selected workspaces
919 auto items = m_tree->selectedItems();
920
921 if (m_groupButton) {
922 if (items.size() == 1) {
923 // check it's group
924 auto wsSptr = items.first()->data(0, Qt::UserRole).value<Workspace_sptr>();
925 auto grpSptr = std::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
926 if (grpSptr) {
927 m_groupButton->setText("Ungroup");
928 m_groupButton->setToolTip("Ungroup selected workspace");
929 m_groupButton->setEnabled(true);
930 } else
931 m_groupButton->setEnabled(false);
932
933 } else if (items.size() >= 2) {
934 m_groupButton->setText("Group");
935 m_groupButton->setEnabled(true);
936 m_groupButton->setToolTip("Group together two or more selected workspaces");
937 } else if (items.size() == 0) {
938 m_groupButton->setText("Group");
939 m_groupButton->setEnabled(false);
940 m_groupButton->setToolTip("Group together two or more selected workspaces");
941 }
942 }
943
944 if (m_deleteButton)
945 m_deleteButton->setEnabled(items.size() > 0);
946
947 if (m_saveButton)
948 m_saveButton->setEnabled(items.size() > 0);
949
950 if (items.size() > 0) {
951 auto item = *(items.begin());
953 } else {
955 }
956}
957
964 const Mantid::API::MatrixWorkspace_const_sptr &matrixWS) const {
965 // Add all options except plot of we only have 1 value
966 menu->addAction(m_showData);
967 menu->addAction(m_showInst);
968 // Disable the 'show instrument' option if a workspace doesn't have an
969 // instrument attached or if it does not have a spectra axis
970 m_showInst->setEnabled(matrixWS->getInstrument() && !matrixWS->getInstrument()->getName().empty() &&
971 matrixWS->getAxis(1)->isSpectra());
972 menu->addSeparator();
973 menu->addAction(m_plotSpec);
974 menu->addAction(m_plotSpecErr);
975 menu->addAction(m_plotAdvanced);
976
977 // Don't plot a spectrum if only one X value
978 bool multipleBins = false;
979 try {
980 multipleBins = (matrixWS->blocksize() > 1);
981 } catch (...) {
982 const size_t numHist = matrixWS->getNumberHistograms();
983 for (size_t i = 0; i < numHist; ++i) {
984 if (matrixWS->y(i).size() > 1) {
985 multipleBins = true;
986 break;
987 }
988 }
989 }
990 m_plotSpec->setEnabled(multipleBins);
991 m_plotSpecErr->setEnabled(multipleBins);
992 m_plotAdvanced->setEnabled(multipleBins);
993
994 menu->addAction(m_showSpectrumViewer); // The 2D spectrum viewer
995
996 menu->addAction(m_colorFill);
997 // Show the color fill plot if you have more than one histogram
998 m_colorFill->setEnabled((matrixWS->axes() > 1 && matrixWS->getNumberHistograms() > 1));
999 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1000 menu->addSeparator();
1001 menu->addAction(m_showDetectors);
1002 menu->addAction(m_showLogs);
1003 menu->addAction(m_showSampleMaterial);
1004 menu->addAction(m_showHist);
1005 menu->addAction(m_saveNexus);
1006}
1007
1015 Q_UNUSED(WS);
1016
1017 // menu->addAction(m_showBoxData); // Show MD Box data (for debugging only)
1018 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1019 menu->addAction(m_showHist); // Algorithm history
1020 menu->addAction(m_showListData); // Show data in table
1021 menu->addAction(m_showLogs);
1022}
1023
1025 const Mantid::API::IMDWorkspace_const_sptr &WS) const {
1026 Q_UNUSED(WS);
1027 menu->addAction(m_showHist); // Algorithm history
1028 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1029 menu->addAction(m_showMDPlot); // A plot of intensity vs bins
1030 menu->addAction(m_showListData); // Show data in table
1031 menu->addAction(m_convertMDHistoToMatrixWorkspace);
1032 menu->addAction(m_showLogs);
1033}
1034
1041 Q_UNUSED(WS);
1042 menu->addAction(m_showData);
1043 menu->addSeparator();
1044 menu->addAction(m_showDetectors);
1045 menu->addAction(m_showHist);
1046}
1047
1053 m_plotSpec->setEnabled(true);
1054 menu->addAction(m_plotSpec);
1055 m_plotSpecErr->setEnabled(true);
1056 menu->addAction(m_plotSpecErr);
1057 m_plotAdvanced->setEnabled(true);
1058 menu->addAction(m_plotAdvanced);
1059 menu->addAction(m_colorFill);
1060 m_colorFill->setEnabled(true);
1061
1062 menu->addSeparator();
1063 menu->addAction(m_saveNexus);
1064}
1065
1071 menu->addAction(m_showData);
1072 menu->addAction(m_showTransposed);
1073 menu->addAction(m_showHist);
1074 menu->addAction(m_saveNexus);
1075 menu->addAction(m_convertToMatrixWorkspace);
1076}
1077
1083void WorkspaceTreeWidget::addClearMenuItems(QMenu *menu, const QString &wsName) {
1084 QMenu *clearMenu = new QMenu(tr("Clear Options"), this);
1085
1086 m_clearUB->setEnabled(hasUBMatrix(wsName.toStdString()));
1087
1088 clearMenu->addAction(m_clearUB);
1089 menu->addMenu(clearMenu);
1090}
1091
1092bool WorkspaceTreeWidget::hasUBMatrix(const std::string &wsName) {
1093 bool hasUB = false;
1094 Workspace_sptr ws = AnalysisDataService::Instance().retrieve(wsName);
1095 IMDWorkspace_sptr wsIMD = std::dynamic_pointer_cast<IMDWorkspace>(ws);
1096 if (ws && wsIMD) {
1097 hasUB = wsIMD->hasOrientedLattice();
1098 }
1099 return hasUB;
1100}
1101
1109void WorkspaceTreeWidget::addSaveMenuOption(const QString &algorithmString, QString menuEntryName) {
1110 // Default to algo string if no entry name given
1111 if (menuEntryName.isEmpty())
1112 menuEntryName = algorithmString;
1113
1114 // Create the action and add data
1115 QAction *saveAction = new QAction(menuEntryName, this);
1116 saveAction->setData(QVariant(algorithmString));
1117
1118 // Connect the trigger slot to show algorithm dialog
1119 connect(saveAction, SIGNAL(triggered()), this, SLOT(handleShowSaveAlgorithm()));
1120
1121 // Add it to the menu
1122 m_saveMenu->addAction(saveAction);
1123}
1124
1130 m_filteredText = text.toStdString();
1132}
1133
1138
1144 return askUserYesNo("Clear Workspaces", "This will delete all the workspaces, are you sure?");
1145}
1146
1151void WorkspaceTreeWidget::enableClearButton(bool enable) { m_clearButton->setEnabled(enable); }
1152
1157
1158void WorkspaceTreeWidget::clickedWorkspace(QTreeWidgetItem *item, int /*unused*/) { Q_UNUSED(item); }
1159
1161 auto selectedNames = getSelectedWorkspaceNames();
1162 if (selectedNames.empty())
1163 return;
1164
1165 // Remove all existing save algorithms from list
1166 m_saveMenu->clear();
1167
1168 addSaveMenuOption("SaveNexus", "Nexus");
1169 addSaveMenuOption("SaveAscii", "ASCII");
1170
1171 m_saveButton->setMenu(m_saveMenu);
1172}
1173
1176 if (m_groupButton) {
1177 QString qButtonName = m_groupButton->text();
1178 if (qButtonName == "Group") {
1180 } else if (qButtonName == "Ungroup") {
1182 }
1183 }
1184}
1185
1188
1193
1194// Asynchronous signal handlers
1198 // do not update until the counter is zero
1199 if (m_updateCount.deref())
1200 return;
1201
1202 // find all expanded top-level entries
1203 QStringList expanded;
1204 int n = m_tree->topLevelItemCount();
1205 for (int i = 0; i < n; ++i) {
1206 auto item = m_tree->topLevelItem(i);
1207 if (item->isExpanded()) {
1208 expanded << item->text(0);
1209 }
1210 }
1211
1212 // create a new tree
1213 setTreeUpdating(true);
1214 populateTopLevel(items, expanded);
1215 setTreeUpdating(false);
1216
1217 // enable clear button here if any items in tree
1218 enableClearButton(!items.empty());
1219
1220 // Re-sort
1221 m_tree->sort();
1222}
1223
1228
1229// Context Menu Methods
1230
1232void WorkspaceTreeWidget::popupMenu(const QPoint &pos) {
1233 if (!m_viewOnly) {
1234 m_menuPosition = pos;
1236 }
1237}
1238
1240 QTreeWidgetItem *treeItem = m_tree->itemAt(m_menuPosition);
1241 selectedWsName = "";
1242 if (treeItem)
1243 selectedWsName = treeItem->text(0);
1244 else
1245 m_tree->selectionModel()->clear();
1246
1247 QMenu *menu(nullptr);
1248
1249 // If no workspace is here then have load raw and dae
1250 if (selectedWsName.isEmpty())
1251 menu = m_loadMenu;
1252 else { // else show instrument, sample logs and delete
1253 // Fresh menu
1254 menu = new QMenu(this);
1255 menu->setObjectName("WorkspaceContextMenu");
1256 auto mantidTreeItem = dynamic_cast<MantidTreeWidgetItem *>(treeItem);
1257 auto ws = mantidTreeItem->data(0, Qt::UserRole).value<Mantid::API::Workspace_sptr>();
1258
1259 // Add the items that are appropriate for the type
1260 if (auto matrixWS = std::dynamic_pointer_cast<const Mantid::API::MatrixWorkspace>(ws)) {
1261 addMatrixWorkspaceMenuItems(menu, matrixWS);
1262 } else if (auto mdeventWS = std::dynamic_pointer_cast<const IMDEventWorkspace>(ws)) {
1263 addMDEventWorkspaceMenuItems(menu, mdeventWS);
1264 } else if (auto mdWS = std::dynamic_pointer_cast<const IMDWorkspace>(ws)) {
1265 addMDHistoWorkspaceMenuItems(menu, mdWS);
1266 } else if (auto peaksWS = std::dynamic_pointer_cast<const IPeaksWorkspace>(ws)) {
1267 addPeaksWorkspaceMenuItems(menu, peaksWS);
1268 } else if (auto groupWS = std::dynamic_pointer_cast<const WorkspaceGroup>(ws)) {
1270 } else if (std::dynamic_pointer_cast<const Mantid::API::ITableWorkspace>(ws)) {
1272 } else {
1273 // None of the above? -> not a workspace
1274 return;
1275 }
1277
1278 // Get the names of the programs for the send to option
1279 std::vector<std::string> programNames =
1280 (Mantid::Kernel::ConfigService::Instance().getKeys("workspace.sendto.name"));
1281 bool firstPass(true);
1282 // Check to see if any options aren't visible
1283 for (const auto &programName : programNames) {
1284 std::string visible =
1285 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".visible");
1286 std::string target =
1287 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".target");
1288 if (Mantid::Kernel::ConfigService::Instance().isExecutable(target) && visible == "Yes") {
1289 bool compatible(true);
1290 std::string saveUsing(
1291 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".saveusing"));
1292 try {
1293 Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create(saveUsing);
1294 alg->setPropertyValue("InputWorkspace", selectedWsName.toStdString());
1295 } catch (std::exception &) {
1296 compatible = false;
1297 }
1298 if (compatible) {
1299 if (firstPass) {
1300 m_saveToProgram = new QMenu(tr("Send to"), this);
1301 menu->addMenu(m_saveToProgram);
1302
1303 // Sub-menu for program list
1304 m_programMapper = new QSignalMapper(this);
1305 }
1306 QString name = QString::fromStdString(programName);
1307 // Setup new menu option for the program
1308 m_program = new QAction(name, this);
1309 connect(m_program, SIGNAL(triggered()), m_programMapper, SLOT(map()));
1310 // Send name of program when clicked
1311 m_programMapper->setMapping(m_program, name);
1312 m_saveToProgram->addAction(m_program);
1313
1314 // Set first pass to false so that it doesn't set up another menu
1315 // entry for all programs.
1316 firstPass = false;
1317 }
1318 }
1319 }
1320
1321 // Tell the button what to listen for and what to do once clicked (if there
1322 // is anything to connect it will be set to false)
1323 if (!firstPass)
1324 connect(m_programMapper, SIGNAL(mappedString(const QString &)), this,
1325 SLOT(onClickSaveToProgram(const QString &)));
1326
1327 // Rename is valid for all workspace types
1328 menu->addAction(m_rename);
1329 // separate delete
1330 menu->addSeparator();
1331 menu->addAction(m_delete);
1332 }
1333
1334 // Show the menu at the cursor's current position
1335 menu->popup(QCursor::pos());
1336}
1337
1339
1341
1345
1347
1352
1357 // Create a map for the keys and details to go into
1358 std::map<std::string, std::string> programKeysAndDetails;
1359 programKeysAndDetails["name"] = m_programName.toStdString();
1360
1361 // Get a list of the program detail keys (mandatory - target, saveusing)
1362 // (optional - arguments, save parameters, workspace type)
1363 std::vector<std::string> programKeys = (Mantid::Kernel::ConfigService::Instance().getKeys(
1364 ("workspace.sendto." + programKeysAndDetails.find("name")->second)));
1365
1366 for (const auto &programKey : programKeys) {
1367 // Assign a key to its value using the map
1368 programKeysAndDetails[programKey] = (Mantid::Kernel::ConfigService::Instance().getString(
1369 ("workspace.sendto." + programKeysAndDetails.find("name")->second + "." + programKey)));
1370 }
1371
1372 // Check to see if mandatory information is included
1373 if ((programKeysAndDetails.count("name") != 0) && (programKeysAndDetails.count("target") != 0) &&
1374 (programKeysAndDetails.count("saveusing") != 0)) {
1375 std::string expTarget = expandEnvironmentVariables(programKeysAndDetails.find("target")->second);
1376
1377 QFileInfo target(QString::fromStdString(expTarget));
1378 if (target.exists()) {
1379 try {
1380 // Convert to QString and create Algorithm
1381 QString saveUsing = QString::fromStdString(programKeysAndDetails.find("saveusing")->second);
1382
1383 // Create a new save based on what files the new program can open
1384 auto alg = m_mantidDisplayModel->createAlgorithm(saveUsing);
1385
1386 // Get the file extention based on the workspace
1387 Property *prop = alg->getProperty("Filename");
1388 auto *fileProp = dynamic_cast<FileProperty *>(prop);
1389 std::string ext;
1390 if (fileProp) {
1391 ext = fileProp->getDefaultExt();
1392 }
1393
1394 // Save as.. default save + the file type i.e .nxs
1395 alg->setPropertyValue("fileName", "auto_save_" + selectedWsName.toStdString() + ext);
1396
1397 // Save the workspace
1398 alg->setPropertyValue("InputWorkspace", selectedWsName.toStdString());
1399
1400 // If there are any save parameters
1401 if (programKeysAndDetails.count("saveparameters") != 0) {
1402 QString saveParametersGrouped = QString::fromStdString(programKeysAndDetails.find("saveparameters")->second);
1403 QStringList saveParameters = saveParametersGrouped.split(',');
1404
1405 // For each one found split it up and assign the parameter
1406 for (int i = 0; i < saveParameters.size(); i++) {
1407 QStringList sPNameAndDetail = saveParameters[i].split('=');
1408 std::string saveParameterName = sPNameAndDetail[0].trimmed().toStdString();
1409 std::string saveParameterDetail = sPNameAndDetail[1].trimmed().toStdString();
1410 if (saveParameterDetail == "True")
1411 alg->setProperty(saveParameterName, true);
1412 else if (saveParameterDetail == "False")
1413 alg->setProperty(saveParameterName, false);
1414 else // if not true or false then must be a value
1415 {
1416 alg->setPropertyValue(saveParameterName, saveParameterDetail);
1417 }
1418 }
1419 }
1420
1421 // Execute the save
1422 executeAlgorithmAsync(alg, true);
1423
1424 // Get the save location of the file (should be default Mantid folder)
1425 QString savedFile = QString::fromStdString(alg->getProperty("Filename"));
1426 QStringList arguments;
1427
1428 // Arguments for the program to take. Default will be the file anyway.
1429 if (programKeysAndDetails.count("arguments") != 0) {
1430 QString temp = QString::fromStdString(programKeysAndDetails.find("arguments")->second);
1431 temp.replace(QString("[file]"), savedFile);
1432 // temp.replace(QString("[user]"), user;
1433 arguments = temp.split(",");
1434 } else
1435 arguments.insert(0, savedFile);
1436
1437 // convert the list into a standard vector for compatibility with Poco
1438 std::vector<std::string> argumentsV;
1439
1440 for (int i = 0; i < arguments.size(); i++) {
1441 argumentsV.assign(1, (arguments[i].toStdString()));
1442 }
1443
1444 // Execute the program
1445 try {
1446 Mantid::Kernel::ConfigService::Instance().launchProcess(expTarget, argumentsV);
1447 } catch (std::runtime_error &) {
1448 QMessageBox::information(this, "Error",
1449 "User tried to open program from: " + QString::fromStdString(expTarget) +
1450 " There was an error opening the program. "
1451 "Please check the target and arguments list "
1452 "to ensure that these are correct");
1453 }
1454 } catch (std::exception &) {
1455 QMessageBox::information(this, "Mantid - Send to Program",
1456 "A file property wasn't found. Please check that the correct" +
1457 QString("save algorithm was used.\n(View -> Preferences -> "
1458 "Mantid -> SendTo -> Edit -> SaveUsing)"));
1459 }
1460 } else
1461 QMessageBox::information(this, "Target Path Error",
1462 "User tried to open program from: " + QString::fromStdString(expTarget) +
1463 " The target file path for the program "
1464 "can't be found. Please check that the full "
1465 "path is correct");
1466 }
1467}
1468
1470
1474
1478
1482void WorkspaceTreeWidget::plotSpectrum(const std::string &type) {
1483 const bool isAdvanced = type == "Advanced";
1484 const auto userInput = m_tree->chooseSpectrumFromSelected(true, true, true, isAdvanced);
1485 // An empty map will be returned if the user clicks cancel in the spectrum
1486 // selection
1487 if (userInput.plots.empty()) {
1488 return;
1489 }
1490 bool showErrorBars = ((type == "Errors") || (type == "Advanced" && userInput.errors));
1491
1492 // mantidUI knows nothing about userInput, hence the long argument lists.
1493 if (userInput.tiled) {
1494 m_mantidDisplayModel->plotSubplots(userInput.plots, MantidQt::DistributionDefault, showErrorBars);
1495 } else if (userInput.simple || userInput.waterfall) {
1496 if (userInput.isAdvanced) {
1497 const auto advancedUserInput = userInput.advanced.value();
1498 m_mantidDisplayModel->plot1D(userInput.plots, true, MantidQt::DistributionDefault, showErrorBars, nullptr, false,
1499 userInput.waterfall, advancedUserInput.logName, advancedUserInput.customLogValues);
1500 } else {
1501 m_mantidDisplayModel->plot1D(userInput.plots, true, MantidQt::DistributionDefault, showErrorBars, nullptr, false,
1502 userInput.waterfall);
1503 }
1504
1505 } else if (userInput.surface) {
1506 const auto advancedUserInput = userInput.advanced.value();
1507 m_mantidDisplayModel->plotSurface(advancedUserInput.accepted, advancedUserInput.plotIndex,
1508 advancedUserInput.axisName, advancedUserInput.logName,
1509 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1510 } else if (userInput.contour) {
1511 const auto advancedUserInput = userInput.advanced.value();
1512 m_mantidDisplayModel->plotContour(advancedUserInput.accepted, advancedUserInput.plotIndex,
1513 advancedUserInput.axisName, advancedUserInput.logName,
1514 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1515 }
1516}
1517
1521
1528 // Get the selected workspaces
1529 auto items = m_tree->selectedItems();
1530 if (items.empty())
1531 return;
1532
1533 // Extract child workspace names from any WorkspaceGroups selected.
1534 // Use a list to preserve workspace order.
1535 QStringList allWsNames;
1536
1537 for (auto &item : items) {
1538 auto ws = item->data(0, Qt::UserRole).value<Workspace_sptr>();
1539
1540 if (auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws)) {
1541 for (const auto &name : wsGroup->getNames())
1542 allWsNames.append(QString::fromStdString(name));
1543 } else
1544 allWsNames.append(item->text(0));
1545 }
1546
1547 // remove duplicate workspace entries
1548 allWsNames.removeDuplicates();
1549
1551}
1552
1554 switch (e->key()) {
1555 case Qt::Key_Delete:
1556 case Qt::Key_Backspace:
1558 break;
1559 }
1560}
1561
1565
1567 // get selected workspace
1568 auto ws = QString::fromStdString(getSelectedWorkspaceNames()[0]);
1569 const auto *table = m_mantidDisplayModel->createDetectorTable(ws, std::vector<int>(), false);
1570 if (!table) {
1571 QMessageBox::information(this, "Error", QString("Cannot create detectors tables for workspace ") + ws);
1572 }
1573}
1574
1576
1578
1580
1582
1584
1586
1590
1592
1596
1598
1600
1602
1606
1608
1612
1614
1616
1618
1629
1636
1640
1644
1649
1660
1662 m_loadButton->hide();
1663 m_saveButton->hide();
1664 m_deleteButton->hide();
1665 m_clearButton->hide();
1666 m_groupButton->hide();
1667 m_sortButton->hide();
1668}
1669
1670} // namespace MantidQt::MantidWidgets
std::string name
Definition Run.cpp:60
IPeaksWorkspace_sptr workspace
std::map< std::string, Mantid::API::Workspace_sptr > TopLevelItems
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.
QPixmap getIcon(const std::string &workspaceID) const
Returns an icon for the given ID.
virtual void deleteWorkspaces(const QStringList &wsNames=QStringList())=0
virtual bool executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg, const bool wait=false)=0
virtual MultiLayer * plot1D(const QMultiMap< QString, std::set< int > > &toPlot, bool spectrumPlot, MantidQt::DistributionFlag distr=MantidQt::DistributionDefault, bool errs=false, MultiLayer *plotWindow=nullptr, bool clearWindow=false, bool waterfallPlot=false, const QString &log="", const std::set< double > &customLogValues=std::set< double >())=0
virtual void plotSurface(bool accepted, int plotIndex, const QString &axisName, const QString &logName, const std::set< double > &customLogValues, const QList< QString > &workspaceNames)=0
virtual void drawColorFillPlots(const QStringList &wsNames, GraphOptions::CurveType curveType=GraphOptions::ColorMap)=0
virtual MultiLayer * plotSubplots(const QMultiMap< QString, std::set< int > > &toPlot, MantidQt::DistributionFlag distr=MantidQt::DistributionDefault, bool errs=false, MultiLayer *plotWindow=nullptr)=0
virtual void updateRecentFilesList(const QString &fname)=0
virtual Mantid::API::IAlgorithm_sptr createAlgorithm(const QString &algName, int version=-1)=0
virtual void showAlgorithmDialog(const QString &algName, int version=-1)=0
virtual void renameWorkspace(QStringList=QStringList())=0
virtual void enableSaveNexus(const QString &wsName)=0
virtual Table * createDetectorTable(const QString &wsName, const std::vector< int > &indices, bool include_data=false)=0
virtual void plotContour(bool accepted, int plotIndex, const QString &axisName, const QString &logName, const std::set< double > &customLogValues, const QList< QString > &workspaceNames)=0
A class derived from QTreeWidgetItem, to accomodate sorting on the items in a MantidTreeWidget.
MantidWSIndexWidget::UserInput chooseSpectrumFromSelected(bool showWaterfallOpt=true, bool showPlotAll=true, bool showTiledOpt=true, bool isAdvanced=false) const
Allows users to choose spectra from the selected workspaces by presenting them with a dialog box.
void dropEvent(QDropEvent *de) override
Accept a drag drop event and process the data appropriately.
void sort()
Sort the items according to the current sort scheme and order.
void onClickLiveData()
handles Live Data menu trigger
void onClickGroupButton()
Handles group button clicks.
bool shouldBeSelected(const QString &name) const
Check if a workspace should be selected after dock update.
void createWorkspaceMenuActions()
Create the action items associated with the dock.
void addWorkspaceGroupMenuItems(QMenu *menu) const
Add the actions that are appropriate for a WorkspaceGroup.
bool clearWorkspacesConfirmation() const override
Gets confirmation from user that they meant to press clear workspaces button.
void enableClearButton(bool enable) override
Enables and disables the Clear Workspaces Button.
void popupMenu(const QPoint &pos)
Handles display of the workspace context menu.
void saveWorkspaces(const MantidQt::MantidWidgets::StringList &wsNames) override
QRecursiveMutex m_mutex
A mutex to lock m_renameMap and m_selectedNames for reading/writing.
void addPeaksWorkspaceMenuItems(QMenu *menu, const Mantid::API::IPeaksWorkspace_const_sptr &WS) const
Add the actions that are appropriate for a PeaksWorkspace.
void populateTopLevel(const TopLevelItems &topLevelItems, const QStringList &expanded)
Clears the tree and re-populates it with the given top level items.
void addMDHistoWorkspaceMenuItems(QMenu *menu, const Mantid::API::IMDWorkspace_const_sptr &WS) const
void deleteWorkspaces(const MantidQt::MantidWidgets::StringList &wsNames) override
MantidQt::MantidWidgets::WorkspacePresenterVN_sptr m_presenter
void addClearMenuItems(QMenu *menu, const QString &wsName)
Add menu for clearing workspace items.
void signalUpdateTree(const TopLevelItems &)
void createSortMenuActions()
Create actions for sorting.
void filterWorkspaces(const std::string &filterText) override
void onClickClearWorkspaces()
Handles clear button trigger.
void onClickClearUB()
Handler for the clear the UB matrix event.
void setTreeUpdating(const bool state)
Flips the flag indicating whether a tree update is in progress.
void onClickLoad()
Handles Load File menu trigger.
bool askUserYesNo(const std::string &caption, const std::string &message) const override
MantidQt::MantidWidgets::StringList getSelectedWorkspaceNames() const override
Returns the names of the selected workspaces in the dock.
MantidQt::MantidWidgets::MantidItemSortScheme whichCriteria(SortCriteria criteria)
void onClickConvertMDHistoToMatrixWorkspace()
Convert selected MDHistoWorkspace to a MatrixWorkspace.
QHash< QString, QString > m_renameMap
Keep a map of renamed workspaces between updates.
void handleUpdateTree(const TopLevelItems &)
Handle asynchronous tree update.
void saveToProgram() override
Saves a workspace based on the program the user chooses to save to.
void populateChildData(QTreeWidgetItem *item)
When an item is expanded, populate the child data for this item.
void setItemIcon(QTreeWidgetItem *item, const std::string &wsID)
Set tree item's icon based on the ID of the workspace.
void saveWorkspace(const std::string &wsName, SaveFileType type) override
void addMDEventWorkspaceMenuItems(QMenu *menu, const Mantid::API::IMDEventWorkspace_const_sptr &mdeventWS) const
Add the actions that are appropriate for a MDEventWorkspace.
WorkspaceTreeWidget(MantidQt::MantidWidgets::MantidDisplayBase *mdb, bool viewOnly=false, QWidget *parent=nullptr)
void plotSpectrum(const std::string &type) override
Plots one or more spectra from each selected workspace.
void filterWorkspaceTree(const QString &text)
Filter workspaces based on the string provided.
void excludeItemFromSort(MantidTreeWidgetItem *item)
void addTableWorkspaceMenuItems(QMenu *menu) const
Add the actions that are appropriate for a MatrixWorkspace.
void showRenameDialog(const MantidQt::MantidWidgets::StringList &wsNames) override
void recordWorkspaceRename(const std::string &oldName, const std::string &newName) override
Save the old and the new name in m_renameMap.
void addSaveMenuOption(const QString &algorithmString, QString menuEntryName="")
Adds an algorithm to the save menu.
MantidTreeWidgetItem * addTreeEntry(const std::pair< std::string, Mantid::API::Workspace_sptr > &item, QTreeWidgetItem *parent=nullptr)
Adds a node for the given named item, including a single child ID item to make each node have a expan...
MantidQt::MantidWidgets::WorkspacePresenterWN_wptr getPresenterWeakPtr() override
void onClickConvertToMatrixWorkspace()
Convert selected TableWorkspace to a MatrixWorkspace.
void onClickDeleteWorkspaces()
Handles delete button/menu item triggers.
Mantid::API::Workspace_sptr getSelectedWorkspace() const override
Returns a pointer to the selected workspace (the first if multiple workspaces selected)
bool executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg, const bool wait=true) override
Allows asynchronous execution of algorithms.
void sortWorkspaces(SortCriteria criteria, SortDirection direction) override
void dropEvent(QDropEvent *de) override
Accept a drag drop event and process the data appropriately.
void showCriticalUserMessage(const std::string &caption, const std::string &message) const override
void updateTree(const TopLevelItems &items) override
Update the workspace tree to match the current state of the ADS.
QStringList m_selectedNames
Temporarily keeps names of selected workspaces during tree update in order to restore selection after...
void showColourFillPlot() override
Draw a color fill plot of the workspaces that are currently selected.
void addMatrixWorkspaceMenuItems(QMenu *menu, const Mantid::API::MatrixWorkspace_const_sptr &matrixWS) const
Add the actions that are appropriate for a MatrixWorkspace.
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.
Definition Logger.h:51
Base class for properties.
Definition Property.h:94
EXPORT_OPT_MANTIDQT_COMMON QPixmap getQPixmap(const std::string &name)
Function that returns a QPixmap given a string name.
std::vector< std::string > StringList
std::weak_ptr< WorkspaceProviderNotifiable > WorkspacePresenterWN_wptr
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)