Equipment: Include Unused Tanks in Merge if Preference is Enabled.

Include unused tanks in merges of multiple logs into a single dive if
the 'Show unused cylinders' preference is enabled.
Also rename the preference (in code) to `include_unused_tanks` to
reflect the fact that it is already used in more places than just the
display (exporting, cloning dives).
Simplified the cylinder model to make forced inclusion of unused tanks
dependent on use of the model in planner.
Leaving the persisted name of the preference as `display_unused_tanks`
to avoid resetting this for all users - is there a good way to migrate
preference names?

Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
Michael Keller 2023-07-09 12:14:27 +12:00
parent cb6f768865
commit 5fae7ce7a0
17 changed files with 50 additions and 47 deletions

View file

@ -1,4 +1,5 @@
equipment: mark gas mixes reported by the dive computer as 'inactive' as 'not used' equipment: mark gas mixes reported by the dive computer as 'inactive' as 'not used'
equipment: include unused cylinders in merged dive if the preference is enabled
desktop: added button to hide the infobox in the dive profile desktop: added button to hide the infobox in the dive profile
desktop: use persisted device information for the dive computer configuration desktop: use persisted device information for the dive computer configuration
core: fix bug using salinity and pressure values in mbar <-> depth conversion core: fix bug using salinity and pressure values in mbar <-> depth conversion

View file

@ -3654,6 +3654,8 @@ image::images/Pref_eqpmnt.jpg["FIGURE: Preferences: equipment",align="center"]
** *Show unused cylinders*: Checking this checkbox allows showing all cylinders entered for a dive ** *Show unused cylinders*: Checking this checkbox allows showing all cylinders entered for a dive
in the Cylinder Table of the *Equipment* tab, even if one or more cylinders were actually not used. in the Cylinder Table of the *Equipment* tab, even if one or more cylinders were actually not used.
This will also include unused cylinders in data exports and when dives are cloned for the planner
or merged into one dive.
=== Media === Media

View file

@ -213,7 +213,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
qty_cyl = 0; qty_cyl = 0;
for (i = 0; i < dive->cylinders.nr; i++){ for (i = 0; i < dive->cylinders.nr; i++){
const cylinder_t &cyl = *get_cylinder(dive, i); const cylinder_t &cyl = *get_cylinder(dive, i);
if (is_cylinder_used(dive, i) || (prefs.display_unused_tanks && cyl.type.description)){ if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && cyl.type.description)){
put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description); put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description);
put_format(&buf, "\\def\\%scyl%cgasname{%s}\n", ssrf, 'a' + i, gasname(cyl.gasmix)); put_format(&buf, "\\def\\%scyl%cgasname{%s}\n", ssrf, 'a' + i, gasname(cyl.gasmix));
put_format(&buf, "\\def\\%scyl%cmixO2{%.1f\\%%}\n", ssrf, 'a' + i, get_o2(cyl.gasmix)/10.0); put_format(&buf, "\\def\\%scyl%cmixO2{%.1f\\%%}\n", ssrf, 'a' + i, get_o2(cyl.gasmix)/10.0);

View file

@ -1908,7 +1908,7 @@ static bool cylinder_in_use(const struct dive *dive, int idx)
return false; return false;
/* This tests for gaschange events or pressure changes */ /* This tests for gaschange events or pressure changes */
if (is_cylinder_used(dive, idx)) if (is_cylinder_used(dive, idx) || prefs.include_unused_tanks)
return true; return true;
/* This tests for typenames or gas contents */ /* This tests for typenames or gas contents */

View file

