1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Yet another graph zoom improvement

(and yet not ideal...)
This commit is contained in:
Martin Tůma 2020-11-22 14:38:52 +01:00
parent 781bc8c38f
commit dc209bd96e
9 changed files with 137 additions and 54 deletions

View File

@ -19,6 +19,7 @@ equals(QT_MAJOR_VERSION, 5) : lessThan(QT_MINOR_VERSION, 4) {QT += opengl}
INCLUDEPATH += ./src INCLUDEPATH += ./src
HEADERS += src/common/config.h \ HEADERS += src/common/config.h \
src/GUI/axislabelitem.h \
src/GUI/graphicsscene.h \ src/GUI/graphicsscene.h \
src/GUI/mapaction.h \ src/GUI/mapaction.h \
src/GUI/marginswidget.h \ src/GUI/marginswidget.h \
@ -204,6 +205,7 @@ HEADERS += src/common/config.h \
src/GUI/pdfexportdialog.h \ src/GUI/pdfexportdialog.h \
src/GUI/pngexportdialog.h src/GUI/pngexportdialog.h
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/GUI/axislabelitem.cpp \
src/GUI/marginswidget.cpp \ src/GUI/marginswidget.cpp \
src/GUI/popup.cpp \ src/GUI/popup.cpp \
src/common/coordinates.cpp \ src/common/coordinates.cpp \

View File

@ -56,6 +56,7 @@ void AxisItem::setRange(const RangeF &range)
Ticks ticks(_range.min(), _range.max(), Ticks ticks(_range.min(), _range.max(),
(_type == X) ? XTICKS * _zoom : YTICKS * _zoom); (_type == X) ? XTICKS * _zoom : YTICKS * _zoom);
_ticks = QVector<Tick>(ticks.count()); _ticks = QVector<Tick>(ticks.count());
for (int i = 0; i < ticks.count(); i++) { for (int i = 0; i < ticks.count(); i++) {
Tick &t = _ticks[i]; Tick &t = _ticks[i];
t.value = ticks.val(i); t.value = ticks.val(i);
@ -74,34 +75,23 @@ void AxisItem::setSize(qreal size)
update(); update();
} }
void AxisItem::setLabel(const QString& label)
{
prepareGeometryChange();
QFontMetrics fm(_font);
_label = label;
_labelBB = fm.tightBoundingRect(label);
updateBoundingRect();
update();
}
void AxisItem::updateBoundingRect() void AxisItem::updateBoundingRect()
{ {
QFontMetrics fm(_font); QFontMetrics fm(_font);
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox; QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox; QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
QRect ls(_labelBB);
if (_type == X) { if (_type == X) {
_boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2 _boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2
+ ss.width()/2, ls.height() + es.height() - fm.descent() + TICK + ss.width()/2, es.height() - 2*fm.descent() + TICK + 2*PADDING);
+ 2*PADDING + 1);
} else { } else {
int mtw = 0; int mtw = 0;
for (int i = 0; i < _ticks.count(); i++) for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw); mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING + TICK/2), _boundingRect = QRectF(-(mtw + 2*PADDING + TICK/2 - fm.descent()),
-(_size + es.height()/2 + fm.descent()), ls.height() + mtw + 2*PADDING -(_size + es.height()/2 + fm.descent()), mtw + 2*PADDING
+ TICK, _size + es.height()/2 + fm.descent() + ss.height()/2); + TICK - fm.descent(), _size + es.height()/2 + fm.descent()
+ ss.height()/2);
} }
} }
@ -110,7 +100,6 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
{ {
Q_UNUSED(option); Q_UNUSED(option);
Q_UNUSED(widget); Q_UNUSED(widget);
QFontMetrics fm(_font);
QRect ts; QRect ts;
painter->setRenderHint(QPainter::Antialiasing, false); painter->setRenderHint(QPainter::Antialiasing, false);
@ -132,9 +121,6 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
- (ts.width()/2), ts.height() + TICK/2 + PADDING, - (ts.width()/2), ts.height() + TICK/2 + PADDING,
_locale.toString(val)); _locale.toString(val));
} }
painter->drawText(_size/2 - _labelBB.width()/2, _labelBB.height()
+ ts.height() - 2*fm.descent() + TICK/2 + 2*PADDING, _label);
} else { } else {
painter->drawLine(0, 0, 0, -_size); painter->drawLine(0, 0, 0, -_size);
@ -151,17 +137,10 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
-((_size/_range.size()) * (val - _range.min())) + (ts.height()/2), -((_size/_range.size()) * (val - _range.min())) + (ts.height()/2),
_locale.toString(val)); _locale.toString(val));
} }
painter->rotate(-90);
painter->drawText(_size/2 - _labelBB.width()/2, -(mtw + 2*PADDING
+ TICK/2), _label);
painter->rotate(90);
} }
/* //painter->setPen(Qt::red);
painter->setPen(Qt::red); //painter->drawRect(boundingRect());
painter->drawRect(boundingRect());
*/
} }
QSizeF AxisItem::margin() const QSizeF AxisItem::margin() const
@ -170,15 +149,15 @@ QSizeF AxisItem::margin() const
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox; QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
if (_type == X) { if (_type == X) {
return QSizeF(es.width()/2, _labelBB.height() + es.height() return QSizeF(es.width()/2, es.height() - 2*fm.descent() + TICK/2
- fm.descent() + TICK/2 + 2*PADDING); + 2*PADDING);
} else { } else {
int mtw = 0; int mtw = 0;
for (int i = 0; i < _ticks.count(); i++) for (int i = 0; i < _ticks.count(); i++)
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw); mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
return QSizeF(_labelBB.height() -fm.descent() + mtw + 2*PADDING return QSizeF(mtw + 2*PADDING + TICK/2 - fm.descent(),
+ TICK/2, es.height()/2 + fm.descent()); es.height()/2 + fm.descent());
} }
} }

