]> Devoid-pointer.net GitWeb - anyanka.git/commitdiff
Heavy redesign to better separate drawing from the user input and signal
authorMichal Malý <madcatxster@prifuk.cz>
Sun, 9 Mar 2014 16:32:51 +0000 (17:32 +0100)
committerMichal Malý <madcatxster@prifuk.cz>
Sun, 9 Mar 2014 16:32:51 +0000 (17:32 +0100)
handling logic. All signal drawers can now be a separate classes with
shared common functionality.

17 files changed:
Anyanka.pro
datamanager.cpp
enumflags.h [new file with mode: 0644]
graphtoimageexporter.cpp [deleted file]
graphtoimageexporter.h [deleted file]
gui/exportgraphtoimagedialog.cpp
gui/graphview.cpp
imagedrawer.cpp
imagedrawer.h
integrationtablemodel.cpp
integrationtablemodel.h
integrator.cpp
integrator.h
signalcontroller.cpp
signalcontroller.h
signaldrawer.cpp
signaldrawer.h

index ebc0bae95b648daa0b759238d817f75c03ecd8bc..083393925e3b3a8805f96eb63d1668c0b8b84fc7 100644 (file)
@@ -14,7 +14,7 @@ TEMPLATE = app
 
 unix {
         LIBS += -ldl
-        QMAKE_CXXFLAGS += -std=c++11 -Wall
+        QMAKE_CXXFLAGS += -std=c++11 -Wall -Wextra
 }
 win32 {
         SOURCES += windows_defines.h
@@ -51,7 +51,6 @@ SOURCES += main.cpp\
     datawriterbackend.cpp \
     csvdatawriterbackend.cpp \
     gui/exportgraphtoimagedialog.cpp \
-    graphtoimageexporter.cpp \
     imagedrawer.cpp \
     signaldrawer.cpp
 
@@ -85,9 +84,9 @@ HEADERS  += \
     datawriterbackend.h \
     csvdatawriterbackend.h \
     gui/exportgraphtoimagedialog.h \
-    graphtoimageexporter.h \
     imagedrawer.h \
-    signaldrawer.h
+    signaldrawer.h \
+    enumflags.h
 
 FORMS += \
     gui/mainwindow.ui \
index c10e0de0d16f3db28b70279259ece9628c137775..96cec2aec7586007f528eec07cfedd753efbe113 100644 (file)
@@ -25,7 +25,6 @@
 #include "logger.h"
 #include "gui/exportgraphtoimagedialog.h"
 #include "gui/exportrawdatadialog.h"
-#include <QtGui/QImageWriter>
 #include <QtWidgets/QMessageBox>
 
 #include <QDebug>
@@ -56,7 +55,8 @@ void DataManager::generateIntegDataWriteList(DataFileExporter::WriteList& writeL
     std::vector<QVariantList> lines;
     std::pair<QVariantList, std::vector<QVariantList>> p;
     const std::shared_ptr<SignalController> ctrl = sr->controllerAt(key);
-    std::shared_ptr<const Integrator> integrator;
+    std::shared_ptr<Integrator> integrator;
+    std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks;
     if (ctrl == nullptr)
       continue;
 
@@ -64,10 +64,12 @@ void DataManager::generateIntegDataWriteList(DataFileExporter::WriteList& writeL
               + QString::fromStdString(ctrl->signal()->yunitToString()) + "]" << "width [" + QString::fromStdString(ctrl->signal()->xunitToString()) + "]"
               << "height [" + QString::fromStdString(ctrl->signal()->yunitToString()) + "]";
     integrator = ctrl->cIntegrator();
-    for (std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator cit = integrator->peaksCBegin();
-         cit != integrator->peaksCEnd(); cit++) {
+    /*for (std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator cit = integrator->peaksCBegin();
+         cit != integrator->peaksCEnd(); cit++) {*/
+    allPeaks = integrator->allPeaks();
+    for (std::shared_ptr<const IntegratedPeak> peak : allPeaks) {
       QVariantList line;
-      line << cit->second->peakTime() << cit->second->auc() << cit->second->width() << cit->second->height();
+      line << peak->peakTime() << peak->auc() << peak->width() << peak->height();
       lines.push_back(line);
     }
     p = std::pair<QVariantList, std::vector<QVariantList>>(header, lines);
@@ -376,8 +378,7 @@ void DataManager::showOneSignal(std::shared_ptr<SignalController> ctrl)
 
 void DataManager::onExportGraphToImage()
 {
-  QImageWriter imageWriter;
-  ExportGraphToImageDialog dlg(imageWriter.supportedImageFormats());
+  ExportGraphToImageDialog dlg(ImageDrawer::supportedImageFormats());
   std::shared_ptr<SingleRunData> sr;
 
   if (m_activeSequence == nullptr)
@@ -391,54 +392,30 @@ void DataManager::onExportGraphToImage()
   }
 
   if (dlg.exec() == QDialog::Accepted) {
-    double fromX = 0, toX = 0;
-    double fromY = 0, toY = 0;
-    int iw, ih;
     const std::string key = dlg.selectedSignal().toStdString();
     std::shared_ptr<SignalController> ctrl = sr->controllerAt(key);
-    std::shared_ptr<Signal> sig;
+    GraphLayers gl = GraphLayers::GRAPH | GraphLayers::SCALE;
 
     if (ctrl == nullptr) {
       Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "Invalid key " + QString::fromStdString(key) + " passed to image exporter");
       return;
     }
-    fromX = dlg.fromX();
-    toX = dlg.toX();
-    fromY = dlg.fromY();
-    toY = dlg.toY();
-    iw = dlg.imageWidth();
-    ih = dlg.imageHeight();
-    sig = ctrl->signal();
-
-    if (iw < 1) {
-      QMessageBox::warning(nullptr, "Error while exporting to image", "Invalid width value");
-      return;
-    }
-    if (ih < 1) {
-      QMessageBox::warning(nullptr, "Error while exporting to image", "Invalid width value");
-      return;
-    }
+
     if (dlg.path().length() == 0) {
       QMessageBox::warning(nullptr, "Error while exporting to image", "Invalid path");
       return;
     }
-    qDebug() << fromX << fromY << toX << toY;
 
     /*if (data == nullptr) {
       QMessageBox::warning(nullptr, "Error while exporting to image", "Cannot generate data to draw. Some values are probably invalid.");
       return;
     }*/
 
-    ImageDrawer imgDrawer(iw, ih, this);
-    connect(ctrl.get(), SIGNAL(viewDrawGraph(double*,size_t,double,double)), &imgDrawer, SLOT(onUpdateGraph(double*,size_t,double,double)));
-    connect(ctrl.get(), SIGNAL(viewDrawIntegration(int,double,int,double,int,double,QString,QString)), &imgDrawer, SLOT(onDrawIntegration(int,double,int,double,int,double,QString,QString)));
-    //ctrl->onViewResized(iw, ih);
-    //ctrl->onViewZoomedByValues(fromX, fromY, toX, toY);
+    if (dlg.includePeaks())
+      gl |= GraphLayers::INTEGRATION;
 
-    QImage result = imgDrawer.pixmap()->toImage();
-    imageWriter.setFileName(dlg.path() + "." + dlg.imageFormat());
-    imageWriter.setFormat(dlg.imageFormat().toLatin1());
-    if (!imageWriter.write(result))
+    ImageDrawer imageDrawer(ctrl);
+    if (!imageDrawer.render(dlg.path() + "." + dlg.imageFormat(), dlg.imageFormat().toLatin1(), dlg.imageWidth(), dlg.imageHeight(), gl))
       QMessageBox::critical(nullptr, "Error while exporting to image", "Image could not have been written.");
 
   }
diff --git a/enumflags.h b/enumflags.h
new file mode 100644 (file)
index 0000000..d94c3eb
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+Copyright (c) 2013, Yuri Yaryshev (aka Lord Odin)
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/*
+Usage sample:
+
+#indlude "enum_flags.h"
+
+ENUM_FLAGS(foo_t)
+enum class foo_t
+    {
+     none           = 0x00
+    ,a              = 0x01
+    ,b              = 0x02
+    };
+
+ENUM_FLAGS(foo2_t)
+enum class foo2_t
+    {
+     none           = 0x00
+    ,d              = 0x01
+    ,e              = 0x02
+    };
+
+int _tmain(int argc, _TCHAR* argv[])
+    {
+    if(flags(foo_t::a & foo_t::b)) {};
+    // if(flags(foo2_t::d & foo_t::b)) {};  // Type safety test - won't compile if uncomment
+    };
+
+*/
+
+#ifndef ENUM_FLAGS_H
+#define ENUM_FLAGS_H
+
+/*
+Use this line before header, if you don't want flags(T x) function to be implemented for your enum.
+#define USE_ENUM_FLAGS_FUNCTION 0
+*/
+
+#ifndef USE_ENUM_FLAGS_FUNCTION
+#define USE_ENUM_FLAGS_FUNCTION 1
+#endif
+
+
+#define ENUM_FLAGS_EX_NO_FLAGS_FUNC(T,INT_T) \
+enum class T;  \
+inline T       operator        &       (T x, T y)              {       return static_cast<T>   (static_cast<INT_T>(x) & static_cast<INT_T>(y));        }; \
+inline T       operator        |       (T x, T y)              {       return static_cast<T>   (static_cast<INT_T>(x) | static_cast<INT_T>(y));        }; \
+inline T       operator        ^       (T x, T y)              {       return static_cast<T>   (static_cast<INT_T>(x) ^ static_cast<INT_T>(y));        }; \
+inline T       operator        ~       (T x)                   {       return static_cast<T>   (~static_cast<INT_T>(x));                                                       }; \
+inline T&      operator        &=      (T& x, T y)             {       x = x & y;      return x;       }; \
+inline T&      operator        |=      (T& x, T y)             {       x = x | y;      return x;       }; \
+inline T&      operator        ^=      (T& x, T y)             {       x = x ^ y;      return x;       };
+
+#if(USE_ENUM_FLAGS_FUNCTION)
+
+       #define ENUM_FLAGS_EX(T,INT_T) ENUM_FLAGS_EX_NO_FLAGS_FUNC(T,INT_T) \
+       inline bool                     flags(T x)                      {       return static_cast<INT_T>(x) != 0;};
+
+#else
+
+       #define ENUM_FLAGS_EX(T,INT_T) ENUM_FLAGS_EX_NO_FLAGS_FUNC(T,INT_T)
+
+#endif
+
+#define ENUM_FLAGS(T) ENUM_FLAGS_EX(T,intptr_t)
+
+#endif //ENUM_FLAGS_H
diff --git a/graphtoimageexporter.cpp b/graphtoimageexporter.cpp
deleted file mode 100644 (file)
index 5ce57c5..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "graphtoimageexporter.h"
-
-GraphToImageExporter::GraphToImageExporter(QObject* parent) :
-  QObject(parent)
-{
-}
-
-GraphToImageExporter::ReturnCode GraphToImageExporter::setParameters(const double fromX, const double fromY, const double toX, const double toY, const int width,
-                                                                     const int height, const QByteArray format, const QString& filename,
-                                                                     const std::shared_ptr<SignalController> ctrl)
-{
-  uint idx;
-
-  if (fromX >= toX)
-    return ReturnCode::E_INVALID_BOUNDS;
-  if (filename.length() == 0)
-    return ReturnCode::E_INVALID_FILENAME;
-  if (ctrl == nullptr)
-    return ReturnCode::E_NULL_CONTROLLER;
-  if (width < 1 || height < 1)
-    return ReturnCode::E_INVALID_SIZE;
-
-  /* Get from an to indices */
-  const std::vector<Signal::TimeValuePair>& tvpairs = ctrl->signal()->values();
-  for (idx = 0; idx < tvpairs.size(); idx++) {
-    if (tvpairs.at(idx).first >= fromX) {
-      m_fromIdx = idx;
-      break;
-    }
-  }
-  if (idx == tvpairs.size())
-    return ReturnCode::E_INVALID_BOUNDS;
-  for (;idx < tvpairs.size(); idx++) {
-    if (tvpairs.at(idx).first >= toX) {
-      m_toIdx = idx;
-      break;
-    }
-  }
-  if (idx == tvpairs.size())
-    m_toIdx = idx - 1;
-
-
-  //m_data = ctrl->generateDrawData(m_fromIdx, m_toIdx);
-  if (m_data == nullptr)
-    return ReturnCode::E_NULL_DATA;
-
-  return ReturnCode::SUCCESS;
-}
diff --git a/graphtoimageexporter.h b/graphtoimageexporter.h
deleted file mode 100644 (file)
index d16cb0f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef GRAPHTOIMAGEEXPORTER_H
-#define GRAPHTOIMAGEEXPORTER_H
-
-#include "signalcontroller.h"
-#include <QtCore/QObject>
-#include <QtGui/QImageWriter>
-
-class GraphToImageExporter : public QObject
-{
-  Q_OBJECT
-public:
-  enum class ReturnCode {
-    SUCCESS,
-    E_INVALID_BOUNDS,
-    E_INVALID_FORMAT,
-    E_INVALID_FILENAME,
-    E_NULL_CONTROLLER,
-    E_INVALID_SIZE,
-    E_NULL_DATA
-  };
-
-  explicit GraphToImageExporter(QObject* parent = nullptr);
-  ReturnCode setParameters(const double fromX, const double fromY, const double toX, const double toY, const int width, const int height,
-                           const QByteArray format, const QString& filename, const std::shared_ptr<SignalController> ctrl);
-  QList<QByteArray> supportedImageFormats();
-
-private:
-  const std::shared_ptr<SignalController> m_ctrl;
-  double* m_data;
-  QString m_filename;
-  double m_fromIdx;
-  double m_fromY;
-  double m_toIdx;
-  double m_toY;
-  int m_height;
-  int m_width;
-  QImageWriter m_writer;
-
-signals:
-
-public slots:
-
-};
-
-#endif // GRAPHTOIMAGEEXPORTER_H
index eea1c1dae771d2f5256714a801d19037b8a803a3..04568ae22592f5f511d179e77b91070874eaf8a7 100644 (file)
@@ -52,6 +52,11 @@ QString ExportGraphToImageDialog::imageFormat() const
   return ui->qcbox_outputFormat->currentText();
 }
 
+bool ExportGraphToImageDialog::includePeaks() const
+{
+  return ui->qck_includeInteg->isChecked();
+}
+
 int ExportGraphToImageDialog::imageHeight() const
 {
   bool ok;
index 42c337dd1000c818f3f6108805fd41a3a4e2b037..20c5519792cb6e3eb07ff9de88d4f6f8b161cf68 100644 (file)
@@ -447,8 +447,6 @@ void GraphView::unzoom()
 
 void GraphView::setDefaultZoom()
 {
-  double range = SignalController::RELATIVE_MAX - SignalController::RELATIVE_MIN;
-
   m_relXMax = SignalController::RELATIVE_MAX;
   m_relXMin = SignalController::RELATIVE_MIN;
   m_relYMax = RELATIVE_Y_MAX_WITH_MARGIN();
index 0ba340cfca8a08ac3a22339b6338bfeb5c07841a..430ee77b3036ecd36ff4aed6a8630cc85b587ed2 100644 (file)
@@ -2,39 +2,29 @@
 
 #include <QDebug>
 
-ImageDrawer::ImageDrawer(const int width, const int height, QObject* parent) :
-  QObject(parent),
-  m_height(height),
-  m_width(width)
+ImageDrawer::ImageDrawer(std::shared_ptr<SignalController> controller) :
+  SignalDrawer(controller),
+  m_controller(controller)
 {
+  m_imageWriter.setCompression(0);
 }
 
-void ImageDrawer::onUpdateGraph(double* data, size_t len, double min, double max)
+bool ImageDrawer::render(const QString& filename, const QByteArray format, const int width, const int height, const GraphLayers layers)
 {
-  if (data == nullptr)
-    return;
-  m_drawDataMin = min;
-  m_drawDataMax = max;
+  QImage image;
 
-  //m_pixmap = m_graphDrawer->drawGraph(data, len, m_width, m_height, min, max);
-}
-
-void ImageDrawer::onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakStartX, const double peakStartY,
-                                    const QString& time, const QString& area)
-{
-  double xStep = static_cast<double>(m_width);
-  double yStep = static_cast<double>(m_height) / (m_drawDataMax - m_drawDataMin);
-  int startX = floor(fromX * xStep + 0.5);
-  int stopX = floor(toX * xStep + 0.5);
-  int startY = floor((m_height - yStep * (fromY - m_drawDataMin)) + 0.5);
-  int stopY = floor((m_height - yStep * (toY - m_drawDataMin)) + 0.5);
-  int peakX = floor(peakStartX * xStep + 0.5);
-  int peakY = floor(m_height - yStep * (peakStartY - m_drawDataMin) + 0.5);
+  setDimensions(width, height);
+  if (!draw(SignalController::RELATIVE_MIN, SignalController::RELATIVE_MIN, SignalController::RELATIVE_MAX, SignalController::RELATIVE_MAX, layers))
+    return false;
 
-  if (m_pixmap == nullptr)
-    return;
+  m_imageWriter.setFileName(filename);
+  m_imageWriter.setFormat(format);
+  image = m_pixmap->toImage();
 
-  qDebug() << "drawing peak";
+  return m_imageWriter.write(image);
+}
 
-  //m_graphDrawer->overlayIntegratedPeak(m_pixmap, startX, startY, stopX, stopY, peakX, peakY, time, area);
+QList<QByteArray> ImageDrawer::supportedImageFormats()
+{
+  return QImageWriter::supportedImageFormats();
 }
index c3c2973bf2db82b1eb2e22ce7393519ed01cbf48..b27922e829bc1831dd9777d60d8f045739f93bea 100644 (file)
@@ -1,29 +1,21 @@
 #ifndef IMAGEDRAWER_H
 #define IMAGEDRAWER_H
 
-#include <QtCore/QObject>
+#include "signaldrawer.h"
+#include <QtGui/QImageWriter>
 
-class ImageDrawer : public QObject
+class ImageDrawer : protected SignalDrawer
 {
-  Q_OBJECT
 public:
-  explicit ImageDrawer(const int width, const int height, QObject* parent = nullptr);
-  const QPixmap* pixmap() const { return m_pixmap; }
+  explicit ImageDrawer(std::shared_ptr<SignalController> controller);
+  bool render(const QString& filename, const QByteArray format, const int width, const int height, const GraphLayers layers);
 
-private:
-  QPixmap* m_pixmap;
-  int m_drawDataMin;
-  int m_drawDataMax;
-
-  const int m_height;
-  const int m_width;
+  static QList<QByteArray> supportedImageFormats();
 
-signals:
+private:
+  std::shared_ptr<SignalController> m_controller;
+  QImageWriter m_imageWriter;
 
-public slots:
-  void onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakStartX, const double peakStartY,
-                         const QString& time, const QString& area);
-  void onUpdateGraph(double* data, size_t len, double min, double max);
 
 };
 
index a2172827e230e8772f941d6b788b6da833c6b4f7..de3cccea580e608c2982a2911e882532a7b12fec 100644 (file)
 */
 
 #include "integrationtablemodel.h"
+#include "logger.h"
 #include <QtCore/QLocale>
 
+const QString IntegrationTableModel::ME_SENDER_STR("IntegrationTableModel");
+
 IntegrationTableModel::IntegrationTableModel(const std::shared_ptr<Integrator> integrator, QObject* parent) :
   QAbstractTableModel(parent),
   m_integrator(integrator)
@@ -35,7 +38,11 @@ QVariant IntegrationTableModel::data(const QModelIndex& index, int role) const
   if (index.row() >= m_integrator->peakCount())
     return QVariant();
 
-  const std::shared_ptr<IntegratedPeak> peak = m_integrator->peakByIdx(index.row());
+  std::shared_ptr<const IntegratedPeak> peak = m_integrator->peakByListIdx(index.row());
+  if (peak == nullptr) {
+    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "Null pointer to peak");
+    return QVariant();
+  }
   switch (role) {
     case Qt::DisplayRole:
     switch (index.column()) {
@@ -85,3 +92,25 @@ int IntegrationTableModel::rowCount(const QModelIndex& parent) const
 
   return m_integrator->peakCount();
 }
+
+void IntegrationTableModel::prepToAdd(const int idx)
+{
+
+  beginInsertRows(QModelIndex(), idx ,idx);
+}
+
+void IntegrationTableModel::addDone()
+{
+  endInsertRows();
+}
+
+void IntegrationTableModel::prepToDelete(const int idx)
+{
+  beginRemoveRows(QModelIndex(), idx, idx);
+}
+
+void IntegrationTableModel::deleteDone()
+{
+  endRemoveRows();
+}
+
index 90daac46df248f55614074e81de1eb5b108f4d20..83c241d2a9197cf014cb3294288380a289d88bcf 100644 (file)
 
 class IntegrationTableModel : public QAbstractTableModel
 {
+  Q_OBJECT
 public:
   IntegrationTableModel(const std::shared_ptr<Integrator> integrator, QObject* parent = nullptr);
   QVariant data(const QModelIndex& index, int role) const;
-  void doneReset() { endResetModel(); }
   int columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return 4; }
   QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-  void prepReset() { beginResetModel(); }
   int rowCount(const QModelIndex& parent) const;
 
 private:
   const std::shared_ptr<Integrator> m_integrator;
+
+  static const QString ME_SENDER_STR;
+
+public slots:
+  void prepToAdd(const int idx);
+  void prepToDelete(const int idx);
+  void addDone();
+  void deleteDone();
 };
 
 #endif // INTEGRATIONTABLEMODEL_H
index 9c5daab48542241294ac7ae3107eb0f895b3fadc..5e8365c3fec1b4b59e274b712626881712d1e211 100644 (file)
@@ -32,22 +32,44 @@ Integrator::Integrator(std::shared_ptr<Signal> signal, QObject* parent) :
   m_signal(signal)
 {}
 
-std::shared_ptr<IntegratedPeak> Integrator::deletePeak(size_t idx)
+std::shared_ptr<const IntegratedPeak> Integrator::deletePeak(size_t idx)
 {
+  size_t ctr = 0;
   std::shared_ptr<IntegratedPeak> peak;
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::iterator it = m_peaks.begin();
 
-  while (it != m_peaks.end() && it->first <= idx) {
-    if (it->first <= idx && it->second->toIdx() > idx) { /* Peak is surrounding the cursor */
-      peak = it->second;
-      m_peaks.erase(it);
-      return peak;
+  m_peaksList.setToFirst();
+  while ((peak = m_peaksList.getCurrent()) != nullptr) {
+    if (peak->fromIdx() <= idx && peak->toIdx() >= idx) { /* Peak is surrounding the cursor */
+      qDebug() << "Deleting peak ctr" << ctr << "auc" << peak->auc();
+      std::shared_ptr<IntegratedPeak> copyPeak = peak;
+      emit deletingPeak(ctr);
+      m_peaksList.removeCurrent();
+      emit peakRemoved();
+      return copyPeak;
     }
-    it++;
+    m_peaksList.next();
+
+    qDebug() << "Going through peaks to delete, ctr " << ctr << "peak auc" << peak->auc();
+    ctr++;
   }
+
   return nullptr;
 }
 
+std::vector<std::shared_ptr<const IntegratedPeak>> Integrator::allPeaks()
+{
+  std::shared_ptr<const IntegratedPeak> peak;
+  std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks;
+
+  m_peaksList.setToFirst();
+  while ((peak = m_peaksList.getCurrent()) != nullptr) {
+    allPeaks.push_back(peak);
+    m_peaksList.next();
+  }
+
+  return allPeaks;
+}
+
 Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak)
 {
   size_t peakValueIdx;
@@ -150,15 +172,109 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
   peak = std::shared_ptr<IntegratedPeak>(new IntegratedPeak(peakType, auc, peakValueIdx, m_signal->timeAt(peakValueIdx), m_signal->valueAt(peakValueIdx),
                                                             startIntersIdx, stopIntersIdx, m_signal->timeAt(startIntersIdx), m_signal->timeAt(stopIntersIdx),
                                                             startYVal, stopYVal));
-  m_peaks.insert(std::pair<size_t, std::shared_ptr<IntegratedPeak>>(startIdx, peak));
-
+  emit addingPeak(m_peaksList.count());
+  m_peaksList.append(peak);
+  emit peakAdded();
+  qDebug() << "Peak added, count" << m_peaksList.count();
   return ReturnCode::SUCCESS;
 }
 
-const std::shared_ptr<IntegratedPeak> Integrator::peakByIdx(const int idx) const
+std::shared_ptr<const IntegratedPeak> Integrator::peakByListIdx(const size_t idx)
+{
+  if (m_peaksList.count() == 0)
+    return nullptr;
+  if (idx >= m_peaksList.count())
+    return nullptr;
+
+  m_peaksList.setToFirst();
+
+  /*while (ctr++ != idx && (peak = m_peaksList.getCurrent()) != nullptr) {
+    peak = m_peaksList.getCurrent();
+    m_peaksList.next();
+  }*/
+  for (size_t i = 0; i < idx; i++)
+    m_peaksList.next();
+
+  return m_peaksList.getCurrent();
+}
+
+/* Linked list methods */
+Integrator::PeaksLinkedList::PeaksLinkedList() :
+  first(nullptr),
+  current(nullptr),
+  last(nullptr),
+  ctr(0)
+{}
+
+void Integrator::PeaksLinkedList::append(std::shared_ptr<IntegratedPeak> peak)
+{
+  ListItem* item = new ListItem(peak);
+
+  if (first == nullptr) {
+    first = item;
+    item->prev = nullptr;
+  } else {
+    last->next = item;
+    item->prev = last;
+  }
+
+  last = item;
+  ctr++;
+}
+
+std::shared_ptr<IntegratedPeak> Integrator::PeaksLinkedList::getCurrent()
+{
+  if (current == nullptr)
+    return nullptr;
+
+  return current->m_peak;
+}
+
+std::shared_ptr<IntegratedPeak> Integrator::PeaksLinkedList::getFirst()
+{
+  if (first == nullptr)
+    return nullptr;
+
+  return first->m_peak;
+}
+
+void Integrator::PeaksLinkedList::removeCurrent()
 {
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator it = m_peaks.begin();
-  std::advance(it, idx);
+  ListItem* deleteMe;
 
-  return it->second;
+  if (current == nullptr)
+    return;
+
+  if (ctr == 1) {
+    first = nullptr;
+    last = nullptr;
+  } else if (current == first) {
+    first = first->next;
+    if (first != nullptr)
+      first->prev = nullptr;
+  } else if (current == last) {
+    last = current->prev;
+    last->next = nullptr;
+  } else {
+    ListItem* prev = current->prev;
+    prev->next = current->next;
+  }
+
+  deleteMe = current;
+  current = current->next;
+  ctr--;
+  delete deleteMe;
+}
+
+void Integrator::PeaksLinkedList::next()
+{
+  if (current == nullptr)
+    current = first;
+  else
+    current = current->next;
+}
+
+void Integrator::PeaksLinkedList::setToFirst()
+{
+  current = first;
 }
index 8b76108e9b474ad323dc5f9697d257766410fb77..08c0fe1f1d1502840af164497e9a12de88037c1b 100644 (file)
@@ -42,20 +42,48 @@ public:
   };
 
   explicit Integrator(std::shared_ptr<Signal> signal, QObject* parent = nullptr);
-  std::shared_ptr<IntegratedPeak> deletePeak(size_t idx);
+  std::shared_ptr<const IntegratedPeak> deletePeak(size_t idx);
+  std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks();
   ReturnCode integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak);