@ -40,7 +40,7 @@ struct preferences default_prefs = {
.mobile_scale = 1.0, .mobile_scale = 1.0,
.display_invalid_dives = false, .display_invalid_dives = false,
.show_sac = false, .show_sac = false,
.display_unused_tanks = false, .include_unused_tanks = false,
.display_default_tank_infos = true, .display_default_tank_infos = true,
.show_average_depth = true, .show_average_depth = true,
.show_icd = false, .show_icd = false,

View file

@ -109,7 +109,7 @@ struct preferences {
// ********** Equipment tab ******* // ********** Equipment tab *******
const char *default_cylinder; const char *default_cylinder;
bool display_unused_tanks; bool include_unused_tanks;
bool display_default_tank_infos; bool display_default_tank_infos;
// ********** General ********** // ********** General **********

View file

@ -13,10 +13,11 @@ qPrefEquipment *qPrefEquipment::instance()
void qPrefEquipment::loadSync(bool doSync) void qPrefEquipment::loadSync(bool doSync)
{ {
disk_default_cylinder(doSync); disk_default_cylinder(doSync);
disk_display_unused_tanks(doSync); disk_include_unused_tanks(doSync);
disk_display_default_tank_infos(doSync); disk_display_default_tank_infos(doSync);
} }
HANDLE_PREFERENCE_TXT(Equipment, "default_cylinder", default_cylinder); HANDLE_PREFERENCE_TXT(Equipment, "default_cylinder", default_cylinder);
HANDLE_PREFERENCE_BOOL(Equipment, "display_unused_tanks", display_unused_tanks); // Keeping the persisted preference name the same to avoid resetting this for everybody
HANDLE_PREFERENCE_BOOL(Equipment, "display_unused_tanks", include_unused_tanks);
HANDLE_PREFERENCE_BOOL(Equipment, "display_default_tank_infos", display_default_tank_infos); HANDLE_PREFERENCE_BOOL(Equipment, "display_default_tank_infos", display_default_tank_infos);

View file

@ -8,7 +8,7 @@
class qPrefEquipment : public QObject { class qPrefEquipment : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString default_cylinder READ default_cylinder WRITE set_default_cylinder NOTIFY default_cylinderChanged) Q_PROPERTY(QString default_cylinder READ default_cylinder WRITE set_default_cylinder NOTIFY default_cylinderChanged)
Q_PROPERTY(bool display_unused_tanks READ display_unused_tanks WRITE set_display_unused_tanks NOTIFY display_unused_tanksChanged) Q_PROPERTY(bool include_unused_tanks READ include_unused_tanks WRITE set_include_unused_tanks NOTIFY include_unused_tanksChanged)
Q_PROPERTY(bool display_default_tank_infos READ display_default_tank_infos WRITE set_display_default_tank_infos NOTIFY display_default_tank_infosChanged) Q_PROPERTY(bool display_default_tank_infos READ display_default_tank_infos WRITE set_display_default_tank_infos NOTIFY display_default_tank_infosChanged)
public: public:
@ -21,23 +21,23 @@ public:
public: public:
static QString default_cylinder() { return prefs.default_cylinder; } static QString default_cylinder() { return prefs.default_cylinder; }
static bool display_unused_tanks() { return prefs.display_unused_tanks; } static bool include_unused_tanks() { return prefs.include_unused_tanks; }
static bool display_default_tank_infos() { return prefs.display_default_tank_infos; } static bool display_default_tank_infos() { return prefs.display_default_tank_infos; }
public slots: public slots:
static void set_default_cylinder(const QString& value); static void set_default_cylinder(const QString& value);
static void set_display_unused_tanks(bool value); static void set_include_unused_tanks(bool value);
static void set_display_default_tank_infos(bool value); static void set_display_default_tank_infos(bool value);
signals: signals:
void default_cylinderChanged(const QString& value); void default_cylinderChanged(const QString& value);
void display_unused_tanksChanged(bool value); void include_unused_tanksChanged(bool value);
void display_default_tank_infosChanged(bool value); void display_default_tank_infosChanged(bool value);
private: private:
qPrefEquipment() {} qPrefEquipment() {}
static void disk_default_cylinder(bool doSync); static void disk_default_cylinder(bool doSync);
static void disk_display_unused_tanks(bool doSync); static void disk_include_unused_tanks(bool doSync);
static void disk_display_default_tank_infos(bool doSync); static void disk_display_default_tank_infos(bool doSync);
}; };

View file

