gui/aboutanyanka.cpp \
     globalinfo.cpp \
     gui/exportrawdatadialog.cpp \
-    rawdataexporter.cpp \
-    rawdatawriter.cpp \
-    csvrawdatawriter.cpp
+    datafileexporter.cpp \
+    datawriterbackend.cpp \
+    csvdatawriterbackend.cpp
 
 HEADERS  += \
     datafilesloader.h \
     globalinfo.h \
     windows_defines.h \
     gui/exportrawdatadialog.h \
-    rawdataexporter.h \
-    rawdatawriter.h \
-    csvrawdatawriter.h
+    datafileexporter.h \
+    datawriterbackend.h \
+    csvdatawriterbackend.h
 
 FORMS += \
     gui/mainwindow.ui \
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#include "csvdatawriterbackend.h"
+
+CSVDataWriterBackend::CSVDataWriterBackend(QObject* parent) :
+  DataWriterBackend("csv", parent)
+{
+  locale = QLocale::system();
+}
+
+QString CSVDataWriterBackend::header(const QVariantList& data) const
+{
+  QString line;
+
+  for (const QVariant& v : data)
+    line += v.toString() + ";";
+
+  return line + "\n";
+}
+
+QString CSVDataWriterBackend::filename(const QString& name, const QString& extra) const
+{
+  QString newname = name;
+  if (extra.compare("") != 0)
+    return newname + "_" + extra + "." + FILE_EXTENSION;
+  else
+    return newname + "." + FILE_EXTENSION;
+}
+
+QString CSVDataWriterBackend::line(const QVariantList& data) const
+{
+  QString line;
+  for (const QVariant& v : data)
+    line += locale.toString(v.toDouble(), 'g') + ";";
+
+  return line + "\n";
+}
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#ifndef CSVRAWDATAWRITER_H
+#define CSVRAWDATAWRITER_H
+
+#include "datawriterbackend.h"
+#include <QtCore/QLocale>
+
+class CSVDataWriterBackend : public DataWriterBackend
+{
+public:
+  CSVDataWriterBackend(QObject* parent = nullptr);
+  QString header(const QVariantList& data) const;
+  QString filename(const QString& name, const QString& extra) const;
+  QString line(const QVariantList& data) const;
+
+private:
+  QLocale locale;
+};
+
+#endif // CSVRAWDATAWRITER_H
 
+++ /dev/null
-#include "csvrawdatawriter.h"
-
-CSVRawDataWriter::CSVRawDataWriter(QObject* parent) :
-  RawDataWriter("csv", parent)
-{
-  locale = QLocale::system();
-}
-
-QString CSVRawDataWriter::filename(const QString& name, const QString& extra) const
-{
-  QString newname = name;
-  if (extra.compare("") != 0)
-    return newname + "_" + extra + "." + FILE_EXTENSION;
-  else
-    return newname + "." + FILE_EXTENSION;
-}
-
-QString CSVRawDataWriter::line(const double time, const double value) const
-{
-  return locale.toString(time) + ";" + locale.toString(value);
-}
 
