]> Devoid-pointer.net GitWeb - anyanka.git/commitdiff
- Extend support for saving user data to JSON-formatted files.
authorMichal Malý <madcatxster@prifuk.cz>
Wed, 12 Mar 2014 11:47:38 +0000 (12:47 +0100)
committerMichal Malý <madcatxster@prifuk.cz>
Wed, 12 Mar 2014 11:47:38 +0000 (12:47 +0100)
- Minor code refactoring

datamanager.cpp
datamanager.h
main.cpp
sequence.cpp
sequence.h
signalcontroller.cpp
signalcontroller.h
singlerundata.cpp
singlerundata.h

index 0e4061efe4e196ab627a322fffc9df17a5ccaa21..9f4b1bc32dffc29a44d59c5feb4b3eac61b9da30 100644 (file)
@@ -25,7 +25,6 @@
 #include "logger.h"
 #include "gui/exportgraphtoimagedialog.h"
 #include "gui/exportrawdatadialog.h"
-#include <QtCore/QJsonDocument>
 #include <QtWidgets/QMessageBox>
 
 #include <QDebug>
@@ -49,6 +48,27 @@ DataManager::DataManager(QObject* parent) :
   m_sigNameCodec = QTextCodec::codecForName("ISO-8859-1");
 }
 
+void DataManager::saveUserDataOnExit()
+{
+  for (NameSequencePair& nsp : m_sequences) {
+    const QString seqName = nsp.first;
+    std::shared_ptr<Sequence> seq = nsp.second;
+    SingleRunsMap::const_iterator it = seq->begin();
+
+    while (it != seq->end()) {
+      std::shared_ptr<SingleRunData> sr = it->second;
+      if (sr->userDataModified()) {
+        const QString srName = QString::fromStdString(it->first);
+        int ret = QMessageBox::question(nullptr, "Save changes?" , "User data in sequence " + seqName + ", signal " + srName + " have been modified. "
+                                        "Would you like to save the changes?", QMessageBox::Yes, QMessageBox::No);
+        if (ret == QMessageBox::Yes)
+          sr->saveUserDataToJSON();
+      }
+      ++it;
+    }
+  }
+}
+
 /* Private functions */
 
 void DataManager::generateIntegDataWriteList(DataFileExporter::WriteList& writeList, const std::shared_ptr<SingleRunData> sr, const std::vector<std::string> &keys)
@@ -202,6 +222,11 @@ Signal::Resource DataManager::resourceFromFiletype(AGRE_Filetype filetype)
   }
 }
 
+bool DataManager::saveSingleRunUserData(std::shared_ptr<SingleRunData> sr)
+{
+  return sr->saveUserDataToJSON();
+}
+
 std::string DataManager::signalControllerKey(const QString& main, const QString& resource)
 {
   return std::string(main.toStdString() + "_" + resource.toStdString());
@@ -234,8 +259,8 @@ std::shared_ptr<SingleRunData> DataManager::loadSingleRun(QDir& dir)
 {
   std::vector<std::shared_ptr<AGRE_MeasurementInfo>> dataFiles;
   std::shared_ptr<SingleRunData> singleRun;
-  std::unordered_map<std::string, std::shared_ptr<Signal>> sigs;
-  std::unordered_map<std::string, std::shared_ptr<SignalController>> ctrls;
+  SignalsMap sigs;
+  SignalControllersMap ctrls;
   DataFilesLoader::ReturnCode ret;
   LocalLoggerPtr llog = Logger::createLocalLog();
   llog->setPrintLevel(Logger::Level::WARNING);
@@ -315,25 +340,6 @@ std::shared_ptr<SingleRunData> DataManager::loadSingleRun(QDir& dir)
 
     _c = std::shared_ptr<SignalController>(new SignalController(_s));
 
-    /* Try to read saved user data from JSON file */
-    QFile jsonFile(dir.path() + "/" + "ank_" + QString::fromStdString(_s->descriptiveName()) + ".json");
-    if (jsonFile.exists()) {
-      if (jsonFile.open(QFile::ReadOnly)) {
-        QByteArray bytes = jsonFile.readAll();
-        QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes);
-        QJsonObject jso = jsonDoc.object();
-
-        if (!_c->deserialize(jso)) {
-          llog->log(Logger::Level::WARNING, ME_SENDER_STR, "Failed to deserialize saved user data for " + QString::fromStdString(_s->descriptiveName()));
-          QMessageBox::warning(nullptr, "Load single run", "Saved user data for signal " + QString::fromStdString(_s->descriptiveName()) +
-                                                           "could not have been read properly.");
-        }
-      } else
-        llog->log(Logger::Level::WARNING, ME_SENDER_STR, "Cannot open saved user data file " + QString::fromStdString(_s->descriptiveName()) +
-                                                           " for reading.");
-    } else
-      llog->log(Logger::Level::DEBUG, ME_SENDER_STR, "No user data file for " + QString::fromStdString(_s->descriptiveName()));
-
     sigs[_s->descriptiveName()] = _s;
     ctrls[_s->descriptiveName()] = _c;
   }