@ -152,7 +152,7 @@ bool uploadDiveLogsDE::prepareDives(const QString &tempfile, bool selected)
return false; return false;
} }
xml_params_add_int(params, "allcylinders", prefs.display_unused_tanks); xml_params_add_int(params, "allcylinders", prefs.include_unused_tanks);
transformed = xsltApplyStylesheet(xslt, doc, xml_params_get(params)); transformed = xsltApplyStylesheet(xslt, doc, xml_params_get(params));
free_xml_params(params); free_xml_params(params);
if (!transformed) { if (!transformed) {

View file

@ -23,7 +23,7 @@ PreferencesEquipment::~PreferencesEquipment()
void PreferencesEquipment::refreshSettings() void PreferencesEquipment::refreshSettings()
{ {
ui->display_unused_tanks->setChecked(prefs.display_unused_tanks); ui->include_unused_tanks->setChecked(prefs.include_unused_tanks);
ui->display_default_tank_infos->setChecked(prefs.display_default_tank_infos); ui->display_default_tank_infos->setChecked(prefs.display_default_tank_infos);
ui->default_cylinder->clear(); ui->default_cylinder->clear();
for (int i = 0; i < tank_info_table.nr; i++) { for (int i = 0; i < tank_info_table.nr; i++) {
@ -37,7 +37,7 @@ void PreferencesEquipment::refreshSettings()
void PreferencesEquipment::syncSettings() void PreferencesEquipment::syncSettings()
{ {
auto equipment = qPrefEquipment::instance(); auto equipment = qPrefEquipment::instance();
qPrefEquipment::set_display_unused_tanks(ui->display_unused_tanks->isChecked()); qPrefEquipment::set_include_unused_tanks(ui->include_unused_tanks->isChecked());
qPrefEquipment::set_display_default_tank_infos(ui->display_default_tank_infos->isChecked()); qPrefEquipment::set_display_default_tank_infos(ui->display_default_tank_infos->isChecked());
equipment->set_default_cylinder(ui->default_cylinder->currentText()); equipment->set_default_cylinder(ui->default_cylinder->currentText());

View file

@ -62,9 +62,9 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="display_unused_tanks"> <widget class="QCheckBox" name="include_unused_tanks">
<property name="text"> <property name="text">
<string>Show unused cylinders in the Cylinders table of the Equipment tab</string> <string>Show unused cylinders in the Cylinders table of the Equipment tab and include them in export / copy / merge</string>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -29,7 +29,7 @@ static bool hiddenByDefault(int i)
} }
TabDiveEquipment::TabDiveEquipment(MainTab *parent) : TabBase(parent), TabDiveEquipment::TabDiveEquipment(MainTab *parent) : TabBase(parent),
cylindersModel(new CylindersModel(false, true, this)), cylindersModel(new CylindersModel(false, this)),
weightModel(new WeightModel(this)) weightModel(new WeightModel(this))
{ {
QCompleter *suitCompleter; QCompleter *suitCompleter;

View file

@ -13,10 +13,9 @@
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include <string> #include <string>
CylindersModel::CylindersModel(bool planner, bool hideUnused, QObject *parent) : CleanerTableModel(parent), CylindersModel::CylindersModel(bool planner, QObject *parent) : CleanerTableModel(parent),
d(nullptr), d(nullptr),
inPlanner(planner), inPlanner(planner),
hideUnused(hideUnused),
numRows(0), numRows(0),
tempRow(-1), tempRow(-1),
tempCyl(empty_cylinder) tempCyl(empty_cylinder)
@ -134,13 +133,14 @@ static QVariant percent_string(fraction_t fraction)
return QString("%L1%").arg(permille / 10.0, 0, 'f', 1); return QString("%L1%").arg(permille / 10.0, 0, 'f', 1);
} }
// Calculate the number of displayed cylinders: If hideUnused // Calculate the number of displayed cylinders: If we are in planner
// is set, we don't show unused cylinders at the end of the list. // or prefs.include_unused_tanks is set we show unused cylinders
// at the end of the list.
int CylindersModel::calcNumRows() const int CylindersModel::calcNumRows() const
{ {
if (!d) if (!d)
return 0; return 0;
if (!hideUnused || prefs.display_unused_tanks) if (inPlanner || prefs.include_unused_tanks)
return d->cylinders.nr; return d->cylinders.nr;
return first_hidden_cylinder(d); return first_hidden_cylinder(d);
} }

View file

@ -36,7 +36,7 @@ public:
COMMIT_ROLE, // Save the temporary data to the dive. Must be set with Column == TYPE. COMMIT_ROLE, // Save the temporary data to the dive. Must be set with Column == TYPE.
REVERT_ROLE // Revert to original data from dive. Must be set with Column == TYPE. REVERT_ROLE // Revert to original data from dive. Must be set with Column == TYPE.
}; };
explicit CylindersModel(bool planner, bool hideUnused, QObject *parent = 0); // First argument: true if this model is used for the planner explicit CylindersModel(bool planner, QObject *parent = 0); // First argument: true if this model is used for the planner
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
@ -67,7 +67,6 @@ private:
dive *d; dive *d;
int dcNr; int dcNr;
bool inPlanner; bool inPlanner;
bool hideUnused;
int numRows; // Does not include unused cylinders at the end int numRows; // Does not include unused cylinders at the end
// Used if we temporarily change a line because the user is selecting a weight type // Used if we temporarily change a line because the user is selecting a weight type
int tempRow; int tempRow;

View file

@ -191,7 +191,7 @@ void DivePlannerPointsModel::setupCylinders()
clear_cylinder_table(&d->cylinders); clear_cylinder_table(&d->cylinders);
if (mode == PLAN && current_dive) { if (mode == PLAN && current_dive) {
// take the displayed cylinders from the selected dive as starting point // take the displayed cylinders from the selected dive as starting point
copy_used_cylinders(current_dive, d, !prefs.display_unused_tanks); copy_used_cylinders(current_dive, d, !prefs.include_unused_tanks);
reset_cylinders(d, true); reset_cylinders(d, true);
if (d->cylinders.nr > 0) { if (d->cylinders.nr > 0) {
@ -445,7 +445,7 @@ int DivePlannerPointsModel::rowCount(const QModelIndex&) const
DivePlannerPointsModel::DivePlannerPointsModel(QObject *parent) : QAbstractTableModel(parent), DivePlannerPointsModel::DivePlannerPointsModel(QObject *parent) : QAbstractTableModel(parent),
d(nullptr), d(nullptr),
cylinders(true, false), cylinders(true),
mode(NOTHING) mode(NOTHING)
{ {
memset(&diveplan, 0, sizeof(diveplan)); memset(&diveplan, 0, sizeof(diveplan));

View file

@ -24,8 +24,8 @@ void TestQPrefEquipment::test_struct_get()
auto tst = qPrefEquipment::instance(); auto tst = qPrefEquipment::instance();
prefs.default_cylinder = copy_qstring("new base11"); prefs.default_cylinder = copy_qstring("new base11");
QCOMPARE(tst->default_cylinder(), QString(prefs.default_cylinder)); QCOMPARE(tst->default_cylinder(), QString(prefs.default_cylinder));
prefs.display_unused_tanks = true; prefs.include_unused_tanks = true;
QCOMPARE(tst->display_unused_tanks(), prefs.display_unused_tanks); QCOMPARE(tst->include_unused_tanks(), prefs.include_unused_tanks);
} }
void TestQPrefEquipment::test_set_struct() void TestQPrefEquipment::test_set_struct()
@ -35,8 +35,8 @@ void TestQPrefEquipment::test_set_struct()
auto tst = qPrefEquipment::instance(); auto tst = qPrefEquipment::instance();
tst->set_default_cylinder("new base21"); tst->set_default_cylinder("new base21");
QCOMPARE(QString(prefs.default_cylinder), QString("new base21")); QCOMPARE(QString(prefs.default_cylinder), QString("new base21"));
tst->set_display_unused_tanks(false); tst->set_include_unused_tanks(false);
QCOMPARE(prefs.display_unused_tanks, false); QCOMPARE(prefs.include_unused_tanks, false);
} }
void TestQPrefEquipment::test_set_load_struct() void TestQPrefEquipment::test_set_load_struct()
@ -47,11 +47,11 @@ void TestQPrefEquipment::test_set_load_struct()
tst->set_default_cylinder("new base31"); tst->set_default_cylinder("new base31");
prefs.default_cylinder = copy_qstring("error"); prefs.default_cylinder = copy_qstring("error");
tst->set_display_unused_tanks(false); tst->set_include_unused_tanks(false);
prefs.display_unused_tanks = true; prefs.include_unused_tanks = true;
tst->load(); tst->load();
QCOMPARE(QString(prefs.default_cylinder), QString("new base31")); QCOMPARE(QString(prefs.default_cylinder), QString("new base31"));
QCOMPARE(prefs.display_unused_tanks, false); QCOMPARE(prefs.include_unused_tanks, false);
} }
void TestQPrefEquipment::test_struct_disk() void TestQPrefEquipment::test_struct_disk()
@ -60,15 +60,15 @@ void TestQPrefEquipment::test_struct_disk()
auto tst = qPrefEquipment::instance(); auto tst = qPrefEquipment::instance();
prefs.default_cylinder = copy_qstring("base41"); prefs.default_cylinder = copy_qstring("base41");
prefs.display_unused_tanks = true; prefs.include_unused_tanks = true;
tst->sync(); tst->sync();
prefs.default_cylinder = copy_qstring("error"); prefs.default_cylinder = copy_qstring("error");
prefs.display_unused_tanks = false; prefs.include_unused_tanks = false;
tst->load(); tst->load();
QCOMPARE(QString(prefs.default_cylinder), QString("base41")); QCOMPARE(QString(prefs.default_cylinder), QString("base41"));
QCOMPARE(prefs.display_unused_tanks, true); QCOMPARE(prefs.include_unused_tanks, true);
} }
@ -85,17 +85,17 @@ void TestQPrefEquipment::test_oldPreferences()
TEST(equipment->default_cylinder(), QStringLiteral("cylinder_2")); TEST(equipment->default_cylinder(), QStringLiteral("cylinder_2"));
equipment->set_default_cylinder("cylinder_1"); equipment->set_default_cylinder("cylinder_1");
TEST(equipment->default_cylinder(), QStringLiteral("cylinder_1")); TEST(equipment->default_cylinder(), QStringLiteral("cylinder_1"));
equipment->set_display_unused_tanks(true); equipment->set_include_unused_tanks(true);
TEST(equipment->display_unused_tanks(), true); TEST(equipment->include_unused_tanks(), true);
equipment->set_display_unused_tanks(false); equipment->set_include_unused_tanks(false);
TEST(equipment->display_unused_tanks(), false); TEST(equipment->include_unused_tanks(), false);
} }
void TestQPrefEquipment::test_signals() void TestQPrefEquipment::test_signals()
{ {
qPrefEquipment::set_default_cylinder("signal test"); qPrefEquipment::set_default_cylinder("signal test");
QSignalSpy spy1(qPrefEquipment::instance(), &qPrefEquipment::default_cylinderChanged); QSignalSpy spy1(qPrefEquipment::instance(), &qPrefEquipment::default_cylinderChanged);
QSignalSpy spy2(qPrefEquipment::instance(), &qPrefEquipment::display_unused_tanksChanged); QSignalSpy spy2(qPrefEquipment::instance(), &qPrefEquipment::include_unused_tanksChanged);
// set default cylinder to same value it already had // set default cylinder to same value it already had
qPrefEquipment::set_default_cylinder("signal test"); qPrefEquipment::set_default_cylinder("signal test");
@ -106,8 +106,8 @@ void TestQPrefEquipment::test_signals()
QCOMPARE(spy1.count(), 1); QCOMPARE(spy1.count(), 1);
QVERIFY(spy1.takeFirst().at(0).toBool() == true); QVERIFY(spy1.takeFirst().at(0).toBool() == true);
prefs.display_unused_tanks = true; prefs.include_unused_tanks = true;
qPrefEquipment::set_display_unused_tanks(false); qPrefEquipment::set_include_unused_tanks(false);
QCOMPARE(spy2.count(), 1); QCOMPARE(spy2.count(), 1);
QVERIFY(spy2.takeFirst().at(0).toBool() == false); QVERIFY(spy2.takeFirst().at(0).toBool() == false);
} }