+++ /dev/null
-#ifndef CSVRAWDATAWRITER_H
-#define CSVRAWDATAWRITER_H
-
-#include "rawdatawriter.h"
-#include <QtCore/QLocale>
-
-class CSVRawDataWriter : public RawDataWriter
-{
-public:
-  CSVRawDataWriter(QObject* parent = nullptr);
-  QString filename(const QString& name, const QString& extra) const;
-  QString line(const double time, const double value) const;
-
-private:
-  QLocale locale;
-};
-
-#endif // CSVRAWDATAWRITER_H
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#include "datafileexporter.h"
+#include "csvdatawriterbackend.h"
+#include <QtCore/QDir>
+#include <QtCore/QLocale>
+#include <QtWidgets/QMessageBox>
+
+const QStringList DataFileExporter::SUPPORTED_FORMATS = QStringList() << "Comma separated values (CSV)";
+
+DataFileExporter::DataFileExporter(QObject* parent) :
+  QObject(parent)
+{
+}
+
+/* Public methods */
+
+DataFileExporter::ReturnCode DataFileExporter::
+exportData(const WriteList& list, const QString& path, const int formatIdx)
+{
+  QDir dir(path);
+  QFile file(path);
+  QString plainName = file.fileName();
+  OutputFormats format;
+  DataFileExporter::ReturnCode ret;
+  DataWriterBackend* backend;
+
+  if (formatIdx < 0 || formatIdx >= SUPPORTED_FORMATS.length()) {
+    QMessageBox::warning(nullptr, "Data export error", "Invalid format selected");
+    return ReturnCode::E_TRYAGAIN;
+  }
+
+  if (path.compare("") == 0) {
+    QMessageBox::information(nullptr, "Data export error", "No output file specified.");
+    return ReturnCode::E_TRYAGAIN;
+  }
+  if (dir.exists()) {
+    QMessageBox::information(nullptr, "Data export error", "Selected path points to a directory. Name of output file is required.");
+    return ReturnCode::E_TRYAGAIN;
+  }
+
+  if (file.exists()) {
+    int ret = QMessageBox::question(nullptr, "Data export", "The selected file already exists. Do you wish to overwrite it?");
+    if (ret == QMessageBox::No)
+      return ReturnCode::E_TRYAGAIN;
+    else
+      file.remove();
+  }
+
+  format = formatIdxToFormat(formatIdx);
+  switch (format) {
+    case OutputFormats::CSV:
+      backend = new CSVDataWriterBackend(this);
+      break;
+  }
+
+  if (list.size() > 1)
+    file.setFileName(backend->filename(plainName, list.cbegin()->first.c_str()));
+  else
+    file.setFileName(backend->filename(plainName));
+
+  /* Export first signal to file */
+  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+    QMessageBox::critical(nullptr, "Data export error", "Cannot open output file for writing.");
+    delete backend;
+    return ReturnCode::E_FAILED;
+  }
+
+  ret = writeToFile(file, backend, list.cbegin()->second);
+  if (ret != ReturnCode::SUCCESS) {
+    file.close();
+    delete backend;
+    return ret;
+  }
+
+  //for (int idx = 1; idx < header.size(); idx++) {
+  WriteList::const_iterator cit = list.cbegin();
+  std::advance(cit, 1);
+  for (; cit != list.cend(); cit++) {
+    file.setFileName(backend->filename(plainName, cit->first.c_str()));
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+      QMessageBox::critical(nullptr, "Data export error", "Cannot open output file '" + file.fileName() + "' for writing.");
+      return ReturnCode::E_FAILED;
+    }
+    ret = writeToFile(file, backend, cit->second);
+    file.close();
+    if (ret != ReturnCode::SUCCESS)
+      break;
+  }
+
+  delete backend;
+  return ret;
+}
+
+/* Private methods */
+
+DataFileExporter::OutputFormats DataFileExporter::formatIdxToFormat(const int idx)
+{
+  switch (idx) {
+    case 0:
+      return OutputFormats::CSV;
+  }
+}
+
+DataFileExporter::ReturnCode DataFileExporter::writeToFile(QFile& file, const DataWriterBackend* backend, const std::pair<QVariantList, std::vector<QVariantList>>& data)
+{
+  QString line;
+  QByteArray bytes;
+  qint64 w;
+
+  line = backend->header(data.first);
+  bytes = line.toUtf8();
+  w = file.write(bytes);
+  if (w < bytes.size())
+    return ReturnCode::E_FAILED;
+
+  for (const QVariantList& l : data.second) {
+    line = backend->line(l);
+    bytes = line.toUtf8();
+    w = file.write(bytes);
+    if (w < bytes.size())
+      return ReturnCode::E_FAILED;
+  }
+
+  return ReturnCode::SUCCESS;
+}
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#ifndef RAWDATAEXPORTER_H
+#define RAWDATAEXPORTER_H
+
+#include "datawriterbackend.h"
+#include "signal.h"
+#include <unordered_map>
+#include <memory>
+#include <QtCore/QFile>
+#include <QtCore/QObject>
+
+class DataFileExporter : public QObject
+{
+  Q_OBJECT
+public:
+  enum class ReturnCode {
+    SUCCESS,
+    E_TRYAGAIN,
+    E_FAILED
+  };
+  typedef std::unordered_map<std::string, std::pair<QVariantList, std::vector<QVariantList>>> WriteList;
+
+  explicit DataFileExporter(QObject* parent = nullptr);
+  ReturnCode exportData(const WriteList& header, const QString& path, const int formatIdx);
+
+  static const QStringList SUPPORTED_FORMATS;
+private:
+  enum class OutputFormats {
+    CSV
+  };
+
+  OutputFormats formatIdxToFormat(const int idx);
+  QString toCSVLine(double time, double value);
+  ReturnCode writeToFile(QFile& file, const DataWriterBackend* writer, const std::pair<QVariantList, std::vector<QVariantList>>& data);
+
+signals:
+
+public slots:
+
+};
+
+#endif // RAWDATAEXPORTER_H
 
 
 #include "datamanager.h"
 #include "logger.h"
