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#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
132 ,
133 m_mutex(QMutex::Recursive) // Qt6 uses QRecursiveMutex, default-constructed
134#endif
135{
136 setObjectName("exploreMantid"); // this is needed for QMainWindow::restoreState()
137 m_saveMenu = new QMenu(this);
138
140
142
143 // Dialog box used for user to specify folder to save multiple workspaces into
144 m_saveFolderDialog = new QFileDialog(this);
145 m_saveFolderDialog->setFileMode(QFileDialog::Directory);
146 m_saveFolderDialog->setOption(QFileDialog::ShowDirsOnly);
147
148 // To be able to use them in queued signals they need to be registered
149 static bool registered_addtional_types = false;
150 if (!registered_addtional_types) {
151 registered_addtional_types = true;
152 qRegisterMetaType<TopLevelItems>();
153 }
154
155 // SET UP SORT
158
160
161 m_tree->setDragEnabled(true);
162
163 auto presenter = std::make_shared<WorkspacePresenter>(this);
164 m_presenter = std::dynamic_pointer_cast<ViewNotifiable>(presenter);
165 presenter->init();
166
167 if (m_viewOnly)
169}
170
172
177void WorkspaceTreeWidget::dropEvent(QDropEvent *de) { m_tree->dropEvent(de); }
178
181 m_tree->setHeaderLabel("Workspaces");
182
183 auto *buttonLayout = new FlowLayout();
184 m_loadButton = new QPushButton("Load");
185 m_loadButton->setToolTip("Load a file or live data");
186 m_saveButton = new QPushButton("Save");
187 m_saveButton->setToolTip("Save the selected workspaces");
188 m_deleteButton = new QPushButton("Delete");
189 m_deleteButton->setToolTip("Delete the selected workspaces");
190 m_clearButton = new QPushButton("Clear");
191 m_clearButton->setToolTip("Delete all workspaces");
192 m_groupButton = new QPushButton("Group");
193 m_groupButton->setToolTip("Group together two or more selected workspaces");
194 m_sortButton = new QPushButton("Sort");
195 m_sortButton->setToolTip("Sort all workspaces by name, size, or the last time they were modified");
196
197 m_groupButton->setEnabled(false);
198 m_deleteButton->setEnabled(false);
199 m_clearButton->setEnabled(false);
200 m_saveButton->setEnabled(false);
201
202 buttonLayout->addWidget(m_loadButton);
203 buttonLayout->addWidget(m_deleteButton);
204 buttonLayout->addWidget(m_clearButton);
205 buttonLayout->addWidget(m_groupButton);
206 buttonLayout->addWidget(m_sortButton);
207 buttonLayout->addWidget(m_saveButton);
208
210 m_workspaceFilter->setPlaceholderText("Filter Workspaces");
211 m_workspaceFilter->setToolTip("Type here to filter the workspaces");
212
213 auto *layout = new QVBoxLayout();
214 layout->setContentsMargins(0, 0, 0, 0);
215 layout->addLayout(buttonLayout);
216 layout->addWidget(m_workspaceFilter);
217 layout->addWidget(m_tree);
218 this->setLayout(layout);
219}
220
222 m_loadMenu = new QMenu(this);
223
224 QAction *loadFileAction = new QAction("File", this);
225 QAction *liveDataAction = new QAction("Live Data", this);
226 connect(loadFileAction, SIGNAL(triggered()), this, SLOT(onClickLoad()));
227 connect(liveDataAction, SIGNAL(triggered()), this, SLOT(onClickLiveData()));
228
229 m_loadMenu->addAction(loadFileAction);
230 m_loadMenu->addAction(liveDataAction);
231 m_loadButton->setMenu(m_loadMenu);
232}
233
235 connect(m_workspaceFilter, SIGNAL(textChanged(const QString &)), this, SLOT(filterWorkspaceTree(const QString &)));
236 connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(onClickDeleteWorkspaces()));
237 connect(m_clearButton, SIGNAL(clicked()), this, SLOT(onClickClearWorkspaces()));
238 connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(clickedWorkspace(QTreeWidgetItem *, int)));
239 connect(m_tree, SIGNAL(itemSelectionChanged()), this, SLOT(workspaceSelected()));
240 connect(m_groupButton, SIGNAL(clicked()), this, SLOT(onClickGroupButton()));
241
242 m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
243 connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(popupMenu(const QPoint &)));
244 connect(this, SIGNAL(signalUpdateTree(const TopLevelItems &)), this, SLOT(handleUpdateTree(const TopLevelItems &)),
245 Qt::QueuedConnection);
246
247 connect(this, SIGNAL(signalClearView()), this, SLOT(handleClearView()), Qt::QueuedConnection);
248 connect(m_tree, SIGNAL(itemSelectionChanged()), this, SLOT(onTreeSelectionChanged()));
249 connect(m_tree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(populateChildData(QTreeWidgetItem *)));
250}
251
258void WorkspaceTreeWidget::setTreeUpdating(const bool state) { m_treeUpdating = state; }
259
261
263 return std::dynamic_pointer_cast<WorkspacePresenter>(m_presenter);
264}
265
270 auto items = m_tree->selectedItems();
271 StringList names;
272 names.reserve(static_cast<size_t>(items.size()));
273 std::transform(items.cbegin(), items.cend(), std::back_inserter(names),
274 [](auto const &item) { return item->text(0).toStdString(); });
275
276 return names;
277}
278
280 auto items = m_tree->selectedItems();
281 QStringList names;
282
283 for (auto &item : items) {
284 names.append(item->text(0));
285 }
286 return names;
287}
288
293 auto items = m_tree->selectedItems();
294 auto data = items[0]->data(0, Qt::UserRole).value<Workspace_sptr>();
295
296 return data;
297}
298
299bool WorkspaceTreeWidget::askUserYesNo(const std::string &caption, const std::string &message) const {
300 return QMessageBox::question(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message),
301 QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes;
302}
303
304void WorkspaceTreeWidget::showCriticalUserMessage(const std::string &caption, const std::string &message) const {
305 QMessageBox::critical(parentWidget(), QString::fromStdString(caption), QString::fromStdString(message));
306}
307
309 QObject *sender = QObject::sender();
310 const auto *dlg = reinterpret_cast<MantidQt::API::AlgorithmDialog *>(sender);
311 if (!dlg)
312 return; // should never happen
313
314 QString fn = MantidQt::API::AlgorithmInputHistory::Instance().previousInput("Load", "Filename");
315
317}
318
320 QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel), "showAlgorithmDialog", Qt::QueuedConnection,
321 Q_ARG(QString, "Load"));
322}
323
325 QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel), "showAlgorithmDialog", Qt::QueuedConnection,
326 Q_ARG(QString, "StartLiveData"));
327}
328
330
332 QStringList names;
333
334 for (const auto &ws : wsNames)
335 names.append(QString::fromStdString(ws));
336
338}
339
347void WorkspaceTreeWidget::recordWorkspaceRename(const std::string &oldName, const std::string &newName) {
348 QString qs_oldName = QString::fromStdString(oldName);
349 QString qs_newName = QString::fromStdString(newName);
350
351 QMutexLocker renameMapLock(&m_mutex);
352 // check if old_name has been recently a new name
353 QList<QString> oldNames = m_renameMap.keys(qs_oldName);
354 // non-empty list of oldNames become new_name
355 if (!oldNames.isEmpty()) {
356 for (const auto &name : oldNames)
357 m_renameMap[name] = qs_newName;
358 } else {
359 // record a new rename pair
360 m_renameMap[qs_oldName] = qs_newName;
361 }
362}
363
365
367
369
371 return askUserYesNo("Delete Workspaces", "Are you sure you want to delete the selected Workspaces?\n\nThis prompt "
372 "can be disabled from:\nFile->Settings->General");
373}
374
376 QStringList names;
377 for (const auto &ws : wsNames)
378 names.append(QString::fromStdString(ws));
380}
381
383
388
393
398
403
408
410 static int counter = 1;
411
412 item->setSortPos(counter);
413
414 counter++;
415}
416
418
420
422 if (isTreeUpdating())
423 return;
425 m_tree->setSortOrder(direction == SortDirection::Ascending ? Qt::AscendingOrder : Qt::DescendingOrder);
426 m_tree->sort();
427}
428
430 switch (criteria) {
437 default:
438 // Handle if someone adds a new Enum and it falls through by defaulting to
439 // name
441 }
442}
443
447
449 const QAction *sendingAction = dynamic_cast<QAction *>(sender());
450 if (!sendingAction)
451 return;
452
453 QString actionName = sendingAction->text();
454
455 if (actionName.compare("Nexus") == 0)
457 else if (actionName.compare("ASCII") == 0)
459
460 auto selectedNames = getSelectedWorkspaceNames();
461
462 if (selectedNames.size() > 1) {
463 // Save multiple workspaces
464 saveWorkspaces(selectedNames);
465 } else if (selectedNames.size() == 1) {
466 // Save single workspace
468 }
469}
470
472
473void WorkspaceTreeWidget::saveWorkspace(const std::string &wsName, SaveFileType type) {
475 if (!wsName.empty()) {
476 presets["InputWorkspace"] = QString::fromStdString(wsName);
477 }
478 int version = -1;
479 std::string algorithmName;
480
481 switch (type) {
483 algorithmName = "SaveNexus";
484 break;
486 algorithmName = "SaveAscii";
487 break;
488 }
489
490 m_mantidDisplayModel->showAlgorithmDialog(QString::fromStdString(algorithmName), presets, nullptr, version);
491}
492
494 QList<QTreeWidgetItem *> items = m_tree->selectedItems();
495 if (items.size() < 2)
496 return;
497
498 m_saveFolderDialog->setWindowTitle("Select save folder");
499 m_saveFolderDialog->setLabelText(QFileDialog::Accept, "Select");
500
501 auto res = m_saveFolderDialog->exec();
502 if (res != QFileDialog::Accepted)
503 return;
504
505 auto folder = m_saveFolderDialog->selectedFiles()[0].toStdString();
506
507 std::string algorithmName;
508 std::string fileExtension;
509
510 switch (m_saveFileType) {
512 algorithmName = "SaveAscii";
513 fileExtension = ".dat";
514 break;
516 default:
517 algorithmName = "SaveNexus";
518 fileExtension = ".nxs";
519 break;
520 }
521
522 IAlgorithm_sptr saveAlg = AlgorithmManager::Instance().create(algorithmName);
523 saveAlg->initialize();
524
525 for (auto &wsName : wsNames) {
526 std::string filename = folder + "/" + wsName + fileExtension;
527 try {
528 saveAlg->setProperty("InputWorkspace", wsName);
529 saveAlg->setProperty("Filename", filename);
530 saveAlg->execute();
531 } catch (std::exception &ex) {
532 docklog.error() << "Error saving workspace " << wsName << ": " << ex.what() << '\n';
533 }
534 }
535}
536
537std::string WorkspaceTreeWidget::getFilterText() const { return m_workspaceFilter->text().toStdString(); }
538
539void WorkspaceTreeWidget::filterWorkspaces(const std::string &filterText) {
540 const QString text = QString::fromStdString(filterText).trimmed();
541 QRegularExpression filterRegEx(text, QRegularExpression::CaseInsensitiveOption);
542
543 // show all items
544 QTreeWidgetItemIterator unhideIter(m_tree);
545 while (*unhideIter) {
546 (*unhideIter)->setHidden(false);
547 ++unhideIter;
548 }
549
550 int hiddenCount = 0;
551 if (!text.isEmpty()) {
552 QList<QTreeWidgetItem *> visibleGroups;
553 // Loop over everything (currently loaded) and top level
554 // find out what is already expanded
555 QStringList expanded;
556 int n = m_tree->topLevelItemCount();
557 for (int i = 0; i < n; ++i) {
558 auto item = m_tree->topLevelItem(i);
559 if (item->isExpanded()) {
560 expanded << item->text(0);
561 } else {
562 // expand everything that is at the top level (as we lazy load this is
563 // required)
564 item->setExpanded(true);
565 }
566 }
567
568 // filter based on the string
569 QTreeWidgetItemIterator it(m_tree, QTreeWidgetItemIterator::All);
570 while (*it) {
571 QTreeWidgetItem *item = (*it);
572 QVariant userData = item->data(0, Qt::UserRole);
573
574 if (!userData.isNull()) {
575 Workspace_sptr workspace = userData.value<Workspace_sptr>();
576 if (workspace) {
577 // I am a workspace
578 if (item->text(0).contains(filterRegEx)) {
579 // my name does match the filter
580 if (workspace->isGroup()) {
581 // I am a group, I will want my children to be visible
582 // but I cannot do that until this iterator has finished
583 // store this pointer in a list for processing later
584 visibleGroups.append(item);
585 item->setHidden(false);
586 }
587
588 if (item->parent() == nullptr) {
589 // No parent, I am a top level workspace - show me
590 item->setHidden(false);
591 } else {
592 // I am a child workspace of a group
593 // I match, so I want my parent to remain visible as well.
594 item->setHidden(false);
595 if (item->parent()->isHidden()) {
596 // I was previously hidden, show me and set to be expanded
597 --hiddenCount;
598 item->parent()->setHidden(false);
599 expanded << item->parent()->text(0);
600 }
601 }
602 } else {
603 // my name does not match the filter - hide me
604 item->setHidden(true);
605 ++hiddenCount;
606 }
607 }
608 }
609 ++it;
610 }
611
612 // make children of visible groups visible
613 for (auto group : visibleGroups) {
614 for (int i = 0; i < group->childCount(); i++) {
615 QTreeWidgetItem *child = group->child(i);
616 if (child->isHidden()) {
617 // I was previously hidden, show me
618 --hiddenCount;
619 child->setHidden(false);
620 }
621 }
622 }
623
624 // set the expanded state
625 for (int i = 0; i < n; ++i) {
626 auto item = m_tree->topLevelItem(i);
627 item->setExpanded(expanded.contains(item->text(0)));
628 }
629 }
630
631 // display a message if items are hidden
632 if (hiddenCount > 0) {
633 QString headerString = QString("Workspaces (%1 filtered)").arg(QString::number(hiddenCount));
634 m_tree->headerItem()->setText(0, headerString);
635 } else {
636 m_tree->headerItem()->setText(0, "Workspaces");
637 }
638}
639
645void WorkspaceTreeWidget::setItemIcon(QTreeWidgetItem *item, const std::string &wsID) {
646 try {
647 item->setIcon(0, QIcon(WORKSPACE_ICONS.getIcon(wsID)));
648 } catch (std::runtime_error &) {
649 docklog.warning() << "Cannot find icon for workspace ID '" << wsID << "'\n";
650 }
651}
652
657 m_showData = new QAction(tr("Show Data"), this);
658 connect(m_showData, SIGNAL(triggered()), this, SLOT(onClickShowData()));
659
660 m_showInst = new QAction(tr("Show Instrument"), this);
661 connect(m_showInst, SIGNAL(triggered()), this, SLOT(onClickShowInstrument()));
662
663 m_plotSpec = new QAction(tr("Plot Spectrum..."), this);
664 connect(m_plotSpec, SIGNAL(triggered()), this, SLOT(onClickPlotSpectra()));
665
666 m_plotSpecErr = new QAction(tr("Plot Spectrum with Errors..."), this);
667 connect(m_plotSpecErr, SIGNAL(triggered()), this, SLOT(onClickPlotSpectraErr()));
668
669 m_plotAdvanced = new QAction(tr("Plot Advanced..."), this);
670 connect(m_plotAdvanced, SIGNAL(triggered()), this, SLOT(onClickPlotAdvanced()));
671
672 m_colorFill = new QAction(tr("Color Fill Plot"), this);
673 connect(m_colorFill, SIGNAL(triggered()), this, SLOT(onClickDrawColorFillPlot()));
674
675 m_showDetectors = new QAction(tr("Show Detectors"), this);
676 connect(m_showDetectors, SIGNAL(triggered()), this, SLOT(onClickShowDetectorTable()));
677
678 m_showBoxData = new QAction(tr("Show Box Data Table"), this);
679 connect(m_showBoxData, SIGNAL(triggered()), this, SLOT(onClickShowBoxData()));
680
681 m_showMDPlot = new QAction(tr("Plot MD"), this);
682 connect(m_showMDPlot, SIGNAL(triggered()), this, SLOT(onClickShowMDPlot()));
683
684 m_showListData = new QAction(tr("List Data"), this);
685 connect(m_showListData, SIGNAL(triggered()), this, SLOT(onClickShowListData()));
686
687 m_showSpectrumViewer = new QAction(tr("Show Spectrum Viewer"), this);
688 connect(m_showSpectrumViewer, SIGNAL(triggered()), this, SLOT(onClickShowSpectrumViewer()));
689
690 m_showSliceViewer = new QAction(tr("Show Slice Viewer"), this);
691 {
692 QIcon icon;
693 icon.addFile(QString::fromUtf8(":/SliceViewer/icons/SliceViewerWindow_icon.png"), QSize(), QIcon::Normal,
694 QIcon::Off);
695 m_showSliceViewer->setIcon(icon);
696 }
697 connect(m_showSliceViewer, SIGNAL(triggered()), this, SLOT(onClickShowSliceViewer()));
698
699 m_showLogs = new QAction(tr("Sample Logs..."), this);
700 connect(m_showLogs, SIGNAL(triggered()), this, SLOT(onClickShowFileLog()));
701
702 m_showSampleMaterial = new QAction(tr("Sample Material..."), this);
703 connect(m_showSampleMaterial, SIGNAL(triggered()), this, SLOT(onClickShowSampleMaterial()));
704
705 m_showHist = new QAction(tr("Show History"), this);
706 connect(m_showHist, SIGNAL(triggered()), this, SLOT(onClickShowAlgHistory()));
707
708 m_saveNexus = new QAction(tr("Save NeXus"), this);
709 connect(m_saveNexus, SIGNAL(triggered()), this, SLOT(onClickSaveNexusWorkspace()));
710
711 m_rename = new QAction(tr("Rename"), this);
712 connect(m_rename, SIGNAL(triggered()), this, SLOT(renameWorkspace()));
713
714 m_delete = new QAction(tr("Delete"), this);
715 connect(m_delete, SIGNAL(triggered()), this, SLOT(onClickDeleteWorkspaces()));
716
717 m_showTransposed = new QAction(tr("Show Transposed"), this);
718 connect(m_showTransposed, SIGNAL(triggered()), this, SLOT(onClickShowTransposed()));
719
720 m_convertToMatrixWorkspace = new QAction(tr("Convert to MatrixWorkspace"), this);
721 m_convertToMatrixWorkspace->setIcon(QIcon(getQPixmap("mantid_matrix_xpm")));
722 connect(m_convertToMatrixWorkspace, SIGNAL(triggered()), this, SLOT(onClickConvertToMatrixWorkspace()));
723
724 m_convertMDHistoToMatrixWorkspace = new QAction(tr("Convert to MatrixWorkspace"), this);
725 m_convertMDHistoToMatrixWorkspace->setIcon(QIcon(getQPixmap("mantid_matrix_xpm")));
726 connect(m_convertMDHistoToMatrixWorkspace, SIGNAL(triggered()), this, SLOT(onClickConvertMDHistoToMatrixWorkspace()));
727
728 m_clearUB = new QAction(tr("Clear UB Matrix"), this);
729 connect(m_clearUB, SIGNAL(triggered()), this, SLOT(onClickClearUB()));
730}
731
737 QMenu *sortMenu = new QMenu(this);
738
739 QAction *ascendingSortAction = new QAction("Ascending", this);
740 QAction *descendingSortAction = new QAction("Descending", this);
741 QAction *byNameChoice = new QAction("Name", this);
742 QAction *byLastModifiedChoice = new QAction("Last Modified", this);
743 QAction *byMemorySize = new QAction("Size", this);
744
745 ascendingSortAction->setCheckable(true);
746 ascendingSortAction->setEnabled(true);
747
748 descendingSortAction->setCheckable(true);
749 descendingSortAction->setEnabled(true);
750
751 QActionGroup *sortDirectionGroup = new QActionGroup(sortMenu);
752 sortDirectionGroup->addAction(ascendingSortAction);
753 sortDirectionGroup->addAction(descendingSortAction);
754 sortDirectionGroup->setExclusive(true);
755 ascendingSortAction->setChecked(true);
756
757 byNameChoice->setCheckable(true);
758 byNameChoice->setEnabled(true);
759
760 byLastModifiedChoice->setCheckable(true);
761 byLastModifiedChoice->setEnabled(true);
762
763 byMemorySize->setCheckable(true);
764 byMemorySize->setEnabled(true);
765
766 QActionGroup *sortChoiceGroup = new QActionGroup(sortMenu);
767 sortChoiceGroup->addAction(byNameChoice);
768 sortChoiceGroup->addAction(byLastModifiedChoice);
769 sortChoiceGroup->addAction(byMemorySize);
770 sortChoiceGroup->setExclusive(true);
771 byNameChoice->setChecked(true);
772
773 connect(ascendingSortAction, SIGNAL(triggered()), this, SLOT(sortAscending()));
774 connect(descendingSortAction, SIGNAL(triggered()), this, SLOT(sortDescending()));
775 connect(byNameChoice, SIGNAL(triggered()), this, SLOT(chooseByName()));
776 connect(byLastModifiedChoice, SIGNAL(triggered()), this, SLOT(chooseByLastModified()));
777 connect(byMemorySize, SIGNAL(triggered()), this, SLOT(chooseByMemorySize()));
778
779 sortMenu->addActions(sortDirectionGroup->actions());
780 sortMenu->addSeparator();
781 sortMenu->addActions(sortChoiceGroup->actions());
782 m_sortButton->setMenu(sortMenu);
783}
784
789void WorkspaceTreeWidget::populateChildData(QTreeWidgetItem *item) {
790 QVariant userData = item->data(0, Qt::UserRole);
791 if (userData.isNull())
792 return;
793
794 // Clear it first
795 while (item->childCount() > 0) {
796 auto *widgetItem = item->takeChild(0);
797 delete widgetItem;
798 }
799
800 Workspace_sptr workspace = userData.value<Workspace_sptr>();
801
802 if (auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace)) {
803 auto members = group->getAllItems();
804 auto visibleNames = AnalysisDataService::Instance().getObjectNames();
805 for (const auto &ws : members) {
806 if (std::find(visibleNames.begin(), visibleNames.end(), ws->getName()) != visibleNames.end()) {
807 auto *node = addTreeEntry(std::make_pair(ws->getName(), ws), item);
809 if (shouldBeSelected(node->text(0)))
810 node->setSelected(true);
811 }
812 }
813 } else {
814 QString details;
815 try {
816 details = workspace->toString().c_str();
817 } catch (std::runtime_error &e) {
818 details = QString("Error: %1").arg(e.what());
819 }
820 QStringList rows = details.split(QLatin1Char('\n'), Qt::SkipEmptyParts);
821 rows.append(QString("Memory used: ") + workspace->getMemorySizeAsStr().c_str());
822
823 auto iend = rows.constEnd();
824 for (auto itr = rows.constBegin(); itr != iend; ++itr) {
825 MantidTreeWidgetItem *data = new MantidTreeWidgetItem(QStringList(*itr), m_tree);
826 data->setFlags(Qt::NoItemFlags);
828 item->addChild(data);
829 }
830 }
831}
832
842
848void WorkspaceTreeWidget::populateTopLevel(const TopLevelItems &topLevelItems, const QStringList &expanded) {
849 {
850 QMutexLocker lock(&m_mutex);
851 // collect names of selected workspaces
852 QList<QTreeWidgetItem *> selected = m_tree->selectedItems();
853 m_selectedNames.clear(); // just in case
854 foreach (QTreeWidgetItem *item, selected) {
855 m_selectedNames << item->text(0);
856 }
857
858 // populate the tree from scratch
859 m_tree->clear();
860 auto iend = topLevelItems.end();
861 for (auto it = topLevelItems.begin(); it != iend; ++it) {
862 auto *node = addTreeEntry(*it);
863 QString name = node->text(0);
864 if (expanded.contains(name))
865 node->setExpanded(true);
866 // see if item must be selected
868 node->setSelected(true);
869 }
870
871 m_selectedNames.clear();
872 m_renameMap.clear();
873 }
874 // apply any filtering
876}
877
885MantidTreeWidgetItem *WorkspaceTreeWidget::addTreeEntry(const std::pair<std::string, Mantid::API::Workspace_sptr> &item,
886 QTreeWidgetItem *parent) {
887 MantidTreeWidgetItem *node = new MantidTreeWidgetItem(QStringList(item.first.c_str()), m_tree);
888 node->setData(0, Qt::UserRole, QVariant::fromValue(item.second));
889
890 // A a child ID item so that it becomes expandable. Using the correct ID is
891 // needed when plotting from non-expanded groups.
892 const std::string wsID = item.second->id();
893 auto *idNode = new MantidTreeWidgetItem(QStringList(wsID.c_str()), m_tree);
894 idNode->setFlags(Qt::NoItemFlags);
895 node->addChild(idNode);
896 setItemIcon(node, wsID);
897
898 if (parent) {
899 parent->addChild(node);
900 } else {
901 m_tree->addTopLevelItem(node);
902 }
903 return node;
904}
905
910bool WorkspaceTreeWidget::shouldBeSelected(const QString &name) const {
911 QMutexLocker lock(&m_mutex);
912 QStringList renamed = m_renameMap.keys(name);
913 if (!renamed.isEmpty()) {
914 return std::any_of(renamed.cbegin(), renamed.cend(),
915 [&](const auto &oldName) { return m_selectedNames.contains(oldName); });
916 } else if (m_selectedNames.contains(name)) {
917 return true;
918 }
919 return false;
920}
921
923 // get selected workspaces
924 auto items = m_tree->selectedItems();
925
926 if (m_groupButton) {
927 if (items.size() == 1) {
928 // check it's group
929 auto wsSptr = items.first()->data(0, Qt::UserRole).value<Workspace_sptr>();
930 auto grpSptr = std::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
931 if (grpSptr) {
932 m_groupButton->setText("Ungroup");
933 m_groupButton->setToolTip("Ungroup selected workspace");
934 m_groupButton->setEnabled(true);
935 } else
936 m_groupButton->setEnabled(false);
937
938 } else if (items.size() >= 2) {
939 m_groupButton->setText("Group");
940 m_groupButton->setEnabled(true);
941 m_groupButton->setToolTip("Group together two or more selected workspaces");
942 } else if (items.size() == 0) {
943 m_groupButton->setText("Group");
944 m_groupButton->setEnabled(false);
945 m_groupButton->setToolTip("Group together two or more selected workspaces");
946 }
947 }
948
949 if (m_deleteButton)
950 m_deleteButton->setEnabled(items.size() > 0);
951
952 if (m_saveButton)
953 m_saveButton->setEnabled(items.size() > 0);
954
955 if (items.size() > 0) {
956 auto item = *(items.begin());
958 } else {
960 }
961}
962
969 const Mantid::API::MatrixWorkspace_const_sptr &matrixWS) const {
970 // Add all options except plot of we only have 1 value
971 menu->addAction(m_showData);
972 menu->addAction(m_showInst);
973 // Disable the 'show instrument' option if a workspace doesn't have an
974 // instrument attached or if it does not have a spectra axis
975 m_showInst->setEnabled(matrixWS->getInstrument() && !matrixWS->getInstrument()->getName().empty() &&
976 matrixWS->getAxis(1)->isSpectra());
977 menu->addSeparator();
978 menu->addAction(m_plotSpec);
979 menu->addAction(m_plotSpecErr);
980 menu->addAction(m_plotAdvanced);
981
982 // Don't plot a spectrum if only one X value
983 bool multipleBins = false;
984 try {
985 multipleBins = (matrixWS->blocksize() > 1);
986 } catch (...) {
987 const size_t numHist = matrixWS->getNumberHistograms();
988 for (size_t i = 0; i < numHist; ++i) {
989 if (matrixWS->y(i).size() > 1) {
990 multipleBins = true;
991 break;
992 }
993 }
994 }
995 m_plotSpec->setEnabled(multipleBins);
996 m_plotSpecErr->setEnabled(multipleBins);
997 m_plotAdvanced->setEnabled(multipleBins);
998
999 menu->addAction(m_showSpectrumViewer); // The 2D spectrum viewer
1000
1001 menu->addAction(m_colorFill);
1002 // Show the color fill plot if you have more than one histogram
1003 m_colorFill->setEnabled((matrixWS->axes() > 1 && matrixWS->getNumberHistograms() > 1));
1004 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1005 menu->addSeparator();
1006 menu->addAction(m_showDetectors);
1007 menu->addAction(m_showLogs);
1008 menu->addAction(m_showSampleMaterial);
1009 menu->addAction(m_showHist);
1010 menu->addAction(m_saveNexus);
1011}
1012
1020 Q_UNUSED(WS);
1021
1022 // menu->addAction(m_showBoxData); // Show MD Box data (for debugging only)
1023 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1024 menu->addAction(m_showHist); // Algorithm history
1025 menu->addAction(m_showListData); // Show data in table
1026 menu->addAction(m_showLogs);
1027}
1028
1030 const Mantid::API::IMDWorkspace_const_sptr &WS) const {
1031 Q_UNUSED(WS);
1032 menu->addAction(m_showHist); // Algorithm history
1033 menu->addAction(m_showSliceViewer); // The 2D slice viewer
1034 menu->addAction(m_showMDPlot); // A plot of intensity vs bins
1035 menu->addAction(m_showListData); // Show data in table
1036 menu->addAction(m_convertMDHistoToMatrixWorkspace);
1037 menu->addAction(m_showLogs);
1038}
1039
1046 Q_UNUSED(WS);
1047 menu->addAction(m_showData);
1048 menu->addSeparator();
1049 menu->addAction(m_showDetectors);
1050 menu->addAction(m_showHist);
1051}
1052
1058 m_plotSpec->setEnabled(true);
1059 menu->addAction(m_plotSpec);
1060 m_plotSpecErr->setEnabled(true);
1061 menu->addAction(m_plotSpecErr);
1062 m_plotAdvanced->setEnabled(true);
1063 menu->addAction(m_plotAdvanced);
1064 menu->addAction(m_colorFill);
1065 m_colorFill->setEnabled(true);
1066
1067 menu->addSeparator();
1068 menu->addAction(m_saveNexus);
1069}
1070
1076 menu->addAction(m_showData);
1077 menu->addAction(m_showTransposed);
1078 menu->addAction(m_showHist);
1079 menu->addAction(m_saveNexus);
1080 menu->addAction(m_convertToMatrixWorkspace);
1081}
1082
1088void WorkspaceTreeWidget::addClearMenuItems(QMenu *menu, const QString &wsName) {
1089 QMenu *clearMenu = new QMenu(tr("Clear Options"), this);
1090
1091 m_clearUB->setEnabled(hasUBMatrix(wsName.toStdString()));
1092
1093 clearMenu->addAction(m_clearUB);
1094 menu->addMenu(clearMenu);
1095}
1096
1097bool WorkspaceTreeWidget::hasUBMatrix(const std::string &wsName) {
1098 bool hasUB = false;
1099 Workspace_sptr ws = AnalysisDataService::Instance().retrieve(wsName);
1100 IMDWorkspace_sptr wsIMD = std::dynamic_pointer_cast<IMDWorkspace>(ws);
1101 if (ws && wsIMD) {
1102 hasUB = wsIMD->hasOrientedLattice();
1103 }
1104 return hasUB;
1105}
1106
1114void WorkspaceTreeWidget::addSaveMenuOption(const QString &algorithmString, QString menuEntryName) {
1115 // Default to algo string if no entry name given
1116 if (menuEntryName.isEmpty())
1117 menuEntryName = algorithmString;
1118
1119 // Create the action and add data
1120 QAction *saveAction = new QAction(menuEntryName, this);
1121 saveAction->setData(QVariant(algorithmString));
1122
1123 // Connect the trigger slot to show algorithm dialog
1124 connect(saveAction, SIGNAL(triggered()), this, SLOT(handleShowSaveAlgorithm()));
1125
1126 // Add it to the menu
1127 m_saveMenu->addAction(saveAction);
1128}
1129
1135 m_filteredText = text.toStdString();
1137}
1138
1143
1149 return askUserYesNo("Clear Workspaces", "This will delete all the workspaces, are you sure?");
1150}
1151
1156void WorkspaceTreeWidget::enableClearButton(bool enable) { m_clearButton->setEnabled(enable); }
1157
1162
1163void WorkspaceTreeWidget::clickedWorkspace(QTreeWidgetItem *item, int /*unused*/) { Q_UNUSED(item); }
1164
1166 auto selectedNames = getSelectedWorkspaceNames();
1167 if (selectedNames.empty())
1168 return;
1169
1170 // Remove all existing save algorithms from list
1171 m_saveMenu->clear();
1172
1173 addSaveMenuOption("SaveNexus", "Nexus");
1174 addSaveMenuOption("SaveAscii", "ASCII");
1175
1176 m_saveButton->setMenu(m_saveMenu);
1177}
1178
1181 if (m_groupButton) {
1182 QString qButtonName = m_groupButton->text();
1183 if (qButtonName == "Group") {
1185 } else if (qButtonName == "Ungroup") {
1187 }
1188 }
1189}
1190
1193
1198
1199// Asynchronous signal handlers
1203 // do not update until the counter is zero
1204 if (m_updateCount.deref())
1205 return;
1206
1207 // find all expanded top-level entries
1208 QStringList expanded;
1209 int n = m_tree->topLevelItemCount();
1210 for (int i = 0; i < n; ++i) {
1211 auto item = m_tree->topLevelItem(i);
1212 if (item->isExpanded()) {
1213 expanded << item->text(0);
1214 }
1215 }
1216
1217 // create a new tree
1218 setTreeUpdating(true);
1219 populateTopLevel(items, expanded);
1220 setTreeUpdating(false);
1221
1222 // enable clear button here if any items in tree
1223 enableClearButton(!items.empty());
1224
1225 // Re-sort
1226 m_tree->sort();
1227}
1228
1233
1234// Context Menu Methods
1235
1237void WorkspaceTreeWidget::popupMenu(const QPoint &pos) {
1238 if (!m_viewOnly) {
1239 m_menuPosition = pos;
1241 }
1242}
1243
1245 QTreeWidgetItem *treeItem = m_tree->itemAt(m_menuPosition);
1246 selectedWsName = "";
1247 if (treeItem)
1248 selectedWsName = treeItem->text(0);
1249 else
1250 m_tree->selectionModel()->clear();
1251
1252 QMenu *menu(nullptr);
1253
1254 // If no workspace is here then have load raw and dae
1255 if (selectedWsName.isEmpty())
1256 menu = m_loadMenu;
1257 else { // else show instrument, sample logs and delete
1258 // Fresh menu
1259 menu = new QMenu(this);
1260 menu->setObjectName("WorkspaceContextMenu");
1261 auto mantidTreeItem = dynamic_cast<MantidTreeWidgetItem *>(treeItem);
1262 auto ws = mantidTreeItem->data(0, Qt::UserRole).value<Mantid::API::Workspace_sptr>();
1263
1264 // Add the items that are appropriate for the type
1265 if (auto matrixWS = std::dynamic_pointer_cast<const Mantid::API::MatrixWorkspace>(ws)) {
1266 addMatrixWorkspaceMenuItems(menu, matrixWS);
1267 } else if (auto mdeventWS = std::dynamic_pointer_cast<const IMDEventWorkspace>(ws)) {
1268 addMDEventWorkspaceMenuItems(menu, mdeventWS);
1269 } else if (auto mdWS = std::dynamic_pointer_cast<const IMDWorkspace>(ws)) {
1270 addMDHistoWorkspaceMenuItems(menu, mdWS);
1271 } else if (auto peaksWS = std::dynamic_pointer_cast<const IPeaksWorkspace>(ws)) {
1272 addPeaksWorkspaceMenuItems(menu, peaksWS);
1273 } else if (auto groupWS = std::dynamic_pointer_cast<const WorkspaceGroup>(ws)) {
1275 } else if (std::dynamic_pointer_cast<const Mantid::API::ITableWorkspace>(ws)) {
1277 } else {
1278 // None of the above? -> not a workspace
1279 return;
1280 }
1282
1283 // Get the names of the programs for the send to option
1284 std::vector<std::string> programNames =
1285 (Mantid::Kernel::ConfigService::Instance().getKeys("workspace.sendto.name"));
1286 bool firstPass(true);
1287 // Check to see if any options aren't visible
1288 for (const auto &programName : programNames) {
1289 std::string visible =
1290 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".visible");
1291 std::string target =
1292 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".target");
1293 if (Mantid::Kernel::ConfigService::Instance().isExecutable(target) && visible == "Yes") {
1294 bool compatible(true);
1295 std::string saveUsing(
1296 Mantid::Kernel::ConfigService::Instance().getString("workspace.sendto." + programName + ".saveusing"));
1297 try {
1298 Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create(saveUsing);
1299 alg->setPropertyValue("InputWorkspace", selectedWsName.toStdString());
1300 } catch (std::exception &) {
1301 compatible = false;
1302 }
1303 if (compatible) {
1304 if (firstPass) {
1305 m_saveToProgram = new QMenu(tr("Send to"), this);
1306 menu->addMenu(m_saveToProgram);
1307
1308 // Sub-menu for program list
1309 m_programMapper = new QSignalMapper(this);
1310 }
1311 QString name = QString::fromStdString(programName);
1312 // Setup new menu option for the program
1313 m_program = new QAction(name, this);
1314 connect(m_program, SIGNAL(triggered()), m_programMapper, SLOT(map()));
1315 // Send name of program when clicked
1316 m_programMapper->setMapping(m_program, name);
1317 m_saveToProgram->addAction(m_program);
1318
1319 // Set first pass to false so that it doesn't set up another menu
1320 // entry for all programs.
1321 firstPass = false;
1322 }
1323 }
1324 }
1325
1326 // Tell the button what to listen for and what to do once clicked (if there
1327 // is anything to connect it will be set to false)
1328 if (!firstPass)
1329 connect(m_programMapper, SIGNAL(mappedString(const QString &)), this,
1330 SLOT(onClickSaveToProgram(const QString &)));
1331
1332 // Rename is valid for all workspace types
1333 menu->addAction(m_rename);
1334 // separate delete
1335 menu->addSeparator();
1336 menu->addAction(m_delete);
1337 }
1338
1339 // Show the menu at the cursor's current position
1340 menu->popup(QCursor::pos());
1341}
1342
1344
1346
1350
1352
1357
1362 // Create a map for the keys and details to go into
1363 std::map<std::string, std::string> programKeysAndDetails;
1364 programKeysAndDetails["name"] = m_programName.toStdString();
1365
1366 // Get a list of the program detail keys (mandatory - target, saveusing)
1367 // (optional - arguments, save parameters, workspace type)
1368 std::vector<std::string> programKeys = (Mantid::Kernel::ConfigService::Instance().getKeys(
1369 ("workspace.sendto." + programKeysAndDetails.find("name")->second)));
1370
1371 for (const auto &programKey : programKeys) {
1372 // Assign a key to its value using the map
1373 programKeysAndDetails[programKey] = (Mantid::Kernel::ConfigService::Instance().getString(
1374 ("workspace.sendto." + programKeysAndDetails.find("name")->second + "." + programKey)));
1375 }
1376
1377 // Check to see if mandatory information is included
1378 if ((programKeysAndDetails.count("name") != 0) && (programKeysAndDetails.count("target") != 0) &&
1379 (programKeysAndDetails.count("saveusing") != 0)) {
1380 std::string expTarget = expandEnvironmentVariables(programKeysAndDetails.find("target")->second);
1381
1382 QFileInfo target(QString::fromStdString(expTarget));
1383 if (target.exists()) {
1384 try {
1385 // Convert to QString and create Algorithm
1386 QString saveUsing = QString::fromStdString(programKeysAndDetails.find("saveusing")->second);
1387
1388 // Create a new save based on what files the new program can open
1389 auto alg = m_mantidDisplayModel->createAlgorithm(saveUsing);
1390
1391 // Get the file extention based on the workspace
1392 Property *prop = alg->getProperty("Filename");
1393 auto *fileProp = dynamic_cast<FileProperty *>(prop);
1394 std::string ext;
1395 if (fileProp) {
1396 ext = fileProp->getDefaultExt();
1397 }
1398
1399 // Save as.. default save + the file type i.e .nxs
1400 alg->setPropertyValue("fileName", "auto_save_" + selectedWsName.toStdString() + ext);
1401
1402 // Save the workspace
1403 alg->setPropertyValue("InputWorkspace", selectedWsName.toStdString());
1404
1405 // If there are any save parameters
1406 if (programKeysAndDetails.count("saveparameters") != 0) {
1407 QString saveParametersGrouped = QString::fromStdString(programKeysAndDetails.find("saveparameters")->second);
1408 QStringList saveParameters = saveParametersGrouped.split(',');
1409
1410 // For each one found split it up and assign the parameter
1411 for (int i = 0; i < saveParameters.size(); i++) {
1412 QStringList sPNameAndDetail = saveParameters[i].split('=');
1413 std::string saveParameterName = sPNameAndDetail[0].trimmed().toStdString();
1414 std::string saveParameterDetail = sPNameAndDetail[1].trimmed().toStdString();
1415 if (saveParameterDetail == "True")
1416 alg->setProperty(saveParameterName, true);
1417 else if (saveParameterDetail == "False")
1418 alg->setProperty(saveParameterName, false);
1419 else // if not true or false then must be a value
1420 {
1421 alg->setPropertyValue(saveParameterName, saveParameterDetail);
1422 }
1423 }
1424 }
1425
1426 // Execute the save
1427 executeAlgorithmAsync(alg, true);
1428
1429 // Get the save location of the file (should be default Mantid folder)
1430 QString savedFile = QString::fromStdString(alg->getProperty("Filename"));
1431 QStringList arguments;
1432
1433 // Arguments for the program to take. Default will be the file anyway.
1434 if (programKeysAndDetails.count("arguments") != 0) {
1435 QString temp = QString::fromStdString(programKeysAndDetails.find("arguments")->second);
1436 temp.replace(QString("[file]"), savedFile);
1437 // temp.replace(QString("[user]"), user;
1438 arguments = temp.split(",");
1439 } else
1440 arguments.insert(0, savedFile);
1441
1442 // convert the list into a standard vector for compatibility with Poco
1443 std::vector<std::string> argumentsV;
1444
1445 for (int i = 0; i < arguments.size(); i++) {
1446 argumentsV.assign(1, (arguments[i].toStdString()));
1447 }
1448
1449 // Execute the program
1450 try {
1451 Mantid::Kernel::ConfigService::Instance().launchProcess(expTarget, argumentsV);
1452 } catch (std::runtime_error &) {
1453 QMessageBox::information(this, "Error",
1454 "User tried to open program from: " + QString::fromStdString(expTarget) +
1455 " There was an error opening the program. "
1456 "Please check the target and arguments list "
1457 "to ensure that these are correct");
1458 }
1459 } catch (std::exception &) {
1460 QMessageBox::information(this, "Mantid - Send to Program",
1461 "A file property wasn't found. Please check that the correct" +
1462 QString("save algorithm was used.\n(View -> Preferences -> "
1463 "Mantid -> SendTo -> Edit -> SaveUsing)"));
1464 }
1465 } else
1466 QMessageBox::information(this, "Target Path Error",
1467 "User tried to open program from: " + QString::fromStdString(expTarget) +
1468 " The target file path for the program "
1469 "can't be found. Please check that the full "
1470 "path is correct");
1471 }
1472}
1473
1475
1479
1483
1487void WorkspaceTreeWidget::plotSpectrum(const std::string &type) {
1488 const bool isAdvanced = type == "Advanced";
1489 const auto userInput = m_tree->chooseSpectrumFromSelected(true, true, true, isAdvanced);
1490 // An empty map will be returned if the user clicks cancel in the spectrum
1491 // selection
1492 if (userInput.plots.empty()) {
1493 return;
1494 }
1495 bool showErrorBars = ((type == "Errors") || (type == "Advanced" && userInput.errors));
1496
1497 // mantidUI knows nothing about userInput, hence the long argument lists.
1498 if (userInput.tiled) {
1499 m_mantidDisplayModel->plotSubplots(userInput.plots, MantidQt::DistributionDefault, showErrorBars);
1500 } else if (userInput.simple || userInput.waterfall) {
1501 if (userInput.isAdvanced) {
1502 const auto advancedUserInput = userInput.advanced.value();
1503 m_mantidDisplayModel->plot1D(userInput.plots, true, MantidQt::DistributionDefault, showErrorBars, nullptr, false,
1504 userInput.waterfall, advancedUserInput.logName, advancedUserInput.customLogValues);
1505 } else {
1506 m_mantidDisplayModel->plot1D(userInput.plots, true, MantidQt::DistributionDefault, showErrorBars, nullptr, false,
1507 userInput.waterfall);
1508 }
1509
1510 } else if (userInput.surface) {
1511 const auto advancedUserInput = userInput.advanced.value();
1512 m_mantidDisplayModel->plotSurface(advancedUserInput.accepted, advancedUserInput.plotIndex,
1513 advancedUserInput.axisName, advancedUserInput.logName,
1514 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1515 } else if (userInput.contour) {
1516 const auto advancedUserInput = userInput.advanced.value();
1517 m_mantidDisplayModel->plotContour(advancedUserInput.accepted, advancedUserInput.plotIndex,
1518 advancedUserInput.axisName, advancedUserInput.logName,
1519 advancedUserInput.customLogValues, advancedUserInput.workspaceNames);
1520 }
1521}
1522
1526
1533 // Get the selected workspaces
1534 auto items = m_tree->selectedItems();
1535 if (items.empty())
1536 return;
1537
1538 // Extract child workspace names from any WorkspaceGroups selected.
1539 // Use a list to preserve workspace order.
1540 QStringList allWsNames;
1541
1542 for (auto &item : items) {
1543 auto ws = item->data(0, Qt::UserRole).value<Workspace_sptr>();
1544
1545 if (auto wsGroup = std::dynamic_pointer_cast<WorkspaceGroup>(ws)) {
1546 for (const auto &name : wsGroup->getNames())
1547 allWsNames.append(QString::fromStdString(name));
1548 } else
1549 allWsNames.append(item->text(0));
1550 }
1551
1552 // remove duplicate workspace entries
1553 allWsNames.removeDuplicates();
1554
1556}
1557
1559 switch (e->key()) {
1560 case Qt::Key_Delete:
1561 case Qt::Key_Backspace:
1563 break;
1564 }
1565}
1566
1570
1572 // get selected workspace
1573 auto ws = QString::fromStdString(getSelectedWorkspaceNames()[0]);
1574 const auto *table = m_mantidDisplayModel->createDetectorTable(ws, std::vector<int>(), false);
1575 if (!table) {
1576 QMessageBox::information(this, "Error", QString("Cannot create detectors tables for workspace ") + ws);
1577 }
1578}
1579
1581
1583
1585
1587
1589
1591
1595
1597
1601
1603
1605
1607
1611
1613
1617
1619
1621
1623
1634
1641
1645
1649
1654
1665
1667 m_loadButton->hide();
1668 m_saveButton->hide();
1669 m_deleteButton->hide();
1670 m_clearButton->hide();
1671 m_groupButton->hide();
1672 m_sortButton->hide();
1673}
1674
1675} // 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 QMutex::Recursive was removed in ...
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)