Compare commits

...

251 Commits

Author SHA1 Message Date
Michael Keller
b126fccb1b Desktop: Fix Inconsistencies in Handling of Salinity.
- add correct setting of the water type drop down for the dive shown
  initially after program start;
- change salinity to have 3 decimals in planner, to make it consistency
  with the log.

Fixes #4240.

Reported-by: @ccsieh
Signed-off-by: Michael Keller <github@ike.ch>
2024-06-10 15:54:22 +12:00
Michael Keller
10fc3bfd47 Bugfix: Fix Incorrect Volumes Displayed for Tank Types.
Fix an issue introduced in #4148.
Essentially the refactoring missed the fact that in the imperial system
tank size is tracked as the free gas volume, but in the metric system
(which is the one used in most of Subsurface's calculations) tank size
is tracked as water capacity.
So when updating a tank template tracking imperial measurements, the
given (metric) volume in l has to be multiplied by the working pressure,
and vice versa.
This also combines all the logic dealing with `tank_info` data in one
place, hopefully making it less likely that this will be broken by
inconsistencies in the future.

Fixes #4239.

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-09 11:15:59 +02:00
Berthold Stoeger
a8c9781205 cleanup: remove unused function create_and_hookup_trip_from_dive()
It seems that the last user was removed 5 years ago: ff9506b21?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-06-08 15:59:53 +02:00
Michael Keller
291ed9d7e3 Documentation: Update Information on Available Versions in README.md.
Update the information on the available versions of Subsurface in
README.

Also update the documentation to reflect the renaming of `INSTALL` to
`INSTALL.md`.

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-06 16:17:44 +12:00
Michael Keller
a39f0e2891 Mobile: Fix QML Warnings.
Fix some runtime warnings when running the mobile build caused by
binding loops and deprecated handler syntax.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-06-06 16:17:32 +12:00
Dirk Hohndel
d9f50bb8e0 add Ubuntu 24.04 / Noble Numbat to our builds
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-06-05 13:23:52 -07:00
Michael Keller
d1db85005b CICD: Remove Workaround for Broken ubuntu 16.04 Repository.
ATTENTION: Only merge this when CICD starts working (will need a rebase
to trigger a build).

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-05 10:52:34 +12:00
Berthold Stoeger
e2d3a12555 cleanup: remove unused roles in DiveTripModelBase
The roles DIVE_IDX and SELECTED_ROLE were used for the old selection
system and removed in b8e7a600d2d2a30f7e0646fc164ab6e57fd4782f.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-06-05 09:16:32 +12:00
Michał Sawicz
568aeb7bce snap: drop candidate channel
Building directly into `stable` from the `current` branch.

Signed-off-by: Michał Sawicz <michal@sawicz.net>
2024-06-03 07:59:22 -07:00
Berthold Stoeger
ca5f28206b tests: make profile test work with non-C locales
For reasons unknown to me, the profile test is executed with a
weird locale, resulting in wrong formatting.

By setting the locale manually to "C", the tests start to work.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-06-03 07:41:47 +02:00
Michael Keller
adaa52bf9b Desktop: Fix Undo for Gaschanges on Manually Added Dives.
Fix the undo functionality for gaschanges edited on manually added
dives.

Pointed-out-by: @bstoeger
Signed-off-by: Michael Keller <github@ike.ch>
2024-06-02 11:38:21 +02:00
Michael Keller
692ec9ee5c Update libdivecomputer to latest on 'Subsurface-DS9'.
Signed-off-by: Michael Keller <github@ike.ch>
2024-06-02 16:33:19 +12:00
Michael Keller
c2c5faeaad Add the change for MacOS builds with Qt6 as well.
Signed-off-by: Michael Keller <github@ike.ch>
2024-06-02 09:42:14 +12:00
jme
88acef7f0f release build google maps
After the Mac QT upgrade to 5.15.13 google maps stopped working because a debug plugin was built and not deployed.   This changes forces a release build.   It may or may not be the best alternative, but if nothing else it's a starting point for discussion with people who know more about qmake than I do.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-06-02 09:42:14 +12:00
Michael Keller
32cd52869b CICD: Fix the AppImage Workflow.
Work around an upstream version inconsistency by pinning the versions in
our build.

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-02 01:35:29 +12:00
Berthold Stoeger
3d96642b8d smartrak: remove copy_string() that makes little sense
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-06-01 14:43:33 +02:00
Michael Keller
c5546fb52f Cleanup: Optimise String Handling.
Cleanup of the sub-optimal string handling in #4222.

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-01 14:43:03 +02:00
Michael Keller
f65afaf5d2 Desktop: Fix Gas Editing for Manually Added Dives.
- show the correct gasmix in the profile;
- make gases available for gas switches in the profile after they have
  been added;
- persist gas changes;
- add air as a default gas when adding a dive.

This still has problems when undoing a gas switch - instead of
completely removing the gas switch it is just moved to the next point in the
profile.

Signed-off-by: Michael Keller <github@ike.ch>
2024-06-01 23:22:40 +12:00
Berthold Stoeger
9243921cbb test: fix subtle bug in testplan.cpp
testplan.cpp had a subtle bug since converting from a fixed-size
cylinder table to a dynamic cylinder table.

As noted in equipment.h, pointers to cylinders are *not* stable
when the cylinder table grows. Therefore, a construct such as
        cylinder_t *cyl0 = get_or_create_cylinder(&dive, 0);
        cylinder_t *cyl1 = get_or_create_cylinder(&dive, 1);
        cylinder_t *cyl2 = get_or_create_cylinder(&dive, 2);
can give dangling cyl0 and cyl1 pointers. This was not an issue
with the old table code, since it had a rather liberal allocation
pattern. However, when switching to std::vector<>, the problem
becomes active.

To "fix" this, simply access the highest index first. Of course,
this should never be done in real code! Therefore, add a
comment at each instance.

Quickly checked all other get_or_create_cylinder() calls and
they seemed to be safe.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-31 22:50:49 +02:00
Michael Keller
d27451979d Profile: Add Gas Description to Disambiguate.
Add the gas description to the label on pressure graphs to disambiguate
if multiple identical gasmixes are shown.

Also move the label to the right, where the end pressures will typically
be more spread out than the starting pressures.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-31 22:50:09 +02:00
Berthold Stoeger
e7d486982f core: remove put_format_loc()
This was replaced by C++ functions in ae299d5e663c.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-31 18:55:47 +02:00
Michael Keller
5b941ea34e Mobile: Fix Build Warnings.
Fix build warnings from building functions not used in the mobile
version.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-30 11:54:51 +02:00
Michael Keller
56f1e7027f Documentation: Update INSTALL and Convert it to Markdown.
Update the instructions for the Windows build and convert the file to
markdown.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-30 14:22:16 +12:00
Berthold Stoeger
64d4de4a1b fix memory leak
logfile_name was converted to std::string. Assigning a strdup()ed
string to it will leak memory.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-29 10:03:41 +12:00
Berthold Stoeger
e39b42df53 cleanup: remove disfunct add_cloned_weightsystem_at()
Clearly, a development artifact.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-29 09:33:23 +12:00
Berthold Stoeger
398cc2b639 cleanup: remove localized snprintf() functions
The last use of these functions was removed in ae299d5e663c.

And that's a good thing, because snprintf-style interfaces
make zero sense in times of variable-length character
encodings.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-29 09:33:23 +12:00
Berthold Stoeger
2776a2fe48 import: fix memory leak when importing dives
A long standing issue: the dives_to_add, etc. tables need to be
manually freed. This kind of problem wouldn't arise with proper
C++ data structures.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-27 20:11:37 +12:00
Michael Keller
1aa5438b2d Cleanup: Improve the Use of 'Planned dive' and 'Manually added dive'.
- standardise the naming;
- use it consistently;
- apply the 'samples < 50' only when putting manually added dives into
  edit mode - everywhere else manually added dives should be treated as
  such;
- do not show a warning before editing a manually added dive in planner.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-25 20:13:45 +02:00
=Michael Keller
ecc6f64d10 Cleanup: Improve Connection Handling in Profile.
- improve naming;
- remove unneeded disconnects.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-25 16:31:04 +02:00
=Michael Keller
8c14fb971c Update livdivecomputer to latest on 'Subsurface-DS9'.
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-25 08:54:53 +12:00
Dirk Hohndel
6bdfee080d Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_de_DE' 2024-05-21 08:04:37 -07:00
Dirk Hohndel
21269183bf Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_pt_PT' 2024-05-21 08:04:17 -07:00
=Michael Keller
245f8002a8 CICD: Remove Workflow to Build ubuntu 14.04 Docker Image.
Remove the workflow for building an ubuntu 14.04 Docker image. This is
no longer needed since the AppImage is now built on 16.04.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-20 09:56:01 +12:00
=Michael Keller
c3d807802d Desktop: Fix Finding Reported by Coverity.
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-18 14:07:15 +02:00
Michael Keller
a66bdb1bf5 Planner: Improve Exit Warning.
Improve the warning shown to the user when closing the application wile
in the planner. We now allow the user to directly discard the planned
dive, save it into the dive log, or cancel the operation altogether.
If they save into the dive log, or if they modified the dive log before
starting the planner, a second warning about the unsaved dive log
changes will be shown.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-17 16:44:04 +12:00
Michael Keller
b579342639 Cleanup: Remove 'context' Reference from Logging Defines.
Remove the reference to `context` from the defines used for logging, as
this is not used.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-16 16:39:48 +02:00
Michael Keller
888704e816 CICD: Have the Artifact Comment Workflow Suppress 'No Artifacts' Errors.
Suppress errors in the 'Add Artifact Comment' workflow if there are no
artifacts produced by the pull request workflow - this gets rid of
follow-on error messages when a pull request workflow encounters a build
error.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-15 13:29:25 +12:00
Berthold Stoeger
6880937838 core: fix INFO() and ERROR() macros in core/serial_ftdi.cpp
Error introduced in da7ea17b66: the INFO() and ERROR() macros
pass stdout instead of the format string as first parameter
to report_error(). Ooooops. How did this ever pass the
compile tests!?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-15 09:19:05 +12:00
Michael Keller
d018b72dab CICD: Fix Signing of Android CICD Built Packages.
Fix the signing of Android .apk packages when they are build in CICD.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 15:21:05 +12:00
Michael Keller
b3d6920de4 CICD: Remove Environment Dumping in Artifact Comment Workflow.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 13:36:26 +12:00
Michael Keller
912badadd4 CICD: Restrict Artifact Comment Workflow to only Run on Pull Requests.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 13:35:12 +12:00
Michael Keller
1c0fe2fa1f Fix GitHub Workflow definition.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 12:53:10 +12:00
Michael Keller
48ef4b3a01 CICD: Debug GitHub Workflow Webhook
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 12:06:51 +12:00
Michael Keller
22082bd60a CICD: Fix Coverity Scan Workflow.
Change the ordering of steps so that git is installed before the
checkout is performed.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-14 10:57:04 +12:00
Michael Keller
be1b80ea8a CICD: Fix the AppImage Workflow.
Fix the workflow by removing the dependency on node 20, which is not
supported in Ubuntu 16.04.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 14:54:49 +12:00
Michael Keller
e81b42d533 Add environment variable required to be able to use the GitHub CLI.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 12:55:09 +12:00
Michael Keller
dd50ab0106 Fix incorrect script references.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 12:39:09 +12:00
Michael Keller
0d6b572a9f Fix script permissions.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 12:32:07 +12:00
Michael Keller
21f64134b7 Fix custom action YML.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 12:17:13 +12:00
Michael Keller
7bf40d659c Fix custom action.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 12:13:41 +12:00
Michael Keller
6ae2844f24 CICD: Fixup Merge Build Workflows on master.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 11:07:05 +12:00
Michael Keller
447f9709f7 CICD: Fixup Merge Build Workflows on master.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-13 10:46:33 +12:00
=Michael Keller
4ae6c0bbc4 CICD: Add Workflow to Pin the Generated Artifacts.
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-13 10:19:59 +12:00
=Michael Keller
6fc8310705 CICD: Improve Workflows.
Make multiple improvements to the existing workflows:
- create a shared custom action to deal with version number tracking
  and generation;
- use this action to add the branch name to the version for pull
  request builds;
- create a shared workflow for all debian-ish builds to avoid re-use
  by copy / paste;
- remove potential security risks by eliminating the use of
  pre-evaluated expressions (`${{ ... }}`) inside scripts;
- update outdated GitHub action versions;
- improve the consistency by renaming scripts acording to have a `.sh`
  extension;
- improve naming of generated artefacts for pull requests to include
  the correct version.

@dirkh: Unfortunately this is potentially going to break builds when it is
merged, as there is no good way to 'test' a merge build short of
merging.
We'll just have to deal with the fallout of it in a follow-up pull
request.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-13 10:19:59 +12:00
Berthold Stoeger
e20ec9248c core: fix leak when clearing dive log
46cf2fc0867 fixed a bug where clearing of a divelog, such as the one
used for import, would erase dives in the global(!) divelog.

However, the new code used the function clear_dive_table(), which
only cleared the table without unregistering the dives. In particular,
the dives were not removed from the trips, which means that the trips
were not free()d.

This reinstates the old code, but now passes a divelog paremeter
to delete_single_dive() instead of accessing the global divelog.
Moreover, delete dives from the back to avoid unnecessary
copying.

An alternative and definitely simpler solution might be to just
add a "clear_trip_table()" after "clear_dive_table()".

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-13 08:58:03 +12:00
Berthold Stoeger
8769b1232e planner: initialize currCombo.ignoreSelection
I am not sure what this does, but it should be initialized before
it is tested.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-12 13:23:21 +02:00
Berthold Stoeger
d061a54e3d planner: fix gas selection
The lambda that created the list of gases took a copy not a
reference of the planned dive. Of course, that never had its
gases updated. Ultimately this would crash, because this sent
an index of "-1" on change.

Fix by
1) Using a reference to the dive, not the copy
2) Catch an invalid "-1" index (by Michael Keller <github@ike.ch>)

Fixes #4188

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-12 13:23:21 +02:00
=Michael Keller
306dad575c CICD: Update the AppImage Build to Use ubuntu 16.04.
Update the linux AppImage build to use ubuntu 16.04, and simplify it to
a single workflow running on a vanilla docker image.

This still uses the upload-artifact@v3 Action that will be EOL in
November 2024, because v4 relies on node 20 which has an unmet glibc
dependency in ubuntu 16.04. But this workflow can be updated to run on
ubuntu 18.04 by a simple search / replace and disabling some 16.04
specific PPAs.

@dirkh, @probonopd: I have moved this here from #4183 to be able to
review and discuss it without the noise of the workflow cleanup.

The workflow now also publishes the AppImage as an artifact on pull
request builds, available under Checks / Details / Summary.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-12 13:52:12 +12:00
Michael Keller
331d6712c6 CICD: Move MacOS / iOS Build Qt Resources into GitHub.
Move the Qt resources required for the build for MacOS and iOS into
GitHub, into their own repositories. This removes the need to publish
them on an external file server and download them from there for every
build.
It will also make it easier for contributors to update these resources
if needed.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-12 10:19:24 +12:00
Michael Keller
f4e61aa5dc Import: Make Directory Selectable when Importing .fit Files.
In the 'Download from dive computer' dialogue, make it possible to
select the source directory for the import.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-11 12:52:05 +12:00
Michael Keller
528532572f Planner: Fix Editing of Plans in Multi-Divecomputer Dives.
Currently editing of planned dives that have been merged with actual
(logged) dives only works if the 'Planned dive' divecomputer is the
first divecomputer, and this divecomputer is selected when clicking
'Edit planned dive'. In other cases the profile of the first
divecomputer is overlaid with the profile of the planned dive, and the
first divecomputer's profile is overwritten when saving the dive plan.
Fix this problem.

