datafileexporter.cpp \
     datawriterbackend.cpp \
     csvdatawriterbackend.cpp \
-    graphdrawer.cpp
+    graphdrawer.cpp \
+    gui/exportgraphtoimagedialog.cpp
 
 HEADERS  += \
     datafilesloader.h \
     datafileexporter.h \
     datawriterbackend.h \
     csvdatawriterbackend.h \
-    graphdrawer.h
+    graphdrawer.h \
+    gui/exportgraphtoimagedialog.h
 
 FORMS += \
     gui/mainwindow.ui \
     gui/signalview.ui \
     gui/aboutanyanka.ui \
-    gui/exportrawdatadialog.ui
+    gui/exportrawdatadialog.ui \
+    gui/exportgraphtoimagedialog.ui
 
 RESOURCES += \
     imgresources.qrc
 
 
 #include "datamanager.h"
 #include "logger.h"
+#include "gui/exportgraphtoimagedialog.h"
 #include "gui/exportrawdatadialog.h"
+#include <QtGui/QImageWriter>
 #include <QtWidgets/QMessageBox>
 
 #include <QDebug>
 
 /* Public slots */
 
+void DataManager::onExportGraphToImage()
+{
+  QImageWriter imageWriter;
+  ExportGraphToImageDialog dlg(imageWriter.supportedImageFormats());
+  std::shared_ptr<SingleRunData> sr;
+
+  if (m_activeSequence == nullptr)
+    return;
+  sr = m_activeSequence->selectedRun();
+  if (sr == nullptr)
+    return;
+
+  for (const std::pair<std::string, std::shared_ptr<SignalController>>& p : sr->allControllers())
+    dlg.addSignal(p.second->currentStartX(), p.second->currentStartY(), p.second->currentStopX(), p.second->currentStopY(), p.first);
+
+  if (dlg.exec() == QDialog::Accepted) {
+    GraphDrawer drawer;
+    double* data;
+    size_t fromIdx, toIdx;
+    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;
+
+    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;
+
+    /* Get from an to indices */
+    const std::vector<Signal::TimeValuePair>& tvpairs = sig->values();
+    uint idx;
+    for (idx = 0; idx < tvpairs.size(); idx++) {
+      if (tvpairs.at(idx).first >= fromX) {
+        fromIdx = idx;
+        break;
+      }
+    }
+    if (idx == tvpairs.size()) {
+      QMessageBox::warning(nullptr, "Error while exporting to image", "Value \"From X\" is higher than the range of the dataset.");
+      return;
+    }
+    for (;idx < tvpairs.size(); idx++) {
+      if (tvpairs.at(idx).first >= toX) {
+        toIdx = idx;
+        break;
+      }
+    }
+    if (idx == tvpairs.size())
+      toIdx = idx - 1;
+
+    qDebug() << "fromIdx" << fromIdx << "toIdx" << toIdx << "size" << tvpairs.size();
+    data = ctrl->generateDrawData(fromIdx, toIdx);
+    if (data == nullptr) {
+      QMessageBox::warning(nullptr, "Error while exporting to image", "Cannot generate data to draw. Some values are probably invalid.");
+      return;
+    }
+
+    QPixmap* pixmap = drawer.drawGraph(data, toIdx - fromIdx, iw, ih, fromY, toY);
+    QImage result = pixmap->toImage();
+    imageWriter.setFileName(dlg.path() + "." + dlg.imageFormat());
+    imageWriter.setFormat(dlg.imageFormat().toLatin1());
+    if (!imageWriter.write(result))
+      QMessageBox::critical(nullptr, "Error while exporting to image", "Image could not have been written.");
+
+    delete pixmap;
+    delete data;
+  }
+}
+
 void DataManager::onExportPeaks()
 {
   if (m_activeSequence == nullptr)
 
   void setSingleRunInfo(const QString& method, const QString& operatorname, const QString& sample, const QString& datetime);
 
 public slots:
+  void onExportGraphToImage();
   void onExportPeaks();
   void onExportRawData();
   void onLoadSequence(const QString& dir);
 
     int toY = h - yStep * (data[i] - min);
     p.drawLine(fromX, fromY, toX, toY);
 
-    qDebug() << "fromX" << fromX << "fromY" << fromY << "toX" << toX << "toY" << toY;
     fromX = toX;
     fromY = toY;
   }
 
--- /dev/null
+#include "exportgraphtoimagedialog.h"
+#include "ui_exportgraphtoimagedialog.h"
+#include <QtCore/QLocale>
+#include <QtWidgets/QFileDialog>
+
+/* Public functions */
+
+ExportGraphToImageDialog::ExportGraphToImageDialog(QList<QByteArray> formats, QWidget *parent) :
+  QDialog(parent),
+  m_curKey(""),
+  ui(new Ui::ExportGraphToImageDialog)
+{
+  ui->setupUi(this);
+
+  for (const QByteArray ba : formats)
+    ui->qcbox_outputFormat->addItem(QString::fromLatin1(ba));
+
+  connect(ui->qpb_browse, SIGNAL(clicked()), this, SLOT(onBrowseClicked()));
+  connect(ui->qpb_cancel, SIGNAL(clicked()), this, SLOT(reject()));
+  connect(ui->qpb_ok, SIGNAL(clicked()), this, SLOT(checkAndAccept()));
+  connect(ui->qcbox_signal, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeBounds(QString)));
+}
+
+void ExportGraphToImageDialog::addSignal(const double fromX, const double fromY, const double toX, const double toY, const std::string& key)
+{
+  m_signalKeys.push_back(key);
+  m_bounds[key] = Bounds(fromX, fromY, toX, toY);
+
+  ui->qcbox_signal->addItem(QString::fromStdString(key));
+}
+
+double ExportGraphToImageDialog::fromX() const
+{
+  try {
+    return std::get<0>(m_bounds.at(m_curKey));
+  } catch (std::out_of_range&) {
+    return 0;
+  }
+}
+
+double ExportGraphToImageDialog::fromY() const
+{
+  try {
+    return std::get<1>(m_bounds.at(m_curKey));
+  } catch (std::out_of_range&) {
+    return 0;
+  }
+}
+
+QString ExportGraphToImageDialog::imageFormat() const
+{
+  return ui->qcbox_outputFormat->currentText();
+}
+
+int ExportGraphToImageDialog::imageHeight() const
+{
+  bool ok;
+  double h = ui->qle_height->text().toInt(&ok);
+  if (!ok) return 0;
+  return h;
+}
+
+QString ExportGraphToImageDialog::path() const
+{
+  return ui->qle_destPath->text();
+}
+
+QString ExportGraphToImageDialog::selectedSignal() const
+{
+  return ui->qcbox_signal->currentText();
+}
+
+double ExportGraphToImageDialog::toX() const
+{
+  try {
+    return std::get<2>(m_bounds.at(m_curKey));
+  } catch (std::out_of_range&) {
+    return 0;
+  }
+}
+
+double ExportGraphToImageDialog::toY() const
+{
+  try {
+    return std::get<3>(m_bounds.at(m_curKey));
+  } catch (std::out_of_range&) {
+    return 0;
+  }
+}
+
+int ExportGraphToImageDialog::imageWidth() const
+{
+  bool ok;
+  double w = ui->qle_width->text().toInt(&ok);
+
+  if (!ok) return 0;
+  return w;
+}
+
+/* Private slots */
+
+void ExportGraphToImageDialog::changeBounds(const QString& key)
+{
+  QLocale l = QLocale::system();
+  Bounds oldBounds, newBounds;
+  std::string skey = key.toStdString();
+  double fX, fY, tX, tY;
+  bool ok;
+
+  try {
+    oldBounds = m_bounds.at(m_curKey);
+
+    fX = ui->qle_fromX->text().toDouble(&ok);
+    if (ok) std::get<0>(oldBounds) = fX;
+    fY = ui->qle_fromY->text().toDouble(&ok);
+    if (ok) std::get<1>(oldBounds) = fY;
+    tX = ui->qle_toX->text().toDouble(&ok);
+    if (ok) std::get<2>(oldBounds) = tX;
+    tY = ui->qle_toY->text().toDouble(&ok);
+    if (ok) std::get<3>(oldBounds) = tY;
+
+    m_bounds[m_curKey] = oldBounds;
+  } catch (std::out_of_range&) {
+  }
+
+  try {
+    newBounds = m_bounds.at(skey);
+
+    ui->qle_fromX->setText(l.toString(std::get<0>(newBounds)));
+    ui->qle_fromY->setText(l.toString(std::get<1>(newBounds)));
+    ui->qle_toX->setText(l.toString(std::get<2>(newBounds)));
+    ui->qle_toY->setText(l.toString(std::get<3>(newBounds)));
+    m_curKey = skey;
+  } catch (std::out_of_range&) {
+  }
+}
+
+void ExportGraphToImageDialog::checkAndAccept()
+{
+  try {
+    double fX, fY, tX, tY;
+    bool ok;
+    const std::string key = ui->qcbox_signal->currentText().toStdString();
+    Bounds b = m_bounds.at(key);
+
+    fX = ui->qle_fromX->text().toDouble(&ok);
+    if (ok) std::get<0>(b) = fX;
+    fY = ui->qle_fromY->text().toDouble(&ok);
+    if (ok) std::get<1>(b) = fY;
+    tX = ui->qle_toX->text().toDouble(&ok);
+    if (ok) std::get<2>(b) = tX;
+    tY = ui->qle_toY->text().toDouble(&ok);
+    if (ok) std::get<3>(b) = tY;
+
+    m_bounds[key] = b;
+  } catch (std::out_of_range&) {
+  }
+
+  accept();
+}
+
+void ExportGraphToImageDialog::onBrowseClicked()
+{
+  QFileDialog fdlg(this, "Pick destination", QString());
+  if (fdlg.exec() == QDialog::Accepted)
+    ui->qle_destPath->setText(fdlg.selectedFiles()[0]);
+}
+
+ExportGraphToImageDialog::~ExportGraphToImageDialog()
+{
+  delete ui;
+}
 
