1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 23:03:22 +02:00
GPXSee/src/graph.cpp

289 lines
6.0 KiB
C++
Raw Normal View History

2015-10-05 01:43:48 +02:00
#include <float.h>
#include <QGraphicsView>
2015-10-13 23:49:15 +02:00
#include <QGraphicsSceneMouseEvent>
2015-10-05 01:43:48 +02:00
#include <QEvent>
2015-10-17 01:33:02 +02:00
#include <QGraphicsSimpleTextItem>
2015-10-12 01:12:12 +02:00
#include "slideritem.h"
2015-10-17 01:33:02 +02:00
#include "sliderinfoitem.h"
2015-10-12 01:12:12 +02:00
#include "infoitem.h"
2015-10-17 01:33:02 +02:00
#include "config.h"
2015-10-05 01:43:48 +02:00
#include "graph.h"
#include <QDebug>
2015-10-17 01:33:02 +02:00
2015-10-05 01:43:48 +02:00
#define MARGIN 10.0
2015-10-13 23:49:15 +02:00
void Scene::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
if (e->button() == Qt::LeftButton)
emit mouseClicked(e->scenePos());
QGraphicsScene::mousePressEvent(e);
}
2015-10-05 01:43:48 +02:00
Graph::Graph(QWidget *parent)
: QGraphicsView(parent)
{
2015-10-13 23:49:15 +02:00
_scene = new Scene(this);
2015-10-05 01:43:48 +02:00
setScene(_scene);
_xAxis = new AxisItem(AxisItem::X);
_yAxis = new AxisItem(AxisItem::Y);
_slider = new SliderItem();
2015-10-12 01:12:12 +02:00
_slider->setZValue(2.0);
2015-10-13 23:49:15 +02:00
2015-10-05 01:43:48 +02:00
connect(_slider, SIGNAL(positionChanged(const QPointF&)), this,
SLOT(emitSliderPositionChanged(const QPointF&)));
2015-10-13 23:49:15 +02:00
connect(_scene, SIGNAL(mouseClicked(const QPointF&)), this,
SLOT(newSliderPosition(const QPointF&)));
2015-10-05 01:43:48 +02:00
2015-10-12 01:12:12 +02:00
_info = new InfoItem();
2015-10-17 01:33:02 +02:00
_sliderInfo = new SliderInfoItem(_slider);
_sliderInfo->setZValue(2.0);
2015-10-05 01:43:48 +02:00
_xMax = -FLT_MAX;
_xMin = FLT_MAX;
_yMax = -FLT_MAX;
_yMin = FLT_MAX;
_xScale = 1;
_yScale = 1;
2015-10-17 01:33:02 +02:00
_precision = 0;
2015-10-05 01:43:48 +02:00
}
Graph::~Graph()
{
if (_xAxis->scene() != _scene)
delete _xAxis;
if (_yAxis->scene() != _scene)
delete _yAxis;
if (_slider->scene() != _scene)
delete _slider;
2015-10-12 01:12:12 +02:00
if (_info->scene() != _scene)
delete _info;
2015-10-05 01:43:48 +02:00
delete _scene;
}
void Graph::updateBounds(const QPointF &point)
{
if (point.x() < _xMin)
_xMin = point.x();
if (point.x() > _xMax)
_xMax = point.x();
if (point.y() < _yMin)
_yMin = point.y();
if (point.y() > _yMax)
_yMax = point.y();
}
2015-10-12 01:12:12 +02:00
void Graph::createXLabel()
{
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel).arg(_xUnits));
}
void Graph::createYLabel()
{
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel).arg(_yUnits));
}
void Graph::setXLabel(const QString &label)
{
_xLabel = label;
createXLabel();
}
void Graph::setYLabel(const QString &label)
{
_yLabel = label;
createYLabel();
}
void Graph::setXUnits(const QString &units)
{
_xUnits = units;
createXLabel();
}
void Graph::setYUnits(const QString &units)
{
_yUnits = units;
createYLabel();
}
2015-10-05 01:43:48 +02:00
void Graph::loadData(const QVector<QPointF> &data)
{
QPainterPath path;
QGraphicsPathItem *pi;
QColor color = _colorShop.color();
if (data.size() < 2)
return;
updateBounds(data.at(0));
path.moveTo(data.at(0).x(), -data.at(0).y());
for (int i = 1; i < data.size(); i++) {
path.lineTo(data.at(i).x(), -data.at(i).y());
updateBounds(data.at(i));
}
pi = new QGraphicsPathItem(path);
2015-10-22 09:43:21 +02:00
pi->setPen(QPen(color));
2015-10-05 01:43:48 +02:00
_scene->addItem(pi);
_graphs.append(pi);
2015-10-17 01:33:02 +02:00
if (_graphs.size() > 1)
_sliderInfo->hide();
2015-10-05 01:43:48 +02:00
resize(viewport()->size() - QSizeF(MARGIN, MARGIN));
}
void Graph::resize(const QSizeF &size)
{
QRectF r;
QSizeF mx, my;
QTransform transform;
qreal xs, ys;
if (_xAxis->scene() == _scene)
_scene->removeItem(_xAxis);
if (_yAxis->scene() == _scene)
_scene->removeItem(_yAxis);
if (_slider->scene() == _scene)
_scene->removeItem(_slider);
2015-10-12 01:12:12 +02:00
if (_info->scene() == _scene)
_scene->removeItem(_info);
2015-10-05 01:43:48 +02:00
for (int i = 0; i < _graphs.size(); i++)
_graphs.at(i)->resetTransform();
2015-10-12 01:12:12 +02:00
_xAxis->setRange(QPointF(_xMin * _xScale, _xMax * _xScale));
_yAxis->setRange(QPointF(_yMin * _yScale, _yMax * _yScale));
2015-10-05 01:43:48 +02:00
mx = _xAxis->margin();
my = _yAxis->margin();
r = _scene->itemsBoundingRect();
xs = (size.width() - (my.width() + mx.width())) / r.width();
2015-10-12 01:12:12 +02:00
ys = (size.height() - (mx.height() + my.height())
- _info->boundingRect().height()) / r.height();
2015-10-05 01:43:48 +02:00
transform.scale(xs, ys);
for (int i = 0; i < _graphs.size(); i++)
_graphs.at(i)->setTransform(transform);
r = _scene->itemsBoundingRect();
_xAxis->setSize(r.width());
_yAxis->setSize(r.height());
_xAxis->setPos(r.bottomLeft());
_yAxis->setPos(r.bottomLeft());
_scene->addItem(_xAxis);
_scene->addItem(_yAxis);
_slider->setArea(r);
_slider->setPos(r.bottomLeft());
_scene->addItem(_slider);
2015-10-12 01:12:12 +02:00
r = _scene->itemsBoundingRect();
_info->setPos(r.topLeft() + QPointF(r.width()/2
- _info->boundingRect().width()/2, -_info->boundingRect().height()));
_scene->addItem(_info);
2015-10-05 01:43:48 +02:00
_scene->setSceneRect(_scene->itemsBoundingRect());
}
void Graph::resizeEvent(QResizeEvent *)
{
if (!_graphs.empty())
resize(viewport()->size() - QSizeF(MARGIN, MARGIN));
}
void Graph::plot(QPainter *painter, const QRectF &target)
{
qreal ratio = target.width() / target.height();
QSizeF orig = _scene->sceneRect().size();
QSizeF canvas = QSizeF(orig.height() * ratio, orig.height());
resize(canvas);
_slider->hide();
_info->hide();
2015-10-05 01:43:48 +02:00
_scene->render(painter, target, QRectF(), Qt::KeepAspectRatioByExpanding);
_slider->show();
_info->show();
2015-10-05 01:43:48 +02:00
resize(orig);
}
void Graph::clear()
{
if (_xAxis->scene() == _scene)
_scene->removeItem(_xAxis);
if (_yAxis->scene() == _scene)
_scene->removeItem(_yAxis);
if (_slider->scene() == _scene)
_scene->removeItem(_slider);
2015-10-12 01:12:12 +02:00
if (_info->scene() == _scene)
_scene->removeItem(_info);
2015-10-17 01:33:02 +02:00
_sliderInfo->show();
2015-10-13 00:27:49 +02:00
_info->clear();
2015-10-05 01:43:48 +02:00
_scene->clear();
_graphs.clear();
_colorShop.reset();
_xMax = -FLT_MAX;
_xMin = FLT_MAX;
_yMax = -FLT_MAX;
_yMin = FLT_MAX;
_scene->setSceneRect(0, 0, 0, 0);
}
void Graph::emitSliderPositionChanged(const QPointF &pos)
{
2015-10-17 12:08:30 +02:00
if (_graphs.isEmpty())
return;
2015-10-05 01:43:48 +02:00
qreal val = pos.x() / _slider->area().width();
emit sliderPositionChanged(val);
2015-10-17 01:33:02 +02:00
const QPainterPath &path = _graphs.at(0)->path();
QPointF p = path.pointAtPercent(val);
qreal r = (p.y() - path.boundingRect().bottom())
/ path.boundingRect().height();
_sliderInfo->setPos(QPointF(0, _slider->boundingRect().height() * r));
_sliderInfo->setText(QString::number(-p.y() * _yScale, 'f', _precision));
2015-10-05 01:43:48 +02:00
}
qreal Graph::sliderPosition() const
{
return _slider->pos().x() / _slider->area().width();
}
void Graph::setSliderPosition(qreal pos)
{
_slider->setPos(pos * _slider->area().width(), 0);
}
2015-10-12 01:12:12 +02:00
2015-10-13 23:49:15 +02:00
void Graph::newSliderPosition(const QPointF &pos)
{
if (_slider->area().contains(pos)) {
_slider->setPos(pos);
emitSliderPositionChanged(pos);
}
}
2015-10-12 01:12:12 +02:00
void Graph::addInfo(const QString &key, const QString &value)
{
_info->insert(key, value);
}