@@ -377,7 +383,7 @@ std::shared_ptr<SingleRunData> DataManager::loadSingleRun(QDir& dir)
 
   singleRun = std::shared_ptr<SingleRunData>(new SingleRunData(methodNames.at(0), operatorNames.at(0), sampleInfos.at(0), dates.at(0), times.at(0), sigs, ctrls,
                                                                dir.dirName(), dir.absolutePath(), this));
-
+  singleRun->readUserDataFromJSON();
 
   Logger::log(Logger::DEBUG, ME_SENDER_STR, "Single run successfully parsed");
 
@@ -398,19 +404,6 @@ void DataManager::showOneSignal(std::shared_ptr<SignalController> ctrl)
   swp->setXUnits(QString::fromStdString(ctrl->signal()->xunitToString()));
   swp->setYUnits(QString::fromStdString(ctrl->signal()->yunitToString()));
 
-  /*connect(swp->m_graphView, SIGNAL(crosshairErased()), ctrl.get(), SLOT(onViewCrosshairErased()));
-  connect(swp->m_graphView, SIGNAL(crosshairMoved(int,int)), ctrl.get(), SLOT(onViewCrosshairMoved(int,int)));
-  connect(swp->m_graphView, SIGNAL(integrated(int,int,int,int)), ctrl.get(), SLOT(onViewIntegrated(int,int,int,int)));
-  connect(swp->m_graphView, SIGNAL(redrawNeeded()), ctrl.get(), SLOT(onViewRedrawNeeded()));
-  connect(swp->m_graphView, SIGNAL(resized(int,int)), ctrl.get(), SLOT(onViewResized(int,int)));
-  connect(swp->m_graphView, SIGNAL(showContextMelnuReq(int,int,QPoint)), ctrl.get(), SLOT(onViewShowContextMenu(int,int,QPoint)));
-  connect(swp->m_graphView, SIGNAL(zoomed(int,int,int,int)), ctrl.get(), SLOT(onViewZoomed(int,int,int,int)));
-  connect(ctrl.get(), SIGNAL(viewDrawGraph(double*,size_t,double,double)), swp->m_graphView, SLOT(onUpdateGraph(double*,size_t,double,double)));
-  connect(ctrl.get(), SIGNAL(viewCtxMenuClosed()), swp->m_graphView, SLOT(onCtxMenuClosed()));
-  connect(ctrl.get(), SIGNAL(viewDrawIntegration(int,double,int,double,int,double,QString,QString)), swp->m_graphView,
-            SLOT(onDrawIntegration(int,double,int,double,int,double,QString,QString)));
-  connect(ctrl.get(), SIGNAL(viewUpdateCurrentValues(double,double)), swp, SLOT(onUpdateCurrentValues(double,double)));
-  connect(ctrl.get(), SIGNAL(viewRemoveCurrentValues()), swp, SLOT(onRemoveCurrentValues()));*/
   emit addToDashboard(swp);
 
   swp->m_graphView->refresh();
