From 490b68ad3fc6b0b8414b7550f494872baa27a71e Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Fri, 26 Jan 2024 13:42:24 +0100
Subject: [PATCH] WIP

---
 GUI/Model/Device/InstrumentXML.cpp           | 24 ++++-----
 GUI/View/Instrument/InstrumentsQListView.cpp | 52 ++++++++++++++++----
 GUI/View/Instrument/InstrumentsQListView.h   |  2 +
 GUI/View/Layout/ApplicationSettings.cpp      |  3 ++
 GUI/View/Layout/ApplicationSettings.h        |  5 ++
 5 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/GUI/Model/Device/InstrumentXML.cpp b/GUI/Model/Device/InstrumentXML.cpp
index 75d3d0c5ea7..1d45f6199e1 100644
--- a/GUI/Model/Device/InstrumentXML.cpp
+++ b/GUI/Model/Device/InstrumentXML.cpp
@@ -60,22 +60,22 @@ InstrumentItem* InstrumentXML::load(const QString& fname)
     QFile file(fname);
 
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
-	throw std::runtime_error("Cannot open instrument file for reading");
+        throw std::runtime_error("Cannot open instrument file for reading");
     QXmlStreamReader r(&file);
     if (r.atEnd())
-	throw std::runtime_error("Empty instrument file?");
+        throw std::runtime_error("Empty instrument file?");
     r.readNext();
     if (!r.isStartDocument())
-	throw std::runtime_error("Missing StartDocument in instrument file");
+        throw std::runtime_error("Missing StartDocument in instrument file");
     r.readNext();
     if (!r.isStartElement())
-	throw std::runtime_error("Missing start element in instrument file");
+        throw std::runtime_error("Missing start element in instrument file");
     if (r.name() != XML_ROOT_TAG)
-	throw std::runtime_error("Missing root tag in instrument file, found "
-				 + r.name().toString().toStdString());
+        throw std::runtime_error("Missing root tag in instrument file, found "
+                                 + r.name().toString().toStdString());
     const int found_version = r.attributes().value(XML_VERSION_TAG).toString().toInt();
     if (found_version != 1)
-	throw std::runtime_error("Unsupported version of instrument element");
+        throw std::runtime_error("Unsupported version of instrument element");
     const uint typeIndex = XML::readUIntAttribute(&r, XML::Attrib::type);
     const auto type = static_cast<typename InstrumentItemCatalog::Type>(typeIndex);
     ii = InstrumentItemCatalog::create(type);
@@ -83,11 +83,11 @@ InstrumentItem* InstrumentXML::load(const QString& fname)
     ii->readFrom(&r);
 
     if (r.hasError())
-	throw std::runtime_error(QString("Error in instrument file, line %1, column %2: %3")
-				 .arg(r.lineNumber())
-				 .arg(r.columnNumber())
-				 .arg(r.errorString())
-				 .toStdString());
+        throw std::runtime_error(QString("Error in instrument file, line %1, column %2: %3")
+                                     .arg(r.lineNumber())
+                                     .arg(r.columnNumber())
+                                     .arg(r.errorString())
+                                     .toStdString());
     file.close();
 
     return ii;
diff --git a/GUI/View/Instrument/InstrumentsQListView.cpp b/GUI/View/Instrument/InstrumentsQListView.cpp
index 9e7940789f2..3551bf2ddad 100644
--- a/GUI/View/Instrument/InstrumentsQListView.cpp
+++ b/GUI/View/Instrument/InstrumentsQListView.cpp
@@ -14,15 +14,20 @@
 
 #include "GUI/View/Instrument/InstrumentsQListView.h"
 #include "Base/Util/Assert.h"
-#include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Device/InstrumentXML.h"
+#include "GUI/Model/Device/InstrumentItems.h"
+#include "GUI/Model/Device/InstrumentsSet.h"
 #include "GUI/Model/Project/ProjectDocument.h"
 #include "GUI/View/Instrument/InstrumentsQListModel.h"
+#include "GUI/View/Layout/ApplicationSettings.h"
 #include "GUI/View/Setup/FrameActions.h"
 #include "GUI/View/Tool/Globals.h"
-#include <QFile>
+#include <QFileDialog>
 #include <QMessageBox>
 #include <QVBoxLayout>
+#include <iostream>
+
+QString InstrumentsQListView::m_xml_dir = "";
 
 InstrumentsQListView::InstrumentsQListView()
     : m_model(new InstrumentsQListModel)