--- /dev/null
+#ifndef EXPORTGRAPHTOIMAGEDIALOG_H
+#define EXPORTGRAPHTOIMAGEDIALOG_H
+
+#include <unordered_map>
+#include <QtWidgets/QDialog>
+
+namespace Ui {
+  class ExportGraphToImageDialog;
+}
+
+class ExportGraphToImageDialog : public QDialog
+{
+  Q_OBJECT
+
+  typedef std::tuple<double, double, double, double> Bounds;
+
+public:
+  explicit ExportGraphToImageDialog(QList<QByteArray> formats, QWidget* parent = nullptr);
+  ~ExportGraphToImageDialog();
+  void addSignal(const double fromX, const double fromY, const double toX, const double toY, const std::string& key);
+  double fromX() const;
+  double fromY() const;
+  QString imageFormat() const;
+  int imageHeight() const;
+  QString path() const;
+  QString selectedSignal() const;
+  double toX() const;
+  double toY() const;
+  int imageWidth() const;
+
+private:
+  std::unordered_map<std::string, Bounds> m_bounds;
+  std::string m_curKey;
+  std::vector<std::string> m_signalKeys;
+
+  Ui::ExportGraphToImageDialog *ui;
+
+private slots:
+  void checkAndAccept();
+  void changeBounds(const QString& key);
+  void onBrowseClicked();
+
+};
+
+#endif // EXPORTGRAPHTOIMAGEDIALOG_H
 
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExportGraphToImageDialog</class>
+ <widget class="QDialog" name="ExportGraphToImageDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Export graph to image</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="topMargin">
+    <number>3</number>
+   </property>
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="1" column="1">
+      <widget class="QComboBox" name="qcbox_signal">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="0">
+      <widget class="QLabel" name="ql_destination">
+       <property name="text">
+        <string>Destination:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="ql_signal">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Signal:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="qle_destPath"/>
+     </item>
+     <item row="0" column="2">
+      <widget class="QPushButton" name="qpb_browse">
+       <property name="text">
+        <string>Browse</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="ql_outputFormat">
+       <property name="text">
+        <string>Output format:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QComboBox" name="qcbox_outputFormat"/>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout_3">
+     <item row="0" column="0">
+      <widget class="QLabel" name="ql_width">
+       <property name="text">
+        <string>Width:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="qle_width">
+       <property name="text">
+        <string>1000</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="2">
+      <widget class="QLabel" name="ql_height">
+       <property name="text">
+        <string>Height:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="3">
+      <widget class="QLineEdit" name="qle_height">
+       <property name="text">
+        <string>1000</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout_2">
+     <item row="0" column="3">
+      <widget class="QLineEdit" name="qle_toX">
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="0">
+      <widget class="QLabel" name="ql_fromX">
+       <property name="text">
+        <string>From X:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="2">
+      <widget class="QLabel" name="ql_toX">
+       <property name="text">
+        <string>To X:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLineEdit" name="qle_fromX">
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="ql_fromY">
+       <property name="text">
+        <string>From Y:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QLineEdit" name="qle_fromY">
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="2">
+      <widget class="QLabel" name="ql_toY">
+       <property name="text">
+        <string>To Y:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="3">
+      <widget class="QLineEdit" name="qle_toY">
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <property name="sizeConstraint">
+      <enum>QLayout::SetMinimumSize</enum>
+     </property>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>1</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="qpb_ok">
+       <property name="text">
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="qpb_cancel">
+       <property name="text">
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
 
   /* EXPORT menu */
   connect(ui->actionRaw_values, SIGNAL(triggered()), this, SLOT(onExportRawData()));
   connect(ui->actionIntegration_results, SIGNAL(triggered()), this, SLOT(onExportPeaks()));