-#include "rawdataexporter.h"
+#include "datafileexporter.h"
 #include "gui/exportrawdatadialog.h"
 #include <QtWidgets/QMessageBox>
 
 
 /* Public slots */
 
+void DataManager::onExportPeaks()
+{
+  std::vector<std::shared_ptr<const SignalController>> ctrls;
+
+  if (m_activeSequence == nullptr)
+    return;
+  if (m_activeSequence->selectedRun() == nullptr)
+    return;
+}
+
 void DataManager::onExportRawData()
 {
-  RawDataExporter exporter(this);
-  ExportRawDataDialog dlg(RawDataExporter::SUPPORTED_FORMATS);
-  std::vector<std::shared_ptr<Signal>> sigs;
+  DataFileExporter exporter(this);
+  ExportRawDataDialog dlg(DataFileExporter::SUPPORTED_FORMATS);
+  DataFileExporter::WriteList writeList;
+  DataFileExporter::ReturnCode ret;
 
   if (m_activeSequence == nullptr)
     return;
   if (m_activeSequence->selectedRun() == nullptr)
     return;
 
-  for (int idx = 0; idx < m_activeSequence->selectedRun()->signalCount(); idx++)
+  for (uint idx = 0; idx < m_activeSequence->selectedRun()->signalCount(); idx++)
     dlg.addAvailableSignal(m_activeSequence->selectedRun()->signalAt(idx)->descriptiveName());
 
-  RawDataExporter::ReturnCode ret;
   do {
     int dret = dlg.exec();
     if (dret == QDialog::Rejected)
       return;
     else if (dret == QDialog::Accepted && dlg.selectedSignalsCount() < 1) {
       QMessageBox::information(nullptr, "Data export error", "No signals selected");
-      ret = RawDataExporter::ReturnCode::E_TRYAGAIN;
+      ret = DataFileExporter::ReturnCode::E_TRYAGAIN;
     } else if (dret == QDialog::Accepted && dlg.selectedSignalsCount() >= 1) {
-      sigs.clear();
+      /* Generate data to export */
       for (int idx = 0; idx < dlg.signalsCount(); idx++) {
-        if (dlg.isSignalSelected(idx))
-          sigs.push_back(m_activeSequence->selectedRun()->signalAt(idx));
+        QVariantList header;
+        std::vector<QVariantList> lines;
+        std::pair<QVariantList, std::vector<QVariantList>> p;
+        std::shared_ptr<const Signal> sig;
+        std::string dname;
+        if (!dlg.isSignalSelected(idx))
+          continue;
+
+        sig = m_activeSequence->selectedRun()->signalAt(idx);
+        dname = m_activeSequence->selectedRun()->signalAt(idx)->descriptiveName().toStdString();
+
+        /* Create header */
+        header << QString("time [" + sig->xunitToString() + "]") << QString("value [" + sig->yunitToString() + "]");
+        for (const Signal::TimeValuePair& tvp : sig->values()) {
+          QVariantList line;
+          line << tvp.first << tvp.second;
+          lines.push_back(line);
+        }
+        p = std::pair<QVariantList, std::vector<QVariantList>>(header, lines);
+        writeList[dname] = p;
       }
-      ret = exporter.exportData(sigs, dlg.destination(), dlg.format());
+      ret = exporter.exportData(writeList, dlg.destination(), dlg.format());
     }
-   } while (ret == RawDataExporter::ReturnCode::E_TRYAGAIN);
+   } while (ret == DataFileExporter::ReturnCode::E_TRYAGAIN);
 }
 
 void DataManager::onLoadSequence(const QString& dir)
 
   void setSingleRunInfo(const QString& method, const QString& operatorname, const QString& sample, const QString& datetime);
 
 public slots:
+  void onExportPeaks();
   void onExportRawData();
   void onLoadSequence(const QString& dir);
   void onLoadSingleRun(const QString& dir);
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#include "datawriterbackend.h"
+
+DataWriterBackend::DataWriterBackend(const QString& extension, QObject* parent) :
+  QObject(parent),
+  FILE_EXTENSION(extension)
+{
+}
 
