Newer
Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidQtWidgets/Common/WorkspacePresenter/WorkspaceTreeWidget.h"
#include "MantidGeometry/Instrument.h"
#include "MantidQtWidgets/Common/AlgorithmDialog.h"
#include "MantidQtWidgets/Common/AlgorithmInputHistory.h"
#include "MantidQtWidgets/Common/FlowLayout.h"
#include "MantidQtWidgets/Common/InterfaceManager.h"
#include "MantidQtWidgets/Common/LineEditWithClear.h"
#include "MantidQtWidgets/Common/MantidDisplayBase.h"
#include "MantidQtWidgets/Common/MantidTreeWidget.h"
#include "MantidQtWidgets/Common/MantidTreeWidgetItem.h"
#include "MantidQtWidgets/Common/WorkspaceIcons.h"
#include "MantidQtWidgets/Common/WorkspacePresenter/ADSAdapter.h"
#include "MantidQtWidgets/Common/WorkspacePresenter/WorkspacePresenter.h"
#include "MantidQtWidgets/Common/pixmaps.h"
#include "MantidAPI/Axis.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/IPeaksWorkspace.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/WorkspaceGroup.h"
#include <QFileDialog>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QSignalMapper>
using namespace MantidQt::API;
using namespace Mantid::API;
namespace {
/// static logger for dock widget
Mantid::Kernel::Logger docklog("MantidDockWidget");
WorkspaceIcons WORKSPACE_ICONS = WorkspaceIcons();
namespace MantidQt {
namespace MantidWidgets {
WorkspaceTreeWidget::WorkspaceTreeWidget(MantidDisplayBase *mdb, bool viewOnly,
: QWidget(parent), m_mantidDisplayModel(mdb), m_viewOnly(viewOnly),
m_updateCount(0), m_treeUpdating(false), m_promptDelete(false),
m_saveFileType(SaveFileType::Nexus), m_sortCriteria(SortCriteria::ByName),
m_sortDirection(SortDirection::Ascending), m_mutex(QMutex::Recursive) {
setObjectName(
"exploreMantid"); // this is needed for QMainWindow::restoreState()
m_saveMenu = new QMenu(this);
setupWidgetLayout();
setupLoadButtonMenu();
// Dialog box used for user to specify folder to save multiple workspaces into
m_saveFolderDialog = new QFileDialog;
m_saveFolderDialog->setFileMode(QFileDialog::DirectoryOnly);
m_saveFolderDialog->setOption(QFileDialog::ShowDirsOnly);
// To be able to use them in queued signals they need to be registered
static bool registered_addtional_types = false;
if (!registered_addtional_types) {
registered_addtional_types = true;
qRegisterMetaType<TopLevelItems>();
}
// SET UP SORT
createSortMenuActions();
createWorkspaceMenuActions();
setupConnections();
m_tree->setDragEnabled(true);
auto presenter = boost::make_shared<WorkspacePresenter>(this);
m_presenter = boost::dynamic_pointer_cast<ViewNotifiable>(presenter);
presenter->init();
WorkspaceTreeWidget::~WorkspaceTreeWidget() {}
* Accept a drag drop event and process the data appropriately
* @param de :: The drag drop event
*/
void WorkspaceTreeWidget::dropEvent(QDropEvent *de) { m_tree->dropEvent(de); }
void WorkspaceTreeWidget::setupWidgetLayout() {
m_tree = new MantidTreeWidget(m_mantidDisplayModel, this);
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
m_tree->setHeaderLabel("Workspaces");
FlowLayout *buttonLayout = new FlowLayout();
m_loadButton = new QPushButton("Load");
m_saveButton = new QPushButton("Save");
m_deleteButton = new QPushButton("Delete");
m_groupButton = new QPushButton("Group");
m_sortButton = new QPushButton("Sort");
if (m_groupButton)
m_groupButton->setEnabled(false);
m_deleteButton->setEnabled(false);
m_saveButton->setEnabled(false);
buttonLayout->addWidget(m_loadButton);
buttonLayout->addWidget(m_deleteButton);
buttonLayout->addWidget(m_groupButton);
buttonLayout->addWidget(m_sortButton);
buttonLayout->addWidget(m_saveButton);
m_workspaceFilter = new MantidQt::MantidWidgets::LineEditWithClear();
m_workspaceFilter->setPlaceholderText("Filter Workspaces");
m_workspaceFilter->setToolTip("Type here to filter the workspaces");
QVBoxLayout *layout = new QVBoxLayout();
layout->setSpacing(0);
layout->setMargin(0);
layout->addLayout(buttonLayout);
layout->addWidget(m_workspaceFilter);
layout->addWidget(m_tree);
void WorkspaceTreeWidget::setupLoadButtonMenu() {
m_loadMenu = new QMenu(this);
QAction *loadFileAction = new QAction("File", this);
QAction *liveDataAction = new QAction("Live Data", this);
connect(loadFileAction, SIGNAL(triggered()), this, SLOT(onClickLoad()));
connect(liveDataAction, SIGNAL(triggered()), this, SLOT(onClickLiveData()));
m_loadMenu->addAction(loadFileAction);
m_loadMenu->addAction(liveDataAction);
m_loadButton->setMenu(m_loadMenu);
}
void WorkspaceTreeWidget::setupConnections() {
connect(m_workspaceFilter, SIGNAL(textChanged(const QString &)), this,
SLOT(filterWorkspaceTree(const QString &)));
connect(m_deleteButton, SIGNAL(clicked()), this,
SLOT(onClickDeleteWorkspaces()));
connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
SLOT(clickedWorkspace(QTreeWidgetItem *, int)));
connect(m_tree, SIGNAL(itemSelectionChanged()), this,
SLOT(workspaceSelected()));
connect(m_groupButton, SIGNAL(clicked()), this, SLOT(onClickGroupButton()));
m_tree->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_tree, SIGNAL(customContextMenuRequested(const QPoint &)), this,
SLOT(popupMenu(const QPoint &)));
connect(this, SIGNAL(signalUpdateTree(const TopLevelItems &)), this,
SLOT(handleUpdateTree(const TopLevelItems &)), Qt::QueuedConnection);
connect(this, SIGNAL(signalClearView()), this, SLOT(handleClearView()),
Qt::QueuedConnection);
connect(m_tree, SIGNAL(itemSelectionChanged()), this,
SLOT(onTreeSelectionChanged()));
connect(m_tree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this,
SLOT(populateChildData(QTreeWidgetItem *)));
}
* Flips the flag indicating whether a tree update is in progress. Actions such
* as sorting
* are disabled while an update is in progress.
* @param state The required state for the flag
*/
void WorkspaceTreeWidget::setTreeUpdating(const bool state) {
m_treeUpdating = state;
}
void WorkspaceTreeWidget::incrementUpdateCount() { m_updateCount.ref(); }
WorkspacePresenterWN_wptr WorkspaceTreeWidget::getPresenterWeakPtr() {
return boost::dynamic_pointer_cast<WorkspacePresenter>(m_presenter);
/** Returns the names of the selected workspaces
StringList WorkspaceTreeWidget::getSelectedWorkspaceNames() const {
StringList names;
names.reserve(static_cast<size_t>(items.size()));
for (auto &item : items)
names.emplace_back(item->text(0).toStdString());
QStringList WorkspaceTreeWidget::getSelectedWorkspaceNamesAsQList() const {
auto items = m_tree->selectedItems();
QStringList names;
for (auto &item : items) {
names.append(item->text(0));
}
return names;
}
/** Returns a pointer to the selected workspace (the first if multiple
Mantid::API::Workspace_sptr WorkspaceTreeWidget::getSelectedWorkspace() const {
auto items = m_tree->selectedItems();
auto data = items[0]->data(0, Qt::UserRole).value<Workspace_sptr>();
return data;
bool WorkspaceTreeWidget::askUserYesNo(const std::string &caption,
const std::string &message) const {
return QMessageBox::question(parentWidget(), QString::fromStdString(caption),
QString::fromStdString(message),
QMessageBox::Yes,
QMessageBox::No) == QMessageBox::Yes;
}
void WorkspaceTreeWidget::showCriticalUserMessage(
const std::string &caption, const std::string &message) const {
QMessageBox::critical(parentWidget(), QString::fromStdString(caption),
QString::fromStdString(message));
}
QObject *sender = QObject::sender();
MantidQt::API::AlgorithmDialog *dlg =
reinterpret_cast<MantidQt::API::AlgorithmDialog *>(sender);
if (!dlg)
return; // should never happen
QString fn = MantidQt::API::AlgorithmInputHistory::Instance().previousInput(
"Load", "Filename");
m_mantidDisplayModel->updateRecentFilesList(fn);
void WorkspaceTreeWidget::showLoadDialog() {
QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel),
"showAlgorithmDialog", Qt::QueuedConnection,
Q_ARG(QString, "Load"));
void WorkspaceTreeWidget::showLiveDataDialog() {
QMetaObject::invokeMethod(dynamic_cast<QObject *>(m_mantidDisplayModel),
"showAlgorithmDialog", Qt::QueuedConnection,
Q_ARG(QString, "StartLiveData"));
void WorkspaceTreeWidget::renameWorkspace() {
m_presenter->notifyFromView(ViewNotifiable::Flag::RenameWorkspace);
}
void WorkspaceTreeWidget::showRenameDialog(const StringList &wsNames) {
names.append(QString::fromStdString(ws));
m_mantidDisplayModel->renameWorkspace(names);
* Save the old and the new name in m_renameMap. This is needed to restore
* selection
* of the renamed workspace (if it was selected before renaming).
* @param oldName :: Old name of a renamed workspace.
* @param newName :: New name of a renamed workspace.
*/
void WorkspaceTreeWidget::recordWorkspaceRename(const std::string &oldName,
QString qs_oldName = QString::fromStdString(oldName);
QString qs_newName = QString::fromStdString(newName);
QMutexLocker renameMapLock(&m_mutex);
// check if old_name has been recently a new name
QList<QString> oldNames = m_renameMap.keys(qs_oldName);
// non-empty list of oldNames become new_name
if (!oldNames.isEmpty()) {
for (auto &name : oldNames)
m_renameMap[name] = qs_newName;
} else {
// record a new rename pair
m_renameMap[qs_oldName] = qs_newName;
void WorkspaceTreeWidget::refreshWorkspaces() {
m_presenter->notifyFromView(ViewNotifiable::Flag::RefreshWorkspaces);
}
void WorkspaceTreeWidget::enableDeletePrompt(bool enable) {
m_promptDelete = enable;
}
bool WorkspaceTreeWidget::isPromptDelete() const { return m_promptDelete; }
bool WorkspaceTreeWidget::deleteConfirmation() const {
std::string message =
"Are you sure you want to delete the selected Workspaces?";
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
message += "\n\nThis prompt can be disabled from:\nFile->Settings->General";
#else
message += "\n\nThis prompt can be disabled "
"from:\nPreferences->General->Confirmations";
#endif
return askUserYesNo("Delete Workspaces", message);
void WorkspaceTreeWidget::deleteWorkspaces(const StringList &wsNames) {
QStringList names;
for (auto &ws : wsNames)
names.append(QString::fromStdString(ws));
m_mantidDisplayModel->deleteWorkspaces(names);
void WorkspaceTreeWidget::clearView() { emit signalClearView(); }
m_sortDirection = SortDirection::Ascending;
m_presenter->notifyFromView(ViewNotifiable::Flag::SortWorkspaces);
}
void WorkspaceTreeWidget::sortDescending() {
m_sortDirection = SortDirection::Descending;
m_presenter->notifyFromView(ViewNotifiable::Flag::SortWorkspaces);
}
m_sortCriteria = SortCriteria::ByName;
m_presenter->notifyFromView(ViewNotifiable::Flag::SortWorkspaces);
}
void WorkspaceTreeWidget::chooseByLastModified() {
m_sortCriteria = SortCriteria::ByLastModified;
m_presenter->notifyFromView(ViewNotifiable::Flag::SortWorkspaces);
}
m_sortCriteria = SortCriteria::ByMemorySize;
m_presenter->notifyFromView(ViewNotifiable::Flag::SortWorkspaces);
}
void WorkspaceTreeWidget::excludeItemFromSort(MantidTreeWidgetItem *item) {
static int counter = 1;
item->setSortPos(counter);
counter++;
}
WorkspaceTreeWidget::SortDirection
WorkspaceTreeWidget::getSortDirection() const {
return m_sortDirection;
WorkspaceTreeWidget::SortCriteria WorkspaceTreeWidget::getSortCriteria() const {
return m_sortCriteria;
void WorkspaceTreeWidget::sortWorkspaces(SortCriteria criteria,
m_tree->setSortScheme(whichCriteria(criteria));
m_tree->setSortOrder(direction == SortDirection::Ascending
? Qt::AscendingOrder
: Qt::DescendingOrder);
m_tree->sort();
}
MantidQt::MantidWidgets::MantidItemSortScheme
WorkspaceTreeWidget::whichCriteria(SortCriteria criteria) {
switch (criteria) {
case SortCriteria::ByName:
return MantidItemSortScheme::ByName;
case SortCriteria::ByLastModified:
return MantidItemSortScheme::ByLastModified;
case SortCriteria::ByMemorySize:
return MantidItemSortScheme::ByMemorySize;
default:
// Handle if someone adds a new Enum and it falls through by defaulting to
// name
return MantidItemSortScheme::ByName;
void WorkspaceTreeWidget::saveWorkspaceCollection() {
m_presenter->notifyFromView(ViewNotifiable::Flag::SaveWorkspaceCollection);
}
void WorkspaceTreeWidget::handleShowSaveAlgorithm() {
QAction *sendingAction = dynamic_cast<QAction *>(sender());
if (sendingAction) {
QString actionName = sendingAction->text();
if (actionName.compare("Nexus") == 0)
m_saveFileType = SaveFileType::Nexus;
else if (actionName.compare("ASCII") == 0)
m_saveFileType = SaveFileType::ASCII;
}
m_presenter->notifyFromView(ViewNotifiable::Flag::SaveSingleWorkspace);
}
WorkspaceTreeWidget::SaveFileType WorkspaceTreeWidget::getSaveFileType() const {
void WorkspaceTreeWidget::saveWorkspace(const std::string &wsName,
SaveFileType type) {
QHash<QString, QString> presets;
if (!wsName.empty()) {
presets["InputWorkspace"] = QString::fromStdString(wsName);
}
int version = -1;
std::string algorithmName;
switch (type) {
case SaveFileType::Nexus:
algorithmName = "SaveNexus";
break;
case SaveFileType::ASCII:
algorithmName = "SaveAscii";
break;
}
QString::fromStdString(algorithmName), presets, nullptr, version);
void WorkspaceTreeWidget::saveWorkspaces(const StringList &wsNames) {
QList<QTreeWidgetItem *> items = m_tree->selectedItems();
if (items.size() < 2)
return;
m_saveFolderDialog->setWindowTitle("Select save folder");
m_saveFolderDialog->setLabelText(QFileDialog::Accept, "Select");
auto res = m_saveFolderDialog->exec();
auto folder = m_saveFolderDialog->selectedFiles()[0].toStdString();
IAlgorithm_sptr saveAlg = AlgorithmManager::Instance().create("SaveNexus");
saveAlg->initialize();
if (res == QFileDialog::Accepted) {
for (auto &wsName : wsNames) {
std::string filename = folder + "/" + wsName + ".nxs";
try {
saveAlg->setProperty("InputWorkspace", wsName);
saveAlg->setProperty("Filename", filename);
saveAlg->execute();
} catch (std::exception &ex) {
docklog.error() << "Error saving workspace " << wsName << ": "
std::string WorkspaceTreeWidget::getFilterText() const {
return m_workspaceFilter->text().toStdString();
}
void WorkspaceTreeWidget::filterWorkspaces(const std::string &filterText) {
const QString text = QString::fromStdString(filterText).trimmed();
QRegExp filterRegEx(text, Qt::CaseInsensitive);
// show all items
QTreeWidgetItemIterator unhideIter(m_tree);
while (*unhideIter) {
(*unhideIter)->setHidden(false);
++unhideIter;
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
}
int hiddenCount = 0;
QList<QTreeWidgetItem *> visibleGroups;
if (!text.isEmpty()) {
// Loop over everything (currently loaded) and top level
// find out what is already expanded
QStringList expanded;
int n = m_tree->topLevelItemCount();
for (int i = 0; i < n; ++i) {
auto item = m_tree->topLevelItem(i);
if (item->isExpanded()) {
expanded << item->text(0);
} else {
// expand everything that is at the top level (as we lazy load this is
// required)
item->setExpanded(true);
}
}
// filter based on the string
QTreeWidgetItemIterator it(m_tree, QTreeWidgetItemIterator::All);
while (*it) {
QTreeWidgetItem *item = (*it);
QVariant userData = item->data(0, Qt::UserRole);
if (!userData.isNull()) {
Workspace_sptr workspace = userData.value<Workspace_sptr>();
if (workspace) {
// I am a workspace
if (item->text(0).contains(filterRegEx)) {
// my name does match the filter
if (auto group =
boost::dynamic_pointer_cast<WorkspaceGroup>(workspace)) {
// I am a group, I will want my children to be visible
// but I cannot do that until this iterator has finished
// store this pointer in a list for processing later
visibleGroups.append(item);
item->setHidden(false);
}
// No parent, I am a top level workspace - show me
item->setHidden(false);
} else {
// I am a child workspace of a group
// I match, so I want my parent to remain visible as well.
item->setHidden(false);
if (item->parent()->isHidden()) {
// I was previously hidden, show me and set to be expanded
--hiddenCount;
item->parent()->setHidden(false);
expanded << item->parent()->text(0);
}
}
} else {
// my name does not match the filter - hide me
item->setHidden(true);
++hiddenCount;
}
}
}
++it;
}
// make children of visible groups visible
for (auto group : visibleGroups) {
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
for (int i = 0; i < group->childCount(); i++) {
QTreeWidgetItem *child = group->child(i);
if (child->isHidden()) {
// I was previously hidden, show me
--hiddenCount;
child->setHidden(false);
}
}
}
// set the expanded state
for (int i = 0; i < n; ++i) {
auto item = m_tree->topLevelItem(i);
item->setExpanded(expanded.contains(item->text(0)));
}
}
// display a message if items are hidden
if (hiddenCount > 0) {
QString headerString =
QString("Workspaces (%1 filtered)").arg(QString::number(hiddenCount));
m_tree->headerItem()->setText(0, headerString);
} else {
m_tree->headerItem()->setText(0, "Workspaces");
}
}
* Set tree item's icon based on the ID of the workspace.
* @param item :: A workspace tree item.
* @param wsID :: An icon type code.
*/
void WorkspaceTreeWidget::setItemIcon(QTreeWidgetItem *item,
try {
item->setIcon(0, QIcon(WORKSPACE_ICONS.getIcon(wsID)));
} catch (std::runtime_error &) {
docklog.warning() << "Cannot find icon for workspace ID '" << wsID << "'\n";
}
}
/**
* Create the action items associated with the dock
*/
void WorkspaceTreeWidget::createWorkspaceMenuActions() {
m_showData = new QAction(tr("Show Data"), this);
connect(m_showData, SIGNAL(triggered()), this, SLOT(onClickShowData()));
m_showInst = new QAction(tr("Show Instrument"), this);
connect(m_showInst, SIGNAL(triggered()), this, SLOT(onClickShowInstrument()));
m_plotSpec = new QAction(tr("Plot Spectrum..."), this);
connect(m_plotSpec, SIGNAL(triggered()), this, SLOT(onClickPlotSpectra()));
m_plotSpecErr = new QAction(tr("Plot Spectrum with Errors..."), this);
connect(m_plotSpecErr, SIGNAL(triggered()), this,
SLOT(onClickPlotSpectraErr()));
m_plotAdvanced = new QAction(tr("Plot Advanced..."), this);
connect(m_plotAdvanced, SIGNAL(triggered()), this,
SLOT(onClickPlotAdvanced()));
m_colorFill = new QAction(tr("Color Fill Plot"), this);
connect(m_colorFill, SIGNAL(triggered()), this,
SLOT(onClickDrawColorFillPlot()));
m_showDetectors = new QAction(tr("Show Detectors"), this);
connect(m_showDetectors, SIGNAL(triggered()), this,
SLOT(onClickShowDetectorTable()));
m_showBoxData = new QAction(tr("Show Box Data Table"), this);
connect(m_showBoxData, SIGNAL(triggered()), this, SLOT(onClickShowBoxData()));
m_showVatesGui = new QAction(tr("Show Vates Simple Interface"), this);
{
QIcon icon;
icon.addFile(
QString::fromUtf8(":/VatesSimpleGuiViewWidgets/icons/pvIcon.png"),
QSize(), QIcon::Normal, QIcon::Off);
m_showVatesGui->setIcon(icon);
}
connect(m_showVatesGui, SIGNAL(triggered()), this, SLOT(onClickShowVates()));
m_showMDPlot = new QAction(tr("Plot MD"), this);
connect(m_showMDPlot, SIGNAL(triggered()), this, SLOT(onClickShowMDPlot()));
m_showListData = new QAction(tr("List Data"), this);
connect(m_showListData, SIGNAL(triggered()), this,
SLOT(onClickShowListData()));
m_showSpectrumViewer = new QAction(tr("Show Spectrum Viewer"), this);
connect(m_showSpectrumViewer, SIGNAL(triggered()), this,
SLOT(onClickShowSpectrumViewer()));
m_showSliceViewer = new QAction(tr("Show Slice Viewer"), this);
{
QIcon icon;
icon.addFile(
QString::fromUtf8(":/SliceViewer/icons/SliceViewerWindow_icon.png"),
QSize(), QIcon::Normal, QIcon::Off);
m_showSliceViewer->setIcon(icon);
}
connect(m_showSliceViewer, SIGNAL(triggered()), this,
SLOT(onClickShowSliceViewer()));
m_showLogs = new QAction(tr("Sample Logs..."), this);
connect(m_showLogs, SIGNAL(triggered()), this, SLOT(onClickShowFileLog()));
m_showSampleMaterial = new QAction(tr("Sample Material..."), this);
connect(m_showSampleMaterial, SIGNAL(triggered()), this,
SLOT(onClickShowSampleMaterial()));
m_showHist = new QAction(tr("Show History"), this);
connect(m_showHist, SIGNAL(triggered()), this, SLOT(onClickShowAlgHistory()));
m_saveNexus = new QAction(tr("Save NeXus"), this);
connect(m_saveNexus, SIGNAL(triggered()), this,
SLOT(onClickSaveNexusWorkspace()));
m_rename = new QAction(tr("Rename"), this);
connect(m_rename, SIGNAL(triggered()), this, SLOT(renameWorkspace()));
m_delete = new QAction(tr("Delete"), this);
connect(m_delete, SIGNAL(triggered()), this, SLOT(onClickDeleteWorkspaces()));
m_showTransposed = new QAction(tr("Show Transposed"), this);
connect(m_showTransposed, SIGNAL(triggered()), this,
SLOT(onClickShowTransposed()));
m_convertToMatrixWorkspace =
new QAction(tr("Convert to MatrixWorkspace"), this);
m_convertToMatrixWorkspace->setIcon(QIcon(getQPixmap("mantid_matrix_xpm")));
connect(m_convertToMatrixWorkspace, SIGNAL(triggered()), this,
SLOT(onClickConvertToMatrixWorkspace()));
m_convertMDHistoToMatrixWorkspace =
new QAction(tr("Convert to MatrixWorkspace"), this);
m_convertMDHistoToMatrixWorkspace->setIcon(
QIcon(getQPixmap("mantid_matrix_xpm")));
connect(m_convertMDHistoToMatrixWorkspace, SIGNAL(triggered()), this,
SLOT(onClickConvertMDHistoToMatrixWorkspace()));
m_clearUB = new QAction(tr("Clear UB Matrix"), this);
connect(m_clearUB, SIGNAL(triggered()), this, SLOT(onClickClearUB()));
void WorkspaceTreeWidget::createSortMenuActions() {
m_sortCriteria = SortCriteria::ByName;
m_sortMenu = new QMenu(this);
QAction *m_ascendingSortAction = new QAction("Ascending", this);
QAction *m_descendingSortAction = new QAction("Descending", this);
QAction *m_byNameChoice = new QAction("Name", this);
QAction *m_byLastModifiedChoice = new QAction("Last Modified", this);
QAction *m_byMemorySize = new QAction("Size", this);
m_ascendingSortAction->setCheckable(true);
m_ascendingSortAction->setEnabled(true);
m_descendingSortAction->setCheckable(true);
m_descendingSortAction->setEnabled(true);
QActionGroup *sortDirectionGroup = new QActionGroup(m_sortMenu);
sortDirectionGroup->addAction(m_ascendingSortAction);
sortDirectionGroup->addAction(m_descendingSortAction);
sortDirectionGroup->setExclusive(true);
m_ascendingSortAction->setChecked(true);
m_byNameChoice->setCheckable(true);
m_byNameChoice->setEnabled(true);
m_byLastModifiedChoice->setCheckable(true);
m_byLastModifiedChoice->setEnabled(true);
m_byMemorySize->setCheckable(true);
m_byMemorySize->setEnabled(true);
m_sortChoiceGroup = new QActionGroup(m_sortMenu);
m_sortChoiceGroup->addAction(m_byNameChoice);
m_sortChoiceGroup->addAction(m_byLastModifiedChoice);
m_sortChoiceGroup->addAction(m_byMemorySize);
m_sortChoiceGroup->setExclusive(true);
m_byNameChoice->setChecked(true);
connect(m_ascendingSortAction, SIGNAL(triggered()), this,
SLOT(sortAscending()));
connect(m_descendingSortAction, SIGNAL(triggered()), this,
SLOT(sortDescending()));
connect(m_byNameChoice, SIGNAL(triggered()), this, SLOT(chooseByName()));
connect(m_byLastModifiedChoice, SIGNAL(triggered()), this,
SLOT(chooseByLastModified()));
connect(m_byMemorySize, SIGNAL(triggered()), this,
SLOT(chooseByMemorySize()));
m_sortMenu->addActions(sortDirectionGroup->actions());
m_sortMenu->addSeparator();
m_sortMenu->addActions(m_sortChoiceGroup->actions());
m_sortButton->setMenu(m_sortMenu);
}
* When an item is expanded, populate the child data for this item
* @param item :: The tree item being expanded
*/
void WorkspaceTreeWidget::populateChildData(QTreeWidgetItem *item) {
QVariant userData = item->data(0, Qt::UserRole);
if (userData.isNull())
return;
// Clear it first
while (item->childCount() > 0) {
auto *widgetItem = item->takeChild(0);
delete widgetItem;
}
Workspace_sptr workspace = userData.value<Workspace_sptr>();
if (auto group = boost::dynamic_pointer_cast<WorkspaceGroup>(workspace)) {
auto members = group->getAllItems();
auto *node = addTreeEntry(std::make_pair(ws->getName(), ws), item);
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
excludeItemFromSort(node);
if (shouldBeSelected(node->text(0)))
node->setSelected(true);
}
} else {
QString details;
try {
details = workspace->toString().c_str();
} catch (std::runtime_error &e) {
details = QString("Error: %1").arg(e.what());
}
QStringList rows =
details.split(QLatin1Char('\n'), QString::SkipEmptyParts);
rows.append(QString("Memory used: ") +
workspace->getMemorySizeAsStr().c_str());
auto iend = rows.constEnd();
for (auto itr = rows.constBegin(); itr != iend; ++itr) {
MantidTreeWidgetItem *data =
new MantidTreeWidgetItem(QStringList(*itr), m_tree);
data->setFlags(Qt::NoItemFlags);
excludeItemFromSort(data);
item->addChild(data);
}
}
}
* Update the workspace tree to match the current state of the ADS.
* It is important that the workspace tree is modified only by this method.
* @param items Items which are currently in the ADS.
*/
void WorkspaceTreeWidget::updateTree(const TopLevelItems &items) {
incrementUpdateCount();
emit signalUpdateTree(items);
* Clears the tree and re-populates it with the given top level items
* @param topLevelItems The map of names to workspaces
* @param expanded Names of items who should expanded after being populated
*/
void WorkspaceTreeWidget::populateTopLevel(const TopLevelItems &topLevelItems,
{
QMutexLocker lock(&m_mutex);
// collect names of selected workspaces
QList<QTreeWidgetItem *> selected = m_tree->selectedItems();
m_selectedNames.clear(); // just in case
foreach (QTreeWidgetItem *item, selected) {
m_selectedNames << item->text(0);
}
// populate the tree from scratch
m_tree->clear();
auto iend = topLevelItems.end();
for (auto it = topLevelItems.begin(); it != iend; ++it) {
auto *node = addTreeEntry(*it);
QString name = node->text(0);
if (expanded.contains(name))
node->setExpanded(true);
// see if item must be selected
if (shouldBeSelected(name))
node->setSelected(true);
}
m_selectedNames.clear();
m_renameMap.clear();
}
// apply any filtering
filterWorkspaceTree(m_workspaceFilter->text());
}
* Adds a node for the given named item, including a single child ID item to
* make each node have a expandable button and allowing plotting to work from
* non-expanded items
* @param item A name/workspace pair to add.
* @param parent If not null then add the new items as a child of the given item
*/
MantidTreeWidgetItem *WorkspaceTreeWidget::addTreeEntry(
const std::pair<std::string, Mantid::API::Workspace_sptr> &item,
QTreeWidgetItem *parent) {
MantidTreeWidgetItem *node =
new MantidTreeWidgetItem(QStringList(item.first.c_str()), m_tree);
node->setData(0, Qt::UserRole, QVariant::fromValue(item.second));
// A a child ID item so that it becomes expandable. Using the correct ID is
// needed when plotting from non-expanded groups.
const std::string wsID = item.second->id();
MantidTreeWidgetItem *idNode =
new MantidTreeWidgetItem(QStringList(wsID.c_str()), m_tree);
idNode->setFlags(Qt::NoItemFlags);
node->addChild(idNode);
setItemIcon(node, wsID);
if (parent) {
parent->addChild(node);
} else {
m_tree->addTopLevelItem(node);
}
return node;
}
* Check if a workspace should be selected after dock update.
* @param name :: Name of a workspace to check.
*/
bool WorkspaceTreeWidget::shouldBeSelected(QString name) const {
QMutexLocker lock(&m_mutex);
QStringList renamed = m_renameMap.keys(name);
if (!renamed.isEmpty()) {
foreach (QString oldName, renamed) {
if (m_selectedNames.contains(oldName)) {
return true;
}
}
} else if (m_selectedNames.contains(name)) {
return true;
}
return false;
}
void WorkspaceTreeWidget::onTreeSelectionChanged() {
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
// get selected workspaces
auto items = m_tree->selectedItems();
if (m_groupButton) {
if (items.size() == 1) {
// check it's group
auto wsSptr =
items.first()->data(0, Qt::UserRole).value<Workspace_sptr>();
auto grpSptr = boost::dynamic_pointer_cast<WorkspaceGroup>(wsSptr);
if (grpSptr) {
m_groupButton->setText("Ungroup");
m_groupButton->setEnabled(true);
} else
m_groupButton->setEnabled(false);
} else if (items.size() >= 2) {
m_groupButton->setText("Group");
m_groupButton->setEnabled(true);
} else if (items.size() == 0) {
m_groupButton->setText("Group");
m_groupButton->setEnabled(false);
}
}
if (m_deleteButton)
m_deleteButton->setEnabled(items.size() > 0);
if (m_saveButton)
m_saveButton->setEnabled(items.size() > 0);
if (items.size() > 0) {
auto item = *(items.begin());
m_mantidDisplayModel->enableSaveNexus(item->text(0));
* Add the actions that are appropriate for a MatrixWorkspace
* @param menu :: The menu to store the items
* @param matrixWS :: The workspace related to the menu
*/
void WorkspaceTreeWidget::addMatrixWorkspaceMenuItems(
QMenu *menu,
const Mantid::API::MatrixWorkspace_const_sptr &matrixWS) const {
// Add all options except plot of we only have 1 value
menu->addAction(m_showData);
menu->addAction(m_showInst);
// Disable the 'show instrument' option if a workspace doesn't have an
// instrument attached or if it does not have a spectra axis
m_showInst->setEnabled(matrixWS->getInstrument() &&
!matrixWS->getInstrument()->getName().empty() &&
matrixWS->getAxis(1)->isSpectra());
menu->addSeparator();
menu->addAction(m_plotSpec);
menu->addAction(m_plotSpecErr);
menu->addAction(m_plotAdvanced);
// Don't plot a spectrum if only one X value
bool multipleBins = false;
try {
multipleBins = (matrixWS->blocksize() > 1);
} catch (...) {
const size_t numHist = matrixWS->getNumberHistograms();
for (size_t i = 0; i < numHist; ++i) {
if (matrixWS->y(i).size() > 1) {
multipleBins = true;
break;
}
}
}
m_plotSpec->setEnabled(multipleBins);
m_plotSpecErr->setEnabled(multipleBins);
m_plotAdvanced->setEnabled(multipleBins);
menu->addAction(m_showSpectrumViewer); // The 2D spectrum viewer
menu->addAction(m_colorFill);
// Show the color fill plot if you have more than one histogram
m_colorFill->setEnabled(
(matrixWS->axes() > 1 && matrixWS->getNumberHistograms() > 1));
menu->addAction(m_showSliceViewer); // The 2D slice viewer
menu->addSeparator();
menu->addAction(m_showDetectors);
menu->addAction(m_showLogs);
menu->addAction(m_showSampleMaterial);
menu->addAction(m_showHist);
menu->addAction(m_saveNexus);
}
/**
* Add the actions that are appropriate for a MDEventWorkspace
* @param menu :: The menu to store the items
* @param WS :: The workspace related to the menu
*/
void WorkspaceTreeWidget::addMDEventWorkspaceMenuItems(