summaryrefslogtreecommitdiff
path: root/seriesmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'seriesmodel.cpp')
-rw-r--r--seriesmodel.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/seriesmodel.cpp b/seriesmodel.cpp
new file mode 100644
index 0000000..628cb60
--- /dev/null
+++ b/seriesmodel.cpp
@@ -0,0 +1,146 @@
+#include "seriesmodel.h"
+
+// cpp
+// tbb
+#ifdef __linux__
+#ifndef Q_MOC_RUN
+#if defined(emit)
+#undef emit
+#include <execution>
+#define emit // restore the macro definition of "emit", as it was defined in
+ // gtmetamacros.h
+#else
+#include <execution>
+#endif // defined(emit)
+#endif // Q_MOC_RUN
+#endif
+
+SeriesModel::SeriesModel(QObject* parent)
+ : QAbstractTableModel(parent)
+{
+}
+
+SeriesModel::SeriesModel(const SeriesModel& other)
+ : QAbstractTableModel()
+{
+ append(other.m_points);
+}
+
+int SeriesModel::rowCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return m_points.count();
+}
+
+int SeriesModel::columnCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return 2;
+}
+
+QVariant SeriesModel::data(const QModelIndex& modelIndex, int role) const
+{
+ if (!modelIndex.isValid())
+ return QVariant();
+
+ if (modelIndex.row() < 0 || modelIndex.row() >= m_points.count())
+ return QVariant();
+
+ if (role == Qt::DisplayRole)
+ {
+ if (modelIndex.column() == 0)
+ return m_points.at(modelIndex.row()).x();
+ else if (modelIndex.column() == 1)
+ return m_points.at(modelIndex.row()).y();
+ }
+
+ return QVariant();
+}
+
+void SeriesModel::append(const QVector<QVector2D> points)
+{
+ QMutexLocker l(&m_mtx);
+ beginInsertRows(
+ QModelIndex(),
+ m_points.count(),
+ m_points.count() + points.count() - 1
+ );
+
+ m_points << points;
+ endInsertRows();
+ recalcLimits();
+}
+
+void SeriesModel::clear()
+{
+ QMutexLocker l(&m_mtx);
+
+ if (m_points.isEmpty())
+ return;
+
+ beginRemoveRows(QModelIndex(), 0, m_points.count() - 1);
+ m_points.clear();
+ endRemoveRows();
+}
+
+void SeriesModel::recalcLimits()
+{
+ // WARNING: not thread safe
+ m_minX = std::numeric_limits<float>::max();
+ m_maxX = std::numeric_limits<float>::min();
+ m_minY = std::numeric_limits<float>::max();
+ m_maxY = std::numeric_limits<float>::min();
+
+#ifdef __linux__
+ const auto [minX, maxX] = std::minmax_element(
+ std::execution::par_unseq,
+ m_points.constBegin(),
+ m_points.constEnd(),
+ [](const auto& a, const auto& b) { return a.x() < b.x(); }
+ );
+
+ const auto [minY, maxY] = std::minmax_element(
+ std::execution::par_unseq,
+ m_points.constBegin(),
+ m_points.constEnd(),
+ [](const auto& a, const auto& b) { return a.y() < b.y(); }
+ );
+
+ float min = std::min(minX->x(), minY->y());
+ float max = std::max(maxX->x(), maxY->y());
+#else
+ for (const auto& p : m_points)
+ {
+ if (p.x() < m_minX)
+ m_minX = p.x();
+
+ if (p.x() > m_maxX)
+ m_maxX = p.x();
+
+ if (p.y() < m_minY)
+ m_minY = p.y();
+
+ if (p.y() > m_maxY)
+ m_maxY = p.y();
+ }
+
+ float min = std::min(m_minX, m_minY);
+ float max = std::max(m_maxX, m_maxY);
+#endif
+
+ m_minX = min;
+ m_maxX = max;
+ m_minY = min;
+ m_maxY = max;
+
+ emit minXChanged();
+ emit maxXChanged();
+ emit minYChanged();
+ emit maxYChanged();
+}
+
+void SeriesModel::replace(const QVector<QVector2D> points)
+{
+ clear();
+ append(points);
+}