+  connect(ui->actionGraph_as_image, SIGNAL(triggered()), this, SLOT(onExportGraphToImage()));
   /* HELP menu */
   connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAnyanka()));
   /* RUN/SEQ cboxes*/
 
 
 private slots:
   void onAboutAnyanka();
+  void onExportGraphToImage() { emit exportGraphToImage(); }
   void onExportPeaks() { emit exportPeaks(); }
   void onExportRawData() { emit exportRawData(); }
   void onIntegrateSelected();
 
 signals:
   void controlModeChanged(GraphControlModes mode);
+  void exportGraphToImage();
   void exportPeaks();
   void exportRawData();
   void loadSequence(const QString& dir);
 
   QObject::connect(dMgr.get(), SIGNAL(setActiveSequenceIndex(int)), mWin.get(), SLOT(onSetActiveSequenceIndex(int)));
   QObject::connect(dMgr.get(), SIGNAL(setActiveSingleRunKey(std::string)), mWin.get(), SLOT(onSetActiveSingleRunKey(std::string)));
   QObject::connect(dMgr.get(), SIGNAL(setSingleRunInfo(QString,QString,QString,QString)), mWin.get(), SLOT(onSetSingleRunInfo(QString,QString,QString,QString)));
+  QObject::connect(mWin.get(), SIGNAL(exportGraphToImage()),dMgr.get(), SLOT(onExportGraphToImage()));
   QObject::connect(mWin.get(), SIGNAL(exportPeaks()), dMgr.get(), SLOT(onExportPeaks()));
   QObject::connect(mWin.get(), SIGNAL(exportRawData()), dMgr.get(), SLOT(onExportRawData()));
   QObject::connect(mWin.get(), SIGNAL(loadSingleRun(QString)), dMgr.get(), SLOT(onLoadSingleRun(QString)));
 
   std::string resourceToString() const;
   double timeAt(const size_t idx) const;
   double samplingRate() const { return m_samplingRate; }
-  //QString uidString() const;
   double valueAt(const size_t idx) const;
   const std::vector<TimeValuePair>& values() const { return m_values; }
   std::vector<TimeValuePair>::const_iterator valuesBegin() const { return m_values.begin(); }
 
   connect(m_ctxMenu.m_acDeletePeak, SIGNAL(triggered()), this, SLOT(onCtxMenuDeletePeak()));
 }
 