View File

@ -13,13 +13,14 @@ public:
AxisItem(Type type, QGraphicsItem *parent = 0); AxisItem(Type type, QGraphicsItem *parent = 0);
/* Note: The items position is at the 0 point of the axis line, not at the
top-left point of the bounding rect as usual */
QRectF boundingRect() const {return _boundingRect;} QRectF boundingRect() const {return _boundingRect;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget); QWidget *widget);
void setRange(const RangeF &range); void setRange(const RangeF &range);
void setSize(qreal size); void setSize(qreal size);
void setLabel(const QString& label);
void setZoom(qreal zoom) {_zoom = zoom;} void setZoom(qreal zoom) {_zoom = zoom;}
QSizeF margin() const; QSizeF margin() const;
@ -36,8 +37,6 @@ private:
Type _type; Type _type;
RangeF _range; RangeF _range;
qreal _size; qreal _size;
QString _label;
QRect _labelBB;
QVector<Tick> _ticks; QVector<Tick> _ticks;
QRectF _boundingRect; QRectF _boundingRect;
QFont _font; QFont _font;

54
src/GUI/axislabelitem.cpp Normal file
View File

@ -0,0 +1,54 @@
#include <QPainter>
#include <QFontMetrics>
#include "font.h"
#include "axislabelitem.h"
AxisLabelItem::AxisLabelItem(Type type, QGraphicsItem *parent)
: QGraphicsItem(parent), _type(type)
{
_font.setPixelSize(FONT_SIZE);
_font.setFamily(FONT_FAMILY);
}
void AxisLabelItem::setLabel(const QString& label)
{
prepareGeometryChange();
QFontMetrics fm(_font);
_label = label;
_labelBB = fm.tightBoundingRect(label);
updateBoundingRect();
update();
}
void AxisLabelItem::updateBoundingRect()
{
QFontMetrics fm(_font);
if (_type == X)
_boundingRect = QRectF(0, 0, _labelBB.width(), fm.height());
else
_boundingRect = QRectF(0, 0, fm.height(), _labelBB.width());
}
void AxisLabelItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QFontMetrics fm(_font);
painter->setFont(_font);
if (_type == X) {
painter->drawText(0, fm.height() - fm.descent(), _label);
} else {
painter->rotate(-90);
painter->drawText(-_labelBB.width(), fm.height() - fm.descent(), _label);
painter->rotate(90);
}
//painter->setRenderHint(QPainter::Antialiasing, false);
//painter->setPen(Qt::red);
//painter->drawRect(boundingRect());
}

30
src/GUI/axislabelitem.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef AXISLABELITEM_H
#define AXISLABELITEM_H
#include <QGraphicsItem>
#include <QFont>
class AxisLabelItem : public QGraphicsItem
{
public:
enum Type {X, Y};
AxisLabelItem(Type type, QGraphicsItem *parent = 0);
QRectF boundingRect() const {return _boundingRect;}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void setLabel(const QString& label);
private:
void updateBoundingRect();
Type _type;
QString _label;
QFont _font;
QRect _labelBB;
QRectF _boundingRect;
};
#endif // AXISLABELITEM_H

