diff --git a/android-mobile/build.gradle b/android-mobile/build.gradle index bc4bb27bc..3434020b4 100644 --- a/android-mobile/build.gradle +++ b/android-mobile/build.gradle @@ -28,7 +28,7 @@ apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.github.mik3y:usb-serial-for-android:v3.8.0' + implementation 'com.github.mik3y:usb-serial-for-android:3.8.1' implementation 'com.android.support:support-v4:28.0.0' } diff --git a/core/save-html.cpp b/core/save-html.cpp index 436fdd571..76cbd63f6 100644 --- a/core/save-html.cpp +++ b/core/save-html.cpp @@ -92,7 +92,8 @@ static void write_dive_status(struct membuffer *b, const struct dive &dive) static void put_HTML_bookmarks(struct membuffer *b, const struct dive &dive) { - const char *separator = "\"events\":["; + const char *separator = ""; + put_string(b, "\"events\":["); for (const auto &ev: dive.dcs[0].events) { put_string(b, separator); separator = ", "; diff --git a/packaging/ubuntu/make-package.sh b/packaging/ubuntu/make-package.sh index 234675347..be6e62c60 100755 --- a/packaging/ubuntu/make-package.sh +++ b/packaging/ubuntu/make-package.sh @@ -105,7 +105,7 @@ debuild -S -d # create builds for the newer Ubuntu releases that Launchpad supports # rel=focal -others="jammy mantic noble" +others="jammy noble oracular" for next in $others do sed -i "s/${rel}/${next}/g" debian/changelog diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 3fc4f0278..6824011b4 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -1118,38 +1118,25 @@ void DivePlannerPointsModel::updateDiveProfile() if (diveplan.is_empty()) return; + // For calculating variations, we need a copy of the plan. We have to copy _before_ + // calling plan(), because that adds deco stops. + bool computeVariations = isPlanner() && shouldComputeVariations(); + struct diveplan plan_copy; + if (computeVariations) + plan_copy = diveplan; + deco_state_cache cache; struct deco_state plan_deco_state; plan(&plan_deco_state, diveplan, d, dcNr, decotimestep, cache, isPlanner(), false); updateMaxDepth(); - if (isPlanner() && shouldComputeVariations()) { - auto plan_copy = std::make_unique(); - lock_planner(); - *plan_copy = diveplan; - unlock_planner(); + if (computeVariations) { #ifdef VARIATIONS_IN_BACKGROUND - // Since we're calling computeVariations asynchronously and plan_deco_state is allocated - // on the stack, it must be copied and freed by the worker-thread. - auto deco_copy = std::make_unique(plan_deco_state); - - // Ideally, we would pass the unique_ptrs to the lambda for QtConcurrent::run(). - // This, in principle, can be done as such: - // [ptr = std::move(ptr)] () mutable { f(std::move(ptr)) }; - // However, this make the lambda uncopyable and QtConcurrent::run() sadly - // uses copy semantics. - // So let's be pragmatic and do a release/reaquire pair. - // Somewhat disappointing, but what do you want to do? - // Note 1: this is now not exception safe, but Qt doesn't support - // exceptions anyway. - // Note 2: We also can't use the function / argument syntax of QtConcurrent::run(), - // because it likewise uses copy-semantics. How annoying. - QtConcurrent::run([this, plan = plan_copy.release(), deco = deco_copy.release()] () - { this->computeVariationsFreeDeco(std::unique_ptr(plan), - std::unique_ptr(deco)); }); + QtConcurrent::run([this, plan = std::move(plan_copy), deco = plan_deco_state] () + { this->computeVariations(std::move(plan), deco); }); #else - computeVariations(std::move(plan_copy), &plan_deco_state); + computeVariations(std::move(plan_copy), plan_deco_state); #endif final_deco_state = plan_deco_state; } @@ -1194,12 +1181,6 @@ int DivePlannerPointsModel::analyzeVariations(const std::vector &min, return (leftsum + rightsum) / 2; } -void DivePlannerPointsModel::computeVariationsFreeDeco(std::unique_ptr original_plan, std::unique_ptr previous_ds) -{ - computeVariations(std::move(original_plan), previous_ds.get()); - // Note: previous ds automatically free()d by virtue of being a unique_ptr. -} - // Return reference to second to last element. // Caller is responsible for checking that there are at least two elements. template @@ -1208,17 +1189,16 @@ auto &second_to_last(T &v) return *std::prev(std::prev(v.end())); } -void DivePlannerPointsModel::computeVariations(std::unique_ptr original_plan, const struct deco_state *previous_ds) +void DivePlannerPointsModel::computeVariations(struct diveplan original_plan, struct deco_state ds) { // nothing to do unless there's an original plan - if (!original_plan) + if (original_plan.dp.empty()) return; auto dive = std::make_unique(); copy_dive(d, dive.get()); deco_state_cache cache, save; struct diveplan plan_copy; - struct deco_state ds = *previous_ds; int my_instance = ++instanceCounter; save.cache(&ds); @@ -1236,7 +1216,7 @@ void DivePlannerPointsModel::computeVariations(std::unique_ptr depth_units = tr("ft"); } - plan_copy = *original_plan; + plan_copy = original_plan; if (plan_copy.dp.size() < 2) return; if (my_instance != instanceCounter) @@ -1244,7 +1224,7 @@ void DivePlannerPointsModel::computeVariations(std::unique_ptr auto original = plan(&ds, plan_copy, dive.get(), dcNr, 1, cache, true, false); save.restore(&ds, false); - plan_copy = *original_plan; + plan_copy = original_plan; second_to_last(plan_copy.dp).depth.mm += delta_depth.mm; plan_copy.dp.back().depth.mm += delta_depth.mm; if (my_instance != instanceCounter) @@ -1252,6 +1232,7 @@ void DivePlannerPointsModel::computeVariations(std::unique_ptr auto deeper = plan(&ds, plan_copy, dive.get(), dcNr, 1, cache, true, false); save.restore(&ds, false); + plan_copy = original_plan; second_to_last(plan_copy.dp).depth.mm -= delta_depth.mm; plan_copy.dp.back().depth.mm -= delta_depth.mm; if (my_instance != instanceCounter) @@ -1259,13 +1240,14 @@ void DivePlannerPointsModel::computeVariations(std::unique_ptr auto shallower = plan(&ds, plan_copy, dive.get(), dcNr, 1, cache, true, false); save.restore(&ds, false); - plan_copy = *original_plan; + plan_copy = original_plan; plan_copy.dp.back().time += delta_time.seconds; if (my_instance != instanceCounter) return; auto longer = plan(&ds, plan_copy, dive.get(), dcNr, 1, cache, true, false); save.restore(&ds, false); + plan_copy = original_plan; plan_copy.dp.back().time -= delta_time.seconds; if (my_instance != instanceCounter) return; @@ -1308,15 +1290,16 @@ void DivePlannerPointsModel::createPlan(bool saveAsNew) removeDeco(); createTemporaryPlan(); + // For calculating variations, we need a copy of the plan. We have to copy _before_ + // calling plan(), because that adds deco stops. + struct diveplan plan_copy; + if (shouldComputeVariations()) + plan_copy = diveplan; + plan(&ds_after_previous_dives, diveplan, d, dcNr, decotimestep, cache, isPlanner(), true); - if (shouldComputeVariations()) { - auto plan_copy = std::make_unique(); - lock_planner(); - *plan_copy = diveplan; - unlock_planner(); - computeVariations(std::move(plan_copy), &ds_after_previous_dives); - } + if (shouldComputeVariations()) + computeVariations(std::move(plan_copy), ds_after_previous_dives); // Fixup planner notes. if (current_dive && d->id == current_dive->id) { diff --git a/qt-models/diveplannermodel.h b/qt-models/diveplannermodel.h index af958b938..1dadfacc7 100644 --- a/qt-models/diveplannermodel.h +++ b/qt-models/diveplannermodel.h @@ -131,8 +131,7 @@ private: void createTemporaryPlan(); struct diveplan diveplan; void computeVariationsDone(QString text); - void computeVariations(std::unique_ptr plan, const struct deco_state *ds); - void computeVariationsFreeDeco(std::unique_ptr plan, std::unique_ptr ds); + void computeVariations(struct diveplan plan, struct deco_state ds); // Note: works on copies of plan and ds int analyzeVariations(const std::vector &min, const std::vector &mid, const std::vector &max, const char *unit); struct dive *d; int dcNr;