mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Get the math right for cylinder model setData function
This is a fun one. We only want to mark the divelist changed if the user actually changed something. So we try really hard to compare what was entered with what was there and only if it is different do we overwrite existing values and record this as a change to the divelist. An additional challenge here is the fact that the user needs to enter a working pressure before they can enter a size (when in cuft mode). That is not really intuitive. We work around this by assuming working pressure is 3000psi if a size is given in cuft - but then if the user changes the working pressure, that changes the volume. Now going back and changing the volume again does the trick. Or enter the working pressure FIRST and then the volume... This also changes the incorrect MAXPRESSURE to WORKINGPRESSURE and uses the text WorkPress in English (Gtk code used MaxPress which was simply wrong - this is just the design pressure or working pressure, not some hard maximum. In fact, people quite commonly "overfill" these tanks. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
63b6f7d5a2
commit
76903849de
4 changed files with 85 additions and 34 deletions
5
dive.c
5
dive.c
|
@ -312,6 +312,11 @@ int gas_volume(cylinder_t *cyl, pressure_t p)
|
|||
return cyl->type.size.mliter * surface_volume_multiplier(p);
|
||||
}
|
||||
|
||||
int wet_volume(double cuft, pressure_t p)
|
||||
{
|
||||
return cuft_to_l(cuft) * 1000 / surface_volume_multiplier(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the cylinder tank pressures are within half a bar
|
||||
* (about 8 PSI) of the sample pressures, we consider it
|
||||
|
|
3
dive.h
3
dive.h
|
@ -221,7 +221,7 @@ static inline double psi_to_bar(double psi)
|
|||
return psi / 14.5037738;
|
||||
}
|
||||
|
||||
static inline unsigned long psi_to_mbar(double psi)
|
||||
static inline long psi_to_mbar(double psi)
|
||||
{
|
||||
return psi_to_bar(psi)*1000 + 0.5;
|
||||
}
|
||||
|
@ -238,6 +238,7 @@ static inline double bar_to_atm(double bar)
|
|||
|
||||
/* Volume in mliter of a cylinder at pressure 'p' */
|
||||
extern int gas_volume(cylinder_t *cyl, pressure_t p);
|
||||
extern int wet_volume(double cuft, pressure_t p);
|
||||
|
||||
static inline int mbar_to_PSI(int mbar)
|
||||
{
|
||||
|
|
109
qt-ui/models.cpp
109
qt-ui/models.cpp
|
@ -34,8 +34,8 @@ QVariant CylindersModel::headerData(int section, Qt::Orientation orientation, in
|
|||
case SIZE:
|
||||
ret = tr("Size");
|
||||
break;
|
||||
case MAXPRESS:
|
||||
ret = tr("MaxPress");
|
||||
case WORKINGPRESS:
|
||||
ret = tr("WorkPress");
|
||||
break;
|
||||
case START:
|
||||
ret = tr("Start");
|
||||
|
@ -77,14 +77,14 @@ QVariant CylindersModel::data(const QModelIndex& index, int role) const
|
|||
// sizes take working pressure into account...
|
||||
if (cyl->type.size.mliter) {
|
||||
if (prefs.units.volume == prefs.units.CUFT) {
|
||||
int cuft = ml_to_cuft(gas_volume(cyl, cyl->type.workingpressure));
|
||||
int cuft = 0.5 + ml_to_cuft(gas_volume(cyl, cyl->type.workingpressure));
|
||||
ret = QString("%1cuft").arg(cuft);
|
||||
} else {
|
||||
ret = QString("%1l").arg(cyl->type.size.mliter / 1000.0, 0, 'f', 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MAXPRESS:
|
||||
case WORKINGPRESS:
|
||||
if (cyl->type.workingpressure.mbar)
|
||||
ret = get_pressure_string(cyl->type.workingpressure, TRUE);
|
||||
break;
|
||||
|
@ -114,45 +114,90 @@ QVariant CylindersModel::data(const QModelIndex& index, int role) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define CHANGED(_t,_u1,_u2) value._t() != data(index, role).toString().replace(_u1,"").replace(_u2,"")._t()
|
||||
|
||||
bool CylindersModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
cylinder_t *cyl = ¤t->cylinder[index.row()];
|
||||
switch(index.column()){
|
||||
case TYPE:{
|
||||
QByteArray desc = value.toByteArray();
|
||||
cyl->type.description = strdup(desc.data());
|
||||
break;
|
||||
switch(index.column()) {
|
||||
case TYPE:
|
||||
if (!value.isNull()) {
|
||||
char *text = value.toByteArray().data();
|
||||
if (strcmp(cyl->type.description, text)) {
|
||||
cyl->type.description = strdup(text);
|
||||
mark_divelist_changed(TRUE);
|
||||
}
|
||||
}
|
||||
case SIZE:
|
||||
// we can't use get_volume_string because the idiotic imperial tank
|
||||
// sizes take working pressure into account...
|
||||
if (cyl->type.size.mliter) {
|
||||
break;
|
||||
case SIZE:
|
||||
if (CHANGED(toDouble, "cuft", "l")) {
|
||||
// if units are CUFT then this value is meaningless until we have working pressure
|
||||
if (value.toDouble() != 0.0) {
|
||||
if (prefs.units.volume == prefs.units.CUFT) {
|
||||
double liters = cuft_to_l(value.toDouble());
|
||||
cyl->type.size.mliter = liters * 1000.0;
|
||||
if (cyl->type.workingpressure.mbar == 0)
|
||||
// this is a hack as we can't store a wet size
|
||||
// without working pressure in cuft mode
|
||||
// so we assume it's an aluminum tank at 3000psi
|
||||
cyl->type.workingpressure.mbar = psi_to_mbar(3000);
|
||||
if (cyl->type.size.mliter != wet_volume(value.toDouble(), cyl->type.workingpressure)) {
|
||||
mark_divelist_changed(TRUE);
|
||||
cyl->type.size.mliter = wet_volume(value.toDouble(), cyl->type.workingpressure);
|
||||
}
|
||||
} else {
|
||||
cyl->type.size.mliter = value.toDouble() * 1000.0;
|
||||
if (cyl->type.size.mliter != value.toDouble() * 1000.0) {
|
||||
mark_divelist_changed(TRUE);
|
||||
cyl->type.size.mliter = value.toDouble() * 1000.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MAXPRESS:
|
||||
cyl->type.workingpressure.mbar = value.toInt();
|
||||
break;
|
||||
case START:
|
||||
cyl->start.mbar = value.toInt();
|
||||
break;
|
||||
case END:
|
||||
cyl->end.mbar = value.toInt();
|
||||
break;
|
||||
case O2:
|
||||
}
|
||||
break;
|
||||
case WORKINGPRESS:
|
||||
if (CHANGED(toDouble, "psi", "bar")) {
|
||||
if (value.toDouble() != 0.0) {
|
||||
if (prefs.units.pressure == prefs.units.PSI)
|
||||
cyl->type.workingpressure.mbar = psi_to_mbar(value.toDouble());
|
||||
else
|
||||
cyl->type.workingpressure.mbar = value.toDouble() * 1000;
|
||||
mark_divelist_changed(TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case START:
|
||||
if (CHANGED(toDouble, "psi", "bar")) {
|
||||
if (value.toDouble() != 0.0) {
|
||||
if (prefs.units.pressure == prefs.units.PSI)
|
||||
cyl->start.mbar = psi_to_mbar(value.toDouble());
|
||||
else
|
||||
cyl->start.mbar = value.toDouble() * 1000;
|
||||
mark_divelist_changed(TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
if (CHANGED(toDouble, "psi", "bar")) {
|
||||
if (value.toDouble() != 0.0) {
|
||||
if (prefs.units.pressure == prefs.units.PSI)
|
||||
cyl->end.mbar = psi_to_mbar(value.toDouble());
|
||||
else
|
||||
cyl->end.mbar = value.toDouble() * 1000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case O2:
|
||||
if (CHANGED(toInt, "%", "%")) {
|
||||
cyl->gasmix.o2.permille = value.toInt() * 10 - 5;
|
||||
break;
|
||||
case HE:
|
||||
mark_divelist_changed(TRUE);
|
||||
}
|
||||
break;
|
||||
case HE:
|
||||
if (CHANGED(toInt, "%", "%")) {
|
||||
cyl->gasmix.he.permille = value.toInt() * 10 - 5;
|
||||
break;
|
||||
mark_divelist_changed(TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
int CylindersModel::rowCount(const QModelIndex& parent) const
|
||||
|
|
|
@ -38,7 +38,7 @@ private:
|
|||
class CylindersModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Column {REMOVE, TYPE, SIZE, MAXPRESS, START, END, O2, HE, COLUMNS};
|
||||
enum Column {REMOVE, TYPE, SIZE, WORKINGPRESS, START, END, O2, HE, COLUMNS};
|
||||
|
||||
explicit CylindersModel(QObject* parent = 0);
|
||||
/*reimp*/ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue