// 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 & CSNS, Institute of High Energy Physics, CAS // SPDX - License - Identifier: GPL - 3.0 + #include "MainWindowPresenter.h" #include "GUI/Batch/IBatchPresenterFactory.h" #include "GUI/Common/IDecoder.h" #include "GUI/Common/IEncoder.h" #include "GUI/Common/IFileHandler.h" #include "GUI/Common/IMessageHandler.h" #include "GUI/Runs/IRunsPresenter.h" #include "IMainWindowView.h" #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidKernel/ConfigService.h" #include "MantidQtWidgets/Common/HelpWindow.h" #include "MantidQtWidgets/Common/ISlitCalculator.h" #include "Reduction/Batch.h" namespace MantidQt { namespace CustomInterfaces { namespace ISISReflectometry { using Mantid::API::AlgorithmManager; using Mantid::API::MatrixWorkspace_sptr; using MantidWidgets::ISlitCalculator; // unnamed namespace namespace { Mantid::Kernel::Logger g_log("Reflectometry GUI"); } /** Constructor * @param view :: [input] The view we are managing * @param messageHandler :: Interface to a class that displays messages to * the user * @param fileHandler :: Interface to a class that loads/saves files * @param encoder :: Interface for encoding a batch for saving to file * @param decoder :: Interface for decoding a batch loaded from file * @param slitCalculator :: Interface to the Slit Calculator dialog * @param batchPresenterFactory :: [input] A factory to create the batches * we will manage */ MainWindowPresenter::MainWindowPresenter( IMainWindowView *view, IMessageHandler *messageHandler, IFileHandler *fileHandler, std::unique_ptr<IEncoder> encoder, std::unique_ptr<IDecoder> decoder, std::unique_ptr<ISlitCalculator> slitCalculator, std::unique_ptr<IBatchPresenterFactory> batchPresenterFactory) : m_view(view), m_messageHandler(messageHandler), m_fileHandler(fileHandler), m_instrument(), m_encoder(std::move(encoder)), m_decoder(std::move(decoder)), m_slitCalculator(std::move(slitCalculator)), m_batchPresenterFactory(std::move(batchPresenterFactory)) { view->subscribe(this); for (auto *batchView : m_view->batches()) addNewBatch(batchView); } MainWindowPresenter::~MainWindowPresenter() = default; MainWindowPresenter::MainWindowPresenter(MainWindowPresenter &&) = default; MainWindowPresenter &MainWindowPresenter:: operator=(MainWindowPresenter &&) = default; void MainWindowPresenter::notifyNewBatchRequested() { auto *newBatchView = m_view->newBatch(); addNewBatch(newBatchView); } void MainWindowPresenter::notifyCloseBatchRequested(int batchIndex) { if (m_batchPresenters[batchIndex]->isAutoreducing() || m_batchPresenters[batchIndex]->isProcessing()) { m_messageHandler->giveUserCritical( "Cannot close batch while processing or autoprocessing is in progress", "Error"); return; } if (m_batchPresenters[batchIndex]->requestClose()) { m_batchPresenters.erase(m_batchPresenters.begin() + batchIndex); m_view->removeBatch(batchIndex); } } void MainWindowPresenter::notifyShowOptionsRequested() { // TODO Show the options dialog when it is implemented } void MainWindowPresenter::notifyShowSlitCalculatorRequested() { m_slitCalculator->setCurrentInstrumentName(instrumentName()); m_slitCalculator->processInstrumentHasBeenChanged(); m_slitCalculator->show(); } void MainWindowPresenter::notifyAnyBatchAutoreductionResumed() { for (const auto &batchPresenter : m_batchPresenters) { batchPresenter->notifyAnyBatchAutoreductionResumed(); } } void MainWindowPresenter::notifyAnyBatchAutoreductionPaused() { for (const auto &batchPresenter : m_batchPresenters) { batchPresenter->notifyAnyBatchAutoreductionPaused(); } } // Called on autoreduction normal reduction void MainWindowPresenter::notifyAnyBatchReductionResumed() { for (const auto &batchPresenter : m_batchPresenters) { batchPresenter->notifyAnyBatchReductionResumed(); } disableSaveAndLoadBatch(); } // Called on autoreduction normal reduction void MainWindowPresenter::notifyAnyBatchReductionPaused() { for (const auto &batchPresenter : m_batchPresenters) { batchPresenter->notifyAnyBatchReductionPaused(); } enableSaveAndLoadBatch(); } void MainWindowPresenter::notifyChangeInstrumentRequested( std::string const &newInstrumentName) { auto const hasChanged = (newInstrumentName != instrumentName()); // Re-load instrument regardless of whether it has changed, e.g. if we are // creating a new batch the instrument may not have changed but we still want // the most up to date settings updateInstrument(newInstrumentName); // However, only perform updates if the instrument has changed, otherwise we // may trigger overriding of user-specified settings if (hasChanged) onInstrumentChanged(); } void MainWindowPresenter::notifyUpdateInstrumentRequested() { // An instrument should have been set up before any calls to this function. if (!instrument()) throw std::runtime_error("Internal error: instrument has not been set"); // Re-load instrument with the existing name. updateInstrument(instrumentName()); } void MainWindowPresenter::notifyHelpPressed() { showHelp(); } bool MainWindowPresenter::isAnyBatchProcessing() const { for (const auto &batchPresenter : m_batchPresenters) { if (batchPresenter->isProcessing()) return true; } return false; } bool MainWindowPresenter::isAnyBatchAutoreducing() const { for (const auto &batchPresenter : m_batchPresenters) { if (batchPresenter->isAutoreducing()) return true; } return false; } void MainWindowPresenter::addNewBatch(IBatchView *batchView) { // Remember the instrument name so we can re-set it (it will otherwise // get overridden by the instrument list default in the new batch) auto const instrument = instrumentName(); m_batchPresenters.emplace_back(m_batchPresenterFactory->make(batchView)); m_batchPresenters.back()->acceptMainPresenter(this); initNewBatch(m_batchPresenters.back().get(), instrument); } void MainWindowPresenter::initNewBatch(IBatchPresenter *batchPresenter, std::string const &instrument) { batchPresenter->initInstrumentList(); batchPresenter->notifyInstrumentChanged(instrument); // starts in the paused state batchPresenter->notifyReductionPaused(); // Ensure autoreduce button is enabled/disabled correctly for the new batch if (isAnyBatchAutoreducing()) batchPresenter->notifyAnyBatchAutoreductionResumed(); else batchPresenter->notifyAnyBatchAutoreductionPaused(); } void MainWindowPresenter::showHelp() { MantidQt::API::HelpWindow::showCustomInterface(nullptr, QString("ISIS Reflectometry")); } void MainWindowPresenter::notifySaveBatchRequested(int tabIndex) { auto filename = m_messageHandler->askUserForSaveFileName("JSON (*.json)"); if (filename == "") return; auto map = m_encoder->encodeBatch(m_view, tabIndex, false); m_fileHandler->saveJSONToFile(filename, map); } void MainWindowPresenter::notifyLoadBatchRequested(int tabIndex) { auto filename = m_messageHandler->askUserForLoadFileName("JSON (*.json)"); if (filename == "") return; QMap<QString, QVariant> map; try { map = m_fileHandler->loadJSONFromFile(filename); } catch (const std::runtime_error) { m_messageHandler->giveUserCritical( "Unable to load requested file. Please load a file of " "appropriate format saved from the GUI.", "Error:"); return; } m_decoder->decodeBatch(m_view, tabIndex, map); } void MainWindowPresenter::disableSaveAndLoadBatch() { m_view->disableSaveAndLoadBatch(); } void MainWindowPresenter::enableSaveAndLoadBatch() { m_view->enableSaveAndLoadBatch(); } Mantid::Geometry::Instrument_const_sptr MainWindowPresenter::instrument() const { return m_instrument; } std::string MainWindowPresenter::instrumentName() const { if (m_instrument) return m_instrument->getName(); return std::string(); } void MainWindowPresenter::updateInstrument(const std::string &instrumentName) { setDefaultInstrument(instrumentName); // Load a workspace for this instrument so we can get the actual instrument auto loadAlg = AlgorithmManager::Instance().createUnmanaged("LoadEmptyInstrument"); loadAlg->setChild(true); loadAlg->initialize(); loadAlg->setProperty("InstrumentName", instrumentName); loadAlg->setProperty("OutputWorkspace", "__Reflectometry_GUI_Empty_Instrument"); loadAlg->execute(); MatrixWorkspace_sptr instWorkspace = loadAlg->getProperty("OutputWorkspace"); m_instrument = instWorkspace->getInstrument(); } void MainWindowPresenter::setDefaultInstrument( const std::string &requiredInstrument) { auto &config = Mantid::Kernel::ConfigService::Instance(); auto currentFacility = config.getString("default.facility"); auto requiredFacility = "ISIS"; if (currentFacility != requiredFacility) { config.setString("default.facility", requiredFacility); g_log.notice() << "Facility changed to " << requiredFacility; } auto currentInstrument = config.getString("default.instrument"); if (currentInstrument != requiredInstrument) { config.setString("default.instrument", requiredInstrument); g_log.notice() << "Instrument changed to " << requiredInstrument; } } void MainWindowPresenter::onInstrumentChanged() { // Notify child presenters for (auto &batchPresenter : m_batchPresenters) batchPresenter->notifyInstrumentChanged(instrumentName()); // Notify the slit calculator m_slitCalculator->setCurrentInstrumentName(instrumentName()); m_slitCalculator->processInstrumentHasBeenChanged(); } } // namespace ISISReflectometry } // namespace CustomInterfaces } // namespace MantidQt