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