From 245e18a03dfe81a350b0e380d69b710260185e45 Mon Sep 17 00:00:00 2001
From: Tobias Knopff <t.knopff@fz-juelich.de>
Date: Tue, 1 Jun 2021 08:11:37 +0200
Subject: [PATCH] Split AppSvc into ProjectManagerStore and MaterialModelStore

---
 GUI/Models/MaterialItemUtils.cpp              |  11 +-
 GUI/Models/MaterialModel.cpp                  |  12 +-
 GUI/Models/MaterialModelStore.cpp             | 100 ++++-------------
 GUI/Models/MaterialModelStore.h               |  42 ++-----
 .../ImportDataWidgets/ImportDataUtils.cpp     |   1 -
 .../RealDataSelectorWidget.cpp                |  18 +--
 .../IntensityDataCanvas.cpp                   |   4 +-
 GUI/Views/MaskWidgets/MaskEditorCanvas.cpp    |   4 +-
 .../MaterialEditor/MaterialEditorUtils.cpp    |   4 +-
 .../RealSpaceBuilderUtils.cpp                 |   4 +-
 .../RealSpaceWidgets/RealSpaceCanvas.cpp      |   4 +-
 .../SimulationSetupWidget.cpp                 |   4 +-
 .../SpecularDataCanvas.cpp                    |   4 +-
 .../SpecularDataImportWidget.cpp              |   3 +-
 GUI/mainwindow/ProjectManagerStore.cpp        | 104 +++++-------------
 GUI/mainwindow/ProjectManagerStore.h          |  43 ++------
 GUI/mainwindow/ProjectUtils.cpp               |   4 +-
 GUI/mainwindow/PyImportAssistant.cpp          |   6 +-
 GUI/mainwindow/projectmanager.cpp             |   6 +-
 19 files changed, 118 insertions(+), 260 deletions(-)

diff --git a/GUI/Models/MaterialItemUtils.cpp b/GUI/Models/MaterialItemUtils.cpp
index 67885372422..90e9d8dd41b 100644
--- a/GUI/Models/MaterialItemUtils.cpp
+++ b/GUI/Models/MaterialItemUtils.cpp
@@ -19,12 +19,12 @@
 #include "GUI/Models/MaterialDataItems.h"
 #include "GUI/Models/MaterialItemContainer.h"
 #include "GUI/Models/MaterialModel.h"
+#include "GUI/Models/MaterialModelStore.h"
 #include "GUI/Models/MesoCrystalItem.h"
 #include "GUI/Models/ParticleCompositionItem.h"
 #include "GUI/Models/ParticleCoreShellItem.h"
 #include "GUI/Models/ParticleItem.h"
 #include "GUI/Models/ParticleLayoutItem.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "Sample/Material/Material.h"
 
 #include <random>
@@ -67,10 +67,10 @@ QColor MaterialItemUtils::randomMaterialColor()
 
 ExternalProperty MaterialItemUtils::defaultMaterialProperty()
 {
-    if (!AppSvc::materialModel())
+    if (!MaterialModelStore::materialModel())
         return ExternalProperty();
 
-    auto materials = AppSvc::materialModel()->topItems<MaterialItem>();
+    auto materials = MaterialModelStore::materialModel()->topItems<MaterialItem>();
     return materials.isEmpty() ? ExternalProperty()
                                : MaterialItemUtils::materialProperty(*materials.front());
 }