View file

@ -30,9 +30,9 @@ TestCase {
//TBD PrefTechnicalDetails.display_deco_mode = BUEHLMANN //TBD PrefTechnicalDetails.display_deco_mode = BUEHLMANN
//TBD compare(PrefTechnicalDetails.display_deco_mode, BUEHLMANN) //TBD compare(PrefTechnicalDetails.display_deco_mode, BUEHLMANN)
var x07 = PrefTechnicalDetails.display_unused_tanks var x07 = PrefTechnicalDetails.include_unused_tanks
PrefTechnicalDetails.display_unused_tanks = true PrefTechnicalDetails.include_unused_tanks = true
compare(PrefTechnicalDetails.display_unused_tanks, true) compare(PrefTechnicalDetails.include_unused_tanks, true)
var x08 = PrefTechnicalDetails.ead var x08 = PrefTechnicalDetails.ead
PrefTechnicalDetails.ead = true PrefTechnicalDetails.ead = true
@ -183,7 +183,7 @@ TestCase {
PrefTechnicalDetails.calcndltts = ! PrefTechnicalDetails.calcndltts PrefTechnicalDetails.calcndltts = ! PrefTechnicalDetails.calcndltts
PrefTechnicalDetails.dcceiling = ! PrefTechnicalDetails.dcceiling PrefTechnicalDetails.dcceiling = ! PrefTechnicalDetails.dcceiling
// 6 does not emit signal // 6 does not emit signal
PrefTechnicalDetails.display_unused_tanks = ! PrefTechnicalDetails.display_unused_tanks PrefTechnicalDetails.include_unused_tanks = ! PrefTechnicalDetails.include_unused_tanks
PrefTechnicalDetails.ead = ! PrefTechnicalDetails.ead PrefTechnicalDetails.ead = ! PrefTechnicalDetails.ead
PrefTechnicalDetails.gfhigh = -27 PrefTechnicalDetails.gfhigh = -27
PrefTechnicalDetails.gflow = -25 PrefTechnicalDetails.gflow = -25