示例#1
0
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;
}
示例#2
0
/*
 * 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);
}
示例#3
0
/* 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;
}
示例#4
0
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") : "");
	}
}
示例#5
0
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 : "");
}
示例#6
0
/* 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;
}
示例#7
0
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;
}
示例#8
0
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();
}
示例#10
0
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);
}
示例#11
0
QVariant CylindersModel::data(const QModelIndex& index, int role) const
{
	QVariant ret;

	if (!index.isValid() || index.row() >= MAX_CYLINDERS)
		return ret;

	cylinder_t *cyl = &current->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;
}
示例#12
0
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;
}
示例#13
0
bool CylindersModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
	cylinder_t *cyl = &current->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);
}