2014-01-14 18:20:15 +00:00
|
|
|
#include "divecartesianaxis.h"
|
|
|
|
#include "divelineitem.h"
|
|
|
|
#include "divetextitem.h"
|
|
|
|
#include "helpers.h"
|
|
|
|
|
|
|
|
#include <QPen>
|
|
|
|
#include <QGraphicsScene>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QPropertyAnimation>
|
|
|
|
#include <QGraphicsView>
|
|
|
|
#include <QStyleOption>
|
|
|
|
|
2014-01-19 22:14:48 +00:00
|
|
|
static QPen gridPen(){
|
|
|
|
QPen pen;
|
|
|
|
pen.setColor(getColor(TIME_GRID));
|
|
|
|
pen.setWidth(2);
|
|
|
|
pen.setCosmetic(true);
|
|
|
|
return pen;
|
|
|
|
}
|
2014-01-14 18:20:15 +00:00
|
|
|
void DiveCartesianAxis::setMaximum(double maximum)
|
|
|
|
{
|
|
|
|
max = maximum;
|
2014-01-16 14:32:45 +00:00
|
|
|
emit sizeChanged();
|
2014-01-14 18:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setMinimum(double minimum)
|
|
|
|
{
|
|
|
|
min = minimum;
|
2014-01-16 14:32:45 +00:00
|
|
|
emit sizeChanged();
|
2014-01-14 18:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setTextColor(const QColor& color)
|
|
|
|
{
|
|
|
|
textColor = color;
|
|
|
|
}
|
|
|
|
|
2014-01-19 19:19:00 +00:00
|
|
|
DiveCartesianAxis::DiveCartesianAxis() : orientation(LeftToRight), showTicks(true), showText(true)
|
2014-01-14 18:20:15 +00:00
|
|
|
{
|
2014-01-19 22:14:48 +00:00
|
|
|
setPen(gridPen());
|
2014-01-14 18:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DiveCartesianAxis::~DiveCartesianAxis()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-01-16 21:28:33 +00:00
|
|
|
void DiveCartesianAxis::setOrientation(Orientation o)
|
2014-01-14 18:20:15 +00:00
|
|
|
{
|
|
|
|
orientation = o;
|
|
|
|
}
|
|
|
|
|
2014-01-19 22:14:48 +00:00
|
|
|
QColor DiveCartesianAxis::colorForValue(double value)
|
|
|
|
{
|
|
|
|
return QColor(Qt::black);
|
|
|
|
}
|
|
|
|
|
2014-01-14 18:20:15 +00:00
|
|
|
void DiveCartesianAxis::updateTicks()
|
|
|
|
{
|
|
|
|
QLineF m = line();
|
2014-01-16 05:44:18 +00:00
|
|
|
// unused so far:
|
|
|
|
// QGraphicsView *view = scene()->views().first();
|
2014-01-14 18:20:15 +00:00
|
|
|
double steps = (max - min) / interval;
|
|
|
|
double currValue = min;
|
|
|
|
|
2014-01-19 19:19:00 +00:00
|
|
|
if(!showText && !labels.empty()){
|
|
|
|
qDeleteAll(labels);
|
|
|
|
labels.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!labels.isEmpty() && labels.size() > steps) {
|
|
|
|
while (labels.size() > steps) {
|
|
|
|
DiveTextItem *removedText = labels.takeLast();
|
|
|
|
removedText->animatedHide();
|
|
|
|
}
|
|
|
|
}
|
2014-01-14 18:24:33 +00:00
|
|
|
// Move the remaining Ticks / Text to it's corerct position
|
|
|
|
// Regartind the possibly new values for the Axis
|
2014-01-16 21:28:33 +00:00
|
|
|
qreal begin, stepSize;
|
|
|
|
if (orientation == TopToBottom) {
|
|
|
|
begin = m.y1();
|
|
|
|
stepSize = (m.y2() - m.y1());
|
|
|
|
} else if (orientation == BottomToTop) {
|
|
|
|
begin = m.y2();
|
|
|
|
stepSize = (m.y2() - m.y1());
|
|
|
|
} else if (orientation == LeftToRight ) {
|
|
|
|
begin = m.x1();
|
|
|
|
stepSize = (m.x2() - m.x1());
|
|
|
|
} else if (orientation == RightToLeft) {
|
|
|
|
begin = m.x2();
|
|
|
|
stepSize = (m.x2() - m.x1());
|
|
|
|
}
|
2014-01-14 18:24:33 +00:00
|
|
|
stepSize = stepSize / steps;
|
2014-01-16 21:28:33 +00:00
|
|
|
|
2014-01-19 20:31:26 +00:00
|
|
|
for (int i = 0, count = labels.size(); i < count; i++, currValue += interval) {
|
2014-01-16 21:28:33 +00:00
|
|
|
qreal childPos;
|
|
|
|
if (orientation == TopToBottom || orientation == LeftToRight) {
|
|
|
|
childPos = begin + i * stepSize;
|
|
|
|
} else {
|
|
|
|
childPos = begin - i * stepSize;
|
|
|
|
}
|
2014-01-14 18:24:33 +00:00
|
|
|
labels[i]->setText(textForValue(currValue));
|
2014-01-16 21:28:33 +00:00
|
|
|
if ( orientation == LeftToRight || orientation == RightToLeft) {
|
2014-01-14 18:24:33 +00:00
|
|
|
labels[i]->animateMoveTo(childPos, m.y1() + tickSize);
|
2014-01-16 04:50:56 +00:00
|
|
|
} else {
|
2014-01-14 18:24:33 +00:00
|
|
|
labels[i]->animateMoveTo(m.x1() - tickSize, childPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-14 18:28:07 +00:00
|
|
|
// Add's the rest of the needed Ticks / Text.
|
2014-01-19 20:31:26 +00:00
|
|
|
for (int i = labels.size(); i < steps; i++, currValue += interval) {
|
2014-01-16 21:28:33 +00:00
|
|
|
qreal childPos;
|
|
|
|
if (orientation == TopToBottom || orientation == LeftToRight) {
|
|
|
|
childPos = begin + i * stepSize;
|
|
|
|
} else {
|
|
|
|
childPos = begin - i * stepSize;
|
|
|
|
}
|
2014-01-19 19:19:00 +00:00
|
|
|
DiveTextItem *label = NULL;
|
2014-01-14 18:28:07 +00:00
|
|
|
|
2014-01-19 19:19:00 +00:00
|
|
|
if (showText){
|
|
|
|
label = new DiveTextItem(this);
|
|
|
|
label->setText(textForValue(currValue));
|
|
|
|
label->setBrush(QBrush(textColor));
|
2014-01-19 22:14:48 +00:00
|
|
|
label->setBrush(colorForValue(currValue));
|
2014-01-19 19:19:00 +00:00
|
|
|
}
|
2014-01-14 18:28:07 +00:00
|
|
|
labels.push_back(label);
|
2014-01-16 21:28:33 +00:00
|
|
|
if (orientation == RightToLeft || orientation == LeftToRight) {
|
2014-01-19 20:31:26 +00:00
|
|
|
|
2014-01-19 19:19:00 +00:00
|
|
|
if(showText){
|
|
|
|
label->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
|
|
|
|
label->setPos(scene()->sceneRect().width() + 10, m.y1() + tickSize); // position it outside of the scene);
|
|
|
|
label->animateMoveTo(childPos, m.y1() + tickSize);
|
|
|
|
}
|
2014-01-16 04:50:56 +00:00
|
|
|
} else {
|
2014-01-19 19:19:00 +00:00
|
|
|
if(showText){
|
|
|
|
label->setAlignment(Qt::AlignVCenter| Qt::AlignRight);
|
|
|
|
label->setPos(m.x1() - tickSize, scene()->sceneRect().height() + 10);
|
|
|
|
label->animateMoveTo(m.x1() - tickSize, childPos);
|
|
|
|
}
|
2014-01-14 18:28:07 +00:00
|
|
|
}
|
|
|
|
}
|
2014-01-14 18:20:15 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 19:19:00 +00:00
|
|
|
void DiveCartesianAxis::setShowText(bool show)
|
|
|
|
{
|
|
|
|
showText = show;
|
|
|
|
updateTicks();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setShowTicks(bool show)
|
|
|
|
{
|
|
|
|
showTicks = show;
|
|
|
|
updateTicks();
|
|
|
|
}
|
|
|
|
|
2014-01-14 18:20:15 +00:00
|
|
|
QString DiveCartesianAxis::textForValue(double value)
|
|
|
|
{
|
|
|
|
return QString::number(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setTickSize(qreal size)
|
|
|
|
{
|
|
|
|
tickSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setTickInterval(double i)
|
|
|
|
{
|
|
|
|
interval = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal DiveCartesianAxis::valueAt(const QPointF& p)
|
|
|
|
{
|
|
|
|
QLineF m = line();
|
2014-01-16 21:28:33 +00:00
|
|
|
double retValue = orientation == LeftToRight || RightToLeft?
|
2014-01-14 18:20:15 +00:00
|
|
|
max * (p.x() - m.x1()) / (m.x2() - m.x1()) :
|
|
|
|
max * (p.y() - m.y1()) / (m.y2() - m.y1());
|
|
|
|
return retValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal DiveCartesianAxis::posAtValue(qreal value)
|
|
|
|
{
|
|
|
|
QLineF m = line();
|
|
|
|
QPointF p = pos();
|
|
|
|
|
|
|
|
double size = max - min;
|
2014-01-16 23:30:47 +00:00
|
|
|
// unused for now:
|
|
|
|
// double distanceFromOrigin = value - min;
|
2014-01-16 20:39:13 +00:00
|
|
|
double percent = (value - min) / size;
|
2014-01-16 21:28:33 +00:00
|
|
|
|
|
|
|
double realSize = orientation == LeftToRight || orientation == RightToLeft?
|
2014-01-14 18:20:15 +00:00
|
|
|
m.x2() - m.x1() :
|
|
|
|
m.y2() - m.y1();
|
2014-01-16 21:28:33 +00:00
|
|
|
|
|
|
|
// Inverted axis, just invert the percentage.
|
2014-01-16 23:30:47 +00:00
|
|
|
if (orientation == RightToLeft || orientation == BottomToTop)
|
2014-01-16 21:28:33 +00:00
|
|
|
percent = 1 - percent;
|
|
|
|
|
2014-01-14 18:20:15 +00:00
|
|
|
double retValue = realSize * percent;
|
2014-01-16 21:28:33 +00:00
|
|
|
double adjusted =
|
|
|
|
orientation == LeftToRight ? retValue + m.x1() + p.x() :
|
|
|
|
orientation == RightToLeft ? retValue + m.x1() + p.x() :
|
|
|
|
orientation == TopToBottom ? retValue + m.y1() + p.y() :
|
|
|
|
/* entation == BottomToTop */ retValue + m.y1() + p.y() ;
|
2014-01-16 20:39:13 +00:00
|
|
|
return adjusted;
|
2014-01-14 18:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal DiveCartesianAxis::percentAt(const QPointF& p)
|
|
|
|
{
|
|
|
|
qreal value = valueAt(p);
|
|
|
|
double size = max - min;
|
|
|
|
double percent = value / size;
|
|
|
|
return percent;
|
|
|
|
}
|
|
|
|
|
|
|
|
double DiveCartesianAxis::maximum() const
|
|
|
|
{
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
|
|
|
double DiveCartesianAxis::minimum() const
|
|
|
|
{
|
|
|
|
return min;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianAxis::setColor(const QColor& color)
|
|
|
|
{
|
|
|
|
QPen defaultPen(color);
|
|
|
|
defaultPen.setJoinStyle(Qt::RoundJoin);
|
|
|
|
defaultPen.setCapStyle(Qt::RoundCap);
|
|
|
|
defaultPen.setWidth(2);
|
|
|
|
defaultPen.setCosmetic(true);
|
|
|
|
setPen(defaultPen);
|
|
|
|
}
|
2014-01-15 12:54:33 +00:00
|
|
|
|
|
|
|
QString DepthAxis::textForValue(double value)
|
|
|
|
{
|
|
|
|
return get_depth_string(value, false, false);
|
|
|
|
}
|
2014-01-15 13:08:31 +00:00
|
|
|
|
2014-01-19 22:14:48 +00:00
|
|
|
QColor DepthAxis::colorForValue(double value)
|
|
|
|
{
|
|
|
|
Q_UNUSED(value);
|
|
|
|
return QColor(Qt::red);
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor TimeAxis::colorForValue(double value)
|
|
|
|
{
|
|
|
|
Q_UNUSED(value);
|
|
|
|
return QColor(Qt::blue);
|
|
|
|
}
|
|
|
|
|
2014-01-15 13:08:31 +00:00
|
|
|
QString TimeAxis::textForValue(double value)
|
|
|
|
{
|
2014-01-16 04:50:56 +00:00
|
|
|
return QString::number(value / 60);
|
|
|
|
}
|
2014-01-16 14:32:45 +00:00
|
|
|
|
2014-01-16 20:39:13 +00:00
|
|
|
QString TemperatureAxis::textForValue(double value)
|
|
|
|
{
|
2014-01-16 23:30:47 +00:00
|
|
|
return QString::number(mkelvin_to_C( (int) value));
|
2014-01-16 20:39:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-01-16 14:32:45 +00:00
|
|
|
void DiveCartesianPlane::setLeftAxis(DiveCartesianAxis* axis)
|
|
|
|
{
|
|
|
|
leftAxis = axis;
|
|
|
|
connect(leftAxis, SIGNAL(sizeChanged()), this, SLOT(setup()));
|
|
|
|
if (bottomAxis)
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianPlane::setBottomAxis(DiveCartesianAxis* axis)
|
|
|
|
{
|
|
|
|
bottomAxis = axis;
|
|
|
|
connect(bottomAxis, SIGNAL(sizeChanged()), this, SLOT(setup()));
|
|
|
|
if (leftAxis)
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
QLineF DiveCartesianPlane::horizontalLine() const
|
|
|
|
{
|
|
|
|
return (bottomAxis) ? bottomAxis->line() : QLineF() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianPlane::setHorizontalLine(QLineF line)
|
|
|
|
{
|
|
|
|
if ( horizontalSize == line.length())
|
|
|
|
return;
|
|
|
|
horizontalSize = line.length();
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianPlane::setVerticalLine(QLineF line)
|
|
|
|
{
|
|
|
|
if (verticalSize == line.length())
|
|
|
|
return;
|
|
|
|
verticalSize = line.length();
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
QLineF DiveCartesianPlane::verticalLine() const
|
|
|
|
{
|
|
|
|
return (leftAxis) ? leftAxis->line() : QLineF() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiveCartesianPlane::setup()
|
|
|
|
{
|
|
|
|
if (!leftAxis || !bottomAxis || !scene())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// This creates a Grid around the axis, creating the cartesian plane.
|
|
|
|
const int top = leftAxis->posAtValue(leftAxis->minimum());
|
2014-01-16 23:30:47 +00:00
|
|
|
// unused for now:
|
|
|
|
// const int bottom = leftAxis->posAtValue(leftAxis->maximum());
|
2014-01-16 14:32:45 +00:00
|
|
|
const int left = bottomAxis->posAtValue(bottomAxis->minimum());
|
2014-01-16 23:30:47 +00:00
|
|
|
// unused for now:
|
|
|
|
// const int right = bottomAxis->posAtValue(bottomAxis->maximum());
|
2014-01-16 14:32:45 +00:00
|
|
|
|
|
|
|
setRect(0, 0, horizontalSize, verticalSize);
|
|
|
|
setPos(left, top);
|
|
|
|
|
|
|
|
qDeleteAll(horizontalLines);
|
|
|
|
qDeleteAll(verticalLines);
|
|
|
|
horizontalLines.clear();
|
|
|
|
verticalLines.clear();
|
|
|
|
|
|
|
|
// DEPTH is M_OR_FEET(10,30), Minutes are 600, per line.
|
|
|
|
for (int i = leftAxis->minimum(), max = leftAxis->maximum(); i < max; i += M_OR_FT(10,30)) {
|
|
|
|
DiveLineItem *line = new DiveLineItem();
|
|
|
|
line->setLine(0, 0, horizontalSize, 0);
|
|
|
|
line->setPos(left,leftAxis->posAtValue(i));
|
|
|
|
line->setZValue(-1);
|
2014-01-19 22:14:48 +00:00
|
|
|
line->setPen(gridPen());
|
2014-01-16 14:32:45 +00:00
|
|
|
horizontalLines.push_back(line);
|
|
|
|
scene()->addItem(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = bottomAxis->minimum(), max = bottomAxis->maximum(); i < max; i += 600) { // increments by 10 minutes.
|
|
|
|
DiveLineItem *line = new DiveLineItem();
|
|
|
|
line->setLine(0, 0, 0, verticalSize);
|
|
|
|
line->setPos(bottomAxis->posAtValue(i), top);
|
|
|
|
line->setZValue(-1);
|
2014-01-19 22:14:48 +00:00
|
|
|
line->setPen(gridPen());
|
2014-01-16 14:32:45 +00:00
|
|
|
verticalLines.push_back(line);
|
|
|
|
scene()->addItem(line);
|
|
|
|
}
|
2014-01-16 23:30:47 +00:00
|
|
|
}
|