--- /dev/null
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
+#ifndef DATAFILEWRITER_H
+#define DATAFILEWRITER_H
+
+#include <QtCore/QObject>
+
+class DataWriterBackend : public QObject
+{
+  Q_OBJECT
+public:
+  explicit DataWriterBackend(const QString& extension, QObject* parent = nullptr);
+  virtual QString header(const QVariantList& data) const = 0;
+  virtual QString filename(const QString& name, const QString& extra = QString()) const = 0;
+  virtual QString line(const QVariantList& data) const = 0;
+
+  const QString FILE_EXTENSION;
+
+signals:
+
+public slots:
+
+};
+
+#endif // DATAFILEWRITER_H
 
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
 #include "exportrawdatadialog.h"
 #include "ui_exportrawdatadialog.h"
 #include <QtWidgets/QFileDialog>
 
+/*
+  Copyright (c) 2013 Michal Malý <madcatxster@prifuk.cz>
+
+  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.
+*/
+
 #ifndef EXPORTRAWDATADIALOG_H
 #define EXPORTRAWDATADIALOG_H
 
 
   connect(ui->actionLoad_sequence, SIGNAL(triggered()), this, SLOT(onLoadSequence()));
   /* EXPORT menu */
   connect(ui->actionRaw_values, SIGNAL(triggered()), this, SLOT(onExportRawData()));
+  connect(ui->actionIntegration_results, SIGNAL(triggered()), this, SLOT(onExportPeaks()));
   /* HELP menu */
   connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAnyanka()));
   /* RUN/SEQ cboxes*/
 
 
 private slots:
   void onAboutAnyanka();
+  void onExportPeaks() { emit exportPeaks(); }
   void onExportRawData() { emit exportRawData(); }
   void onIntegrateSelected();
   void onLoadSequence();
 
 signals:
   void controlModeChanged(GraphControlModes mode);
+  void exportPeaks();
   void exportRawData();
   void loadSequence(const QString& dir);
   void loadSingleRun(const QString& dir);
 
   QObject::connect(dMgr.get(), SIGNAL(setActiveSequenceIndex(int)), mWin.get(), SLOT(onSetActiveSequenceIndex(int)));
   QObject::connect(dMgr.get(), SIGNAL(setActiveSingleRunIndex(int)), mWin.get(), SLOT(onSetActiveSingleRunIndex(int)));
   QObject::connect(dMgr.get(), SIGNAL(setSingleRunInfo(QString,QString,QString,QString)), mWin.get(), SLOT(onSetSingleRunInfo(QString,QString,QString,QString)));
+  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)));
   QObject::connect(mWin.get(), SIGNAL(loadSequence(QString)), dMgr.get(), SLOT(onLoadSequence(QString)));
 
 
 template <typename T> T average(T* vals, size_t len) {
   T sum = 0;
-  for (int i = 0; i < len; i++)
+  for (size_t i = 0; i < len; i++)
     sum += vals[i];
   return sum / len;
 }
 