@@ -147,24 +152,53 @@ void InstrumentsQListView::onStoreInLibrary() const
 {
     QModelIndex idx = selectionModel()->selectedIndexes().front();
     InstrumentItem* ii = m_model->instrumentItemForIndex(idx);
+    if (!ii)
+	return;
+
+    QFileDialog dialog(nullptr, "Save instrument", appSettings->xml_dir(), "XML Files (*.xml)");
+    dialog.setAcceptMode(QFileDialog::AcceptSave);
+    dialog.selectFile(ii->instrumentName() + ".xml");
+    if (!dialog.exec())
+	return;
+    QStringList selected_files = dialog.selectedFiles();
+    if (selected_files.size() != 1)
+	return;
+    QString fname = selected_files[0];
+
+    QString fname = ::fileSaveDialog("Save instrument", appSettings->xml_dir, "XML Files (*.xml)",
+				     ii->instrumentName() + ".xml");
+    if (fname.isEmpty())
+        return;
+
     try {
-	InstrumentXML::save("/tmp/instrument.xml", ii);
+        InstrumentXML::save(fname, ii);
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed saving", QString(ex.what()),
-		    QMessageBox::Ok, nullptr).exec();
+                    QMessageBox::Ok, nullptr)
+            .exec();
     }
 }
 
 void InstrumentsQListView::onLoadFromLibrary()
 {
+    QString fname = ::fileLoadDialog("Load instrument", appSettings->xml_dir);
+
+	QFileDialog::getOpenFileName(nullptr, "Load instrument", m_xml_dir, "", nullptr,
+                                                 appSettings->useNativeFileDialog()
+                                                     ? QFileDialog::Options()
+                                                     : QFileDialog::DontUseNativeDialog);
+    if (fname.isEmpty())
+        return;
+
     try {
-	if (InstrumentItem* ii = InstrumentXML::load("/tmp/instrument.xml")) {
-	    QModelIndex idx = m_model->copyInstrument(ii);
-	    selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
-	}
+        if (InstrumentItem* ii = InstrumentXML::load("/tmp/instrument.xml")) {
+            QModelIndex idx = m_model->copyInstrument(ii);
+            selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
+        }
     } catch (const std::exception& ex) {
         QMessageBox(QMessageBox::Warning, "BornAgain: failed loading", QString(ex.what()),
-		    QMessageBox::Ok, nullptr).exec();
+                    QMessageBox::Ok, nullptr)
+            .exec();
     }
 }
 
diff --git a/GUI/View/Instrument/InstrumentsQListView.h b/GUI/View/Instrument/InstrumentsQListView.h
index 84de68c50c1..bfd4c86ee1a 100644
--- a/GUI/View/Instrument/InstrumentsQListView.h
+++ b/GUI/View/Instrument/InstrumentsQListView.h
@@ -55,6 +55,8 @@ private:
     void restoreSelection();
 
     InstrumentsQListModel* m_model;
+
+    static QString m_xml_dir;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_INSTRUMENT_INSTRUMENTSQLISTVIEW_H
diff --git a/GUI/View/Layout/ApplicationSettings.cpp b/GUI/View/Layout/ApplicationSettings.cpp
index 229e968c058..312c459db8b 100644
--- a/GUI/View/Layout/ApplicationSettings.cpp
+++ b/GUI/View/Layout/ApplicationSettings.cpp
@@ -17,6 +17,7 @@
 #include <QApplication>
 #include <QFile>
 #include <QSettings>
+#include <QStandardPaths>
 #include <QStyle>
 
 namespace {
@@ -46,6 +47,8 @@ ApplicationSettings::ApplicationSettings()
     styleSheetPalette.setColor(QPalette::AlternateBase, QColor(255, 255, 255).darker(105));
     styleSheetPalette.setColor(QPalette::Dark, QColor(255, 255, 255).darker(110));
     QApplication::setPalette(styleSheetPalette);
+
+    m_xml_dir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
 }
 
 bool ApplicationSettings::useNativeFileDialog() const
diff --git a/GUI/View/Layout/ApplicationSettings.h b/GUI/View/Layout/ApplicationSettings.h
index 1dc03ceee08..10210b5a9aa 100644
--- a/GUI/View/Layout/ApplicationSettings.h
+++ b/GUI/View/Layout/ApplicationSettings.h
@@ -31,6 +31,11 @@ public:
 
     void saveWindowSizeAndPos(const QWidget* w);
     void loadWindowSizeAndPos(QWidget* w);
+
+    QString xml_dir() { return m_xml_dir; }
+
+private:
+    QString m_xml_dir;
 };
 
 extern ApplicationSettings* appSettings; //!< global pointer to the single instance
-- 
GitLab