From 25c2dab99fc18d93f0cfe38567c24fe2707b8ce7 Mon Sep 17 00:00:00 2001 From: Robert Whitley <robert.whitley@stfc.ac.uk> Date: Fri, 15 Jul 2011 10:58:40 +0000 Subject: [PATCH] Refs #3332 Implemented a simple send to option on the workspace context menu in MantidPlot which saves the current workspace and opens it up on another program. The menu is populated by the programs defined by the user in the properties file. --- .../Kernel/inc/MantidKernel/ConfigService.h | 2 + .../Framework/Kernel/src/ConfigService.cpp | 23 +++ .../Properties/MantidTest.properties | 3 +- .../MantidPlot/src/ApplicationWindow.cpp | 8 +- .../MantidPlot/src/Mantid/MantidDock.cpp | 160 +++++++++++++++++- .../Mantid/MantidPlot/src/Mantid/MantidDock.h | 9 +- .../MantidPlot/src/Mantid/MantidMatrix.cpp | 2 +- .../Mantid/MantidPlot/src/Mantid/MantidUI.cpp | 73 ++++---- Code/Mantid/MantidPlot/src/Mantid/MantidUI.h | 11 +- 9 files changed, 229 insertions(+), 62 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h index a48818af4eb..73e522f4254 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h @@ -120,6 +120,8 @@ namespace Mantid std::string getString(const std::string& keyName, bool use_cache=true) const; /// Searches for a key in the configuration property std::vector<std::string> getKeys(const std::string& keyName) const; + /// Launches a process i.e opening a program + void ConfigServiceImpl::launchProcess(const std::string& programFilePath, const std::vector<std::string>& programArguments) const; /// Sets a configuration property void setString(const std::string & keyName, const std::string & keyValue); // Searches for a configuration property and returns its value diff --git a/Code/Mantid/Framework/Kernel/src/ConfigService.cpp b/Code/Mantid/Framework/Kernel/src/ConfigService.cpp index f1cd69188b7..da2ebe3cb02 100644 --- a/Code/Mantid/Framework/Kernel/src/ConfigService.cpp +++ b/Code/Mantid/Framework/Kernel/src/ConfigService.cpp @@ -23,6 +23,7 @@ #include <Poco/DOM/NodeList.h> #include <Poco/Notification.h> #include <Poco/Environment.h> +#include <Poco/Process.h> #include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/join.hpp> @@ -784,6 +785,8 @@ void ConfigServiceImpl::saveConfig(const std::string & filename) const writer.close(); } + + /** Searches for a string within the currently loaded configuaration values and * returns the value as a string. If the key is one of those that was a possible relative path * then the local store is searched first. @@ -836,6 +839,26 @@ std::vector<std::string> ConfigServiceImpl::getKeys(const std::string& keyName) return keyVector; } +/** Runs a command line string to open a program. The function can take program arguments. + * i.e it can load in a file to the program on startup. + * + * @param programFilePath :: The directory where the program is located. + * @param programArguments :: The arguments that the program can take on startup. For example, + * the file to load up. + */ + +void ConfigServiceImpl::launchProcess(const std::string& programFilePath, const std::vector<std::string>& programArguments) const +{ + try + { + Poco::Process::launch(programFilePath, programArguments); + } + catch(Poco::SystemException &e) + { + throw std::runtime_error(e.what()); + } +} + /** * Set a configuration property. An existing key will have its value updated. * @param key :: The key to refer to this property diff --git a/Code/Mantid/Framework/Properties/MantidTest.properties b/Code/Mantid/Framework/Properties/MantidTest.properties index d95d88f40ea..0e5808fb509 100644 --- a/Code/Mantid/Framework/Properties/MantidTest.properties +++ b/Code/Mantid/Framework/Properties/MantidTest.properties @@ -20,5 +20,4 @@ defaultsave.directory = ../../nonexistent workspace.sendto.1 = python,SaveNexus workspace.sendto.2 = gsas,SaveGSS workspace.sendto.3 = SansView,SaveCansas1D -workspace.sendto.4.5 = SansView,SaveCansas1D - +workspace.sendto.4.5 = SansView,SaveCansas1D \ No newline at end of file diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 33fd62a73e5..38e6d68c3a7 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -3958,8 +3958,8 @@ void ApplicationWindow::importASCII(const QStringList& files, int import_mode, c case ImportASCIIDialog::NewWorkspace: { try - { - Mantid::API::IAlgorithm_sptr alg =mantidUI->CreateAlgorithm("LoadAscii"); + {///////////////////////////////////////////////////////////////// + Mantid::API::IAlgorithm_sptr alg =mantidUI->createAlgorithm("LoadAscii"); QStringList sorted_files = files; sorted_files.sort(); for (int i=0; i<sorted_files.size(); i++){ @@ -6160,8 +6160,8 @@ void ApplicationWindow::exportASCII(const QString& tableName, const QString& sep { //call save ascii try - { - Mantid::API::IAlgorithm_sptr alg =mantidUI->CreateAlgorithm("SaveAscii"); + {//////////////////////////////////////////////////// + Mantid::API::IAlgorithm_sptr alg =mantidUI->createAlgorithm("SaveAscii"); alg->setPropertyValue("Filename",fname.toStdString()); alg->setPropertyValue("Workspace",tableName.toStdString()); alg->execute(); diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidDock.cpp b/Code/Mantid/MantidPlot/src/Mantid/MantidDock.cpp index b251595b07c..b98e8a0c7d9 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidDock.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidDock.cpp @@ -7,6 +7,7 @@ #include <MantidAPI/IEventWorkspace.h> #include <MantidAPI/IMDEventWorkspace.h> #include <MantidAPI/IMDWorkspace.h> +#include <MantidAPI/FileProperty.h> #include <MantidGeometry/MDGeometry/IMDDimension.h> #include "MantidMatrix.h" #include <QInputDialog> @@ -25,6 +26,7 @@ #include <QtGui> #include <map> +#include <vector> #include <iostream> #include <sstream> @@ -67,6 +69,7 @@ QDockWidget(tr("Workspaces"),parent), m_mantidUI(mui), m_known_groups() // m_loadMenu = new QMenu(this); + QAction* loadFileAction = new QAction("File",this); QAction *loadDAEAction = new QAction("from DAE",this); m_loadMapper = new QSignalMapper(this); @@ -232,6 +235,16 @@ void MantidDockWidget::createWorkspaceMenuActions() m_saveNexus = new QAction(tr("Save Nexus"),this); connect(m_saveNexus,SIGNAL(activated()),m_mantidUI,SLOT(saveNexusWorkspace())); + //m_saveToProgram = new QMenu(tr("Save to program"),this); + + ////Sub-menu of save to programs + //m_program1 = new QAction(tr("Program 1"),this); + //connect(m_program1,SIGNAL(activated()),this,SLOT(saveToProgram1())); + //m_program2 = new QAction(tr("Program 2"),this); + //connect(m_program2,SIGNAL(activated()),this,SLOT(saveToProgram2())); + //m_program3 = new QAction(tr("Program 3"),this); + //connect(m_program3,SIGNAL(activated()),this,SLOT(saveToProgram3())); + m_rename = new QAction(tr("Rename"),this); connect(m_rename,SIGNAL(activated()),this,SLOT(renameWorkspace())); @@ -779,6 +792,124 @@ void MantidDockWidget::deleteWorkspaces() }//end of for loop for selected items } +/** +* Saves a workspace based on the program the user chooses to save to. +* @param programSave :: A string containing the name of the program +*/ + +void MantidDockWidget::saveToProgram(const QString & name) +{ + //Create a map for the keys and details to go into + std::map<std::string,std::string> programKeysAndDetails; + programKeysAndDetails["name"] = name.toStdString(); + + //Could use a standard vector but no #include <vector> + //Get a list of the program detail keys (mandatory - target, saveusing) (optional - arguments, save parameters, workspace type) + std::vector<std::string> programKeys = (Mantid::Kernel::ConfigService::Instance().getKeys(("workspace.sendto." + programKeysAndDetails.find("name")->second))); + + for (int i(0); i<programKeys.size(); i++) + { + //Assign a key to its value using the map + programKeysAndDetails[programKeys[i]] = (Mantid::Kernel::ConfigService::Instance().getString(("workspace.sendto." + programKeysAndDetails.find("name")->second + "." + programKeys[i]))); + } + + //Check to see if mandatory information is included + if ((programKeysAndDetails.count("name") != 0) && (programKeysAndDetails.count("target") != 0) && (programKeysAndDetails.count("saveusing") != 0)) + { + QFileInfo target = QString::fromStdString(programKeysAndDetails.find("target")->second); + if(target.exists()) + { + //Setup a shared pointer for the algorithm using the appropriate save type + Mantid::API::IAlgorithm_sptr alg; + + //Convert to QString and create Algorithm + QString saveUsing = QString::fromStdString(programKeysAndDetails.find("saveusing")->second); + + //Create a new save based on what files the new program can open + alg = m_mantidUI->createAlgorithm(saveUsing); + + //Get the file extention based on the workspace + Property* prop = alg->getProperty("Filename"); + FileProperty *fileProp = dynamic_cast<FileProperty*>(prop); + std::string ext; + if(fileProp) + { + ext = fileProp->getDefaultExt(); + } + + //Save as.. default save + the file type i.e .nxs + alg->setPropertyValue("fileName", "auto_save_" + selectedWsName.toStdString() + ext); + + //Save the workspace + alg->setPropertyValue("InputWorkspace", selectedWsName.toStdString()); + + //If there are any save parameters + if (programKeysAndDetails.count("saveparameters") != 0) + { + QString saveParametersGrouped = QString::fromStdString(programKeysAndDetails.find("saveparameters")->second); + QStringList saveParameters = saveParametersGrouped.split(','); + + //For each one found split it up and assign the parameter + for (int i(0); i<saveParameters.size(); i++) + { + QStringList saveParameterDetails = saveParameters[i].split('='); + std::string saveParameterName = saveParameterDetails[0].toStdString(); + + if(saveParameterDetails[1] == "True") + alg->setProperty(saveParameterName, true); + else if(saveParameterDetails[1] == "False") + alg->setProperty(saveParameterName, false); + else //if not true or false then must be a value + { + alg->setPropertyValue(saveParameterName, saveParameterDetails[1].toStdString()); + } + } + } + + //Execute the save + m_mantidUI->executeAlgorithmAsync(alg, true); + //alg->execute(); + + //Get the save location of the file (should be default Mantid folder) + //std::string savedFile = alg->getProperty("Filename"); + QString savedFile = QString::fromStdString(alg->getProperty("Filename")); + QStringList arguments; + + //Arguments for the program to take. Default will be the file anyway. + if (programKeysAndDetails.count("arguments") != 0) + { + QString temp = QString::fromStdString(programKeysAndDetails.find("arguments")->second); + temp.replace(QString("[File]"), savedFile); + //temp.replace(QString("[User]"), user; + arguments = temp.split(","); + } + else + arguments.insert(0, savedFile); + + //convert the list into a standard vector for compatibility with Poco + std::vector<std::string> argumentsV; + + for (int i(0); i<arguments.size(); i++) + { + argumentsV.assign(1, (arguments[i].toStdString())); + } + + //Execute the program + try + { + Mantid::Kernel::ConfigService::Instance().launchProcess(programKeysAndDetails.find("target")->second, argumentsV); + } + catch(std::runtime_error&) + { + QMessageBox::information(this, "Error", "User tried to open program from: " + QString::fromStdString(programKeysAndDetails.find("target")->second) + " There was an error opening the program. Please check the target and arguments list to ensure that these are correct"); + } + } + else + QMessageBox::information(this, "Target Path Error", "User tried to open program from: " + QString::fromStdString(programKeysAndDetails.find("target")->second) + " The target file path for the program can't be found. Please check that the full path is correct"); + } +} + + void MantidDockWidget::renameWorkspace() { //get selected workspace @@ -806,7 +937,7 @@ void MantidDockWidget::showDetectorTable() void MantidDockWidget::popupMenu(const QPoint & pos) { QTreeWidgetItem* treeItem = m_tree->itemAt(pos); - QString selectedWsName(""); + selectedWsName = ""; if( treeItem ) selectedWsName = treeItem->text(0); else m_tree->selectionModel()->clear(); QMenu *menu(NULL); @@ -851,6 +982,30 @@ void MantidDockWidget::popupMenu(const QPoint & pos) } else {} + //Get the names of the programs for the send to option + std::vector<std::string> programNames = (Mantid::Kernel::ConfigService::Instance().getKeys("workspace.sendto.name")); + if (programNames.size() > 0) + { + m_saveToProgram = new QMenu(tr("Send to"),this); + menu->addMenu(m_saveToProgram); + + //Sub-menu for program list + m_programMapper = new QSignalMapper(this); + + for (int i(0); i<programNames.size(); i++) + { + //Convert name from std string to QString for use with QAction menu entry + QString name = QString::fromStdString(programNames[i]); + //Setup new menu option for the program + m_program = new QAction(tr(name),this); + connect(m_program,SIGNAL(activated()),m_programMapper,SLOT(map())); + //Send name of program when clicked + m_programMapper->setMapping(m_program, name); + m_saveToProgram->addAction(m_program); + } + + connect(m_programMapper, SIGNAL(mapped(const QString &)), this, SLOT(saveToProgram(const QString &))); + } //Rename is valid for all workspace types menu->addAction(m_rename); //separate delete @@ -1386,5 +1541,4 @@ void AlgorithmTreeWidget::mouseDoubleClickEvent(QMouseEvent *e) } QTreeWidget::mouseDoubleClickEvent(e); -} - +} \ No newline at end of file diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidDock.h b/Code/Mantid/MantidPlot/src/Mantid/MantidDock.h index 9af4889403e..24c34281fb7 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidDock.h +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidDock.h @@ -37,6 +37,7 @@ public slots: void deleteWorkspaces(); void renameWorkspace(); void populateChildData(QTreeWidgetItem* item); + void saveToProgram(const QString & name); protected slots: void popupMenu(const QPoint & pos); @@ -77,18 +78,20 @@ protected: friend class MantidUI; private: + QString selectedWsName; + MantidUI * const m_mantidUI; QSet<QString> m_known_groups; QPushButton *m_loadButton; - QMenu *m_loadMenu; + QMenu *m_loadMenu, *m_saveToProgram; QPushButton *m_deleteButton; QPushButton *m_groupButton; - QSignalMapper *m_loadMapper; + QSignalMapper *m_loadMapper, *m_programMapper; //Context-menu actions QAction *m_showData, *m_showInst, *m_plotSpec, *m_plotSpecDistr, *m_showDetectors, *m_colorFill, *m_showLogs, *m_showHist, - *m_saveNexus, *m_rename, *m_delete; + *m_saveNexus, *m_rename, *m_delete, *m_program; static Mantid::Kernel::Logger& logObject; }; diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp index 524335a009e..927d1ac1b1e 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidMatrix.cpp @@ -1106,7 +1106,7 @@ bool MantidMatrix::setSelectedColumns() QTableView *tv = activeView(); QItemSelectionModel *selModel = tv->selectionModel(); if( !selModel || !selModel->hasSelection()) return false; - + m_selectedCols.clear(); const QModelIndexList cols = selModel->selectedColumns(); QModelIndexList::const_iterator it; diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp index bbc45aa7329..f2c04a12d8e 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.cpp @@ -290,19 +290,6 @@ int MantidUI::runningAlgCount() const return m_algMonitor->count(); } -/** - CreateAlgorithm - - @param algName :: Algorithm's name - @return Pointer to the created algorithm - */ -IAlgorithm_sptr MantidUI::CreateAlgorithm(const QString& algName) -{ - IAlgorithm_sptr alg = AlgorithmManager::Instance().create(algName.toStdString()); - - return alg; -} - /** * Ticket #678 */ @@ -821,30 +808,11 @@ void MantidUI::executeAlgorithm() bool MantidUI::runAlgorithmAsync_PyCallback(const QString & alg_name) { Mantid::API::IAlgorithm_sptr alg = findAlgorithmPointer(alg_name); - if( !alg ) { return false; } - if( m_algMonitor ) - { - m_algMonitor->add(alg); - } - Poco::ActiveResult<bool> result(alg->executeAsync()); - while( !result.available() ) - { - QCoreApplication::processEvents(); - } - result.wait(); - - try - { - return result.data(); - } - catch( Poco::NullPointerException& ) - { - return false; - } + return executeAlgorithmAsync(alg, true); } /** @@ -1263,19 +1231,38 @@ Mantid::API::IAlgorithm_sptr MantidUI::createAlgorithm(const QString& algName, i return alg; } -void MantidUI::executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg) +bool MantidUI::executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg, const bool wait) { - m_algMonitor->add(alg); + if( m_algMonitor ) + { + m_algMonitor->add(alg); + } - try + if( wait ) { - alg->executeAsync(); + Poco::ActiveResult<bool> result(alg->executeAsync()); + while( !result.available() ) + { + QCoreApplication::processEvents(); + } + result.wait(); + + try + { + return result.data(); + } + catch( Poco::NullPointerException& ) + { + return false; + } } - catch(...) + else { - QMessageBox::critical(appWindow(),"MantidPlot - Algorithm error","Exception is caught"); + alg->executeAsync(); + return true; } } + bool MantidUI::executeICatLogout(int version) { Mantid::API::IAlgorithm_sptr alg = this->createAlgorithm("CatalogLogout", version); @@ -1369,7 +1356,7 @@ void MantidUI::createLoadDAEMantidMatrix(const QString& wsQName) int updateInterval = m_DAE_map[wsName]; if (updateInterval > 0) { - IAlgorithm_sptr updater = CreateAlgorithm("UpdateDAE"); + IAlgorithm_sptr updater = createAlgorithm("UpdateDAE"); updater->setPropertyValue("Workspace",wsName); updater->setPropertyValue("UpdateRate",QString::number(updateInterval).toStdString()); executeAlgorithmAsync(updater); @@ -2710,7 +2697,7 @@ void MantidUI::savedatainNexusFormat(const std::string& fileName,const std::stri { try { - Mantid::API::IAlgorithm_sptr alg =CreateAlgorithm("SaveNexusProcessed"); + Mantid::API::IAlgorithm_sptr alg =createAlgorithm("SaveNexusProcessed"); alg->setPropertyValue("Filename",fileName); alg->setPropertyValue("InputWorkspace",wsName); alg->execute(); @@ -2728,7 +2715,7 @@ void MantidUI::loaddataFromNexusFile(const std::string& wsName,const std::string if(fileName.empty()) return ; try { - Mantid::API::IAlgorithm_sptr alg =CreateAlgorithm("LoadNexus"); + Mantid::API::IAlgorithm_sptr alg =createAlgorithm("LoadNexus"); alg->setPropertyValue("Filename",fileName); alg->setPropertyValue("OutputWorkspace",wsName); if(project)alg->execute(); @@ -2747,7 +2734,7 @@ void MantidUI::loadadataFromRawFile(const std::string& wsName,const std::string& if(fileName.empty()) return ; try { - Mantid::API::IAlgorithm_sptr alg =CreateAlgorithm("LoadRaw"); + Mantid::API::IAlgorithm_sptr alg =createAlgorithm("LoadRaw"); alg->setPropertyValue("Filename",fileName); alg->setPropertyValue("OutputWorkspace",wsName); if(project)alg->execute(); diff --git a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h index 9a9d1e8428b..5617800a0ea 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h +++ b/Code/Mantid/MantidPlot/src/Mantid/MantidUI.h @@ -124,7 +124,11 @@ public: int runningAlgCount() const; // Create an algorithm using Mantid FrameworkManager - Mantid::API::IAlgorithm_sptr CreateAlgorithm(const QString& algName); + // Create a pointer to the named algorithm and version + Mantid::API::IAlgorithm_sptr createAlgorithm(const QString& algName, int version = -1); + + // Execute algorithm asinchronously + bool executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg, const bool wait = false); // Gets a pointer to workspace workspaceName Mantid::API::Workspace_sptr getWorkspace(const QString& workspaceName); @@ -415,11 +419,6 @@ public: private: -// Create a pointer to the named algorithm and version - Mantid::API::IAlgorithm_sptr createAlgorithm(const QString& algName, int version); - // Execute algorithm asinchronously - void executeAlgorithmAsync(Mantid::API::IAlgorithm_sptr alg); - // Notification handlers and corresponding observers. void handleLoadDAEFinishedNotification(const Poco::AutoPtr<Mantid::API::Algorithm::FinishedNotification>& pNf); Poco::NObserver<MantidUI, Mantid::API::Algorithm::FinishedNotification> m_finishedLoadDAEObserver; -- GitLab