-  const std::shared_ptr<IntegratedPeak> peakByIdx(const int idx) const;
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCBegin() const { return m_peaks.cbegin(); }
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCEnd() const { return m_peaks.cend(); }
-  size_t peakCount() const { return m_peaks.size(); }
+  std::shared_ptr<const IntegratedPeak> peakByListIdx(const size_t idx);
+  //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCBegin() const { return m_peaks.cbegin(); }
+  //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCEnd() const { return m_peaks.cend(); }
+  size_t peakCount() const { return m_peaksList.count(); }
 
 private:
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>> m_peaks;
+  struct ListItem {
+    ListItem(std::shared_ptr<IntegratedPeak> peak) : m_peak(peak), next(nullptr) {}
+    std::shared_ptr<IntegratedPeak> m_peak;
+    ListItem* prev;
+    ListItem* next;
+  };
+  class PeaksLinkedList {
+  public:
+    explicit PeaksLinkedList();
+    void append(std::shared_ptr<IntegratedPeak> peak);
+    size_t count() const { return ctr; }
+    std::shared_ptr<IntegratedPeak> getCurrent();
+    std::shared_ptr<IntegratedPeak> getFirst();
+    void next();
+    void removeCurrent();
+    void setToFirst();
+  private:
+    ListItem* first;
+    ListItem* current;
+    ListItem* last;
+    size_t ctr;
+  };
+
+  PeaksLinkedList m_peaksList;
   std::shared_ptr<Signal> m_signal;
 
   static const QString ME_SENDER_STR;
 
 signals:
+  void addingPeak(const int idx);
+  void deletingPeak(const int idx);
+  void peakAdded();
+  void peakRemoved();
 
 public slots:
 
index 14a77642065c9b92b8940e42dbbde6013736f2c4..94880fbca457ea3b50362b9403547d216af9fdbe 100644 (file)
@@ -37,6 +37,11 @@ SignalController::SignalController(std::shared_ptr<Signal> signal, QObject* pare
   m_integrator = std::shared_ptr<Integrator>(new Integrator(signal));
   m_integTblModel = new IntegrationTableModel(m_integrator);
   m_dtblModel = new SignalDataTableModel(signal);
+
+  connect(m_integrator.get(), SIGNAL(addingPeak(int)), m_integTblModel, SLOT(prepToAdd(int)));
+  connect(m_integrator.get(), SIGNAL(peakAdded()), m_integTblModel, SLOT(addDone()));
+  connect(m_integrator.get(), SIGNAL(deletingPeak(int)), m_integTblModel, SLOT(prepToDelete(int)));
+  connect(m_integrator.get(), SIGNAL(peakRemoved()), m_integTblModel, SLOT(deleteDone()));
 }
 
 /** Public methods **/
@@ -44,22 +49,19 @@ SignalController::SignalController(std::shared_ptr<Signal> signal, QObject* pare
 PeakDrawData SignalController::deletePeak(const double x)
 {
   size_t idx = relToIdx(x);
-  std::shared_ptr<IntegratedPeak> peak;
+  std::shared_ptr<const IntegratedPeak> peak;
 
   if (idx > m_signal->count()-1) {
     Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, __QFUNC__ + " idx value " + QString::number(idx) + " out of bounds!");
     return PeakDrawData();
   }
 
-  m_integTblModel->prepReset();
   peak = m_integrator->deletePeak(idx);
 
   if (peak == nullptr) {
     Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + " no peak to delete (idx " + QString::number(idx) + ")");
-    m_integTblModel->doneReset();
     return PeakDrawData();
   }