Triggered by @SeppoTakalo's comment (https://github.com/subsurface/subsurface/issues/1913#issuecomment-2075562119): Users don't like that planned dives show up as their own entries in the dive list, so being able to merge them with the actual dive after it has been executed is a good feature - but this wasn't working well until now.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-11 12:51:45 +12:00
=Michael Keller
a83349015a CICD: Improve the GitHub Actions for Linux.
Do a few things:
- add a build for Debian trixie (as discussed in #4182);
- add a build for Ubuntu 24.04;
- rename the build definitions to match the build names;
- update the artifact uploads to use a non-deprecated version of the
  action, and name the artifact appropriately;
- remove a stale workflow file.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-11 12:51:33 +12:00
=Michael Keller
8627f6fc4a Desktop: Add Auto-sizing to the Extra Info Table.
Add auto-sizing to the extra info table - resize the columns so that all
rows are shown in full whenever the data is updated.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-08 08:26:56 -07:00
Michael Keller
5bad522390 Update livdivecomputer to latest on 'Subsurface-DS9'.
Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-08 12:34:31 +12:00
Richard Fuchs
edb771e8e6 uemis-downloader: convert strings to std::string
Convert some C-style strings in uemis-downloader.cpp to std::string.
This has the side effect of fixing builds on Debian Trixie, which
currently fail with the (rather silly) error:

/build/subsurface-beta-202405060411/core/uemis-downloader.cpp: In function 'char* build_ans_path(const char*, int)':
/build/subsurface-beta-202405060411/core/uemis-downloader.cpp:290:32: error: '%s' directive output between 0 and 12 bytes may cause result to exceed 'INT_MAX' [-Werror=format-truncation=]
  290 |         snprintf(buf, len, "%s/%s", path, name);
      |                                ^~
......
  529 |         ans_path = build_filename(intermediate, fl);
      |                                                 ~~
cc1plus: some warnings being treated as errors

Signed-off-by: Richard Fuchs <dfx@dfx.at>
2024-05-07 22:34:00 +12:00
=Michael Keller
17d83acdab Documentation: Add Instructions for Using Qt 5.15.13 on MacOS.
Add instructions for using Qt 5.15.13 on MacOS, which seems to have
better support for Apple silicon.`

Provided-by: jme <32236882+notrege@users.noreply.github.com>
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-07 18:43:26 +12:00
=Michael Keller
133354d51d CICD: Update Qt Version Used in the MacOS Build to 5.15.13.
Update the version of Qt that is used in the CICD build for MacOS to
5.15.13. This version is showing promise for building binaries that work
on Apple silicon.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-07 18:43:26 +12:00
Michael Keller
46cf2fc086 Import: Fix Application Hang when Cancelling the Download Dialogue.
Fix a bug causing the 'Download from dive computer' dialogue to hang
when the user attempts to cancel the dialogue after successfully
downloading one or more dives.

Fixes #4176.

Signed-off-by: Michael Keller <github@ike.ch>
2024-05-05 19:15:26 +02:00
Michael Keller
5ac1922d84 Cleanup: Improve (Android) Build Scripts.
Add a script for building the Android APK in the docker container.
Also make some improvements to the Windows build scripts, and update the
documentation for both builds.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-05-06 00:45:51 +12:00
Michael Keller
3153a139b3 Update livdivecomputer to latest on 'Subsurface-DS9'.
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-04 01:41:51 +12:00
Michael Keller
e65c7cedc8 Refactoring: Improve Naming of FRACTION and SIGNED_FRAC defines.
Make it more obvious that the FRACTION and SIGNED_FRAC defines return a
tuple / triplet of values.

Fixes https://github.com/subsurface/subsurface/pull/4171#discussion_r1585941133

Complained-about-by: @bstoeger
Signed-off-by: Michael Keller <github@ike.ch>
2024-05-02 20:36:26 +02:00
Berthold Stoeger
32a08735c3 profile: fix string formating in profile.cpp
ae299d5e663cd672d1114c3fe90cf026b9ab463e introduced a format-
string bug by splitting a format-string in two and splitting
the arguments at the wrong place.

The compiler doesn't warn in this case, because the format-
string is passed through translate(...).

This should have crashed, but for some reason didn't, at least
on Linux.

Fix the arguments.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-05-01 20:39:59 +12:00
Michael Keller
af6caa6fa2 Import: Improve Error Logging.
Add logging of the libdivecomputer return code for errors. Also, switch
logging of errors in the background thread to callback based logging to
make it visible.

Signed-off-by: Michael Keller <github@ike.ch>
2024-04-30 12:26:18 +12:00
Michael Keller
f3c7dcf9c9 Desktop: Fix 'planned' and 'logged' Filters.
Fix the filters for planned (i.e. has at least one dive plan attached)
and logged (i.e. has at least one dive computer log attached) dives.
Also refactor the respective functions for improved readability.

Signed-off-by: Michael Keller <github@ike.ch>
2024-04-30 12:25:31 +12:00
Michael Keller
bb00a9728f Cleanup: More Fixes for Problems Reported by Coverity.
Fix the problem another way as Coverity was still not happy with it.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-28 23:44:16 +12:00
Michael Keller
a2cd621819 Update livdivecomputer to latest on 'Subsurface-DS9'.
Signed-off-by: Michael Keller <github@ike.ch>
2024-04-28 18:52:19 +12:00
Michael Keller
d92777a3ff Packaging: Cleanup Windows Build Scripts.
Do some housekeeping and cleanup on the build scripts for Windows:
- remove Windows 32bit builds as support for this has been removed from
  the mxe container;
- fix some warnings in the smtk2ssrf installer configuration;
- sanitise the output colour of the smtk2ssrf build script;
- add a docker based build script for the Windows installers;
- remove outdated and deprecated documentation and scripts.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-26 07:42:59 -07:00
jme
e09a134a3f Delete desktop-widgets/preferences/preferences_dc.ui
Remove preferences "Dive Download" window.    Delete all dive computers no longer needed now that they can be deleted on the import window.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-26 08:14:16 +12:00
jme
aecb4f5005 Delete desktop-widgets/preferences/preferences_dc.h
Remove preferences "Dive Download" window.    Delete all dive computers no longer needed now that they can be deleted on the import window.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-26 08:14:16 +12:00
jme
358b9186bf Delete desktop-widgets/preferences/preferences_dc.cpp
Remove preferences "Dive Download" window.    Delete all dive computers no longer needed now that they can be deleted on the import window.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-26 08:14:16 +12:00
jme
12ae3d4e96 Update preferencesdialog.cpp
Remove preferences "Dive Download" window.    Delete all dive computers no longer needed now that they can be dleted on the import window.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-26 08:14:16 +12:00
jme
34926f1325 Update CMakeLists.txt
Remove preferences "Dive Download" window.    Delete all dive computers no longer needed now that they can be dleted on the import window.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-26 08:14:16 +12:00
Michael Keller
da8509d29b Cleanup: Actualise README.md
Actualise the status badges in README.md, and remove the outdated
reference to the current release.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-26 01:14:23 +12:00
Michael Keller
9deef235e2 Cleanup: Fix new Findings in Coverity Scan.
Fix some findings in a Coverity scan in `core/planner.cpp` and
`core/profile.cpp`, that were reported as new after the changes
in #4126 (likely because of the rename from .c to .cpp).
Results: https://scan4.scan.coverity.com/#/project-view/60459/13160

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-24 10:15:53 +02:00
Berthold Stoeger
e7a6de3894 core: use std::string instead of strndup()
Allows us to remove the strndup.h header. This code will be
even more simple, once core is fully converted away from C-strings.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
177a1a6706 make format-warnings hard compile errors
Code such as `report_info("msg: %s", i)` may crash if `i` is
not a string type. To avoid such problems make format-warnings
hard compile errors.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
556ecd5a9b core: use C++-primitives for g_tag_list
The old code was leaking memory. Use std::unique_ptr<> for
ownership management.

This is still very primitive and divetags are kept during
application lifetime. There should probably be some form
of reference counting. And the taglist should not be global,
but attached to the divelog.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
b320942343 Replace remaining qDebug()s by report_info()
The only case left is in android.cpp, though that is only compiled
when compiling the full desktop app on Android. I.e. never. So
don't bother for now.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
8867edffe8 Replace qDebug() by report_info() in profilewidget2.cpp
Remove those that are commented out, since this part of the code
will not be ported to QtQuick. So why bother?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
991b72d4ff Replace qDebug() by report_info() in core/cloudstorage.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
47254d91e0 Replace qDebug() by report_info() in qt-init.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
9923d49624 Replace qDebug() by report_info in qthelper.cpp
To do so replace QStrings by std::strings in ui-language code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
9febfdd084 Remove diabled debugging output in subsurfacewebservices.cpp
Why bother with commented out code?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
8677d1f325 Replace qDebug() by report_info() in downloadfromdcthread.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
6dd5ec296d Convert qDebug() to report_info() in testing code
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
4de109bbf1 Replace qDebug() by report_info() in bluetooth code
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
d83da05f8d Replace qDebug() by report_info in checkcloudconnection.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
b6439e0420 Replace qDebug() by report_info() in smtk-import
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
ab7218d543 Use report_info() instead of qDebug in mobile code
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
2c2ad1e5c9 user report_info() instead of qDebug in main() functions
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
4af2ec88bd Use std::vector<string> instead of QStringList in main()
In an effort to convert core to C++ structures.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
c6cd10a43f core: make getCloudURL() return an std::string
Let's use std::string in the core. Notably, I'd like to make
the numerous main() functions mostly independent of Qt. Some
things will have to remain, such as argument parsing, of course.

This changes the API: instead of returning an error code and
taking a pointer to the actual return-value, return an
std::optional<std::string>> that is set if the function succeeds.

Returning an empty string in the error case might be simpler,
but oh well...

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
8e106b0449 core: replace qDebug() by report_info() in subsurface-helper.cpp
Start unifying debug output.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
da7ea17b66 cleanup: replace fprintf to stderr by report_info()
Let's try to unify debugging output!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
b097c0a44f core: port errorhelper.c to C++
Use the C++-version of membuffer.

This fixes two memory leaks: report_info() on every(!) invocation
and report_error() before the error callback is set.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
ec0bc2d06c cleanup: replace MIN and MAX macrors by standard versions
In C++ files, replace MIN and MAX by std::min and std::max,
respectively. There are still a few C files using these
macros. Convert them in due course.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
b89029353f import: use C++ primitives in smartrak.cpp
Makes memory management more palatable.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
14cfb17c1a import: compile smartrak.cpp as C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
157b52aa6e tests: make git-storage test more robust
The code was crashing if it couldn't reach the cloud, because then
info.repo is NULL. Skip the test if that happens.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
322c3b55e6 core: add compile time format check to format_string_std
Had to rewrite the thing, because gcc's warnings don't work
with templatized var-args. Since there is no string-format.cpp
and I didn't want to inline it, moved it to format.cpp.

String formatting is distributed around at least four
headers: membuffer.h, subsurface-string.h, format.h
and format-string.h. This really should be unified!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
a123589efb core: convert git_info to std::string
Quite a bit of fallout in users of this structure.

Conveniently, since git-access.cpp is now C++ we can move
some helpers from the monstrous qthelper.cpp to git-access.cpp.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
ae299d5e66 profile: use C++ string functions to format plot data
This may appear a bit ominous, as it doesn't generate a string,
but a vector of strings (one for each line). However, that is
in preparation for the QtQuickification of the profile, where
the text-items take such a list.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
422f693f5b core: port tag.c to C++
Let taglist_get_tagstring() return an std::string, since all callers
are C++ anyway.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
84b7ffafd2 core: use C++ versions of membuffer in add_to_string
Avoid explicit calls to free().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
e65ba50c1a core: use C++ constructs in save-html.cpp
Since this is the only caller, onvert the get_file_name() function
to return an std::string.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
82ba236859 core: port save-html.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
177b03958c core: port worldmap-save.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
bd3f9b107e planner: turn TIMESTEP macro into integer constant
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
15b17a0aca planner: turn error argument of add_plan_to_notes() into a boolean flag
This used to have multiple values, but is currently only checked for
true/false. Reflect that in the type.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
b542a39a00 planner: turn UNIT_FACTOR macro into function
No apparent reason why this is a hard-to-read macro.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
9a052cd089 planner: move decotimestap to diveplannermodel.cpp
The deco timestep is a parameter to the plan() function. There
seems no need to define this as a global macro. Probably some
code reshuffeling artifact.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
4db19d6284 planner: use std::string in plannernotes.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
8b51ff7ded core: add locale aware formatting function to std::string
We had locale aware formatting functions that generated QStrings.
Create an alternative that creates std::string, since we want that
in the core.

This commit is unfortunate for two reasons:
- The function is called "casprintf()" for analogy with the QString
  version. However, the non locale aware function is called
  "format_string_std()" for analogy with "format_string()".
  Ultimately these names should be unified. Probably, once there
  are no membuffer users left.
- This does UTF-16->UTF-8->UTF-16 roundtrips. The core formatting
  functions should render UTF-8 and only convert to UTF-16, in
  the UI layer.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
fe68870079 planner: use std::vector instead of malloc() in planner.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
f69686d429 planner: encapsulate deco state cache in a struct
Removes memory management pain: the struct cleans up when it
goes out of scope.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
Berthold Stoeger
77e8c3655e core: compile planner source files with C++
Another relatively easily converted part of the code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-23 07:47:11 +07:00
jme
bd31efa821 Update downloadfromdivecomputer.cpp
Remove lines setting "current" computer to computer1.  

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
80eff1d6e2 Update downloadfromdivecomputer.ui
Per suggestion, use QFrame and trashcan icon.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
74b1648fcc Update downloadfromdivecomputer.h
Change DDC<n> to DeleteDC<n>

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
7fb0e9e59e Update downloadfromdivecomputer.cpp
Changed DDC<n> to DeleteDC<n> and hide set visibility for new Qframe

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
d59bd1831a Update downloadfromdivecomputer.cpp
Added delete dive computer buttons.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
f05808fded Update downloadfromdivecomputer.h
Added delete dive computer buttons.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
jme
1692e48163 Update downloadfromdivecomputer.ui
Added delete dive computer buttons.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-22 16:52:19 +12:00
Michael Keller
375b08857c Desktop: Remove Unneeded Special Case for MacOS.
Since the removal of this special case for MacOS was confirmed to be
working in the case of building with bluetooth support in #4120, we should
probably remove it from the code used when building without bluetooth
support as well.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-21 13:13:18 +12:00
Michael Keller
d49092ac70 CICD: Add Script to Find the Changeset ID for a CICD Release Number.
Add a script that finds the changeset ID in the subsurface repository
that a given CICD release was built from.
The option '-c' can be used to check out the changeset, if one is found.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-20 10:46:28 +07:00
Michael Keller
ee8b37cc6e Import: Fix Info Logging.
Avoid logging the expected outcome (success) at info level.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-04-19 15:31:34 +12:00
jme
77281f8bfe Update downloadfromdivecomputer.cpp
If Bluetooth isn't enabled, don't clear non Bluetooth address.    There was an earlier concern that USB mount point shouldn't be preserved because they may change.   This behavior is different on a Mac where the USB serial mount points tend to be persistent.   Michael tested this on Linux and suggested on saving the mount points for Linux and Windows.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
6b11457ddd Update downloadfromdivecomputer.cpp
Based on Michael's suggestion, added code to refine enableBluetoothMode. 

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
8a20509861 Update downloadfromdivecomputer.cpp
Removed blank lines - forgot that blank lines without a continuation \ would break the macro.    Embarrassing to say the least.   I need to figure out how to upload tested code into git.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
334a357c19 Update downloadfromdivecomputer.cpp
Removed the MacOs specific code and added comment explaining why ui.device.Text must be set before the ui.bluetoothMode change handler runs.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
1973d7c881 Update downloadfromdivecomputer.cpp
Preserve bluetooth address if we have it (don't rescan) and for MacOS save the mount point if we have it.     As best as I can tell, the mount points for USB devices do not change on MacOs regardless of the USB port being used.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
a5575f43a3 Update downloadfromdivecomputer.cpp
Per Michael's suggestion, use isBluetoothAddress as check before skipping Bluetooth scan. 

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
ffce4bc097 Update downloadfromdivecomputer.cpp
another space that should have been a tab.

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
5980db073a Update downloadfromdivecomputer.cpp
Replaces spaces with tabs and corrected misplaced braces (embarassing...).

Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
jme
4dcc9210a9 Avoid unnecessary bluetooth device address scanning.
When switching from a non-bluetooth computer to a bluetooh computer an unnecessary bluetooth scan may be forced.   This patch will avoid the scan if the bluetooth device address is known.



Signed-off-by: jme <32236882+notrege@users.noreply.github.com>
2024-04-17 10:03:32 +12:00
Berthold Stoeger
f4b35f67f6 Don't "untranslate" cylinder names
As far as I can see there are no translation strings for the
cylinder names, so there is no point in translating them back.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-16 08:56:49 +12:00
Berthold Stoeger
0d011231e6 desktop: unglobalize ComboBox-models
The combo-boxes (cylinder type, weightsystem, etc.) were controlled
by global models. Keeping these models up-to-date was very combersome
and buggy.

Create a new model everytime a combobox is opened. Ultimately it
might even be better to create a copy of the strings and switch
to simple QStringListModel. Set data in the core directly and
don't do this via the models.

The result is much simpler and easier to handle.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-16 08:56:49 +12:00
Berthold Stoeger
de313bd01a mobile: save changes from main event loop
When autosync to cloud was enabled, the old code would crash,
because it synced to cloud from a signal handler, which executed
the main loop when checking the cloud connection, which deleted
the object which was causing the original signal. Or something
like that. See discussion in #4119.

To avoid such problems, send a signal via a 'QueuedConnection'
from QMLManager to itself. The slot will be called once the
signal handler terminates and the main event loop retakes
control.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-04 13:57:00 +02:00
Berthold Stoeger
2172e18298 mobile: pull undo/redo notification text up
When changes need saving, the notification text was set quite
deep in the calltree in "saveChangesLocal()". I don't know why
this was put so deep in the call tree. In any case, it prevents
asynchronous saving of the data. Therefore, pull it up to
chnagesNeedSaving().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-04-04 13:57:00 +02:00
Berthold Stoeger
dd466d2d48 statistics: improve formatting of date axis in day-mode
In January it would just show the year for every day. That's
silly. Show the year only for Jan 1st.

Moreover, it would never show the month, because day-of-month
is counted from 1 (whereas month-of-year is counted from 0).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-31 14:20:14 +02:00
Berthold Stoeger
916c88ded9 mobile: fix undo/redo
The signals of the undo-stack can only be connected after it
was initialized. One of those cases where I would have preferred
a crash over a warning message. The mobile version is extremely
noisy!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-31 14:19:44 +02:00
transifex-integration[bot]
176ee1ac9c
Translate subsurface_source.ts in pt_PT
100% translated source file: 'subsurface_source.ts'
on 'pt_PT'.
2024-03-30 16:39:17 +00:00
Berthold Stoeger
83fa38b3b4 cleanup: remove unused function parse_display_units()
This was added in d9b39efeb7998392524ff2197683aef50246c6ab,
but never used as far as I can see...

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-26 17:00:38 +01:00
Berthold Stoeger
2bf7432a94 cleanup: remove unused macros in qmlmanager.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-25 21:41:57 +01:00
Berthold Stoeger
c53cdf039b cleanup: remove unused global variable filesOnCommandLine
Last user was removed in 0a92823af64c76b165ddd2c1bddadd01a5fc6b56.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-25 07:09:05 -07:00
Berthold Stoeger
29d71eb85e cleanup: remove picturedir_string()
This seems to be dead code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-25 06:49:35 +01:00
Berthold Stoeger
2c490fcbbb desktop: take an std::string in MainWindow::setCurrentFile()
This fixes a crash condition when opening the cloud from
desktop: The old code passed a NULL pointer that was then
assigned to an std::string, which is not supported.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-25 06:45:36 +01:00
Michael Keller
6aca76c342 Import / Export: Remove Unsafe XML Handling Options.
Remove the options to expand entities and so continue when encountering invalid /
malformed XML, as both of these can be exploited by supplying
maliciously crafted XML.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-03-24 19:01:05 +01:00
Berthold Stoeger
92c3837f6e cleanup: remove unused taglist functions
No users of taglist_added() and taglist_contains().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
5ac64ab2cd cleanup: replace Q_FOREACH and foreach by range base for
Q_FOREACH and foreach are anachronisms.

Range based for may cause a performance regression: it can
lead to a copy of shared containers (one reason why Qt's
COW containers are broken). However, as long as there is no
user noticeable delay, there is no point in analyzing each case.
And also no point in slapping an 'asConst' on every container
that is looped over.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
41cb916060 core: turn existing_filename into std::string
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
37f2207f94 printing: pass current filename to dialog
Instead of accessing a global variable, pass the filename
from the MainWindow to the dialog. This is supposed to cut
down on the global variable mess.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
3a1122048b core: make logfile_name and dumpfile_name std::string
To avoid memory management woes. These shouldn't be global
variables, but let's fix that later.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
64419f2b19 dive download: pass current filename to dialog
Instead of accessing a global variable, pass the filename
from the MainWindow to the dialog. This is supposed to cut
down on the global variable mess.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
981352646c computer configuration: pass current filename to dialog
Instead of accessing a global variable, pass the filename
from the MainWindow to the dialog. This is supposed to cut
down on the global variable mess.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
2e067c89dd cleanup: Make ConfigureDiveComputerDialog::closeEvent() private
There is no subclass of ConfigureDiveComputerDialog, so there
seems no reason for protected members.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Berthold Stoeger
8733828380 computer configuration: use value semantics for DeviceDetails
The memory managements for DeviceDetails was very sketchy.
First of all, sharing a pointer to a structure between threads
seems like a recipe for disaster. Secondly, the structure was
a QObject and when first generated included in the (silly)
Qt object tree, but when generated in the threads it was not.
Clearly, this leaks.

Instead, use value semantics and use local copies of the
structure. I didn't go full length and use std::move to
move the data, because this doesn't work through signals
(which are the wrong abstraction here, but OK) and secondly
I didn't have time to analyze whether the caller still
needs the data after passing it down to the worker thread.

To be able to pass an object through signals, the class
has to be registered in the Qt MetaType system. Super
ugly, but fine for now. Ultimately, this whole thing should
probably be replaced by futures, co-routines, or whatever.

Moreover, this removes the prefix from  number of "m_*"
function parameters. By convention, "m_" marks member
variables, which function parameters are not.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>

make DeviceDetails a metatype

So that we can pass it as value through the signal/slot system.
(squash with original commit)

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-24 17:53:19 +01:00
Michael Keller
322c1b56b2 CICD: Add smtk2ssrf Build to CI.
Add a build job for smtk2ssrf to the GitHub action for ubuntu jammy.

Signed-off-by: Michael Keller <github@ike.ch>
2024-03-19 20:20:33 +01:00
Michael Keller
8b0b3cba3c CICD: Add Downloader Build to the CI Pipeline.
Add a build for subsurface-downloader to the CI pipeline. The artifact
is currently not used, but this will ensure pull requests breaking the
downloader are spotted before they are merged.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-03-19 20:20:33 +01:00
Richard Fuchs
2533909337 core: fix downloader builds
Downloder builds pull in show_computer_list() from
downloadfromdcthread.cpp, but it's declared as extern "C". With 76c2069f
having converted subsurfacestartup.c to .cpp, we can remove the extern
"C"

Signed-off-by: Richard Fuchs <dfx@dfx.at>
2024-03-16 18:21:52 +01:00
Michael Keller
1508d305b8 Desktop: Add Country to the Fields Indexed for Fulltext Search.
Add 'Country' to the fields that are indexed for fulltext search - this
seems to be a quite intuitive choice as 'Country' is also a field that
is available in the dive list view.

Fixes #4134.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-03-16 17:23:24 +01:00
Michael Keller
8a5009786e Fix Translation Error in Android Build.
Same as iOS.

Signed-off-by: Michael Keller <github@ike.ch>
2024-03-16 13:32:02 +13:00
Dirk Hohndel
153bcdec42 fix incorrect Italian localization on iOS
Stupid cut and paste error...

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-03-15 07:50:29 -07:00
Michael Keller
e6ff3f7537 Cleanup: Fix Problems Raised by Coverity Scan.
Opportunistically fix some problems newly raised by a recent Coverity
scan.

Not touching any of the string memory allocation issues as this is being
handled by the move towards C++ strings.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-03-14 11:42:09 +13:00
Berthold Stoeger
3229d1e3a1 preferences: replace macro by local function
No apparent reason for having this as a hard-to-read macro.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-13 13:17:01 +13:00
Berthold Stoeger
857148efd6 preferences: replace SIGNAL/SLOT by function pointers
This give compile time checking. In fact, one of the connections was
not working (currentIndexChanged(QString) doesn't exist in newer(?)
Qt versions).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-13 13:17:01 +13:00
Berthold Stoeger
8980d61786 core: replace SSRF_INFO macro by report_info()
The point of this macro is unclear. It just calls report_info()
anyway...

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-12 10:31:07 -04:00
Berthold Stoeger
bfbf4934dd core: enable compiler warngings for report_error and report_info
printf() is a horrible interface as it does no type checking.
Let's at least use the compiler to check format strings and
arguments. This obviously doesn't work for translated strings
and using report_error on translated strings is dubious. But OK.

Had to convert a number of report_error() calls to supress
warnings.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-12 10:31:07 -04:00
Berthold Stoeger
fcf0bda042 core: move report_info and SSRF_INFO to errorhelper.h
qthelper.h is an absolute monstrosity and it is unclear what
report_info and SSRF_INFO have to do with Qt.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-12 10:31:07 -04:00
Dirk Hohndel
d653cec7a4 ensure locale language info lands in the applog
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-03-11 11:30:14 -04:00
Dirk Hohndel
8f50c9c1b3 Improve automated language handling
This mimics the code added in commit cf990b0f39 ("preferences: choose language
code with one '-'") and adds some debugging for the mobile case - some people
are being presented with Subsurface-mobile in Korean for some reason.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-03-11 11:30:14 -04:00
Berthold Stoeger
c7a929a8a8 Correctly initialize string in core/device.cpp
When initializing a string with multiple characters, first
comes the length, then the size. Not the other way around.

Fixes #4127.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-11 20:20:18 +13:00
Berthold Stoeger
8b5812bc2c profile: fix uninitialized variable in DivePercentageItem
Fix bug introduced in 505e4e47eb.

Nobody complained, so not clear if that was user visible.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 17:59:32 +01:00
Berthold Stoeger
cf990b0f39 preferences: choose language code with one '-'
On initialization, the old code searched for the first language
code containing a '-'. However, my Qt version gives de-Latn-DE
as the first entry. That messed up the preferences code: it
didn't recognize that entry. Thus, simply opening and closing
the preferences switched the language to Bulgarian.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-09 22:11:11 -05:00
Berthold Stoeger
889ca23999 cleanup: automatically determine array size in load-git.cpp
There was a pattern of code like
match_action(line, state, dive_action, ARRAY_SIZE(dive_action));

The doubling of the array might cause copy & paste errors, where
only one array is replaced.

Therefore, determine the length of the array with (hopefully
easily understood) template tricksery.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
6bf8cbfe46 core: avoid pointless copying in git parser
When iterating over the converted strings of a line, the
first entry of the array would be popped off, leading to
a full copy of the remaining array.

Instead, use an index in the parser state.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
885ff44c56 core: directly generate std::strings in git parser
The converted strings were stored in a membuffer and later
converted to std::strings. Generate an std::string directly
to avoid unnecessary copying.

Ultimately, when the core structures are converted to
std::string, there should be no copying of the string data
at all (unless formatting is applied or small string
optimization kicks in, of course).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
6b054318e0 core: convert parse_mkvi_value() and parse_mkvi_key() to C++
This was a particularly funny one: It trampled on and then
restored the buffer.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
cca4c8cae5 core: return std::string from get_dive_date_c_string()
Had to convert uemis-donwloader.c to C++. Lot's of
non-const clean code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
203ff8b2e6 core: port string handling in divecomputer.cpp to C++
Replace formatstring() by the C++ version.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
ad7530f7bb core: use std::string for dummy hash value in parser
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
affcbddbb0 core: use std::string to format battery extra data
Create a format_string_std function that works like format_string,
but does return a std::string instead of a strdup()ed C string.

Make it a global function to be used in other parts of the code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
e6321a1305 core: turn extra_data key/value pair in parser to std::string
Less troublesome memory management.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
92a1a08b21 core: remove alloc_filter_preset() and free_filter_preset()
All users of that are now C++ and don't need these helpers.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
cf7c54bd56 core: turn a memblock in the parser to std::string
This avoid memory-management troubles. Had to convert a few
of the parsers (cochran, datatrak, liquivision) to C++.
Also had to convert libdivecomputer.c. This was less
painful than expected.

std::string is used because parts of the code assumes
that the data is null terminated after the last character
of the data. std::string does precisely that.

One disadvantage is that std::string clears its memory
when resizing / initializing. Thus we read the file onto
freshly cleared data, which some might thing is a
performance regression. Until someone shows me that this
matters, I don't care.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
2f4dbf1848 core: make get_sha() return std::string
This was crazy: it returned a local static buffer, i.e. was
inherently non-reentrant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
2f3d8d83f5 core: port printGPSCoordsC to return std::string
Less memory management hassle.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
119fe908c7 core: port filterpreset.cpp to std::string
Less memory management hassle.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
2e1d852e36 core: convert filter_constraint_data_to_string to C++
Return an std::string to avoid memory management headaches.

While doing that, convert time.c to C++ so that
format_datetime directly returns an std::string.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
898ecd2df5 core: make fp_get_data return an std::string
No need for manual memory management.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
8d96b7557d core: convert parser_state to C++
Add constructor, destructor and use std::string for memory
management of text data.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
5e466d91f0 core: convert core/import-*.c to C++
import-csv.c was crazy with implicit (const char *) to (char *)
conversions!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
83b0c1da40 core: convert parse-xml.c and parse.c to C++
This was very annoying, because the old code was not const-clean
at all and trampled all over buffers. This makes the new code
pretty messy for now.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
a133c6c4db mobile: turn testqml into a std::string
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
9509eb6876 divetripmodel: explicitly convert char * to QString
The automatic conversion from char * to QVariant failed to
compile for me. Let's hint that this should be interpreted
as a string. No idea, why this happens for me, but apparently
not on CI.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
43ec3fc1d9 core: use std::string in load-git.cpp
Make the memory management easier to follow. I feel that the old
code was leaking left and right, but not sure because it was so
intractable.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
114513493b core: use std::string in parser state of git loader
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
a1826f77da core: turn saved_git_id into a std::string
Simplifies memory management. Think about unglobalizing this,
once everything is in C++ so that we can put an std::string
into struct divelog.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
c05be40bfd core: convert load-git.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
d803e42314 core: convert file.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
a032d9c979 core: convert save-xml.c to C++
This includes using the C++ version of membuffer. There appears
to not have been a leak, because the buffer is freed in
flush_buffer(), but usage was somewhat inconsistent and hard to
follow.

Also, convert some string handling to std::string to avoid free()
madness.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
76c2069fa8 core: port subsurface-startup.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
f1012283a0 core: turn a few string helpers into C++
get_changes_made(), subsurface_user_agent() and normalize_cloud_name()
are only called from C++.

Avoids having to manually free the returned value and is therefore
more robust against leaks.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
924b23ed56 core: convert git-access.c to C++
Had to make sha.h compatible with C++.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
b0438ad1dd core: use C++-style memory management for struct dir
The code is now much easier to check for memory leaks,
since there are no explicit free()s. Yes, memory is not
released immediately, but that should be of no concern.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
371b155922 core: convert core/save-git.c to C++
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
148775f418 core: convert sample.c to C++ and add default constructor
This changes default behavior when creating a sample struct
in C++ code: it is now initialized to default values. If this
ever turns out to be a performance problem, we can either add
additional constructors or use special functions that do
not initialize memory, such as make_unique_for_overwrite.

This removes non-standard (respectively >C++20) constructs,
namely designated initializers.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
c27e093ebd core: replace dynamic arrays in dive.cpp by C++ constructs
Avoid error-prone malloc/free pairs. This uses somewhat
obscure constructs to stay as close as possible to the
original C code. Notably, it uses mostly unique_ptr<T[]>
which doesn't store the length of the array, because the
length is supposed to be known.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
52e6a098aa core: convert dive.c to C++
Long term project: convert core to C++ so that we can
use higer-level constructs, notably std::vector<>.

This does not change any code - only fixes compile issues.

Mostly casting of (void *) to the proper type. Also designated
initialization of the sample struct had to be rearranged.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
Berthold Stoeger
096e49e15b core: make translate() accessible from C++
In the core, we usually want C strings, not QStrings. Therefore,
make translated C strings directly available from C++.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-10 11:01:42 +13:00
transifex-integration[bot]
0ea287cc2c
Translate subsurface_source.ts in de_DE
100% translated source file: 'subsurface_source.ts'
on 'de_DE'.
2024-03-09 16:14:26 +00:00
transifex-integration[bot]
8c861f749f
Translate subsurface_source.ts in de_DE
100% translated source file: 'subsurface_source.ts'
on 'de_DE'.
2024-03-09 16:07:59 +00:00
transifex-integration[bot]
f1bd5dc051
Translate subsurface_source.ts in de_DE
100% translated source file: 'subsurface_source.ts'
on 'de_DE'.
2024-03-09 16:07:04 +00:00
transifex-integration[bot]
d64986415c
Translate subsurface_source.ts in de_DE
100% translated source file: 'subsurface_source.ts'
on 'de_DE'.
2024-03-09 16:06:38 +00:00
Dirk Hohndel
649ed8a9ae Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_ca' 2024-03-08 15:16:23 -08:00
Dirk Hohndel
569c5520af Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_nl_NL' 2024-03-08 15:15:53 -08:00
Dirk Hohndel
5dc4c5855b Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_en_GB' 2024-03-08 15:15:18 -08:00
Dirk Hohndel
af8f67ed5f Merge remote-tracking branch 'origin/translations_translations-subsurface-source-ts--master_de_DE' 2024-03-08 15:14:38 -08:00
Berthold Stoeger
9d2bd425e1 core: fix memory leak in tables code
The function clear_*_table frees all elements of the table.
However, persumably as a performance feature, it kept the
memory of the table itselt (i.e. it only reset the number of
elements but kept the capacity).

That is fine if the table is reused later. However, this
function was also used when freeing the table and this
would leak the table memory.

This commit frees the table memory. An alternative would
be to have separate clear_*_table and free_*_table functions.
But let's wait with that until we port the table code to C++.
Then this will be "automatically" fixed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-07 07:55:23 -05:00
transifex-integration[bot]
4b1a6f8824
Translate translations/subsurface_source.ts in ca
100% translated source file: 'translations/subsurface_source.ts'
on 'ca'.
2024-03-04 01:40:49 +00:00
transifex-integration[bot]
6c2b126c8e
Translate translations/subsurface_source.ts in ca
100% translated source file: 'translations/subsurface_source.ts'
on 'ca'.
2024-03-04 01:40:34 +00:00
Berthold Stoeger
805cd550f2 cleanup: fix memory leak
get_local_dir() returns the copy of a c-string. It therefore
has to be free()d.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-03 14:59:31 -08:00
Berthold Stoeger
a4091189b0 cleanup: use proper size when allocating string
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-02 19:21:59 +01:00
Berthold Stoeger
ef5859437a cleanup: remove ominous pointer calculation
Firstly, why calculate something when the next statement is a return
anyway.

Secondly, the calculation subtracts two completely unrelated pointers.

This must be some code reshuffling artifact.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-01 12:28:52 -08:00
Michał Sawicz
96470227d5 snap: fix grade determination
Determine grade based on whether we actually managed to check out the
buildnumber.

This assumes that the tree is clean for building a stable snap (one that
can be published to candidate and stable channels).

Signed-off-by: Michał Sawicz <michal@sawicz.net>
2024-03-01 09:03:28 -08:00
Berthold Stoeger
cb3e21c443 cleanup: remove unused data and bogus UNUSED in libdivecomputer.c
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-01 07:57:34 -08:00
transifex-integration[bot]
9d3498f01e
Translate subsurface_source.ts in nl_NL
100% translated source file: 'subsurface_source.ts'
on 'nl_NL'.
2024-02-29 19:58:56 +00:00
transifex-integration[bot]
afcff5da2b
Translate subsurface_source.ts in nl_NL
100% translated source file: 'subsurface_source.ts'
on 'nl_NL'.
2024-02-29 19:57:24 +00:00
transifex-integration[bot]
10d95531ff
Translate subsurface_source.ts in en_GB
100% translated source file: 'subsurface_source.ts'
on 'en_GB'.
2024-02-29 12:23:40 +00:00
Michael Keller
cedccbc340 Import: Update the libdivecomputer Submodule.
Update the libdivecomputer submodule.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-02-28 15:38:48 +13:00
Michael Keller
3ccd7e4bc7 Import: Add Support for New Dive Computer Models Supported by Libdivecomputer.
Add support for the new dive computer models that have been added in the
latest version of libdivecomputer.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-02-28 15:38:48 +13:00
Michael Keller
f495c4f002 Import: Update libdivecomputer to the Latest Version.
Update `libdivecomputer` to the latest upstream version.

Signed-off-by: Michael Keller <mikeller@042.ch>
2024-02-28 15:38:48 +13:00
Miika Turkia
4642f12e29 Divelogs.de integration update
Adding temp support for divelogs.de import/export.

Adding export of divecomputer model to divelogs.de export

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2024-02-27 15:44:32 -08:00
Michał Sawicz
c3aa505f2b snap: fix grade-setting
> variable 'grade' can be set only once.

Signed-off-by: Michał Sawicz <michal@sawicz.net>
2024-02-27 06:52:45 -08:00
Berthold Stoeger
bf5510e5a6 cleanup: remove bogus forward declaration of inexistent structure
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-02-27 13:14:34 +01:00
transifex-integration[bot]
8e023717f7
Translate subsurface_source.ts in de_DE
100% translated source file: 'subsurface_source.ts'
on 'de_DE'.
2024-02-24 22:09:16 +00:00
Dirk Hohndel
0cb5273766 Update translation source strings
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-02-24 10:30:02 -08:00
transifex-integration[bot]
bca8eabcec Translate subsurface_source.ts in bg_BG
100% translated source file: 'subsurface_source.ts'
on 'bg_BG'.
2024-02-24 10:30:02 -08:00
transifex-integration[bot]
5ab5bc51cd Translate subsurface_source.ts in es_ES
100% translated source file: 'subsurface_source.ts'
on 'es_ES'.
2024-02-24 10:30:02 -08:00
transifex-integration[bot]
36a76e015f Translate subsurface_source.ts in es_ES
100% translated source file: 'subsurface_source.ts'
on 'es_ES'.
2024-02-24 10:30:02 -08:00
Dirk Hohndel
4b0fe3bc38 mobile: show incorrect cloud password state
While the startup flow should make it obvious when a user is not
correctly logged into the cloud, we still do see fairly frequent
situations where a user has an incorrect password on a mobile device and
is confused about why their data isn't syncing with their PC. Now this
is clearly shown in the main menu.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2024-02-23 20:12:12 -08:00
313 changed files with 11838 additions and 11917 deletions

View File

@ -10,7 +10,7 @@ ColumnLimit: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
ForEachMacros: [ 'foreach', 'for_each_dc', 'for_each_relevant_dc', 'for_each_dive', 'for_each_line', 'Q_FOREACH' ]
ForEachMacros: [ 'for_each_dc', 'for_each_relevant_dc', 'for_each_dive', 'for_each_line' ]
IndentFunctionDeclarationAfterType: false #personal taste, good for long methods
IndentWidth: 8
MaxEmptyLinesToKeep: 2

View File

@ -0,0 +1,56 @@
name: Manage the Subsurface CICD versioning
inputs:
no-increment:
description: 'Only get the current version, do not increment it even for push events (Caution: not actually a boolean)'
default: false
nightly-builds-secret:
description: The secret to access the nightly builds repository
default: ''
outputs:
version:
description: The long form version number
value: ${{ steps.version_number.outputs.version }}
buildnr:
description: The build number
value: ${{ steps.version_number.outputs.buildnr }}
runs:
using: composite
steps:
- name: atomically create or retrieve the build number and assemble release notes for a push (i.e. merging of a pull request)
if: github.event_name == 'push' && inputs.no-increment == 'false'
env:
NIGHTLY_BUILDS_SECRET: ${{ inputs.nightly-builds-secret }}
shell: bash
run: |
if [ -z "$NIGHTLY_BUILDS_SECRET" ]; then
echo "Need to supply the secret for the nightly-builds repository to increment the version number, aborting."
exit 1
fi
scripts/get-atomic-buildnr.sh $GITHUB_SHA $NIGHTLY_BUILDS_SECRET "CICD-release"
- name: retrieve the current version number in all other cases
if: github.event_name != 'push' || inputs.no-increment != 'false'
env:
PULL_REQUEST_BRANCH: ${{ github.event.pull_request.head.ref }}
shell: bash
run: |
echo "pull-request-$PULL_REQUEST_BRANCH" > latest-subsurface-buildnumber-extension
- name: store version number for the build
id: version_number
env:
PULL_REQUEST_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
shell: bash
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
# For a pull request we need the information from the pull request branch
# and not from the merge branch on the pull request
git checkout $PULL_REQUEST_HEAD_SHA
version=$(scripts/get-version.sh)
echo "version=$version" >> $GITHUB_OUTPUT
buildnr=$(scripts/get-version.sh 1)
echo "buildnr=$buildnr" >> $GITHUB_OUTPUT
git checkout $GITHUB_SHA

View File

@ -15,17 +15,17 @@ jobs:
VERSION: ${{ '5.15.2' }} # the version numbers here is based on the Qt version, the third digit is the rev of the docker image
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: Build the name for the docker image
id: build_name
run: |
v=${{ env.VERSION }}
b=${{ github.ref }} # -BRANCH suffix, unless the branch is master
v=$VERSION
b=$GITHUB_REF # -BRANCH suffix, unless the branch is master
b=${b/refs\/heads\//}
b=${b,,} # the name needs to be all lower case
if [ $b = "master" ] ; then b="" ; else b="-$b" ; fi
echo "NAME=subsurface/android-build${b}:${v}" >> $GITHUB_OUTPUT
echo "NAME=$GITHUB_REPOSITORY_OWNER/android-build${b}:${v}" >> $GITHUB_OUTPUT
- name: Build and Publish Linux Docker image to Dockerhub
uses: elgohr/Publish-Docker-Github-Action@v5

View File

@ -1,4 +1,5 @@
name: Android
on:
push:
paths-ignore:
@ -11,12 +12,10 @@ on:
branches:
- master
env:
BUILD_ROOT: ${{ github.workspace }}/..
KEYSTORE_FILE: ${{ github.workspace }}/../subsurface.keystore
jobs:
buildAndroid:
build:
env:
KEYSTORE_FILE: ${{ github.workspace }}/../subsurface.keystore
runs-on: ubuntu-latest
container:
image: docker://subsurface/android-build:5.15.2
@ -24,32 +23,33 @@ jobs:
steps:
- name: checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: atomically create or retrieve the build number and assemble release notes
- name: set the version information
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
- name: store dummy version and build number for non-push build runs
if: github.event_name != 'push'
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-pull-request" > latest-subsurface-buildnumber-extension
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: set up the keystore
if: github.event_name == 'push'
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > $KEYSTORE_FILE
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > $KEYSTORE_FILE
- name: run build
id: build
env:
KEYSTORE_PASSWORD: pass:${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEYSTORE_ALIAS }}
BUILDNR: ${{ steps.version_number.outputs.buildnr }}
run: |
# this is rather awkward, but it allows us to use the preinstalled
# Android and Qt versions with relative paths
cd $BUILD_ROOT
cd ..
ln -s /android/5.15.* .
ln -s /android/build-tools .
ln -s /android/cmdline-tools .
@ -62,17 +62,25 @@ jobs:
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
# get the build number via curl so this works both for a pull request as well as a push
BUILDNR=$(curl -q https://raw.githubusercontent.com/subsurface/nightly-builds/main/latest-subsurface-buildnumber)
export OUTPUT_DIR="$GITHUB_WORKSPACE"
export KEYSTORE_FILE="$KEYSTORE_FILE"
export KEYSTORE_PASSWORD="pass:${{ secrets.ANDROID_KEYSTORE_PASSWORD }}"
export KEYSTORE_ALIAS="${{ secrets.ANDROID_KEYSTORE_ALIAS }}"
bash -x ./subsurface/packaging/android/qmake-build.sh -buildnr ${BUILDNR}
bash -x ./subsurface/packaging/android/qmake-build.sh -buildnr $BUILDNR
- name: delete the keystore
if: github.event_name == 'push'
run: |
rm $KEYSTORE_FILE
- name: publish pull request artifacts
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: Subsurface-Android-${{ steps.version_number.outputs.version }}
path: Subsurface-mobile-*.apk
# only publish a 'release' on push events (those include merging a PR)
- name: upload binaries
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds
@ -81,8 +89,3 @@ jobs:
fail_on_unmatched_files: true
files: |
Subsurface-mobile-${{ steps.version_number.outputs.version }}.apk
- name: delete the keystore
if: github.event_name == 'push'
run: |
rm $KEYSTORE_FILE

24
.github/workflows/artifact-links.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Add artifact links to pull request
on:
workflow_run:
workflows: ["Ubuntu 16.04 / Qt 5.15-- for AppImage", "Mac", "Windows", "Android", "iOS"]
types: [completed]
jobs:
artifacts-url-comments:
name: Add artifact links to PR and issues
runs-on: ubuntu-22.04
steps:
- name: Add artifact links to PR and issues
if: github.event.workflow_run.event == 'pull_request'
uses: tonyhallett/artifacts-url-comments@v1.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
prefix: "**Artifacts:**"
suffix: "_**WARNING:** Use at your own risk._"
format: name
addTo: pull
errorNoArtifacts: false

View File

@ -25,20 +25,19 @@ jobs:
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['cpp', 'javascript']
language: ['c-cpp', 'javascript-typescript']
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
fetch-depth: 0
submodules: recursive
- name: get container ready for build
run: |
sudo apt-get update
sudo apt-get install -y -q --force-yes \
sudo apt-get install -y -q \
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
@ -51,7 +50,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -60,13 +59,11 @@ jobs:
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Build
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
cd ..
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
bash -e -x subsurface/scripts/build.sh -desktop -build-with-webkit
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3

View File

@ -1,4 +1,5 @@
name: Coverity Scan Linux Qt 5.9
on:
schedule:
- cron: '0 18 * * *' # Daily at 18:00 UTC
@ -10,14 +11,11 @@ jobs:
image: ubuntu:22.04
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: add build dependencies
run: |
apt-get update
apt-get upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q --force-yes \
apt-get dist-upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
wget curl \
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
@ -29,12 +27,22 @@ jobs:
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
qtquickcontrols2-5-dev libbluetooth-dev libmtp-dev
- name: checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: configure environment
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
- name: get the version information
id: version_number
uses: ./.github/actions/manage-version
with:
no-increment: true
- name: run coverity scan
uses: vapier/coverity-scan-action@v1
@ -44,5 +52,5 @@ jobs:
email: glance@acc.umu.se
command: subsurface/scripts/build.sh -desktop -build-with-webkit
working-directory: ${{ github.workspace }}/..
version: $(/scripts/get-version)
version: ${{ steps.version_number.outputs.version }}
description: Automatic scan on github actions

View File

@ -26,6 +26,9 @@ jobs:
- name: Checkout Sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: Process the Documentation
id: process_documentation

View File

@ -11,30 +11,32 @@ jobs:
setup-build:
name: Submit build to Fedora COPR
# this seems backwards, but we want to run under Fedora, but Github doesn' support that
container: fedora:latest
runs-on: ubuntu-latest
container:
image: fedora:latest
steps:
- name: Check out sources
uses: actions/checkout@v1
- name: Setup build dependencies in the Fedora container
run: |
dnf -y install @development-tools @rpm-development-tools
dnf -y install copr-cli make
- name: Check out sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: setup git
run: |
git config --global --add safe.directory /__w/subsurface/subsurface
git config --global --add safe.directory /__w/subsurface/subsurface/libdivecomputer
- name: atomically create or retrieve the build number
- name: set the version information
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: Setup API token for copr-cli
env:
@ -53,5 +55,5 @@ jobs:
- name: run the copr build script
run: |
cd ..
bash -x subsurface/packaging/copr/make-package.sh ${{ github.ref_name }}
bash -x subsurface/packaging/copr/make-package.sh $GITHUB_REF_NAME

View File

@ -1,4 +1,5 @@
name: iOS
on:
push:
paths-ignore:
@ -12,37 +13,49 @@ on:
- master
jobs:
iOSBuild:
build:
runs-on: macOS-11
steps:
- name: switch to Xcode 11
run: sudo xcode-select -s "/Applications/Xcode_11.7.app"
- name: checkout sources
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: setup Homebrew
run: brew install autoconf automake libtool pkg-config
- name: set our Qt build
run: |
env
curl -L --output Qt-5.14.1-ios.tar.xz https://f002.backblazeb2.com/file/Subsurface-Travis/Qt-5.14.1-ios.tar.xz
mkdir -p $HOME/Qt
xzcat Qt-5.14.1-ios.tar.xz | tar -x -C $HOME/Qt -f -
- name: checkout Qt resources
uses: actions/checkout@v4
with:
repository: subsurface/qt-ios
ref: main
path: qt-ios
- name: store dummy version and build number for test build
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: build Subsurface-mobile for iOS
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
VERSION: ${{ steps.version_number.outputs.version }}
run: |
cd ${SUBSURFACE_REPO_PATH}/..
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
ln -s $HOME/Qt Qt
cd ..
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
export IOS_QT=$GITHUB_WORKSPACE/qt-ios
echo "build for simulator"
bash -x $GITHUB_WORKSPACE/packaging/ios/build.sh -simulator
# We need this in order to be able to access the file and publish it
mv build-Subsurface-mobile-Qt_5_14_1_for_iOS-Release/Release-iphonesimulator/Subsurface-mobile.app $GITHUB_WORKSPACE/Subsurface-mobile-$VERSION.app
- name: publish artifacts
uses: actions/upload-artifact@v4
with:
name: Subsurface-iOS-${{ steps.version_number.outputs.version }}
path: Subsurface-mobile-*.app

View File

@ -1,55 +0,0 @@
name: Ubuntu 18.04 / Qt 5.9--
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
buildOnBionic:
runs-on: ubuntu-18.04
container:
image: ubuntu:18.04 # yes, this looks redundant, but something is messed up with their Ubuntu image that causes our builds to fail
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: add build dependencies
run: |
apt update
apt install -y \
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
libtool libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make \
pkg-config qml-module-qtlocation qml-module-qtpositioning \
qml-module-qtquick2 qt5-default qt5-qmake qtchooser qtconnectivity5-dev \
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
qtquickcontrols2-5-dev xvfb libbluetooth-dev libmtp-dev
- name: store dummy version and build number for pull request
if: github.event_name == 'pull_request'
run: |
echo "6.0.100" > latest-subsurface-buildnumber
- name: build Subsurface
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
cd ..
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
bash -x subsurface/scripts/build.sh -desktop -build-with-webkit
- name: test desktop build
run: |
# and now run the tests - with Qt 5.9 we can only run the desktop flavor
echo "------------------------------------"
echo "run tests"
cd build/tests
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check

View File

@ -1,34 +1,27 @@
name: Ubuntu 22.04 / Qt 5.15--
name: Generic workflow for Debian and derivatives
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
workflow_call:
inputs:
container-image:
required: true
type: string
jobs:
buildUbuntuJammy:
build:
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
image: ${{ inputs.container-image }}
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: get container ready for build
run: |
echo "--------------------------------------------------------------"
echo "update distro and install dependencies"
apt-get update
apt-get upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q --force-yes \
apt-get dist-upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
@ -37,23 +30,30 @@ jobs:
qml-module-qtquick2 qt5-qmake qtchooser qtconnectivity5-dev \
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
qtquickcontrols2-5-dev xvfb libbluetooth-dev libmtp-dev
qtquickcontrols2-5-dev xvfb libbluetooth-dev libmtp-dev \
mdbtools-dev
- name: store dummy version and build number for test build
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
git config --global user.email "ci@subsurface-divelog.org"
git config --global user.name "Subsurface CI"
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
# needs git from the previous step
- name: checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: build Subsurface-mobile
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
no-increment: true
- name: build subsurface-mobile
run: |
echo "--------------------------------------------------------------"
echo "building mobile"
git config --global user.email "ci@subsurface-divelog.org"
git config --global user.name "Subsurface CI"
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
cd ..
bash -e -x subsurface/scripts/build.sh -mobile
@ -66,7 +66,7 @@ jobs:
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check
- name: build Subsurface
- name: build subsurface
run: |
echo "--------------------------------------------------------------"
echo "building desktop"
@ -83,3 +83,18 @@ jobs:
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check
- name: build subsurface-downloader
run: |
echo "--------------------------------------------------------------"
echo "building downloader"
cd ..
bash -e -x subsurface/scripts/build.sh -downloader
- name: build smtk2ssrf
run: |
echo "--------------------------------------------------------------"
echo "building smtk2ssrf"
# build smtk2ssrf (needs the artefacts generated by the subsurface build
cd ..
bash -e -x subsurface/scripts/smtk2ssrf-build.sh -y

View File

@ -0,0 +1,19 @@
name: Debian trixie / Qt 5.15--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
do-build-test:
uses: ./.github/workflows/linux-debian-generic.yml
with:
container-image: debian:trixie

View File

@ -1,39 +0,0 @@
name: Linux Qt 5.12 Docker Image CI
#on:
# push:
# paths:
# - scripts/docker/trusty-qt512/Dockerfile
# - .github/workflows/linux-docker*
jobs:
trusty-qt512:
runs-on: ubuntu-latest
env:
VERSION: ${{ '1.0' }} # 'official' images should have a dot-zero version
steps:
- uses: actions/checkout@v1
- name: Get our pre-reqs
run: |
cd scripts/docker/trusty-qt512
bash getpackages.sh
- name: set env
run: |
v=${{ env.VERSION }}
b=${{ github.ref }} # -BRANCH suffix, unless the branch is master
b=${b/refs\/heads\//}
b=${b,,} # the name needs to be all lower case
if [ $b = "master" ] ; then b="" ; else b="-$b" ; fi
echo "::set-env name=NAME::subsurface/trusty-qt512${b}:${v}"
- name: Build and Publish Linux Docker image to Dockerhub
uses: elgohr/Publish-Docker-Github-Action@master
with:
name: ${{ env.NAME }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
dockerfile: 'Dockerfile'
workdir: './scripts/docker/trusty-qt512/'

View File

@ -1,4 +1,5 @@
name: Fedora 35 / Qt 6--
on:
push:
paths-ignore:
@ -12,15 +13,12 @@ on:
- master
jobs:
buildFedoraQt6:
build:
runs-on: ubuntu-latest
container:
image: fedora:35
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: get container ready for build
run: |
echo "--------------------------------------------------------------"
@ -37,22 +35,27 @@ jobs:
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel \
xorg-x11-server-Xvfb
- name: store dummy version and build number for test build
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
- name: checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
no-increment: true
- name: build Subsurface
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
echo "--------------------------------------------------------------"
echo "building desktop"
# now build for the desktop version (without WebKit)
cd ..
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
git config --global --add safe.directory $GITHUB_WORKSPACE
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
git config --global --get-all safe.directory
bash -e -x subsurface/scripts/build.sh -desktop -build-with-qt6

View File

@ -1,85 +0,0 @@
name: Ubuntu 20.04 / Qt 5.12--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
buildUbuntuFocal:
runs-on: ubuntu-latest
container:
image: ubuntu:20.04
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: get container ready for build
run: |
echo "--------------------------------------------------------------"
echo "update distro and install dependencies"
apt-get update
apt-get upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q --force-yes \
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
libtool libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make \
pkg-config qml-module-qtlocation qml-module-qtpositioning \
qml-module-qtquick2 qt5-qmake qtchooser qtconnectivity5-dev \
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
qtquickcontrols2-5-dev xvfb libbluetooth-dev libmtp-dev
- name: store dummy version and build number for test build
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
- name: build Subsurface-mobile
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
echo "--------------------------------------------------------------"
echo "building mobile"
git config --global user.email "ci@subsurface-divelog.org"
git config --global user.name "Subsurface CI"
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
cd ..
bash -e -x subsurface/scripts/build.sh -mobile
- name: test mobile build
run: |
echo "--------------------------------------------------------------"
echo "running tests for mobile"
cd build-mobile/tests
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check
- name: build Subsurface
run: |
echo "--------------------------------------------------------------"
echo "building desktop"
# now build for the desktop version (including WebKit)
cd ..
bash -e -x subsurface/scripts/build.sh -desktop -build-with-webkit
- name: test desktop build
run: |
echo "--------------------------------------------------------------"
echo "running tests for desktop"
cd build/tests
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check

View File

@ -19,16 +19,16 @@ jobs:
timeout-minutes: 60
steps:
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Needed for version determination to work
fetch-depth: 0
submodules: recursive
- name: atomically create or retrieve the build number
- name: set the version information
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: store dummy version and build number for pull request
if: github.event_name == 'pull_request'
@ -48,11 +48,11 @@ jobs:
/snap/bin/lxc profile device add default ccache disk source=${HOME}/.ccache/ path=/root/.ccache
# Patch snapcraft.yaml to enable ccache
patch -p1 < .github/workflows/linux-snap.patch
patch -p1 < .github/workflows/scripts/linux-snap.patch
# Find common base between master and HEAD to use as cache key.
git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules origin master
echo "key=$( git merge-base origin/master ${{ github.sha }} )" >> $GITHUB_OUTPUT
echo "key=$( git merge-base origin/master $GITHUB_SHA )" >> $GITHUB_OUTPUT
- name: CCache
uses: actions/cache@v3
@ -73,7 +73,7 @@ jobs:
- name: Upload the snap
if: github.event_name == 'push'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: ${{ steps.build-snap.outputs.snap-name }}
path: ${{ steps.build-snap.outputs.snap-path }}

View File

@ -1,77 +0,0 @@
name: Ubuntu 14.04 / Qt 5.12 for AppImage--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
buildAppImage:
runs-on: ubuntu-latest
container:
image: docker://subsurface/trusty-qt512:1.1
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: atomically create or retrieve the build number and assemble release notes
id: version_number
if: github.event_name == 'push'
run: |
bash ./scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
- name: store dummy version and build number for pull request
if: github.event_name == 'pull_request'
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-pull-request" > latest-subsurface-buildnumber-extension
- name: run build
env:
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
run: |
cd ..
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
rm -rf /install-root/include/libdivecomputer
bash -x subsurface/.github/workflows/scripts/linux-in-container-build.sh
- name: prepare PR artifacts
if: github.event_name == 'pull_request'
run: |
mkdir -p Linux-artifacts
mv Subsurface.AppImage Linux-artifacts
- name: PR artifacts
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v3
with:
name: Linux-artifacts
path: Linux-artifacts
- name: prepare release artifacts
if: github.event_name == 'push'
run: |
mv Subsurface.AppImage Subsurface-v${{ steps.version_number.outputs.version }}.AppImage
# only publish a 'release' on push events (those include merging a PR)
- name: upload binaries
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds
token: ${{ secrets.NIGHTLY_BUILDS }}
prerelease: false
fail_on_unmatched_files: true
files: |
./Subsurface*.AppImage

View File

@ -0,0 +1,149 @@
name: Ubuntu 16.04 / Qt 5.15-- for AppImage
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
container:
image: ubuntu:16.04
steps:
- name: get container ready for build
run: |
echo "--------------------------------------------------------------"
echo "update distro and install dependencies"
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
software-properties-common
add-apt-repository -y ppa:savoury1/qt-5-15
add-apt-repository -y ppa:savoury1/kde-5-80
add-apt-repository -y ppa:savoury1/gpg
add-apt-repository -y ppa:savoury1/ffmpeg4
add-apt-repository -y ppa:savoury1/vlc3
add-apt-repository -y ppa:savoury1/gcc-9
add-apt-repository -y ppa:savoury1/display
add-apt-repository -y ppa:savoury1/apt-xenial
add-apt-repository -y ppa:savoury1/gtk-xenial
add-apt-repository -y ppa:savoury1/qt-xenial
add-apt-repository -y ppa:savoury1/kde-xenial
add-apt-repository -y ppa:savoury1/backports
add-apt-repository -y ppa:savoury1/build-tools
apt-get update
apt-get dist-upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
autoconf automake cmake g++ g++-9 git libcrypto++-dev libcurl4-gnutls-dev \
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
libtool libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make \
pkg-config qml-module-qtlocation qml-module-qtpositioning \
qml-module-qtquick2 qt5-qmake qtchooser qtconnectivity5-dev \
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
qtquickcontrols2-5-dev xvfb libbluetooth-dev libmtp-dev liblzma-dev \
curl
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 60 \
--slave /usr/bin/g++ g++ /usr/bin/g++-9
- name: checkout sources
# We cannot update this as glibc on 16.04 is too old for node 20.
uses: actions/checkout@v3
with:
fetch-depth: 0
submodules: recursive
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: build Subsurface
run: |
echo "--------------------------------------------------------------"
echo "building desktop"
# now build the appimage
cd ..
bash -e -x subsurface/scripts/build.sh -desktop -create-appdir -build-with-webkit
- name: test desktop build
run: |
echo "--------------------------------------------------------------"
echo "running tests for desktop"
cd build/tests
# xvfb-run --auto-servernum ./TestGitStorage -v2
xvfb-run --auto-servernum make check
- name: build appimage
env:
VERSION: ${{ steps.version_number.outputs.version }}
run: |
echo "--------------------------------------------------------------"
echo "assembling AppImage"
export QT_PLUGIN_PATH=$QT_ROOT/plugins
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins
export QT_DEBUG_PLUGINS=1
cd ..
# set up the appdir
mkdir -p appdir/usr/plugins/
# mv googlemaps plugins into place
mv appdir/usr/usr/lib/x86_64-linux-gnu/qt5/plugins/* appdir/usr/plugins # the usr/usr is not a typo, that's where it ends up
rm -rf appdir/usr/home/ appdir/usr/include/ appdir/usr/share/man/ # No need to ship developer and man files as part of the AppImage
rm -rf appdir/usr/usr appdir/usr/lib/x86_64-linux-gnu/cmake appdir/usr/lib/pkgconfig
cp /usr/lib/x86_64-linux-gnu/libssl.so.1.1 appdir/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 appdir/usr/lib/
# get the linuxdeployqt tool and run it to collect the libraries
curl -L -O "https://github.com/probonopd/linuxdeployqt/releases/download/7/linuxdeployqt-7-x86_64.AppImage"
chmod a+x linuxdeployqt*.AppImage
unset QTDIR
unset QT_PLUGIN_PATH
unset LD_LIBRARY_PATH
./linuxdeployqt*.AppImage --appimage-extract-and-run ./appdir/usr/share/applications/*.desktop -exclude-libs=libdbus-1.so.3 -bundle-non-qt-libs -qmldir=./subsurface/stats -qmldir=./subsurface/map-widget/ -verbose=2
# create the AppImage
./linuxdeployqt*.AppImage --appimage-extract-and-run ./appdir/usr/share/applications/*.desktop -exclude-libs=libdbus-1.so.3 -appimage -qmldir=./subsurface/stats -qmldir=./subsurface/map-widget/ -verbose=2
# copy AppImage to the calling VM
# with GitHub Actions the $GITHUB_WORKSPACE directory is the current working directory at the start of a step
cp Subsurface*.AppImage* $GITHUB_WORKSPACE/Subsurface-$VERSION.AppImage
- name: PR artifacts
if: github.event_name == 'pull_request'
# We cannot update this as glibc on 16.04 is too old for node 20.
uses: actions/upload-artifact@v3
with:
name: Subsurface-Linux-AppImage-${{ steps.version_number.outputs.version }}
path: Subsurface-*.AppImage
compression-level: 0
# only publish a 'release' on push events (those include merging a PR)
- name: upload binaries
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds
token: ${{ secrets.NIGHTLY_BUILDS }}
prerelease: false
fail_on_unmatched_files: true
files: |
./Subsurface-*.AppImage

View File

@ -0,0 +1,19 @@
name: Ubuntu 20.04 / Qt 5.12--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
do-build-test:
uses: ./.github/workflows/linux-debian-generic.yml
with:
container-image: ubuntu:20.04

View File

@ -0,0 +1,19 @@
name: Ubuntu 22.04 / Qt 5.15--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
do-build-test:
uses: ./.github/workflows/linux-debian-generic.yml
with:
container-image: ubuntu:22.04

View File

@ -0,0 +1,19 @@
name: Ubuntu 24.04 / Qt 5.15--
on:
push:
paths-ignore:
- scripts/docker/**
branches:
- master
pull_request:
paths-ignore:
- scripts/docker/**
branches:
- master
jobs:
do-build-test:
uses: ./.github/workflows/linux-debian-generic.yml
with:
container-image: ubuntu:24.04

View File

@ -1,4 +1,5 @@
name: Mac
on:
push:
paths-ignore:
@ -11,38 +12,38 @@ on:
branches:
- master
jobs:
buildMac:
build:
runs-on: macOS-11
steps:
- name: checkout sources
uses: actions/checkout@v1
- name: atomically create or retrieve the build number and assemble release notes
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
- name: store dummy version and build number for pull request
if: github.event_name == 'pull_request'
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-pull-request" > latest-subsurface-buildnumber-extension
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: setup Homebrew
run: brew install hidapi libxslt libjpg libmtp create-dmg confuse
- name: set our Qt build
run: |
curl --output ssrf-Qt-5.15.2-mac.tar.xz https://f002.backblazeb2.com/file/Subsurface-Travis/ssrf-Qt5.15.2.tar.xz
tar -xJf ssrf-Qt-5.15.2-mac.tar.xz
- name: checkout Qt resources
uses: actions/checkout@v4
with:
repository: subsurface/qt-mac
ref: main
path: qt-mac
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: build Subsurface
id: build
run: |
cd ${GITHUB_WORKSPACE}/..
export QT_ROOT=${GITHUB_WORKSPACE}/Qt5.15.2/5.15.2/clang_64
export QT_ROOT=${GITHUB_WORKSPACE}/qt-mac/Qt5.15.13
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins
export PATH=$QT_ROOT/bin:$PATH
export CMAKE_PREFIX_PATH=$QT_ROOT/lib/cmake
@ -58,10 +59,18 @@ jobs:
echo "Created $IMG"
echo "dmg=$IMG" >> $GITHUB_OUTPUT
- name: publish pull request artifacts
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: Subsurface-MacOS-${{ steps.version_number.outputs.version }}
path: ${{ steps.build.outputs.dmg }}
compression-level: 0
# only publish a 'release' on push events (those include merging a PR)
- name: upload binaries
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds

View File

@ -1,4 +1,5 @@
name: Post Release
name: Post Release Notes
on:
push:
paths-ignore:
@ -6,29 +7,35 @@ on:
branches:
- master
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
postRelease:
runs-on: ubuntu-latest
steps:
- name: checkout sources
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: set the version information
id: version_number
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
# since we are running this step on a pull request, we will skip build numbers in releases
- name: atomically create or retrieve the build number and assemble release notes
id: version_number
- name: assemble release notes
env:
EVENT_HEAD_COMMIT_ID: ${{ github.event.head_commit.id }}
# Required because we are using the GitHub CLI in 'create-releasenotes.sh'
GH_TOKEN: ${{ github.token }}
run: |
bash -x ./scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
bash scripts/create-releasenotes.sh ${{ github.event.head_commit.id }}
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
scripts/create-releasenotes.sh $EVENT_HEAD_COMMIT_ID
# add a file containing the release title so it can be picked up and listed on the release page on our web server
- name: publish release
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds

View File

@ -23,13 +23,11 @@ logger.setLevel(logging.INFO)
APPLICATION = "subsurface-ci"
LAUNCHPAD = "production"
RELEASE = "bionic"
TEAM = "subsurface"
SOURCE_NAME = "subsurface"
SNAPS = {
"subsurface": {
"stable": {"recipe": "subsurface-stable"},
"candidate": {"recipe": "subsurface-candidate"},
},
}

View File

@ -1,58 +0,0 @@
#!/bin/bash
set -x
set -e
# this gets executed by the GitHub Action when building an AppImage for Linux
# inside of the trusty-qt512 container
export PATH=$QT_ROOT/bin:$PATH # Make sure correct qmake is found on the $PATH for linuxdeployqt
export CMAKE_PREFIX_PATH=$QT_ROOT/lib/cmake
# echo "--------------------------------------------------------------"
# echo "install missing packages"
# apt install -y libbluetooth-dev libmtp-dev
# the container currently has things under / that need to be under /__w/subsurface/subsurface instead
cp -a /appdir /__w/subsurface/
cp -a /install-root /__w/subsurface/
echo "--------------------------------------------------------------"
echo "building desktop"
# now build our AppImage
bash -e -x subsurface/scripts/build.sh -desktop -create-appdir -build-with-webkit -quick
echo "--------------------------------------------------------------"
echo "assembling AppImage"
export QT_PLUGIN_PATH=$QT_ROOT/plugins
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins
export QT_DEBUG_PLUGINS=1
# set up the appdir
mkdir -p appdir/usr/plugins/
# mv googlemaps plugins into place
mv appdir/usr/usr/local/Qt/5.*/gcc_64/plugins/* appdir/usr/plugins # the usr/usr is not a typo, that's where it ends up
rm -rf appdir/usr/home/ appdir/usr/include/ appdir/usr/share/man/ # No need to ship developer and man files as part of the AppImage
rm -rf appdir/usr/usr appdir/usr/lib/cmake appdir/usr/lib/pkgconfig
cp /ssllibs/libssl.so appdir/usr/lib/libssl.so.1.1
cp /ssllibs/libcrypto.so appdir/usr/lib/libcrypto.so.1.1
# get the linuxdeployqt tool and run it to collect the libraries
curl -L -O "https://github.com/probonopd/linuxdeployqt/releases/download/7/linuxdeployqt-7-x86_64.AppImage"
chmod a+x linuxdeployqt*.AppImage
unset QTDIR
unset QT_PLUGIN_PATH
unset LD_LIBRARY_PATH
./linuxdeployqt*.AppImage --appimage-extract-and-run ./appdir/usr/share/applications/*.desktop -exclude-libs=libdbus-1.so.3 -bundle-non-qt-libs -qmldir=./subsurface/stats -qmldir=./subsurface/map-widget/ -verbose=2
# create the AppImage
export VERSION=$(cd subsurface/scripts ; ./get-version) # linuxdeployqt uses this for naming the file
./linuxdeployqt*.AppImage --appimage-extract-and-run ./appdir/usr/share/applications/*.desktop -exclude-libs=libdbus-1.so.3 -appimage -qmldir=./subsurface/stats -qmldir=./subsurface/map-widget/ -verbose=2
# copy AppImage to the calling VM
# with GitHub Actions the /${GITHUB_WORKSPACE} directory is the current working directory at the start of a step
cp Subsurface*.AppImage* /${GITHUB_WORKSPACE}/Subsurface.AppImage
ls -l /${GITHUB_WORKSPACE}/Subsurface.AppImage

View File

@ -15,13 +15,16 @@ jobs:
steps:
- name: Check out sources
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: atomically create or retrieve the build number
- name: set the version information
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: Setup build dependencies
run: |
@ -48,5 +51,5 @@ jobs:
- name: run the launchpad make-package script
run: |
cd ..
bash -x subsurface/packaging/ubuntu/make-package.sh ${{ github.ref_name }}
bash -x subsurface/packaging/ubuntu/make-package.sh $GITHUB_REF_NAME

View File

@ -16,17 +16,17 @@ jobs:
mxe_sha: 'c0bfefc57a00fdf6cb5278263e21a478e47b0bf5'
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: Build the name for the docker image
id: build_name
run: |
v=${{ env.VERSION }}
b=${{ github.ref }} # -BRANCH suffix, unless the branch is master
v=$VERSION
b=$GITHUB_REF # -BRANCH suffix, unless the branch is master
b=${b/refs\/heads\//}
b=${b,,} # the name needs to be all lower case
if [ $b = "master" ] ; then b="" ; else b="-$b" ; fi
echo "NAME=${{ github.repository_owner }}/mxe-build${b}:${v}" >> $GITHUB_OUTPUT
echo "NAME=$GITHUB_REPOSITORY_OWNER/mxe-build${b}:${v}" >> $GITHUB_OUTPUT
- name: Build and Publish Linux Docker image to Dockerhub
uses: elgohr/Publish-Docker-Github-Action@v5

View File

@ -1,4 +1,5 @@
name: Windows
on:
push:
paths-ignore:
@ -12,28 +13,23 @@ on:
- master
jobs:
buildWindows:
build:
runs-on: ubuntu-latest
container:
image: docker://subsurface/mxe-build:3.1.0
steps:
- name: checkout sources
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: atomically create or retrieve the build number and assemble release notes
- name: set the version information
id: version_number
if: github.event_name == 'push'
run: |
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
version=$(cat release-version)
echo "version=$version" >> $GITHUB_OUTPUT
- name: store dummy version and build number for pull request
if: github.event_name == 'pull_request'
run: |
echo "100" > latest-subsurface-buildnumber
echo "CICD-pull-request" > latest-subsurface-buildnumber-extension
uses: ./.github/actions/manage-version
with:
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
- name: get other dependencies
env:
@ -44,18 +40,28 @@ jobs:
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
cd /win
ln -s /__w/subsurface/subsurface .
bash -x subsurface/.github/workflows/scripts/windows-container-prep.sh 2>&1 | tee pre-build.log
bash -x subsurface/packaging/windows/container-prep.sh 2>&1 | tee pre-build.log
- name: run build
run: |
export OUTPUT_DIR="$GITHUB_WORKSPACE"
cd /win
bash -x subsurface/.github/workflows/scripts/windows-in-container-build.sh 2>&1 | tee build.log
bash -x subsurface/packaging/windows/in-container-build.sh 2>&1 | tee build.log
grep "Built target installer" build.log
- name: publish pull request artifacts
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: Subsurface-Windows-${{ steps.version_number.outputs.version }}
path: |
subsurface*.exe*
smtk2ssrf*.exe
# only publish a 'release' on push events (those include merging a PR)
- name: upload binaries
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.version_number.outputs.version }}
repository: ${{ github.repository_owner }}/nightly-builds

1
.gitignore vendored
View File

@ -49,3 +49,4 @@ appdata/subsurface.appdata.xml
android-mobile/Roboto-Regular.ttf
gh_release_notes.md
release_content_title.txt
/output/

View File

@ -1,3 +1,6 @@
statistics: show proper dates in January
desktop: add country to the fields indexed for full text search
import: update libdivecomputer version, add support for the Scubapro G3 / Luna and Shearwater Tern
desktop: add a button linking to the 'Contribute' page
mobile: fix configuration of decompression ceiling and gradient factors
desktop: fix gas switches in UDDF exports

View File

@ -124,8 +124,8 @@ if (SUBSURFACE_ASAN_BUILD)
endif()
# every compiler understands -Wall
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=format")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=format")
# by detault optimize with -O2 even for debug builds
set (GCC_OPTIMIZATION_FLAGS "-O2" CACHE STRING "GCC optimization flags")
@ -320,7 +320,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
execute_process(
COMMAND bash scripts/get-version
COMMAND bash scripts/get-version.sh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE SSRF_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE

View File

@ -135,7 +135,7 @@ msgid ""
"mailto:subsurface@subsurface-divelog.org[our mailing list] and report bugs "
"at https://github.com/Subsurface/subsurface/issues[our bugtracker]. "
"For instructions on how to build the software and (if needed) its "
"dependencies please consult the INSTALL file included with the source code."
"dependencies please consult the INSTALL.md file included with the source code."
msgstr ""
#. type: Plain text

View File

@ -175,7 +175,7 @@ msgid ""
"an email to mailto:subsurface@subsurface-divelog.org[our mailing list] and "
"report bugs at https://github.com/Subsurface-divelog/subsurface/issues[our "
"bugtracker]. For instructions on how to build the software and (if needed) "
"its dependencies please consult the INSTALL file included with the source "
"its dependencies please consult the INSTALL.md file included with the source "
"code."
msgstr ""
"Ce manuel explique comment utiliser le programme _Subsurface_. Pour "
@ -184,7 +184,7 @@ msgstr ""
"pouvez envoyer un e-mail sur mailto:subsurface@subsurface-divelog.org[notre "
"liste de diffusion] et rapportez les bogues sur http://trac.hohndel."
"org[notre bugtracker]. Pour des instructions de compilation du logiciel et "
"(si besoin) de ses dépendances, merci de consulter le fichier INSTALL inclus "
"(si besoin) de ses dépendances, merci de consulter le fichier INSTALL.md inclus "
"dans les sources logicielles."
#. type: Plain text

View File

@ -460,7 +460,7 @@ the software, consult the <em>Downloads</em> page on the
Please discuss issues with this program by sending an email to
<a href="mailto:subsurface@subsurface-divelog.org">our mailing list</a> and report bugs at
<a href="https://github.com/Subsurface/subsurface/issues">our bugtracker</a>. For instructions on how to build the
software and (if needed) its dependencies please consult the INSTALL file
software and (if needed) its dependencies please consult the INSTALL.md file
included with the source code.</p></div>
<div class="paragraph"><p><strong>Audience</strong>: Recreational Scuba Divers, Free Divers, Tec Divers, Professional
Divers</p></div>

View File

@ -34,7 +34,7 @@ https://subsurface-divelog.org/[_Subsurface_ web site].
Please discuss issues with this program by sending an email to
mailto:subsurface@subsurface-divelog.org[our mailing list] and report bugs at
https://github.com/Subsurface/subsurface/issues[our bugtracker]. For instructions on how to build the
software and (if needed) its dependencies please consult the INSTALL file
software and (if needed) its dependencies please consult the INSTALL.md file
included with the source code.
*Audience*: Recreational Scuba Divers, Free Divers, Tec Divers, Professional

View File

@ -517,7 +517,7 @@ web</a>. Por favor, comenta los problemas que tengas con este programa enviando
mail a <a href="mailto:subsurface@subsurface-divelog.org">nuestra lista de correo</a> e informa de
fallos en <a href="https://github.com/Subsurface/subsurface/issues">nuestro bugtracker</a>.
Para instrucciones acerca de como compilar el software y (en caso necesario)
sus dependencias, por favor, consulta el archivo INSTALL incluido con el código
sus dependencias, por favor, consulta el archivo INSTALL.md incluido con el código
fuente.</p></div>
<div class="paragraph"><p><strong>Audiencia</strong>: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,
Buceadores profesionales.</p></div>

View File

@ -61,7 +61,7 @@ web]. Por favor, comenta los problemas que tengas con este programa enviando un
mail a mailto:subsurface@subsurface-divelog.org[nuestra lista de correo] e informa de
fallos en https://github.com/Subsurface/subsurface/issues[nuestro bugtracker].
Para instrucciones acerca de como compilar el software y (en caso necesario)
sus dependencias, por favor, consulta el archivo INSTALL incluido con el código
sus dependencias, por favor, consulta el archivo INSTALL.md incluido con el código
fuente.
*Audiencia*: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,

View File

@ -526,7 +526,7 @@ problème, vous pouvez envoyer un e-mail sur
<a href="mailto:subsurface@subsurface-divelog.org">notre liste de diffusion</a> et
rapportez les bogues sur <a href="http://trac.hohndel.org">notre bugtracker</a>. Pour
des instructions de compilation du logiciel et (si besoin) de ses
dépendances, merci de consulter le fichier INSTALL inclus dans les sources
dépendances, merci de consulter le fichier INSTALL.md inclus dans les sources
logicielles.</p></div>
<div class="paragraph"><p><strong>Public</strong> : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs
professionnels</p></div>

View File

@ -61,7 +61,7 @@ problème, vous pouvez envoyer un e-mail sur
mailto:subsurface@subsurface-divelog.org[notre liste de diffusion] et
rapportez les bogues sur http://trac.hohndel.org[notre bugtracker]. Pour
des instructions de compilation du logiciel et (si besoin) de ses
dépendances, merci de consulter le fichier INSTALL inclus dans les sources
dépendances, merci de consulter le fichier INSTALL.md inclus dans les sources
logicielles.
*Public* : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs

View File

@ -516,7 +516,7 @@ het programma kunnen bij de ontwikkelaars gemeld worden via email op
<a href="mailto:subsurface@subsurface-divelog.org">onze mailinglijst</a>. Fouten kunnen
ook gemeld worden op <a href="https://github.com/Subsurface/subsurface/issues">onze bugtracker</a>.
Instructies hoe <em>Subsurface</em> zelf te compileren vanuit de broncode staan ook op
onze website en in het INSTALL bestand in de broncode.</p></div>
onze website en in het INSTALL.md bestand in de broncode.</p></div>
<div class="paragraph"><p><strong>Doelgroep</strong>: Recreatieve duikers, Tec duikers, Apneu duikers,
Professionele duikers.</p></div>
<div id="toc">

View File

@ -59,7 +59,7 @@ het programma kunnen bij de ontwikkelaars gemeld worden via email op
mailto:subsurface@subsurface-divelog.org[onze mailinglijst]. Fouten kunnen
ook gemeld worden op https://github.com/Subsurface/subsurface/issues[onze bugtracker].
Instructies hoe _Subsurface_ zelf te compileren vanuit de broncode staan ook op
onze website en in het INSTALL bestand in de broncode.
onze website en in het INSTALL.md bestand in de broncode.
*Doelgroep*: Recreatieve duikers, Tec duikers, Apneu duikers,
Professionele duikers.

View File

@ -1,5 +1,4 @@
Building Subsurface from Source
===============================
# Building Subsurface from Source
Subsurface uses quite a few open source libraries and frameworks to do its
job. The most important ones include libdivecomputer, Qt, libxml2, libxslt,
@ -13,23 +12,27 @@ Below are instructions for building Subsurface
- iOS (cross-building)
Getting Subsurface source
-------------------------
## Getting Subsurface source
You can get the sources to the latest development version from our git
repository:
git clone http://github.com/Subsurface/subsurface.git
cd subsurface
git submodule init # this will give you our flavor of libdivecomputer
```
git clone http://github.com/Subsurface/subsurface.git
cd subsurface
git submodule init # this will give you our flavor of libdivecomputer
```
You keep it updated by doing:
git checkout master
git pull -r
git submodule update
```
git checkout master
git pull -r
git submodule update
```
Our flavor of libdivecomputer
-----------------------------
### Our flavor of libdivecomputer
Subsurface requires its own flavor of libdivecomputer which is inclduded
above as git submodule
@ -37,7 +40,7 @@ above as git submodule
The branches won't have a pretty history and will include ugly merges,
but they should always allow a fast forward pull that tracks what we
believe developers should build against. All our patches are contained
in the "Subsurface-DS9" branch.
in the `Subsurface-DS9` branch.
This should allow distros to see which patches we have applied on top of
upstream. They will receive force pushes as we rebase to newer versions of
@ -53,8 +56,7 @@ Subsurface or trying to understand what we have done relative to their
respective upstreams.
Getting Qt5
-----------
### Getting Qt5
We use Qt5 in order to only maintain one UI across platforms.
@ -74,36 +76,41 @@ significantly reduced flexibility.
As of this writing, there is thankfully a thirdparty offline installer still
available:
pip3 install aqtinstall
aqt install -O <Qt Location> 5.15.2 mac desktop
```
pip3 install aqtinstall
aqt install -O <Qt Location> 5.15.2 mac desktop
```
(or whatever version / OS you need). This installer is surprisingly fast
and seems well maintained - note that we don't use this for Windows as
that is completely built from source using MXE.
In order to use this Qt installation, simply add it to your PATH:
```
PATH=<Qt Location>/<version>/<type>/bin:$PATH
```
QtWebKit is needed, if you want to print, but no longer part of Qt5,
so you need to download it and compile. In case you just want to test
without print possibility omit this step.
git clone -b 5.212 https://github.com/qt/qtwebkit
mkdir -p qtwebkit/WebKitBuild/Release
cd qtwebkit/WebKitBuild/Release
cmake -DPORT=Qt -DCMAKE_BUILD_TYPE=Release -DQt5_DIR=/<Qt Location>/<version>/<type>/lib/cmake/Qt5 ../..
make install
```
git clone -b 5.212 https://github.com/qt/qtwebkit
mkdir -p qtwebkit/WebKitBuild/Release
cd qtwebkit/WebKitBuild/Release
cmake -DPORT=Qt -DCMAKE_BUILD_TYPE=Release -DQt5_DIR=/<Qt Location>/<version>/<type>/lib/cmake/Qt5 ../..
make install
```
Other third party library dependencies
--------------------------------------
### Other third party library dependencies
In order for our cloud storage to be fully functional you need
libgit2 0.26 or newer.
cmake build system
------------------
### cmake build system
Our main build system is based on cmake. But qmake is needed
for the googlemaps plugin and the iOS build.
@ -114,109 +121,127 @@ distribution (see build instructions).
Build options for Subsurface
----------------------------
## Build options for Subsurface
The following options are recognised when passed to cmake:
-DCMAKE_BUILD_TYPE=Release create a release build
-DCMAKE_BUILD_TYPE=Debug create a debug build
`-DCMAKE_BUILD_TYPE=Release` create a release build
`-DCMAKE_BUILD_TYPE=Debug` create a debug build
The Makefile that was created using cmake can be forced into a much more
verbose mode by calling
make VERBOSE=1
```
make VERBOSE=1
```
Many more variables are supported, the easiest way to interact with them is
to call
ccmake .
```
ccmake .
```
in your build directory.
Building the development version of Subsurface under Linux
----------------------------------------------------------
### Building the development version of Subsurface under Linux
On Fedora you need
```
sudo dnf install autoconf automake bluez-libs-devel cmake gcc-c++ git \
libcurl-devel libsqlite3x-devel libssh2-devel libtool libudev-devel \
libusbx-devel libxml2-devel libxslt-devel make \
qt5-qtbase-devel qt5-qtconnectivity-devel qt5-qtdeclarative-devel \
qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \
qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel
libcurl-devel libsqlite3x-devel libssh2-devel libtool libudev-devel \
libusbx-devel libxml2-devel libxslt-devel make \
qt5-qtbase-devel qt5-qtconnectivity-devel qt5-qtdeclarative-devel \
qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \
qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel
```
Package names are sadly different on OpenSUSE
```
sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-devel \
libxml2-devel libxslt-devel sqlite3-devel libusb-1_0-devel \
libqt5-linguist-devel libqt5-qttools-devel libQt5WebKitWidgets-devel \
libqt5-qtbase-devel libQt5WebKit5-devel libqt5-qtsvg-devel \
libqt5-qtscript-devel libqt5-qtdeclarative-devel \
libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \
bluez-devel libgit2-devel libmtp-devel
libxml2-devel libxslt-devel sqlite3-devel libusb-1_0-devel \
libqt5-linguist-devel libqt5-qttools-devel libQt5WebKitWidgets-devel \
libqt5-qtbase-devel libQt5WebKit5-devel libqt5-qtsvg-devel \
libqt5-qtscript-devel libqt5-qtdeclarative-devel \
libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \
bluez-devel libgit2-devel libmtp-devel
```
On Debian Bookworm this seems to work
```
sudo apt install \
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-openssl-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-openssl-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
```
In order to build and run mobile-on-desktop, you also need
```
sudo apt install \
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
```
Package names for Ubuntu 21.04
```
sudo apt install \
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
```
In order to build and run mobile-on-desktop, you also need
```
sudo apt install \
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
```
On Raspberry Pi (Raspian Buster and Ubuntu Mate 20.04.1) this seems to work
```
sudo apt install \
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
```
In order to build and run mobile-on-desktop, you also need
```
sudo apt install \
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
qml-module-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
```
Note that on Ubuntu Mate on the Raspberry Pi, you may need to configure
@ -226,42 +251,46 @@ swap space configured by default. See the dphys-swapfile package.
On Raspberry Pi OS with Desktop (64-bit) Released April 4th, 2022, this seems
to work
```
sudo apt install \
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libtool \
libusb-1.0-0-dev libxml2-dev libxslt1-dev libzip-dev make pkg-config \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
```
Note that you'll need to increase the swap space as the default of 100MB
doesn't seem to be enough. 1024MB worked on a 3B+.
If maps aren't working, copy the googlemaps plugin
from <build_dir>/subsurface/googlemaps/build/libqtgeoservices_googlemaps.so
to /usr/lib/aarch64-linux-gnu/qt5/plugins/geoservices.
from `<build_dir>/subsurface/googlemaps/build/libqtgeoservices_googlemaps.so`
to `/usr/lib/aarch64-linux-gnu/qt5/plugins/geoservices/`.
If Subsurface can't seem to see your dive computer on /dev/ttyUSB0, even after
If Subsurface can't seem to see your dive computer on `/dev/ttyUSB0`, even after
adjusting your account's group settings (see note below about usermod), it
might be that the FTDI driver doesn't recognize the VendorID/ProductID of your
computer. Follow the instructions here:
computer. Follow the instructions here:
https://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_101_Customising_FTDI_VID_PID_In_Linux(FT_000081).pdf
https://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_101_Customising_FTDI_VID_PID_In_Linux(FT_000081).pdf
If you're unsure of the VID/PID of your device, plug your dive computer in to
your host and run `dmesg`. That should show the codes that are needed to
your host and run `dmesg`. That should show the codes that are needed to
follow TN_101.
On PCLinuxOS you appear to need the following packages
su -c "apt-get install -y autoconf automake cmake gcc-c++ git libtool \
lib64bluez-devel lib64qt5bluetooth-devel lib64qt5concurrent-devel \
lib64qt5help-devel lib64qt5location-devel lib64qt5quicktest-devel \
lib64qt5quickwidgets-devel lib64qt5script-devel lib64qt5svg-devel \
lib64qt5test-devel lib64qt5webkitwidgets-devel lib64qt5xml-devel \
lib64ssh2-devel lib64usb1.0-devel lib64zip-devel qttools5 qttranslations5"
```
su -c "apt-get install -y autoconf automake cmake gcc-c++ git libtool \
lib64bluez-devel lib64qt5bluetooth-devel lib64qt5concurrent-devel \
lib64qt5help-devel lib64qt5location-devel lib64qt5quicktest-devel \
lib64qt5quickwidgets-devel lib64qt5script-devel lib64qt5svg-devel \
lib64qt5test-devel lib64qt5webkitwidgets-devel lib64qt5xml-devel \
lib64ssh2-devel lib64usb1.0-devel lib64zip-devel qttools5 qttranslations5"
```
In order to build Subsurface, use the supplied build script. This should
work on most systems that have all the prerequisite packages installed.
@ -269,109 +298,121 @@ work on most systems that have all the prerequisite packages installed.
You should have Subsurface sources checked out in a sane place, something
like this:
```
mkdir -p ~/src
cd ~/src
git clone https://github.com/Subsurface/subsurface.git
./subsurface/scripts/build.sh # <- this step will take quite a while as it
# compiles a handful of libraries before
# building Subsurface
# building Subsurface
```
Now you can run Subsurface like this:
```
cd ~/src/subsurface/build
./subsurface
```
Note: on many Linux versions (for example on Kubuntu 15.04) the user must
belong to the dialout group.
belong to the `dialout` group.
You may need to run something like
sudo usermod -a -G dialout username
```
sudo usermod -a -G dialout $USER
```
with your correct username and log out and log in again for that to take
effect.
If you get errors like:
```
./subsurface: error while loading shared libraries: libGrantlee_Templates.so.5: cannot open shared object file: No such file or directory
```
You can run the following command:
```
sudo ldconfig ~/src/install-root/lib
```
Building Subsurface under MacOSX
--------------------------------
### Building Subsurface under MacOSX
While it is possible to build all required components completely from source,
at this point the preferred way to build Subsurface is to set up the build
infrastructure via Homebrew and then build the dependencies from source.
0) You need to have XCode installed. The first time (and possibly after updating OSX)
0. You need to have XCode installed. The first time (and possibly after updating OSX)
```
xcode-select --install
```
1) install Homebrew (see https://brew.sh) and then the required build infrastructure:
1. install Homebrew (see https://brew.sh) and then the required build infrastructure:
```
brew install autoconf automake libtool pkg-config gettext
```
2) install Qt
2. install Qt
download the macOS installer from https://download.qt.io/official_releases/online_installers
and use it to install the desired Qt version. At this point the latest Qt5 version is still
preferred over Qt6.
3) now build Subsurface
If you plan to deploy your build to an Apple Silicon Mac, you may have better results with
Bluetooth connections if you install Qt5.15.13. If Qt5.15.13 is not available via the
installer, you can download from https://download.qt.io/official_releases/qt/5.15/5.15.13
and build using the usual configure, make, and make install.
3. now build Subsurface
```
cd ~/src; bash subsurface/scripts/build.sh -build-deps
```
if you are building against Qt6 (still experimental) you can create a universal binary with
```
cd ~/src; bash subsurface/scripts/build.sh -build-with-qt6 -build-deps -fat-build
```
After the above is done, Subsurface.app will be available in the
subsurface/build directory. You can run Subsurface with the command
A) open subsurface/build/Subsurface.app
A. `open subsurface/build/Subsurface.app`
this will however not show diagnostic output
B) subsurface/build/Subsurface.app/Contents/MacOS/Subsurface
the TAB key is your friend :-)
B. `subsurface/build/Subsurface.app/Contents/MacOS/Subsurface`
the [Tab] key is your friend :-)
Debugging can be done with either Xcode or QtCreator.
To install the app for all users, move subsurface/build/Subsurface.app to /Applications.
Cross-building Subsurface on MacOSX for iOS
-------------------------------------------
### Cross-building Subsurface on MacOSX for iOS
1) build SubSurface under MacOSX and iOS
0. build SubSurface under MacOSX and iOS
1.1) cd <repo>/..; bash <repo>/scripts/build.sh -build-deps -both
1. `cd <repo>/..; bash <repo>/scripts/build.sh -build-deps -both`
note: this is mainly done to ensure all external dependencies are downloaded and set
to the correct versions
2) continue as described in subsurface/packaging/ios
2. follow [these instructions](packaging/ios/README.md)
Cross-building Subsurface on Linux for Windows
----------------------------------------------
### Cross-building Subsurface on Linux for Windows
Subsurface builds nicely with MinGW - the official builds are done as
cross builds under Linux (currently on Ubuntu 20.04). A shell script to do
that (plus the .nsi file to create the installer with makensis) are
included in the packaging/windows directory.
Subsurface for Windows builds on linux by using the [MXE (M cross environment)](https://github.com/mxe/mxe). The easiest way to do this is to use a Docker container with a pre-built MXE for Subsurface by following [these instructions](packaging/windows/README.md).
Please read through the explanations and instructions in
packaging/windows/README.md, packaging/windows/create-win-installer.sh, and
packaging/windows/mxe-based-build.sh if you want to build the Windows version
on your Linux system.
Building Subsurface on Windows
------------------------------
### Building Subsurface on Windows
This is NOT RECOMMENDED. To the best of our knowledge there is one single
person who regularly does this. The Subsurface team does not provide support
@ -381,8 +422,9 @@ The lack of a working package management system for Windows makes it
really painful to build Subsurface natively under Windows,
so we don't support that at all.
But if you want to build Subsurface on a Windows system, the docker based [cross-build for Windows](packaging/windows/README.md) works just fine in WSL2 on Windows.
Cross-building Subsurface on Linux for Android
----------------------------------------------
Follow the instructions in packaging/android/README
### Cross-building Subsurface on Linux for Android
Follow [these instructions](packaging/android/README.md).

View File

@ -1,20 +1,17 @@
# Subsurface
![Build Status](https://github.com/subsurface/subsurface/workflows/Windows/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Mac/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/iOS/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Android/badge.svg)
[![Windows](https://github.com/subsurface/subsurface/actions/workflows/windows.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/windows.yml)
[![Mac](https://github.com/subsurface/subsurface/actions/workflows/mac.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/mac.yml)
[![iOS](https://github.com/subsurface/subsurface/actions/workflows/ios.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/ios.yml)
[![Android](https://github.com/subsurface/subsurface/actions/workflows/android.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/android.yml)
![Build Status](https://github.com/subsurface/subsurface/workflows/Linux%20Snap/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Ubuntu%2014.04%20/%20Qt%205.12%20for%20AppImage--/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Ubuntu%2018.04%20/%20Qt%205.9--/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Ubuntu%2020.04%20/%20Qt%205.12--/badge.svg)
![Build Status](https://github.com/subsurface/subsurface/workflows/Ubuntu%2022.04%20/%20Qt%205.15--/badge.svg)
[![Snap](https://github.com/subsurface/subsurface/actions/workflows/linux-snap.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/linux-snap.yml)
[![Ubuntu 16.04 / Qt 5.15-- for AppImage](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-16.04-5.12-appimage.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-16.04-5.12-appimage.yml)
[![Ubuntu 24.04 / Qt 5.15--](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-24.04-5.15.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-24.04-5.15.yml)
[![Fedora 35 / Qt 6--](https://github.com/subsurface/subsurface/actions/workflows/linux-fedora-35-qt6.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/linux-fedora-35-qt6.yml)
[![Debian trixie / Qt 5.15--](https://github.com/subsurface/subsurface/actions/workflows/linux-debian-trixie-5.15.yml/badge.svg)](https://github.com/subsurface/subsurface/actions/workflows/linux-debian-trixie-5.15.yml)
This is the README file for Subsurface 5.0.10
Please check the `ReleaseNotes.txt` for details about new features and
changes since Subsurface 5.0.9 (and earlier versions).
[![Coverity Scan Results](https://scan.coverity.com/projects/14405/badge.svg)](https://scan.coverity.com/projects/subsurface-divelog-subsurface)
Subsurface can be found at http://subsurface-divelog.org
@ -24,16 +21,9 @@ Report bugs and issues at https://github.com/Subsurface/subsurface/issues
License: GPLv2
We frequently make new test versions of Subsurface available at
http://subsurface-divelog.org/downloads/test/ and there you can always get
the latest builds for Mac, Windows, Linux AppImage and Android (with some
caveats about installability). Additionally, those same versions are
We are releasing 'nightly' builds of Subsurface that are built from the latest version of the code. Versions of this build for Windows, macOS, Android (requiring sideloading), and a Linux AppImage can be downloaded from the [Latest Dev Release](https://www.subsurface-divelog.org/latest-release/) page on [our website](https://www.subsurface-divelog.org/). Alternatively, they can be downloaded [directly from GitHub](https://github.com/subsurface/nightly-builds/releases). Additionally, those same versions are
posted to the Subsurface-daily repos on Ubuntu Launchpad, Fedora COPR, and
OpenSUSE OBS.
These tend to contain the latest bug fixes and features, but also
occasionally the latest bugs and issues. Please understand when using them
that these are primarily intended for testing.
OpenSUSE OBS, and released to [Snapcraft](https://snapcraft.io/subsurface) into the 'edge' channel of subsurface.
You can get the sources to the latest development version from the git
repository:
@ -45,17 +35,11 @@ git clone https://github.com/Subsurface/subsurface.git
You can also fork the repository and browse the sources at the same site,
simply using https://github.com/Subsurface/subsurface
If you want the latest release (instead of the bleeding edge
development version) you can either get this via git or the release tar
ball. After cloning run the following command:
Additionally, artifacts for Windows, macOS, Android, Linux AppImage, and iOS (simulator build) are generated for all open pull requests and linked in pull request comments. Use these if you want to test the changes in a specific pull request and provide feedback before it has been merged.
```
git checkout v5.0.10 (or whatever the last release is)
```
If you want a more stable version that is a little bit more tested you can get this from the [Curent Release](https://www.subsurface-divelog.org/current-release/) page on [our website](https://www.subsurface-divelog.org/).
or download a tarball from http://subsurface-divelog.org/downloads/Subsurface-5.0.10.tgz
Detailed build instructions can be found in the INSTALL file.
Detailed build instructions can be found in the [INSTALL.md](/INSTALL.md) file.
## System Requirements

View File

@ -25,15 +25,15 @@ SOURCES += subsurface-mobile-main.cpp \
core/devicedetails.cpp \
core/downloadfromdcthread.cpp \
core/qtserialbluetooth.cpp \
core/plannernotes.c \
core/uemis-downloader.c \
core/plannernotes.cpp \
core/uemis-downloader.cpp \
core/qthelper.cpp \
core/checkcloudconnection.cpp \
core/color.cpp \
core/configuredivecomputer.cpp \
core/divelogexportlogic.cpp \
core/divesitehelpers.cpp \
core/errorhelper.c \
core/errorhelper.cpp \
core/exif.cpp \
core/format.cpp \
core/gettextfromc.cpp \
@ -41,13 +41,14 @@ SOURCES += subsurface-mobile-main.cpp \
core/qt-init.cpp \
core/subsurfacesysinfo.cpp \
core/windowtitleupdate.cpp \
core/file.c \
core/file.cpp \
core/fulltext.cpp \
core/subsurfacestartup.c \
core/subsurfacestartup.cpp \
core/subsurface-string.cpp \
core/pref.c \
core/profile.c \
core/profile.cpp \
core/device.cpp \
core/dive.c \
core/dive.cpp \
core/divecomputer.c \
core/divefilter.cpp \
core/event.c \
@ -58,33 +59,33 @@ SOURCES += subsurface-mobile-main.cpp \
core/divelog.cpp \
core/gas-model.c \
core/gaspressures.c \
core/git-access.c \
core/git-access.cpp \
core/globals.cpp \
core/liquivision.c \
core/load-git.c \
core/parse-xml.c \
core/parse.c \
core/liquivision.cpp \
core/load-git.cpp \
core/parse-xml.cpp \
core/parse.cpp \
core/picture.c \
core/pictureobj.cpp \
core/sample.c \
core/import-suunto.c \
core/import-shearwater.c \
core/import-seac.c \
core/import-cobalt.c \
core/import-divinglog.c \
core/import-csv.c \
core/save-html.c \
core/sample.cpp \
core/import-suunto.cpp \
core/import-shearwater.cpp \
core/import-seac.cpp \
core/import-cobalt.cpp \
core/import-divinglog.cpp \
core/import-csv.cpp \
core/save-html.cpp \
core/statistics.c \
core/worldmap-save.c \
core/libdivecomputer.c \
core/worldmap-save.cpp \
core/libdivecomputer.cpp \
core/version.c \
core/save-git.c \
core/datatrak.c \
core/save-git.cpp \
core/datatrak.cpp \
core/ostctools.c \
core/planner.c \
core/save-xml.c \
core/cochran.c \
core/deco.c \
core/planner.cpp \
core/save-xml.cpp \
core/cochran.cpp \
core/deco.cpp \
core/divesite.c \
core/equipment.c \
core/gas.c \
@ -93,9 +94,9 @@ SOURCES += subsurface-mobile-main.cpp \
core/sha1.c \
core/string-format.cpp \
core/strtod.c \
core/tag.c \
core/tag.cpp \
core/taxonomy.c \
core/time.c \
core/time.cpp \
core/trip.c \
core/units.c \
core/uemis.c \
@ -244,7 +245,6 @@ HEADERS += \
core/sample.h \
core/selection.h \
core/sha1.h \
core/strndup.h \
core/string-format.h \
core/subsurfacestartup.h \
core/subsurfacesysinfo.h \

View File

@ -38,6 +38,12 @@
<dt>DiveSystem</dt><dd><ul>
<li>Orca, iDive DAN, iDive Deep, iDive Easy, iDive Free, iDive Pro, iDive Reb, iDive Stealth, iDive Tech, iDive X3M</li></ul>
</dd>
<dt>Divesoft</dt><dd><ul>
<li>Freedom, Liberty</li></ul>
</dd>
<dt>FIT</dt><dd><ul>
<li>File import</li></ul>
</dd>
<dt>Garmin</dt><dd><ul>
<li>Descent Mk1, Descent Mk2/Mk2i</li></ul>
</dd>
@ -66,7 +72,7 @@
<li>S1</li></ul>
</dd>
<dt>Ratio</dt><dd><ul>
<li>iDive Color Deep, iDive Color Easy, iDive Color Fancy, iDive Color Free, iDive Color Pro, iDive Color Reb, iDive Color Tech+, iDive Deep, iDive Easy, iDive Fancy, iDive Free, iDive Pro, iDive Reb, iDive Tech+, iX3M 2 Deep, iX3M 2 Easy, iX3M 2 Gauge, iX3M 2 Pro, iX3M 2 Tech+, iX3M 2021 GPS Deep, iX3M 2021 GPS Easy, iX3M 2021 GPS Fancy, iX3M 2021 GPS Pro , iX3M 2021 GPS Reb, iX3M 2021 GPS Tech+, iX3M 2021 Pro Deep, iX3M 2021 Pro Easy, iX3M 2021 Pro Fancy, iX3M 2021 Pro Pro, iX3M 2021 Pro Reb, iX3M 2021 Pro Tech+, iX3M GPS Deep, iX3M GPS Easy, iX3M GPS Fancy, iX3M GPS Pro , iX3M GPS Reb, iX3M GPS Tech+, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+</li></ul>
<li>ATOM, iDive 2 Deep, iDive 2 Easy, iDive 2 Fancy, iDive 2 Free, iDive 2 Pro, iDive 2 Reb, iDive 2 Tech, iDive Color Deep, iDive Color Easy, iDive Color Fancy, iDive Color Free, iDive Color Pro, iDive Color Reb, iDive Color Tech+, iDive Deep, iDive Easy, iDive Fancy, iDive Free, iDive Pro, iDive Reb, iDive Tech+, iX3M 2 Deep, iX3M 2 Easy, iX3M 2 GPS Deep, iX3M 2 GPS Easy, iX3M 2 GPS Gauge, iX3M 2 GPS Pro, iX3M 2 GPS Reb, iX3M 2 GPS Tech, iX3M 2 Gauge, iX3M 2 Pro, iX3M 2 Tech+, iX3M 2021 GPS Deep, iX3M 2021 GPS Easy, iX3M 2021 GPS Fancy, iX3M 2021 GPS Pro , iX3M 2021 GPS Reb, iX3M 2021 GPS Tech+, iX3M 2021 Pro Deep, iX3M 2021 Pro Easy, iX3M 2021 Pro Fancy, iX3M 2021 Pro Pro, iX3M 2021 Pro Reb, iX3M 2021 Pro Tech+, iX3M GPS Deep, iX3M GPS Easy, iX3M GPS Fancy, iX3M GPS Pro , iX3M GPS Reb, iX3M GPS Tech+, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+</li></ul>
</dd>
<dt>Reefnet</dt><dd><ul>
<li>Sensus, Sensus Pro, Sensus Ultra</li></ul>
@ -75,7 +81,7 @@
<li>Alpha</li></ul>
</dd>
<dt>Scubapro</dt><dd><ul>
<li>Aladin A1, Aladin A2, Aladin H Matrix, Aladin Sport Matrix, Aladin Square, Chromis, G2, G2 Console, G2 HUD, G2 TEK, Mantis, Mantis 2, Meridian, XTender 5</li></ul>
<li>Aladin A1, Aladin A2, Aladin H Matrix, Aladin Sport Matrix, Aladin Square, Chromis, G2, G2 Console, G2 HUD, G2 TEK, G3, Luna 2.0, Luna 2.0 AI, Mantis, Mantis 2, Meridian, XTender 5</li></ul>
</dd>
<dt>Seabaer</dt><dd><ul>
<li>T1, H3, HUDC</li></ul>
@ -87,7 +93,7 @@
<li>XP5</li></ul>
</dd>
<dt>Shearwater</dt><dd><ul>
<li>Nerd, Nerd 2, Perdix, Perdix 2, Perdix AI, Peregrine, Petrel, Petrel 2, Petrel 3, Predator, Teric</li></ul>
<li>Nerd, Nerd 2, Perdix, Perdix 2, Perdix AI, Peregrine, Petrel, Petrel 2, Petrel 3, Predator, Teric, Tern</li></ul>
</dd>
<dt>Sherwood</dt><dd><ul>
<li>Amphos, Amphos 2.0, Amphos Air, Amphos Air 2.0, Beacon, Insight, Insight 2, Sage, Vision, Wisdom, Wisdom 2, Wisdom 3, Wisdom 4</li></ul>
@ -105,7 +111,7 @@
<li>DiveComputer.eu</li></ul>
</dd>
<dt>Tusa</dt><dd><ul>
<li>Element II (IQ-750), IQ-700, TC1, Talis, Zen (IQ-900), Zen Air (IQ-950)</li></ul>
<li>Element II (IQ-750), IQ-700, Talis, Zen (IQ-900), Zen Air (IQ-950)</li></ul>
</dd>
<dt>Uemis</dt><dd><ul>
<li>Zürich SDA</li></ul>

View File

@ -12,6 +12,8 @@ Deep Six: Excursion
Deepblu: Cosmiq+
Dive Rite: NiTek Q, NiTek Trio
DiveSystem: Orca, iDive DAN, iDive Deep, iDive Easy, iDive Free, iDive Pro, iDive Reb, iDive Stealth, iDive Tech, iDive X3M
Divesoft: Freedom, Liberty
FIT: File import
Garmin: Descent Mk1, Descent Mk2/Mk2i
Genesis: Centauri, React Pro, React Pro White
Heinrichs Weikamp: Frog, OSTC, OSTC 2, OSTC 2 TR, OSTC 2C, OSTC 2N, OSTC 3, OSTC 4, OSTC Mk2, OSTC Plus, OSTC Sport, OSTC cR
@ -21,20 +23,20 @@ Mares: Airlab, Darwin, Darwin Air, Genius, Horizon, Icon HD, Icon HD Net Ready,
McLean: Extreme
Oceanic: Atom 1.0, Atom 2.0, Atom 3.0, Atom 3.1, Datamask, F10, F11, Geo, Geo 2.0, Geo 4.0, Geo Air, OC1, OCS, OCi, Pro Plus 2, Pro Plus 2.1, Pro Plus 3, Pro Plus 4, Pro Plus X, VT 4.1, VT Pro, VT3, VT4, VTX, Veo 1.0, Veo 180, Veo 2.0, Veo 200, Veo 250, Veo 3.0, Veo 4.0, Versa Pro
Oceans: S1
Ratio: iDive Color Deep, iDive Color Easy, iDive Color Fancy, iDive Color Free, iDive Color Pro, iDive Color Reb, iDive Color Tech+, iDive Deep, iDive Easy, iDive Fancy, iDive Free, iDive Pro, iDive Reb, iDive Tech+, iX3M 2 Deep, iX3M 2 Easy, iX3M 2 Gauge, iX3M 2 Pro, iX3M 2 Tech+, iX3M 2021 GPS Deep, iX3M 2021 GPS Easy, iX3M 2021 GPS Fancy, iX3M 2021 GPS Pro , iX3M 2021 GPS Reb, iX3M 2021 GPS Tech+, iX3M 2021 Pro Deep, iX3M 2021 Pro Easy, iX3M 2021 Pro Fancy, iX3M 2021 Pro Pro, iX3M 2021 Pro Reb, iX3M 2021 Pro Tech+, iX3M GPS Deep, iX3M GPS Easy, iX3M GPS Fancy, iX3M GPS Pro , iX3M GPS Reb, iX3M GPS Tech+, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+
Ratio: ATOM, iDive 2 Deep, iDive 2 Easy, iDive 2 Fancy, iDive 2 Free, iDive 2 Pro, iDive 2 Reb, iDive 2 Tech, iDive Color Deep, iDive Color Easy, iDive Color Fancy, iDive Color Free, iDive Color Pro, iDive Color Reb, iDive Color Tech+, iDive Deep, iDive Easy, iDive Fancy, iDive Free, iDive Pro, iDive Reb, iDive Tech+, iX3M 2 Deep, iX3M 2 Easy, iX3M 2 GPS Deep, iX3M 2 GPS Easy, iX3M 2 GPS Gauge, iX3M 2 GPS Pro, iX3M 2 GPS Reb, iX3M 2 GPS Tech, iX3M 2 Gauge, iX3M 2 Pro, iX3M 2 Tech+, iX3M 2021 GPS Deep, iX3M 2021 GPS Easy, iX3M 2021 GPS Fancy, iX3M 2021 GPS Pro , iX3M 2021 GPS Reb, iX3M 2021 GPS Tech+, iX3M 2021 Pro Deep, iX3M 2021 Pro Easy, iX3M 2021 Pro Fancy, iX3M 2021 Pro Pro, iX3M 2021 Pro Reb, iX3M 2021 Pro Tech+, iX3M GPS Deep, iX3M GPS Easy, iX3M GPS Fancy, iX3M GPS Pro , iX3M GPS Reb, iX3M GPS Tech+, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+
Reefnet: Sensus, Sensus Pro, Sensus Ultra
Scorpena: Alpha
Scubapro: Aladin A1, Aladin A2, Aladin H Matrix, Aladin Sport Matrix, Aladin Square, Chromis, G2, G2 Console, G2 HUD, G2 TEK, Mantis, Mantis 2, Meridian, XTender 5
Scubapro: Aladin A1, Aladin A2, Aladin H Matrix, Aladin Sport Matrix, Aladin Square, Chromis, G2, G2 Console, G2 HUD, G2 TEK, G3, Luna 2.0, Luna 2.0 AI, Mantis, Mantis 2, Meridian, XTender 5
Seabaer: T1, H3, HUDC
Seac: Action, Guru, Jack, Screen
Seemann: XP5
Shearwater: Nerd, Nerd 2, Perdix, Perdix 2, Perdix AI, Peregrine, Petrel, Petrel 2, Petrel 3, Predator, Teric
Shearwater: Nerd, Nerd 2, Perdix, Perdix 2, Perdix AI, Peregrine, Petrel, Petrel 2, Petrel 3, Predator, Teric, Tern
Sherwood: Amphos, Amphos 2.0, Amphos Air, Amphos Air 2.0, Beacon, Insight, Insight 2, Sage, Vision, Wisdom, Wisdom 2, Wisdom 3, Wisdom 4
Sporasub: SP2
Subgear: XP Air, XP-10, XP-3G, XP-Air
Suunto: Cobra, Cobra 2, Cobra 3, D3, D4, D4f, D4i, D5, D6, D6i, D9, D9tx, DX, EON Core, EON Steel, EON Steel Black, Eon, Gekko, HelO2, Mosquito, Solution, Solution Alpha, Solution Nitrox, Spyder, Stinger, Vyper, Vyper 2, Vyper Air, Vyper Novo, Vytec, Zoop, Zoop Novo
Tecdiving: DiveComputer.eu
Tusa: Element II (IQ-750), IQ-700, TC1, Talis, Zen (IQ-900), Zen Air (IQ-950)
Tusa: Element II (IQ-750), IQ-700, Talis, Zen (IQ-900), Zen Air (IQ-950)
Uemis: Zürich SDA
Uwatec: Aladin 2G, Aladin Air Twin, Aladin Air Z, Aladin Air Z Nitrox, Aladin Air Z O2, Aladin Prime, Aladin Pro, Aladin Pro Ultra, Aladin Sport, Aladin Sport Plus, Aladin Tec, Aladin Tec 2G, Aladin Tec 3G, Galileo Luna, Galileo Sol, Galileo Terra, Galileo Trimix, Memomouse, Smart Com, Smart Pro, Smart Tec, Smart Z
Zeagle: N2iTiON3

View File

@ -181,7 +181,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
site ? put_format(&buf, "\\def\\%sgpslon{%f}\n", ssrf, site->location.lon.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\n");
put_format(&buf, "\\def\\%scomputer{%s}\n", ssrf, dive->dc.model);
put_format(&buf, "\\def\\%scountry{%s}\n", ssrf, country ?: "");
put_format(&buf, "\\def\\%stime{%u:%02u}\n", ssrf, FRACTION(dive->duration.seconds, 60));
put_format(&buf, "\\def\\%stime{%u:%02u}\n", ssrf, FRACTION_TUPLE(dive->duration.seconds, 60));
put_format(&buf, "\n%% Dive Profile Details:\n");
dive->maxtemp.mkelvin ? put_format(&buf, "\\def\\%smaxtemp{%.1f\\%stemperatureunit}\n", ssrf, get_temp_units(dive->maxtemp.mkelvin, &unit), ssrf) : put_format(&buf, "\\def\\%smaxtemp{}\n", ssrf);
@ -191,14 +191,8 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
dive->maxdepth.mm ? put_format(&buf, "\\def\\%smaximumdepth{%.1f\\%sdepthunit}\n", ssrf, get_depth_units(dive->maxdepth.mm, NULL, &unit), ssrf) : put_format(&buf, "\\def\\%smaximumdepth{}\n", ssrf);
dive->meandepth.mm ? put_format(&buf, "\\def\\%smeandepth{%.1f\\%sdepthunit}\n", ssrf, get_depth_units(dive->meandepth.mm, NULL, &unit), ssrf) : put_format(&buf, "\\def\\%smeandepth{}\n", ssrf);
struct tag_entry *tag = dive->tag_list;
QString tags;
if (tag) {
tags = tag->tag->name;
while ((tag = tag->next))
tags += QString(", ") + QString(tag->tag->name);
}
put_format(&buf, "\\def\\%stype{%s}\n", ssrf, qPrintable(tags));
std::string tags = taglist_get_tagstring(dive->tag_list);
put_format(&buf, "\\def\\%stype{%s}\n", ssrf, tags.c_str());
put_format(&buf, "\\def\\%sviz{%s}\n", ssrf, qPrintable(viz));
put_format(&buf, "\\def\\%srating{%s}\n", ssrf, qPrintable(rating));
put_format(&buf, "\\def\\%splot{\\includegraphics[width=9cm,height=4cm]{profile%d}}\n", ssrf, dive->number);

View File

@ -1,20 +1,20 @@
execute_process(
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version 4
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version.sh 4
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_4
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version 3
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version.sh 3
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_3
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version
COMMAND bash ${CMAKE_TOP_SRC_DIR}/scripts/get-version.sh
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
OUTPUT_VARIABLE CANONICAL_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE

View File

@ -100,6 +100,7 @@ enum class EditProfileType {
ADD,
REMOVE,
MOVE,
EDIT,
};
void replanDive(dive *d); // dive computer(s) and cylinder(s) of first argument will be consumed!
void editProfile(const dive *d, int dcNr, EditProfileType type, int count);

View File

@ -514,13 +514,18 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
// When encountering filter presets with equal names, check whether they are
// the same. If they are, ignore them.
for (const filter_preset &preset: *log->filter_presets) {
QString name = preset.name;
std::string name = preset.name;
auto it = std::find_if(divelog.filter_presets->begin(), divelog.filter_presets->end(),
[&name](const filter_preset &preset) { return preset.name == name; });
if (it != divelog.filter_presets->end() && it->data == preset.data)
continue;
filterPresetsToAdd.emplace_back(preset.name, preset.data);
}
free(dives_to_add.dives);
free(dives_to_remove.dives);
free(trips_to_add.trips);
free(sites_to_add.dive_sites);
}
bool ImportDives::workToBeDone()
@ -580,7 +585,7 @@ void ImportDives::undoit()
// Remove filter presets. Do this in reverse order.
for (auto it = filterPresetsToRemove.rbegin(); it != filterPresetsToRemove.rend(); ++it) {
int index = *it;
QString oldName = filter_preset_name_qstring(index);
std::string oldName = filter_preset_name(index);
FilterData oldData = filter_preset_get(index);
filter_preset_delete(index);
emit diveListNotifier.filterPresetRemoved(index);

View File

@ -112,7 +112,7 @@ private:
// For redo
std::vector<OwningDiveSitePtr> sitesToAdd;
std::vector<std::pair<QString,FilterData>>
std::vector<std::pair<std::string,FilterData>>
filterPresetsToAdd;
// For undo

View File

@ -566,7 +566,7 @@ QStringList EditTags::data(struct dive *d) const
{
QStringList res;
for (const struct tag_entry *tag = d->tag_list; tag; tag = tag->next)
res.push_back(tag->tag->name);
res.push_back(QString::fromStdString(tag->tag->name));
return res;
}
@ -879,6 +879,7 @@ QString editProfileTypeToString(EditProfileType type, int count)
case EditProfileType::ADD: return Command::Base::tr("Add stop");
case EditProfileType::REMOVE: return Command::Base::tr("Remove %n stop(s)", "", count);
case EditProfileType::MOVE: return Command::Base::tr("Move %n stop(s)", "", count);
case EditProfileType::EDIT: return Command::Base::tr("Edit stop");
}
}
@ -904,7 +905,7 @@ EditProfile::EditProfile(const dive *source, int dcNr, EditProfileType type, int
copy_samples(sdc, &dc);
copy_events(sdc, &dc);
setText(editProfileTypeToString(type, count) + diveNumberOrDate(d));
setText(editProfileTypeToString(type, count) + " " + diveNumberOrDate(d));
}
EditProfile::~EditProfile()
@ -925,6 +926,7 @@ void EditProfile::undo()
std::swap(sdc->samples, dc.samples);
std::swap(sdc->alloc_samples, dc.alloc_samples);
std::swap(sdc->sample, dc.sample);
std::swap(sdc->events, dc.events);
std::swap(sdc->maxdepth, dc.maxdepth);
std::swap(d->maxdepth, maxdepth);
std::swap(d->meandepth, meandepth);
@ -1090,11 +1092,6 @@ EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
dives.clear();
return;
}
WSInfoModel *wsim = WSInfoModel::instance();
QModelIndexList matches = wsim->match(wsim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(new_ws.description));
if (!matches.isEmpty())
wsim->setData(wsim->index(matches.first().row(), WSInfoModel::GR), new_ws.weight.grams);
}
EditWeight::~EditWeight()
@ -1105,6 +1102,7 @@ EditWeight::~EditWeight()
void EditWeight::redo()
{
for (size_t i = 0; i < dives.size(); ++i) {
add_weightsystem_description(&new_ws); // This updates the weightsystem info table
set_weightsystem(dives[i], indices[i], new_ws);
emit diveListNotifier.weightEdited(dives[i], indices[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
@ -1129,7 +1127,7 @@ AddCylinder::AddCylinder(bool currentDiveOnly) :
setText(Command::Base::tr("Add cylinder"));
else
setText(Command::Base::tr("Add cylinder (%n dive(s))", "", dives.size()));
cyl = create_new_cylinder(dives[0]);
cyl = create_new_manual_cylinder(dives[0]);
indexes.reserve(dives.size());
}
@ -1293,24 +1291,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
else
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
// Try to untranslate the cylinder type
QString description = cylIn.type.description;
for (int i = 0; i < tank_info_table.nr; ++i) {
if (gettextFromC::tr(tank_info_table.infos[i].name) == description) {
description = tank_info_table.infos[i].name;
break;
}
}
// Update the tank info model
TankInfoModel *tim = TankInfoModel::instance();
QModelIndexList matches = tim->match(tim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(cylIn.type.description));
if (!matches.isEmpty()) {
if (cylIn.type.size.mliter != cyl[0].type.size.mliter)
tim->setData(tim->index(matches.first().row(), TankInfoModel::ML), cylIn.type.size.mliter);
if (cylIn.type.workingpressure.mbar != cyl[0].type.workingpressure.mbar)
tim->setData(tim->index(matches.first().row(), TankInfoModel::BAR), cylIn.type.workingpressure.mbar / 1000.0);
}
// The base class copied the cylinders for us, let's edit them
for (int i = 0; i < (int)indexes.size(); ++i) {
@ -1338,6 +1319,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
void EditCylinder::redo()
{
for (size_t i = 0; i < dives.size(); ++i) {
set_tank_info_data(&tank_info_table, cyl[i].type.description, cyl[i].type.size, cyl[i].type.workingpressure);
std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]);
update_cylinder_related_info(dives[i]);
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
@ -1358,7 +1340,6 @@ EditSensors::EditSensors(int toCylinderIn, int fromCylinderIn, int dcNr)
return;
setText(Command::Base::tr("Edit sensors"));
}
void EditSensors::mapSensors(int toCyl, int fromCyl)
@ -1446,7 +1427,7 @@ EditDive::EditDive(dive *oldDiveIn, dive *newDiveIn, dive_site *createDs, dive_s
changedFields |= DiveField::CHILL;
if (!same_string(oldDive->suit, newDive->suit))
changedFields |= DiveField::SUIT;
if (get_taglist_string(oldDive->tag_list) != get_taglist_string(newDive->tag_list)) // This is cheating. Do we have a taglist comparison function?
if (taglist_get_tagstring(oldDive->tag_list) != taglist_get_tagstring(newDive->tag_list)) // This is cheating. Do we have a taglist comparison function?
changedFields |= DiveField::TAGS;
if (oldDive->dc.divemode != newDive->dc.divemode)
changedFields |= DiveField::MODE;

View File

@ -6,16 +6,16 @@
namespace Command {
static int createFilterPreset(const QString &name, const FilterData &data)
static int createFilterPreset(const std::string &name, const FilterData &data)
{
int index = filter_preset_add(name, data);
emit diveListNotifier.filterPresetAdded(index);
return index;
}
static std::pair<QString, FilterData> removeFilterPreset(int index)
static std::pair<std::string, FilterData> removeFilterPreset(int index)
{
QString oldName = filter_preset_name_qstring(index);
std::string oldName = filter_preset_name(index);
FilterData oldData = filter_preset_get(index);
filter_preset_delete(index);
emit diveListNotifier.filterPresetRemoved(index);
@ -23,7 +23,7 @@ static std::pair<QString, FilterData> removeFilterPreset(int index)
}
CreateFilterPreset::CreateFilterPreset(const QString &nameIn, const FilterData &dataIn) :
name(nameIn), data(dataIn), index(0)
name(nameIn.toStdString()), data(dataIn), index(0)
{
setText(Command::Base::tr("Create filter preset %1").arg(nameIn));
}
@ -46,7 +46,7 @@ void CreateFilterPreset::undo()
RemoveFilterPreset::RemoveFilterPreset(int indexIn) : index(indexIn)
{
setText(Command::Base::tr("Delete filter preset %1").arg(filter_preset_name_qstring(index)));
setText(Command::Base::tr("Delete filter preset %1").arg(QString(filter_preset_name(index).c_str())));
}
bool RemoveFilterPreset::workToBeDone()
@ -68,7 +68,7 @@ void RemoveFilterPreset::undo()
EditFilterPreset::EditFilterPreset(int indexIn, const FilterData &dataIn) :
index(indexIn), data(dataIn)
{
setText(Command::Base::tr("Edit filter preset %1").arg(filter_preset_name_qstring(index)));
setText(Command::Base::tr("Edit filter preset %1").arg(QString(filter_preset_name(index).c_str())));
}
bool EditFilterPreset::workToBeDone()

View File

@ -17,7 +17,7 @@ public:
CreateFilterPreset(const QString &name, const FilterData &data);
private:
// for redo
QString name;
std::string name;
FilterData data;
// for undo
@ -33,7 +33,7 @@ public:
RemoveFilterPreset(int index);
private:
// for undo
QString name;
std::string name;
FilterData data;
// for redo

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "command_pictures.h"
#include "core/errorhelper.h"
#include "core/subsurface-qt/divelistnotifier.h"
#include "qt-models/divelocationmodel.h"
@ -24,7 +25,7 @@ void SetPictureOffset::redo()
{
picture *pic = dive_get_picture(d, filename);
if (!pic) {
fprintf(stderr, "SetPictureOffset::redo(): picture disappeared!\n");
report_info("SetPictureOffset::redo(): picture disappeared!");
return;
}
std::swap(pic->offset, offset);
@ -73,7 +74,7 @@ static std::vector<PictureListForAddition> removePictures(std::vector<PictureLis
for (const std::string &fn: list.filenames) {
int idx = get_picture_idx(&list.d->pictures, fn.c_str());
if (idx < 0) {
fprintf(stderr, "removePictures(): picture disappeared!\n");
report_info("removePictures(): picture disappeared!");
continue; // Huh? We made sure that this can't happen by filtering out non-existent pictures.
}
filenames.push_back(QString::fromStdString(fn));
@ -103,7 +104,7 @@ static std::vector<PictureListForDeletion> addPictures(std::vector<PictureListFo
for (const PictureObj &pic: list.pics) {
int idx = get_picture_idx(&list.d->pictures, pic.filename.c_str()); // This should *not* already exist!
if (idx >= 0) {
fprintf(stderr, "addPictures(): picture disappeared!\n");
report_info("addPictures(): picture disappeared!");
continue; // Huh? We made sure that this can't happen by filtering out existing pictures.
}
picsForSignal.push_back(pic);

View File

@ -41,7 +41,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
checkcloudconnection.h
cloudstorage.cpp
cloudstorage.h
cochran.c
cochran.cpp
cochran.h
color.cpp
color.h
@ -51,15 +51,15 @@ set(SUBSURFACE_CORE_LIB_SRCS
configuredivecomputerthreads.h
connectionlistmodel.cpp
connectionlistmodel.h
datatrak.c
datatrak.cpp
datatrak.h
deco.c
deco.cpp
deco.h
device.cpp
device.h
devicedetails.cpp
devicedetails.h
dive.c
dive.cpp
dive.h
divecomputer.c
divecomputer.h
@ -85,11 +85,11 @@ set(SUBSURFACE_CORE_LIB_SRCS
eventtype.h
equipment.c
equipment.h
errorhelper.c
errorhelper.cpp
exif.cpp
exif.h
extradata.h
file.c
file.cpp
file.h
filterconstraint.cpp
filterconstraint.h
@ -107,24 +107,24 @@ set(SUBSURFACE_CORE_LIB_SRCS
gettext.h
gettextfromc.cpp
gettextfromc.h
git-access.c
git-access.cpp
git-access.h
globals.cpp
globals.h
imagedownloader.cpp
imagedownloader.h
import-cobalt.c
import-csv.c
import-cobalt.cpp
import-csv.cpp
import-csv.h
import-divinglog.c
import-shearwater.c
import-suunto.c
import-seac.c
import-divinglog.cpp
import-shearwater.cpp
import-suunto.cpp
import-seac.cpp
interpolate.h
libdivecomputer.c
libdivecomputer.cpp
libdivecomputer.h
liquivision.c
load-git.c
liquivision.cpp
load-git.cpp
membuffer.cpp
membuffer.h
metadata.cpp
@ -134,32 +134,32 @@ set(SUBSURFACE_CORE_LIB_SRCS
ostctools.c
owning_ptrs.h
parse-gpx.cpp
parse-xml.c
parse.c
parse-xml.cpp
parse.cpp
parse.h
picture.c
picture.h
pictureobj.cpp
pictureobj.h
planner.c
planner.cpp
planner.h
plannernotes.c
plannernotes.cpp
pref.h
pref.c
profile.c
profile.cpp
profile.h
qt-gui.h
qt-init.cpp
qthelper.cpp
qthelper.h
range.h
sample.c
sample.cpp
sample.h
save-git.c
save-html.c
save-git.cpp
save-html.cpp
save-html.h
save-profiledata.c
save-xml.c
save-xml.cpp
selection.cpp
selection.h
sha1.c
@ -167,26 +167,26 @@ set(SUBSURFACE_CORE_LIB_SRCS
ssrf.h
statistics.c
statistics.h
strndup.h
string-format.h
string-format.cpp
strtod.c
subsurface-float.h
subsurface-string.cpp
subsurface-string.h
subsurfacestartup.c
subsurfacestartup.cpp
subsurfacestartup.h
subsurfacesysinfo.cpp
subsurfacesysinfo.h
tag.c
tag.cpp
tag.h
taxonomy.c
taxonomy.h
time.c
time.cpp
timer.c
timer.h
trip.c
trip.h
uemis-downloader.c
uemis-downloader.cpp
uemis.c
uemis.h
units.h
@ -203,7 +203,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
windowtitleupdate.cpp
windowtitleupdate.h
worldmap-options.h
worldmap-save.c
worldmap-save.cpp
worldmap-save.h
xmlparams.cpp
xmlparams.h

View File

@ -2,9 +2,9 @@
#include "btdiscovery.h"
#include "downloadfromdcthread.h"
#include "core/libdivecomputer.h"
#include "libdivecomputer.h"
#include "errorhelper.h"
#include <QTimer>
#include <QDebug>
#include <QLoggingCategory>
#include <QRegularExpression>
#include <QElapsedTimer>
@ -62,6 +62,7 @@ static struct namePattern name[] = {
{ "NERD 2", "Shearwater", "NERD 2" },
{ "NERD", "Shearwater", "NERD" }, // order is important, test for the more specific one first
{ "Predator", "Shearwater", "Predator" },
{ "Tern", "Shearwater", "Tern" },
// Suunto dive computers
{ "EON Steel", "Suunto", "EON Steel" },
{ "EON Core", "Suunto", "EON Core" },
@ -69,9 +70,12 @@ static struct namePattern name[] = {
// Scubapro dive computers
{ "G2", "Scubapro", "G2" },
{ "HUD", "Scubapro", "G2 HUD" },
{ "G3", "Scubapro", "G3" },
{ "Aladin", "Scubapro", "Aladin Sport Matrix" },
{ "A1", "Scubapro", "Aladin A1" },
{ "A2", "Scubapro", "Aladin A2" },
{ "Luna 2.0 AI", "Scubapro", "Luna 2.0 AI" },
{ "Luna 2.0", "Scubapro", "Luna 2.0" },
// Mares dive computers
{ "Mares Genius", "Mares", "Genius" },
{ "Mares", "Mares", "Quad" }, // we actually don't know and just pick a common one - user needs to fix in UI
@ -173,7 +177,7 @@ BTDiscovery::BTDiscovery(QObject*) : m_btValid(false),
discoveryAgent(nullptr)
{
if (m_instance) {
qDebug() << "trying to create an additional BTDiscovery object";
report_info("trying to create an additional BTDiscovery object");
return;
}
m_instance = this;
@ -191,11 +195,11 @@ void BTDiscovery::showNonDiveComputers(bool show)
void BTDiscovery::BTDiscoveryReDiscover()
{
#if !defined(Q_OS_IOS)
qDebug() << "BTDiscoveryReDiscover: localBtDevice.isValid()" << localBtDevice.isValid();
report_info("BTDiscoveryReDiscover: localBtDevice.isValid() %d", localBtDevice.isValid());
if (localBtDevice.isValid() &&
localBtDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
btPairedDevices.clear();
qDebug() << "BTDiscoveryReDiscover: localDevice " + localBtDevice.name() + " is powered on, starting discovery";
report_info("BTDiscoveryReDiscover: localDevice %s is powered on, starting discovery", qPrintable(localBtDevice.name()));
#else
// for iOS we can't use the localBtDevice as iOS is BLE only
// we need to find some other way to test if Bluetooth is enabled, though
@ -216,13 +220,13 @@ void BTDiscovery::BTDiscoveryReDiscover()
connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
#endif
[this](QBluetoothDeviceDiscoveryAgent::Error error){
qDebug() << "device discovery received error" << discoveryAgent->errorString();
report_info("device discovery received error %s", qPrintable(discoveryAgent->errorString()));
});
qDebug() << "discovery methods" << (int)QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods();
report_info("discovery methods %d", (int)QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods());
}
#if defined(Q_OS_ANDROID)
// on Android, we cannot scan for classic devices - we just get the paired ones
qDebug() << "starting BLE discovery";
report_info("starting BLE discovery");
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
getBluetoothDevices();
// and add the paired devices to the internal data
@ -231,10 +235,10 @@ void BTDiscovery::BTDiscoveryReDiscover()
for (int i = 0; i < btPairedDevices.length(); i++)
btDeviceDiscoveredMain(btPairedDevices[i], true);
#else
qDebug() << "starting BT/BLE discovery";
report_info("starting BT/BLE discovery");
discoveryAgent->start();
for (int i = 0; i < btPairedDevices.length(); i++)
qDebug() << "Paired =" << btPairedDevices[i].name << btPairedDevices[i].address;
report_info("Paired = %s %s", qPrintable( btPairedDevices[i].name), qPrintable(btPairedDevices[i].address));
#endif
#if defined(Q_OS_IOS) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
@ -244,7 +248,7 @@ void BTDiscovery::BTDiscoveryReDiscover()
timer.start(3000);
#endif
} else {
qDebug() << "localBtDevice isn't valid or not connectable";
report_info("localBtDevice isn't valid or not connectable");
m_btValid = false;
}
}
@ -287,10 +291,10 @@ QString markBLEAddress(const QBluetoothDeviceInfo *device)
void BTDiscovery::btDeviceDiscoveryFinished()
{
qDebug() << "BT/BLE finished discovery";
report_info("BT/BLE finished discovery");
QList<QBluetoothDeviceInfo> devList = discoveryAgent->discoveredDevices();
for (QBluetoothDeviceInfo device: devList) {
qDebug() << device.name() << device.address().toString();
report_info("%s %s", qPrintable(device.name()), qPrintable(device.address().toString()));
}
}
@ -304,7 +308,7 @@ void BTDiscovery::btDeviceDiscovered(const QBluetoothDeviceInfo &device)
const auto serviceUuids = device.serviceUuids();
for (QBluetoothUuid id: serviceUuids) {
addBtUuid(id);
qDebug() << id.toByteArray();
report_info("%s", qPrintable(id.toByteArray()));
}
#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) || defined(Q_OS_WIN)
@ -333,7 +337,7 @@ void BTDiscovery::btDeviceDiscoveredMain(const btPairedDevice &device, bool from
msg = QString("%1 device: '%2' [%3]: ").arg(fromPaired ? "Paired" : "Discovered new").arg(newDevice).arg(device.address);
if (newDC) {
QString vendor = dc_descriptor_get_vendor(newDC);
qDebug() << msg << "this could be a " + vendor;
report_info("%s this could be a %s", qPrintable(msg), qPrintable(vendor));
btVP.btpdi = device;
btVP.dcDescriptor = newDC;
btVP.vendorIdx = vendorList.indexOf(vendor);
@ -348,7 +352,7 @@ void BTDiscovery::btDeviceDiscoveredMain(const btPairedDevice &device, bool from
newDevice += " ";
connectionListModel.addAddress(newDevice + device.address);
}
qDebug() << msg << "not recognized as dive computer";
report_info("%s not recognized as dive computer", qPrintable(msg));
}
QList<BTDiscovery::btVendorProduct> BTDiscovery::getBtDcs()
@ -403,12 +407,12 @@ void BTDiscovery::getBluetoothDevices()
result.address = dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString();
result.name = dev.callObjectMethod("getName", "()Ljava/lang/String;").toString();
if (btType & 1) { // DEVICE_TYPE_CLASSIC
qDebug() << "paired BT classic device type" << btType << "with address" << result.address;
report_info("paired BT classic device type %d with address %s", btType, qPrintable(result.address));
btPairedDevices.append(result);
}
if (btType & 2) { // DEVICE_TYPE_LE
result.address = QString("LE:%1").arg(result.address);
qDebug() << "paired BLE device type" << btType << "with address" << result.address;
report_info("paired BLE device type %d with address %s", btType, qPrintable(result.address));
btPairedDevices.append(result);
}
}
@ -447,7 +451,7 @@ void BTDiscovery::discoverAddress(QString address)
btAddress = extractBluetoothAddress(address);
if (!btDeviceInfo.keys().contains(address) && !discoveryAgent->isActive()) {
qDebug() << "restarting discovery agent";
report_info("restarting discovery agent");
discoveryAgent->start();
}
}
@ -456,7 +460,7 @@ void BTDiscovery::stopAgent()
{
if (!discoveryAgent)
return;
qDebug() << "---> stopping the discovery agent";
report_info("---> stopping the discovery agent");
discoveryAgent->stop();
}
@ -487,7 +491,7 @@ QString extractBluetoothNameAddress(const QString &address, QString &name)
name = m.captured(1).trimmed();
return extractedAddress;
}
qDebug() << "can't parse address" << address;
report_info("can't parse address %s", qPrintable(address));
return QString();
}
@ -503,7 +507,7 @@ QBluetoothDeviceInfo getBtDeviceInfo(const QString &devaddr)
return btDeviceInfo[devaddr];
}
if(!btDeviceInfo.keys().contains(devaddr)) {
qDebug() << "still looking scan is still running, we should just wait for a few moments";
report_info("still looking scan is still running, we should just wait for a few moments");
// wait for a maximum of 30 more seconds
// yes, that seems crazy, but on my Mac I see this take more than 20 seconds
QElapsedTimer timer;
@ -517,7 +521,7 @@ QBluetoothDeviceInfo getBtDeviceInfo(const QString &devaddr)
QThread::msleep(100);
} while (timer.elapsed() < 30000);
}
qDebug() << "notify user that we can't find" << devaddr;
report_info("notify user that we can't find %s", qPrintable(devaddr));
return QBluetoothDeviceInfo();
}
#endif // BT_SUPPORT

View File

@ -10,6 +10,7 @@
#include "qthelper.h"
#include "git-access.h"
#include "errorhelper.h"
#include "core/format.h"
#include "core/subsurface-string.h"
#include "core/membuffer.h"
#include "core/settings/qPrefCloudStorage.h"
@ -34,7 +35,7 @@ CheckCloudConnection::CheckCloudConnection(QObject *parent) :
bool CheckCloudConnection::checkServer()
{
if (verbose)
fprintf(stderr, "Checking cloud connection...\n");
report_info("Checking cloud connection...");
QEventLoop loop;
QNetworkAccessManager *mgr = new QNetworkAccessManager();
@ -72,10 +73,10 @@ bool CheckCloudConnection::checkServer()
}
}
if (verbose)
qDebug() << "connection test to cloud server" << prefs.cloud_base_url << "failed" <<
reply->error() << reply->errorString() <<
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() <<
reply->readAll();
report_info("connection test to cloud server %s failed %d %s %d %s", prefs.cloud_base_url,
static_cast<int>(reply->error()), qPrintable(reply->errorString()),
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),
qPrintable(reply->readAll()));
} while (nextServer());
// if none of the servers was reachable, update the user and switch to git_local_only
git_storage_update_progress(qPrintable(tr("Cloud connection failed")));
@ -89,9 +90,9 @@ bool CheckCloudConnection::checkServer()
void CheckCloudConnection::sslErrors(const QList<QSslError> &errorList)
{
qDebug() << "Received error response trying to set up https connection with cloud storage backend:";
report_info("Received error response trying to set up https connection with cloud storage backend:");
for (QSslError err: errorList)
qDebug() << err.errorString();
report_info("%s", qPrintable(err.errorString()));
}
bool CheckCloudConnection::nextServer()
@ -119,12 +120,12 @@ bool CheckCloudConnection::nextServer()
strcpy(baseurl, "https://");
strncat(baseurl, server, s);
strcat(baseurl, "/");
qDebug() << "failed to connect to" << prefs.cloud_base_url << "next server to try: " << baseurl;
report_info("failed to connect to %s next server to try: %s", prefs.cloud_base_url, baseurl);
prefs.cloud_base_url = baseurl;
git_storage_update_progress(qPrintable(tr("Trying different cloud server...")));
return true;
}
qDebug() << "failed to connect to any of the Subsurface cloud servers, giving up";
report_info("failed to connect to any of the Subsurface cloud servers, giving up");
return false;
}
@ -143,7 +144,7 @@ void CheckCloudConnection::gotIP(QNetworkReply *reply)
if (reply->error() != QNetworkReply::NoError) {
// whatever, just use the default host
if (verbose)
qDebug() << __FUNCTION__ << "got error reply from ip webservice - not changing cloud host";
report_info("%s got error reply from ip webservice - not changing cloud host", __func__);
return;
}
QString addressString = reply->readAll();
@ -153,11 +154,11 @@ void CheckCloudConnection::gotIP(QNetworkReply *reply)
if (addr.isNull()) {
// this isn't an address, don't try to update the cloud host
if (verbose)
qDebug() << __FUNCTION__ << "returned address doesn't appear to be valid (" << addressString << ") - not changing cloud host";
report_info("%s returned address doesn't appear to be valid (%s) - not changing cloud host", __func__, qPrintable(addressString));
return;
}
if (verbose)
qDebug() << "IP used for cloud server access" << addressString;
report_info("IP used for cloud server access %s", qPrintable(addressString));
// now figure out which continent we are on
QNetworkRequest request(QString(GET_CONTINENT_API).arg(addressString));
request.setRawHeader("Accept", "text/plain");
@ -172,7 +173,7 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
if (reply->error() != QNetworkReply::NoError) {
// whatever, just use the default host
if (verbose)
qDebug() << __FUNCTION__ << "got error reply from ip location webservice - not changing cloud host";
report_info("%s got error reply from ip location webservice - not changing cloud host", __func__);
return;
}
QString continentString = reply->readAll();
@ -193,7 +194,7 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
base_url = "https://" CLOUD_HOST_EU "/";
if (!same_string(base_url, prefs.cloud_base_url)) {
if (verbose)
qDebug() << "remember cloud server" << base_url << "based on IP location in " << continentString;
report_info("remember cloud server %s based on IP location in %s", base_url, qPrintable(continentString));
qPrefCloudStorage::instance()->store_cloud_base_url(base_url);
}
}
@ -202,17 +203,18 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
extern "C" bool canReachCloudServer(struct git_info *info)
{
if (verbose)
qWarning() << "Cloud storage: checking connection to cloud server" << info->url;
qWarning() << "Cloud storage: checking connection to cloud server" << info->url.c_str();
bool connection = CheckCloudConnection().checkServer();
if (strstr(info->url, prefs.cloud_base_url) == nullptr) {
if (info->url.find(prefs.cloud_base_url) == std::string::npos) {
// we switched the cloud URL - likely because we couldn't reach the server passed in
// the strstr with the offset is designed so we match the right component in the name;
// the cloud_base_url ends with a '/', so we need the text starting at "git/..."
char *newremote = format_string("%s%s", prefs.cloud_base_url, strstr(info->url, "org/git/") + 4);
if (verbose)
qDebug() << "updating remote to: " << newremote;
free((void*)info->url);
info->url = newremote;
size_t pos = info->url.find("org/git/");
if (pos != std::string::npos) {
info->url = format_string_std("%s%s", prefs.cloud_base_url, info->url.c_str() + pos + 4);
if (verbose)
report_info("updating remote to: %s", info->url.c_str());
}
}
return connection;
}

View File

@ -74,31 +74,30 @@ QNetworkReply* CloudStorageAuthenticate::deleteAccount(const QString& email, con
void CloudStorageAuthenticate::deleteFinished()
{
QString cloudAuthReply(reply->readAll());
qDebug() << "Completed connection with cloud storage backend, response" << cloudAuthReply;
std::string cloudAuthReply = reply->readAll().toStdString();
report_info("Completed connection with cloud storage backend, response %s", cloudAuthReply.c_str());
emit finishedDelete();
}
void CloudStorageAuthenticate::uploadFinished()
{
static QString myLastError;
static std::string myLastError;
QString cloudAuthReply(reply->readAll());
qDebug() << "Completed connection with cloud storage backend, response" << cloudAuthReply;
std::string cloudAuthReply = reply->readAll().toStdString();
report_info("Completed connection with cloud storage backend, response %s", cloudAuthReply.c_str());
if (cloudAuthReply == QLatin1String("[VERIFIED]") || cloudAuthReply == QLatin1String("[OK]")) {
if (cloudAuthReply == "[VERIFIED]" || cloudAuthReply == "[OK]") {
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_VERIFIED);
/* TODO: Move this to a correct place
NotificationWidget *nw = MainWindow::instance()->getNotificationWidget();
if (nw->getNotificationText() == myLastError)
if (nw->getNotificationText().toStdString() == myLastError)
nw->hideNotification();
*/
myLastError.clear();
} else if (cloudAuthReply == QLatin1String("[VERIFY]") ||
cloudAuthReply == QLatin1String("Invalid PIN")) {
} else if (cloudAuthReply == "[VERIFY]" || cloudAuthReply == "Invalid PIN") {
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NEED_TO_VERIFY);
report_error(qPrintable(tr("Cloud account verification required, enter PIN in preferences")));
} else if (cloudAuthReply == QLatin1String("[PASSWDCHANGED]")) {
report_error("%s", qPrintable(tr("Cloud account verification required, enter PIN in preferences")));
} else if (cloudAuthReply == "[PASSWDCHANGED]") {
qPrefCloudStorage::set_cloud_storage_password(cloudNewPassword);
cloudNewPassword.clear();
emit passwordChangeSuccessful();
@ -106,28 +105,28 @@ void CloudStorageAuthenticate::uploadFinished()
} else {
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_INCORRECT_USER_PASSWD);
myLastError = cloudAuthReply;
report_error("%s", qPrintable(cloudAuthReply));
report_error("%s", cloudAuthReply.c_str());
}
emit finishedAuthenticate();
}
void CloudStorageAuthenticate::uploadError(QNetworkReply::NetworkError)
{
qDebug() << "Received error response from cloud storage backend:" << reply->errorString();
report_info("Received error response from cloud storage backend: %s", qPrintable(reply->errorString()));
}
void CloudStorageAuthenticate::sslErrors(const QList<QSslError> &errorList)
{
if (verbose) {
qDebug() << "Received error response trying to set up https connection with cloud storage backend:";
report_info("Received error response trying to set up https connection with cloud storage backend:");
for (QSslError err: errorList) {
qDebug() << err.errorString();
report_info("%s", qPrintable(err.errorString()));
}
}
QSslConfiguration conf = reply->sslConfiguration();
QSslCertificate cert = conf.peerCertificate();
QByteArray hexDigest = cert.digest().toHex();
qDebug() << "got invalid SSL certificate with hex digest" << hexDigest;
report_info("got invalid SSL certificate with hex digest %s", qPrintable(hexDigest));
}
QNetworkAccessManager *manager()

View File

@ -207,7 +207,7 @@ static void cochran_debug_sample(const char *s, unsigned int sample_cnt)
static void cochran_parse_header(const unsigned char *decode, unsigned mod,
const unsigned char *in, unsigned size)
{
unsigned char *buf = malloc(size);
unsigned char *buf = (unsigned char *)malloc(size);
/* Do the "null decode" using a one-byte decode array of '\0' */
/* Copies in plaintext, will be overwritten later */
@ -441,7 +441,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
const unsigned char *s;
unsigned int offset = 0, profile_period = 1, sample_cnt = 0;
double depth = 0, temp = 0, depth_sample = 0, psi = 0, sgc_rate = 0;
int ascent_rate = 0;
//int ascent_rate = 0;
unsigned int ndl = 0;
unsigned int in_deco = 0, deco_ceiling = 0, deco_time = 0;
@ -517,8 +517,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
switch (config.type) {
case TYPE_COMMANDER:
switch (sample_cnt % 2) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
break;
case 1: // Temperature
temp = s[1] / 2 + 20;
@ -528,8 +528,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
case TYPE_GEMINI:
// Gemini with tank pressure and SAC rate.
switch (sample_cnt % 4) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
break;
case 2: // PSI change
psi -= (double)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 4;
@ -544,8 +544,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
break;
case TYPE_EMC:
switch (sample_cnt % 2) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
break;
case 1: // Temperature
temp = (double)s[1] / 2 + 20;
@ -597,7 +597,6 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
offset += config.sample_size;
sample_cnt++;
}
UNUSED(ascent_rate); // mark the variable as unused
if (sample_cnt > 0)
*duration = sample_cnt * profile_period - 1;
@ -607,7 +606,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
const unsigned char *in, unsigned size,
struct dive_table *table)
{
unsigned char *buf = malloc(size);
unsigned char *buf = (unsigned char *)malloc(size);
struct dive *dive;
struct divecomputer *dc;
struct tm tm = {0};
@ -712,9 +711,9 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->duration.seconds = (log[CMD_BT] + log[CMD_BT + 1] * 256) * 60;
dc->surfacetime.seconds = (log[CMD_SIT] + log[CMD_SIT + 1] * 256) * 60;
dc->maxdepth.mm = lrint((log[CMD_MAX_DEPTH] +
log[CMD_MAX_DEPTH + 1] * 256) / 4 * FEET * 1000);
log[CMD_MAX_DEPTH + 1] * 256) / 4.0 * FEET * 1000);
dc->meandepth.mm = lrint((log[CMD_AVG_DEPTH] +
log[CMD_AVG_DEPTH + 1] * 256) / 4 * FEET * 1000);
log[CMD_AVG_DEPTH + 1] * 256) / 4.0 * FEET * 1000);
dc->watertemp.mkelvin = F_to_mkelvin(log[CMD_MIN_TEMP]);
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
* (double) log[CMD_ALTITUDE] * 250 * FEET, 5.25588) * 1000);
@ -758,9 +757,9 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->duration.seconds = (log[EMC_BT] + log[EMC_BT + 1] * 256) * 60;
dc->surfacetime.seconds = (log[EMC_SIT] + log[EMC_SIT + 1] * 256) * 60;
dc->maxdepth.mm = lrint((log[EMC_MAX_DEPTH] +
log[EMC_MAX_DEPTH + 1] * 256) / 4 * FEET * 1000);
log[EMC_MAX_DEPTH + 1] * 256) / 4.0 * FEET * 1000);
dc->meandepth.mm = lrint((log[EMC_AVG_DEPTH] +
log[EMC_AVG_DEPTH + 1] * 256) / 4 * FEET * 1000);
log[EMC_AVG_DEPTH + 1] * 256) / 4.0 * FEET * 1000);
dc->watertemp.mkelvin = F_to_mkelvin(log[EMC_MIN_TEMP]);
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
* (double) log[EMC_ALTITUDE] * 250 * FEET, 5.25588) * 1000);
@ -800,26 +799,25 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
free(buf);
}
int try_to_open_cochran(const char *filename, struct memblock *mem, struct divelog *log)
int try_to_open_cochran(const char *, std::string &mem, struct divelog *log)
{
UNUSED(filename);
unsigned int i;
unsigned int mod;
unsigned int *offsets, dive1, dive2;
unsigned char *decode = mem->buffer + 0x40001;
unsigned char *decode = (unsigned char *)mem.data() + 0x40001;
if (mem->size < 0x40000)
if (mem.size() < 0x40000)
return 0;
offsets = (unsigned int *) mem->buffer;
offsets = (unsigned int *) mem.data();
dive1 = offsets[0];
dive2 = offsets[1];
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem.size())
return 0;
mod = decode[0x100] + 1;
cochran_parse_header(decode, mod, mem->buffer + 0x40000, dive1 - 0x40000);
cochran_parse_header(decode, mod, (unsigned char *)mem.data() + 0x40000, dive1 - 0x40000);
// Decode each dive
for (i = 0; i < 65534; i++) {
@ -827,10 +825,10 @@ int try_to_open_cochran(const char *filename, struct memblock *mem, struct divel
dive2 = offsets[i + 1];
if (dive2 < dive1)
break;
if (dive2 > mem->size)
if (dive2 > mem.size())
break;
cochran_parse_dive(decode, mod, mem->buffer + dive1,
cochran_parse_dive(decode, mod, (unsigned char *)mem.data() + dive1,
dive2 - dive1, log->dives);
}

View File

@ -41,7 +41,7 @@ void ConfigureDiveComputer::readSettings(device_data_t *data)
readThread->start();
}
void ConfigureDiveComputer::saveDeviceDetails(DeviceDetails *details, device_data_t *data)
void ConfigureDiveComputer::saveDeviceDetails(const DeviceDetails &details, device_data_t *data)
{
setState(WRITING);
@ -65,7 +65,7 @@ static QString writeGasDetails(gas g)
}).join(QLatin1Char(','));
}
bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails *details, device_data_t *data)
bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, const DeviceDetails &details, device_data_t *data)
{
QString xml = "";
QString vendor = data->vendor;
@ -80,37 +80,37 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
writer.writeTextElement("Product", product);
writer.writeEndElement();
writer.writeStartElement("Settings");
writer.writeTextElement("CustomText", details->customText);
writer.writeTextElement("CustomText", details.customText);
//Add gasses
writer.writeTextElement("Gas1", writeGasDetails(details->gas1));
writer.writeTextElement("Gas2", writeGasDetails(details->gas2));
writer.writeTextElement("Gas3", writeGasDetails(details->gas3));
writer.writeTextElement("Gas4", writeGasDetails(details->gas4));
writer.writeTextElement("Gas5", writeGasDetails(details->gas5));
writer.writeTextElement("Gas1", writeGasDetails(details.gas1));
writer.writeTextElement("Gas2", writeGasDetails(details.gas2));
writer.writeTextElement("Gas3", writeGasDetails(details.gas3));
writer.writeTextElement("Gas4", writeGasDetails(details.gas4));
writer.writeTextElement("Gas5", writeGasDetails(details.gas5));
//
//Add dil values
writer.writeTextElement("Dil1", writeGasDetails(details->dil1));
writer.writeTextElement("Dil2", writeGasDetails(details->dil2));
writer.writeTextElement("Dil3", writeGasDetails(details->dil3));
writer.writeTextElement("Dil4", writeGasDetails(details->dil4));
writer.writeTextElement("Dil5", writeGasDetails(details->dil5));
writer.writeTextElement("Dil1", writeGasDetails(details.dil1));
writer.writeTextElement("Dil2", writeGasDetails(details.dil2));
writer.writeTextElement("Dil3", writeGasDetails(details.dil3));
writer.writeTextElement("Dil4", writeGasDetails(details.dil4));
writer.writeTextElement("Dil5", writeGasDetails(details.dil5));
//Add setpoint values
QString sp1 = QString("%1,%2")
.arg(QString::number(details->sp1.sp),
QString::number(details->sp1.depth));
.arg(QString::number(details.sp1.sp),
QString::number(details.sp1.depth));
QString sp2 = QString("%1,%2")
.arg(QString::number(details->sp2.sp),
QString::number(details->sp2.depth));
.arg(QString::number(details.sp2.sp),
QString::number(details.sp2.depth));
QString sp3 = QString("%1,%2")
.arg(QString::number(details->sp3.sp),
QString::number(details->sp3.depth));
.arg(QString::number(details.sp3.sp),
QString::number(details.sp3.depth));
QString sp4 = QString("%1,%2")
.arg(QString::number(details->sp4.sp),
QString::number(details->sp4.depth));
.arg(QString::number(details.sp4.sp),
QString::number(details.sp4.depth));
QString sp5 = QString("%1,%2")
.arg(QString::number(details->sp5.sp),
QString::number(details->sp5.depth));
.arg(QString::number(details.sp5.sp),
QString::number(details.sp5.depth));
writer.writeTextElement("SetPoint1", sp1);
writer.writeTextElement("SetPoint2", sp2);
writer.writeTextElement("SetPoint3", sp3);
@ -118,60 +118,60 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
writer.writeTextElement("SetPoint5", sp5);
//Other Settings
writer.writeTextElement("DiveMode", QString::number(details->diveMode));
writer.writeTextElement("Saturation", QString::number(details->saturation));
writer.writeTextElement("Desaturation", QString::number(details->desaturation));
writer.writeTextElement("LastDeco", QString::number(details->lastDeco));
writer.writeTextElement("Brightness", QString::number(details->brightness));
writer.writeTextElement("Units", QString::number(details->units));
writer.writeTextElement("SamplingRate", QString::number(details->samplingRate));
writer.writeTextElement("Salinity", QString::number(details->salinity));
writer.writeTextElement("DiveModeColor", QString::number(details->diveModeColor));
writer.writeTextElement("Language", QString::number(details->language));
writer.writeTextElement("DateFormat", QString::number(details->dateFormat));
writer.writeTextElement("CompassGain", QString::number(details->compassGain));
writer.writeTextElement("SafetyStop", QString::number(details->safetyStop));
writer.writeTextElement("GfHigh", QString::number(details->gfHigh));
writer.writeTextElement("GfLow", QString::number(details->gfLow));
writer.writeTextElement("PressureSensorOffset", QString::number(details->pressureSensorOffset));
writer.writeTextElement("PpO2Min", QString::number(details->ppO2Min));
writer.writeTextElement("PpO2Max", QString::number(details->ppO2Max));
writer.writeTextElement("FutureTTS", QString::number(details->futureTTS));
writer.writeTextElement("CcrMode", QString::number(details->ccrMode));
writer.writeTextElement("DecoType", QString::number(details->decoType));
writer.writeTextElement("AGFSelectable", QString::number(details->aGFSelectable));
writer.writeTextElement("AGFHigh", QString::number(details->aGFHigh));
writer.writeTextElement("AGFLow", QString::number(details->aGFLow));
writer.writeTextElement("CalibrationGas", QString::number(details->calibrationGas));
writer.writeTextElement("FlipScreen", QString::number(details->flipScreen));
writer.writeTextElement("SetPointFallback", QString::number(details->setPointFallback));
writer.writeTextElement("LeftButtonSensitivity", QString::number(details->leftButtonSensitivity));
writer.writeTextElement("RightButtonSensitivity", QString::number(details->rightButtonSensitivity));
writer.writeTextElement("BottomGasConsumption", QString::number(details->bottomGasConsumption));
writer.writeTextElement("DecoGasConsumption", QString::number(details->decoGasConsumption));
writer.writeTextElement("ModWarning", QString::number(details->modWarning));
writer.writeTextElement("DynamicAscendRate", QString::number(details->dynamicAscendRate));
writer.writeTextElement("GraphicalSpeedIndicator", QString::number(details->graphicalSpeedIndicator));
writer.writeTextElement("AlwaysShowppO2", QString::number(details->alwaysShowppO2));
writer.writeTextElement("DiveMode", QString::number(details.diveMode));
writer.writeTextElement("Saturation", QString::number(details.saturation));
writer.writeTextElement("Desaturation", QString::number(details.desaturation));
writer.writeTextElement("LastDeco", QString::number(details.lastDeco));
writer.writeTextElement("Brightness", QString::number(details.brightness));
writer.writeTextElement("Units", QString::number(details.units));
writer.writeTextElement("SamplingRate", QString::number(details.samplingRate));
writer.writeTextElement("Salinity", QString::number(details.salinity));
writer.writeTextElement("DiveModeColor", QString::number(details.diveModeColor));
writer.writeTextElement("Language", QString::number(details.language));
writer.writeTextElement("DateFormat", QString::number(details.dateFormat));
writer.writeTextElement("CompassGain", QString::number(details.compassGain));
writer.writeTextElement("SafetyStop", QString::number(details.safetyStop));
writer.writeTextElement("GfHigh", QString::number(details.gfHigh));
writer.writeTextElement("GfLow", QString::number(details.gfLow));
writer.writeTextElement("PressureSensorOffset", QString::number(details.pressureSensorOffset));
writer.writeTextElement("PpO2Min", QString::number(details.ppO2Min));
writer.writeTextElement("PpO2Max", QString::number(details.ppO2Max));
writer.writeTextElement("FutureTTS", QString::number(details.futureTTS));
writer.writeTextElement("CcrMode", QString::number(details.ccrMode));
writer.writeTextElement("DecoType", QString::number(details.decoType));
writer.writeTextElement("AGFSelectable", QString::number(details.aGFSelectable));
writer.writeTextElement("AGFHigh", QString::number(details.aGFHigh));
writer.writeTextElement("AGFLow", QString::number(details.aGFLow));
writer.writeTextElement("CalibrationGas", QString::number(details.calibrationGas));
writer.writeTextElement("FlipScreen", QString::number(details.flipScreen));
writer.writeTextElement("SetPointFallback", QString::number(details.setPointFallback));
writer.writeTextElement("LeftButtonSensitivity", QString::number(details.leftButtonSensitivity));
writer.writeTextElement("RightButtonSensitivity", QString::number(details.rightButtonSensitivity));
writer.writeTextElement("BottomGasConsumption", QString::number(details.bottomGasConsumption));
writer.writeTextElement("DecoGasConsumption", QString::number(details.decoGasConsumption));
writer.writeTextElement("ModWarning", QString::number(details.modWarning));
writer.writeTextElement("DynamicAscendRate", QString::number(details.dynamicAscendRate));
writer.writeTextElement("GraphicalSpeedIndicator", QString::number(details.graphicalSpeedIndicator));
writer.writeTextElement("AlwaysShowppO2", QString::number(details.alwaysShowppO2));
// Suunto vyper settings.
writer.writeTextElement("Altitude", QString::number(details->altitude));
writer.writeTextElement("PersonalSafety", QString::number(details->personalSafety));
writer.writeTextElement("TimeFormat", QString::number(details->timeFormat));
writer.writeTextElement("Altitude", QString::number(details.altitude));
writer.writeTextElement("PersonalSafety", QString::number(details.personalSafety));
writer.writeTextElement("TimeFormat", QString::number(details.timeFormat));
writer.writeStartElement("Light");
writer.writeAttribute("enabled", QString::number(details->lightEnabled));
writer.writeCharacters(QString::number(details->light));
writer.writeAttribute("enabled", QString::number(details.lightEnabled));
writer.writeCharacters(QString::number(details.light));
writer.writeEndElement();
writer.writeStartElement("AlarmTime");
writer.writeAttribute("enabled", QString::number(details->alarmTimeEnabled));
writer.writeCharacters(QString::number(details->alarmTime));
writer.writeAttribute("enabled", QString::number(details.alarmTimeEnabled));
writer.writeCharacters(QString::number(details.alarmTime));
writer.writeEndElement();
writer.writeStartElement("AlarmDepth");
writer.writeAttribute("enabled", QString::number(details->alarmDepthEnabled));
writer.writeCharacters(QString::number(details->alarmDepth));
writer.writeAttribute("enabled", QString::number(details.alarmDepthEnabled));
writer.writeCharacters(QString::number(details.alarmDepth));
writer.writeEndElement();
writer.writeEndElement();
@ -192,7 +192,7 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
return true;
}
bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDetails *details)
bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDetails &details)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
@ -211,7 +211,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
QString keyString = reader.text().toString();
if (settingName == "CustomText")
details->customText = keyString;
details.customText = keyString;
if (settingName == "Gas1") {
QStringList gasData = keyString.split(",");
@ -220,7 +220,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
gas1.helium = gasData.at(1).toInt();
gas1.type = gasData.at(2).toInt();
gas1.depth = gasData.at(3).toInt();
details->gas1 = gas1;
details.gas1 = gas1;
}
if (settingName == "Gas2") {
@ -230,7 +230,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
gas2.helium = gasData.at(1).toInt();
gas2.type = gasData.at(2).toInt();
gas2.depth = gasData.at(3).toInt();
details->gas2 = gas2;
details.gas2 = gas2;
}
if (settingName == "Gas3") {
@ -240,7 +240,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
gas3.helium = gasData.at(1).toInt();
gas3.type = gasData.at(2).toInt();
gas3.depth = gasData.at(3).toInt();
details->gas3 = gas3;
details.gas3 = gas3;
}
if (settingName == "Gas4") {
@ -250,7 +250,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
gas4.helium = gasData.at(1).toInt();
gas4.type = gasData.at(2).toInt();
gas4.depth = gasData.at(3).toInt();
details->gas4 = gas4;
details.gas4 = gas4;
}
if (settingName == "Gas5") {
@ -260,7 +260,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
gas5.helium = gasData.at(1).toInt();
gas5.type = gasData.at(2).toInt();
gas5.depth = gasData.at(3).toInt();
details->gas5 = gas5;
details.gas5 = gas5;
}
if (settingName == "Dil1") {
@ -270,7 +270,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
dil1.helium = dilData.at(1).toInt();
dil1.type = dilData.at(2).toInt();
dil1.depth = dilData.at(3).toInt();
details->dil1 = dil1;
details.dil1 = dil1;
}
if (settingName == "Dil2") {
@ -280,7 +280,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
dil2.helium = dilData.at(1).toInt();
dil2.type = dilData.at(2).toInt();
dil2.depth = dilData.at(3).toInt();
details->dil1 = dil2;
details.dil1 = dil2;
}
if (settingName == "Dil3") {
@ -290,7 +290,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
dil3.helium = dilData.at(1).toInt();
dil3.type = dilData.at(2).toInt();
dil3.depth = dilData.at(3).toInt();
details->dil3 = dil3;
details.dil3 = dil3;
}
if (settingName == "Dil4") {
@ -300,7 +300,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
dil4.helium = dilData.at(1).toInt();
dil4.type = dilData.at(2).toInt();
dil4.depth = dilData.at(3).toInt();
details->dil4 = dil4;
details.dil4 = dil4;
}
if (settingName == "Dil5") {
@ -310,7 +310,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
dil5.helium = dilData.at(1).toInt();
dil5.type = dilData.at(2).toInt();
dil5.depth = dilData.at(3).toInt();
details->dil5 = dil5;
details.dil5 = dil5;
}
if (settingName == "SetPoint1") {
@ -318,7 +318,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
setpoint sp1;
sp1.sp = spData.at(0).toInt();
sp1.depth = spData.at(1).toInt();
details->sp1 = sp1;
details.sp1 = sp1;
}
if (settingName == "SetPoint2") {
@ -326,7 +326,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
setpoint sp2;
sp2.sp = spData.at(0).toInt();
sp2.depth = spData.at(1).toInt();
details->sp2 = sp2;
details.sp2 = sp2;
}
if (settingName == "SetPoint3") {
@ -334,7 +334,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
setpoint sp3;
sp3.sp = spData.at(0).toInt();
sp3.depth = spData.at(1).toInt();
details->sp3 = sp3;
details.sp3 = sp3;
}
if (settingName == "SetPoint4") {
@ -342,7 +342,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
setpoint sp4;
sp4.sp = spData.at(0).toInt();
sp4.depth = spData.at(1).toInt();
details->sp4 = sp4;
details.sp4 = sp4;
}
if (settingName == "SetPoint5") {
@ -350,139 +350,139 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
setpoint sp5;
sp5.sp = spData.at(0).toInt();
sp5.depth = spData.at(1).toInt();
details->sp5 = sp5;
details.sp5 = sp5;
}
if (settingName == "Saturation")
details->saturation = keyString.toInt();
details.saturation = keyString.toInt();
if (settingName == "Desaturation")
details->desaturation = keyString.toInt();
details.desaturation = keyString.toInt();
if (settingName == "DiveMode")
details->diveMode = keyString.toInt();
details.diveMode = keyString.toInt();
if (settingName == "LastDeco")
details->lastDeco = keyString.toInt();
details.lastDeco = keyString.toInt();
if (settingName == "Brightness")
details->brightness = keyString.toInt();
details.brightness = keyString.toInt();
if (settingName == "Units")
details->units = keyString.toInt();
details.units = keyString.toInt();
if (settingName == "SamplingRate")
details->samplingRate = keyString.toInt();
details.samplingRate = keyString.toInt();
if (settingName == "Salinity")
details->salinity = keyString.toInt();
details.salinity = keyString.toInt();
if (settingName == "DiveModeColour")
details->diveModeColor = keyString.toInt();
details.diveModeColor = keyString.toInt();
if (settingName == "Language")
details->language = keyString.toInt();
details.language = keyString.toInt();
if (settingName == "DateFormat")
details->dateFormat = keyString.toInt();
details.dateFormat = keyString.toInt();
if (settingName == "CompassGain")
details->compassGain = keyString.toInt();
details.compassGain = keyString.toInt();
if (settingName == "SafetyStop")
details->safetyStop = keyString.toInt();
details.safetyStop = keyString.toInt();
if (settingName == "GfHigh")
details->gfHigh = keyString.toInt();
details.gfHigh = keyString.toInt();
if (settingName == "GfLow")
details->gfLow = keyString.toInt();
details.gfLow = keyString.toInt();
if (settingName == "PressureSensorOffset")
details->pressureSensorOffset = keyString.toInt();
details.pressureSensorOffset = keyString.toInt();
if (settingName == "PpO2Min")
details->ppO2Min = keyString.toInt();
details.ppO2Min = keyString.toInt();
if (settingName == "PpO2Max")
details->ppO2Max = keyString.toInt();
details.ppO2Max = keyString.toInt();
if (settingName == "FutureTTS")
details->futureTTS = keyString.toInt();
details.futureTTS = keyString.toInt();
if (settingName == "CcrMode")
details->ccrMode = keyString.toInt();
details.ccrMode = keyString.toInt();
if (settingName == "DecoType")
details->decoType = keyString.toInt();
details.decoType = keyString.toInt();
if (settingName == "AGFSelectable")
details->aGFSelectable = keyString.toInt();
details.aGFSelectable = keyString.toInt();
if (settingName == "AGFHigh")
details->aGFHigh = keyString.toInt();
details.aGFHigh = keyString.toInt();
if (settingName == "AGFLow")
details->aGFLow = keyString.toInt();
details.aGFLow = keyString.toInt();
if (settingName == "CalibrationGas")
details->calibrationGas = keyString.toInt();
details.calibrationGas = keyString.toInt();
if (settingName == "FlipScreen")
details->flipScreen = keyString.toInt();
details.flipScreen = keyString.toInt();
if (settingName == "SetPointFallback")
details->setPointFallback = keyString.toInt();
details.setPointFallback = keyString.toInt();
if (settingName == "LeftButtonSensitivity")
details->leftButtonSensitivity = keyString.toInt();
details.leftButtonSensitivity = keyString.toInt();
if (settingName == "RightButtonSensitivity")
details->rightButtonSensitivity = keyString.toInt();
details.rightButtonSensitivity = keyString.toInt();
if (settingName == "BottomGasConsumption")
details->bottomGasConsumption = keyString.toInt();
details.bottomGasConsumption = keyString.toInt();
if (settingName == "DecoGasConsumption")
details->decoGasConsumption = keyString.toInt();
details.decoGasConsumption = keyString.toInt();
if (settingName == "ModWarning")
details->modWarning = keyString.toInt();
details.modWarning = keyString.toInt();
if (settingName == "DynamicAscendRate")
details->dynamicAscendRate = keyString.toInt();
details.dynamicAscendRate = keyString.toInt();
if (settingName == "GraphicalSpeedIndicator")
details->graphicalSpeedIndicator = keyString.toInt();
details.graphicalSpeedIndicator = keyString.toInt();
if (settingName == "AlwaysShowppO2")
details->alwaysShowppO2 = keyString.toInt();
details.alwaysShowppO2 = keyString.toInt();
if (settingName == "Altitude")
details->altitude = keyString.toInt();
details.altitude = keyString.toInt();
if (settingName == "PersonalSafety")
details->personalSafety = keyString.toInt();
details.personalSafety = keyString.toInt();
if (settingName == "TimeFormat")
details->timeFormat = keyString.toInt();
details.timeFormat = keyString.toInt();
if (settingName == "Light") {
if (attributes.hasAttribute("enabled"))
details->lightEnabled = attributes.value("enabled").toString().toInt();
details->light = keyString.toInt();
details.lightEnabled = attributes.value("enabled").toString().toInt();
details.light = keyString.toInt();
}
if (settingName == "AlarmDepth") {
if (attributes.hasAttribute("enabled"))
details->alarmDepthEnabled = attributes.value("enabled").toString().toInt();
details->alarmDepth = keyString.toInt();
details.alarmDepthEnabled = attributes.value("enabled").toString().toInt();
details.alarmDepth = keyString.toInt();
}
if (settingName == "AlarmTime") {
if (attributes.hasAttribute("enabled"))
details->alarmTimeEnabled = attributes.value("enabled").toString().toInt();
details->alarmTime = keyString.toInt();
details.alarmTimeEnabled = attributes.value("enabled").toString().toInt();
details.alarmTime = keyString.toInt();
}
}
reader.readNext();
@ -574,8 +574,8 @@ QString ConfigureDiveComputer::dc_open(device_data_t *data)
FILE *fp = NULL;
dc_status_t rc;
if (data->libdc_log)
fp = subsurface_fopen(logfile_name, "w");
if (data->libdc_log && !logfile_name.empty())
fp = subsurface_fopen(logfile_name.c_str(), "w");
data->libdc_logfile = fp;
@ -594,7 +594,7 @@ QString ConfigureDiveComputer::dc_open(device_data_t *data)
rc = divecomputer_device_open(data);
if (rc != DC_STATUS_SUCCESS) {
report_error(errmsg(rc));
report_error("%s", errmsg(rc));
} else {
rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream);
}

View File

@ -32,10 +32,10 @@ public:
QString lastError;
states currentState;
void saveDeviceDetails(DeviceDetails *details, device_data_t *data);
void saveDeviceDetails(const DeviceDetails &details, device_data_t *data);
void fetchDeviceDetails();
bool saveXMLBackup(const QString &fileName, DeviceDetails *details, device_data_t *data);
bool restoreXMLBackup(const QString &fileName, DeviceDetails *details);
bool saveXMLBackup(const QString &fileName, const DeviceDetails &details, device_data_t *data);
bool restoreXMLBackup(const QString &fileName, DeviceDetails &details);
void startFirmwareUpdate(const QString &fileName, device_data_t *data, bool forceUpdate);
void resetSettings(device_data_t *data);
@ -48,7 +48,7 @@ signals:
void message(QString msg);
void error(QString err);
void stateChanged(states newState);
void deviceDetailsChanged(DeviceDetails *newDetails);
void deviceDetailsChanged(DeviceDetails newDetails);
private:
ReadSettingsThread *readThread;

File diff suppressed because it is too large Load Diff

View File

@ -27,18 +27,18 @@ public:
ReadSettingsThread(QObject *parent, device_data_t *data);
void run();
signals:
void devicedetails(DeviceDetails *newDeviceDetails);
void devicedetails(DeviceDetails newDeviceDetails);
};
class WriteSettingsThread : public DeviceThread {
Q_OBJECT
public:
WriteSettingsThread(QObject *parent, device_data_t *data);
void setDeviceDetails(DeviceDetails *details);
void setDeviceDetails(const DeviceDetails &details);
void run();
private:
DeviceDetails *m_deviceDetails;
DeviceDetails m_deviceDetails;
};
class FirmwareUpdateThread : public DeviceThread {

View File

@ -67,7 +67,7 @@ static char *to_utf8(unsigned char *in_string)
inlen = strlen((char *)in_string);
outlen = inlen * 2 + 1;
char *out_string = calloc(outlen, 1);
char *out_string = (char *)calloc(outlen, 1);
for (i = 0; i < inlen; i++) {
if (in_string[i] < 127) {
out_string[j] = in_string[i];
@ -158,7 +158,7 @@ static dc_status_t dt_libdc_buffer(unsigned char *ptr, int prf_length, int dc_mo
* Parses a mem buffer extracting its data and filling a subsurface's dive structure.
* Returns a pointer to last position in buffer, or NULL on failure.
*/
static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct divelog *log, long maxbuf)
static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct divelog *log, char *maxbuf)
{
int rc, profile_length, libdc_model;
char *tmp_notes_str = NULL;
@ -174,7 +174,7 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
struct dive_site *ds;
char is_nitrox = 0, is_O2 = 0, is_SCR = 0;
device_data_t *devdata = calloc(1, sizeof(device_data_t));
device_data_t *devdata = (device_data_t *)calloc(1, sizeof(device_data_t));
devdata->log = log;
/*
@ -478,8 +478,8 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
tmp_notes_str ? tmp_notes_str : "",
QT_TRANSLATE_NOOP("gettextFromC", "Datatrak/Wlog notes"),
tmp_string1);
dt_dive->notes = calloc((len +1), 1);
dt_dive->notes = memcpy(dt_dive->notes, buffer, len);
dt_dive->notes = (char *)calloc((len +1), 1);
memcpy(dt_dive->notes, buffer, len);
free(tmp_string1);
}
free(tmp_notes_str);
@ -571,7 +571,7 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
((get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000);
}
free(devdata);
return membuf;
return (char *)membuf;
bail:
free(locality);
free(devdata);
@ -582,10 +582,10 @@ bail:
* Parses the header of the .add file, returns the number of dives in
* the archive (must be the same than number of dives in .log file).
*/
static int wlog_header_parser (struct memblock *mem)
static int wlog_header_parser (std::string &mem)
{
int tmp;
unsigned char *runner = (unsigned char *) mem->buffer;
unsigned char *runner = (unsigned char *) mem.data();
if (!runner)
return -1;
if (!memcmp(runner, "\x52\x02", 2)) {
@ -600,7 +600,7 @@ static int wlog_header_parser (struct memblock *mem)
#define NOTES_LENGTH 256
#define SUIT_LENGTH 26
static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int dcount)
static void wlog_compl_parser(std::string &wl_mem, struct dive *dt_dive, int dcount)
{
int tmp = 0, offset = 12 + (dcount * 850),
pos_weight = offset + 256,
@ -608,7 +608,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
pos_tank_init = offset + 266,
pos_suit = offset + 268;
char *wlog_notes = NULL, *wlog_suit = NULL, *buffer = NULL;
unsigned char *runner = (unsigned char *) wl_mem->buffer;
unsigned char *runner = (unsigned char *) wl_mem.data();
/*
* Extended notes string. Fixed length 256 bytes. 0 padded if not complete
@ -620,7 +620,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
wlog_notes = to_utf8((unsigned char *) wlog_notes_temp);
}
if (dt_dive->notes && wlog_notes) {
buffer = calloc (strlen(dt_dive->notes) + strlen(wlog_notes) + 1, 1);
buffer = (char *)calloc (strlen(dt_dive->notes) + strlen(wlog_notes) + 1, 1);
sprintf(buffer, "%s%s", dt_dive->notes, wlog_notes);
free(dt_dive->notes);
dt_dive->notes = copy_string(buffer);
@ -635,7 +635,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
*/
tmp = (int) two_bytes_to_int(runner[pos_weight + 1], runner[pos_weight]);
if (tmp != 0x7fff) {
weightsystem_t ws = { {lrint(tmp * 10)}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
weightsystem_t ws = { {tmp * 10}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
add_cloned_weightsystem(&dt_dive->weightsystems, ws);
}
@ -675,45 +675,43 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
}
/*
* Main function call from file.c memblock is allocated (and freed) there.
* Main function call from file.c data is allocated (and freed) there.
* If parsing is aborted due to errors, stores correctly parsed dives.
*/
int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelog *log)
int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
{
unsigned char *runner;
char *runner;
int i = 0, numdives = 0, rc = 0;
long maxbuf = (long) mem->buffer + mem->size;
char *maxbuf = mem.data() + mem.size();
// Verify fileheader, get number of dives in datatrak divelog, zero on error
numdives = read_file_header((unsigned char *)mem->buffer);
numdives = read_file_header((unsigned char *)mem.data());
if (!numdives) {
report_error(translate("gettextFromC", "[Error] File is not a DataTrak file. Aborted"));
report_error("%s", translate("gettextFromC", "[Error] File is not a DataTrak file. Aborted"));
goto bail;
}
// Verify WLog .add file, Beginning sequence and Nº dives
if(wl_mem) {
if(!wl_mem.empty()) {
int compl_dives_n = wlog_header_parser(wl_mem);
if (compl_dives_n != numdives) {
report_error("ERROR: Not the same number of dives in .log %d and .add file %d.\nWill not parse .add file", numdives , compl_dives_n);
free(wl_mem->buffer);
wl_mem->buffer = NULL;
wl_mem = NULL;
wl_mem.clear();
}
}
// Point to the expected begining of 1st. dive data
runner = (unsigned char *)mem->buffer;
runner = mem.data();
JUMP(runner, 12);
// Secuential parsing. Abort if received NULL from dt_dive_parser.
while ((i < numdives) && ((long) runner < maxbuf)) {
while ((i < numdives) && (runner < maxbuf)) {
struct dive *ptdive = alloc_dive();
runner = dt_dive_parser(runner, ptdive, log, maxbuf);
if (wl_mem)
runner = dt_dive_parser((unsigned char *)runner, ptdive, log, maxbuf);
if (!wl_mem.empty())
wlog_compl_parser(wl_mem, ptdive, i);
if (runner == NULL) {
report_error(translate("gettextFromC", "Error: no dive"));
report_error("%s", translate("gettextFromC", "Error: no dive"));
free(ptdive);
rc = 1;
goto out;
@ -723,7 +721,6 @@ int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelo
i++;
}
out:
taglist_cleanup(&g_tag_list);
sort_dive_table(log->dives);
return rc;
bail:

View File

@ -41,8 +41,8 @@ static const struct models_table_t g_models[] = {
{0xEE, 0x44, "Uwatec Unknown model", DC_FAMILY_UWATEC_ALADIN},
};
#define JUMP(_ptr, _n) if ((long) (_ptr += _n) > maxbuf) goto bail
#define CHECK(_ptr, _n) if ((long) _ptr + _n > maxbuf) goto bail
#define JUMP(_ptr, _n) if ((char *) (_ptr += _n) > (char *)maxbuf) goto bail
#define CHECK(_ptr, _n) if ((char *) _ptr + _n > (char *)maxbuf) goto bail
#define read_bytes(_n) \
switch (_n) { \
case 1: \
@ -62,10 +62,12 @@ static const struct models_table_t g_models[] = {
#define read_string(_property) \
CHECK(membuf, tmp_1byte); \
{ \
unsigned char *_property##tmp = (unsigned char *)calloc(tmp_1byte + 1, 1); \
_property##tmp = memcpy(_property##tmp, membuf, tmp_1byte);\
_property##tmp = (unsigned char*)memcpy(_property##tmp, membuf, tmp_1byte);\
_property = (unsigned char *)strcat(to_utf8(_property##tmp), ""); \
free(_property##tmp);\
JUMP(membuf, tmp_1byte);
JUMP(membuf, tmp_1byte); \
}
#endif // DATATRAK_HEADER_H

View File

@ -13,8 +13,6 @@
* set_gf() - set Buehlmann gradient factors
* set_vpmb_conservatism() - set VPM-B conservatism value
* clear_deco()
* cache_deco_state()
* restore_deco_state()
* dump_tissues()
*/
#include <stdlib.h>
@ -218,7 +216,7 @@ static double vpmb_tolerated_ambient_pressure(struct deco_state *ds, double refe
return ds->tissue_n2_sat[ci] + ds->tissue_he_sat[ci] + vpmb_config.other_gases_pressure - total_gradient;
}
double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, double pressure, bool in_planner)
extern "C" double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, double pressure, bool in_planner)
{
int ci = -1;
double ret_tolerance_limit_ambient_pressure = 0.0;
@ -325,7 +323,7 @@ static double calc_surface_phase(double surface_pressure, double he_pressure, do
return 0;
}
void vpmb_start_gradient(struct deco_state *ds)
extern "C" void vpmb_start_gradient(struct deco_state *ds)
{
int ci;
@ -335,7 +333,7 @@ void vpmb_start_gradient(struct deco_state *ds)
}
}
void vpmb_next_gradient(struct deco_state *ds, double deco_time, double surface_pressure, bool in_planner)
extern "C" void vpmb_next_gradient(struct deco_state *ds, double deco_time, double surface_pressure, bool in_planner)
{
int ci;
double n2_b, n2_c;
@ -381,7 +379,7 @@ static double solve_cubic(double A, double B, double C)
}
void nuclear_regeneration(struct deco_state *ds, double time)
extern "C" void nuclear_regeneration(struct deco_state *ds, double time)
{
time /= 60.0;
int ci;
@ -413,7 +411,7 @@ static double calc_inner_pressure(double crit_radius, double onset_tension, doub
}
// Calculates the crushing pressure in the given moment. Updates crushing_onset_tension and critical radius if needed
void calc_crushing_pressure(struct deco_state *ds, double pressure)
extern "C" void calc_crushing_pressure(struct deco_state *ds, double pressure)
{
int ci;
double gradient;
@ -438,16 +436,15 @@ void calc_crushing_pressure(struct deco_state *ds, double pressure)
n2_crushing_pressure = pressure - n2_inner_pressure;
he_crushing_pressure = pressure - he_inner_pressure;
}
ds->max_n2_crushing_pressure[ci] = MAX(ds->max_n2_crushing_pressure[ci], n2_crushing_pressure);
ds->max_he_crushing_pressure[ci] = MAX(ds->max_he_crushing_pressure[ci], he_crushing_pressure);
ds->max_n2_crushing_pressure[ci] = std::max(ds->max_n2_crushing_pressure[ci], n2_crushing_pressure);
ds->max_he_crushing_pressure[ci] = std::max(ds->max_he_crushing_pressure[ci], he_crushing_pressure);
}
ds->max_ambient_pressure = MAX(pressure, ds->max_ambient_pressure);
ds->max_ambient_pressure = std::max(pressure, ds->max_ambient_pressure);
}
/* add period_in_seconds at the given pressure and gas to the deco calculation */
void add_segment(struct deco_state *ds, double pressure, struct gasmix gasmix, int period_in_seconds, int ccpo2, enum divemode_t divemode, int sac, bool in_planner)
extern "C" void add_segment(struct deco_state *ds, double pressure, struct gasmix gasmix, int period_in_seconds, int ccpo2, enum divemode_t divemode, int, bool in_planner)
{
UNUSED(sac);
int ci;
struct gas_pressures pressures;
bool icd = false;
@ -479,7 +476,7 @@ void add_segment(struct deco_state *ds, double pressure, struct gasmix gasmix, i
}
#if DECO_CALC_DEBUG
void dump_tissues(struct deco_state *ds)
extern "C" void dump_tissues(struct deco_state *ds)
{
int ci;
printf("N2 tissues:");
@ -492,7 +489,7 @@ void dump_tissues(struct deco_state *ds)
}
#endif
void clear_vpmb_state(struct deco_state *ds)
extern "C" void clear_vpmb_state(struct deco_state *ds)
{
int ci;
for (ci = 0; ci < 16; ci++) {
@ -504,7 +501,7 @@ void clear_vpmb_state(struct deco_state *ds)
ds->max_bottom_ceiling_pressure.mbar = 0;
}
void clear_deco(struct deco_state *ds, double surface_pressure, bool in_planner)
extern "C" void clear_deco(struct deco_state *ds, double surface_pressure, bool in_planner)
{
int ci;
@ -523,19 +520,17 @@ void clear_deco(struct deco_state *ds, double surface_pressure, bool in_planner)
ds->ci_pointing_to_guiding_tissue = -1;
}
void cache_deco_state(struct deco_state *src, struct deco_state **cached_datap)
void deco_state_cache::cache(const struct deco_state *src)
{
struct deco_state *data = *cached_datap;
if (!data) {
data = malloc(sizeof(struct deco_state));
*cached_datap = data;
}
if (!data)
data = std::make_unique<deco_state>();
*data = *src;
}
void restore_deco_state(struct deco_state *data, struct deco_state *target, bool keep_vpmb_state)
void deco_state_cache::restore(struct deco_state *target, bool keep_vpmb_state) const
{
if (!data)
return;
if (keep_vpmb_state) {
int ci;
for (ci = 0; ci < 16; ci++) {
@ -548,10 +543,9 @@ void restore_deco_state(struct deco_state *data, struct deco_state *target, bool
data->max_bottom_ceiling_pressure = target->max_bottom_ceiling_pressure;
}
*target = *data;
}
int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth)
extern "C" int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const struct dive *dive, bool smooth)
{
int depth;
double pressure_delta;
@ -570,7 +564,7 @@ int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const
return depth;
}
void set_gf(short gflow, short gfhigh)
extern "C" void set_gf(short gflow, short gfhigh)
{
if (gflow != -1)
buehlmann_config.gf_low = (double)gflow / 100.0;
@ -578,7 +572,7 @@ void set_gf(short gflow, short gfhigh)
buehlmann_config.gf_high = (double)gfhigh / 100.0;
}
void set_vpmb_conservatism(short conservatism)
extern "C" void set_vpmb_conservatism(short conservatism)
{
if (conservatism < 0)
vpmb_config.conservatism = 0;
@ -588,21 +582,21 @@ void set_vpmb_conservatism(short conservatism)
vpmb_config.conservatism = conservatism;
}
double get_gf(struct deco_state *ds, double ambpressure_bar, const struct dive *dive)
extern "C" double get_gf(struct deco_state *ds, double ambpressure_bar, const struct dive *dive)
{
double surface_pressure_bar = get_surface_pressure_in_mbar(dive, true) / 1000.0;
double gf_low = buehlmann_config.gf_low;
double gf_high = buehlmann_config.gf_high;
double gf;
if (ds->gf_low_pressure_this_dive > surface_pressure_bar)
gf = MAX((double)gf_low, (ambpressure_bar - surface_pressure_bar) /
gf = std::max((double)gf_low, (ambpressure_bar - surface_pressure_bar) /
(ds->gf_low_pressure_this_dive - surface_pressure_bar) * (gf_low - gf_high) + gf_high);
else
gf = gf_low;
return gf;
}
double regressiona(const struct deco_state *ds)
extern "C" double regressiona(const struct deco_state *ds)
{
if (ds->sum1 > 1) {
double avxy = ds->sumxy / ds->sum1;
@ -615,7 +609,7 @@ double regressiona(const struct deco_state *ds)
return 0.0;
}
double regressionb(const struct deco_state *ds)
extern "C" double regressionb(const struct deco_state *ds)
{
if (ds->sum1)
return ds->sumy / ds->sum1 - ds->sumx * regressiona(ds) / ds->sum1;
@ -623,14 +617,14 @@ double regressionb(const struct deco_state *ds)
return 0.0;
}
void reset_regression(struct deco_state *ds)
extern "C" void reset_regression(struct deco_state *ds)
{
ds->sum1 = 0;
ds->sumxx = ds->sumx = 0L;
ds->sumy = ds->sumxy = 0.0;
}
void update_regression(struct deco_state *ds, const struct dive *dive)
extern "C" void update_regression(struct deco_state *ds, const struct dive *dive)
{
if (!ds->plot_depth)
return;

View File

@ -56,8 +56,6 @@ extern void clear_deco(struct deco_state *ds, double surface_pressure, bool in_p
extern void dump_tissues(struct deco_state *ds);
extern void set_gf(short gflow, short gfhigh);
extern void set_vpmb_conservatism(short conservatism);
extern void cache_deco_state(struct deco_state *source, struct deco_state **datap);
extern void restore_deco_state(struct deco_state *data, struct deco_state *target, bool keep_vpmb_state);
extern void nuclear_regeneration(struct deco_state *ds, double time);
extern void vpmb_start_gradient(struct deco_state *ds);
extern void vpmb_next_gradient(struct deco_state *ds, double deco_time, double surface_pressure, bool in_planner);
@ -74,6 +72,21 @@ extern void update_regression(struct deco_state *ds, const struct dive *dive);
#ifdef __cplusplus
}
// C++ only functions
#include <memory>
struct deco_state_cache {
// Test if there is cached data
operator bool () {
return !!data;
}
void cache(const struct deco_state *source);
void restore(struct deco_state *target, bool keep_vpmb_state) const;
private:
std::unique_ptr<deco_state> data;
};
#endif
#endif // DECO_H

View File

@ -4,7 +4,7 @@
#include "divelist.h"
#include "divelog.h"
#include "subsurface-string.h"
#include "errorhelper.h" // for verbose flag
#include "errorhelper.h"
#include "selection.h"
#include "core/settings/qPrefDiveComputer.h"
@ -60,9 +60,9 @@ void device::showchanges(const std::string &n) const
{
if (nickName != n) {
if (!n.empty())
qDebug("new nickname %s for DC model %s serial %s", n.c_str(), model.c_str(), serialNumber.c_str());
report_info("new nickname %s for DC model %s serial %s", n.c_str(), model.c_str(), serialNumber.c_str());
else
qDebug("deleted nickname %s for DC model %s serial %s", nickName.c_str(), model.c_str(), serialNumber.c_str());
report_info("deleted nickname %s for DC model %s serial %s", nickName.c_str(), model.c_str(), serialNumber.c_str());
}
}
@ -286,12 +286,20 @@ extern "C" uint32_t fp_get_diveid(struct fingerprint_table *table, unsigned int
return table->fingerprints[i].fdiveid;
}
extern "C" char *fp_get_data(struct fingerprint_table *table, unsigned int i)
static char to_hex_digit(unsigned char d)
{
return d <= 9 ? d + '0' : d - 10 + 'a';
}
std::string fp_get_data(struct fingerprint_table *table, unsigned int i)
{
if (!table || i >= table->fingerprints.size())
return 0;
return std::string();
struct fingerprint_record *fpr = &table->fingerprints[i];
// fromRawData() avoids one copy of the raw_data
QByteArray hex = QByteArray::fromRawData((char *)fpr->raw_data, fpr->fsize).toHex();
return strdup(hex.constData());
std::string res(fpr->fsize * 2, ' ');
for (unsigned int i = 0; i < fpr->fsize; ++i) {
res[2 * i] = to_hex_digit((fpr->raw_data[i] >> 4) & 0xf);
res[2 * i + 1] = to_hex_digit(fpr->raw_data[i] & 0xf);
}
return res;
}

View File

@ -54,7 +54,6 @@ extern uint32_t fp_get_model(struct fingerprint_table *table, unsigned int i);
extern uint32_t fp_get_serial(struct fingerprint_table *table, unsigned int i);
extern uint32_t fp_get_deviceid(struct fingerprint_table *table, unsigned int i);
extern uint32_t fp_get_diveid(struct fingerprint_table *table, unsigned int i);
extern char *fp_get_data(struct fingerprint_table *table, unsigned int i);
extern int is_default_dive_computer_device(const char *);
@ -100,6 +99,8 @@ struct fingerprint_table {
std::vector<fingerprint_record> fingerprints;
};
std::string fp_get_data(struct fingerprint_table *table, unsigned int i);
#endif
#endif // DEVICE_H

View File

@ -11,8 +11,7 @@ setpoint::setpoint(unsigned char sp, unsigned char depth) :
{
}
DeviceDetails::DeviceDetails(QObject *parent) :
QObject(parent),
DeviceDetails::DeviceDetails() :
syncTime(false),
setPointFallback(0),
ccrMode(0),

View File

@ -20,11 +20,10 @@ struct setpoint {
setpoint(unsigned char sp = 0, unsigned char depth = 0);
};
class DeviceDetails : public QObject
class DeviceDetails
{
Q_OBJECT
public:
explicit DeviceDetails(QObject *parent = 0);
DeviceDetails();
QString serialNo;
QString firmwareVersion;
@ -103,5 +102,6 @@ public:
unsigned safetyStopResetDepth;
};
Q_DECLARE_METATYPE(DeviceDetails);
#endif // DEVICEDETAILS_H

File diff suppressed because it is too large Load Diff

View File

@ -141,8 +141,7 @@ void split_divecomputer(const struct dive *src, int num, struct dive **out1, str
for (_dc = &_dive->dc; _dc; _dc = _dc->next)
#define for_each_relevant_dc(_dive, _dc) \
bool _all_planned = !has_planned(_dive, false); \
for (_dc = &_dive->dc; _dc; _dc = _dc->next) if (_all_planned || !is_dc_planner(_dc))
for (_dc = &_dive->dc; _dc; _dc = _dc->next) if (!is_logged(_dive) || !is_dc_planner(_dc))
extern struct dive *get_dive_by_uniq_id(int id);
extern int get_idx_by_uniq_id(int id);
@ -187,7 +186,7 @@ extern int split_dive(const struct dive *dive, struct dive **new1, struct dive *
extern int split_dive_at_time(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2);
extern struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site);
extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded);
extern void copy_events_until(const struct dive *sd, struct dive *dd, int time);
extern void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int time);
extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only);
extern bool is_cylinder_used(const struct dive *dive, int idx);
extern bool is_cylinder_prot(const struct dive *dive, int idx);
@ -207,9 +206,8 @@ extern void invalidate_dive_cache(struct dive *dc);
extern int total_weight(const struct dive *);
extern const char *existing_filename;
extern bool has_planned(const struct dive *dive, bool planned);
extern bool is_planned(const struct dive *dive);
extern bool is_logged(const struct dive *dive);
/* Get gasmixes at increasing timestamps.
* In "evp", pass a pointer to a "struct event *" which is NULL-initialized on first invocation.
@ -220,7 +218,6 @@ extern struct gasmix get_gasmix(const struct dive *dive, const struct divecomput
/* Get gasmix at a given time */
extern struct gasmix get_gasmix_at_time(const struct dive *dive, const struct divecomputer *dc, duration_t time);
extern char *get_dive_date_c_string(timestamp_t when);
extern void update_setpoint_events(const struct dive *dive, struct divecomputer *dc);
#ifdef __cplusplus
@ -230,8 +227,11 @@ extern void update_setpoint_events(const struct dive *dive, struct divecomputer
* QVariants and through QML.
*/
#include <QObject>
#include <string>
Q_DECLARE_METATYPE(struct dive *);
extern std::string existing_filename;
#endif
#endif // DIVE_H

View File

@ -492,11 +492,6 @@ void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
}
}
bool is_dc_planner(const struct divecomputer *dc)
{
return same_string(dc->model, "planned dive");
}
/*
* Match two dive computer entries against each other, and
* tell if it's the same dive. Return 0 if "don't know",
@ -548,14 +543,27 @@ void free_dc(struct divecomputer *dc)
free(dc);
}
static const char *manual_dc_name = "manually added dive";
bool is_manually_added_dc(const struct divecomputer *dc)
static const char *planner_dc_name = "planned dive";
bool is_dc_planner(const struct divecomputer *dc)
{
return dc && dc->samples <= 50 &&
same_string(dc->model, manual_dc_name);
return dc && same_string(dc->model, planner_dc_name);
}
void make_manually_added_dc(struct divecomputer *dc)
void make_planner_dc(struct divecomputer *dc)
{
free((void *)dc->model);
dc->model = strdup(planner_dc_name);
}
const char *manual_dc_name = "manually added dive";
bool is_dc_manually_added_dive(const struct divecomputer *dc)
{
return dc && same_string(dc->model, manual_dc_name);
}
void make_manually_added_dive_dc(struct divecomputer *dc)
{
free((void *)dc->model);
dc->model = strdup(manual_dc_name);

View File

@ -67,10 +67,12 @@ extern void add_event_to_dc(struct divecomputer *dc, struct event *ev);
extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name);
extern void remove_event_from_dc(struct divecomputer *dc, struct event *event);
extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value);
extern bool is_dc_planner(const struct divecomputer *dc);
extern uint32_t calculate_string_hash(const char *str);
extern bool is_manually_added_dc(const struct divecomputer *dc);
extern void make_manually_added_dc(struct divecomputer *dc);
extern bool is_dc_planner(const struct divecomputer *dc);
extern void make_planner_dc(struct divecomputer *dc);
extern const char *manual_dc_name;
extern bool is_dc_manually_added_dive(const struct divecomputer *dc);
extern void make_manually_added_dive_dc(struct divecomputer *dc);
/* Check if two dive computer entries are the exact same dive (-1=no/0=maybe/1=yes) */
extern int match_one_dc(const struct divecomputer *a, const struct divecomputer *b);

View File

@ -561,7 +561,7 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
}
add_segment(ds, surface_pressure, air, surface_time, 0, OC, prefs.decosac, in_planner);
#if DECO_CALC_DEBUG & 2
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION_TUPLE(surface_time, 60));
dump_tissues(ds);
#endif
}
@ -598,7 +598,7 @@ int init_decompression(struct deco_state *ds, const struct dive *dive, bool in_p
}
add_segment(ds, surface_pressure, air, surface_time, 0, OC, prefs.decosac, in_planner);
#if DECO_CALC_DEBUG & 2
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION(surface_time, 60));
printf("Tissues after surface intervall of %d:%02u:\n", FRACTION_TUPLE(surface_time, 60));
dump_tissues(ds);
#endif
}
@ -767,18 +767,6 @@ struct dive *unregister_dive(int idx)
return dive;
}
/* this implements the mechanics of removing the dive from the global
* dive table and the trip, but doesn't deal with updating dive trips, etc */
void delete_single_dive(int idx)
{
struct dive *dive = get_dive(idx);
if (!dive)
return; /* this should never happen */
remove_dive_from_trip(dive, divelog.trips);
unregister_dive_from_dive_site(dive);
delete_dive_from_table(divelog.dives, idx);
}
void process_loaded_dives()
{
sort_dive_table(divelog.dives);
@ -989,7 +977,7 @@ void add_imported_dives(struct divelog *import_log, int flags)
/* Remove old dives */
for (i = 0; i < dives_to_remove.nr; i++) {
idx = get_divenr(dives_to_remove.dives[i]);
delete_single_dive(idx);
delete_single_dive(&divelog, idx);
}
dives_to_remove.nr = 0;
@ -1019,6 +1007,10 @@ void add_imported_dives(struct divelog *import_log, int flags)
current_dive = divelog.dives->nr > 0 ? divelog.dives->dives[divelog.dives->nr - 1] : NULL;
free_device_table(devices_to_add);
free(dives_to_add.dives);
free(dives_to_remove.dives);
free(trips_to_add.trips);
free(dive_sites_to_add.dive_sites);
/* Inform frontend of reset data. This should reset all the models. */
emit_reset_signal();

View File

@ -62,7 +62,6 @@ void clear_dive_file_data();
void clear_dive_table(struct dive_table *table);
void move_dive_table(struct dive_table *src, struct dive_table *dst);
struct dive *unregister_dive(int idx);
extern void delete_single_dive(int idx);
extern bool has_dive(unsigned int deviceid, unsigned int diveid);
#ifdef __cplusplus

View File

@ -3,6 +3,7 @@
#include "divelist.h"
#include "divesite.h"
#include "device.h"
#include "errorhelper.h"
#include "filterpreset.h"
#include "trip.h"
@ -63,14 +64,28 @@ struct divelog &divelog::operator=(divelog &&log)
return *this;
}
/* this implements the mechanics of removing the dive from the
* dive log and the trip, but doesn't deal with updating dive trips, etc */
void delete_single_dive(struct divelog *log, int idx)
{
if (idx < 0 || idx > log->dives->nr) {
report_info("Warning: deleting unexisting dive with index %d", idx);
return;
}
struct dive *dive = log->dives->dives[idx];
remove_dive_from_trip(dive, log->trips);
unregister_dive_from_dive_site(dive);
delete_dive_from_table(log->dives, idx);
}
void divelog::clear()
{
while (dives->nr)
delete_single_dive(0);
while (dives->nr > 0)
delete_single_dive(this, dives->nr - 1);
while (sites->nr)
delete_dive_site(get_dive_site(0, sites), sites);
if (trips->nr != 0) {
fprintf(stderr, "Warning: trip table not empty in divelog::clear()!\n");
report_info("Warning: trip table not empty in divelog::clear()!");
trips->nr = 0;
}
clear_device_table(devices);

View File

@ -34,6 +34,7 @@ extern "C" {
#endif
void clear_divelog(struct divelog *);
extern void delete_single_dive(struct divelog *, int idx);
#ifdef __cplusplus
}

View File

@ -149,7 +149,7 @@ void exportHtmlInitLogic(const QString &filename, struct htmlExportSetting &hes)
QString searchPath = getSubsurfaceDataPath("theme");
if (searchPath.isEmpty()) {
report_error(qPrintable(gettextFromC::tr("Cannot find a folder called 'theme' in the standard locations")));
report_error("%s", qPrintable(gettextFromC::tr("Cannot find a folder called 'theme' in the standard locations")));
return;
}

View File

@ -4,6 +4,7 @@
#include "dive.h"
#include "divelist.h"
#include "divelog.h"
#include "errorhelper.h"
#include "membuffer.h"
#include "subsurface-string.h"
#include "table.h"
@ -62,7 +63,7 @@ struct dive_site *get_dive_site_by_gps(const location_t *loc, struct dive_site_t
/* to avoid a bug where we have two dive sites with different name and the same GPS coordinates
* and first get the gps coordinates (reading a V2 file) and happen to get back "the other" name,
* this function allows us to verify if a very specific name/GPS combination already exists */
struct dive_site *get_dive_site_by_gps_and_name(char *name, const location_t *loc, struct dive_site_table *ds_table)
struct dive_site *get_dive_site_by_gps_and_name(const char *name, const location_t *loc, struct dive_site_table *ds_table)
{
int i;
struct dive_site *ds;
@ -371,17 +372,17 @@ void add_dive_to_dive_site(struct dive *d, struct dive_site *ds)
{
int idx;
if (!d) {
fprintf(stderr, "Warning: add_dive_to_dive_site called with NULL dive\n");
report_info("Warning: add_dive_to_dive_site called with NULL dive");
return;
}
if (!ds) {
fprintf(stderr, "Warning: add_dive_to_dive_site called with NULL dive site\n");
report_info("Warning: add_dive_to_dive_site called with NULL dive site");
return;
}
if (d->dive_site == ds)
return;
if (d->dive_site) {
fprintf(stderr, "Warning: adding dive that already belongs to a dive site to a different site\n");
report_info("Warning: adding dive that already belongs to a dive site to a different site");
unregister_dive_from_dive_site(d);
}
idx = dive_table_get_insertion_index(&ds->dives, d);

View File

@ -62,7 +62,7 @@ struct dive_site *create_dive_site(const char *name, struct dive_site_table *ds_
struct dive_site *create_dive_site_with_gps(const char *name, const location_t *, struct dive_site_table *ds_table);
struct dive_site *get_dive_site_by_name(const char *name, struct dive_site_table *ds_table);
struct dive_site *get_dive_site_by_gps(const location_t *, struct dive_site_table *ds_table);
struct dive_site *get_dive_site_by_gps_and_name(char *name, const location_t *, struct dive_site_table *ds_table);
struct dive_site *get_dive_site_by_gps_and_name(const char *name, const location_t *, struct dive_site_table *ds_table);
struct dive_site *get_dive_site_by_gps_proximity(const location_t *, int distance, struct dive_site_table *ds_table);
struct dive_site *get_same_dive_site(const struct dive_site *);
bool dive_site_is_empty(struct dive_site *ds);

View File

@ -9,7 +9,6 @@
#include "errorhelper.h"
#include "subsurface-string.h"
#include "qthelper.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
@ -124,7 +123,6 @@ taxonomy_data reverseGeoLookup(degrees_t latitude, degrees_t longitude)
}
} else {
report_error("geonames.org did not provide reverse lookup information");
//qDebug() << "no reverse geo lookup; geonames returned\n" << fullReply;
}
return taxonomy;

View File

@ -1,10 +1,10 @@
#include "downloadfromdcthread.h"
#include "core/errorhelper.h"
#include "core/libdivecomputer.h"
#include "core/qthelper.h"
#include "core/range.h"
#include "core/settings/qPrefDiveComputer.h"
#include "core/divelist.h"
#include <QDebug>
#if defined(Q_OS_ANDROID)
#include "core/subsurface-string.h"
#endif
@ -91,7 +91,7 @@ void DownloadThread::run()
internalData->log = &log;
internalData->btname = strdup(m_data->devBluetoothName().toUtf8());
if (!internalData->descriptor) {
qDebug() << "No download possible when DC type is unknown";
report_info("No download possible when DC type is unknown");
return;
}
// get the list of transports that this device supports and filter depending on Bluetooth option
@ -103,8 +103,8 @@ void DownloadThread::run()
if (transports == DC_TRANSPORT_USBHID)
internalData->devname = "";
qDebug() << "Starting download from " << getTransportString(transports);
qDebug() << "downloading" << (internalData->force_download ? "all" : "only new") << "dives";
report_info("Starting download from %s", qPrintable(getTransportString(transports)));
report_info("downloading %s dives", internalData->force_download ? "all" : "only new");
clear_divelog(&log);
Q_ASSERT(internalData->log != nullptr);
@ -117,11 +117,11 @@ void DownloadThread::run()
errorText = do_libdivecomputer_import(internalData);
if (errorText) {
error = str_error(errorText, internalData->devname, internalData->vendor, internalData->product);
qDebug() << "Finishing download thread:" << error;
report_info("Finishing download thread: %s", qPrintable(error));
} else {
if (!log.dives->nr)
error = tr("No new dives downloaded from dive computer");
qDebug() << "Finishing download thread:" << log.dives->nr << "dives downloaded";
report_info("Finishing download thread: %d dives downloaded", log.dives->nr);
}
qPrefDiveComputer::set_vendor(internalData->vendor);
qPrefDiveComputer::set_product(internalData->product);
@ -156,7 +156,7 @@ void fill_computer_list()
descriptorLookup[QString(vendor).toLower() + QString(product).toLower()] = descriptor;
}
dc_iterator_free(iterator);
Q_FOREACH (QString vendor, vendorList) {
for (const QString &vendor: vendorList) {
auto &l = productList[vendor];
std::sort(l.begin(), l.end());
}
@ -193,17 +193,17 @@ void fill_computer_list()
void show_computer_list()
{
unsigned int transportMask = get_supported_transports(NULL);
qDebug() << "Supported dive computers:";
Q_FOREACH (QString vendor, vendorList) {
report_info("Supported dive computers:");
for (const QString &vendor: vendorList) {
QString msg = vendor + ": ";
Q_FOREACH (QString product, productList[vendor]) {
for (const QString &product: productList[vendor]) {
dc_descriptor_t *descriptor = descriptorLookup[vendor.toLower() + product.toLower()];
unsigned int transport = dc_descriptor_get_transports(descriptor) & transportMask;
QString transportString = getTransportString(transport);
msg += product + " (" + transportString + "), ";
}
msg.chop(2);
qDebug() << msg;
report_info("%s", qPrintable(msg));
}
}
@ -274,7 +274,7 @@ QString DCDeviceData::devBluetoothName() const
QString DCDeviceData::descriptor() const
{
return "";
return QString();
}
bool DCDeviceData::bluetoothMode() const

View File

@ -95,9 +95,7 @@ struct mydescriptor {
* stay like this for now.
*/
void fill_computer_list();
extern "C" {
void show_computer_list();
}
extern QStringList vendorList;
extern QHash<QString, QStringList> productList;
extern QMap<QString, dc_descriptor_t *> descriptorLookup;

View File

@ -16,6 +16,7 @@
#include "dive.h"
#include "divelist.h"
#include "divelog.h"
#include "errorhelper.h"
#include "pref.h"
#include "subsurface-string.h"
#include "table.h"
@ -86,13 +87,13 @@ const char *cylinderuse_text[NUM_GAS_USE] = {
QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used")
};
int cylinderuse_from_text(const char *text)
enum cylinderuse cylinderuse_from_text(const char *text)
{
for (enum cylinderuse i = 0; i < NUM_GAS_USE; i++) {
if (same_string(text, cylinderuse_text[i]) || same_string(text, translate("gettextFromC", cylinderuse_text[i])))
return i;
}
return -1;
return (enum cylinderuse)-1;
}
/* Add a metric or an imperial tank info structure. Copies the passed-in string. */
@ -108,6 +109,52 @@ void add_tank_info_imperial(struct tank_info_table *table, const char *name, int
add_to_tank_info_table(table, table->nr, info);
}
static struct tank_info *get_tank_info(struct tank_info_table *table, const char *name)
{
for (int i = 0; i < table->nr; ++i) {
if (same_string(table->infos[i].name, name))
return &table->infos[i];
}
return NULL;
}
extern void set_tank_info_data(struct tank_info_table *table, const char *name, volume_t size, pressure_t working_pressure)
{
struct tank_info *info = get_tank_info(table, name);
if (info) {
if (info->ml != 0 || info->bar != 0) {
info->bar = working_pressure.mbar / 1000;
info->ml = size.mliter;
} else {
info->psi = lrint(to_PSI(working_pressure));
info->cuft = lrint(ml_to_cuft(size.mliter) * mbar_to_atm(working_pressure.mbar));
}
} else {
// Metric is a better choice as the volume is independent of the working pressure
add_tank_info_metric(table, name, size.mliter, working_pressure.mbar / 1000);
}
}
extern void extract_tank_info(const struct tank_info *info, volume_t *size, pressure_t *working_pressure)
{
working_pressure->mbar = info->bar != 0 ? info->bar * 1000 : psi_to_mbar(info->psi);
if (info->ml != 0)
size->mliter = info->ml;
else if (working_pressure->mbar != 0)
size->mliter = lrint(cuft_to_l(info->cuft) * 1000 / mbar_to_atm(working_pressure->mbar));
}
extern bool get_tank_info_data(struct tank_info_table *table, const char *name, volume_t *size, pressure_t *working_pressure)
{
struct tank_info *info = get_tank_info(table, name);
if (info) {
extract_tank_info(info, size, working_pressure);
return true;
}
return false;
}
/* placeholders for a few functions that we need to redesign for the Qt UI */
void add_cylinder_description(const cylinder_type_t *type)
{
@ -131,7 +178,7 @@ void add_weightsystem_description(const weightsystem_t *weightsystem)
if (!desc)
return;
for (i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
if (strcmp(ws_info[i].name, desc) == 0) {
if (same_string(ws_info[i].name, desc)) {
ws_info[i].grams = weightsystem->weight.grams;
return;
}
@ -143,6 +190,17 @@ void add_weightsystem_description(const weightsystem_t *weightsystem)
}
}
struct ws_info_t *get_weightsystem_description(const char *name)
{
for (int i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
// Also finds translated names (TODO: should only consider non-user items).
if (same_string(ws_info[i].name, name) ||
same_string(translate("gettextFromC", ws_info[i].name), name))
return &ws_info[i];
}
return NULL;
}
weightsystem_t clone_weightsystem(weightsystem_t ws)
{
weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled };
@ -156,13 +214,6 @@ void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws)
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
/* Add a clone of a weightsystem to the end of a weightsystem table.
* Cloned means that the description-string is copied. */
void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws)
{
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
cylinder_t clone_cylinder(cylinder_t cyl)
{
cylinder_t res = cyl;
@ -410,7 +461,7 @@ cylinder_t *get_cylinder(const struct dive *d, int idx)
* in the table to mark no-cylinder surface interavals. This is horrendous. Fix ASAP. */
// if (idx < 0 || idx >= d->cylinders.nr) {
if (idx < 0 || idx >= d->cylinders.nr + 1 || idx >= d->cylinders.allocated) {
fprintf(stderr, "Warning: accessing invalid cylinder %d (%d existing)\n", idx, d->cylinders.nr);
report_info("Warning: accessing invalid cylinder %d (%d existing)", idx, d->cylinders.nr);
return NULL;
}
return &d->cylinders.cylinders[idx];
@ -419,7 +470,7 @@ cylinder_t *get_cylinder(const struct dive *d, int idx)
cylinder_t *get_or_create_cylinder(struct dive *d, int idx)
{
if (idx < 0) {
fprintf(stderr, "Warning: accessing invalid cylinder %d\n", idx);
report_info("Warning: accessing invalid cylinder %d", idx);
return NULL;
}
while (idx >= d->cylinders.nr)
@ -459,12 +510,38 @@ cylinder_t create_new_cylinder(const struct dive *d)
cylinder_t cyl = empty_cylinder;
fill_default_cylinder(d, &cyl);
cyl.start = cyl.type.workingpressure;
cyl.manually_added = true;
cyl.cylinder_use = OC_GAS;
return cyl;
}
static bool show_cylinder(const struct dive *d, int i)
cylinder_t create_new_manual_cylinder(const struct dive *d)
{
cylinder_t cyl = create_new_cylinder(d);
cyl.manually_added = true;
return cyl;
}
void add_default_cylinder(struct dive *d)
{
// Only add if there are no cylinders yet
if (d->cylinders.nr > 0)
return;
cylinder_t cyl;
if (!empty_string(prefs.default_cylinder)) {
cyl = create_new_cylinder(d);
} else {
cyl = empty_cylinder;
// roughly an AL80
cyl.type.description = strdup(translate("gettextFromC", "unknown"));
cyl.type.size.mliter = 11100;
cyl.type.workingpressure.mbar = 207000;
}
add_cylinder(&d->cylinders, 0, cyl);
reset_cylinders(d, false);
}
static bool show_cylinder(const struct dive *d, int i)
{
if (is_cylinder_used(d, i))
return true;

View File

@ -70,7 +70,7 @@ struct weightsystem_table {
#define MAX_WS_INFO (100)
extern int cylinderuse_from_text(const char *text);
extern enum cylinderuse cylinderuse_from_text(const char *text);
extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d);
extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d);
extern weightsystem_t clone_weightsystem(weightsystem_t ws);
@ -93,7 +93,8 @@ extern void reset_cylinders(struct dive *dive, bool track_gas);
extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */
extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders);
extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); /* dive is needed to fill out MOD, which depends on salinity. */
extern cylinder_t create_new_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */
extern cylinder_t create_new_manual_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */
extern void add_default_cylinder(struct dive *dive);
extern int first_hidden_cylinder(const struct dive *d);
#ifdef DEBUG_CYL
extern void dump_cylinders(struct dive *dive, bool verbose);
@ -125,12 +126,16 @@ extern void reset_tank_info_table(struct tank_info_table *table);
extern void clear_tank_info_table(struct tank_info_table *table);
extern void add_tank_info_metric(struct tank_info_table *table, const char *name, int ml, int bar);
extern void add_tank_info_imperial(struct tank_info_table *table, const char *name, int cuft, int psi);
extern void extract_tank_info(const struct tank_info *info, volume_t *size, pressure_t *working_pressure);
extern bool get_tank_info_data(struct tank_info_table *table, const char *name, volume_t *size, pressure_t *pressure);
extern void set_tank_info_data(struct tank_info_table *table, const char *name, volume_t size, pressure_t working_pressure);
struct ws_info_t {
const char *name;
int grams;
};
extern struct ws_info_t ws_info[MAX_WS_INFO];
extern struct ws_info_t *get_weightsystem_description(const char *name);
#ifdef __cplusplus
}

View File

@ -6,7 +6,6 @@
#include <stdarg.h>
#include "errorhelper.h"
#include "membuffer.h"
#include "qthelper.h"
#if !defined(Q_OS_ANDROID) && !defined(__ANDROID__)
#define LOG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
@ -21,7 +20,7 @@ int verbose;
void report_info(const char *fmt, ...)
{
struct membuffer buf = { 0 };
struct membufferpp buf;
VA_BUF(&buf, fmt);
strip_mb(&buf);
@ -32,7 +31,7 @@ static void (*error_cb)(char *) = NULL;
int report_error(const char *fmt, ...)
{
struct membuffer buf = { 0 };
struct membufferpp buf;
VA_BUF(&buf, fmt);
strip_mb(&buf);

View File

@ -8,10 +8,18 @@
extern "C" {
#endif
#ifdef __GNUC__
#define __printf(x, y) __attribute__((__format__(__printf__, x, y)))
#else
#define __printf(x, y)
#endif
extern int verbose;
extern int report_error(const char *fmt, ...);
extern int __printf(1, 2) report_error(const char *fmt, ...);
extern void __printf(1, 2) report_info(const char *fmt, ...);
extern void set_error_cb(void(*cb)(char *)); // Callback takes ownership of passed string
#ifdef __cplusplus
}
#endif

View File

@ -13,6 +13,7 @@
#include "dive.h"
#include "divelog.h"
#include "subsurface-string.h"
#include "format.h"
#include "errorhelper.h"
#include "file.h"
#include "git-access.h"
@ -31,68 +32,53 @@
#define O_BINARY 0
#endif
int readfile(const char *filename, struct memblock *mem)
std::pair<std::string, int> readfile(const char *filename)
{
int ret, fd;
struct stat st;
char *buf;
mem->buffer = NULL;
mem->size = 0;
std::string res;
fd = subsurface_open(filename, O_RDONLY | O_BINARY, 0);
if (fd < 0)
return fd;
return std::make_pair(res, fd);
ret = fstat(fd, &st);
if (ret < 0)
goto out;
ret = -EINVAL;
return std::make_pair(res, ret);
if (!S_ISREG(st.st_mode))
goto out;
ret = 0;
return std::make_pair(res, -EINVAL);
if (!st.st_size)
goto out;
buf = malloc(st.st_size + 1);
ret = -1;
errno = ENOMEM;
if (!buf)
goto out;
mem->buffer = buf;
mem->size = st.st_size;
ret = read(fd, buf, mem->size);
return std::make_pair(res, 0);
// Sadly, this 0-initializes the string, just before overwriting it.
// However, we use std::string, because that automatically 0-terminates
// the data and the code expects that.
res.resize(st.st_size);
ret = read(fd, res.data(), res.size());
if (ret < 0)
goto free;
buf[ret] = 0;
if (ret == (int)mem->size) // converting to int loses a bit but size will never be that big
goto out;
errno = EIO;
ret = -1;
free:
free(mem->buffer);
mem->buffer = NULL;
mem->size = 0;
out:
close(fd);
return ret;
return std::make_pair(res, ret);
// converting to int loses a bit but size will never be that big
if (ret == (int)res.size()) {
return std::make_pair(res, ret);
} else {
errno = EIO;
return std::make_pair(res, -1);
}
}
static void zip_read(struct zip_file *file, const char *filename, struct divelog *log)
{
int size = 1024, n, read = 0;
char *mem = malloc(size);
std::vector<char> mem(size + 1);
while ((n = zip_fread(file, mem + read, size - read)) > 0) {
while ((n = zip_fread(file, mem.data() + read, size - read)) > 0) {
read += n;
size = read * 3 / 2;
mem = realloc(mem, size);
mem.resize(size + 1);
}
mem[read] = 0;
(void) parse_xml_buffer(filename, mem, read, log, NULL);
free(mem);
(void) parse_xml_buffer(filename, mem.data(), read, log, NULL);
}
int try_to_open_zip(const char *filename, struct divelog *log)
extern "C" int try_to_open_zip(const char *filename, struct divelog *log)
{
int success = 0;
/* Grr. libzip needs to re-open the file, it can't take a buffer */
@ -119,15 +105,12 @@ int try_to_open_zip(const char *filename, struct divelog *log)
return success;
}
static int db_test_func(void *param, int columns, char **data, char **column)
static int db_test_func(void *, int, char **data, char **)
{
UNUSED(param);
UNUSED(columns);
UNUSED(column);
return *data[0] == '0';
}
static int try_to_open_db(const char *filename, struct memblock *mem, struct divelog *log)
static int try_to_open_db(const char *filename, std::string &mem, struct divelog *log)
{
sqlite3 *handle;
char dm4_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%ProfileBlob%'";
@ -142,14 +125,14 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
retval = sqlite3_open(filename, &handle);
if (retval) {
fprintf(stderr, "Database connection failed '%s'.\n", filename);
report_info("Database connection failed '%s'", filename);
return 1;
}
/* Testing if DB schema resembles Suunto DM5 database format */
retval = sqlite3_exec(handle, dm5_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_dm5_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_dm5_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -157,7 +140,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Suunto DM4 database format */
retval = sqlite3_exec(handle, dm4_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_dm4_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_dm4_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -165,7 +148,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Shearwater database format */
retval = sqlite3_exec(handle, shearwater_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_shearwater_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_shearwater_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -173,7 +156,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Shearwater cloud database format */
retval = sqlite3_exec(handle, shearwater_cloud_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_shearwater_cloud_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_shearwater_cloud_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -181,7 +164,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Atomic Cobalt database format */
retval = sqlite3_exec(handle, cobalt_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_cobalt_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_cobalt_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -189,7 +172,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Divinglog database format */
retval = sqlite3_exec(handle, divinglog_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_divinglog_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_divinglog_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -197,7 +180,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Seac database format */
retval = sqlite3_exec(handle, seacsync_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_seac_buffer(handle, filename, mem->buffer, mem->size, log);
retval = parse_seac_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -224,12 +207,13 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
*
* Followed by the data values (all comma-separated, all one long line).
*/
static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, struct divelog *log)
static int open_by_filename(const char *filename, const char *fmt, std::string &mem, struct divelog *log)
{
// hack to be able to provide a comment for the translated string
static char *csv_warning = QT_TRANSLATE_NOOP3("gettextFromC",
"Cannot open CSV file %s; please use Import log file dialog",
"'Import log file' should be the same text as corresponding label in Import menu");
static struct { const char *s; const char *comment; } csv_warning =
QT_TRANSLATE_NOOP3("gettextFromC",
"Cannot open CSV file %s; please use Import log file dialog",
"'Import log file' should be the same text as corresponding label in Import menu");
/* Suunto Dive Manager files: SDE, ZIP; divelogs.de files: DLD */
if (!strcasecmp(fmt, "SDE") || !strcasecmp(fmt, "ZIP") || !strcasecmp(fmt, "DLD"))
@ -237,7 +221,7 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo
/* CSV files */
if (!strcasecmp(fmt, "CSV"))
return report_error(translate("gettextFromC", csv_warning), filename);
return report_error(translate("gettextFromC", csv_warning.s), filename);
/* Truly nasty intentionally obfuscated Cochran Anal software */
if (!strcasecmp(fmt, "CAN"))
return try_to_open_cochran(filename, mem, log);
@ -254,44 +238,40 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo
return 0;
}
static int parse_file_buffer(const char *filename, struct memblock *mem, struct divelog *log)
static int parse_file_buffer(const char *filename, std::string &mem, struct divelog *log)
{
int ret;
char *fmt = strrchr(filename, '.');
const char *fmt = strrchr(filename, '.');
if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, log)) != 0)
return ret;
if (!mem->size || !mem->buffer)
if (mem.empty())
return report_error("Out of memory parsing file %s\n", filename);
return parse_xml_buffer(filename, mem->buffer, mem->size, log, NULL);
return parse_xml_buffer(filename, mem.data(), mem.size(), log, NULL);
}
bool remote_repo_uptodate(const char *filename, struct git_info *info)
{
char *current_sha = copy_string(saved_git_id);
std::string current_sha = saved_git_id;
if (is_git_repository(filename, info) && open_git_repository(info)) {
const char *sha = get_sha(info->repo, info->branch);
if (!empty_string(sha) && same_string(sha, current_sha)) {
fprintf(stderr, "already have loaded SHA %s - don't load again\n", sha);
free(current_sha);
std::string sha = get_sha(info->repo, info->branch);
if (!sha.empty() && current_sha == sha) {
report_info("already have loaded SHA %s - don't load again", sha.c_str());
return true;
}
}
// Either the repository couldn't be opened, or the SHA couldn't
// be found.
free(current_sha);
return false;
}
int parse_file(const char *filename, struct divelog *log)
extern "C" int parse_file(const char *filename, struct divelog *log)
{
struct git_info info;
struct memblock mem;
char *fmt;
int ret;
const char *fmt;
if (is_git_repository(filename, &info)) {
if (!open_git_repository(&info)) {
@ -299,69 +279,52 @@ int parse_file(const char *filename, struct divelog *log)
* Opening the cloud storage repository failed for some reason
* give up here and don't send errors about git repositories
*/
if (info.is_subsurface_cloud) {
cleanup_git_info(&info);
if (info.is_subsurface_cloud)
return -1;
}
}
ret = git_load_dives(&info, log);
cleanup_git_info(&info);
int ret = git_load_dives(&info, log);
return ret;
}
if ((ret = readfile(filename, &mem)) < 0) {
auto [mem, err] = readfile(filename);
if (err < 0) {
/* we don't want to display an error if this was the default file */
if (same_string(filename, prefs.default_filename))
return 0;
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
} else if (ret == 0) {
} else if (err == 0) {
return report_error(translate("gettextFromC", "Empty file '%s'"), filename);
}
fmt = strrchr(filename, '.');
if (fmt && (!strcasecmp(fmt + 1, "DB") || !strcasecmp(fmt + 1, "BAK") || !strcasecmp(fmt + 1, "SQL"))) {
if (!try_to_open_db(filename, &mem, log)) {
free(mem.buffer);
if (!try_to_open_db(filename, mem, log))
return 0;
}
}
/* Divesoft Freedom */
if (fmt && (!strcasecmp(fmt + 1, "DLF"))) {
ret = parse_dlf_buffer(mem.buffer, mem.size, log);
free(mem.buffer);
return ret;
}
if (fmt && (!strcasecmp(fmt + 1, "DLF")))
return parse_dlf_buffer((unsigned char *)mem.data(), mem.size(), log);
/* DataTrak/Wlog */
if (fmt && !strcasecmp(fmt + 1, "LOG")) {
struct memblock wl_mem;
const char *t = strrchr(filename, '.');
char *wl_name = memcpy(calloc(t - filename + 1, 1), filename, t - filename);
wl_name = realloc(wl_name, strlen(wl_name) + 5);
wl_name = strcat(wl_name, ".add");
if((ret = readfile(wl_name, &wl_mem)) < 0) {
fprintf(stderr, "No file %s found. No WLog extensions.\n", wl_name);
ret = datatrak_import(&mem, NULL, log);
} else {
ret = datatrak_import(&mem, &wl_mem, log);
free(wl_mem.buffer);
std::string wl_name = std::string(filename, t - filename) + ".add";
auto [wl_mem, err] = readfile(wl_name.c_str());
if (err < 0) {
report_info("No file %s found. No WLog extensions.", wl_name.c_str());
wl_mem.clear();
}
free(mem.buffer);
free(wl_name);
return ret;
return datatrak_import(mem, wl_mem, log);
}
/* OSTCtools */
if (fmt && (!strcasecmp(fmt + 1, "DIVE"))) {
free(mem.buffer);
ostctools_import(filename, log);
return 0;
}
ret = parse_file_buffer(filename, &mem, log);
free(mem.buffer);
return ret;
return parse_file_buffer(filename, mem, log);
}

View File

@ -7,23 +7,14 @@
#include <sys/stat.h>
#include <stdio.h>
struct memblock {
void *buffer;
size_t size;
};
struct divelog;
struct zip;
#ifdef __cplusplus
extern "C" {
#endif
extern int try_to_open_cochran(const char *filename, struct memblock *mem, struct divelog *log);
extern int try_to_open_liquivision(const char *filename, struct memblock *mem, struct divelog *log);
extern int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelog *log);
extern void ostctools_import(const char *file, struct divelog *log);
extern int readfile(const char *filename, struct memblock *mem);
extern int parse_file(const char *filename, struct divelog *log);
extern int try_to_open_zip(const char *filename, struct divelog *log);
@ -39,7 +30,20 @@ extern struct zip *subsurface_zip_open_readonly(const char *path, int flags, int
extern int subsurface_zip_close(struct zip *zip);
#ifdef __cplusplus
}
// C++ only functions
#include <vector>
#include <utility>
// return data, errorcode pair.
extern std::pair<std::string, int> readfile(const char *filename);
extern int try_to_open_cochran(const char *filename, std::string &mem, struct divelog *log);
extern int try_to_open_liquivision(const char *filename, std::string &mem, struct divelog *log);
extern int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log);
#endif
#endif // FILE_H

View File

@ -622,33 +622,29 @@ filter_constraint::~filter_constraint()
delete data.string_list;
}
extern "C" char *filter_constraint_data_to_string(const filter_constraint *c)
std::string filter_constraint_data_to_string(const filter_constraint *c)
{
QString s;
if (filter_constraint_is_timestamp(c->type)) {
char *from_s = format_datetime(c->data.timestamp_range.from);
char *to_s = format_datetime(c->data.timestamp_range.to);
s = QString(from_s) + ',' + QString(to_s);
free(from_s);
free(to_s);
std::string from_s = format_datetime(c->data.timestamp_range.from);
std::string to_s = format_datetime(c->data.timestamp_range.to);
return from_s + ',' + to_s;
} else if (filter_constraint_is_string(c->type)) {
// TODO: this obviously breaks if the strings contain ",".
// That is currently not supported by the UI, but one day we might
// have to escape the strings.
s = c->data.string_list->join(",");
return c->data.string_list->join(",").toStdString();
} else if (filter_constraint_is_multiple_choice(c->type)) {
s = QString::number(c->data.multiple_choice);
return std::to_string(c->data.multiple_choice);
} else {
s = QString::number(c->data.numerical_range.from) + ',' +
QString::number(c->data.numerical_range.to);
return std::to_string(c->data.numerical_range.from) + ',' +
std::to_string(c->data.numerical_range.to);
}
return copy_qstring(s);
}
void filter_constraint_set_stringlist(filter_constraint &c, const QString &s)
{
if (!filter_constraint_is_string(c.type)) {
fprintf(stderr, "Setting strings in non-string constraint!\n");
report_info("Setting strings in non-string constraint!");
return;
}
c.data.string_list->clear();
@ -659,7 +655,7 @@ void filter_constraint_set_stringlist(filter_constraint &c, const QString &s)
void filter_constraint_set_timestamp_from(filter_constraint &c, timestamp_t from)
{
if (!filter_constraint_is_timestamp(c.type)) {
fprintf(stderr, "Setting timestamp from in non-timestamp constraint!\n");
report_info("Setting timestamp from in non-timestamp constraint!");
return;
}
c.data.timestamp_range.from = from;
@ -668,7 +664,7 @@ void filter_constraint_set_timestamp_from(filter_constraint &c, timestamp_t from
void filter_constraint_set_timestamp_to(filter_constraint &c, timestamp_t to)
{
if (!filter_constraint_is_timestamp(c.type)) {
fprintf(stderr, "Setting timestamp to in non-timestamp constraint!\n");
report_info("Setting timestamp to in non-timestamp constraint!");
return;
}
c.data.timestamp_range.to = to;
@ -677,7 +673,7 @@ void filter_constraint_set_timestamp_to(filter_constraint &c, timestamp_t to)
void filter_constraint_set_integer_from(filter_constraint &c, int from)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Setting integer from of non-numerical constraint!\n");
report_info("Setting integer from of non-numerical constraint!");
return;
}
c.data.numerical_range.from = from;
@ -686,7 +682,7 @@ void filter_constraint_set_integer_from(filter_constraint &c, int from)
void filter_constraint_set_integer_to(filter_constraint &c, int to)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Setting integer to of non-numerical constraint!\n");
report_info("Setting integer to of non-numerical constraint!");
return;
}
c.data.numerical_range.to = to;
@ -695,7 +691,7 @@ void filter_constraint_set_integer_to(filter_constraint &c, int to)
void filter_constraint_set_float_from(filter_constraint &c, double from)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Setting float from of non-numerical constraint!\n");
report_info("Setting float from of non-numerical constraint!");
return;
}
c.data.numerical_range.from = display_to_base_unit(from, c.type);
@ -704,7 +700,7 @@ void filter_constraint_set_float_from(filter_constraint &c, double from)
void filter_constraint_set_float_to(filter_constraint &c, double to)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Setting float to of non-numerical constraint!\n");
report_info("Setting float to of non-numerical constraint!");
return;
}
c.data.numerical_range.to = display_to_base_unit(to, c.type);
@ -713,7 +709,7 @@ void filter_constraint_set_float_to(filter_constraint &c, double to)
void filter_constraint_set_multiple_choice(filter_constraint &c, uint64_t multiple_choice)
{
if (!filter_constraint_is_multiple_choice(c.type)) {
fprintf(stderr, "Setting multiple-choice to of non-multiple-choice constraint!\n");
report_info("Setting multiple-choice to of non-multiple-choice constraint!");
return;
}
c.data.multiple_choice = multiple_choice;
@ -722,7 +718,7 @@ void filter_constraint_set_multiple_choice(filter_constraint &c, uint64_t multip
QString filter_constraint_get_string(const filter_constraint &c)
{
if (!filter_constraint_is_string(c.type)) {
fprintf(stderr, "Getting string of non-string constraint!\n");
report_info("Getting string of non-string constraint!");
return QString();
}
return c.data.string_list->join(",");
@ -731,7 +727,7 @@ QString filter_constraint_get_string(const filter_constraint &c)
int filter_constraint_get_integer_from(const filter_constraint &c)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Getting integer from of non-numerical constraint!\n");
report_info("Getting integer from of non-numerical constraint!");
return -1;
}
return c.data.numerical_range.from;
@ -740,7 +736,7 @@ int filter_constraint_get_integer_from(const filter_constraint &c)
int filter_constraint_get_integer_to(const filter_constraint &c)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Getting integer to of non-numerical constraint!\n");
report_info("Getting integer to of non-numerical constraint!");
return -1;
}
return c.data.numerical_range.to;
@ -749,7 +745,7 @@ int filter_constraint_get_integer_to(const filter_constraint &c)
double filter_constraint_get_float_from(const filter_constraint &c)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Getting float from of non-numerical constraint!\n");
report_info("Getting float from of non-numerical constraint!");
return 0.0;
}
return base_to_display_unit(c.data.numerical_range.from, c.type);
@ -758,7 +754,7 @@ double filter_constraint_get_float_from(const filter_constraint &c)
double filter_constraint_get_float_to(const filter_constraint &c)
{
if (!is_numerical_constraint(c.type)) {
fprintf(stderr, "Getting float to of non-numerical constraint!\n");
report_info("Getting float to of non-numerical constraint!");
return 0.0;
}
return base_to_display_unit(c.data.numerical_range.to, c.type);
@ -767,7 +763,7 @@ double filter_constraint_get_float_to(const filter_constraint &c)
timestamp_t filter_constraint_get_timestamp_from(const filter_constraint &c)
{
if (!filter_constraint_is_timestamp(c.type)) {
fprintf(stderr, "Getting timestamp from of non-timestamp constraint!\n");
report_info("Getting timestamp from of non-timestamp constraint!");
return 0;
}
return c.data.timestamp_range.from;
@ -776,7 +772,7 @@ timestamp_t filter_constraint_get_timestamp_from(const filter_constraint &c)
timestamp_t filter_constraint_get_timestamp_to(const filter_constraint &c)
{
if (!filter_constraint_is_timestamp(c.type)) {
fprintf(stderr, "Getting timestamp to of non-timestamp constraint!\n");
report_info("Getting timestamp to of non-timestamp constraint!");
return 0;
}
return c.data.timestamp_range.to;
@ -785,7 +781,7 @@ timestamp_t filter_constraint_get_timestamp_to(const filter_constraint &c)
uint64_t filter_constraint_get_multiple_choice(const filter_constraint &c)
{
if (!filter_constraint_is_multiple_choice(c.type)) {
fprintf(stderr, "Getting multiple-choice of non-multiple choice constraint!\n");
report_info("Getting multiple-choice of non-multiple choice constraint!");
return 0;
}
return c.data.multiple_choice;
@ -823,7 +819,7 @@ static bool has_tags(const filter_constraint &c, const struct dive *d)
{
QStringList dive_tags;
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
dive_tags.push_back(QString(tag->tag->name).trimmed());
dive_tags.push_back(QString::fromStdString(tag->tag->name).trimmed());
dive_tags.append(gettextFromC::tr(divemode_text_ui[d->dc.divemode]).trimmed());
return check(c, dive_tags);
}
@ -1078,9 +1074,9 @@ bool filter_constraint_match_dive(const filter_constraint &c, const struct dive
case FILTER_CONSTRAINT_SAC:
return check_numerical_range_non_zero(c, d->sac);
case FILTER_CONSTRAINT_LOGGED:
return has_planned(d, false) != c.negate;
return is_logged(d) != c.negate;
case FILTER_CONSTRAINT_PLANNED:
return has_planned(d, true) != c.negate;
return is_planned(d) != c.negate;
case FILTER_CONSTRAINT_DIVE_MODE:
return check_multiple_choice(c, (int)d->dc.divemode); // should we be smarter and check all DCs?
case FILTER_CONSTRAINT_TAGS:

View File

@ -116,7 +116,6 @@ extern bool filter_constraint_has_date_widget(enum filter_constraint_type);
extern bool filter_constraint_has_time_widget(enum filter_constraint_type);
extern int filter_constraint_num_decimals(enum filter_constraint_type);
extern bool filter_constraint_is_valid(const struct filter_constraint *constraint);
extern char *filter_constraint_data_to_string(const struct filter_constraint *constraint); // caller takes ownership of returned string
#ifdef __cplusplus
}
@ -152,6 +151,8 @@ void filter_constraint_set_timestamp_from(filter_constraint &c, timestamp_t from
void filter_constraint_set_timestamp_to(filter_constraint &c, timestamp_t to); // convert according to current units (metric or imperial)
void filter_constraint_set_multiple_choice(filter_constraint &c, uint64_t);
bool filter_constraint_match_dive(const filter_constraint &c, const struct dive *d);
std::string filter_constraint_data_to_string(const struct filter_constraint *constraint); // caller takes ownership of returned string
#endif
#endif

View File

@ -14,14 +14,9 @@ extern "C" int filter_presets_count(void)
return (int)global_table().size();
}
extern "C" char *filter_preset_name(int preset)
extern std::string filter_preset_fulltext_query(int preset)
{
return copy_qstring(filter_preset_name_qstring(preset));
}
extern "C" char *filter_preset_fulltext_query(int preset)
{
return copy_qstring(global_table()[preset].data.fullText.originalQuery);
return global_table()[preset].data.fullText.originalQuery.toStdString();
}
extern "C" const char *filter_preset_fulltext_mode(int preset)
@ -58,22 +53,12 @@ extern "C" const filter_constraint *filter_preset_constraint(int preset, int con
return &global_table()[preset].data.constraints[constraint];
}
extern "C" struct filter_preset *alloc_filter_preset()
{
return new filter_preset;
}
extern "C" void free_filter_preset(const struct filter_preset *preset)
{
delete preset;
}
extern "C" void filter_preset_set_name(struct filter_preset *preset, const char *name)
{
preset->name = name;
}
static int filter_preset_add_to_table(const QString &name, const FilterData &d, struct filter_preset_table &table)
static int filter_preset_add_to_table(const std::string name, const FilterData &d, struct filter_preset_table &table)
{
// std::lower_bound does a binary search - the vector must be sorted.
filter_preset newEntry { name, d };
@ -85,14 +70,14 @@ static int filter_preset_add_to_table(const QString &name, const FilterData &d,
}
// Take care that the name doesn't already exist by adding numbers
static QString get_unique_preset_name(const QString &orig, const struct filter_preset_table &table)
static std::string get_unique_preset_name(const std::string &orig, const struct filter_preset_table &table)
{
QString res = orig;
std::string res = orig;
int count = 2;
while (std::find_if(table.begin(), table.end(),
[&res](const filter_preset &preset)
{ return preset.name == res; }) != table.end()) {
res = orig + "#" + QString::number(count);
res = orig + "#" + std::to_string(count);
++count;
}
return res;
@ -100,7 +85,7 @@ static QString get_unique_preset_name(const QString &orig, const struct filter_p
extern "C" void add_filter_preset_to_table(const struct filter_preset *preset, struct filter_preset_table *table)
{
QString name = get_unique_preset_name(preset->name, *table);
std::string name = get_unique_preset_name(preset->name, *table);
filter_preset_add_to_table(name, preset->data, *table);
}
@ -110,14 +95,14 @@ extern "C" void filter_preset_add_constraint(struct filter_preset *preset, const
preset->data.constraints.emplace_back(type, string_mode, range_mode, negate, data);
}
int filter_preset_id(const QString &name)
int filter_preset_id(const std::string &name)
{
auto it = std::find_if(global_table().begin(), global_table().end(),
[&name] (filter_preset &p) { return p.name == name; });
return it != global_table().end() ? it - global_table().begin() : -1;
}
QString filter_preset_name_qstring(int preset)
std::string filter_preset_name(int preset)
{
return global_table()[preset].name;
}
@ -132,9 +117,9 @@ FilterData filter_preset_get(int preset)
return global_table()[preset].data;
}
int filter_preset_add(const QString &nameIn, const FilterData &d)
int filter_preset_add(const std::string &nameIn, const FilterData &d)
{
QString name = get_unique_preset_name(nameIn, global_table());
std::string name = get_unique_preset_name(nameIn, global_table());
return filter_preset_add_to_table(name, d, global_table());
}

View File

@ -18,9 +18,9 @@ struct filter_constraint;
#ifdef __cplusplus
#include "divefilter.h"
#include <vector>
#include <QStringList>
#include <string>
struct filter_preset {
QString name;
std::string name;
FilterData data;
};
@ -44,13 +44,9 @@ extern "C" {
// The C IO code accesses the filter presets via integer indices.
extern int filter_presets_count(void);
extern char *filter_preset_name(int preset); // name of filter preset - caller must free the result.
extern char *filter_preset_fulltext_query(int preset); // fulltext query of filter preset - caller must free the result.
extern const char *filter_preset_fulltext_mode(int preset); // string mode of fulltext query. ownership is *not* passed to caller.
extern int filter_preset_constraint_count(int preset); // number of constraints in the filter preset.
extern const struct filter_constraint *filter_preset_constraint(int preset, int constraint); // get constraint. ownership is *not* passed to caller.
extern struct filter_preset *alloc_filter_preset();
extern void free_filter_preset(const struct filter_preset *preset);
extern void filter_preset_set_name(struct filter_preset *preset, const char *name);
extern void filter_preset_set_fulltext(struct filter_preset *preset, const char *fulltext, const char *fulltext_string_mode);
extern void add_filter_preset_to_table(const struct filter_preset *preset, struct filter_preset_table *table);
@ -66,12 +62,13 @@ extern void filter_preset_add_constraint(struct filter_preset *preset, const cha
struct FilterData;
int filter_preset_id(const QString &s); // for now, we assume that names are unique. returns -1 if no preset with that name.
QString filter_preset_name_qstring(int preset);
int filter_preset_id(const std::string &s); // for now, we assume that names are unique. returns -1 if no preset with that name.
void filter_preset_set(int preset, const FilterData &d); // this will override a preset if the name already exists.
FilterData filter_preset_get(int preset);
int filter_preset_add(const QString &name, const FilterData &d); // returns point of insertion
int filter_preset_add(const std::string &name, const FilterData &d); // returns point of insertion
void filter_preset_delete(int preset);
std::string filter_preset_name(int preset); // name of filter preset - caller must free the result.
std::string filter_preset_fulltext_query(int preset); // fulltext query of filter preset - caller must free the result.
#endif

View File

@ -343,67 +343,30 @@ QString vqasprintf_loc(const char *fmt, va_list ap_in)
return ret;
}
// Put a formated string respecting the default locale into a C-style array in UTF-8 encoding.
// The only complication arises from the fact that we don't want to cut through multi-byte UTF-8 code points.
extern "C" int snprintf_loc(char *dst, size_t size, const char *cformat, ...)
// TODO: Avoid back-and-forth conversion between UTF16 and UTF8.
std::string casprintf_loc(const char *cformat, ...)
{
va_list ap;
va_start(ap, cformat);
int res = vsnprintf_loc(dst, size, cformat, ap);
va_end(ap);
return res;
}
extern "C" int vsnprintf_loc(char *dst, size_t size, const char *cformat, va_list ap)
{
QByteArray utf8 = vqasprintf_loc(cformat, ap).toUtf8();
const char *data = utf8.constData();
size_t utf8_size = utf8.size();
if (size == 0)
return utf8_size;
if (size < utf8_size + 1) {
memcpy(dst, data, size - 1);
if ((data[size - 1] & 0xC0) == 0x80) {
// We truncated a multi-byte UTF-8 encoding.
--size;
// Jump to last copied byte.
if (size > 0)
--size;
while(size > 0 && (dst[size] & 0xC0) == 0x80)
--size;
dst[size] = 0;
} else {
dst[size - 1] = 0;
}
} else {
memcpy(dst, data, utf8_size + 1); // QByteArray guarantees a trailing 0
}
return utf8_size;
va_end(ap);
return std::string(utf8.constData(), utf8.size());
}
int asprintf_loc(char **dst, const char *cformat, ...)
std::string __printf(1, 2) format_string_std(const char *fmt, ...)
{
va_list ap;
va_start(ap, cformat);
int res = vasprintf_loc(dst, cformat, ap);
va_start(ap, fmt);
size_t stringsize = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
if (stringsize == 0)
return std::string();
std::string res;
res.resize(stringsize); // Pointless clearing, oh my.
// This overwrites the terminal null-byte of std::string.
// That's probably "undefined behavior". Oh my.
va_start(ap, fmt);
vsnprintf(res.data(), stringsize + 1, fmt, ap);
va_end(ap);
return res;
}
int vasprintf_loc(char **dst, const char *cformat, va_list ap)
{
QByteArray utf8 = vqasprintf_loc(cformat, ap).toUtf8();
*dst = strdup(utf8.constData());
return utf8.size();
}
extern "C" void put_vformat_loc(struct membuffer *b, const char *fmt, va_list args)
{
QByteArray utf8 = vqasprintf_loc(fmt, args).toUtf8();
const char *data = utf8.constData();
size_t utf8_size = utf8.size();
make_room(b, utf8_size);
memcpy(b->buffer + b->len, data, utf8_size);
b->len += utf8_size;
}

View File

@ -11,19 +11,8 @@
#include <QString>
__printf(1, 2) QString qasprintf_loc(const char *cformat, ...);
__printf(1, 0) QString vqasprintf_loc(const char *cformat, va_list ap);
#endif
#ifdef __cplusplus
extern "C" {
#endif
__printf(3, 4) int snprintf_loc(char *dst, size_t size, const char *cformat, ...);
__printf(3, 0) int vsnprintf_loc(char *dst, size_t size, const char *cformat, va_list ap);
__printf(2, 3) int asprintf_loc(char **dst, const char *cformat, ...);
__printf(2, 0) int vasprintf_loc(char **dst, const char *cformat, va_list ap);
#ifdef __cplusplus
}
__printf(1, 2) std::string casprintf_loc(const char *cformat, ...);
__printf(1, 2) std::string format_string_std(const char *fmt, ...);
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More