+++ /dev/null
-#include "rawdataexporter.h"
-#include "csvrawdatawriter.h"
-#include <QtCore/QDir>
-#include <QtCore/QLocale>
-#include <QtWidgets/QMessageBox>
-
-const QStringList RawDataExporter::SUPPORTED_FORMATS = QStringList() << "Comma separated values (CSV)";
-
-RawDataExporter::RawDataExporter(QObject* parent) :
-  QObject(parent)
-{
-}
-
-/* Public methods */
-
-RawDataExporter::ReturnCode RawDataExporter::exportData(const std::vector<std::shared_ptr<Signal>> sigs, const QString& path, const int formatIdx)
-{
-  QDir dir(path);
-  QFile file(path);
-  QString plainName = file.fileName();
-  OutputFormats format;
-  RawDataExporter::ReturnCode ret;
-  RawDataWriter* writer;
-
-  if (formatIdx < 0 || formatIdx >= SUPPORTED_FORMATS.length()) {
-    QMessageBox::warning(nullptr, "Data export error", "Invalid format selected");
-    return ReturnCode::E_TRYAGAIN;
-  }
-
-  if (path.compare("") == 0) {
-    QMessageBox::information(nullptr, "Data export error", "No output file specified.");
-    return ReturnCode::E_TRYAGAIN;
-  }
-  if (dir.exists()) {
-    QMessageBox::information(nullptr, "Data export error", "Selected path points to a directory. Name of output file is required.");
-    return ReturnCode::E_TRYAGAIN;
-  }
-
-  if (file.exists()) {
-    int ret = QMessageBox::question(nullptr, "Data export", "The selected file already exists. Do you wish to overwrite it?");
-    if (ret == QMessageBox::No)
-      return ReturnCode::E_TRYAGAIN;
-    else
-      file.remove();
-  }
-
-  format = formatIdxToFormat(formatIdx);
-  switch (format) {
-    case OutputFormats::CSV:
-      writer = new CSVRawDataWriter(this);
-      break;
-  }
-
-  if (sigs.size() > 1)
-    file.setFileName(writer->filename(plainName, sigs.at(0)->descriptiveName()));
-  else
-    file.setFileName(writer->filename(plainName));
-
-  /* Export first signal to file */
-  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-    QMessageBox::critical(nullptr, "Data export error", "Cannot open output file for writing.");
-    delete writer;
-    return ReturnCode::E_FAILED;
-  }
-
-  ret = writeToFile(file, writer, sigs.at(0));
-  if (ret != ReturnCode::SUCCESS) {
-    file.close();
-    delete writer;
-    return ret;
-  }
-
-  for (int idx = 1; idx < sigs.size(); idx++) {
-    file.setFileName(writer->filename(plainName, sigs.at(idx)->descriptiveName()));
-    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-      QMessageBox::critical(nullptr, "Data export error", "Cannot open output file '" + file.fileName() + "' for writing.");
-      return ReturnCode::E_FAILED;
-    }
-    ret = writeToFile(file, writer, sigs.at(idx));
-    file.close();
-    if (ret != ReturnCode::SUCCESS)
-      break;
-  }
-
-  delete writer;
-  return ret;
-}
-
-/* Private methods */
-
-RawDataExporter::OutputFormats RawDataExporter::formatIdxToFormat(const int idx)
-{
-  switch (idx) {
-    case 0:
-      return OutputFormats::CSV;
-  }
-}
-
-RawDataExporter::ReturnCode RawDataExporter::writeToFile(QFile& file, const RawDataWriter* writer, const std::shared_ptr<Signal> signal)
-{
-  QString line;
-  QByteArray bytes;
-  qint64 w;
-
-  bytes = QString("time;value\n").toUtf8();
-  w = file.write(bytes);
-  if (w < bytes.size())
-    return ReturnCode::E_FAILED;
-
-  for (int idx = 0; idx < signal->valuesCount(); idx++) {
-    line = writer->line(signal->timeAt(idx), signal->valueAt(idx));
-    bytes = line.toUtf8();
-    w = file.write(bytes);
-    if (w < bytes.size())
-      return ReturnCode::E_FAILED;
-  }
-
-  return ReturnCode::SUCCESS;
-}
 
+++ /dev/null
-#ifndef RAWDATAEXPORTER_H
-#define RAWDATAEXPORTER_H
-
-#include "rawdatawriter.h"
-#include "signal.h"
-#include <memory>
-#include <QtCore/QFile>
-#include <QtCore/QObject>
-
-class RawDataExporter : public QObject
-{
-  Q_OBJECT
-public:
-  enum class ReturnCode {
-    SUCCESS,
-    E_TRYAGAIN,
-    E_FAILED
-  };
-
-  explicit RawDataExporter(QObject* parent = nullptr);
-  ReturnCode exportData(std::vector<std::shared_ptr<Signal>> sigs, const QString& path, const int formatIdx);
-
-  static const QStringList SUPPORTED_FORMATS;
-private:
-  enum class OutputFormats {
-    CSV
-  };
-
-  OutputFormats formatIdxToFormat(const int idx);
-  QString toCSVLine(double time, double value);
-  ReturnCode writeToFile(QFile& file, const RawDataWriter* writer, const std::shared_ptr<Signal> signal);
-
-signals:
-
-public slots:
-
-};
-
-#endif // RAWDATAEXPORTER_H
 
+++ /dev/null
-#include "rawdatawriter.h"
-
-RawDataWriter::RawDataWriter(const QString& extension, QObject* parent) :
-  QObject(parent),
-  FILE_EXTENSION(extension)
-{
-}
 
+++ /dev/null
-#ifndef RAWDATAWRITER_H
-#define RAWDATAWRITER_H
-
-#include <QtCore/QObject>
-
-class RawDataWriter : public QObject
-{
-  Q_OBJECT
-public:
-  explicit RawDataWriter(const QString& extension, QObject* parent = nullptr);
-  virtual QString filename(const QString& name, const QString& extra = QString()) const = 0;
-  virtual QString line(const double time, const double value) const = 0;
-
-  const QString FILE_EXTENSION;
-
-signals:
-
-public slots:
-
-};
-
-#endif // RAWDATAWRITER_H
 
   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(); }
   size_t valuesCount() const { return m_values.size(); }
   std::vector<TimeValuePair>::const_iterator valuesEnd() const { return m_values.end(); }