From b1f5ce41d73df0a3520a201a2f90e9af626f4a53 Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Mon, 23 Aug 2021 13:08:22 +0200
Subject: [PATCH] pass current document to views, so they work on this
 document, not with global pointers and MainWindow

---
 GUI/Views/ImportDataView.cpp                  | 10 ++++++----
 GUI/Views/ImportDataView.h                    |  4 +++-
 .../InstrumentWidgets/InstrumentView.cpp      | 11 +++++-----
 GUI/Views/InstrumentWidgets/InstrumentView.h  |  4 ++--
 GUI/Views/JobView.cpp                         | 20 +++++++------------
 GUI/Views/JobView.h                           |  6 ++----
 GUI/Views/SampleView.cpp                      |  8 ++++----
 GUI/Views/SampleView.h                        |  3 ++-
 GUI/Views/SessionModelView.cpp                | 12 +++++------
 GUI/Views/SessionModelView.h                  |  4 +++-
 GUI/Views/SimulationView.cpp                  | 12 +++++------
 GUI/Views/SimulationView.h                    |  4 +++-
 GUI/mainwindow/mainwindow.cpp                 | 15 ++++++++------
 13 files changed, 57 insertions(+), 56 deletions(-)

diff --git a/GUI/Views/ImportDataView.cpp b/GUI/Views/ImportDataView.cpp
index 686744ae251..bedfaaab37e 100644
--- a/GUI/Views/ImportDataView.cpp
+++ b/GUI/Views/ImportDataView.cpp
@@ -17,6 +17,7 @@
 #include "GUI/Views/ImportDataWidgets/RealDataSelectorWidget.h"
 #include "GUI/Views/Tools/mainwindow_constants.h"
 #include "GUI/mainwindow/mainwindow.h"
+#include "GUI/mainwindow/projectdocument.h"
 #include <QSplitter>
 #include <QVBoxLayout>
 
@@ -24,10 +25,11 @@ namespace {
 const bool reuse_widget = true;
 }
 
-ImportDataView::ImportDataView(MainWindow* mainWindow)
-    : QWidget(mainWindow)
+ImportDataView::ImportDataView(QWidget* parent, ProjectDocument* document)
+    : QWidget(parent)
     , m_selectorWidget(new RealDataSelectorWidget)
     , m_stackedWidget(new ItemStackPresenter<RealDataPresenter>(reuse_widget))
+    , m_document(document)
 {
     auto mainLayout = new QVBoxLayout;
     mainLayout->setMargin(0);
@@ -53,8 +55,8 @@ ImportDataView::ImportDataView(MainWindow* mainWindow)
 
     setupConnections();
 
-    m_selectorWidget->setModel(mainWindow->realDataModel());
-    m_stackedWidget->setModel(mainWindow->realDataModel());
+    m_selectorWidget->setModel(m_document->realDataModel());
+    m_stackedWidget->setModel(m_document->realDataModel());
 }
 
 void ImportDataView::onSelectionChanged(SessionItem* item)
diff --git a/GUI/Views/ImportDataView.h b/GUI/Views/ImportDataView.h
index da9d224056a..297a4b66f6c 100644
--- a/GUI/Views/ImportDataView.h
+++ b/GUI/Views/ImportDataView.h
@@ -20,6 +20,7 @@
 
 class RealDataModel;
 class RealDataSelectorWidget;
+class ProjectDocument;
 
 //! The ImportDataView class is a main view for importing experimental data.
 