-  m_integTblModel->doneReset();
   return genPeakDrawData(peak);
 }
 
@@ -97,7 +99,8 @@ std::vector<PeakDrawData> SignalController::getPeaksDrawData(const double fromX,
 {
   std::vector<PeakDrawData> peaks;
   size_t fromIdx, toIdx;
-  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator cit = m_integrator->peaksCBegin();
+  std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks;
+  //  std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator cit = m_integrator->peaksCBegin();
 
   if (toX <= fromX) {
     Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " toX is lower than fromX");
@@ -116,14 +119,12 @@ std::vector<PeakDrawData> SignalController::getPeaksDrawData(const double fromX,
     return peaks;
   }
 
-  while (cit != m_integrator->peaksCEnd()) {
-    std::shared_ptr<IntegratedPeak> peak = cit->second;
-
+  allPeaks = m_integrator->allPeaks();
+  for (std::shared_ptr<const IntegratedPeak> peak : allPeaks) {
     if (peak->toIdx() < fromIdx || peak->fromIdx() > toIdx) /* Peak is not in view X-wise, skip it */
       continue;
 
     peaks.push_back(genPeakDrawData(peak));
-    cit++;
   }
 
   return peaks;
@@ -194,12 +195,10 @@ PeakDrawData SignalController::integratePeak(const double fromX, const double fr
   fromVal = relToValue(fromY);
   toVal = relToValue(toY);
 
-  m_integTblModel->prepReset();
   ret = m_integrator->integrate(fromIdx, toIdx, fromVal, toVal, peak);
 
   switch (ret) {
     case Integrator::ReturnCode::SUCCESS:
-      m_integTblModel->doneReset();
       return genPeakDrawData(peak);
       break;
     case Integrator::ReturnCode::E_NO_FIRST_INTERSECT:
@@ -217,7 +216,7 @@ PeakDrawData SignalController::integratePeak(const double fromX, const double fr
 
 /** Private methods **/
 
-PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<IntegratedPeak> peak)
+PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<const IntegratedPeak> peak)
 {
   return PeakDrawData(idxToRel(peak->fromIdx()), valueToRel(peak->fromY()),
                       idxToRel(peak->toIdx()), valueToRel(peak->toY()),
index ee84f090927f2eb02bce08acb92242d15c5ca7bd..f5c17f2798b6f9cd2c6fc6bf31ac22c9da031f0b 100644 (file)
@@ -106,8 +106,8 @@ private:
   size_t relToIdx(const double rel);
   double relToValue(const double rel);
 
-  void drawIntegratedPeak(const std::shared_ptr<IntegratedPeak> peak);
-  PeakDrawData genPeakDrawData(const std::shared_ptr<IntegratedPeak> peak);
+  void drawIntegratedPeak(const std::shared_ptr<const IntegratedPeak> peak);
+  PeakDrawData genPeakDrawData(const std::shared_ptr<const IntegratedPeak> peak);
 
   static const QString ME_SENDER_STR;
 
index 345ad2a5d41222049803c0708c92092f9c209ef5..678aecaf367b105dfc74acc0e444d082ade5b439 100644 (file)
@@ -25,7 +25,7 @@ Constraints SignalDrawer::currentConstraints()
   return Constraints(m_relXMin, m_relYMin, m_relXMax, m_relYMax);
 }
 
-bool SignalDrawer::draw(const double fromX, const double fromY, const double toX, const double toY)
+bool SignalDrawer::draw(const double fromX, const double fromY, const double toX, const double toY, const GraphLayers layers)
 {
   QPixmap* fresh;
   bool ret;
@@ -35,21 +35,33 @@ bool SignalDrawer::draw(const double fromX, const double fromY, const double toX
   fresh = createFreshPixmap();
   if (fresh == nullptr)
     return false;
-  ret = drawGraph(fresh);
-  if (!ret) {
-    Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw graph");
-    restoreRelativeConstraints();
-    delete fresh;
-    return ret;
+
+  /* Draw the signal itself */
+  if (flags(GraphLayers::GRAPH & layers)) {
+    ret = drawGraph(fresh);
+    if (!ret) {
+      Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw graph");
+      restoreRelativeConstraints();
+      delete fresh;
+      return ret;
+    }
+  }
+
+  /* Draw the scale */
+  if (flags(GraphLayers::SCALE & layers)) {
+    ret = renderScale(SignalController::Axis::VALUE, fresh);
+    ret = renderScale(SignalController::Axis::TIME, fresh);
   }
-  ret = renderScale(SignalController::Axis::VALUE, fresh);
-  ret = renderScale(SignalController::Axis::TIME, fresh);
-  ret = drawPeaks(fresh);
-  if (!ret) {
-    Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw integrated peaks");
-    restoreRelativeConstraints();
-    delete fresh;
-    return ret;
+
+  /* Draw integrated peaks */
+  if (flags(GraphLayers::INTEGRATION & layers)) {
+    ret = drawPeaks(fresh);
+    if (!ret) {
+      Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw integrated peaks");
+      restoreRelativeConstraints();
+      delete fresh;
+      return ret;
+    }
   }
   renderFresh(fresh);
 
index 0c89ff3d8a1c4aec4b7d4f577cdd14abf5ef152c..9efcae59dccc189cc77a2032d57e7f45858600ce 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef SIGNALDRAWER_H
 #define SIGNALDRAWER_H
 
+#include "enumflags.h"
 #include "signalcontroller.h"
 #include <QtCore/QLocale>
 #include <QtGui/QFont>
@@ -17,14 +18,22 @@ struct Constraints {
   const double fromX, fromY, toX, toY;
 };
 
+ENUM_FLAGS(GraphLayers)
+enum class GraphLayers {
+  GRAPH = 0x01,
+  INTEGRATION = 0x02,
+  SCALE = 0x04,
+  ALL = INT_MAX
+};
+
 class SignalDrawer
 {
 public:
-  SignalDrawer(std::shared_ptr<SignalController> controller, const Constraints& constraints = Constraints());
+   SignalDrawer(std::shared_ptr<SignalController> controller, const Constraints& constraints = Constraints());
   ~SignalDrawer();
   Constraints currentConstraints();
   int dheight() const { return m_height; }
-  bool draw(const double fromX, const double fromY, const double toX, const double toY);
+  bool draw(const double fromX, const double fromY, const double toX, const double toY, const GraphLayers layers = GraphLayers::ALL);
   bool drawGraph(QPixmap* const target);
   bool drawPeaks(QPixmap* const target);
   QRect erasePeak(const PeakDrawData& pd);