View File

@ -9,6 +9,7 @@
#include "data/graph.h" #include "data/graph.h"
#include "opengl.h" #include "opengl.h"
#include "axisitem.h" #include "axisitem.h"
#include "axislabelitem.h"
#include "slideritem.h" #include "slideritem.h"
#include "sliderinfoitem.h" #include "sliderinfoitem.h"
#include "infoitem.h" #include "infoitem.h"
@ -22,6 +23,9 @@
#define MARGIN 10.0 #define MARGIN 10.0
#define IW(item) ((item)->boundingRect().width())
#define IH(item) ((item)->boundingRect().height())
GraphView::GraphView(QWidget *parent) GraphView::GraphView(QWidget *parent)
: QGraphicsView(parent) : QGraphicsView(parent)
{ {
@ -38,6 +42,10 @@ GraphView::GraphView(QWidget *parent)
_xAxis->setZValue(1.0); _xAxis->setZValue(1.0);
_yAxis = new AxisItem(AxisItem::Y); _yAxis = new AxisItem(AxisItem::Y);
_yAxis->setZValue(1.0); _yAxis->setZValue(1.0);
_xAxisLabel = new AxisLabelItem(AxisLabelItem::X);
_xAxisLabel->setZValue(1.0);
_yAxisLabel = new AxisLabelItem(AxisLabelItem::Y);
_yAxisLabel->setZValue(1.0);
_slider = new SliderItem(); _slider = new SliderItem();
_slider->setZValue(4.0); _slider->setZValue(4.0);
_sliderInfo = new SliderInfoItem(_slider); _sliderInfo = new SliderInfoItem(_slider);
@ -73,6 +81,8 @@ GraphView::~GraphView()
{ {
delete _xAxis; delete _xAxis;
delete _yAxis; delete _yAxis;
delete _xAxisLabel;
delete _yAxisLabel;
delete _slider; delete _slider;
delete _info; delete _info;
delete _grid; delete _grid;
@ -81,13 +91,13 @@ GraphView::~GraphView()
void GraphView::createXLabel() void GraphView::createXLabel()
{ {
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel, _xAxisLabel->setLabel(QString("%1 [%2]").arg(_xLabel,
_xUnits.isEmpty() ? "-" : _xUnits)); _xUnits.isEmpty() ? "-" : _xUnits));
} }
void GraphView::createYLabel() void GraphView::createYLabel()
{ {
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel, _yAxisLabel->setLabel(QString("%1 [%2]").arg(_yLabel,
_yUnits.isEmpty() ? "-" : _yUnits)); _yUnits.isEmpty() ? "-" : _yUnits));
} }
@ -163,6 +173,7 @@ void GraphView::setGraphType(GraphType type)
{ {
_graphType = type; _graphType = type;
_bounds = QRectF(); _bounds = QRectF();
_zoom = 1.0;
for (int i = 0; i < _graphs.count(); i++) { for (int i = 0; i < _graphs.count(); i++) {
GraphItem *gi = _graphs.at(i); GraphItem *gi = _graphs.at(i);
@ -257,6 +268,8 @@ void GraphView::redraw(const QSizeF &size)
if (_bounds.isNull()) { if (_bounds.isNull()) {
removeItem(_xAxis); removeItem(_xAxis);
removeItem(_yAxis); removeItem(_yAxis);
removeItem(_xAxisLabel);
removeItem(_yAxisLabel);
removeItem(_slider); removeItem(_slider);
removeItem(_info); removeItem(_info);
removeItem(_grid); removeItem(_grid);
@ -268,6 +281,8 @@ void GraphView::redraw(const QSizeF &size)
removeItem(_message); removeItem(_message);
addItem(_xAxis); addItem(_xAxis);
addItem(_yAxis); addItem(_yAxis);
addItem(_xAxisLabel);
addItem(_yAxisLabel);
addItem(_slider); addItem(_slider);
addItem(_info); addItem(_info);
addItem(_grid); addItem(_grid);
@ -278,6 +293,7 @@ void GraphView::redraw(const QSizeF &size)
if (ry.size() < _minYRange * _yScale) if (ry.size() < _minYRange * _yScale)
ry.resize(_minYRange * _yScale); ry.resize(_minYRange * _yScale);
_xAxis->setZoom(_zoom);
_xAxis->setRange(rx); _xAxis->setRange(rx);
_xAxis->setZoom(_zoom); _xAxis->setZoom(_zoom);
_yAxis->setRange(ry); _yAxis->setRange(ry);
@ -289,9 +305,10 @@ void GraphView::redraw(const QSizeF &size)
r.adjust(0, -(_minYRange/2 - r.height()/2), 0, r.adjust(0, -(_minYRange/2 - r.height()/2), 0,
_minYRange/2 - r.height()/2); _minYRange/2 - r.height()/2);
sx = (size.width() - (my.width() + mx.width())) / r.width(); sx = (size.width() - (my.width() + mx.width()) - IW(_yAxisLabel))
/ r.width();
sy = (size.height() - (mx.height() + my.height()) sy = (size.height() - (mx.height() + my.height())
- _info->boundingRect().height()) / r.height(); - IH(_info) - IH(_xAxisLabel)) / r.height();
sx *= _zoom; sx *= _zoom;
for (int i = 0; i < _graphs.size(); i++) for (int i = 0; i < _graphs.size(); i++)
@ -317,10 +334,12 @@ void GraphView::redraw(const QSizeF &size)
_slider->setArea(r); _slider->setArea(r);
updateSliderPosition(); updateSliderPosition();
r |= _xAxis->sceneBoundingRect(); _info->setPos(QPointF(r.width()/2 - IW(_info)/2 - (IW(_yAxisLabel)
r |= _yAxis->sceneBoundingRect(); + IW(_yAxis))/2, r.top() - IH(_info) - my.height()));
_info->setPos(r.topLeft() + QPointF(r.width()/2 _xAxisLabel->setPos(QPointF(r.width()/2 - IW(_xAxisLabel)/2,
- _info->boundingRect().width()/2, -_info->boundingRect().height())); r.bottom() + mx.height()));
_yAxisLabel->setPos(QPointF(r.left() - my.width() - IW(_yAxisLabel),
r.bottom() - (r.height()/2 + IH(_yAxisLabel)/2)));
_scene->setSceneRect(_scene->itemsBoundingRect()); _scene->setSceneRect(_scene->itemsBoundingRect());
} }
@ -368,8 +387,10 @@ void GraphView::wheelEvent(QWheelEvent *e)
void GraphView::paintEvent(QPaintEvent *e) void GraphView::paintEvent(QPaintEvent *e)
{ {
QRectF viewRect(mapToScene(rect()).boundingRect()); QRectF viewRect(mapToScene(rect()).boundingRect());
_info->setPos(QPointF(viewRect.left() + (viewRect.width() _info->setPos(QPointF(viewRect.left() + (viewRect.width() - IW(_info))/2.0,
- _info->boundingRect().width())/2.0, _info->pos().y())); _info->pos().y()));
_xAxisLabel->setPos(QPointF(viewRect.left() + (viewRect.width()
- IW(_xAxisLabel))/2.0, _xAxisLabel->pos().y()));
QGraphicsView::paintEvent(e); QGraphicsView::paintEvent(e);
} }

View File

@ -10,6 +10,7 @@
class AxisItem; class AxisItem;
class AxisLabelItem;
class SliderItem; class SliderItem;
class SliderInfoItem; class SliderInfoItem;
class GraphItem; class GraphItem;
@ -96,6 +97,7 @@ private:
GraphicsScene *_scene; GraphicsScene *_scene;
AxisItem *_xAxis, *_yAxis; AxisItem *_xAxis, *_yAxis;
AxisLabelItem *_xAxisLabel, *_yAxisLabel;
SliderItem *_slider; SliderItem *_slider;
SliderInfoItem *_sliderInfo; SliderInfoItem *_sliderInfo;
InfoItem *_info; InfoItem *_info;

View File

@ -23,10 +23,8 @@ void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->drawLine(0, -_yTicks.at(i), boundingRect().width(), painter->drawLine(0, -_yTicks.at(i), boundingRect().width(),
-_yTicks.at(i)); -_yTicks.at(i));
/* //painter->setPen(Qt::red);
painter->setPen(Qt::red); //painter->drawRect(boundingRect());
painter->drawRect(boundingRect());
*/
} }
void GridItem::setTicks(const QList<qreal> &x, const QList<qreal> &y) void GridItem::setTicks(const QList<qreal> &x, const QList<qreal> &y)

View File

@ -53,10 +53,8 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
} }
} }
/* //painter->setPen(Qt::red);
painter->setPen(Qt::red); //painter->drawRect(boundingRect());
painter->drawRect(boundingRect());
*/
} }
void InfoItem::insert(const QString &key, const QString &value) void InfoItem::insert(const QString &key, const QString &value)