From bf0bd88226508ca9c2dc8941cde82f72cbe1d371 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 8 Nov 2013 18:12:26 +0900 Subject: Correctly identify air Because of rounding issues we need to use our macro to test for air (especially since the events store gas percentages and not gas permille). Signed-off-by: Dirk Hohndel --- qt-ui/diveplanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'qt-ui/diveplanner.cpp') diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index 39db8f431..2b4b1d1d2 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -41,7 +41,7 @@ QStringListModel *airTypes() { } QString strForAir(const divedatapoint& p) { - return p.o2 == 209 ? QObject::tr("AIR") + return is_air(p.o2, p.he) ? QObject::tr("AIR") : p.o2 == 320 ? QObject::tr("EAN32") : p.o2 == 360 ? QObject::tr("EAN36") : QObject::tr("Choose Gas"); -- cgit v1.2.3-70-g09d2 From 1578c1edb2dd7e74b111e6b6b5c7883c37554235 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 8 Nov 2013 18:15:04 +0900 Subject: Be consistent when passing around gas data in the planner We need to make sure that the correct segment has the correct gas assigned to it - and that those gases are correctly tracked when editing a manually added dive as well. Signed-off-by: Dirk Hohndel --- dive.c | 14 +++++++++++++ dive.h | 1 + planner.h | 1 + qt-ui/diveplanner.cpp | 58 ++++++++++++++++++++++++++++++--------------------- qt-ui/diveplanner.h | 2 +- qt-ui/maintab.cpp | 7 +++---- qt-ui/maintab.h | 1 - 7 files changed, 54 insertions(+), 30 deletions(-) (limited to 'qt-ui/diveplanner.cpp') diff --git a/dive.c b/dive.c index 030dfa410..e4bec0314 100644 --- a/dive.c +++ b/dive.c @@ -195,6 +195,20 @@ struct dive *alloc_dive(void) return dive; } +/* only copies events from the first dive computer */ +void copy_events(struct dive *s, struct dive *d) +{ + struct event *ev; + if (!s || !d) + return; + ev = s->dc.events; + d->dc.events = NULL; + while (ev != NULL) { + add_event(&d->dc, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name); + ev = ev->next; + } +} + void copy_cylinders(struct dive *s, struct dive *d) { int i; diff --git a/dive.h b/dive.h index e199f7878..b97ecefc3 100644 --- a/dive.h +++ b/dive.h @@ -653,6 +653,7 @@ extern unsigned int dc_airtemp(struct divecomputer *dc); extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded); extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded); extern void renumber_dives(int nr); +extern void copy_events(struct dive *s, struct dive *d); extern void copy_cylinders(struct dive *s, struct dive *d); extern void copy_samples(struct dive *s, struct dive *d); diff --git a/planner.h b/planner.h index 30dca4f70..caecd513f 100644 --- a/planner.h +++ b/planner.h @@ -11,6 +11,7 @@ extern int validate_po2(const char *text, int *mbar_po2); extern timestamp_t current_time_notz(void); extern void show_planned_dive(char **error_string_p); extern void set_last_stop(bool last_stop_6m); +extern void get_gas_from_events(struct divecomputer *dc, int time, int *o2, int *he); extern struct diveplan diveplan; extern struct dive *planned_dive; diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index 2b4b1d1d2..398d11fc3 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -412,17 +412,16 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event) int minutes = rint(timeLine->valueAt(mappedPos)); int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1); - plannerModel->addStop(milimeters, minutes * 60, tr("Air"), 0); + plannerModel->addStop(milimeters, minutes * 60, O2_IN_AIR, 0, 0); } void DivePlannerPointsModel::createSimpleDive() { - plannerModel->addStop(M_OR_FT(15,45), 1 * 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, 41 * 60, tr("Air"), 0); - plannerModel->addStop(M_OR_FT(5,15), 42 * 60, tr("Air"), 0); - plannerModel->addStop(M_OR_FT(5,15), 45 * 60, tr("Air"), 0); + plannerModel->addStop(0, 0, O2_IN_AIR, 0, 0); + plannerModel->addStop(M_OR_FT(15,45), 1 * 60, O2_IN_AIR, 0, 0); + plannerModel->addStop(M_OR_FT(15,45), 40 * 60, O2_IN_AIR, 0, 0); + plannerModel->addStop(M_OR_FT(5,15), 42 * 60, O2_IN_AIR, 0, 0); + plannerModel->addStop(M_OR_FT(5,15), 45 * 60, O2_IN_AIR, 0, 0); } void DivePlannerPointsModel::loadFromDive(dive* d) @@ -431,14 +430,23 @@ void DivePlannerPointsModel::loadFromDive(dive* d) * as soon as the model is modified, it will * remove all samples from the current dive. * */ + struct dive *backupDive = alloc_dive(); + backupDive->when = current_dive->when; // do we need anything else? + copy_samples(current_dive, backupDive); + copy_cylinders(current_dive, backupDive); + copy_events(current_dive, backupDive); backupSamples.clear(); - for(int i = 1; i < d->dc.samples-1; i++){ + for(int i = 0; i < d->dc.samples-1; i++){ backupSamples.push_back( d->dc.sample[i]); } + save_dive(stdout, current_dive); + save_dive(stdout, backupDive); Q_FOREACH(const sample &s, backupSamples){ - // we need to use the correct gas - plannerModel->addStop(s.depth.mm, s.time.seconds, tr("Air"), 0); + int o2 = 0, he = 0; + get_gas_from_events(&backupDive->dc, s.time.seconds, &o2, &he); + qDebug() << "time / depth" << s.time.seconds << s.depth.mm << "o2/he" << o2 << he; + plannerModel->addStop(s.depth.mm, s.time.seconds, o2, he, 0); } } @@ -466,6 +474,10 @@ void DivePlannerGraphics::drawProfile() plannerModel->createTemporaryPlan(); struct diveplan diveplan = plannerModel->getDiveplan(); struct divedatapoint *dp = diveplan.dp; + if (!dp) { + plannerModel->deleteTemporaryPlan(); + return; + } while(dp->next) dp = dp->next; @@ -1076,9 +1088,10 @@ bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2) return p1.time <= p2.time; } -int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& gas, int ccpoint) +int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint) { int row = divepoints.count(); +#if 0 // this seems bogus if(milimeters == 0 && minutes == 0) { if(row == 0) { milimeters = M_OR_FT(10,30); @@ -1089,6 +1102,7 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& minutes = p.time + 600; } } +#endif // check if there's already a new stop before this one: for (int i = 0; i < divepoints.count(); i++) { @@ -1104,16 +1118,9 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& divedatapoint point; point.depth = milimeters; point.time = minutes; - if (row == 0) { - point.o2 = 209; - point.he = 0; - point.po2 = 0; - } else { - divedatapoint before = at(row-1); - point.o2 = before.o2; - point.he = before.he; - point.po2 = 0; - } + point.o2 = o2; + point.he = he; + point.po2 = ccpoint; divepoints.append( point ); std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan); endInsertRows(); @@ -1174,8 +1181,8 @@ void DivePlannerPointsModel::createTemporaryPlan() // Get the user-input and calculate the dive info // Not sure if this is the place to create the diveplan... // We just start with a surface node at time = 0 - struct divedatapoint *dp = create_dp(0, 0, 209, 0, 0); - dp->entered = TRUE; + struct divedatapoint *dp = NULL; // create_dp(0, 0, 209, 0, 0); +// dp->entered = TRUE; diveplan.dp = dp; int lastIndex = -1; for (int i = 0; i < rowCount(); i++) { @@ -1194,6 +1201,7 @@ void DivePlannerPointsModel::createTemporaryPlan() if (mode == ADD) { copy_samples(tempDive, current_dive); copy_cylinders(tempDive, current_dive); + copy_events(tempDive, current_dive); } #if DEBUG_PLAN dump_plan(&diveplan); @@ -1206,7 +1214,9 @@ void DivePlannerPointsModel::undoEdition() divepoints.clear(); endRemoveRows(); Q_FOREACH(const sample &s, backupSamples){ - plannerModel->addStop(s.depth.mm, s.time.seconds, tr("Air"), 0); + int o2, he; + get_gas_from_events(¤t_dive->dc, s.time.seconds, &o2, &he); + plannerModel->addStop(s.depth.mm, s.time.seconds, o2, he, 0); } } diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h index 6883f62eb..83bfadc32 100644 --- a/qt-ui/diveplanner.h +++ b/qt-ui/diveplanner.h @@ -41,7 +41,7 @@ public: int size(); struct diveplan getDiveplan(); public slots: - int addStop(int meters = 0, int minutes = 0,const QString& gas = QString(), int ccpoint = 0 ); + int addStop(int meters = 0, int minutes = 0, int o2 = 0, int he = 0, int ccpoint = 0 ); void setGFHigh(short gfhigh); void setGFLow(short ghflow); void setSurfacePressure(int pressure); diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index dfcb48a0c..8230cf663 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -538,14 +538,13 @@ void MainTab::rejectChanges() if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1){ ui.notes->setText(notesBackup[NULL].notes ); ui.location->setText(notesBackup[NULL].location); - }else{ + } else { if (editMode == ADD) { // clean up delete_single_dive(selected_dive); DivePlannerPointsModel::instance()->cancelPlan(); - } - else if (editMode == MANUALLY_ADDED_DIVE ){ - DivePlannerPointsModel::instance()->undoEdition(); + } else if (editMode == MANUALLY_ADDED_DIVE ) { + DivePlannerPointsModel::instance()->undoEdition(); // that's BOGUS... just copy the original dive back and be done with it... } struct dive *curr = current_dive; ui.notes->setText(notesBackup[curr].notes ); diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index 22a705530..68803c02d 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -94,7 +94,6 @@ private: * dive to this structure, making all editions there, * then applying the changes on the other dives.*/ struct dive multiEditEquipmentPlaceholder; - Completers completers; void resetPallete(); void saveTags(); -- cgit v1.2.3-70-g09d2 From 8941e8677e2b56084c07ac840adb1b655d5c806b Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 8 Nov 2013 21:22:59 +0900 Subject: Correctly track gases when manually adding and then editing dives The code had quite a few odd special cases that may have been left-overs from the old Gtk algorithm. With this the gas is actually in the dive plan node where it's use starts. And we maintain the gas correctly between multiple edit sessions. Signed-off-by: Dirk Hohndel --- planner.c | 6 +++-- qt-ui/diveplanner.cpp | 68 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 26 deletions(-) (limited to 'qt-ui/diveplanner.cpp') diff --git a/planner.c b/planner.c index 81f96937d..abefb6213 100644 --- a/planner.c +++ b/planner.c @@ -233,6 +233,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error int time = dp->time; int depth = dp->depth; +#if 0 // the new planner doesn't use that any more if (time == 0) { /* special entries that just inform the algorithm about * additional gases that are available */ @@ -241,6 +242,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error dp = dp->next; continue; } +#endif if (!o2 && !he) { o2 = oldo2; he = oldhe; @@ -256,14 +258,14 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error /* Create new gas, and gas change event if necessary; * Sadly, we inherited our gaschange event from libdivecomputer which only * support percentage values, so round the entries */ - if (o2 != oldo2 || he != oldhe) { + if (time == 0 || o2 != oldo2 || he != oldhe) { int plano2 = (o2 + 5) / 10 * 10; int planhe = (he + 5) / 10 * 10; int value; if (add_gas(dive, plano2, planhe) < 0) goto gas_error_exit; value = (plano2 / 10) | ((planhe / 10) << 16); - add_event(dc, lasttime, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2 + add_event(dc, time, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2 oldo2 = o2; oldhe = he; } /* Create sample */ diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index 398d11fc3..c2103b093 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -439,7 +439,6 @@ void DivePlannerPointsModel::loadFromDive(dive* d) for(int i = 0; i < d->dc.samples-1; i++){ backupSamples.push_back( d->dc.sample[i]); } - save_dive(stdout, current_dive); save_dive(stdout, backupDive); Q_FOREACH(const sample &s, backupSamples){ @@ -495,9 +494,11 @@ void DivePlannerGraphics::drawProfile() QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos(); QPointF p2 = handles[i]->pos(); QLineF line(p1, p2); - QPointF pos = line.pointAt(0.5); - gases[i]->setPos(pos); - gases[i]->setText( strForAir(dp)); + if (i > 0) { + QPointF pos = line.pointAt(0.5); + gases[i]->setPos(pos); + gases[i]->setText(strForAir(plannerModel->at(i-1))); + } } // (re-) create the profile with different colors for segments that were @@ -965,10 +966,15 @@ QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const if(role == Qt::DisplayRole) { divedatapoint p = divepoints.at(index.row()); switch(index.column()) { - case CCSETPOINT: return p.po2; - case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL)); - case DURATION: return p.time / 60; - case GAS: return strForAir(p); + case CCSETPOINT: return p.po2; + case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL)); + case DURATION: return p.time / 60; + case GAS: + if (index.row() > 0) { + p = divepoints.at(index.row() - 1); + return strForAir(p); + } + return ""; } } else if (role == Qt::DecorationRole) { switch(index.column()) { @@ -985,23 +991,30 @@ bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& v if(role == Qt::EditRole) { divedatapoint& p = divepoints[index.row()]; switch(index.column()) { - case DEPTH: p.depth = units_to_depth(value.toInt()); break; - case DURATION: p.time = value.toInt() * 60; break; - case CCSETPOINT:{ - int po2 = 0; - QByteArray gasv = value.toByteArray(); - if (validate_po2(gasv.data(), &po2)) - p.po2 = po2; - } break; - case GAS: { - int o2 = 0; - int he = 0; - QByteArray gasv = value.toByteArray(); - if (validate_gas(gasv.data(), &o2, &he)) { - p.o2 = o2; - p.he = he; - }break; + case DEPTH: p.depth = units_to_depth(value.toInt()); break; + case DURATION: p.time = value.toInt() * 60; break; + case CCSETPOINT: { + int po2 = 0; + QByteArray gasv = value.toByteArray(); + if (validate_po2(gasv.data(), &po2)) + p.po2 = po2; + } + break; + case GAS: { + if (index.row() == 0) { + qDebug() << "how can index.row be 0???"; + return false; + } + divedatapoint& pp = divepoints[index.row() - 1]; + int o2 = 0; + int he = 0; + QByteArray gasv = value.toByteArray(); + if (validate_gas(gasv.data(), &o2, &he)) { + pp.o2 = o2; + pp.he = he; } + } + break; } editStop(index.row(), p); } @@ -1107,6 +1120,13 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, // check if there's already a new stop before this one: for (int i = 0; i < divepoints.count(); i++) { const divedatapoint& dp = divepoints.at(i); + if (dp.time == minutes) { + row = i; + beginRemoveRows(QModelIndex(), row, row); + divepoints.remove(row); + endRemoveRows(); + break; + } if (dp.time > minutes ) { row = i; break; -- cgit v1.2.3-70-g09d2 From 6d5b2d75927b23183f8864bebf894b7bf4828311 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 9 Nov 2013 20:33:33 +0900 Subject: Adjust planner to work with the new semantic Insert the dive data point at 0,0 manually at the beginning of the plan. Now everything should work. We still can't edit a plan created like this, but at least we can once again plan things. Signed-off-by: Dirk Hohndel --- qt-ui/diveplanner.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'qt-ui/diveplanner.cpp') diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index c2103b093..0701cb6d6 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -487,18 +487,16 @@ void DivePlannerGraphics::drawProfile() } // Re-position the user generated dive handlers - for (int i = 0; i < plannerModel->rowCount(); i++) { + for (int i = 1; i < plannerModel->rowCount(); i++) { divedatapoint dp = plannerModel->at(i); DiveHandler *h = handles.at(i); 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 = handles[i-1]->pos(); QPointF p2 = handles[i]->pos(); QLineF line(p1, p2); - if (i > 0) { - QPointF pos = line.pointAt(0.5); - gases[i]->setPos(pos); - gases[i]->setText(strForAir(plannerModel->at(i-1))); - } + QPointF pos = line.pointAt(0.5); + gases[i]->setPos(pos); + gases[i]->setText(strForAir(plannerModel->at(i-1))); } // (re-) create the profile with different colors for segments that were @@ -1104,21 +1102,21 @@ bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2) int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint) { int row = divepoints.count(); -#if 0 // this seems bogus - if(milimeters == 0 && minutes == 0) { - if(row == 0) { - milimeters = M_OR_FT(10,30); - minutes = 600; - } else { - divedatapoint p = at(row-1); - milimeters = p.depth; - minutes = p.time + 600; - } + if(row == 0) { + beginInsertRows(QModelIndex(), row, row); + divedatapoint point; + point.depth = 0; + point.time = 0; + point.o2 = o2; + point.he = he; + point.po2 = ccpoint; + divepoints.append( point ); + endInsertRows(); + row++; } -#endif // check if there's already a new stop before this one: - for (int i = 0; i < divepoints.count(); i++) { + for (int i = 0; i < row; i++) { const divedatapoint& dp = divepoints.at(i); if (dp.time == minutes) { row = i; -- cgit v1.2.3-70-g09d2