@@ -96,11 +96,12 @@ MaterialItemUtils::createDomainMaterial(const ExternalProperty& material_propert
 
 MaterialItem* MaterialItemUtils::findMaterial(const ExternalProperty& material_property)
 {
-    if (!AppSvc::materialModel())
+    if (!MaterialModelStore::materialModel())
         throw Error("MaterialItemUtils::findMaterial() -> Error. "
                     "Attempt to access non-existing material model");
 
-    auto material = AppSvc::materialModel()->materialFromIdentifier(material_property.identifier());
+    auto material = MaterialModelStore::materialModel()
+        ->materialFromIdentifier(material_property.identifier());
 
     if (!material)
         throw Error("MaterialUtils::findMaterial() -> Error. Can't find "
diff --git a/GUI/Models/MaterialModel.cpp b/GUI/Models/MaterialModel.cpp
index b8c38f118a3..49f959e465b 100644
--- a/GUI/Models/MaterialModel.cpp
+++ b/GUI/Models/MaterialModel.cpp
@@ -13,22 +13,22 @@
 //  ************************************************************************************************
 
 #include "GUI/Models/MaterialModel.h"
-#include "GUI/Models/MaterialItemUtils.h"
 #include "GUI/Models/MaterialDataItems.h"
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/Models/MaterialItemUtils.h"
+#include "GUI/Models/MaterialModelStore.h"
 #include "GUI/utils/GUIHelpers.h"
 
 MaterialModel::MaterialModel(QObject* parent) : SessionModel(SessionXML::MaterialModelTag, parent)
 {
     setObjectName(SessionXML::MaterialModelTag);
-    if (AppSvc::materialModel() == nullptr)
-        AppSvc::subscribe(this);
+    if (MaterialModelStore::materialModel() == nullptr)
+        MaterialModelStore::subscribe(this);
 }
 
 MaterialModel::~MaterialModel()
 {
-    if (AppSvc::materialModel() == this)
-        AppSvc::unsubscribe(this);
+    if (MaterialModelStore::materialModel() == this)
+        MaterialModelStore::unsubscribe(this);
 }
 
 MaterialModel* MaterialModel::createCopy(SessionItem* parent)
diff --git a/GUI/Models/MaterialModelStore.cpp b/GUI/Models/MaterialModelStore.cpp
index ddd12bf070c..4b4be73b0ee 100644
--- a/GUI/Models/MaterialModelStore.cpp
+++ b/GUI/Models/MaterialModelStore.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/mainwindow/AppSvc.cpp
-//! @brief     Implements class AppSvc
+//! @file      GUI/Models/MaterialModelStore.cpp
+//! @brief     Implements namespace MaterialModelStore
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,87 +12,35 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/Models/MaterialModelStore.h"
 #include "GUI/Models/Error.h"
 
-ProjectManager* AppSvc::projectManager()
-{
-    return instance().this_projectManager();
+namespace {
+    MaterialModel* theMaterialModel = nullptr;
 }
 
-void AppSvc::subscribe(ProjectManager* projectManager)
-{
-    return instance().this_subscribe(projectManager);
-}
-
-void AppSvc::unsubscribe(ProjectManager* projectManager)
-{
-    instance().this_unsubscribe(projectManager);
-}
+namespace MaterialModelStore {
 
-MaterialModel* AppSvc::materialModel()
-{
-    return instance().this_materialModel();
-}
-
-void AppSvc::subscribe(MaterialModel* materialModel)
-{
-    return instance().this_subscribe(materialModel);
-}
+    MaterialModel* materialModel()
+    {
+        return theMaterialModel;
+    }
 
-void AppSvc::unsubscribe(MaterialModel* materialModel)
-{
-    instance().this_unsubscribe(materialModel);
-}
-
-AppSvc::AppSvc() : m_projectManager(nullptr), m_materialModel(nullptr) {}
-
-ProjectManager* AppSvc::this_projectManager()
-{
-    if (!m_projectManager)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to access "
-                    "non existing ProjectManager.");
-
-    return m_projectManager;
-}
+    void subscribe(MaterialModel* materialModel)
+    {
+        if (theMaterialModel != nullptr)
+            throw Error("MaterialModelStore::subscribe() -> Error. Attempt to subscribe "
+                        "MaterialModel twice.");
 
-MaterialModel* AppSvc::this_materialModel()
-{
-    return m_materialModel;
-}
-
-void AppSvc::this_subscribe(ProjectManager* projectManager)
-{
-    if (m_projectManager != nullptr)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to subscribe "
-                    "ProjectManager twice.");
-
-    m_projectManager = projectManager;
-}
-
-void AppSvc::this_unsubscribe(ProjectManager* projectManager)
-{
-    if (m_projectManager != projectManager)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to unsubscribe "
-                    "ProjectManager before it was subscribed.");
-
-    m_projectManager = nullptr;
-}
-
-void AppSvc::this_subscribe(MaterialModel* materialModel)
-{
-    if (m_materialModel)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to subscribe "
-                    "MaterialModel twice.");
-
-    m_materialModel = materialModel;
-}
+        theMaterialModel = materialModel;
+    }
 
-void AppSvc::this_unsubscribe(MaterialModel* materialModel)
-{
-    if (m_materialModel != materialModel)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to unsubscribe "
-                    "MaterialModel before it was subscribed.");
+    void unsubscribe(MaterialModel* materialModel)
+    {
+        if (theMaterialModel != materialModel)
+            throw Error("MaterialModelStore::unsubscribe -> Error. Attempt to unsubscribe "
+                        "MaterialModel before it was subscribed.");
 
-    m_materialModel = nullptr;
+        theMaterialModel = nullptr;
+    }
 }
