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; }