@@ -578,28 +571,11 @@ void DataManager::onLoadSingleRun(const QString& str)
 void DataManager::onSaveChanges()
 {
   std::shared_ptr<SingleRunData> sr = m_activeSequence->selectedRun();
-  std::unordered_map<std::string, std::shared_ptr<SignalController>>::const_iterator cit;
 
   if (m_activeSequence == nullptr)
     return;
 
-  const std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls = sr->allControllers();
-  cit = ctrls.cbegin();
-
-  while (cit != ctrls.cend()) {
-    QJsonValue val = cit->second->serialize();
-    QJsonDocument doc(val.toObject());
-    QFile f(sr->absPath() + "/" + "ank_" + QString::fromStdString(cit->first) + ".json");
-    QByteArray bytes = doc.toJson();
-
-    f.open(QFile::WriteOnly);
-    f.write(bytes.data(), bytes.size());
-
-    qDebug() << val;
-    f.close();
-    ++cit;
-  }
-
+  sr->saveUserDataToJSON();
 }
 
 void DataManager::onSequenceSelected(const QString& key)
index 0775feb009f3745c60f71e9b55196ab502085968..f095e859fc137d3ef52516a2d445cfa54d406d41 100644 (file)
@@ -44,6 +44,7 @@ class DataManager : public QObject
   Q_OBJECT
 public:
   explicit DataManager(QObject* parent = nullptr);
+  void saveUserDataOnExit();
   SequenceSelectorModel* sequenceSelectorModel() { return &m_seqSelModel; }
   SingleRunsSelectorModel* singleRunsSelectorModel() { return &m_singleSelModel; }
 
@@ -56,7 +57,8 @@ private:
   std::shared_ptr<SingleRunData> loadSingleRun(QDir& dir);
   void processDataExport(GeneratorFunc genfunc);
   Signal::Resource resourceFromFiletype(AGRE_Filetype filetype);
-  std::string signalControllerKey(const QString& main, const QString& resource) ;
+  bool saveSingleRunUserData(std::shared_ptr<SingleRunData> sr);
+  std::string signalControllerKey(const QString& main, const QString& resource);
   void showOneSignal(std::shared_ptr<SignalController> ctrl);
   Signal::YUnit yunitFromUnitStr(const std::string& unit_str);
 
index fe29bd1a27cd879e986a2df3705664817f7e03aa..b544f218fa33ce2452b93a5370f8bb068f065428 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -31,6 +31,7 @@
 
 int main(int argc, char *argv[])
 {
+  int ret;
   QApplication a(argc, argv);
 
 #ifndef COMPILER_MSVC11
@@ -80,5 +81,9 @@ int main(int argc, char *argv[])
 
   mWin->show();
 
-  return a.exec();
+  ret = a.exec();
+
+  dMgr->saveUserDataOnExit();
+
+  return ret;
 }
index a5fc15f4f8f1815832160b9ec164e96b4719474a..67da0873b0097661c2d34adb4a8228d1affbec41 100644 (file)
@@ -27,7 +27,7 @@ Sequence::Sequence(QObject* parent) :
 {
 }
 