diff --git a/GUI/Models/MaterialModelStore.h b/GUI/Models/MaterialModelStore.h
index b03e0b199b5..1e2eb28b38e 100644
--- a/GUI/Models/MaterialModelStore.h
+++ b/GUI/Models/MaterialModelStore.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/mainwindow/AppSvc.h
-//! @brief     Defines class AppSvc
+//! @file      GUI/Models/MaterialModelStore.h
+//! @brief     Defines namespace MaterialModelStore
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,39 +12,19 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
-#define BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
+#ifndef BORNAGAIN_GUI_MODELS_MATERIALMODELSTORE_H
+#define BORNAGAIN_GUI_MODELS_MATERIALMODELSTORE_H
 
-#include "GUI/Models/ISingleton.h"
-
-class ProjectManager;
 class MaterialModel;
 
-//! The AppSvc class provides common access for key components of the GUI.
-
-class AppSvc : public ISingleton<AppSvc> {
-    friend class ISingleton<AppSvc>;
-
-public:
-    static ProjectManager* projectManager();
-    static void subscribe(ProjectManager* projectManager);
-    static void unsubscribe(ProjectManager* projectManager);
+//! The MaterialModelStore holds an instance of the MaterialModel class
 
-    static MaterialModel* materialModel();
-    static void subscribe(MaterialModel* materialModel);
-    static void unsubscribe(MaterialModel* materialModel);
+namespace MaterialModelStore {
 
-private:
-    AppSvc();
-    ProjectManager* this_projectManager();
-    MaterialModel* this_materialModel();
-    void this_subscribe(ProjectManager* projectManager);
-    void this_unsubscribe(ProjectManager* projectManager);
-    void this_subscribe(MaterialModel* materialModel);
-    void this_unsubscribe(MaterialModel* materialModel);
+    MaterialModel* materialModel();
+    void subscribe(MaterialModel* materialModel);
+    void unsubscribe(MaterialModel* materialModel);
 
-    ProjectManager* m_projectManager;
-    MaterialModel* m_materialModel;
-};
+}
 
-#endif // BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
+#endif // BORNAGAIN_GUI_MODELS_MATERIALMODELSTORE_H
diff --git a/GUI/Views/ImportDataWidgets/ImportDataUtils.cpp b/GUI/Views/ImportDataWidgets/ImportDataUtils.cpp
index e0d0d8d426f..f9ac827f37c 100644
--- a/GUI/Views/ImportDataWidgets/ImportDataUtils.cpp
+++ b/GUI/Views/ImportDataWidgets/ImportDataUtils.cpp
@@ -24,7 +24,6 @@
 #include "GUI/Models/InstrumentItems.h"
 #include "GUI/Models/IntensityDataItem.h"
 #include "GUI/Models/RealDataItem.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
 #include "GUI/utils/GUIHelpers.h"
 #include <QApplication>
diff --git a/GUI/Views/ImportDataWidgets/RealDataSelectorWidget.cpp b/GUI/Views/ImportDataWidgets/RealDataSelectorWidget.cpp
index ad15106ae86..e0969499e5f 100644
--- a/GUI/Views/ImportDataWidgets/RealDataSelectorWidget.cpp
+++ b/GUI/Views/ImportDataWidgets/RealDataSelectorWidget.cpp
@@ -22,10 +22,10 @@
 #include "GUI/Views/ImportDataWidgets/ImportDataUtils.h"
 #include "GUI/Views/ImportDataWidgets/RealDataPropertiesWidget.h"
 #include "GUI/Views/ImportDataWidgets/RealDataTreeModel.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/StyledToolBar.h"
 #include "GUI/mainwindow/mainwindow.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include "GUI/utils/GUIHelpers.h"
 #include <QApplication>
 #include <QFileDialog>
@@ -216,8 +216,8 @@ void RealDataSelectorWidget::importData1D()
     }
     filters += ";;Other (*.*)";
 
