mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
This commit is rather big, and I forgot to cut it in pieces. The first part creates a new 'calculate_gas_information' that will not fill the profile_info->maxpp member ( that should be removed from it as soon as the new dialog is finished ). The reason for that is that all of the profile data will be calculated and the graph needs to update dynamically, so whenever the settings changes, I ask for the model which is the biggest graph and replot only the ones we need. The second part adds a new animation function 'animdelete' to fade-out and delete the item when it's done. the old function 'hide' did just that but a hide shouldn't delete anything. The third part is preferenes awareness for the PP graphs. I created two new functions that receive the settings key for visibility and use the QSettings to show / hide them. This also works quite well for the axis; if no graph is visible, the axis will also hide itself. The fourth part is colors. The pp graphs now have the correct colors. And a bit of code cleanup too. Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
410 lines
9.7 KiB
C++
410 lines
9.7 KiB
C++
#include "divecartesianaxis.h"
|
|
#include "divelineitem.h"
|
|
#include "divetextitem.h"
|
|
#include "helpers.h"
|
|
#include "preferences.h"
|
|
#include "diveplotdatamodel.h"
|
|
#include "animationfunctions.h"
|
|
#include <QPen>
|
|
#include <QGraphicsScene>
|
|
#include <QDebug>
|
|
#include <QGraphicsView>
|
|
#include <QStyleOption>
|
|
#include <QSettings>
|
|
|
|
static QPen gridPen(){
|
|
QPen pen;
|
|
pen.setColor(getColor(TIME_GRID));
|
|
pen.setWidth(2);
|
|
pen.setCosmetic(true);
|
|
return pen;
|
|
}
|
|
void DiveCartesianAxis::setMaximum(double maximum)
|
|
{
|
|
max = maximum;
|
|
emit maxChanged();
|
|
}
|
|
|
|
void DiveCartesianAxis::setMinimum(double minimum)
|
|
{
|
|
min = minimum;
|
|
}
|
|
|
|
void DiveCartesianAxis::setTextColor(const QColor& color)
|
|
{
|
|
textColor = color;
|
|
}
|
|
|
|
DiveCartesianAxis::DiveCartesianAxis() : orientation(LeftToRight), showTicks(true), showText(true)
|
|
{
|
|
setPen(gridPen());
|
|
}
|
|
|
|
DiveCartesianAxis::~DiveCartesianAxis()
|
|
{
|
|
|
|
}
|
|
|
|
void DiveCartesianAxis::setOrientation(Orientation o)
|
|
{
|
|
orientation = o;
|
|
}
|
|
|
|
QColor DiveCartesianAxis::colorForValue(double value)
|
|
{
|
|
return QColor(Qt::black);
|
|
}
|
|
|
|
void DiveCartesianAxis::updateTicks()
|
|
{
|
|
if (!scene())
|
|
return;
|
|
QLineF m = line();
|
|
// unused so far:
|
|
// QGraphicsView *view = scene()->views().first();
|
|
double steps = (max - min) / interval;
|
|
double currValue = min;
|
|
|
|
if(!showText && !labels.isEmpty()){
|
|
qDeleteAll(labels);
|
|
labels.clear();
|
|
}
|
|
if (steps < 1)
|
|
return;
|
|
if (!labels.isEmpty() && labels.size() > steps) {
|
|
while (labels.size() > steps) {
|
|
DiveTextItem *removedText = labels.takeLast();
|
|
Animations::animDelete(removedText);
|
|
}
|
|
}
|
|
// Move the remaining Ticks / Text to it's corerct position
|
|
// Regartind the possibly new values for the Axis
|
|
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());
|
|
}
|
|
stepSize = stepSize / steps;
|
|
|
|
for (int i = 0, count = labels.size(); i < count; i++, currValue += interval) {
|
|
qreal childPos;
|
|
if (orientation == TopToBottom || orientation == LeftToRight) {
|
|
childPos = begin + i * stepSize;
|
|
} else {
|
|
childPos = begin - i * stepSize;
|
|
}
|
|
labels[i]->setText(textForValue(currValue));
|
|
if ( orientation == LeftToRight || orientation == RightToLeft) {
|
|
labels[i]->animateMoveTo(childPos, m.y1() + tickSize);
|
|
} else {
|
|
labels[i]->animateMoveTo(m.x1() - tickSize, childPos);
|
|
}
|
|
}
|
|
|
|
// Add's the rest of the needed Ticks / Text.
|
|
for (int i = labels.size(); i < steps; i++, currValue += interval) {
|
|
qreal childPos;
|
|
if (orientation == TopToBottom || orientation == LeftToRight) {
|
|
childPos = begin + i * stepSize;
|
|
} else {
|
|
childPos = begin - i * stepSize;
|
|
}
|
|
DiveTextItem *label = NULL;
|
|
|
|
if (showText){
|
|
label = new DiveTextItem(this);
|
|
label->setText(textForValue(currValue));
|
|
label->setBrush(QBrush(textColor));
|
|
label->setBrush(colorForValue(currValue));
|
|
}
|
|
labels.push_back(label);
|
|
if (orientation == RightToLeft || orientation == LeftToRight) {
|
|
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);
|
|
}
|
|
} else {
|
|
if(showText){
|
|
label->setAlignment(Qt::AlignVCenter| Qt::AlignRight);
|
|
label->setPos(m.x1() - tickSize, scene()->sceneRect().height() + 10);
|
|
label->animateMoveTo(m.x1() - tickSize, childPos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DiveCartesianAxis::animateChangeLine(const QLineF& newLine)
|
|
{
|
|
setLine(newLine);
|
|
updateTicks();
|
|
sizeChanged();
|
|
}
|
|
|
|
void DiveCartesianAxis::setShowText(bool show)
|
|
{
|
|
showText = show;
|
|
updateTicks();
|
|
}
|
|
|
|
void DiveCartesianAxis::setShowTicks(bool show)
|
|
{
|
|
showTicks = show;
|
|
updateTicks();
|
|
}
|
|
|
|
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();
|
|
double retValue = orientation == LeftToRight || RightToLeft?
|
|
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;
|
|
// unused for now:
|
|
// double distanceFromOrigin = value - min;
|
|
double percent = IS_FP_SAME(min,max) ? 0.0 : (value - min) / size;
|
|
|
|
|
|
double realSize = orientation == LeftToRight || orientation == RightToLeft?
|
|
m.x2() - m.x1() :
|
|
m.y2() - m.y1();
|
|
|
|
// Inverted axis, just invert the percentage.
|
|
if (orientation == RightToLeft || orientation == BottomToTop)
|
|
percent = 1 - percent;
|
|
|
|
double retValue = realSize * percent;
|
|
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() ;
|
|
return adjusted;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
QString DepthAxis::textForValue(double value)
|
|
{
|
|
return get_depth_string(value, false, false);
|
|
}
|
|
|
|
QColor DepthAxis::colorForValue(double value)
|
|
{
|
|
Q_UNUSED(value);
|
|
return QColor(Qt::red);
|
|
}
|
|
|
|
DepthAxis::DepthAxis()
|
|
{
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
|
|
settingsChanged(); // force the correct size of the line.
|
|
}
|
|
|
|
void DepthAxis::settingsChanged()
|
|
{
|
|
QSettings s;
|
|
|
|
s.beginGroup("TecDetails");
|
|
bool ppGraph = s.value("phegraph").toBool() || s.value("po2graph").toBool() || s.value("pn2graph").toBool();
|
|
if (ppGraph) {
|
|
animateChangeLine(QLineF(0,2,0,60));
|
|
} else {
|
|
animateChangeLine(QLineF(0,2,0,98));
|
|
}
|
|
}
|
|
|
|
QColor TimeAxis::colorForValue(double value)
|
|
{
|
|
Q_UNUSED(value);
|
|
return QColor(Qt::blue);
|
|
}
|
|
|
|
QString TimeAxis::textForValue(double value)
|
|
{
|
|
return QString::number(value / 60);
|
|
}
|
|
|
|
QString TemperatureAxis::textForValue(double value)
|
|
{
|
|
return QString::number(mkelvin_to_C( (int) value));
|
|
}
|
|
|
|
|
|
void DiveCartesianPlane::setLeftAxis(DiveCartesianAxis* axis)
|
|
{
|
|
leftAxis = axis;
|
|
connect(leftAxis, SIGNAL(maxChanged()), this, SLOT(setup()));
|
|
if (bottomAxis)
|
|
setup();
|
|
}
|
|
|
|
void DiveCartesianPlane::setBottomAxis(DiveCartesianAxis* axis)
|
|
{
|
|
bottomAxis = axis;
|
|
connect(bottomAxis, SIGNAL(maxChanged()), 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());
|
|
// unused for now:
|
|
// const int bottom = leftAxis->posAtValue(leftAxis->maximum());
|
|
const int left = bottomAxis->posAtValue(bottomAxis->minimum());
|
|
// unused for now:
|
|
// const int right = bottomAxis->posAtValue(bottomAxis->maximum());
|
|
|
|
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);
|
|
line->setPen(gridPen());
|
|
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);
|
|
line->setPen(gridPen());
|
|
verticalLines.push_back(line);
|
|
scene()->addItem(line);
|
|
}
|
|
}
|
|
|
|
PartialGasPressureAxis::PartialGasPressureAxis()
|
|
{
|
|
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(preferencesChanged()));
|
|
}
|
|
|
|
void PartialGasPressureAxis::setModel(DivePlotDataModel* m)
|
|
{
|
|
model = m;
|
|
connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(preferencesChanged()));
|
|
preferencesChanged();
|
|
}
|
|
|
|
void PartialGasPressureAxis::preferencesChanged()
|
|
{
|
|
QSettings s;
|
|
s.beginGroup("TecDetails");
|
|
bool showPhe = s.value("phegraph").toBool();
|
|
bool showPn2 = s.value("pn2graph").toBool();
|
|
bool showPo2 = s.value("po2graph").toBool();
|
|
setVisible(showPhe || showPn2 || showPo2);
|
|
if (!model->rowCount())
|
|
return;
|
|
|
|
double max = showPhe ? model->pheMax() : -1;
|
|
if (showPn2 && model->pn2Max() > max)
|
|
max = model->pn2Max();
|
|
if( showPo2 && model->po2Max() > max)
|
|
max = model->po2Max();
|
|
|
|
qreal pp = floor(max * 10.0) / 10.0 + 0.2;
|
|
setMaximum(pp);
|
|
setTickInterval( pp > 4 ? 0.5 : 0.25 );
|
|
updateTicks();
|
|
}
|