-Sequence::Sequence(std::unordered_map<std::string, std::shared_ptr<SingleRunData>>& singleRuns, QObject* parent) :
+Sequence::Sequence(SingleRunsMap& singleRuns, QObject* parent) :
   QObject(parent),
   m_selectedRunKey("")
 {
index 8e040f55ae2c127464b69d6d2eabd133ea570e22..14485785f7dce77f3c9eaf94bdcceb7194714244 100644 (file)
 #include <vector>
 #include <QtCore/QObject>
 
+typedef std::unordered_map<std::string, std::shared_ptr<SingleRunData>> SingleRunsMap;
+
 class Sequence : public QObject
 {
   Q_OBJECT
 public:
   explicit Sequence(QObject* parent = nullptr);
-  explicit Sequence(std::unordered_map<std::string, std::shared_ptr<SingleRunData>>& singleRuns, QObject* parent = nullptr);
+  explicit Sequence(SingleRunsMap& singleRuns, QObject* parent = nullptr);
   int add(const std::string name, std::shared_ptr<SingleRunData> value);
   std::vector<std::string> allRunKeys() const;
   std::shared_ptr<SingleRunData> at(const std::string& key);
-  std::unordered_map<std::string, std::shared_ptr<SingleRunData>>::iterator begin() { return m_singleRuns.begin(); }
-  std::unordered_map<std::string, std::shared_ptr<SingleRunData>>::const_iterator cbegin() const { return m_singleRuns.cbegin(); }
-  std::unordered_map<std::string, std::shared_ptr<SingleRunData>>::const_iterator cend() const { return m_singleRuns.cend(); }
+  SingleRunsMap::iterator begin() { return m_singleRuns.begin(); }
+  SingleRunsMap::const_iterator cbegin() const { return m_singleRuns.cbegin(); }
+  SingleRunsMap::const_iterator cend() const { return m_singleRuns.cend(); }
   std::shared_ptr<SignalController> controller(const std::string& uid);
   size_t count() const { return m_singleRuns.size(); }
-  std::unordered_map<std::string, std::shared_ptr<SingleRunData>>::iterator end() { return m_singleRuns.end(); }
+  SingleRunsMap::iterator end() { return m_singleRuns.end(); }
   void remove(const std::string& key);
   std::string selectedRunKey() const { return m_selectedRunKey; }
   std::shared_ptr<SingleRunData> selectedRun();
-  //int selectedRunIdx() const;
-  //int singleRunToIdx(const QString& key) const;
   bool setSelectedRun(const std::string& key);
 
 private:
index ce2fd6d55384b705970cb1face4ee5c65218770e..63406b017028639d4e1f0ceee830a733cd6a7bb8 100644 (file)
@@ -37,7 +37,8 @@ const QString SignalController::KEY_PEAKS("peaks");
 SignalController::SignalController(std::shared_ptr<Signal> signal, QObject* parent) :
   QObject(parent),
   JSONSerializable(),
-  m_signal(signal)
+  m_signal(signal),
+  m_userDataModified(false)
 {
   m_integrator = std::shared_ptr<Integrator>(new Integrator(signal));
   m_integTblModel = new IntegrationTableModel(m_integrator);
@@ -67,6 +68,9 @@ PeakDrawData SignalController::deletePeak(const double x)
     Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + " no peak to delete (idx " + QString::number(idx) + ")");
     return PeakDrawData();
   }
+
+  m_userDataModified = true;
+  emit userDataModified();
   return genPeakDrawData(peak);
 }
 
