Support imperial measurements in dive planner / add dive

This was not as hard as I assumed it would be. I may still change the
horizontal dimension to be the more logical seconds instead of minutes,
but for now this achieves the main goal.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2013-09-22 12:37:49 -07:00
parent ff58fd7dca
commit 6ce5704435
3 changed files with 61 additions and 48 deletions

View file

@ -11,7 +11,8 @@
#include "dive.h" #include "dive.h"
#include "qthelper.h" #include "qthelper.h"
QString get_depth_string(depth_t depth, bool showunit = false); QString get_depth_string(depth_t depth, bool showunit = false, bool showdecimal = true);
QString get_depth_string(int mm, bool showunit = false, bool showdecimal = true);
QString get_depth_unit(); QString get_depth_unit();
QString get_weight_string(weight_t weight, bool showunit = false); QString get_weight_string(weight_t weight, bool showunit = false);
QString get_weight_unit(); QString get_weight_unit();

View file

@ -195,17 +195,22 @@ void set_dc_nickname(struct dive *dive)
} }
} }
QString get_depth_string(depth_t depth, bool showunit) QString get_depth_string(int mm, bool showunit, bool showdecimal)
{ {
if (prefs.units.length == units::METERS) { if (prefs.units.length == units::METERS) {
double meters = depth.mm / 1000.0; double meters = mm / 1000.0;
return QString("%1%2").arg(meters, 0, 'f', meters >= 20.0 ? 0 : 1 ).arg(showunit ? _("m") : ""); return QString("%1%2").arg(meters, 0, 'f', (showdecimal && meters < 20.0) ? 1 : 0 ).arg(showunit ? _("m") : "");
} else { } else {
double feet = mm_to_feet(depth.mm); double feet = mm_to_feet(mm);
return QString("%1%2").arg(feet, 0, 'f', 1). arg(showunit ? _("ft") : ""); return QString("%1%2").arg(feet, 0, 'f', showdecimal ? 1 : 0). arg(showunit ? _("ft") : "");
} }
} }
QString get_depth_string(depth_t depth, bool showunit, bool showdecimal)
{
return get_depth_string(depth.mm, showunit, showdecimal);
}
QString get_depth_unit() QString get_depth_unit()
{ {
if (prefs.units.length == units::METERS) if (prefs.units.length == units::METERS)

View file

@ -26,10 +26,12 @@
#define TIME_INITIAL_MAX 30 #define TIME_INITIAL_MAX 30
#define MAX_DEEPNESS 150 #define MAX_DEPTH M_OR_FT(150, 450)
#define MIN_DEEPNESS 40 #define MIN_DEPTH M_OR_FT(20, 60)
QStringListModel *airTypes(){ #define M_OR_FT(_m,_f) ((prefs.units.length == units::METERS) ? ((_m) * 1000) : ((_f) * 304.8))
QStringListModel *airTypes() {
static QStringListModel *self = new QStringListModel(QStringList() static QStringListModel *self = new QStringListModel(QStringList()
<< QObject::tr("AIR") << QObject::tr("AIR")
<< QObject::tr("EAN32") << QObject::tr("EAN32")
@ -98,8 +100,8 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
depthLine = new Ruler(); depthLine = new Ruler();
depthLine->setMinimum(0); depthLine->setMinimum(0);
depthLine->setMaximum(40); depthLine->setMaximum(M_OR_FT(40,120));
depthLine->setTickInterval(10); depthLine->setTickInterval(M_OR_FT(10,30));
depthLine->setLine( depthLine->setLine(
fromPercent(10, Qt::Horizontal), fromPercent(10, Qt::Horizontal),
fromPercent(10, Qt::Vertical), fromPercent(10, Qt::Vertical),
@ -127,18 +129,23 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
diveBg->setPen(QPen(QBrush(),0)); diveBg->setPen(QPen(QBrush(),0));
scene()->addItem(diveBg); scene()->addItem(diveBg);
#define ADDBTN(obj, icon, text, horizontal, vertical, tooltip, slot) \ #define ADDBTN(obj, icon, text, horizontal, vertical, tooltip, value, slot) \
obj = new Button(); \ obj = new Button(); \
obj->setPixmap(QPixmap(icon)); \ obj->setPixmap(QPixmap(icon)); \
obj->setPos(fromPercent(horizontal, Qt::Horizontal), fromPercent(vertical, Qt::Vertical)); \ obj->setPos(fromPercent(horizontal, Qt::Horizontal), fromPercent(vertical, Qt::Vertical)); \
obj->setToolTip(tooltip); \ obj->setToolTip(QString(tooltip.arg(value))); \
scene()->addItem(obj); \ scene()->addItem(obj); \
connect(obj, SIGNAL(clicked()), this, SLOT(slot)); connect(obj, SIGNAL(clicked()), this, SLOT(slot));
ADDBTN(plusDepth, ":plus", "" , 5, 5, tr("Increase maximum depth by 10m"), increaseDepth()); QString incrText;
ADDBTN(plusTime, ":plus", "" , 95, 95, tr("Increase minimum time by 10m"), increaseTime()); if (prefs.units.length == units::METERS)
ADDBTN(lessDepth, ":minimum","" , 2, 5, tr("Decreases maximum depth by 10m"), decreaseDepth()); incrText = tr("10m");
ADDBTN(lessTime, ":minimum","" , 92, 95, tr("Decreases minimum time by 10m"), decreaseTime()); else
incrText = tr("30ft");
ADDBTN(plusDepth, ":plus", "" , 5, 5, tr("Increase maximum depth by %1"), incrText, increaseDepth());
ADDBTN(lessDepth, ":minimum","" , 2, 5, tr("Decreases maximum depth by %1"), incrText, decreaseDepth());
ADDBTN(plusTime, ":plus", "" , 95, 95, tr("Increase minimum time by %1"), tr("10min"), increaseTime());
ADDBTN(lessTime, ":minimum","" , 92, 95, tr("Decreases minimum time by %1"), tr("10min"), decreaseTime());
#undef ADDBTN #undef ADDBTN
minMinutes = TIME_INITIAL_MAX; minMinutes = TIME_INITIAL_MAX;
@ -208,10 +215,10 @@ void DivePlannerGraphics::keyDownAction()
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)) { if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)) {
int row = handles.indexOf(handler); int row = handles.indexOf(handler);
divedatapoint dp = plannerModel->at(row); divedatapoint dp = plannerModel->at(row);
if (dp.depth / 1000 >= depthLine->maximum()) if (dp.depth >= depthLine->maximum())
continue; continue;
dp.depth += 1000; dp.depth += M_OR_FT(1,5);
plannerModel->editStop(row, dp); plannerModel->editStop(row, dp);
} }
} }
@ -225,10 +232,10 @@ void DivePlannerGraphics::keyUpAction()
int row = handles.indexOf(handler); int row = handles.indexOf(handler);
divedatapoint dp = plannerModel->at(row); divedatapoint dp = plannerModel->at(row);
if (dp.depth / 1000 <= 0) if (dp.depth <= 0)
continue; continue;
dp.depth -= 1000; dp.depth -= M_OR_FT(1,5);
plannerModel->editStop(row, dp); plannerModel->editStop(row, dp);
} }
} }
@ -353,9 +360,9 @@ qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientatio
void DivePlannerGraphics::increaseDepth() void DivePlannerGraphics::increaseDepth()
{ {
if (depthLine->maximum() + 10 > MAX_DEEPNESS) if (depthLine->maximum() + M_OR_FT(10,30) > MAX_DEPTH)
return; return;
depthLine->setMaximum( depthLine->maximum() + 10); depthLine->setMaximum( depthLine->maximum() + M_OR_FT(10,30));
depthLine->updateTicks(); depthLine->updateTicks();
drawProfile(); drawProfile();
} }
@ -370,11 +377,11 @@ void DivePlannerGraphics::increaseTime()
void DivePlannerGraphics::decreaseDepth() void DivePlannerGraphics::decreaseDepth()
{ {
if (depthLine->maximum() - 10 < MIN_DEEPNESS) if (depthLine->maximum() - M_OR_FT(10,30) < MIN_DEPTH)
return; return;
Q_FOREACH(DiveHandler *d, handles){ Q_FOREACH(DiveHandler *d, handles) {
if (depthLine->valueAt(d->pos()) > depthLine->maximum() - 10){ if (depthLine->valueAt(d->pos()) > depthLine->maximum() - M_OR_FT(10,30)) {
QMessageBox::warning(mainWindow(), QMessageBox::warning(mainWindow(),
tr("Handler Position Error"), tr("Handler Position Error"),
tr("One or more of your stops will be lost with this operations, \n" tr("One or more of your stops will be lost with this operations, \n"
@ -382,7 +389,7 @@ void DivePlannerGraphics::decreaseDepth()
return; return;
} }
} }
depthLine->setMaximum(depthLine->maximum() - 10); depthLine->setMaximum(depthLine->maximum() - M_OR_FT(10,30));
depthLine->updateTicks(); depthLine->updateTicks();
drawProfile(); drawProfile();
} }
@ -409,18 +416,18 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event)
return; return;
int minutes = rint(timeLine->valueAt(mappedPos)); int minutes = rint(timeLine->valueAt(mappedPos));
int meters = rint(depthLine->valueAt(mappedPos)); int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1);
plannerModel->addStop(meters * 1000, minutes * 60, tr("Air"), 0); plannerModel->addStop(milimeters, minutes * 60, tr("Air"), 0);
} }
void DivePlannerPointsModel::createSimpleDive() void DivePlannerPointsModel::createSimpleDive()
{ {
plannerModel->addStop(15000, 1 * 60, tr("Air"), 0); plannerModel->addStop(M_OR_FT(15,45), 1 * 60, tr("Air"), 0);
plannerModel->addStop(15000, 40 * 60, tr("Air"), 0); plannerModel->addStop(M_OR_FT(15,45), 40 * 60, tr("Air"), 0);
// plannerModel->addStop(9000, 26 * 60, tr("Air"), 0); // plannerModel->addStop(9000, 26 * 60, tr("Air"), 0);
// plannerModel->addStop(9000, 41 * 60, tr("Air"), 0); // plannerModel->addStop(9000, 41 * 60, tr("Air"), 0);
plannerModel->addStop(5000, 42 * 60, tr("Air"), 0); plannerModel->addStop(M_OR_FT(5,15), 42 * 60, tr("Air"), 0);
plannerModel->addStop(5000, 45 * 60, tr("Air"), 0); plannerModel->addStop(M_OR_FT(5,15), 45 * 60, tr("Air"), 0);
} }
void DivePlannerGraphics::prepareSelectGas() void DivePlannerGraphics::prepareSelectGas()
@ -460,7 +467,7 @@ void DivePlannerGraphics::drawProfile()
for (int i = 0; i < plannerModel->rowCount(); i++) { for (int i = 0; i < plannerModel->rowCount(); i++) {
divedatapoint dp = plannerModel->at(i); divedatapoint dp = plannerModel->at(i);
DiveHandler *h = handles.at(i); DiveHandler *h = handles.at(i);
h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth / 1000)); h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth));
QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos(); QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos();
QPointF p2 = handles[i]->pos(); QPointF p2 = handles[i]->pos();
QLineF line(p1, p2); QLineF line(p1, p2);
@ -479,7 +486,7 @@ void DivePlannerGraphics::drawProfile()
for (dp = diveplan.dp; dp != NULL; dp = dp->next) { for (dp = diveplan.dp; dp != NULL; dp = dp->next) {
double xpos = timeLine->posAtValue(dp->time / 60.0); double xpos = timeLine->posAtValue(dp->time / 60.0);
double ypos = depthLine->posAtValue(dp->depth / 1000.0); double ypos = depthLine->posAtValue(dp->depth);
if (!dp->entered) { if (!dp->entered) {
QGraphicsLineItem *item = new QGraphicsLineItem(lastx, lasty, xpos, ypos); QGraphicsLineItem *item = new QGraphicsLineItem(lastx, lasty, xpos, ypos);
item->setPen(QPen(QBrush(Qt::red),0)); item->setPen(QPen(QBrush(Qt::red),0));
@ -528,7 +535,7 @@ void DivePlannerGraphics::mouseMoveEvent(QMouseEvent* event)
verticalLine->setPos(mappedPos.x(), fromPercent(0, Qt::Vertical)); verticalLine->setPos(mappedPos.x(), fromPercent(0, Qt::Vertical));
horizontalLine->setPos(fromPercent(0, Qt::Horizontal), mappedPos.y()); horizontalLine->setPos(fromPercent(0, Qt::Horizontal), mappedPos.y());
depthString->setText(QString::number(rint(depthLine->valueAt(mappedPos))) + "m" ); depthString->setText(get_depth_string(depthLine->valueAt(mappedPos), true, false));
depthString->setPos(fromPercent(5, Qt::Horizontal), mappedPos.y()); depthString->setPos(fromPercent(5, Qt::Horizontal), mappedPos.y());
timeString->setText(QString::number(rint(timeLine->valueAt(mappedPos))) + "min"); timeString->setText(QString::number(rint(timeLine->valueAt(mappedPos))) + "min");
timeString->setPos(mappedPos.x()+1, fromPercent(95, Qt::Vertical)); timeString->setPos(mappedPos.x()+1, fromPercent(95, Qt::Vertical));
@ -571,11 +578,11 @@ void DivePlannerGraphics::moveActiveHandler(const QPointF& mappedPos, const int
if (minutes * 60 <= mintime || minutes * 60 >= maxtime) if (minutes * 60 <= mintime || minutes * 60 >= maxtime)
return; return;
int meters = rint(depthLine->valueAt(mappedPos)); int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1);
double xpos = timeLine->posAtValue(minutes); double xpos = timeLine->posAtValue(minutes);
double ypos = depthLine->posAtValue(meters); double ypos = depthLine->posAtValue(milimeters);
data.depth = rint(depthLine->valueAt(mappedPos)) * 1000; data.depth = milimeters;
data.time = rint(timeLine->valueAt(mappedPos)) * 60; data.time = rint(timeLine->valueAt(mappedPos)) * 60;
plannerModel->editStop(pos, data); plannerModel->editStop(pos, data);
@ -727,7 +734,7 @@ void Ruler::updateTicks()
item->setPen(pen()); item->setPen(pen());
ticks.push_back(item); ticks.push_back(item);
label = new QGraphicsSimpleTextItem(QString::number(currValue), this); label = new QGraphicsSimpleTextItem(get_depth_string(currValue, false, false), this);
label->setBrush(QBrush(textColor)); label->setBrush(QBrush(textColor));
label->setFlag(ItemIgnoresTransformations); label->setFlag(ItemIgnoresTransformations);
label->setPos(m.x2() - 80, pos); label->setPos(m.x2() - 80, pos);
@ -737,7 +744,7 @@ void Ruler::updateTicks()
item->setPen(pen()); item->setPen(pen());
ticks.push_back(item); ticks.push_back(item);
label = new QGraphicsSimpleTextItem(QString::number(currValue), this); label = new QGraphicsSimpleTextItem(get_depth_string(currValue, false, false), this);
label->setBrush(QBrush(textColor)); label->setBrush(QBrush(textColor));
label->setFlag(ItemIgnoresTransformations); label->setFlag(ItemIgnoresTransformations);
label->setPos(m.x2() - 80, pos); label->setPos(m.x2() - 80, pos);
@ -938,7 +945,7 @@ QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const
divedatapoint p = divepoints.at(index.row()); divedatapoint p = divepoints.at(index.row());
switch(index.column()) { switch(index.column()) {
case CCSETPOINT: return p.po2; case CCSETPOINT: return p.po2;
case DEPTH: return p.depth / 1000; case DEPTH: return p.depth;
case DURATION: return p.time / 60; case DURATION: return p.time / 60;
case GAS: return strForAir(p); case GAS: return strForAir(p);
} }
@ -957,7 +964,7 @@ bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& v
if(role == Qt::EditRole) { if(role == Qt::EditRole) {
divedatapoint& p = divepoints[index.row()]; divedatapoint& p = divepoints[index.row()];
switch(index.column()) { switch(index.column()) {
case DEPTH: p.depth = value.toInt() * 1000; break; case DEPTH: p.depth = value.toInt(); break;
case DURATION: p.time = value.toInt() * 60; break; case DURATION: p.time = value.toInt() * 60; break;
case CCSETPOINT:{ case CCSETPOINT:{
int po2 = 0; int po2 = 0;
@ -1060,16 +1067,16 @@ bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2)
return p1.time <= p2.time; return p1.time <= p2.time;
} }
int DivePlannerPointsModel::addStop(int meters, int minutes, const QString& gas, int ccpoint) int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& gas, int ccpoint)
{ {
int row = divepoints.count(); int row = divepoints.count();
if(meters == 0 && minutes == 0) { if(milimeters == 0 && minutes == 0) {
if(row == 0) { if(row == 0) {
meters = 10000; milimeters = M_OR_FT(10,30);
minutes = 600; minutes = 600;
} else { } else {
divedatapoint p = at(row-1); divedatapoint p = at(row-1);
meters = p.depth; milimeters = p.depth;
minutes = p.time + 600; minutes = p.time + 600;
} }
} }
@ -1086,7 +1093,7 @@ int DivePlannerPointsModel::addStop(int meters, int minutes, const QString& gas,
// add the new stop // add the new stop
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
divedatapoint point; divedatapoint point;
point.depth = meters; point.depth = milimeters;
point.time = minutes; point.time = minutes;
if (row == 0) { if (row == 0) {
point.o2 = 209; point.o2 = 209;