@@ -27,7 +28,7 @@ class ImportDataView : public QWidget {
     Q_OBJECT
 
 public:
-    ImportDataView(class MainWindow* mainWindow);
+    ImportDataView(QWidget* parent, ProjectDocument* document);
 
 public slots:
     void onSelectionChanged(SessionItem* item);
@@ -37,6 +38,7 @@ private:
 
     RealDataSelectorWidget* m_selectorWidget;
     ItemStackPresenter<RealDataPresenter>* m_stackedWidget;
+    ProjectDocument* m_document;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_IMPORTDATAVIEW_H
diff --git a/GUI/Views/InstrumentWidgets/InstrumentView.cpp b/GUI/Views/InstrumentWidgets/InstrumentView.cpp
index d18201e0032..8f4bb318920 100644
--- a/GUI/Views/InstrumentWidgets/InstrumentView.cpp
+++ b/GUI/Views/InstrumentWidgets/InstrumentView.cpp
@@ -18,22 +18,21 @@
 #include "GUI/Views/CommonWidgets/StyledToolBar.h"
 #include "GUI/Views/InstrumentWidgets/InstrumentEditor.h"
 #include "GUI/Views/InstrumentWidgets/InstrumentSelectorWidget.h"
+#include "GUI/mainwindow/projectdocument.h"
 #include <QBoxLayout>
 
-InstrumentView::InstrumentView(QWidget* parent, InstrumentModel* instrumentModel)
-    : QWidget(parent)
-    , m_instrumentEditor(new InstrumentEditor)
-    , m_instrumentModel(instrumentModel)
+InstrumentView::InstrumentView(QWidget* parent, ProjectDocument* document)
+    : QWidget(parent), m_instrumentEditor(new InstrumentEditor)
 {
     auto horizontalLayout = new QHBoxLayout;
-    m_instrumentSelector = new InstrumentSelectorWidget(m_instrumentModel, this);
+    m_instrumentSelector = new InstrumentSelectorWidget(document->instrumentModel(), this);
     horizontalLayout->addWidget(m_instrumentSelector);
     horizontalLayout->addWidget(m_instrumentEditor, 1);
 
     StyledToolBar* toolbar = new StyledToolBar(this);
     toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     toolbar->addActions(m_instrumentSelector->toolbarActions());
-    
+
     auto mainLayout = new QVBoxLayout;
     mainLayout->setMargin(0);
     mainLayout->setSpacing(0);
diff --git a/GUI/Views/InstrumentWidgets/InstrumentView.h b/GUI/Views/InstrumentWidgets/InstrumentView.h
index 12840c17374..969029a7e94 100644
--- a/GUI/Views/InstrumentWidgets/InstrumentView.h
+++ b/GUI/Views/InstrumentWidgets/InstrumentView.h
@@ -23,12 +23,13 @@ class InstrumentSelectorWidget;
 class InstrumentEditor;
 class InstrumentModel;
 class SessionItem;
+class ProjectDocument;
 
 class InstrumentView : public QWidget {
     Q_OBJECT
 
 public:
-    InstrumentView(QWidget* parent, InstrumentModel* instrumentModel);
+    InstrumentView(QWidget* parent, ProjectDocument* document);
 
 private slots:
     void onItemSelectionChanged(SessionItem* instrumentItem);
@@ -39,7 +40,6 @@ protected:
 private:
     InstrumentSelectorWidget* m_instrumentSelector;
     InstrumentEditor* m_instrumentEditor;
-    InstrumentModel* m_instrumentModel;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_INSTRUMENTWIDGETS_INSTRUMENTVIEW_H
diff --git a/GUI/Views/JobView.cpp b/GUI/Views/JobView.cpp
index 1704ddc827f..5250c6abc9d 100644
--- a/GUI/Views/JobView.cpp
+++ b/GUI/Views/JobView.cpp
@@ -28,14 +28,13 @@
 #include "GUI/mainwindow/projectmanager.h"
 #include <QMenu>
 
-JobView::JobView(MainWindow* mainWindow)
+JobView::JobView(MainWindow* mainWindow, ProjectDocument* document)
     : m_docks(new DocksController(this))
     , m_progressAssistant(new JobProgressAssistant(mainWindow))
     , m_currentItem(nullptr)
-    , m_mainWindow(mainWindow)
     , m_activityActions(this)
+    , m_document(document)
 {
-
     setObjectName("JobView");
     createActions();
     createSubWindows();
@@ -57,11 +56,6 @@ void JobView::fillViewMenu(QMenu* menu)
     menu->addAction(action);
 }
 
-ProjectDocument* JobView::document() const
-{
-    return ProjectManager::instance()->document();
-}
-
 void JobView::onFocusRequest(JobItem* jobItem)
 {
     if (jobItem->runInBackground())
@@ -102,10 +96,10 @@ void JobView::onSelectionChanged(JobItem* jobItem)
 
 void JobView::createSubWindows()
 {
-    m_jobOutputDataWidget = new JobOutputDataWidget(document()->jobModel(), this);
-    m_jobSelector = new JobSelectorWidget(document()->jobModel(), this);
-    m_jobRealTimeWidget = new JobRealTimeWidget(document()->jobModel(), this);
-    m_fitActivityPanel = new FitActivityPanel(document()->jobModel(), this);
+    m_jobOutputDataWidget = new JobOutputDataWidget(m_document->jobModel(), this);
+    m_jobSelector = new JobSelectorWidget(m_document->jobModel(), this);
+    m_jobRealTimeWidget = new JobRealTimeWidget(m_document->jobModel(), this);
+    m_fitActivityPanel = new FitActivityPanel(m_document->jobModel(), this);
     m_jobMessagePanel = new JobMessagePanel(this);
 
     m_docks->addWidget(JobViewFlags::JOB_LIST_DOCK, m_jobSelector, Qt::LeftDockWidgetArea);
@@ -157,7 +151,7 @@ void JobView::connectActivityRelated()
 void JobView::connectJobRelated()
 {
     // Focus request: JobModel -> this
-    connect(document()->jobModel(), &JobModel::focusRequest, this, &JobView::onFocusRequest);
+    connect(m_document->jobModel(), &JobModel::focusRequest, this, &JobView::onFocusRequest);
 
     // JobItem selection: JobSelectorWidget -> this
     connect(m_jobSelector, &JobSelectorWidget::selectionChanged, this,
diff --git a/GUI/Views/JobView.h b/GUI/Views/JobView.h
index 3970b97020e..e7b302618db 100644
--- a/GUI/Views/JobView.h
+++ b/GUI/Views/JobView.h
@@ -37,12 +37,10 @@ class JobView : public QMainWindow {
     Q_OBJECT
 
 public:
-    JobView(MainWindow* mainWindow);
+    JobView(MainWindow* mainWindow, ProjectDocument* document);
 
     void fillViewMenu(QMenu* menu);
 
-    ProjectDocument* document() const;
-
 signals:
     void focusRequest(int);
     void activityChanged(int activity);
@@ -65,7 +63,6 @@ private:
     DocksController* m_docks;
     JobProgressAssistant* m_progressAssistant;
     JobItem* m_currentItem;
-    MainWindow* m_mainWindow;
 
     JobSelectorWidget* m_jobSelector = nullptr;
     JobOutputDataWidget* m_jobOutputDataWidget = nullptr;
@@ -74,6 +71,7 @@ private:
     JobMessagePanel* m_jobMessagePanel = nullptr;
 
     QActionGroup m_activityActions;
+    ProjectDocument* m_document;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_JOBVIEW_H
diff --git a/GUI/Views/SampleView.cpp b/GUI/Views/SampleView.cpp
index b18eb6b279e..aaceda4977b 100644
--- a/GUI/Views/SampleView.cpp
+++ b/GUI/Views/SampleView.cpp
@@ -25,15 +25,15 @@
 #include "GUI/Views/SampleDesigner/SampleTreeWidget.h"
 #include "GUI/Views/SampleDesigner/ScriptPanel.h"
 #include "GUI/mainwindow/mainwindow.h"
+#include "GUI/mainwindow/projectdocument.h"
 #include "GUI/mainwindow/projectmanager.h"
 #include <QDockWidget>
 #include <QMenu>
 #include <memory>
 
-SampleView::SampleView(MainWindow* mainWindow)
-    : QMainWindow(mainWindow), m_docks(new DocksController(this))
+SampleView::SampleView(QWidget* parent, ProjectDocument* document)
+    : QMainWindow(parent), m_docks(new DocksController(this)), m_document(document)
 {
-
     setObjectName("SampleView");
     createSubWindows();
     connectSignals();
@@ -41,7 +41,7 @@ SampleView::SampleView(MainWindow* mainWindow)
 
 ApplicationModels* SampleView::models()
 {
-    return MainWindow::instance()->models();
+    return m_document->applicationModels();
 }
 
 void SampleView::toggleRealSpaceView()
diff --git a/GUI/Views/SampleView.h b/GUI/Views/SampleView.h
index 23ac209ed14..3f8a7b2036f 100644
--- a/GUI/Views/SampleView.h
+++ b/GUI/Views/SampleView.h
@@ -35,7 +35,7 @@ class SampleView : public QMainWindow {
 public:
     enum ESubWindows { TOOLBOX, SAMPLE_TREE, PROPERTY_EDITOR, INFO, REALSPACEPANEL };
 
-    SampleView(MainWindow* mainWindow);
+    SampleView(QWidget* parent, ProjectDocument* document);
 
     ApplicationModels* models();
     void toggleRealSpaceView();
@@ -57,6 +57,7 @@ private:
     SamplePropertyWidget* m_propertyWidget = nullptr;
     ScriptPanel* m_scriptPanel = nullptr;
     RealSpacePanel* m_realSpacePanel = nullptr;
+    ProjectDocument* m_document;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_SAMPLEVIEW_H
diff --git a/GUI/Views/SessionModelView.cpp b/GUI/Views/SessionModelView.cpp
index edc3b642a02..c6cc343c9ae 100644
--- a/GUI/Views/SessionModelView.cpp
+++ b/GUI/Views/SessionModelView.cpp
@@ -22,6 +22,7 @@
 #include "GUI/Views/SessionModelDelegate.h"
 #include "GUI/Views/TestView.h"
 #include "GUI/mainwindow/mainwindow.h"
+#include "GUI/mainwindow/projectdocument.h"
 #include "GUI/mainwindow/projectmanager.h"
 #include <QToolBar>
 #include <QToolButton>
@@ -31,13 +32,14 @@ namespace {
 const bool show_test_view = false;
 }
 
-SessionModelView::SessionModelView(MainWindow* mainWindow)
+SessionModelView::SessionModelView(MainWindow* mainWindow, ProjectDocument* document)
     : QWidget(mainWindow)
     , m_mainWindow(mainWindow)
     , m_toolBar(new QToolBar)
     , m_tabs(new QTabWidget)
     , m_expandCollapseButton(new QToolButton)
     , m_delegate(new SessionModelDelegate(this))
+    , m_document(document)
 {
     auto layout = new QVBoxLayout;
     layout->setMargin(0);
@@ -84,12 +86,8 @@ void SessionModelView::init_tabs()
 
 QList<SessionModel*> SessionModelView::modelsForTabs()
 {
-    auto doc = ProjectManager::instance()->document();
-    if (!doc)
-        return {};
-
-    return {doc->instrumentModel(), doc->sampleModel(), doc->realDataModel(), doc->materialModel(),
-            doc->jobModel()};
+    return {m_document->instrumentModel(), m_document->sampleModel(), m_document->realDataModel(),
+            m_document->materialModel(), m_document->jobModel()};
 }
 
 void SessionModelView::init_test_view()
diff --git a/GUI/Views/SessionModelView.h b/GUI/Views/SessionModelView.h
index 791c852aae4..b0d4b0781be 100644
--- a/GUI/Views/SessionModelView.h
+++ b/GUI/Views/SessionModelView.h
@@ -24,6 +24,7 @@ class QToolButton;
 class SessionModel;
 class ModelTreeView;
 class SessionModelDelegate;
+class ProjectDocument;
 
 //! The SessionModelView is a technical view which shows the content all current application
 //! models. It appears as an additional view in the main navigation bar on the left, right
@@ -33,7 +34,7 @@ class SessionModelView : public QWidget {
     Q_OBJECT
 
 public:
-    SessionModelView(MainWindow* mainWindow = 0);
+    SessionModelView(MainWindow* mainWindow, ProjectDocument* document);
 
     void setViewActive(bool is_active);
 
@@ -51,6 +52,7 @@ private:
     QToolButton* m_expandCollapseButton;
     SessionModelDelegate* m_delegate;
     QVector<ModelTreeView*> m_content;
+    ProjectDocument* m_document;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_SESSIONMODELVIEW_H
diff --git a/GUI/Views/SimulationView.cpp b/GUI/Views/SimulationView.cpp
index f8db5107f41..53cb1fe8de0 100644
--- a/GUI/Views/SimulationView.cpp
+++ b/GUI/Views/SimulationView.cpp
@@ -36,8 +36,8 @@
 #include <QMessageBox>
 #include <thread>
 
-SimulationView::SimulationView(MainWindow* mainWindow)
-    : QWidget(mainWindow), m_ui(new Ui::SimulationView)
+SimulationView::SimulationView(MainWindow* mainWindow, ProjectDocument* document)
+    : QWidget(mainWindow), m_ui(new Ui::SimulationView), m_document(document)
 {
     m_ui->setupUi(this);
 
@@ -230,22 +230,22 @@ QString SimulationView::validateSimulationSetup(bool validateRealData) const
 
 QVector<MultiLayerItem*> SimulationView::multiLayerItems() const
 {
-    return MainWindow::instance()->models()->sampleModel()->topItems<MultiLayerItem>();
+    return m_document->sampleModel()->topItems<MultiLayerItem>();
 }
 
 QVector<InstrumentItem*> SimulationView::instrumentItems() const
 {
-    return MainWindow::instance()->models()->instrumentModel()->instrumentItems();
+    return m_document->instrumentModel()->instrumentItems();
 }
 
 QVector<RealDataItem*> SimulationView::realDataItems() const
 {
-    return MainWindow::instance()->models()->realDataModel()->realDataItems();
+    return m_document->realDataModel()->realDataItems();
 }
 
 SimulationOptionsItem* SimulationView::optionsItem() const
 {
-    return MainWindow::instance()->models()->documentModel()->simulationOptionsItem();
+    return m_document->applicationModels()->documentModel()->simulationOptionsItem();
 }
 
 const MultiLayerItem* SimulationView::selectedSample() const
diff --git a/GUI/Views/SimulationView.h b/GUI/Views/SimulationView.h
index 4bde9685fb0..4f6e6c84b07 100644
--- a/GUI/Views/SimulationView.h
+++ b/GUI/Views/SimulationView.h
@@ -23,6 +23,7 @@ class InstrumentItem;
 class RealDataItem;
 class QComboBox;
 class SimulationOptionsItem;
+class ProjectDocument;
 
 namespace Ui {
 class SimulationView;
@@ -37,7 +38,7 @@ class SimulationView : public QWidget {
     Q_OBJECT
 
 public:
-    SimulationView(MainWindow* mainWindow);
+    SimulationView(MainWindow* mainWindow, ProjectDocument* document);
 
     void runSimulation();
     void exportPythonScript();
@@ -84,6 +85,7 @@ private:
 
 private:
     Ui::SimulationView* m_ui;
+    ProjectDocument* m_document;
 };
 
 #endif // BORNAGAIN_GUI_VIEWS_SIMULATIONVIEW_H
diff --git a/GUI/mainwindow/mainwindow.cpp b/GUI/mainwindow/mainwindow.cpp
index ac83c8b0bd3..47db8c4711f 100644
--- a/GUI/mainwindow/mainwindow.cpp
+++ b/GUI/mainwindow/mainwindow.cpp
@@ -293,12 +293,15 @@ void MainWindow::initProgressBar()
 void MainWindow::initViews()
 {
     m_welcomeView = new WelcomeView(this);
-    m_instrumentView = new InstrumentView(this, instrumentModel());
-    m_sampleView = new SampleView(this);
-    m_importDataView = new ImportDataView(this);
-    m_simulationView = new SimulationView(this);
-    m_jobView = new JobView(this);
-    m_sessionModelView = new SessionModelView(this);
+
+    auto doc = m_projectManager->document();
+    
+    m_instrumentView = new InstrumentView(this, doc);
+    m_sampleView = new SampleView(this, doc);
+    m_importDataView = new ImportDataView(this, doc);
+    m_simulationView = new SimulationView(this, doc);
+    m_jobView = new JobView(this, doc);
+    m_sessionModelView = new SessionModelView(this, doc);
 
     addView(ViewId::WELCOME, QIcon(":/images/main_welcomeview.svg"), "Welcome",
             "Switch to Welcome View", m_welcomeView);
-- 
GitLab