-    QString selectedFilter = AppSvc::projectManager()->recentlyUsedImportFilter1D();
-    const QString dirname = AppSvc::projectManager()->userImportDir();
+    QString selectedFilter = ProjectManagerStore::projectManager()->recentlyUsedImportFilter1D();
+    const QString dirname = ProjectManagerStore::projectManager()->userImportDir();
 
     const QStringList fileNames =
         QFileDialog::getOpenFileNames(Q_NULLPTR, "Open Intensity Files", dirname, filters,
@@ -226,8 +226,8 @@ void RealDataSelectorWidget::importData1D()
     if (fileNames.isEmpty())
         return;
 
-    AppSvc::projectManager()->setImportDirFromFilePath(fileNames[0]);
-    AppSvc::projectManager()->setRecentlyUsedImportFilter1D(selectedFilter);
+    ProjectManagerStore::projectManager()->setImportDirFromFilePath(fileNames[0]);
+    ProjectManagerStore::projectManager()->setRecentlyUsedImportFilter1D(selectedFilter);
 
     const AbstractDataLoader* selectedLoader = loaderOfFilter.value(selectedFilter, nullptr);
     for (const auto& fileName : fileNames) {
@@ -266,17 +266,17 @@ void RealDataSelectorWidget::importData2D()
     addFilter(IntensityDataIOFactory::automatic, "CSV (*.txt *.csv *.dat)");
     addFilter(IntensityDataIOFactory::automatic, "All (*.*)");
 
-    QString selectedFilter = AppSvc::projectManager()->recentlyUsedImportFilter2D();
+    QString selectedFilter = ProjectManagerStore::projectManager()->recentlyUsedImportFilter2D();
 
-    const QString dirname = AppSvc::projectManager()->userImportDir();
+    const QString dirname = ProjectManagerStore::projectManager()->userImportDir();
     const QStringList fileNames =
         QFileDialog::getOpenFileNames(Q_NULLPTR, "Open Intensity Files", dirname, filters,
                                       &selectedFilter, QFileDialog::DontUseNativeDialog);
     if (fileNames.isEmpty())
         return;
 
-    AppSvc::projectManager()->setImportDirFromFilePath(fileNames[0]);
-    AppSvc::projectManager()->setRecentlyUsedImportFilter2D(selectedFilter);
+    ProjectManagerStore::projectManager()->setImportDirFromFilePath(fileNames[0]);
+    ProjectManagerStore::projectManager()->setRecentlyUsedImportFilter2D(selectedFilter);
 
     const auto selectedLoader =
         loaderOfFilter.value(selectedFilter, IntensityDataIOFactory::automatic);
diff --git a/GUI/Views/IntensityDataWidgets/IntensityDataCanvas.cpp b/GUI/Views/IntensityDataWidgets/IntensityDataCanvas.cpp
index 3ad738b9513..895bed233c2 100644
--- a/GUI/Views/IntensityDataWidgets/IntensityDataCanvas.cpp
+++ b/GUI/Views/IntensityDataWidgets/IntensityDataCanvas.cpp
@@ -19,8 +19,8 @@
 #include "GUI/Views/IntensityDataWidgets/ColorMapCanvas.h"
 #include "GUI/Views/IntensityDataWidgets/IntensityDataFFTPresenter.h"
 #include "GUI/Views/IntensityDataWidgets/SavePlotAssistant.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include <QAction>
 #include <QMouseEvent>
 #include <QSettings>
@@ -88,7 +88,7 @@ void IntensityDataCanvas::onResetViewAction()
 
 void IntensityDataCanvas::onSavePlotAction()
 {
-    QString dirname = AppSvc::projectManager()->userExportDir();
+    QString dirname = ProjectManagerStore::projectManager()->userExportDir();
     SavePlotAssistant saveAssistant;
     saveAssistant.savePlot(dirname, m_colorMap->customPlot(), intensityDataItem()->getOutputData());
 }
diff --git a/GUI/Views/MaskWidgets/MaskEditorCanvas.cpp b/GUI/Views/MaskWidgets/MaskEditorCanvas.cpp
index b431f23fecf..dda98d5f27a 100644
--- a/GUI/Views/MaskWidgets/MaskEditorCanvas.cpp
+++ b/GUI/Views/MaskWidgets/MaskEditorCanvas.cpp
@@ -21,8 +21,8 @@
 #include "GUI/Views/MaskWidgets/MaskGraphicsScene.h"
 #include "GUI/Views/MaskWidgets/MaskGraphicsView.h"
 #include "GUI/Views/MaskWidgets/MaskResultsPresenter.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include <QVBoxLayout>
 
 MaskEditorCanvas::MaskEditorCanvas(QWidget* parent)
@@ -93,7 +93,7 @@ void MaskEditorCanvas::onPresentationTypeRequest(MaskEditorFlags::PresentationTy
 
 void MaskEditorCanvas::onSavePlotRequest()
 {
-    QString dirname = AppSvc::projectManager()->userExportDir();
+    QString dirname = ProjectManagerStore::projectManager()->userExportDir();
 
     SavePlotAssistant saveAssistant;
     saveAssistant.savePlot(dirname, m_scene->colorMap()->customPlot(),
diff --git a/GUI/Views/MaterialEditor/MaterialEditorUtils.cpp b/GUI/Views/MaterialEditor/MaterialEditorUtils.cpp
index f7dd09106cd..6dbe74c0511 100644
--- a/GUI/Views/MaterialEditor/MaterialEditorUtils.cpp
+++ b/GUI/Views/MaterialEditor/MaterialEditorUtils.cpp
@@ -15,14 +15,14 @@
 #include "GUI/Views/MaterialEditor/MaterialEditorUtils.h"
 #include "GUI/Models/MaterialItemUtils.h"
 #include "GUI/Models/MaterialModel.h"
+#include "GUI/Models/MaterialModelStore.h"
 #include "GUI/Views/MaterialEditor/MaterialEditorDialog.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/mainwindow.h"
 #include <QColorDialog>
 
 ExternalProperty MaterialEditorUtils::selectMaterialProperty(const ExternalProperty& previous)
 {
-    MaterialEditorDialog dialog(AppSvc::materialModel(), MainWindow::instance());
+    MaterialEditorDialog dialog(MaterialModelStore::materialModel(), MainWindow::instance());
     dialog.setMaterialProperty(previous);
     if (dialog.exec() == QDialog::Accepted) {
         return dialog.selectedMaterialProperty();
diff --git a/GUI/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp b/GUI/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
index df344094fc0..3fdfcd908b0 100644
--- a/GUI/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
+++ b/GUI/Views/RealSpaceWidgets/RealSpaceBuilderUtils.cpp
@@ -19,6 +19,7 @@
 #include "GUI/Models/LayerItem.h"
 #include "GUI/Models/MaterialItem.h"
 #include "GUI/Models/MaterialModel.h"
+#include "GUI/Models/MaterialModelStore.h"
 #include "GUI/Models/MesoCrystalItem.h"
 #include "GUI/Models/MultiLayerItem.h"
 #include "GUI/Models/ParticleCompositionItem.h"
@@ -34,7 +35,6 @@
 #include "GUI/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.h"
 #include "GUI/Views/RealSpaceWidgets/RealSpaceModel.h"
 #include "GUI/Views/RealSpaceWidgets/TransformTo3D.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "Sample/Aggregate/InterferenceFunctions.h"
 #include "Sample/Particle/FormFactorCrystal.h"
 #include "Sample/Particle/MesoCrystal.h"
@@ -205,7 +205,7 @@ void RealSpaceBuilderUtils::applyParticleColor(const Particle& particle,
     // assign correct color to the particle from the knowledge of its material
     const Material* particle_material = particle.material();
     QString material_name = QString::fromStdString(particle_material->getName());
-    auto materialItem = AppSvc::materialModel()->materialFromName(material_name);
+    auto materialItem = MaterialModelStore::materialModel()->materialFromName(material_name);
     QColor color = materialItem->color();
     color.setAlphaF(alpha);
     particle3D.color = color;
diff --git a/GUI/Views/RealSpaceWidgets/RealSpaceCanvas.cpp b/GUI/Views/RealSpaceWidgets/RealSpaceCanvas.cpp
index d11503cfa2f..a61e8fc5177 100644
--- a/GUI/Views/RealSpaceWidgets/RealSpaceCanvas.cpp
+++ b/GUI/Views/RealSpaceWidgets/RealSpaceCanvas.cpp
@@ -20,8 +20,8 @@
 #include "GUI/Views/RealSpaceWidgets/RealSpaceBuilder.h"
 #include "GUI/Views/RealSpaceWidgets/RealSpaceModel.h"
 #include "GUI/Views/RealSpaceWidgets/RealSpaceView.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include <QApplication>
 #include <QFileDialog>
 #include <QMessageBox>
@@ -145,7 +145,7 @@ void RealSpaceCanvas::onRowsAboutToBeRemoved(const QModelIndex& parent, int firs
 
 void RealSpaceCanvas::savePicture(const QPixmap& pixmap)
 {
-    QString dirname = AppSvc::projectManager()->userExportDir();
+    QString dirname = ProjectManagerStore::projectManager()->userExportDir();
     QString defaultExtension = ".png";
     QString selectedFilter("*" + defaultExtension);
     QString defaultName = dirname + "/untitled";
diff --git a/GUI/Views/SimulationWidgets/SimulationSetupWidget.cpp b/GUI/Views/SimulationWidgets/SimulationSetupWidget.cpp
index 39a610557cb..b68c27b5dd9 100644
--- a/GUI/Views/SimulationWidgets/SimulationSetupWidget.cpp
+++ b/GUI/Views/SimulationWidgets/SimulationSetupWidget.cpp
@@ -22,8 +22,8 @@
 #include "GUI/Views/SimulationWidgets/SimulationDataSelectorWidget.h"
 #include "GUI/Views/SimulationWidgets/SimulationOptionsWidget.h"
 #include "GUI/Views/SimulationWidgets/SimulationSetupAssistant.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include <QMessageBox>
 #include <QPushButton>
 #include <QVBoxLayout>
@@ -99,7 +99,7 @@ void SimulationSetupWidget::onExportToPythonScript()
     pythonWidget->generatePythonScript(
         multiLayerItem, instrumentItem,
         m_applicationModels->documentModel()->simulationOptionsItem(),
-        AppSvc::projectManager()->projectDir());
+        ProjectManagerStore::projectManager()->projectDir());
 }
 
 QWidget* SimulationSetupWidget::createButtonWidget()
diff --git a/GUI/Views/SpecularDataWidgets/SpecularDataCanvas.cpp b/GUI/Views/SpecularDataWidgets/SpecularDataCanvas.cpp
index 80bf09fd97c..e49fd63cc65 100644
--- a/GUI/Views/SpecularDataWidgets/SpecularDataCanvas.cpp
+++ b/GUI/Views/SpecularDataWidgets/SpecularDataCanvas.cpp
@@ -17,8 +17,8 @@
 #include "GUI/Views/FitWidgets/plot_constants.h"
 #include "GUI/Views/IntensityDataWidgets/SavePlotAssistant.h"
 #include "GUI/Views/SpecularDataWidgets/SpecularPlotCanvas.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/projectmanager.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include <qcustomplot.h>
 
 SpecularDataCanvas::SpecularDataCanvas(QWidget* parent)
@@ -85,7 +85,7 @@ void SpecularDataCanvas::onResetViewAction()
 
 void SpecularDataCanvas::onSavePlotAction()
 {
-    QString dirname = AppSvc::projectManager()->userExportDir();
+    QString dirname = ProjectManagerStore::projectManager()->userExportDir();
     SavePlotAssistant saveAssistant;
     saveAssistant.savePlot(dirname, m_plot_canvas->customPlot(),
                            specularDataItem()->getOutputData());
diff --git a/GUI/Views/SpecularDataWidgets/SpecularDataImportWidget.cpp b/GUI/Views/SpecularDataWidgets/SpecularDataImportWidget.cpp
index 0f1fd3bb669..c3ca3871ef9 100644
--- a/GUI/Views/SpecularDataWidgets/SpecularDataImportWidget.cpp
+++ b/GUI/Views/SpecularDataWidgets/SpecularDataImportWidget.cpp
@@ -22,7 +22,6 @@
 #include "GUI/Models/InstrumentItems.h"
 #include "GUI/Models/RealDataItem.h"
 #include "GUI/Models/SpecularDataItem.h"
-#include "GUI/mainwindow/AppSvc.h"
 #include "GUI/mainwindow/mainwindow.h"
 #include "GUI/mainwindow/projectmanager.h"
 #include "ui_SpecularDataImportWidget.h"
@@ -365,4 +364,4 @@ void SpecularDataImportWidget::onPropertiesChanged()
 QString SpecularDataImportWidget::currentFileName() const
 {
     return realDataItem()->nativeFileName();
-}
\ No newline at end of file
+}
diff --git a/GUI/mainwindow/ProjectManagerStore.cpp b/GUI/mainwindow/ProjectManagerStore.cpp
index ddd12bf070c..3ff41e4f694 100644
--- a/GUI/mainwindow/ProjectManagerStore.cpp
+++ b/GUI/mainwindow/ProjectManagerStore.cpp
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/mainwindow/AppSvc.cpp
-//! @brief     Implements class AppSvc
+//! @file      GUI/mainwindow/ProjectManagerStore.cpp
+//! @brief     Implements namespace ProjectManagerStore
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,87 +12,39 @@
 //
 //  ************************************************************************************************
 
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include "GUI/Models/Error.h"
 
-ProjectManager* AppSvc::projectManager()
-{
-    return instance().this_projectManager();
+namespace {
+    ProjectManager* theProjectManager = nullptr;
 }
 
-void AppSvc::subscribe(ProjectManager* projectManager)
-{
-    return instance().this_subscribe(projectManager);
-}
-
-void AppSvc::unsubscribe(ProjectManager* projectManager)
-{
-    instance().this_unsubscribe(projectManager);
-}
+namespace ProjectManagerStore {
 
-MaterialModel* AppSvc::materialModel()
-{
-    return instance().this_materialModel();
-}
-
-void AppSvc::subscribe(MaterialModel* materialModel)
-{
-    return instance().this_subscribe(materialModel);
-}
+    ProjectManager* projectManager()
+    {
+        if (!theProjectManager)
+            throw Error("ProjectManagerStore::projectManager() -> Error. Attempt to access "
+                        "non existing ProjectManager.");
+        
+        return theProjectManager;
+    }
 
-void AppSvc::unsubscribe(MaterialModel* materialModel)
-{
-    instance().this_unsubscribe(materialModel);
-}
-
-AppSvc::AppSvc() : m_projectManager(nullptr), m_materialModel(nullptr) {}
-
-ProjectManager* AppSvc::this_projectManager()
-{
-    if (!m_projectManager)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to access "
-                    "non existing ProjectManager.");
-
-    return m_projectManager;
-}
+    void subscribe(ProjectManager* projectManager)
+    {
+        if (theProjectManager != nullptr)
+            throw Error("ProjectManagerStore::subscribe() -> Error. Attempt to subscribe "
+                        "ProjectManager twice.");
 
-MaterialModel* AppSvc::this_materialModel()
-{
-    return m_materialModel;
-}
-
-void AppSvc::this_subscribe(ProjectManager* projectManager)
-{
-    if (m_projectManager != nullptr)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to subscribe "
-                    "ProjectManager twice.");
-
-    m_projectManager = projectManager;
-}
-
-void AppSvc::this_unsubscribe(ProjectManager* projectManager)
-{
-    if (m_projectManager != projectManager)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to unsubscribe "
-                    "ProjectManager before it was subscribed.");
-
-    m_projectManager = nullptr;
-}
-
-void AppSvc::this_subscribe(MaterialModel* materialModel)
-{
-    if (m_materialModel)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to subscribe "
-                    "MaterialModel twice.");
-
-    m_materialModel = materialModel;
-}
+        theProjectManager = projectManager;
+    }
 
-void AppSvc::this_unsubscribe(MaterialModel* materialModel)
-{
-    if (m_materialModel != materialModel)
-        throw Error("AppSvc::projectManager() -> Error. Attempt to unsubscribe "
-                    "MaterialModel before it was subscribed.");
+    void unsubscribe(ProjectManager* projectManager)
+    {
+        if (theProjectManager != projectManager)
+            throw Error("ProjectManagerStore::unsubscribe -> Error. Attempt to unsubscribe "
+                        "ProjectManager before it was subscribed.");
 
-    m_materialModel = nullptr;
+        theProjectManager = nullptr;
+    }
 }
diff --git a/GUI/mainwindow/ProjectManagerStore.h b/GUI/mainwindow/ProjectManagerStore.h
index b03e0b199b5..380ae3bfc80 100644
--- a/GUI/mainwindow/ProjectManagerStore.h
+++ b/GUI/mainwindow/ProjectManagerStore.h
@@ -2,8 +2,8 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      GUI/mainwindow/AppSvc.h
-//! @brief     Defines class AppSvc
+//! @file      GUI/mainwindow/ProjectManagerStore.h
+//! @brief     Defines namespace ProjectManagerStore
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -12,39 +12,18 @@
 //
 //  ************************************************************************************************
 
-#ifndef BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
-#define BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
-
-#include "GUI/Models/ISingleton.h"
+#ifndef BORNAGAIN_GUI_MAINWINDOW_PROJECTMANAGERSTORE_H
+#define BORNAGAIN_GUI_MAINWINDOW_PROJECTMANAGERSTORE_H
 
 class ProjectManager;
-class MaterialModel;
-
-//! The AppSvc class provides common access for key components of the GUI.
-
-class AppSvc : public ISingleton<AppSvc> {
-    friend class ISingleton<AppSvc>;
-
-public:
-    static ProjectManager* projectManager();
-    static void subscribe(ProjectManager* projectManager);
-    static void unsubscribe(ProjectManager* projectManager);
 
-    static MaterialModel* materialModel();
-    static void subscribe(MaterialModel* materialModel);
-    static void unsubscribe(MaterialModel* materialModel);
+//! The ProjectManagerStore holds an instance of the ProjectManager class
 
-private:
-    AppSvc();
-    ProjectManager* this_projectManager();
-    MaterialModel* this_materialModel();
-    void this_subscribe(ProjectManager* projectManager);
-    void this_unsubscribe(ProjectManager* projectManager);
-    void this_subscribe(MaterialModel* materialModel);
-    void this_unsubscribe(MaterialModel* materialModel);
+namespace ProjectManagerStore {
 
-    ProjectManager* m_projectManager;
-    MaterialModel* m_materialModel;
-};
+    ProjectManager* projectManager();
+    void subscribe(ProjectManager* projectManager);
+    void unsubscribe(ProjectManager* projectManager);
+}
 
-#endif // BORNAGAIN_GUI_MAINWINDOW_APPSVC_H
+#endif // BORNAGAIN_GUI_MAINWINDOW_PROJECTMANAGERSTORE_H
diff --git a/GUI/mainwindow/ProjectUtils.cpp b/GUI/mainwindow/ProjectUtils.cpp
index b857b17647e..e6165332f2d 100644
--- a/GUI/mainwindow/ProjectUtils.cpp
+++ b/GUI/mainwindow/ProjectUtils.cpp
@@ -15,7 +15,7 @@
 #include "GUI/mainwindow/ProjectUtils.h"
 #include "GUI/Models/Error.h"
 #include "GUI/Models/ItemFileNameUtils.h"
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include "GUI/mainwindow/projectdocument.h"
 #include "GUI/mainwindow/projectmanager.h"
 #include <QDateTime>
@@ -144,5 +144,5 @@ QString ProjectUtils::readTextFile(const QString& fileName)
 
 QString ProjectUtils::userExportDir()
 {
-    return AppSvc::projectManager()->userExportDir();
+    return ProjectManagerStore::projectManager()->userExportDir();
 }
diff --git a/GUI/mainwindow/PyImportAssistant.cpp b/GUI/mainwindow/PyImportAssistant.cpp
index 8719edc6cfe..e221c26d7f1 100644
--- a/GUI/mainwindow/PyImportAssistant.cpp
+++ b/GUI/mainwindow/PyImportAssistant.cpp
@@ -20,7 +20,7 @@
 #include "GUI/Models/GUIObjectBuilder.h"
 #include "GUI/Views/InfoWidgets/ComboSelectorDialog.h"
 #include "GUI/Views/InfoWidgets/DetailedMessageBox.h"
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include "GUI/mainwindow/ProjectUtils.h"
 #include "GUI/mainwindow/mainwindow.h"
 #include "GUI/mainwindow/projectmanager.h"
@@ -92,7 +92,7 @@ void PyImportAssistant::exec()
 
 QString PyImportAssistant::fileNameToOpen()
 {
-    QString dirname = AppSvc::projectManager()->userImportDir();
+    QString dirname = ProjectManagerStore::projectManager()->userImportDir();
 
     QString result = QFileDialog::getOpenFileName(m_mainWindow, "Open python script", dirname,
                                                   "Python scripts (*.py)", nullptr,
@@ -110,7 +110,7 @@ void PyImportAssistant::saveImportDir(const QString& fileName)
     if (fileName.isEmpty())
         return;
 
-    AppSvc::projectManager()->setImportDir(GUIHelpers::fileDir(fileName));
+    ProjectManagerStore::projectManager()->setImportDir(GUIHelpers::fileDir(fileName));
 }
 
 //! Read content of text file and returns it as a multi-line string.
diff --git a/GUI/mainwindow/projectmanager.cpp b/GUI/mainwindow/projectmanager.cpp
index adb406f4b53..3f6d68588d6 100644
--- a/GUI/mainwindow/projectmanager.cpp
+++ b/GUI/mainwindow/projectmanager.cpp
@@ -17,7 +17,7 @@
 #include "GUI/Models/ApplicationModels.h"
 #include "GUI/Models/Error.h"
 #include "GUI/Views/InfoWidgets/ProjectLoadWarningDialog.h"
-#include "GUI/mainwindow/AppSvc.h"
+#include "GUI/mainwindow/ProjectManagerStore.h"
 #include "GUI/mainwindow/ProjectUtils.h"
 #include "GUI/mainwindow/SaveService.h"
 #include "GUI/mainwindow/mainwindow.h"
@@ -51,12 +51,12 @@ ProjectManager::ProjectManager(MainWindow* parent)
 
 {
     createNewProject();
-    AppSvc::subscribe(this);
+    ProjectManagerStore::subscribe(this);
 }
 
 ProjectManager::~ProjectManager()
 {
-    AppSvc::unsubscribe(this);
+    ProjectManagerStore::unsubscribe(this);
     delete m_project_document;
     delete m_messageService;
 }
-- 
GitLab