@@ -231,6 +235,8 @@ PeakDrawData SignalController::integratePeak(const double fromX, const double fr
 
   switch (ret) {
     case Integrator::ReturnCode::SUCCESS:
+      emit userDataModified();
+      m_userDataModified = true;
       return genPeakDrawData(peak);
       break;
     case Integrator::ReturnCode::E_NO_FIRST_INTERSECT:
index e4b9b3d430c6f56a88c6c01e6ae370a9c0baebe1..5a3db71ba4380d748c720a2809e1cb7ad76d5aaa 100644 (file)
@@ -108,6 +108,8 @@ public:
   void setGUIViewport(const double fromX, const double fromY, const double toX, const double toY);
   virtual QJsonValue serialize() const;
   const std::shared_ptr<Signal> signal() const { return m_signal; }
+  bool userDataStatus() const { return m_userDataModified; }
+  void userDataSaved() { m_userDataModified = false; }
   const std::shared_ptr<Integrator> cIntegrator() const { return m_integrator; }
 
   double idxToRel(const size_t idx);
@@ -125,6 +127,7 @@ private:
   IntegrationTableModel* m_integTblModel;
   std::shared_ptr<Integrator> m_integrator;
   std::shared_ptr<Signal> m_signal;
+  bool m_userDataModified;
 
   GUIViewport m_guiViewport;
 
@@ -140,6 +143,7 @@ public slots:
 
 signals:
   void fillDataList();
+  void userDataModified();
 };
 
 #endif // SIGNALCONTROLLER_H
index 0b39ff879edc8ea9a9dce4a3889d98192bbfc291..276cb9a0bec0940a5d5cd92141d63594dd91fb26 100644 (file)
   THE SOFTWARE.
 */
 
+#include "logger.h"
 #include "singlerundata.h"
+#include <QtCore/QFile>
+#include <QtCore/QJsonParseError>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonValue>
+#include <QtWidgets/QMessageBox>
+
+const QString SingleRunData::ME_SENDER_STR("SingleRunData");
 
 SingleRunData::SingleRunData(const QString& methodName, const QString& operatorName, const QString& sampleInfo, const QDate date, const QTime time,
-                             std::unordered_map<std::string, std::shared_ptr<Signal>>& sigs, std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls,
+                             SignalsMap& sigs, SignalControllersMap& ctrls,
                              const QString& dirname, const QString& absPath, QObject *parent) :
   QObject(parent),
   m_absPath(absPath),
@@ -32,10 +40,17 @@ SingleRunData::SingleRunData(const QString& methodName, const QString& operatorN
   m_methodName(methodName),
   m_operatorName(operatorName),
   m_sampleInfo(sampleInfo),
+  m_userDataModified(false),
   m_ctrls(ctrls),
   m_signals(sigs),
   m_time(time)
 {
+  SignalControllersMap::iterator it = ctrls.begin();
+
+  while (it != ctrls.end()) {
+    connect(it->second.get(), SIGNAL(userDataModified()), this, SLOT(onUserDataModified()));
+    ++it;
+  }
 }
 
 std::vector<std::string> SingleRunData::allKeys() const
@@ -58,6 +73,87 @@ std::shared_ptr<SignalController> SingleRunData::controllerAt(const std::string&
   }
 }
 
+void SingleRunData::readUserDataFromJSON()
+{
+  SignalControllersMap::iterator it = m_ctrls.begin();
+
+  while (it != m_ctrls.end()) {
+    std::shared_ptr<SignalController> c = it->second;
+    QString descriptiveName = QString::fromStdString(c->signal()->descriptiveName());
+    QString filename = "ank_" + descriptiveName + ".json";
+    QFile jsonFile(m_absPath + "/" + filename);
+
+    if (jsonFile.exists()) {
+      if (!jsonFile.open(QFile::ReadOnly)) {
+        QString errMsg = "Cannot open user data file " + filename + " for reading.";
+        Logger::log(Logger::Level::WARNING, ME_SENDER_STR, errMsg);
+        QMessageBox::warning(nullptr, "Cannot read user data", errMsg);
+        ++it;
+        continue;
+      }
+
+      QJsonParseError parseErr;
+      QByteArray bytes = jsonFile.readAll();
+      QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes, &parseErr);
+      if (parseErr.error != QJsonParseError::NoError) {
+        QString errMsg = "Cannot parse user data file " + filename + " (" + parseErr.errorString() + ")";
+        Logger::log(Logger::Level::WARNING, ME_SENDER_STR, errMsg);
+        QMessageBox::warning(nullptr, "Cannot read user data" , errMsg);
+        ++it;
+        continue;
+      }
+      QJsonObject jso = jsonDoc.object();
+
+      if (!c->deserialize(jso)) {
+        Logger::log(Logger::Level::WARNING, ME_SENDER_STR, "Failed to deserialize saved user data for " + descriptiveName);
+        QMessageBox::warning(nullptr, "Load single run", "Saved user data for signal " + descriptiveName +
+                                                           "could not have been read properly.");
+      }
+    }
+
+    ++it;
+  }
+}
+
+bool SingleRunData::saveUserDataToJSON()
+{
+  SignalControllersMap::const_iterator cit = m_ctrls.cbegin();
+
+  while (cit != m_ctrls.cend()) {
+    if (!cit->second->userDataStatus()) {
+      ++cit;
+      continue;
+    }
+
+    QJsonValue val = cit->second->serialize();
+    if (!val.isObject()) {
+      Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + " QJsonValue is not an object!");
+      return false;
+    }
+    QJsonDocument doc(val.toObject());
+
+    QString filename("ank_" + QString::fromStdString(cit->first) + ".json");
+    QFile f(m_absPath + "/" + filename);
+    QByteArray bytes = doc.toJson();
+
+    if (!f.open(QFile::WriteOnly)) {
+      QString errMsg = "Cannot open output file " + filename + " for writing (" + f.errorString() + ")";
+      Logger::log(Logger::Level::WARNING, ME_SENDER_STR, errMsg);
+      QMessageBox::warning(nullptr, "Cannot save user data", errMsg);
+      return false;
+    }
+    f.write(bytes.data(), bytes.size());
+
+    qDebug() << val;
+    f.close();
+    cit->second->userDataSaved();
+    ++cit;
+  }
+
+  m_userDataModified = false;
+  return true;
+}
+
 std::shared_ptr<Signal> SingleRunData::signalAt(const std::string& key)
 {
   try {
index b0f1c1d08f981124af14321d004e66b1735ef6d8..24197177ada2d7c0b6448b8cf61003300e2a90b7 100644 (file)
 #include <QtCore/QObject>
 #include <QtCore/QTime>
 
+typedef std::unordered_map<std::string, std::shared_ptr<SignalController>> SignalControllersMap;
+typedef std::unordered_map<std::string, std::shared_ptr<Signal>> SignalsMap;
+
 class SingleRunData : public QObject
 {
   Q_OBJECT
 public:
   explicit SingleRunData(const QString& methodName, const QString& operatorName, const QString& sampleInfo, const QDate date, const QTime time,
-                         std::unordered_map<std::string, std::shared_ptr<Signal>>& sigs, std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls,
+                         SignalsMap& sigs, SignalControllersMap& ctrls,
                          const QString& dirname, const QString& absPath, QObject* parent = nullptr);
   QString absPath() const { return m_absPath; }
-  const std::unordered_map<std::string, std::shared_ptr<SignalController>>& allControllers() const { return m_ctrls; }
+  const SignalControllersMap& allControllers() const { return m_ctrls; }
   std::vector<std::string> allKeys() const;
-  const std::unordered_map<std::string, std::shared_ptr<Signal>>& allSignals() const { return m_signals; }
+  const SignalsMap& allSignals() const { return m_signals; }
   std::shared_ptr<SignalController> controllerAt(const std::string& key);
   QDate date() const { return m_date; }
   QString dirName() const { return m_dirName; }
   QString methodName() const { return m_methodName; }
   QString operatorName() const { return m_operatorName; }
+  void readUserDataFromJSON();
+  bool saveUserDataToJSON();
   QString sampleInfo() const { return m_sampleInfo; }
   std::shared_ptr<Signal> signalAt(const std::string& key);
   size_t signalCount() const { return m_signals.size(); }
   QTime time() const { return m_time; }
+  bool userDataModified() const { return m_userDataModified; }
 
 private:
   const QString m_absPath;
@@ -59,13 +65,17 @@ private:
   const QString m_methodName;
   const QString m_operatorName;
   const QString m_sampleInfo;
-  std::unordered_map<std::string, std::shared_ptr<SignalController>> m_ctrls;
-  std::unordered_map<std::string, std::shared_ptr<Signal>> m_signals;
+  bool m_userDataModified;
+  SignalControllersMap m_ctrls;
+  SignalsMap m_signals;
   const QTime m_time;
 
+  static const QString ME_SENDER_STR;
+
 signals:
 
 public slots:
+  void onUserDataModified() { m_userDataModified = true; }
 
 };