+double SignalController::currentStartX() const
+{
+  return m_signal->pairAt(m_fromIdx).first;
+}
+
+double SignalController::currentStartY() const
+{
+  return m_yMin;
+}
+
+double SignalController::currentStopX() const
+{
+  return m_signal->pairAt(m_toIdx).first;
+}
+
+double SignalController::currentStopY() const
+{
+  return m_yMax;
+}
+
 /* Public methods */
 void SignalController::draw()
 {
 
 void SignalController::drawGraph()
 {
-  double* arr;
-  size_t len;
-
-  if (m_fromIdx > m_toIdx) {
-    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "From index lower than to index");
-    return;
-  }
-  if (m_fromIdx == m_toIdx)
-    return; //Nothing to zoom to
-  if (m_toIdx >= m_signal->valuesCount() || m_fromIdx >= m_signal->valuesCount()) {
-    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "Invalid value index");
-    return;
-  }
-  len = m_toIdx - m_fromIdx;
-
-  arr = new double[len];
-  for (uint idx = 0; idx < len; idx++)
-    arr[idx] = m_signal->valueAt(idx + m_fromIdx);
-
-  emit viewDrawGraph(arr, len, m_yMin, m_yMax);
+  size_t len = m_toIdx - m_fromIdx;
+  double* arr = generateDrawData(m_fromIdx, m_toIdx);
+  if (arr != nullptr)
+    emit viewDrawGraph(arr, len, m_yMin, m_yMax);
 }
 
 void SignalController::drawIntegratedPeak(const std::shared_ptr<IntegratedPeak> peak)
   emit viewDrawIntegration(fromX, fromY, toX, toY, peak->peakIdx() - m_fromIdx, m_signal->valueAt(peak->peakIdx()), peakTime, peakArea, valley);
 }
 
+double* SignalController::generateDrawData(size_t from, size_t to)
+{
+  double* arr;
+  size_t len;
+
+  if (from > to) {
+    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "From index lower than to index");
+    return nullptr;
+  }
+  if (from == to)
+    return nullptr;
+  if (to >= m_signal->valuesCount() || from >= m_signal->valuesCount()) {
+    Logger::log(Logger::Level::CRITICAL, ME_SENDER_STR, "Invalid value index");
+    return nullptr;
+  }
+  len = to - from;
+
+  arr = new double[len];
+  for (uint idx = 0; idx < len; idx++)
+    arr[idx] = m_signal->valueAt(idx + from);
+
+  return arr;
+}
+
 bool SignalController::updateConstraints(const int fromX, const int fromY, const int toX, const int toY)
 {
   size_t xRange = m_toIdx - m_fromIdx;
 
 public:
   explicit SignalController(std::shared_ptr<Signal> signal, QObject* parent = nullptr);
   ~SignalController();
+  double currentYMax() const { return m_yMax; }
+  double currentYMin() const { return m_yMin; }
+  double currentStartX() const;
+  double currentStartY() const;
+  double currentStopX() const;
+  double currentStopY() const;
   void draw();
   SignalDataTableModel* dataTableModel() { return m_dtblModel; }
+  double* generateDrawData(size_t from, size_t to);
   IntegrationTableModel* integrationTableModel() { return m_integTblModel;}
   const std::shared_ptr<Signal> signal() const { return m_signal; }
   const std::shared_ptr<Integrator> cIntegrator() const { return m_integrator; }
 
   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,
                          const QString& dirname, QObject* parent = nullptr);
+  const std::unordered_map<std::string, std::shared_ptr<SignalController>>& 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; }
   std::shared_ptr<SignalController> controllerAt(const std::string& key);
   QDate date() const { return m_date; }
   QString dirName() const { return m_dirName; }
   QString operatorName() const { return m_operatorName; }
   QString sampleInfo() const { return m_sampleInfo; }
   std::shared_ptr<Signal> signalAt(const std::string& key);
-  const std::unordered_map<std::string, std::shared_ptr<Signal>>& allSignals() const { return m_signals; }
   size_t signalCount() const { return m_signals.size(); }
   QTime time() const { return m_time; }