QVariant TankInfoModel::data(const QModelIndex& index, int role) const { QVariant ret; if (!index.isValid()) { return ret; } if (role == Qt::FontRole){ return defaultModelFont(); } if (role == Qt::DisplayRole || role == Qt::EditRole) { struct tank_info_t *info = &tank_info[index.row()]; int ml = info->ml; double bar = (info->psi) ? psi_to_bar(info->psi) : info->bar; if (info->cuft && info->psi) ml = cuft_to_l(info->cuft) * 1000 / bar_to_atm(bar); switch(index.column()) { case BAR: ret = bar * 1000; break; case ML: ret = ml; break; case DESCRIPTION: ret = QString(info->name); break; } } return ret; }
/* * Uemis water_pressure. In centibar. And when converting to * depth, I'm just going to always use saltwater, because I * think "true depth" is just stupid. From a diving standpoint, * "true depth" is pretty much completely pointless, unless * you're doing some kind of underwater surveying work. * * So I give water depths in "pressure depth", always assuming * salt water. So one atmosphere per 10m. */ static void water_pressure(char *buffer, void *_depth) { depth_t *depth = _depth; union int_or_float val; double atm, cm; switch (integer_or_float(buffer, &val)) { case FLOAT: if (!val.fp) break; /* cbar to atm */ atm = bar_to_atm(val.fp * 10); /* * atm to cm. Why not mm? The precision just isn't * there. */ cm = 100 * atm + 0.5; if (cm > 0) { depth->mm = 10 * (long)cm; break; } default: fprintf(stderr, "Strange water pressure '%s'\n", buffer); } free(buffer); }
/* Imperial cylinder volumes need working pressure to be meaningful */ volume_t string_to_volume(const char *str, pressure_t workp) { const char *end; double value = strtod_flags(str, &end, 0); QString rest = QString(end).trimmed(); QString local_l = QObject::tr("l"); QString local_cuft = QObject::tr("cuft"); volume_t volume; if (rest.startsWith("l") || rest.startsWith("ℓ") || rest.startsWith(local_l)) goto l; if (rest.startsWith("cuft") || rest.startsWith(local_cuft)) goto cuft; /* * If we don't have explicit units, and there is no working * pressure, we're going to assume "liter" even in imperial * measurements. */ if (!workp.mbar) goto l; if (prefs.units.volume == prefs.units.LITER) goto l; cuft: if (workp.mbar) value /= bar_to_atm(workp.mbar / 1000.0); value = cuft_to_l(value); l: volume.mliter = rint(value * 1000); return volume; }
QString get_volume_string(volume_t volume, bool showunit, unsigned int mbar) { if (prefs.units.volume == units::LITER) { double liter = volume.mliter / 1000.0; return QString("%1%2").arg(liter, 0, 'f', liter >= 40.0 ? 0 : 1).arg(showunit ? translate("gettextFromC", "l") : ""); } else { double cuft = ml_to_cuft(volume.mliter); if (mbar) cuft *= bar_to_atm(mbar / 1000.0); return QString("%1%2").arg(cuft, 0, 'f', cuft >= 20.0 ? 0 : (cuft >= 2.0 ? 1 : 2)).arg(showunit ? translate("gettextFromC", "cuft") : ""); } }
QString get_volume_string(volume_t volume, bool showunit, int mbar) { const char *unit; int decimals; double value = get_volume_units(volume.mliter, &decimals, &unit); if (mbar) { // we are showing a tank size // fix the weird imperial way of denominating size and provide // reasonable number of decimals if (prefs.units.volume == units::CUFT) value *= bar_to_atm(mbar / 1000.0); decimals = (value > 20.0) ? 0 : (value > 2.0) ? 1 : 2; } return QString("%1%2").arg(value, 0, 'f', decimals).arg(showunit ? unit : ""); }
/* if a default cylinder is set, use that */ void fill_default_cylinder(cylinder_t *cyl) { const char *cyl_name = prefs.default_cylinder; struct tank_info_t *ti = tank_info; pressure_t pO2 = {.mbar = 1600}; if (!cyl_name) return; while (ti->name != NULL) { if (strcmp(ti->name, cyl_name) == 0) break; ti++; } if (ti->name == NULL) /* didn't find it */ return; cyl->type.description = strdup(ti->name); if (ti->ml) { cyl->type.size.mliter = ti->ml; cyl->type.workingpressure.mbar = ti->bar * 1000; } else { cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); if (ti->psi) cyl->type.size.mliter = cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi)); } // MOD of air cyl->depth = gas_mod(&cyl->gasmix, pO2, 1); } /* make sure that the gas we are switching to is represented in our * list of cylinders */ static int verify_gas_exists(struct gasmix mix_in) { int i; cylinder_t *cyl; for (i = 0; i < MAX_CYLINDERS; i++) { cyl = displayed_dive.cylinder + i; if (cylinder_nodata(cyl)) continue; if (gasmix_distance(&cyl->gasmix, &mix_in) < 200) return i; } fprintf(stderr, "this gas %s should have been on the cylinder list\nThings will fail now\n", gasname(&mix_in)); return -1; }
static void convert_volume_pressure(int ml, int mbar, double *v, double *p) { double volume, pressure; volume = ml / 1000.0; if (mbar) { if (output_units.volume == CUFT) { volume = ml_to_cuft(ml); volume *= bar_to_atm(mbar / 1000.0); } if (output_units.pressure == PSI) { pressure = mbar_to_PSI(mbar); } else pressure = mbar / 1000.0; } *v = volume; *p = pressure; }
QString get_cylinder_used_gas_string(cylinder_t *cyl, bool showunit) { int decimals; const char *unit; double gas_usage; /* Get the cylinder gas use in mbar */ gas_usage = start_pressure(cyl) - end_pressure(cyl); /* Can we turn it into a volume? */ if (cyl->type.size.mliter) { gas_usage = bar_to_atm(gas_usage / 1000); gas_usage *= cyl->type.size.mliter; gas_usage = get_volume_units(gas_usage, &decimals, &unit); } else { gas_usage = get_pressure_units(gas_usage, &unit); decimals = 0; } // translate("gettextFromC","%.*f %s" return QString("%1 %2").arg(gas_usage, 0, 'f', decimals).arg(showunit ? unit : ""); }
void TestUnitConversion::testUnitConversions() { QCOMPARE(IS_FP_SAME(grams_to_lbs(1000), 2.204586), true); QCOMPARE(lbs_to_grams(1), 454); QCOMPARE(IS_FP_SAME(ml_to_cuft(1000), 0.0353147), true); QCOMPARE(IS_FP_SAME(cuft_to_l(1), 28.316847), true); QCOMPARE(IS_FP_SAME(mm_to_feet(1000), 3.280840), true); QCOMPARE(feet_to_mm(1), (long unsigned int) 305); QCOMPARE(to_feet((depth_t){ 1000 }), 3); QCOMPARE(IS_FP_SAME(mkelvin_to_C(647000), 373.85), true); QCOMPARE(IS_FP_SAME(mkelvin_to_F(647000), 704.93), true); QCOMPARE(F_to_mkelvin(704.93), (unsigned long)647000); QCOMPARE(C_to_mkelvin(373.85), (unsigned long)647000); QCOMPARE(IS_FP_SAME(psi_to_bar(14.6959488), 1.01325), true); QCOMPARE(psi_to_mbar(14.6959488), (long)1013); QCOMPARE(to_PSI((pressure_t){ 1013 }), (int)15); QCOMPARE(IS_FP_SAME(bar_to_atm(1.013), 1.0), true); QCOMPARE(IS_FP_SAME(mbar_to_atm(1013), 1.0), true); QCOMPARE(mbar_to_PSI(1013), (int)15); get_units(); }
static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl, const char *desc, double volume, double pressure, double start, double end, int o2, int he) { int mbar, ml; if (output_units.pressure == PSI) { pressure = psi_to_bar(pressure); start = psi_to_bar(start); end = psi_to_bar(end); } if (pressure && output_units.volume == CUFT) { volume = cuft_to_l(volume); volume /= bar_to_atm(pressure); } ml = volume * 1000 + 0.5; mbar = pressure * 1000 + 0.5; /* Ignore obviously crazy He values */ if (o2 + he > 1000) he = 0; /* We have a rule that normal air is all zeroes */ if (!he && o2 > 208 && o2 < 211) o2 = 0; cyl->type.description = desc; cyl->type.size.mliter = ml; cyl->type.workingpressure.mbar = mbar; cyl->start.mbar = start * 1000 + 0.5; cyl->end.mbar = end * 1000 + 0.5; cyl->gasmix.o2.permille = o2; cyl->gasmix.he.permille = he; /* * Also, insert it into the model if it doesn't already exist */ add_cylinder(cylinder, desc, ml, mbar); }
QVariant CylindersModel::data(const QModelIndex& index, int role) const { QVariant ret; if (!index.isValid() || index.row() >= MAX_CYLINDERS) return ret; cylinder_t *cyl = ¤t->cylinder[index.row()]; switch (role) { case Qt::FontRole: { QFont font = defaultModelFont(); switch (index.column()) { case START: font.setItalic(!cyl->start.mbar); break; case END: font.setItalic(!cyl->end.mbar); break; } ret = font; break; } case Qt::TextAlignmentRole: ret = Qt::AlignCenter; break; case Qt::DisplayRole: case Qt::EditRole: switch(index.column()) { case TYPE: ret = QString(cyl->type.description); break; 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) { double volume; int mbar = cyl->type.workingpressure.mbar; if (mbar && prefs.units.volume == prefs.units.CUFT) { volume = ml_to_cuft(cyl->type.size.mliter); volume *= bar_to_atm(mbar / 1000.0); } else { volume = cyl->type.size.mliter / 1000.0; } ret = QString("%1").arg(volume, 0, 'f', 1); } break; case WORKINGPRESS: if (cyl->type.workingpressure.mbar) ret = get_pressure_string(cyl->type.workingpressure, TRUE); break; case START: if (cyl->start.mbar) ret = get_pressure_string(cyl->start, FALSE); else if (cyl->sample_start.mbar) ret = get_pressure_string(cyl->sample_start, FALSE); break; case END: if (cyl->end.mbar) ret = get_pressure_string(cyl->end, FALSE); else if (cyl->sample_end.mbar) ret = get_pressure_string(cyl->sample_end, FALSE); break; case O2: ret = percent_string(cyl->gasmix.o2); break; case HE: ret = percent_string(cyl->gasmix.he); break; case DEPTH: if (prefs.units.length == prefs.units.FEET) ret = mm_to_feet(cyl->depth.mm); else ret = cyl->depth.mm / 1000; break; } break; case Qt::DecorationRole: if (index.column() == REMOVE) ret = QIcon(":trash"); break; case Qt::ToolTipRole: if (index.column() == REMOVE) ret = tr("Clicking here will remove this cylinder."); break; } return ret; }
bool CylindersModel::setData(const QModelIndex& index, const QVariant& value, int role) { bool addDiveMode = DivePlannerPointsModel::instance()->currentMode() != DivePlannerPointsModel::NOTHING; if (addDiveMode) DivePlannerPointsModel::instance()->rememberTanks(); cylinder_t *cyl = cylinderAt(index); switch(index.column()) { case TYPE: if (!value.isNull()) { QByteArray ba = value.toByteArray(); const char *text = ba.constData(); if (!cyl->type.description || strcmp(cyl->type.description, text)) { cyl->type.description = strdup(text); changed = true; } } 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) { TankInfoModel *tanks = TankInfoModel::instance(); QModelIndexList matches = tanks->match(tanks->index(0,0), Qt::DisplayRole, cyl->type.description); int mbar = cyl->type.workingpressure.mbar; int mliter; if (mbar && prefs.units.volume == prefs.units.CUFT) { double liters = cuft_to_l(value.toDouble()); liters /= bar_to_atm(mbar / 1000.0); mliter = rint(liters * 1000); } else { mliter = rint(value.toDouble() * 1000); } if (cyl->type.size.mliter != mliter) { mark_divelist_changed(TRUE); cyl->type.size.mliter = mliter; if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::ML), cyl->type.size.mliter); } changed = true; } } break; case WORKINGPRESS: if (CHANGED(toDouble, "psi", "bar")) { QString vString = value.toString(); vString.remove("psi").remove("bar"); if (vString.toDouble() != 0.0) { TankInfoModel *tanks = TankInfoModel::instance(); QModelIndexList matches = tanks->match(tanks->index(0,0), Qt::DisplayRole, cyl->type.description); if (prefs.units.pressure == prefs.units.PSI) cyl->type.workingpressure.mbar = psi_to_mbar(vString.toDouble()); else cyl->type.workingpressure.mbar = vString.toDouble() * 1000; if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::BAR), cyl->type.workingpressure.mbar / 1000.0); 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; 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; changed = true; } } break; case O2: if (CHANGED(toDouble, "%", "%")) { int o2 = value.toString().remove('%').toDouble() * 10 + 0.5; if (cyl->gasmix.he.permille + o2 <= 1000) { cyl->gasmix.o2.permille = o2; changed = true; } } break; case HE: if (CHANGED(toDouble, "%", "%")) { int he = value.toString().remove('%').toDouble() * 10 + 0.5; if (cyl->gasmix.o2.permille + he <= 1000) { cyl->gasmix.he.permille = he; changed = true; } } break; case DEPTH: if (CHANGED(toDouble, "ft", "m")) { if (value.toInt() != 0) { if (prefs.units.length == prefs.units.FEET) cyl->depth.mm = feet_to_mm(value.toString().remove("ft").remove("m").toInt()); else cyl->depth.mm = value.toString().remove("ft").remove("m").toInt() * 1000; } } } dataChanged(index, index); if (addDiveMode) DivePlannerPointsModel::instance()->tanksUpdated(); return true; }
bool CylindersModel::setData(const QModelIndex& index, const QVariant& value, int role) { cylinder_t *cyl = ¤t->cylinder[index.row()]; switch(index.column()) { case TYPE: if (!value.isNull()) { QByteArray ba = value.toByteArray(); const char *text = ba.constData(); if (!cyl->type.description || strcmp(cyl->type.description, text)) { cyl->type.description = strdup(text); mark_divelist_changed(TRUE); } } 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) { TankInfoModel *tanks = TankInfoModel::instance(); QModelIndexList matches = tanks->match(tanks->index(0,0), Qt::DisplayRole, cyl->type.description); int mbar = cyl->type.workingpressure.mbar; int mliter; if (mbar && prefs.units.volume == prefs.units.CUFT) { double liters = cuft_to_l(value.toDouble()); liters /= bar_to_atm(mbar / 1000.0); mliter = rint(liters * 1000); } else { mliter = rint(value.toDouble() * 1000); } if (cyl->type.size.mliter != mliter) { mark_divelist_changed(TRUE); cyl->type.size.mliter = mliter; if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::ML), cyl->type.size.mliter); } } } break; case WORKINGPRESS: if (CHANGED(toDouble, "psi", "bar")) { if (value.toDouble() != 0.0) { TankInfoModel *tanks = TankInfoModel::instance(); QModelIndexList matches = tanks->match(tanks->index(0,0), Qt::DisplayRole, cyl->type.description); if (prefs.units.pressure == prefs.units.PSI) cyl->type.workingpressure.mbar = psi_to_mbar(value.toDouble()); else cyl->type.workingpressure.mbar = value.toDouble() * 1000; if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::BAR), cyl->type.workingpressure.mbar / 1000.0); 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(toDouble, "%", "%")) { cyl->gasmix.o2.permille = value.toDouble() * 10 + 0.5; mark_divelist_changed(TRUE); } break; case HE: if (CHANGED(toDouble, "%", "%")) { cyl->gasmix.he.permille = value.toDouble() * 10 + 0.5; mark_divelist_changed(TRUE); } break; } return QAbstractItemModel::setData(index, value, role); }