-
Anton Piccardo-Selg authoredAnton Piccardo-Selg authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MdViewerWidget.cpp 36.26 KiB
#include "MantidVatesSimpleGuiViewWidgets/MdViewerWidget.h"
#include "MantidVatesSimpleGuiQtWidgets/ModeControlWidget.h"
#include "MantidVatesSimpleGuiQtWidgets/RotationPointDialog.h"
#include "MantidVatesSimpleGuiViewWidgets/BackgroundRgbProvider.h"
#include "MantidVatesSimpleGuiViewWidgets/ColorSelectionWidget.h"
#include "MantidVatesSimpleGuiViewWidgets/MultisliceView.h"
#include "MantidVatesSimpleGuiViewWidgets/SaveScreenshotReaction.h"
#include "MantidVatesSimpleGuiViewWidgets/SplatterPlotView.h"
#include "MantidVatesSimpleGuiViewWidgets/StandardView.h"
#include "MantidVatesSimpleGuiViewWidgets/ThreesliceView.h"
#include "MantidVatesSimpleGuiViewWidgets/TimeControlWidget.h"
#include "MantidQtAPI/InterfaceManager.h"
#include "MantidKernel/DynamicFactory.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/InstrumentInfo.h"
// Have to deal with ParaView warnings and Intel compiler the hard way.
#if defined(__INTEL_COMPILER)
#pragma warning disable 1170
#endif
#include <pqActiveObjects.h>
#include <pqAnimationManager.h>
#include <pqAnimationScene.h>
#include <pqApplicationCore.h>
#include <pqLoadDataReaction.h>
#include <pqObjectBuilder.h>
#include <pqObjectInspectorWidget.h>
#include <pqParaViewBehaviors.h>
#include <pqPipelineSource.h>
#include <pqPVApplicationCore.h>
#include <pqRenderView.h>
#include <pqSettings.h>
#include <pqStatusBar.h>
#include <pqViewSettingsReaction.h>
#include <vtkSMDoubleVectorProperty.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMProxyManager.h>
#include <vtkSMProxy.h>
#include <vtkSMViewProxy.h>
#include <vtkSMSourceProxy.h>
#include <vtkSMReaderFactory.h>
#include <vtksys/SystemTools.hxx>
#include <pqPipelineRepresentation.h>
// Used for plugin mode
#include <pqAlwaysConnectedBehavior.h>
#include <pqAutoLoadPluginXMLBehavior.h>
#include <pqCollaborationBehavior.h>
#include <pqCommandLineOptionsBehavior.h>
#include <pqCrashRecoveryBehavior.h>
#include <pqDataTimeStepBehavior.h>
#include <pqDefaultViewBehavior.h>
#include <pqDeleteBehavior.h>
#include <pqFixPathsInStateFilesBehavior.h>
#include <pqInterfaceTracker.h>
#include <pqMultiServerBehavior.h>
#include <pqObjectPickingBehavior.h>
//#include <pqPersistentMainWindowStateBehavior.h>
#include <pqPipelineContextMenuBehavior.h>
//#include <pqPluginActionGroupBehavior.h>
//#include <pqPluginDockWidgetsBehavior.h>
#include <pqPluginManager.h>
#include <pqPVNewSourceBehavior.h>
#include <pqQtMessageHandlerBehavior.h>
#include <pqSpreadSheetVisibilityBehavior.h>
#include <pqStandardPropertyWidgetInterface.h>
#include <pqStandardViewModules.h>
#include <pqUndoRedoBehavior.h>
#include <pqViewFrameActionsBehavior.h>
#include <pqViewStreamingBehavior.h>
#include <pqVerifyRequiredPluginBehavior.h>
#if defined(__INTEL_COMPILER)
#pragma warning enable 1170
#endif
#include <QAction>
#include <QDesktopServices>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QMenuBar>
#include <QModelIndex>
#include <QUrl>
#include <QWidget>
#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <boost/regex.hpp>
namespace Mantid
{
namespace Vates
{
namespace SimpleGui
{
using namespace Mantid::API;
using namespace MantidQt::API;
namespace
{
Mantid::Kernel::Logger g_log("MdViewerWidget");
}
REGISTER_VATESGUI(MdViewerWidget)
/**
* This constructor is used in the plugin mode operation of the VSI.
*/
MdViewerWidget::MdViewerWidget() : VatesViewerInterface(), currentView(NULL),
dataLoader(NULL), hiddenView(NULL), lodAction(NULL), screenShot(NULL), viewLayout(NULL),
viewSettings(NULL)
{
// Calling workspace observer functions.
observeAfterReplace();
observePreDelete();
observeADSClear();
this->internalSetup(true);
// Create the mapping from the measurement technique to the view
}
/**
* This constructor is used in the standalone mode operation of the VSI.
* @param parent the parent widget for the main window
*/
MdViewerWidget::MdViewerWidget(QWidget *parent) : VatesViewerInterface(parent)
{
this->checkEnvSetup();
// We're in the standalone application mode
this->internalSetup(false);
this->setupUiAndConnections();
// FIXME: This doesn't allow a clean split of the classes. I will need
// to investigate creating the individual behaviors to see if that
// eliminates the dependence on the QMainWindow.
if (parent->inherits("QMainWindow"))
{
QMainWindow *mw = qobject_cast<QMainWindow *>(parent);
new pqParaViewBehaviors(mw, mw);
}
this->setupMainView();
}
MdViewerWidget::~MdViewerWidget()
{
}
/**
* This function consolidates setting up some of the internal members between
* the standalone and plugin modes.
* @param pMode flag to set the plugin mode
*/
void MdViewerWidget::internalSetup(bool pMode)
{
this->isPluginInitialized = false;
this->pluginMode = pMode;
this->rotPointDialog = NULL;
this->lodThreshold = 5.0;
this->viewSwitched = false;
this->startingUp = true;
}
/**
* This function uses VTK's system tools to check the environmental variables
* to make sure PV_PLUGIN_PATH is available.
*/
void MdViewerWidget::checkEnvSetup()
{
QString pv_plugin_path = vtksys::SystemTools::GetEnv("PV_PLUGIN_PATH");
if (pv_plugin_path.isEmpty())
{
throw std::runtime_error("PV_PLUGIN_PATH not setup.\nVates plugins will not be available.\n"
"Further use will cause the program to crash.\nPlease exit and "
"set this variable.");
}
}
/**
* This function sets up the UI components and connects some of the main
* window's control buttons.
*/
void MdViewerWidget::setupUiAndConnections()
{
this->ui.setupUi(this);
this->ui.splitter_2->setStretchFactor(1, 1);
this->ui.statusBar->setSizeGripEnabled(false);
// Unset the connections since the views aren't up yet.
this->removeProxyTabWidgetConnections();
QObject::connect(this->ui.modeControlWidget,
SIGNAL(executeSwitchViews(ModeControlWidget::Views)),
this, SLOT(switchViews(ModeControlWidget::Views)));
// Setup rotation point button
QObject::connect(this->ui.resetCenterToPointButton,
SIGNAL(clicked()),
this,
SLOT(onRotationPoint()));
}
/**
* This function places the standard view to the main window, installs an
* event filter, tweaks the UI layout for the view and calls the routine that
* sets up connections between ParaView and the main window widgets.
*/
void MdViewerWidget::setupMainView()
{
// Commented this out to only use Mantid supplied readers
// Initialize all readers available to ParaView. Now our application can load
// all types of datasets supported by ParaView.
//vtkSMProxyManager::GetProxyManager()->GetReaderFactory()->RegisterPrototypes("sources");
// Set the view at startup to STANDARD, the view will be changed, depending on the workspace
this->currentView = this->setMainViewWidget(this->ui.viewWidget, ModeControlWidget::STANDARD);
this->initialView = ModeControlWidget::STANDARD;
this->currentView->installEventFilter(this);
// Create a layout to manage the view properly
this->viewLayout = new QHBoxLayout(this->ui.viewWidget);
this->viewLayout->setMargin(0);
this->viewLayout->setStretch(0, 1);
this->viewLayout->addWidget(this->currentView);
this->setParaViewComponentsForView();
}
/**
* This function ensures that the main ParaView instance is only initialized
* once. On the second call, it checks to make sure one doesn't exist. This is
* only important for plugin mode operation of the VSI.
*/
void MdViewerWidget::createAppCoreForPlugin()
{
if (!pqApplicationCore::instance())
{
// Provide ParaView's application core with a path to ParaView
std::string paraviewPath = Mantid::Kernel::ConfigService::Instance().getParaViewPath();
if(paraviewPath.empty())
{
// ParaView crashes with an empty string but on Linux/OSX we dont set this property
paraviewPath = "/tmp/MantidPlot";
}
std::vector<char> argvConversion(paraviewPath.begin(), paraviewPath.end());
argvConversion.push_back('\0');
int argc = 1;
char *argv[] = {&argvConversion[0]};
g_log.debug() << "Intialize pqApplicationCore with " << argv << "\n";
new pqPVApplicationCore(argc, argv);
}
else
{
this->isPluginInitialized = true;
}
}
/**
* This function duplicates the nearly identical call in ParaView for their
* main program setup. This is necessary for the plugin mode since it does
* not have access to the QMainWindow of MantidPlot.
*/
void MdViewerWidget::setupParaViewBehaviors()
{
// Register ParaView interfaces.
pqInterfaceTracker* pgm = pqApplicationCore::instance()->interfaceTracker();
// * adds support for standard paraview views.
pgm->addInterface(new pqStandardViewModules(pgm));
pgm->addInterface(new pqStandardPropertyWidgetInterface(pgm));
// Load plugins distributed with application.
pqApplicationCore::instance()->loadDistributedPlugins();
// Define application behaviors.
new pqQtMessageHandlerBehavior(this);
new pqDataTimeStepBehavior(this);
new pqViewFrameActionsBehavior(this);
new pqSpreadSheetVisibilityBehavior(this);
new pqPipelineContextMenuBehavior(this);
new pqDefaultViewBehavior(this);
new pqAlwaysConnectedBehavior(this);
new pqPVNewSourceBehavior(this);
new pqDeleteBehavior(this);
new pqUndoRedoBehavior(this);
new pqCrashRecoveryBehavior(this);
new pqAutoLoadPluginXMLBehavior(this);
//new pqPluginDockWidgetsBehavior(mainWindow);
new pqVerifyRequiredPluginBehavior(this);
//new pqPluginActionGroupBehavior(mainWindow);
new pqFixPathsInStateFilesBehavior(this);
new pqCommandLineOptionsBehavior(this);
//new pqPersistentMainWindowStateBehavior(mainWindow);
new pqObjectPickingBehavior(this);
new pqCollaborationBehavior(this);
new pqMultiServerBehavior(this);
new pqViewStreamingBehavior(this);
}
/**
* This function connects ParaView's data loader the given action.
* @param action the action to connect data loading to
*/
void MdViewerWidget::connectLoadDataReaction(QAction *action)
{
// We want the actionLoad to result in the showing up the ParaView's OpenData
// dialog letting the user pick from one of the supported file formats.
this->dataLoader = new pqLoadDataReaction(action);
QObject::connect(this->dataLoader, SIGNAL(loadedData(pqPipelineSource*)),
this, SLOT(onDataLoaded(pqPipelineSource*)));
}
/**
* This function disconnects ParaView connections between pqActiveObjects
* and the pqProxyTabWidget. This is necessary for clean view switching.
*/
void MdViewerWidget::removeProxyTabWidgetConnections()
{
QObject::disconnect(&pqActiveObjects::instance(), 0,
this->ui.propertiesPanel, 0);
this->ui.propertiesPanel->setRepresentation(NULL);
this->ui.propertiesPanel->setView(NULL);
this->ui.propertiesPanel->setOutputPort(NULL);
}
/**
* This function creates the requested view on the main window.
* @param container the UI widget to associate the view mode with
* @param v the view mode to set on the main window
* @return the requested view
*/
ViewBase* MdViewerWidget::setMainViewWidget(QWidget *container,
ModeControlWidget::Views v)
{
ViewBase *view;
switch(v)
{
case ModeControlWidget::STANDARD:
{
view = new StandardView(container);
}
break;
case ModeControlWidget::THREESLICE:
{
view = new ThreeSliceView(container);
}
break;
case ModeControlWidget::MULTISLICE:
{
view = new MultiSliceView(container);
}
break;
case ModeControlWidget::SPLATTERPLOT:
{
view = new SplatterPlotView(container);
}
break;
default:
view = NULL;
break;
}
return view;
}
/**
* This function is responsible for setting up all the connections between
* ParaView's pqPipelineBrowser and pqProxyTabWidget and cetatin main window
* widgets.
*/
void MdViewerWidget::setParaViewComponentsForView()
{
// Extra setup stuff to hook up view to other items
this->ui.propertiesPanel->setView(this->currentView->getView());
this->ui.pipelineBrowser->setActiveView(this->currentView->getView());
pqActiveObjects *activeObjects = &pqActiveObjects::instance();
QObject::connect(activeObjects, SIGNAL(portChanged(pqOutputPort*)),
this->ui.propertiesPanel, SLOT(setOutputPort(pqOutputPort*)));
QObject::connect(activeObjects, SIGNAL(representationChanged(pqRepresentation*)),
this->ui.propertiesPanel, SLOT(setRepresentation(pqRepresentation*)));
QObject::connect(activeObjects, SIGNAL(viewChanged(pqView*)),
this->ui.propertiesPanel, SLOT(setView(pqView*)));
this->ui.propertiesPanel->setOutputPort(activeObjects->activePort());
this->ui.propertiesPanel->setView(this->currentView->getView());
this->ui.propertiesPanel->setRepresentation(activeObjects->activeRepresentation());
QObject::connect(this->currentView,
SIGNAL(triggerAccept()),
this->ui.propertiesPanel,
SLOT(apply()));
QObject::connect(this->ui.propertiesPanel,
SIGNAL(applied()),
this, SLOT(checkForUpdates()));
QObject::connect(this->currentView,
SIGNAL(renderingDone()),
this,
SLOT(renderingDone()));
SplatterPlotView *spv = dynamic_cast<SplatterPlotView *>(this->currentView);
if (spv)
{
QObject::connect(this->ui.propertiesPanel,
SIGNAL(applied()),
spv,
SLOT(checkPeaksCoordinates()));
QObject::connect(spv,
SIGNAL(toggleOrthographicProjection(bool)),
this->ui.parallelProjButton,
SLOT(setChecked(bool)));
QObject::connect(spv,
SIGNAL(resetToStandardView()),
this->ui.modeControlWidget,
SLOT(setToStandardView()));
}
QObject::connect(this->currentView, SIGNAL(setViewsStatus(ModeControlWidget::Views, bool)),
this->ui.modeControlWidget, SLOT(enableViewButtons(ModeControlWidget::Views, bool)));
QObject::connect(this->currentView,
SIGNAL(setViewStatus(ModeControlWidget::Views, bool)),
this->ui.modeControlWidget,
SLOT(enableViewButton(ModeControlWidget::Views, bool)));
this->connectColorSelectionWidget();
// Set animation (time) control widget <-> view signals/slots.
QObject::connect(this->currentView,
SIGNAL(setAnimationControlState(bool)),
this->ui.timeControlWidget,
SLOT(enableAnimationControls(bool)));
QObject::connect(this->currentView,
SIGNAL(setAnimationControlInfo(double, double, int)),
this->ui.timeControlWidget,
SLOT(updateAnimationControls(double, double, int)));
// Set the connection for the parallel projection button
QObject::connect(this->ui.parallelProjButton,
SIGNAL(toggled(bool)),
this->currentView,
SLOT(onParallelProjection(bool)));
}
/**
* This function loads and renders data from the given source for the
* standalone mode.
* @param source a ParaView compatible source
*/
void MdViewerWidget::onDataLoaded(pqPipelineSource* source)
{
source->updatePipeline();
this->renderAndFinalSetup();
}
/**
* This function is responsible for carrying out actions when ParaView
* says the rendering is completed. It currently handles making sure the
* color selection widget state is passed between views.
*/
void MdViewerWidget::renderingDone()
{
if (this->viewSwitched)
{
this->viewSwitched = false;
this->currentView->setColorsForView();
}
}
/**
* This function determines the type of source plugin and sets the workspace
* name so that the data can be retrieved and rendered.
* @param workspaceName The workspace name for the data.
* @param workspaceType A numeric indicator of the workspace type.
* @param instrumentName The name of the instrument which measured the workspace data.
*/
void MdViewerWidget::renderWorkspace(QString workspaceName, int workspaceType, std::string instrumentName)
{
QString sourcePlugin = "";
if (VatesViewerInterface::PEAKS == workspaceType)
{
sourcePlugin = "Peaks Source";
}
else if (VatesViewerInterface::MDHW == workspaceType)
{
sourcePlugin = "MDHW Source";
}
else
{
sourcePlugin = "MDEW Source";
}
// Load a new source plugin
this->currentView->setPluginSource(sourcePlugin, workspaceName);
this->renderAndFinalSetup();
// Reset the current view to the correct initial view
// Note that we can only reset if a source plugin exists.
// Also note that we can only reset the current view to the
// correct initial after calling renderAndFinalSetup. We first
// need to load in the current view and then switch to be inline
// with the current architecture.
if (VatesViewerInterface::PEAKS != workspaceType)
{
resetCurrentView(workspaceType, instrumentName);
}
}
/**
* Reset the current view if this is required
* @param workspaceType The type of workspace.
* @param instrumentName The name of the instrument.
*/
void MdViewerWidget::resetCurrentView(int workspaceType, const std::string& instrumentName)
{
// Check if the current view is the correct initial view for the workspace type and the instrument
ModeControlWidget::Views initialView = getInitialView(workspaceType, instrumentName);
bool isSetToCorrectInitialView = false;
switch(initialView)
{
case ModeControlWidget::STANDARD:
{
isSetToCorrectInitialView = dynamic_cast<StandardView *>(this->currentView) != 0;
}
break;
case ModeControlWidget::MULTISLICE:
{
isSetToCorrectInitialView = dynamic_cast<MultiSliceView *>(this->currentView) != 0;
}
break;
case ModeControlWidget::THREESLICE:
{
isSetToCorrectInitialView = dynamic_cast<ThreeSliceView *>(this->currentView) != 0;
}
break;
case ModeControlWidget::SPLATTERPLOT:
{
isSetToCorrectInitialView = dynamic_cast<SplatterPlotView *>(this->currentView) != 0;
}
break;
default:
isSetToCorrectInitialView = false;
break;
}
if (isSetToCorrectInitialView == false)
{
this->ui.modeControlWidget->setToSelectedView(initialView);
}
this->initialView = initialView;
}
/*
* Provides an initial view. This view is specified either in the
* Mantid.user.properties file or by the most common technique of the
* instrument which is associated with the workspace data.
* @param workspaceType The work space type.
* @param instrumentName The name of the instrument with which the workspace
* data was measured.
* @returns An initial view.
*/
ModeControlWidget::Views MdViewerWidget::getInitialView(int workspaceType, std::string instrumentName)
{
// Get the possible initial views
std::string initialViewFromUserProperties = Mantid::Kernel::ConfigService::Instance().getVsiInitialView();
std::string initialViewFromTechnique = getViewForInstrument(instrumentName);
// The user-properties-defined default view takes precedence over the techique-defined default view
std::string initialView = initialViewFromUserProperties.empty() ? initialViewFromTechnique : initialViewFromUserProperties;
ModeControlWidget::Views view = this->ui.modeControlWidget->getViewFromString(initialView);
// Make sure that the default view is compatible with the current workspace, e.g. a a histo workspace cannot have a splatter plot
return checkViewAgainstWorkspace(view, workspaceType);
}
/**
* Get the view which is adequat for a specified machine
* @param instrumentName The name of the instrument with which the workspace
* data was measured.
* @returns A view.
*/
std::string MdViewerWidget::getViewForInstrument(const std::string& instrumentName) const
{
// If nothing is specified the standard view is chosen
if (instrumentName.empty())
{
return "STANDARD";
}
// Check for techniques
// Precedence is 1. Single Crystal Diffraction -->SPLATTERPLOT
// 2. Neutron Diffraction --> SPLATTERPLOT
// 3. *Spectroscopy* --> MULTISLICE
// 4. Other --> STANDARD
const std::set<std::string> techniques = Mantid::Kernel::ConfigService::Instance().getInstrument(instrumentName).techniques();
std::string associatedView;
if (techniques.count("Single Crystal Diffraction") > 0 )
{
associatedView = "SPLATTERPLOT";
}
else if (techniques.count("Neutron Diffraction") > 0 )
{
associatedView = "SPLATTERPLOT";
} else if (checkIfTechniqueContainsKeyword(techniques, "Spectroscopy"))
{
associatedView = "MULTISLICE";
}
else
{
associatedView = "STANDARD";
}
return associatedView;
}
/**
* Check if a set of techniques contains a technique which matches specified keyword
* @param techniques A set of techniques
* @param keyword A keyword
* @returns True if the keyword is contained in at least one technique else false.
*/
bool MdViewerWidget::checkIfTechniqueContainsKeyword(const std::set<std::string>& techniques, const std::string& keyword) const
{
boost::regex pattern( "(.*)" + keyword + "(.*)");
for (std::set<std::string>::iterator it = techniques.begin(); it != techniques.end(); ++it)
{
if (boost::regex_match(*it, pattern))
{
return true;
}
}
return false;
}
/*
* Check that the selected default view is compatible with the workspace type
*
* @param view An initial view.
* @param workspaceType The type of workspace.
* @returns A user-specified inital view or the standard view.
*/
ModeControlWidget::Views MdViewerWidget::checkViewAgainstWorkspace(ModeControlWidget::Views view, int workspaceType)
{
ModeControlWidget::Views selectedView;
if (VatesViewerInterface::MDHW == workspaceType)
{
// Histo workspaces cannot have a splatter plot,
if (view == ModeControlWidget::SPLATTERPLOT)
{
g_log.warning() << "Selected a splatter plot for a histo workspace. Defaulted to standard view. \n";
selectedView = ModeControlWidget::STANDARD;
}
else
{
selectedView = view;
}
}
else
{
selectedView = view;
}
return selectedView;
}
/**
* This function performs setup for the plugin mode of the Vates Simple
* Interface. It calls a number of defined functions to complete the process.
*/
void MdViewerWidget::setupPluginMode()
{
this->createAppCoreForPlugin();
this->checkEnvSetup();
this->setupUiAndConnections();
if (!this->isPluginInitialized)
{
this->setupParaViewBehaviors();
this->createMenus();
}
this->setupMainView();
}
/**
* This function tells the current view to render the data, perform any
* necessary checks on the view given the workspace type and update the
* animation controls if necessary.
*/
void MdViewerWidget::renderAndFinalSetup()
{
this->setDefaultColorForBackground();
this->currentView->render();
this->currentView->setColorsForView();
this->currentView->checkView(this->initialView);
this->currentView->updateAnimationControls();
// Only load the default color map for the first time
// that a representation is created.
if (this->startingUp)
{
this->ui.colorSelectionWidget->loadDefaultColorMap();
this->startingUp = false;
}
}
/**
* Set the background color for this view.
*/
void MdViewerWidget::setDefaultColorForBackground()
{
// Get background setting
BackgroundRgbProvider backgroundRgbProvider;
std::vector<double> backgroundRgb = backgroundRgbProvider.getRgb();
vtkSMDoubleVectorProperty* background = vtkSMDoubleVectorProperty::SafeDownCast(this->currentView->getView()->getViewProxy()->GetProperty("Background"));
background->SetElements3(backgroundRgb[0],backgroundRgb[1],backgroundRgb[2]);
this->currentView->getView()->resetCamera();
}
/**
* This function is used during the post-apply process of particular pipeline
* filters to check for updates to anything that relies on information from the
* rendered data.
*/
void MdViewerWidget::checkForUpdates()
{
pqPipelineSource *src = pqActiveObjects::instance().activeSource();
if (NULL == src)
{
return;
}
vtkSMProxy *proxy = src->getProxy();
if (strcmp(proxy->GetXMLName(), "MDEWRebinningCutter") == 0)
{
this->currentView->onAutoScale();
this->currentView->updateAnimationControls();
this->currentView->updateView();
this->currentView->updateUI();
}
if (QString(proxy->GetXMLName()).contains("Threshold"))
{
this->ui.colorSelectionWidget->enableControls(true);
vtkSMDoubleVectorProperty *range = \
vtkSMDoubleVectorProperty::SafeDownCast(\
proxy->GetProperty("ThresholdBetween"));
this->ui.colorSelectionWidget->setColorScaleRange(range->GetElement(0),
range->GetElement(1));
}
if (QString(proxy->GetXMLName()).contains("ScaleWorkspace"))
{
this->currentView->resetDisplay();
}
}
/**
* This function executes the logic for switching views on the main level
* window.
* @param v the view mode to switch to
*/
void MdViewerWidget::switchViews(ModeControlWidget::Views v)
{
this->viewSwitched = true;
this->currentView->closeSubWindows();
this->disconnectDialogs();
this->removeProxyTabWidgetConnections();
this->hiddenView = this->setMainViewWidget(this->ui.viewWidget, v);
this->hiddenView->setColorScaleState(this->ui.colorSelectionWidget);
this->hiddenView->hide();
this->viewLayout->removeWidget(this->currentView);
this->swapViews();
this->viewLayout->addWidget(this->currentView);
this->currentView->installEventFilter(this);
this->currentView->show();
this->hiddenView->hide();
this->setParaViewComponentsForView();
this->connectDialogs();
this->hiddenView->close();
this->hiddenView->destroyView();
delete this->hiddenView;
this->setDefaultColorForBackground(); // Keeps background color to default value
this->currentView->render();
this->currentView->setColorsForView();
this->ui.colorSelectionWidget->loadDefaultColorMap(); // Load the default color map
this->currentView->checkViewOnSwitch();
this->updateAppState();
this->initialView = v;
}
/**
* This function performs a standard pointer swap for the view switching.
*/
void MdViewerWidget::swapViews()
{
ViewBase *temp;
temp = this->currentView;
this->currentView = this->hiddenView;
this->hiddenView = temp;
}
/**
* This function allows one to filter the Qt events and look for a hide
* event. As long as the event does not come from the system (minimize VSI
* window or switch virtual desktops), it then executes source cleanup and
* view mode switch if the viewer is in plugin mode.
* @param obj the subject of the event
* @param ev the actual event
* @return true if the event was handled
*/
bool MdViewerWidget::eventFilter(QObject *obj, QEvent *ev)
{
if (this->currentView == obj)
{
if (this->pluginMode && QEvent::Hide == ev->type() &&
!ev->spontaneous())
{
if (this->ui.parallelProjButton->isChecked())
{
this->ui.parallelProjButton->toggle();
}
this->ui.colorSelectionWidget->reset();
this->currentView->setColorScaleState(this->ui.colorSelectionWidget);
pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder();
builder->destroySources();
this->ui.modeControlWidget->setToStandardView();
return true;
}
}
return VatesViewerInterface::eventFilter(obj, ev);
}
/**
* This function performs shutdown procedures when MantidPlot is shut down,
*/
void MdViewerWidget::shutdown()
{
// This seems to cure a XInitThreads error.
pqPVApplicationCore::instance()->deleteLater();
}
/**
* This function creates the main view widget specific menu items.
*/
void MdViewerWidget::createMenus()
{
QMenuBar *menubar;
if (this->pluginMode)
{
menubar = new QMenuBar(this->parentWidget());
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed);
menubar->setSizePolicy(policy);
}
else
{
menubar = qobject_cast<QMainWindow *>(this->parentWidget())->menuBar();
}
QMenu *viewMenu = menubar->addMenu(QApplication::tr("&View"));
this->lodAction = new QAction(QApplication::tr("Level-of-Detail (LOD...)"), this);
this->lodAction->setShortcut(QKeySequence::fromString("Ctrl+Shift+L"));
this->lodAction->setStatusTip(QApplication::tr("Enable/disable level-of-detail threshold."));
this->lodAction->setCheckable(true);
this->lodAction->setChecked(true);
QObject::connect(this->lodAction, SIGNAL(toggled(bool)),
this, SLOT(onLodToggled(bool)));
viewMenu->addAction(this->lodAction);
QAction *screenShotAction = new QAction(QApplication::tr("Save Screenshot"), this);
screenShotAction->setShortcut(QKeySequence::fromString("Ctrl+Shift+R"));
screenShotAction->setStatusTip(QApplication::tr("Save a screenshot of the current view."));
this->screenShot = new SaveScreenshotReaction(screenShotAction);
viewMenu->addAction(screenShotAction);
QAction *settingsAction = new QAction(QApplication::tr("View Settings..."), this);
settingsAction->setShortcut(QKeySequence::fromString("Ctrl+Shift+S"));
settingsAction->setStatusTip(QApplication::tr("Show the settings for the current view."));
this->viewSettings = new pqViewSettingsReaction(settingsAction);
viewMenu->addAction(settingsAction);
QMenu *helpMenu = menubar->addMenu(QApplication::tr("&Help"));
QAction *wikiHelpAction = new QAction(QApplication::tr("Show Wiki Help"), this);
wikiHelpAction->setShortcut(QKeySequence::fromString("Ctrl+Shift+H"));
wikiHelpAction->setStatusTip(QApplication::tr("Show the wiki help page in a browser."));
QObject::connect(wikiHelpAction, SIGNAL(triggered()),
this, SLOT(onWikiHelp()));
helpMenu->addAction(wikiHelpAction);
if (this->pluginMode)
{
this->ui.verticalLayout_4->insertWidget(0, menubar);
}
}
/**
* This function adds the menus defined here to a QMainWindow menu bar.
* This must be done after the setup of the standalone application so that
* the MdViewerWidget menus aren't added before the standalone ones.
*/
void MdViewerWidget::addMenus()
{
this->createMenus();
}
/**
* This function intercepts the LOD menu action checking and calls the
* correct slot on the current view.
* @param state : whether the action is checked or not
*/
void MdViewerWidget::onLodToggled(bool state)
{
this->currentView->onLodThresholdChange(state, this->lodThreshold);
}
/**
* This function handles creating the rotation point input dialog box and
* setting the communication between it and the current view.
*/
void MdViewerWidget::onRotationPoint()
{
if (NULL == this->rotPointDialog)
{
this->rotPointDialog = new RotationPointDialog(this);
this->connectRotationPointDialog();
}
this->rotPointDialog->show();
this->rotPointDialog->raise();
this->rotPointDialog->activateWindow();
}
/**
* This function shows the wiki help page for the simple interface in a
* browser.
*/
void MdViewerWidget::onWikiHelp()
{
QDesktopServices::openUrl(QUrl(QString("http://www.mantidproject.org/") +
"VatesSimpleInterface_v2"));
}
/**
* This function disconnects the present instances of the color options and the
* point rotation dialog boxes from the current view. This is necessary on
* switch view since the connection to the current view is destroyed.
*/
void MdViewerWidget::disconnectDialogs()
{
if (NULL != this->rotPointDialog)
{
this->rotPointDialog->close();
QObject::disconnect(this->rotPointDialog, 0, this->currentView, 0);
}
}
/**
* This function sets up the connections between the color selection widget
* items and the current view.
*/
void MdViewerWidget::connectColorSelectionWidget()
{
// Set color selection widget <-> view signals/slots
QObject::connect(this->ui.colorSelectionWidget,
SIGNAL(colorMapChanged(const pqColorMapModel *)),
this->currentView,
SLOT(onColorMapChange(const pqColorMapModel *)));
QObject::connect(this->ui.colorSelectionWidget,
SIGNAL(colorScaleChanged(double, double)),
this->currentView,
SLOT(onColorScaleChange(double, double)));
QObject::connect(this->currentView, SIGNAL(dataRange(double, double)),
this->ui.colorSelectionWidget,
SLOT(setColorScaleRange(double, double)));
QObject::connect(this->ui.colorSelectionWidget, SIGNAL(autoScale()),
this->currentView, SLOT(onAutoScale()));
QObject::connect(this->ui.colorSelectionWidget, SIGNAL(logScale(int)),
this->currentView, SLOT(onLogScale(int)));
QObject::connect(this->currentView, SIGNAL(lockColorControls(bool)),
this->ui.colorSelectionWidget,
SLOT(enableControls(bool)));
}
/**
* This function sets up the connections between the rotation point dialog and
* the current view.
*/
void MdViewerWidget::connectRotationPointDialog()
{
if (NULL != this->rotPointDialog)
{
QObject::connect(this->rotPointDialog,
SIGNAL(sendCoordinates(double,double,double)),
this->currentView,
SLOT(onResetCenterToPoint(double,double,double)));
}
}
/**
* This function sets up the connections for all the dialogs associated with
* the MdViewerWidget.
*/
void MdViewerWidget::connectDialogs()
{
this->connectRotationPointDialog();
}
/**
* This function handles any update to the state of application components
* like menus, menu items, buttons, views etc.
*/
void MdViewerWidget::updateAppState()
{
this->viewSettings->updateEnableState();
ThreeSliceView *tsv = dynamic_cast<ThreeSliceView *>(this->currentView);
SplatterPlotView *spv = dynamic_cast<SplatterPlotView *>(this->currentView);
if (NULL != tsv || NULL != spv)
{
this->currentView->onLodThresholdChange(false, this->lodThreshold);
this->lodAction->setChecked(false);
}
else
{
this->currentView->onLodThresholdChange(true, this->lodThreshold);
this->lodAction->setChecked(true);
}
}
/**
* This function responds to the replacement of a workspace. It does not
* handle workspace renaming. Also, by default it replaces the original
* representation with a new one, deleting the old one first.
* @param wsName : Name of workspace changing
* @param ws : Pointer to changing workspace
*/
void MdViewerWidget::afterReplaceHandle(const std::string &wsName,
const boost::shared_ptr<Mantid::API::Workspace> ws)
{
UNUSED_ARG(ws);
pqPipelineSource *src = this->currentView->hasWorkspace(wsName.c_str());
if (NULL != src)
{
// Have to mark the filter as modified to get it to update. Do this by
// changing the requested workspace name to a dummy name and then change
// back. However, push the change all the way down for it to work.
vtkSMPropertyHelper(src->getProxy(),
"Mantid Workspace Name").Set("ChangeMe!");
vtkSMSourceProxy *srcProxy = vtkSMSourceProxy::SafeDownCast(src->getProxy());
srcProxy->UpdateVTKObjects();
srcProxy->Modified();
srcProxy->UpdatePipelineInformation();
src->updatePipeline();
vtkSMPropertyHelper(src->getProxy(),
"Mantid Workspace Name").Set(wsName.c_str());
// Update the source so that it retrieves the data from the Mantid workspace
srcProxy = vtkSMSourceProxy::SafeDownCast(src->getProxy());
srcProxy->UpdateVTKObjects();
srcProxy->Modified();
srcProxy->UpdatePipelineInformation();
src->updatePipeline();
this->currentView->setColorsForView();
this->currentView->renderAll();;
}
}
/**
* This function responds to a workspace being deleted. If there are one or
* more PeaksWorkspaces present, the requested one will be deleted. Otherwise,
* if it is an IMDWorkspace, everything goes!
* @param wsName : Name of workspace being deleted
* @param ws : Pointer to workspace being deleted
*/
void MdViewerWidget::preDeleteHandle(const std::string &wsName,
const boost::shared_ptr<Workspace> ws)
{
UNUSED_ARG(ws);
pqPipelineSource *src = this->currentView->hasWorkspace(wsName.c_str());
if (NULL != src)
{
unsigned int numSources = this->currentView->getNumSources();
if (numSources > 1)
{
pqObjectBuilder *builder = pqApplicationCore::instance()->getObjectBuilder();
if (this->currentView->isPeaksWorkspace(src))
{
builder->destroy(src);
return;
}
}
emit this->requestClose();
}
}
} // namespace SimpleGui
} // namespace Vates
} // namespace Mantid