Compare commits
251 Commits
mobilePass
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b126fccb1b | ||
|
|
10fc3bfd47 | ||
|
|
a8c9781205 | ||
|
|
291ed9d7e3 | ||
|
|
a39f0e2891 | ||
|
|
d9f50bb8e0 | ||
|
|
d1db85005b | ||
|
|
e2d3a12555 | ||
|
|
568aeb7bce | ||
|
|
ca5f28206b | ||
|
|
adaa52bf9b | ||
|
|
692ec9ee5c | ||
|
|
c2c5faeaad | ||
|
|
88acef7f0f | ||
|
|
32cd52869b | ||
|
|
3d96642b8d | ||
|
|
c5546fb52f | ||
|
|
f65afaf5d2 | ||
|
|
9243921cbb | ||
|
|
d27451979d | ||
|
|
e7d486982f | ||
|
|
5b941ea34e | ||
|
|
56f1e7027f | ||
|
|
64d4de4a1b | ||
|
|
e39b42df53 | ||
|
|
398cc2b639 | ||
|
|
2776a2fe48 | ||
|
|
1aa5438b2d | ||
|
|
ecc6f64d10 | ||
|
|
8c14fb971c | ||
|
|
6bdfee080d | ||
|
|
21269183bf | ||
|
|
245f8002a8 | ||
|
|
c3d807802d | ||
|
|
a66bdb1bf5 | ||
|
|
b579342639 | ||
|
|
888704e816 | ||
|
|
6880937838 | ||
|
|
d018b72dab | ||
|
|
b3d6920de4 | ||
|
|
912badadd4 | ||
|
|
1c0fe2fa1f | ||
|
|
48ef4b3a01 | ||
|
|
22082bd60a | ||
|
|
be1b80ea8a | ||
|
|
e81b42d533 | ||
|
|
dd50ab0106 | ||
|
|
0d6b572a9f | ||
|
|
21f64134b7 | ||
|
|
7bf40d659c | ||
|
|
6ae2844f24 | ||
|
|
447f9709f7 | ||
|
|
4ae6c0bbc4 | ||
|
|
6fc8310705 | ||
|
|
e20ec9248c | ||
|
|
8769b1232e | ||
|
|
d061a54e3d | ||
|
|
306dad575c | ||
|
|
331d6712c6 | ||
|
|
f4e61aa5dc | ||
|
|
528532572f | ||
|
|
a83349015a | ||
|
|
8627f6fc4a | ||
|
|
5bad522390 | ||
|
|
edb771e8e6 | ||
|
|
17d83acdab | ||
|
|
133354d51d | ||
|
|
46cf2fc086 | ||
|
|
5ac1922d84 | ||
|
|
3153a139b3 | ||
|
|
e65c7cedc8 | ||
|
|
32a08735c3 | ||
|
|
af6caa6fa2 | ||
|
|
f3c7dcf9c9 | ||
|
|
bb00a9728f | ||
|
|
a2cd621819 | ||
|
|
d92777a3ff | ||
|
|
e09a134a3f | ||
|
|
aecb4f5005 | ||
|
|
358b9186bf | ||
|
|
12ae3d4e96 | ||
|
|
34926f1325 | ||
|
|
da8509d29b | ||
|
|
9deef235e2 | ||
|
|
e7a6de3894 | ||
|
|
177a1a6706 | ||
|
|
556ecd5a9b | ||
|
|
b320942343 | ||
|
|
8867edffe8 | ||
|
|
991b72d4ff | ||
|
|
47254d91e0 | ||
|
|
9923d49624 | ||
|
|
9febfdd084 | ||
|
|
8677d1f325 | ||
|
|
6dd5ec296d | ||
|
|
4de109bbf1 | ||
|
|
d83da05f8d | ||
|
|
b6439e0420 | ||
|
|
ab7218d543 | ||
|
|
2c2ad1e5c9 | ||
|
|
4af2ec88bd | ||
|
|
c6cd10a43f | ||
|
|
8e106b0449 | ||
|
|
da7ea17b66 | ||
|
|
b097c0a44f | ||
|
|
ec0bc2d06c | ||
|
|
b89029353f | ||
|
|
14cfb17c1a | ||
|
|
157b52aa6e | ||
|
|
322c3b55e6 | ||
|
|
a123589efb | ||
|
|
ae299d5e66 | ||
|
|
422f693f5b | ||
|
|
84b7ffafd2 | ||
|
|
e65ba50c1a | ||
|
|
82ba236859 | ||
|
|
177b03958c | ||
|
|
bd3f9b107e | ||
|
|
15b17a0aca | ||
|
|
b542a39a00 | ||
|
|
9a052cd089 | ||
|
|
4db19d6284 | ||
|
|
8b51ff7ded | ||
|
|
fe68870079 | ||
|
|
f69686d429 | ||
|
|
77e8c3655e | ||
|
|
bd31efa821 | ||
|
|
80eff1d6e2 | ||
|
|
74b1648fcc | ||
|
|
7fb0e9e59e | ||
|
|
d59bd1831a | ||
|
|
f05808fded | ||
|
|
1692e48163 | ||
|
|
375b08857c | ||
|
|
d49092ac70 | ||
|
|
ee8b37cc6e | ||
|
|
77281f8bfe | ||
|
|
6b11457ddd | ||
|
|
8a20509861 | ||
|
|
334a357c19 | ||
|
|
1973d7c881 | ||
|
|
a5575f43a3 | ||
|
|
ffce4bc097 | ||
|
|
5980db073a | ||
|
|
4dcc9210a9 | ||
|
|
f4b35f67f6 | ||
|
|
0d011231e6 | ||
|
|
de313bd01a | ||
|
|
2172e18298 | ||
|
|
dd466d2d48 | ||
|
|
916c88ded9 | ||
|
|
176ee1ac9c | ||
|
|
83fa38b3b4 | ||
|
|
2bf7432a94 | ||
|
|
c53cdf039b | ||
|
|
29d71eb85e | ||
|
|
2c490fcbbb | ||
|
|
6aca76c342 | ||
|
|
92c3837f6e | ||
|
|
5ac64ab2cd | ||
|
|
41cb916060 | ||
|
|
37f2207f94 | ||
|
|
3a1122048b | ||
|
|
64419f2b19 | ||
|
|
981352646c | ||
|
|
2e067c89dd | ||
|
|
8733828380 | ||
|
|
322c1b56b2 | ||
|
|
8b0b3cba3c | ||
|
|
2533909337 | ||
|
|
1508d305b8 | ||
|
|
8a5009786e | ||
|
|
153bcdec42 | ||
|
|
e6ff3f7537 | ||
|
|
3229d1e3a1 | ||
|
|
857148efd6 | ||
|
|
8980d61786 | ||
|
|
bfbf4934dd | ||
|
|
fcf0bda042 | ||
|
|
d653cec7a4 | ||
|
|
8f50c9c1b3 | ||
|
|
c7a929a8a8 | ||
|
|
8b5812bc2c | ||
|
|
cf990b0f39 | ||
|
|
889ca23999 | ||
|
|
6bf8cbfe46 | ||
|
|
885ff44c56 | ||
|
|
6b054318e0 | ||
|
|
cca4c8cae5 | ||
|
|
203ff8b2e6 | ||
|
|
ad7530f7bb | ||
|
|
affcbddbb0 | ||
|
|
e6321a1305 | ||
|
|
92a1a08b21 | ||
|
|
cf7c54bd56 | ||
|
|
2f4dbf1848 | ||
|
|
2f3d8d83f5 | ||
|
|
119fe908c7 | ||
|
|
2e1d852e36 | ||
|
|
898ecd2df5 | ||
|
|
8d96b7557d | ||
|
|
5e466d91f0 | ||
|
|
83b0c1da40 | ||
|
|
a133c6c4db | ||
|
|
9509eb6876 | ||
|
|
43ec3fc1d9 | ||
|
|
114513493b | ||
|
|
a1826f77da | ||
|
|
c05be40bfd | ||
|
|
d803e42314 | ||
|
|
a032d9c979 | ||
|
|
76c2069fa8 | ||
|
|
f1012283a0 | ||
|
|
924b23ed56 | ||
|
|
b0438ad1dd | ||
|
|
371b155922 | ||
|
|
148775f418 | ||
|
|
c27e093ebd | ||
|
|
52e6a098aa | ||
|
|
096e49e15b | ||
|
|
0ea287cc2c | ||
|
|
8c861f749f | ||
|
|
f1bd5dc051 | ||
|
|
d64986415c | ||
|
|
649ed8a9ae | ||
|
|
569c5520af | ||
|
|
5dc4c5855b | ||
|
|
af8f67ed5f | ||
|
|
9d2bd425e1 | ||
|
|
4b1a6f8824 | ||
|
|
6c2b126c8e | ||
|
|
805cd550f2 | ||
|
|
a4091189b0 | ||
|
|
ef5859437a | ||
|
|
96470227d5 | ||
|
|
cb3e21c443 | ||
|
|
9d3498f01e | ||
|
|
afcff5da2b | ||
|
|
10d95531ff | ||
|
|
cedccbc340 | ||
|
|
3ccd7e4bc7 | ||
|
|
f495c4f002 | ||
|
|
4642f12e29 | ||
|
|
c3aa505f2b | ||
|
|
bf5510e5a6 | ||
|
|
8e023717f7 | ||
|
|
0cb5273766 | ||
|
|
bca8eabcec | ||
|
|
5ab5bc51cd | ||
|
|
36a76e015f | ||
|
|
4b0fe3bc38 |
@ -10,7 +10,7 @@ ColumnLimit: 0
|
|||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ConstructorInitializerIndentWidth: 8
|
ConstructorInitializerIndentWidth: 8
|
||||||
ContinuationIndentWidth: 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
|
IndentFunctionDeclarationAfterType: false #personal taste, good for long methods
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
MaxEmptyLinesToKeep: 2
|
MaxEmptyLinesToKeep: 2
|
||||||
|
|||||||
56
.github/actions/manage-version/action.yml
vendored
Normal file
56
.github/actions/manage-version/action.yml
vendored
Normal 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
|
||||||
8
.github/workflows/android-dockerimage.yml
vendored
8
.github/workflows/android-dockerimage.yml
vendored
@ -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
|
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:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build the name for the docker image
|
- name: Build the name for the docker image
|
||||||
id: build_name
|
id: build_name
|
||||||
run: |
|
run: |
|
||||||
v=${{ env.VERSION }}
|
v=$VERSION
|
||||||
b=${{ github.ref }} # -BRANCH suffix, unless the branch is master
|
b=$GITHUB_REF # -BRANCH suffix, unless the branch is master
|
||||||
b=${b/refs\/heads\//}
|
b=${b/refs\/heads\//}
|
||||||
b=${b,,} # the name needs to be all lower case
|
b=${b,,} # the name needs to be all lower case
|
||||||
if [ $b = "master" ] ; then b="" ; else b="-$b" ; fi
|
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
|
- name: Build and Publish Linux Docker image to Dockerhub
|
||||||
uses: elgohr/Publish-Docker-Github-Action@v5
|
uses: elgohr/Publish-Docker-Github-Action@v5
|
||||||
|
|||||||
63
.github/workflows/android.yml
vendored
63
.github/workflows/android.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Android
|
name: Android
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -11,12 +12,10 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
|
||||||
BUILD_ROOT: ${{ github.workspace }}/..
|
|
||||||
KEYSTORE_FILE: ${{ github.workspace }}/../subsurface.keystore
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildAndroid:
|
build:
|
||||||
|
env:
|
||||||
|
KEYSTORE_FILE: ${{ github.workspace }}/../subsurface.keystore
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: docker://subsurface/android-build:5.15.2
|
image: docker://subsurface/android-build:5.15.2
|
||||||
@ -24,32 +23,33 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
- name: checkout sources
|
||||||
uses: actions/checkout@v4
|
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
|
id: version_number
|
||||||
if: github.event_name == 'push'
|
uses: ./.github/actions/manage-version
|
||||||
run: |
|
with:
|
||||||
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
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
|
|
||||||
|
|
||||||
- name: set up the keystore
|
- name: set up the keystore
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
|
env:
|
||||||
|
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > $KEYSTORE_FILE
|
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > $KEYSTORE_FILE
|
||||||
|
|
||||||
- name: run build
|
- name: run build
|
||||||
id: build
|
id: build
|
||||||
|
env:
|
||||||
|
KEYSTORE_PASSWORD: pass:${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||||
|
KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEYSTORE_ALIAS }}
|
||||||
|
BUILDNR: ${{ steps.version_number.outputs.buildnr }}
|
||||||
run: |
|
run: |
|
||||||
# this is rather awkward, but it allows us to use the preinstalled
|
# this is rather awkward, but it allows us to use the preinstalled
|
||||||
# Android and Qt versions with relative paths
|
# Android and Qt versions with relative paths
|
||||||
cd $BUILD_ROOT
|
cd ..
|
||||||
ln -s /android/5.15.* .
|
ln -s /android/5.15.* .
|
||||||
ln -s /android/build-tools .
|
ln -s /android/build-tools .
|
||||||
ln -s /android/cmdline-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
|
||||||
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
|
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
|
# 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 OUTPUT_DIR="$GITHUB_WORKSPACE"
|
||||||
export KEYSTORE_FILE="$KEYSTORE_FILE"
|
bash -x ./subsurface/packaging/android/qmake-build.sh -buildnr $BUILDNR
|
||||||
export KEYSTORE_PASSWORD="pass:${{ secrets.ANDROID_KEYSTORE_PASSWORD }}"
|
|
||||||
export KEYSTORE_ALIAS="${{ secrets.ANDROID_KEYSTORE_ALIAS }}"
|
- name: delete the keystore
|
||||||
bash -x ./subsurface/packaging/android/qmake-build.sh -buildnr ${BUILDNR}
|
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)
|
# only publish a 'release' on push events (those include merging a PR)
|
||||||
- name: upload binaries
|
- name: upload binaries
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ steps.version_number.outputs.version }}
|
tag_name: v${{ steps.version_number.outputs.version }}
|
||||||
repository: ${{ github.repository_owner }}/nightly-builds
|
repository: ${{ github.repository_owner }}/nightly-builds
|
||||||
@ -81,8 +89,3 @@ jobs:
|
|||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
files: |
|
files: |
|
||||||
Subsurface-mobile-${{ steps.version_number.outputs.version }}.apk
|
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
24
.github/workflows/artifact-links.yml
vendored
Normal 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
|
||||||
19
.github/workflows/codeql-analysis.yml
vendored
19
.github/workflows/codeql-analysis.yml
vendored
@ -25,20 +25,19 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
# Override automatic language detection by changing the below list
|
# Override automatic language detection by changing the below list
|
||||||
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
||||||
language: ['cpp', 'javascript']
|
language: ['c-cpp', 'javascript-typescript']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
fetch-depth: 0
|
||||||
# a pull request then we can checkout the head.
|
submodules: recursive
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: get container ready for build
|
- name: get container ready for build
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
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 \
|
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
|
||||||
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
|
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-dev \
|
||||||
@ -51,7 +50,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# 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
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
|
||||||
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
|
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
|
||||||
bash -e -x subsurface/scripts/build.sh -desktop -build-with-webkit
|
bash -e -x subsurface/scripts/build.sh -desktop -build-with-webkit
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|||||||
28
.github/workflows/coverity-scan.yml
vendored
28
.github/workflows/coverity-scan.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Coverity Scan Linux Qt 5.9
|
name: Coverity Scan Linux Qt 5.9
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 18 * * *' # Daily at 18:00 UTC
|
- cron: '0 18 * * *' # Daily at 18:00 UTC
|
||||||
@ -10,14 +11,11 @@ jobs:
|
|||||||
image: ubuntu:22.04
|
image: ubuntu:22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: add build dependencies
|
- name: add build dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get upgrade -y
|
apt-get dist-upgrade -y
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y -q --force-yes \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
wget curl \
|
wget curl \
|
||||||
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
|
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
|
||||||
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
@ -29,12 +27,22 @@ jobs:
|
|||||||
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
|
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
|
||||||
qtquickcontrols2-5-dev libbluetooth-dev libmtp-dev
|
qtquickcontrols2-5-dev libbluetooth-dev libmtp-dev
|
||||||
|
|
||||||
|
- name: checkout sources
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: configure environment
|
- name: configure environment
|
||||||
env:
|
|
||||||
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
|
|
||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
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
|
- name: run coverity scan
|
||||||
uses: vapier/coverity-scan-action@v1
|
uses: vapier/coverity-scan-action@v1
|
||||||
@ -44,5 +52,5 @@ jobs:
|
|||||||
email: glance@acc.umu.se
|
email: glance@acc.umu.se
|
||||||
command: subsurface/scripts/build.sh -desktop -build-with-webkit
|
command: subsurface/scripts/build.sh -desktop -build-with-webkit
|
||||||
working-directory: ${{ github.workspace }}/..
|
working-directory: ${{ github.workspace }}/..
|
||||||
version: $(/scripts/get-version)
|
version: ${{ steps.version_number.outputs.version }}
|
||||||
description: Automatic scan on github actions
|
description: Automatic scan on github actions
|
||||||
|
|||||||
3
.github/workflows/documentation.yml
vendored
3
.github/workflows/documentation.yml
vendored
@ -26,6 +26,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Checkout Sources
|
- name: Checkout Sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Process the Documentation
|
- name: Process the Documentation
|
||||||
id: process_documentation
|
id: process_documentation
|
||||||
|
|||||||
24
.github/workflows/fedora-copr-build.yml
vendored
24
.github/workflows/fedora-copr-build.yml
vendored
@ -11,30 +11,32 @@ jobs:
|
|||||||
setup-build:
|
setup-build:
|
||||||
name: Submit build to Fedora COPR
|
name: Submit build to Fedora COPR
|
||||||
# this seems backwards, but we want to run under Fedora, but Github doesn' support that
|
# this seems backwards, but we want to run under Fedora, but Github doesn' support that
|
||||||
container: fedora:latest
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: fedora:latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out sources
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Setup build dependencies in the Fedora container
|
- name: Setup build dependencies in the Fedora container
|
||||||
run: |
|
run: |
|
||||||
dnf -y install @development-tools @rpm-development-tools
|
dnf -y install @development-tools @rpm-development-tools
|
||||||
dnf -y install copr-cli make
|
dnf -y install copr-cli make
|
||||||
|
|
||||||
|
- name: Check out sources
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: setup git
|
- name: setup git
|
||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory /__w/subsurface/subsurface
|
git config --global --add safe.directory /__w/subsurface/subsurface
|
||||||
git config --global --add safe.directory /__w/subsurface/subsurface/libdivecomputer
|
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
|
id: version_number
|
||||||
if: github.event_name == 'push'
|
uses: ./.github/actions/manage-version
|
||||||
run: |
|
with:
|
||||||
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
version=$(cat release-version)
|
|
||||||
echo "version=$version" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Setup API token for copr-cli
|
- name: Setup API token for copr-cli
|
||||||
env:
|
env:
|
||||||
@ -53,5 +55,5 @@ jobs:
|
|||||||
- name: run the copr build script
|
- name: run the copr build script
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
bash -x subsurface/packaging/copr/make-package.sh ${{ github.ref_name }}
|
bash -x subsurface/packaging/copr/make-package.sh $GITHUB_REF_NAME
|
||||||
|
|
||||||
|
|||||||
47
.github/workflows/ios.yml
vendored
47
.github/workflows/ios.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: iOS
|
name: iOS
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -12,37 +13,49 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
iOSBuild:
|
build:
|
||||||
runs-on: macOS-11
|
runs-on: macOS-11
|
||||||
steps:
|
steps:
|
||||||
- name: switch to Xcode 11
|
- name: switch to Xcode 11
|
||||||
run: sudo xcode-select -s "/Applications/Xcode_11.7.app"
|
run: sudo xcode-select -s "/Applications/Xcode_11.7.app"
|
||||||
|
|
||||||
- name: checkout sources
|
- name: checkout sources
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: setup Homebrew
|
- name: setup Homebrew
|
||||||
run: brew install autoconf automake libtool pkg-config
|
run: brew install autoconf automake libtool pkg-config
|
||||||
|
|
||||||
- name: set our Qt build
|
- name: checkout Qt resources
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
env
|
with:
|
||||||
curl -L --output Qt-5.14.1-ios.tar.xz https://f002.backblazeb2.com/file/Subsurface-Travis/Qt-5.14.1-ios.tar.xz
|
repository: subsurface/qt-ios
|
||||||
mkdir -p $HOME/Qt
|
ref: main
|
||||||
xzcat Qt-5.14.1-ios.tar.xz | tar -x -C $HOME/Qt -f -
|
path: qt-ios
|
||||||
|
|
||||||
- name: store dummy version and build number for test build
|
- name: set the version information
|
||||||
run: |
|
id: version_number
|
||||||
echo "100" > latest-subsurface-buildnumber
|
uses: ./.github/actions/manage-version
|
||||||
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
|
with:
|
||||||
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
|
|
||||||
- name: build Subsurface-mobile for iOS
|
- name: build Subsurface-mobile for iOS
|
||||||
env:
|
env:
|
||||||
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
|
VERSION: ${{ steps.version_number.outputs.version }}
|
||||||
run: |
|
run: |
|
||||||
cd ${SUBSURFACE_REPO_PATH}/..
|
cd ..
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
|
||||||
ln -s $HOME/Qt Qt
|
export IOS_QT=$GITHUB_WORKSPACE/qt-ios
|
||||||
echo "build for simulator"
|
echo "build for simulator"
|
||||||
bash -x $GITHUB_WORKSPACE/packaging/ios/build.sh -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
|
||||||
|
|||||||
55
.github/workflows/linux-bionic-5.9.yml.disabled
vendored
55
.github/workflows/linux-bionic-5.9.yml.disabled
vendored
@ -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
|
|
||||||
@ -1,34 +1,27 @@
|
|||||||
name: Ubuntu 22.04 / Qt 5.15--
|
name: Generic workflow for Debian and derivatives
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_call:
|
||||||
paths-ignore:
|
inputs:
|
||||||
- scripts/docker/**
|
container-image:
|
||||||
branches:
|
required: true
|
||||||
- master
|
type: string
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- scripts/docker/**
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildUbuntuJammy:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ubuntu:22.04
|
image: ${{ inputs.container-image }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: get container ready for build
|
- name: get container ready for build
|
||||||
run: |
|
run: |
|
||||||
echo "--------------------------------------------------------------"
|
echo "--------------------------------------------------------------"
|
||||||
echo "update distro and install dependencies"
|
echo "update distro and install dependencies"
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get upgrade -y
|
apt-get dist-upgrade -y
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y -q --force-yes \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||||
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
|
autoconf automake cmake g++ git libcrypto++-dev libcurl4-gnutls-dev \
|
||||||
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
libqt5webkit5-dev libsqlite3-dev libssh2-1-dev libssl-dev libssl-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 \
|
qml-module-qtquick2 qt5-qmake qtchooser qtconnectivity5-dev \
|
||||||
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
|
qtdeclarative5-dev qtdeclarative5-private-dev qtlocation5-dev \
|
||||||
qtpositioning5-dev qtscript5-dev qttools5-dev qttools5-dev-tools \
|
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
|
git config --global user.email "ci@subsurface-divelog.org"
|
||||||
run: |
|
git config --global user.name "Subsurface CI"
|
||||||
echo "100" > latest-subsurface-buildnumber
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
|
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
|
- name: set the version information
|
||||||
env:
|
id: version_number
|
||||||
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
|
uses: ./.github/actions/manage-version
|
||||||
|
with:
|
||||||
|
no-increment: true
|
||||||
|
|
||||||
|
- name: build subsurface-mobile
|
||||||
run: |
|
run: |
|
||||||
echo "--------------------------------------------------------------"
|
echo "--------------------------------------------------------------"
|
||||||
echo "building mobile"
|
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 ..
|
cd ..
|
||||||
bash -e -x subsurface/scripts/build.sh -mobile
|
bash -e -x subsurface/scripts/build.sh -mobile
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
# xvfb-run --auto-servernum ./TestGitStorage -v2
|
# xvfb-run --auto-servernum ./TestGitStorage -v2
|
||||||
xvfb-run --auto-servernum make check
|
xvfb-run --auto-servernum make check
|
||||||
|
|
||||||
- name: build Subsurface
|
- name: build subsurface
|
||||||
run: |
|
run: |
|
||||||
echo "--------------------------------------------------------------"
|
echo "--------------------------------------------------------------"
|
||||||
echo "building desktop"
|
echo "building desktop"
|
||||||
@ -83,3 +83,18 @@ jobs:
|
|||||||
# xvfb-run --auto-servernum ./TestGitStorage -v2
|
# xvfb-run --auto-servernum ./TestGitStorage -v2
|
||||||
xvfb-run --auto-servernum make check
|
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
|
||||||
19
.github/workflows/linux-debian-trixie-5.15.yml
vendored
Normal file
19
.github/workflows/linux-debian-trixie-5.15.yml
vendored
Normal 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
|
||||||
39
.github/workflows/linux-dockerimage.disabled
vendored
39
.github/workflows/linux-dockerimage.disabled
vendored
@ -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/'
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
name: Fedora 35 / Qt 6--
|
name: Fedora 35 / Qt 6--
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -12,15 +13,12 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildFedoraQt6:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: fedora:35
|
image: fedora:35
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: get container ready for build
|
- name: get container ready for build
|
||||||
run: |
|
run: |
|
||||||
echo "--------------------------------------------------------------"
|
echo "--------------------------------------------------------------"
|
||||||
@ -37,22 +35,27 @@ jobs:
|
|||||||
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel \
|
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel \
|
||||||
xorg-x11-server-Xvfb
|
xorg-x11-server-Xvfb
|
||||||
|
|
||||||
- name: store dummy version and build number for test build
|
- name: checkout sources
|
||||||
run: |
|
uses: actions/checkout@v4
|
||||||
echo "100" > latest-subsurface-buildnumber
|
with:
|
||||||
echo "CICD-test-build" > latest-subsurface-buildnumber-extension
|
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
|
- name: build Subsurface
|
||||||
env:
|
|
||||||
SUBSURFACE_REPO_PATH: ${{ github.workspace }}
|
|
||||||
run: |
|
run: |
|
||||||
echo "--------------------------------------------------------------"
|
echo "--------------------------------------------------------------"
|
||||||
echo "building desktop"
|
echo "building desktop"
|
||||||
|
|
||||||
# now build for the desktop version (without WebKit)
|
# now build for the desktop version (without WebKit)
|
||||||
cd ..
|
cd ..
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
git config --global --add safe.directory $GITHUB_WORKSPACE/libdivecomputer
|
||||||
git config --global --get-all safe.directory
|
git config --global --get-all safe.directory
|
||||||
bash -e -x subsurface/scripts/build.sh -desktop -build-with-qt6
|
bash -e -x subsurface/scripts/build.sh -desktop -build-with-qt6
|
||||||
|
|
||||||
85
.github/workflows/linux-focal-5.12.yml
vendored
85
.github/workflows/linux-focal-5.12.yml
vendored
@ -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
|
|
||||||
|
|
||||||
18
.github/workflows/linux-snap.yml
vendored
18
.github/workflows/linux-snap.yml
vendored
@ -19,16 +19,16 @@ jobs:
|
|||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
# Needed for version determination to work
|
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: atomically create or retrieve the build number
|
- name: set the version information
|
||||||
id: version_number
|
id: version_number
|
||||||
if: github.event_name == 'push'
|
uses: ./.github/actions/manage-version
|
||||||
run: |
|
with:
|
||||||
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
|
|
||||||
- name: store dummy version and build number for pull request
|
- name: store dummy version and build number for pull request
|
||||||
if: github.event_name == '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
|
/snap/bin/lxc profile device add default ccache disk source=${HOME}/.ccache/ path=/root/.ccache
|
||||||
|
|
||||||
# Patch snapcraft.yaml to enable 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.
|
# 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
|
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
|
- name: CCache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload the snap
|
- name: Upload the snap
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.build-snap.outputs.snap-name }}
|
name: ${{ steps.build-snap.outputs.snap-name }}
|
||||||
path: ${{ steps.build-snap.outputs.snap-path }}
|
path: ${{ steps.build-snap.outputs.snap-path }}
|
||||||
|
|||||||
77
.github/workflows/linux-trusty-5.12.yml
vendored
77
.github/workflows/linux-trusty-5.12.yml
vendored
@ -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
|
|
||||||
149
.github/workflows/linux-ubuntu-16.04-5.12-appimage.yml
vendored
Normal file
149
.github/workflows/linux-ubuntu-16.04-5.12-appimage.yml
vendored
Normal 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
|
||||||
19
.github/workflows/linux-ubuntu-20.04-5.15.yml
vendored
Normal file
19
.github/workflows/linux-ubuntu-20.04-5.15.yml
vendored
Normal 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
|
||||||
19
.github/workflows/linux-ubuntu-22.04-5.15.yml
vendored
Normal file
19
.github/workflows/linux-ubuntu-22.04-5.15.yml
vendored
Normal 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
|
||||||
19
.github/workflows/linux-ubuntu-24.04-5.15.yml
vendored
Normal file
19
.github/workflows/linux-ubuntu-24.04-5.15.yml
vendored
Normal 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
|
||||||
53
.github/workflows/mac.yml
vendored
53
.github/workflows/mac.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Mac
|
name: Mac
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -11,38 +12,38 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildMac:
|
build:
|
||||||
runs-on: macOS-11
|
runs-on: macOS-11
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
- name: checkout sources
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
- name: atomically create or retrieve the build number and assemble release notes
|
fetch-depth: 0
|
||||||
id: version_number
|
submodules: recursive
|
||||||
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: setup Homebrew
|
- name: setup Homebrew
|
||||||
run: brew install hidapi libxslt libjpg libmtp create-dmg confuse
|
run: brew install hidapi libxslt libjpg libmtp create-dmg confuse
|
||||||
- name: set our Qt build
|
|
||||||
run: |
|
- name: checkout Qt resources
|
||||||
curl --output ssrf-Qt-5.15.2-mac.tar.xz https://f002.backblazeb2.com/file/Subsurface-Travis/ssrf-Qt5.15.2.tar.xz
|
uses: actions/checkout@v4
|
||||||
tar -xJf ssrf-Qt-5.15.2-mac.tar.xz
|
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
|
- name: build Subsurface
|
||||||
id: build
|
id: build
|
||||||
run: |
|
run: |
|
||||||
cd ${GITHUB_WORKSPACE}/..
|
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 QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins
|
||||||
export PATH=$QT_ROOT/bin:$PATH
|
export PATH=$QT_ROOT/bin:$PATH
|
||||||
export CMAKE_PREFIX_PATH=$QT_ROOT/lib/cmake
|
export CMAKE_PREFIX_PATH=$QT_ROOT/lib/cmake
|
||||||
@ -58,10 +59,18 @@ jobs:
|
|||||||
echo "Created $IMG"
|
echo "Created $IMG"
|
||||||
echo "dmg=$IMG" >> $GITHUB_OUTPUT
|
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)
|
# only publish a 'release' on push events (those include merging a PR)
|
||||||
- name: upload binaries
|
- name: upload binaries
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ steps.version_number.outputs.version }}
|
tag_name: v${{ steps.version_number.outputs.version }}
|
||||||
repository: ${{ github.repository_owner }}/nightly-builds
|
repository: ${{ github.repository_owner }}/nightly-builds
|
||||||
|
|||||||
29
.github/workflows/post-releasenotes.yml
vendored
29
.github/workflows/post-releasenotes.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Post Release
|
name: Post Release Notes
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -6,29 +7,35 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
postRelease:
|
postRelease:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
- name: checkout sources
|
||||||
uses: actions/checkout@v4
|
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
|
# 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
|
- name: assemble release notes
|
||||||
id: version_number
|
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: |
|
run: |
|
||||||
bash -x ./scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
scripts/create-releasenotes.sh $EVENT_HEAD_COMMIT_ID
|
||||||
bash scripts/create-releasenotes.sh ${{ github.event.head_commit.id }}
|
|
||||||
version=$(cat release-version)
|
|
||||||
echo "version=$version" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# add a file containing the release title so it can be picked up and listed on the release page on our web server
|
# 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
|
- name: publish release
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ steps.version_number.outputs.version }}
|
tag_name: v${{ steps.version_number.outputs.version }}
|
||||||
repository: ${{ github.repository_owner }}/nightly-builds
|
repository: ${{ github.repository_owner }}/nightly-builds
|
||||||
|
|||||||
2
.github/workflows/scripts/check_usns.py
vendored
2
.github/workflows/scripts/check_usns.py
vendored
@ -23,13 +23,11 @@ logger.setLevel(logging.INFO)
|
|||||||
|
|
||||||
APPLICATION = "subsurface-ci"
|
APPLICATION = "subsurface-ci"
|
||||||
LAUNCHPAD = "production"
|
LAUNCHPAD = "production"
|
||||||
RELEASE = "bionic"
|
|
||||||
TEAM = "subsurface"
|
TEAM = "subsurface"
|
||||||
SOURCE_NAME = "subsurface"
|
SOURCE_NAME = "subsurface"
|
||||||
SNAPS = {
|
SNAPS = {
|
||||||
"subsurface": {
|
"subsurface": {
|
||||||
"stable": {"recipe": "subsurface-stable"},
|
"stable": {"recipe": "subsurface-stable"},
|
||||||
"candidate": {"recipe": "subsurface-candidate"},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
15
.github/workflows/ubuntu-launchpad-build.yml
vendored
15
.github/workflows/ubuntu-launchpad-build.yml
vendored
@ -15,13 +15,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out sources
|
- 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
|
id: version_number
|
||||||
if: github.event_name == 'push'
|
uses: ./.github/actions/manage-version
|
||||||
run: |
|
with:
|
||||||
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
|
|
||||||
- name: Setup build dependencies
|
- name: Setup build dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -48,5 +51,5 @@ jobs:
|
|||||||
- name: run the launchpad make-package script
|
- name: run the launchpad make-package script
|
||||||
run: |
|
run: |
|
||||||
cd ..
|
cd ..
|
||||||
bash -x subsurface/packaging/ubuntu/make-package.sh ${{ github.ref_name }}
|
bash -x subsurface/packaging/ubuntu/make-package.sh $GITHUB_REF_NAME
|
||||||
|
|
||||||
|
|||||||
@ -16,17 +16,17 @@ jobs:
|
|||||||
mxe_sha: 'c0bfefc57a00fdf6cb5278263e21a478e47b0bf5'
|
mxe_sha: 'c0bfefc57a00fdf6cb5278263e21a478e47b0bf5'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Build the name for the docker image
|
- name: Build the name for the docker image
|
||||||
id: build_name
|
id: build_name
|
||||||
run: |
|
run: |
|
||||||
v=${{ env.VERSION }}
|
v=$VERSION
|
||||||
b=${{ github.ref }} # -BRANCH suffix, unless the branch is master
|
b=$GITHUB_REF # -BRANCH suffix, unless the branch is master
|
||||||
b=${b/refs\/heads\//}
|
b=${b/refs\/heads\//}
|
||||||
b=${b,,} # the name needs to be all lower case
|
b=${b,,} # the name needs to be all lower case
|
||||||
if [ $b = "master" ] ; then b="" ; else b="-$b" ; fi
|
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
|
- name: Build and Publish Linux Docker image to Dockerhub
|
||||||
uses: elgohr/Publish-Docker-Github-Action@v5
|
uses: elgohr/Publish-Docker-Github-Action@v5
|
||||||
|
|||||||
40
.github/workflows/windows.yml
vendored
40
.github/workflows/windows.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: Windows
|
name: Windows
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@ -12,28 +13,23 @@ on:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
buildWindows:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: docker://subsurface/mxe-build:3.1.0
|
image: docker://subsurface/mxe-build:3.1.0
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout sources
|
- 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
|
id: version_number
|
||||||
if: github.event_name == 'push'
|
uses: ./.github/actions/manage-version
|
||||||
run: |
|
with:
|
||||||
bash scripts/get-atomic-buildnr.sh ${{ github.sha }} ${{ secrets.NIGHTLY_BUILDS }} "CICD-release"
|
nightly-builds-secret: ${{ secrets.NIGHTLY_BUILDS }}
|
||||||
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: get other dependencies
|
- name: get other dependencies
|
||||||
env:
|
env:
|
||||||
@ -44,18 +40,28 @@ jobs:
|
|||||||
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
git config --global --add safe.directory ${SUBSURFACE_REPO_PATH}/libdivecomputer
|
||||||
cd /win
|
cd /win
|
||||||
ln -s /__w/subsurface/subsurface .
|
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
|
- name: run build
|
||||||
run: |
|
run: |
|
||||||
|
export OUTPUT_DIR="$GITHUB_WORKSPACE"
|
||||||
cd /win
|
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
|
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)
|
# only publish a 'release' on push events (those include merging a PR)
|
||||||
- name: upload binaries
|
- name: upload binaries
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ steps.version_number.outputs.version }}
|
tag_name: v${{ steps.version_number.outputs.version }}
|
||||||
repository: ${{ github.repository_owner }}/nightly-builds
|
repository: ${{ github.repository_owner }}/nightly-builds
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ appdata/subsurface.appdata.xml
|
|||||||
android-mobile/Roboto-Regular.ttf
|
android-mobile/Roboto-Regular.ttf
|
||||||
gh_release_notes.md
|
gh_release_notes.md
|
||||||
release_content_title.txt
|
release_content_title.txt
|
||||||
|
/output/
|
||||||
|
|||||||
@ -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
|
desktop: add a button linking to the 'Contribute' page
|
||||||
mobile: fix configuration of decompression ceiling and gradient factors
|
mobile: fix configuration of decompression ceiling and gradient factors
|
||||||
desktop: fix gas switches in UDDF exports
|
desktop: fix gas switches in UDDF exports
|
||||||
|
|||||||
@ -124,8 +124,8 @@ if (SUBSURFACE_ASAN_BUILD)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# every compiler understands -Wall
|
# every compiler understands -Wall
|
||||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror=format")
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=format")
|
||||||
|
|
||||||
# by detault optimize with -O2 even for debug builds
|
# by detault optimize with -O2 even for debug builds
|
||||||
set (GCC_OPTIMIZATION_FLAGS "-O2" CACHE STRING "GCC optimization flags")
|
set (GCC_OPTIMIZATION_FLAGS "-O2" CACHE STRING "GCC optimization flags")
|
||||||
@ -320,7 +320,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||||||
endif()
|
endif()
|
||||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND bash scripts/get-version
|
COMMAND bash scripts/get-version.sh
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE SSRF_VERSION_STRING
|
OUTPUT_VARIABLE SSRF_VERSION_STRING
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
|||||||
@ -135,7 +135,7 @@ msgid ""
|
|||||||
"mailto:subsurface@subsurface-divelog.org[our mailing list] and report bugs "
|
"mailto:subsurface@subsurface-divelog.org[our mailing list] and report bugs "
|
||||||
"at https://github.com/Subsurface/subsurface/issues[our bugtracker]. "
|
"at https://github.com/Subsurface/subsurface/issues[our bugtracker]. "
|
||||||
"For instructions on how to build the software and (if needed) its "
|
"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 ""
|
msgstr ""
|
||||||
|
|
||||||
#. type: Plain text
|
#. type: Plain text
|
||||||
|
|||||||
@ -175,7 +175,7 @@ msgid ""
|
|||||||
"an email to mailto:subsurface@subsurface-divelog.org[our mailing list] and "
|
"an email to mailto:subsurface@subsurface-divelog.org[our mailing list] and "
|
||||||
"report bugs at https://github.com/Subsurface-divelog/subsurface/issues[our "
|
"report bugs at https://github.com/Subsurface-divelog/subsurface/issues[our "
|
||||||
"bugtracker]. For instructions on how to build the software and (if needed) "
|
"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."
|
"code."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ce manuel explique comment utiliser le programme _Subsurface_. Pour "
|
"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 "
|
"pouvez envoyer un e-mail sur mailto:subsurface@subsurface-divelog.org[notre "
|
||||||
"liste de diffusion] et rapportez les bogues sur http://trac.hohndel."
|
"liste de diffusion] et rapportez les bogues sur http://trac.hohndel."
|
||||||
"org[notre bugtracker]. Pour des instructions de compilation du logiciel et "
|
"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."
|
"dans les sources logicielles."
|
||||||
|
|
||||||
#. type: Plain text
|
#. type: Plain text
|
||||||
|
|||||||
@ -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
|
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="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
|
<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>
|
included with the source code.</p></div>
|
||||||
<div class="paragraph"><p><strong>Audience</strong>: Recreational Scuba Divers, Free Divers, Tec Divers, Professional
|
<div class="paragraph"><p><strong>Audience</strong>: Recreational Scuba Divers, Free Divers, Tec Divers, Professional
|
||||||
Divers</p></div>
|
Divers</p></div>
|
||||||
|
|||||||
@ -34,7 +34,7 @@ https://subsurface-divelog.org/[_Subsurface_ web site].
|
|||||||
Please discuss issues with this program by sending an email to
|
Please discuss issues with this program by sending an email to
|
||||||
mailto:subsurface@subsurface-divelog.org[our mailing list] and report bugs at
|
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
|
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.
|
included with the source code.
|
||||||
|
|
||||||
*Audience*: Recreational Scuba Divers, Free Divers, Tec Divers, Professional
|
*Audience*: Recreational Scuba Divers, Free Divers, Tec Divers, Professional
|
||||||
|
|||||||
@ -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
|
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>.
|
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)
|
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>
|
fuente.</p></div>
|
||||||
<div class="paragraph"><p><strong>Audiencia</strong>: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,
|
<div class="paragraph"><p><strong>Audiencia</strong>: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,
|
||||||
Buceadores profesionales.</p></div>
|
Buceadores profesionales.</p></div>
|
||||||
|
|||||||
@ -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
|
mail a mailto:subsurface@subsurface-divelog.org[nuestra lista de correo] e informa de
|
||||||
fallos en https://github.com/Subsurface/subsurface/issues[nuestro bugtracker].
|
fallos en https://github.com/Subsurface/subsurface/issues[nuestro bugtracker].
|
||||||
Para instrucciones acerca de como compilar el software y (en caso necesario)
|
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.
|
fuente.
|
||||||
|
|
||||||
*Audiencia*: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,
|
*Audiencia*: Buceadores recreativos, Buceadores en apnea, Buceadores técnicos,
|
||||||
|
|||||||
@ -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
|
<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
|
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
|
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>
|
logicielles.</p></div>
|
||||||
<div class="paragraph"><p><strong>Public</strong> : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs
|
<div class="paragraph"><p><strong>Public</strong> : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs
|
||||||
professionnels</p></div>
|
professionnels</p></div>
|
||||||
|
|||||||
@ -61,7 +61,7 @@ problème, vous pouvez envoyer un e-mail sur
|
|||||||
mailto:subsurface@subsurface-divelog.org[notre liste de diffusion] et
|
mailto:subsurface@subsurface-divelog.org[notre liste de diffusion] et
|
||||||
rapportez les bogues sur http://trac.hohndel.org[notre bugtracker]. Pour
|
rapportez les bogues sur http://trac.hohndel.org[notre bugtracker]. Pour
|
||||||
des instructions de compilation du logiciel et (si besoin) de ses
|
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.
|
logicielles.
|
||||||
|
|
||||||
*Public* : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs
|
*Public* : Plongeurs loisirs, apnéistes, plongeurs Tek et plongeurs
|
||||||
|
|||||||
@ -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
|
<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>.
|
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
|
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,
|
<div class="paragraph"><p><strong>Doelgroep</strong>: Recreatieve duikers, Tec duikers, Apneu duikers,
|
||||||
Professionele duikers.</p></div>
|
Professionele duikers.</p></div>
|
||||||
<div id="toc">
|
<div id="toc">
|
||||||
|
|||||||
@ -59,7 +59,7 @@ het programma kunnen bij de ontwikkelaars gemeld worden via email op
|
|||||||
mailto:subsurface@subsurface-divelog.org[onze mailinglijst]. Fouten kunnen
|
mailto:subsurface@subsurface-divelog.org[onze mailinglijst]. Fouten kunnen
|
||||||
ook gemeld worden op https://github.com/Subsurface/subsurface/issues[onze bugtracker].
|
ook gemeld worden op https://github.com/Subsurface/subsurface/issues[onze bugtracker].
|
||||||
Instructies hoe _Subsurface_ zelf te compileren vanuit de broncode staan ook op
|
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,
|
*Doelgroep*: Recreatieve duikers, Tec duikers, Apneu duikers,
|
||||||
Professionele duikers.
|
Professionele duikers.
|
||||||
|
|||||||
@ -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
|
Subsurface uses quite a few open source libraries and frameworks to do its
|
||||||
job. The most important ones include libdivecomputer, Qt, libxml2, libxslt,
|
job. The most important ones include libdivecomputer, Qt, libxml2, libxslt,
|
||||||
@ -13,23 +12,27 @@ Below are instructions for building Subsurface
|
|||||||
- iOS (cross-building)
|
- iOS (cross-building)
|
||||||
|
|
||||||
|
|
||||||
Getting Subsurface source
|
## Getting Subsurface source
|
||||||
-------------------------
|
|
||||||
|
|
||||||
You can get the sources to the latest development version from our git
|
You can get the sources to the latest development version from our git
|
||||||
repository:
|
repository:
|
||||||
|
|
||||||
|
```
|
||||||
git clone http://github.com/Subsurface/subsurface.git
|
git clone http://github.com/Subsurface/subsurface.git
|
||||||
cd subsurface
|
cd subsurface
|
||||||
git submodule init # this will give you our flavor of libdivecomputer
|
git submodule init # this will give you our flavor of libdivecomputer
|
||||||
|
```
|
||||||
|
|
||||||
You keep it updated by doing:
|
You keep it updated by doing:
|
||||||
|
|
||||||
|
```
|
||||||
git checkout master
|
git checkout master
|
||||||
git pull -r
|
git pull -r
|
||||||
git submodule update
|
git submodule update
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Our flavor of libdivecomputer
|
### Our flavor of libdivecomputer
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Subsurface requires its own flavor of libdivecomputer which is inclduded
|
Subsurface requires its own flavor of libdivecomputer which is inclduded
|
||||||
above as git submodule
|
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,
|
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
|
but they should always allow a fast forward pull that tracks what we
|
||||||
believe developers should build against. All our patches are contained
|
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
|
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
|
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.
|
respective upstreams.
|
||||||
|
|
||||||
|
|
||||||
Getting Qt5
|
### Getting Qt5
|
||||||
-----------
|
|
||||||
|
|
||||||
We use Qt5 in order to only maintain one UI across platforms.
|
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
|
As of this writing, there is thankfully a thirdparty offline installer still
|
||||||
available:
|
available:
|
||||||
|
|
||||||
|
```
|
||||||
pip3 install aqtinstall
|
pip3 install aqtinstall
|
||||||
aqt install -O <Qt Location> 5.15.2 mac desktop
|
aqt install -O <Qt Location> 5.15.2 mac desktop
|
||||||
|
```
|
||||||
|
|
||||||
(or whatever version / OS you need). This installer is surprisingly fast
|
(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
|
and seems well maintained - note that we don't use this for Windows as
|
||||||
that is completely built from source using MXE.
|
that is completely built from source using MXE.
|
||||||
|
|
||||||
In order to use this Qt installation, simply add it to your PATH:
|
In order to use this Qt installation, simply add it to your PATH:
|
||||||
|
|
||||||
|
```
|
||||||
PATH=<Qt Location>/<version>/<type>/bin:$PATH
|
PATH=<Qt Location>/<version>/<type>/bin:$PATH
|
||||||
|
```
|
||||||
|
|
||||||
QtWebKit is needed, if you want to print, but no longer part of Qt5,
|
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
|
so you need to download it and compile. In case you just want to test
|
||||||
without print possibility omit this step.
|
without print possibility omit this step.
|
||||||
|
|
||||||
|
```
|
||||||
git clone -b 5.212 https://github.com/qt/qtwebkit
|
git clone -b 5.212 https://github.com/qt/qtwebkit
|
||||||
mkdir -p qtwebkit/WebKitBuild/Release
|
mkdir -p qtwebkit/WebKitBuild/Release
|
||||||
cd qtwebkit/WebKitBuild/Release
|
cd qtwebkit/WebKitBuild/Release
|
||||||
cmake -DPORT=Qt -DCMAKE_BUILD_TYPE=Release -DQt5_DIR=/<Qt Location>/<version>/<type>/lib/cmake/Qt5 ../..
|
cmake -DPORT=Qt -DCMAKE_BUILD_TYPE=Release -DQt5_DIR=/<Qt Location>/<version>/<type>/lib/cmake/Qt5 ../..
|
||||||
make install
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Other third party library dependencies
|
### Other third party library dependencies
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
In order for our cloud storage to be fully functional you need
|
In order for our cloud storage to be fully functional you need
|
||||||
libgit2 0.26 or newer.
|
libgit2 0.26 or newer.
|
||||||
|
|
||||||
|
|
||||||
cmake build system
|
### cmake build system
|
||||||
------------------
|
|
||||||
|
|
||||||
Our main build system is based on cmake. But qmake is needed
|
Our main build system is based on cmake. But qmake is needed
|
||||||
for the googlemaps plugin and the iOS build.
|
for the googlemaps plugin and the iOS build.
|
||||||
@ -114,32 +121,35 @@ distribution (see build instructions).
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Build options for Subsurface
|
## Build options for Subsurface
|
||||||
----------------------------
|
|
||||||
|
|
||||||
The following options are recognised when passed to cmake:
|
The following options are recognised when passed to cmake:
|
||||||
|
|
||||||
-DCMAKE_BUILD_TYPE=Release create a release build
|
`-DCMAKE_BUILD_TYPE=Release` create a release build
|
||||||
-DCMAKE_BUILD_TYPE=Debug create a debug build
|
`-DCMAKE_BUILD_TYPE=Debug` create a debug build
|
||||||
|
|
||||||
The Makefile that was created using cmake can be forced into a much more
|
The Makefile that was created using cmake can be forced into a much more
|
||||||
verbose mode by calling
|
verbose mode by calling
|
||||||
|
|
||||||
|
```
|
||||||
make VERBOSE=1
|
make VERBOSE=1
|
||||||
|
```
|
||||||
|
|
||||||
Many more variables are supported, the easiest way to interact with them is
|
Many more variables are supported, the easiest way to interact with them is
|
||||||
to call
|
to call
|
||||||
|
|
||||||
|
```
|
||||||
ccmake .
|
ccmake .
|
||||||
|
```
|
||||||
|
|
||||||
in your build directory.
|
in your build directory.
|
||||||
|
|
||||||
|
|
||||||
Building the development version of Subsurface under Linux
|
### Building the development version of Subsurface under Linux
|
||||||
----------------------------------------------------------
|
|
||||||
|
|
||||||
On Fedora you need
|
On Fedora you need
|
||||||
|
|
||||||
|
```
|
||||||
sudo dnf install autoconf automake bluez-libs-devel cmake gcc-c++ git \
|
sudo dnf install autoconf automake bluez-libs-devel cmake gcc-c++ git \
|
||||||
libcurl-devel libsqlite3x-devel libssh2-devel libtool libudev-devel \
|
libcurl-devel libsqlite3x-devel libssh2-devel libtool libudev-devel \
|
||||||
libusbx-devel libxml2-devel libxslt-devel make \
|
libusbx-devel libxml2-devel libxslt-devel make \
|
||||||
@ -147,10 +157,12 @@ sudo dnf install autoconf automake bluez-libs-devel cmake gcc-c++ git \
|
|||||||
qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \
|
qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \
|
||||||
qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \
|
qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \
|
||||||
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel
|
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Package names are sadly different on OpenSUSE
|
Package names are sadly different on OpenSUSE
|
||||||
|
|
||||||
|
```
|
||||||
sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-devel \
|
sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-devel \
|
||||||
libxml2-devel libxslt-devel sqlite3-devel libusb-1_0-devel \
|
libxml2-devel libxslt-devel sqlite3-devel libusb-1_0-devel \
|
||||||
libqt5-linguist-devel libqt5-qttools-devel libQt5WebKitWidgets-devel \
|
libqt5-linguist-devel libqt5-qttools-devel libQt5WebKitWidgets-devel \
|
||||||
@ -158,9 +170,11 @@ sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-deve
|
|||||||
libqt5-qtscript-devel libqt5-qtdeclarative-devel \
|
libqt5-qtscript-devel libqt5-qtdeclarative-devel \
|
||||||
libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \
|
libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \
|
||||||
bluez-devel libgit2-devel libmtp-devel
|
bluez-devel libgit2-devel libmtp-devel
|
||||||
|
```
|
||||||
|
|
||||||
On Debian Bookworm this seems to work
|
On Debian Bookworm this seems to work
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
||||||
libcurl4-openssl-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libcurl4-openssl-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
@ -170,17 +184,21 @@ sudo apt install \
|
|||||||
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
||||||
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
||||||
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
||||||
|
```
|
||||||
|
|
||||||
In order to build and run mobile-on-desktop, you also need
|
In order to build and run mobile-on-desktop, you also need
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
|
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-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
|
||||||
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
|
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Package names for Ubuntu 21.04
|
Package names for Ubuntu 21.04
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
||||||
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
@ -190,17 +208,21 @@ sudo apt install \
|
|||||||
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
||||||
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
||||||
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
||||||
|
```
|
||||||
|
|
||||||
In order to build and run mobile-on-desktop, you also need
|
In order to build and run mobile-on-desktop, you also need
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
|
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-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
|
||||||
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
|
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
|
On Raspberry Pi (Raspian Buster and Ubuntu Mate 20.04.1) this seems to work
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
||||||
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
@ -210,13 +232,16 @@ sudo apt install \
|
|||||||
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
||||||
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
||||||
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev
|
||||||
|
```
|
||||||
|
|
||||||
In order to build and run mobile-on-desktop, you also need
|
In order to build and run mobile-on-desktop, you also need
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
qtquickcontrols2-5-dev qml-module-qtquick-window2 qml-module-qtquick-dialogs \
|
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-qtquick-layouts qml-module-qtquick-controls2 qml-module-qtquick-templates2 \
|
||||||
qml-module-qtgraphicaleffects qml-module-qtqml-models2 qml-module-qtquick-controls
|
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
|
Note that on Ubuntu Mate on the Raspberry Pi, you may need to configure
|
||||||
@ -226,6 +251,7 @@ swap space configured by default. See the dphys-swapfile package.
|
|||||||
On Raspberry Pi OS with Desktop (64-bit) Released April 4th, 2022, this seems
|
On Raspberry Pi OS with Desktop (64-bit) Released April 4th, 2022, this seems
|
||||||
to work
|
to work
|
||||||
|
|
||||||
|
```
|
||||||
sudo apt install \
|
sudo apt install \
|
||||||
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
autoconf automake cmake g++ git libbluetooth-dev libcrypto++-dev \
|
||||||
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
libcurl4-gnutls-dev libgit2-dev libqt5qml5 libqt5quick5 libqt5svg5-dev \
|
||||||
@ -235,15 +261,16 @@ sudo apt install \
|
|||||||
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
|
||||||
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
|
||||||
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-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
|
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+.
|
doesn't seem to be enough. 1024MB worked on a 3B+.
|
||||||
|
|
||||||
If maps aren't working, copy the googlemaps plugin
|
If maps aren't working, copy the googlemaps plugin
|
||||||
from <build_dir>/subsurface/googlemaps/build/libqtgeoservices_googlemaps.so
|
from `<build_dir>/subsurface/googlemaps/build/libqtgeoservices_googlemaps.so`
|
||||||
to /usr/lib/aarch64-linux-gnu/qt5/plugins/geoservices.
|
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
|
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
|
might be that the FTDI driver doesn't recognize the VendorID/ProductID of your
|
||||||
computer. Follow the instructions here:
|
computer. Follow the instructions here:
|
||||||
@ -256,12 +283,14 @@ follow TN_101.
|
|||||||
|
|
||||||
On PCLinuxOS you appear to need the following packages
|
On PCLinuxOS you appear to need the following packages
|
||||||
|
|
||||||
|
```
|
||||||
su -c "apt-get install -y autoconf automake cmake gcc-c++ git libtool \
|
su -c "apt-get install -y autoconf automake cmake gcc-c++ git libtool \
|
||||||
lib64bluez-devel lib64qt5bluetooth-devel lib64qt5concurrent-devel \
|
lib64bluez-devel lib64qt5bluetooth-devel lib64qt5concurrent-devel \
|
||||||
lib64qt5help-devel lib64qt5location-devel lib64qt5quicktest-devel \
|
lib64qt5help-devel lib64qt5location-devel lib64qt5quicktest-devel \
|
||||||
lib64qt5quickwidgets-devel lib64qt5script-devel lib64qt5svg-devel \
|
lib64qt5quickwidgets-devel lib64qt5script-devel lib64qt5svg-devel \
|
||||||
lib64qt5test-devel lib64qt5webkitwidgets-devel lib64qt5xml-devel \
|
lib64qt5test-devel lib64qt5webkitwidgets-devel lib64qt5xml-devel \
|
||||||
lib64ssh2-devel lib64usb1.0-devel lib64zip-devel qttools5 qttranslations5"
|
lib64ssh2-devel lib64usb1.0-devel lib64zip-devel qttools5 qttranslations5"
|
||||||
|
```
|
||||||
|
|
||||||
In order to build Subsurface, use the supplied build script. This should
|
In order to build Subsurface, use the supplied build script. This should
|
||||||
work on most systems that have all the prerequisite packages installed.
|
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
|
You should have Subsurface sources checked out in a sane place, something
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
|
```
|
||||||
mkdir -p ~/src
|
mkdir -p ~/src
|
||||||
cd ~/src
|
cd ~/src
|
||||||
git clone https://github.com/Subsurface/subsurface.git
|
git clone https://github.com/Subsurface/subsurface.git
|
||||||
./subsurface/scripts/build.sh # <- this step will take quite a while as it
|
./subsurface/scripts/build.sh # <- this step will take quite a while as it
|
||||||
# compiles a handful of libraries before
|
# compiles a handful of libraries before
|
||||||
# building Subsurface
|
# building Subsurface
|
||||||
|
```
|
||||||
|
|
||||||
Now you can run Subsurface like this:
|
Now you can run Subsurface like this:
|
||||||
|
|
||||||
|
```
|
||||||
cd ~/src/subsurface/build
|
cd ~/src/subsurface/build
|
||||||
./subsurface
|
./subsurface
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Note: on many Linux versions (for example on Kubuntu 15.04) the user must
|
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
|
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
|
with your correct username and log out and log in again for that to take
|
||||||
effect.
|
effect.
|
||||||
|
|
||||||
If you get errors like:
|
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
|
./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:
|
You can run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
sudo ldconfig ~/src/install-root/lib
|
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,
|
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
|
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.
|
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
|
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
|
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
|
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
|
and use it to install the desired Qt version. At this point the latest Qt5 version is still
|
||||||
preferred over Qt6.
|
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
|
cd ~/src; bash subsurface/scripts/build.sh -build-deps
|
||||||
|
```
|
||||||
|
|
||||||
if you are building against Qt6 (still experimental) you can create a universal binary with
|
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
|
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
|
After the above is done, Subsurface.app will be available in the
|
||||||
subsurface/build directory. You can run Subsurface with the command
|
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
|
this will however not show diagnostic output
|
||||||
|
|
||||||
B) subsurface/build/Subsurface.app/Contents/MacOS/Subsurface
|
B. `subsurface/build/Subsurface.app/Contents/MacOS/Subsurface`
|
||||||
the TAB key is your friend :-)
|
the [Tab] key is your friend :-)
|
||||||
|
|
||||||
Debugging can be done with either Xcode or QtCreator.
|
Debugging can be done with either Xcode or QtCreator.
|
||||||
|
|
||||||
To install the app for all users, move subsurface/build/Subsurface.app to /Applications.
|
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
|
note: this is mainly done to ensure all external dependencies are downloaded and set
|
||||||
to the correct versions
|
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
|
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).
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
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
|
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,
|
really painful to build Subsurface natively under Windows,
|
||||||
so we don't support that at all.
|
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).
|
||||||
46
README.md
46
README.md
@ -1,20 +1,17 @@
|
|||||||
# Subsurface
|
# Subsurface
|
||||||
|
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/windows.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/mac.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/ios.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/android.yml)
|
||||||
|
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/linux-snap.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-16.04-5.12-appimage.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/linux-ubuntu-24.04-5.15.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/linux-fedora-35-qt6.yml)
|
||||||

|
[](https://github.com/subsurface/subsurface/actions/workflows/linux-debian-trixie-5.15.yml)
|
||||||
|
|
||||||
This is the README file for Subsurface 5.0.10
|
[](https://scan.coverity.com/projects/subsurface-divelog-subsurface)
|
||||||
|
|
||||||
Please check the `ReleaseNotes.txt` for details about new features and
|
|
||||||
changes since Subsurface 5.0.9 (and earlier versions).
|
|
||||||
|
|
||||||
Subsurface can be found at http://subsurface-divelog.org
|
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
|
License: GPLv2
|
||||||
|
|
||||||
We frequently make new test versions of Subsurface available at
|
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
|
||||||
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
|
|
||||||
posted to the Subsurface-daily repos on Ubuntu Launchpad, Fedora COPR, and
|
posted to the Subsurface-daily repos on Ubuntu Launchpad, Fedora COPR, and
|
||||||
OpenSUSE OBS.
|
OpenSUSE OBS, and released to [Snapcraft](https://snapcraft.io/subsurface) into the 'edge' channel of subsurface.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
You can get the sources to the latest development version from the git
|
You can get the sources to the latest development version from the git
|
||||||
repository:
|
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,
|
You can also fork the repository and browse the sources at the same site,
|
||||||
simply using https://github.com/Subsurface/subsurface
|
simply using https://github.com/Subsurface/subsurface
|
||||||
|
|
||||||
If you want the latest release (instead of the bleeding edge
|
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.
|
||||||
development version) you can either get this via git or the release tar
|
|
||||||
ball. After cloning run the following command:
|
|
||||||
|
|
||||||
```
|
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/).
|
||||||
git checkout v5.0.10 (or whatever the last release is)
|
|
||||||
```
|
|
||||||
|
|
||||||
or download a tarball from http://subsurface-divelog.org/downloads/Subsurface-5.0.10.tgz
|
Detailed build instructions can be found in the [INSTALL.md](/INSTALL.md) file.
|
||||||
|
|
||||||
Detailed build instructions can be found in the INSTALL file.
|
|
||||||
|
|
||||||
## System Requirements
|
## System Requirements
|
||||||
|
|
||||||
|
|||||||
@ -25,15 +25,15 @@ SOURCES += subsurface-mobile-main.cpp \
|
|||||||
core/devicedetails.cpp \
|
core/devicedetails.cpp \
|
||||||
core/downloadfromdcthread.cpp \
|
core/downloadfromdcthread.cpp \
|
||||||
core/qtserialbluetooth.cpp \
|
core/qtserialbluetooth.cpp \
|
||||||
core/plannernotes.c \
|
core/plannernotes.cpp \
|
||||||
core/uemis-downloader.c \
|
core/uemis-downloader.cpp \
|
||||||
core/qthelper.cpp \
|
core/qthelper.cpp \
|
||||||
core/checkcloudconnection.cpp \
|
core/checkcloudconnection.cpp \
|
||||||
core/color.cpp \
|
core/color.cpp \
|
||||||
core/configuredivecomputer.cpp \
|
core/configuredivecomputer.cpp \
|
||||||
core/divelogexportlogic.cpp \
|
core/divelogexportlogic.cpp \
|
||||||
core/divesitehelpers.cpp \
|
core/divesitehelpers.cpp \
|
||||||
core/errorhelper.c \
|
core/errorhelper.cpp \
|
||||||
core/exif.cpp \
|
core/exif.cpp \
|
||||||
core/format.cpp \
|
core/format.cpp \
|
||||||
core/gettextfromc.cpp \
|
core/gettextfromc.cpp \
|
||||||
@ -41,13 +41,14 @@ SOURCES += subsurface-mobile-main.cpp \
|
|||||||
core/qt-init.cpp \
|
core/qt-init.cpp \
|
||||||
core/subsurfacesysinfo.cpp \
|
core/subsurfacesysinfo.cpp \
|
||||||
core/windowtitleupdate.cpp \
|
core/windowtitleupdate.cpp \
|
||||||
core/file.c \
|
core/file.cpp \
|
||||||
core/fulltext.cpp \
|
core/fulltext.cpp \
|
||||||
core/subsurfacestartup.c \
|
core/subsurfacestartup.cpp \
|
||||||
|
core/subsurface-string.cpp \
|
||||||
core/pref.c \
|
core/pref.c \
|
||||||
core/profile.c \
|
core/profile.cpp \
|
||||||
core/device.cpp \
|
core/device.cpp \
|
||||||
core/dive.c \
|
core/dive.cpp \
|
||||||
core/divecomputer.c \
|
core/divecomputer.c \
|
||||||
core/divefilter.cpp \
|
core/divefilter.cpp \
|
||||||
core/event.c \
|
core/event.c \
|
||||||
@ -58,33 +59,33 @@ SOURCES += subsurface-mobile-main.cpp \
|
|||||||
core/divelog.cpp \
|
core/divelog.cpp \
|
||||||
core/gas-model.c \
|
core/gas-model.c \
|
||||||
core/gaspressures.c \
|
core/gaspressures.c \
|
||||||
core/git-access.c \
|
core/git-access.cpp \
|
||||||
core/globals.cpp \
|
core/globals.cpp \
|
||||||
core/liquivision.c \
|
core/liquivision.cpp \
|
||||||
core/load-git.c \
|
core/load-git.cpp \
|
||||||
core/parse-xml.c \
|
core/parse-xml.cpp \
|
||||||
core/parse.c \
|
core/parse.cpp \
|
||||||
core/picture.c \
|
core/picture.c \
|
||||||
core/pictureobj.cpp \
|
core/pictureobj.cpp \
|
||||||
core/sample.c \
|
core/sample.cpp \
|
||||||
core/import-suunto.c \
|
core/import-suunto.cpp \
|
||||||
core/import-shearwater.c \
|
core/import-shearwater.cpp \
|
||||||
core/import-seac.c \
|
core/import-seac.cpp \
|
||||||
core/import-cobalt.c \
|
core/import-cobalt.cpp \
|
||||||
core/import-divinglog.c \
|
core/import-divinglog.cpp \
|
||||||
core/import-csv.c \
|
core/import-csv.cpp \
|
||||||
core/save-html.c \
|
core/save-html.cpp \
|
||||||
core/statistics.c \
|
core/statistics.c \
|
||||||
core/worldmap-save.c \
|
core/worldmap-save.cpp \
|
||||||
core/libdivecomputer.c \
|
core/libdivecomputer.cpp \
|
||||||
core/version.c \
|
core/version.c \
|
||||||
core/save-git.c \
|
core/save-git.cpp \
|
||||||
core/datatrak.c \
|
core/datatrak.cpp \
|
||||||
core/ostctools.c \
|
core/ostctools.c \
|
||||||
core/planner.c \
|
core/planner.cpp \
|
||||||
core/save-xml.c \
|
core/save-xml.cpp \
|
||||||
core/cochran.c \
|
core/cochran.cpp \
|
||||||
core/deco.c \
|
core/deco.cpp \
|
||||||
core/divesite.c \
|
core/divesite.c \
|
||||||
core/equipment.c \
|
core/equipment.c \
|
||||||
core/gas.c \
|
core/gas.c \
|
||||||
@ -93,9 +94,9 @@ SOURCES += subsurface-mobile-main.cpp \
|
|||||||
core/sha1.c \
|
core/sha1.c \
|
||||||
core/string-format.cpp \
|
core/string-format.cpp \
|
||||||
core/strtod.c \
|
core/strtod.c \
|
||||||
core/tag.c \
|
core/tag.cpp \
|
||||||
core/taxonomy.c \
|
core/taxonomy.c \
|
||||||
core/time.c \
|
core/time.cpp \
|
||||||
core/trip.c \
|
core/trip.c \
|
||||||
core/units.c \
|
core/units.c \
|
||||||
core/uemis.c \
|
core/uemis.c \
|
||||||
@ -244,7 +245,6 @@ HEADERS += \
|
|||||||
core/sample.h \
|
core/sample.h \
|
||||||
core/selection.h \
|
core/selection.h \
|
||||||
core/sha1.h \
|
core/sha1.h \
|
||||||
core/strndup.h \
|
|
||||||
core/string-format.h \
|
core/string-format.h \
|
||||||
core/subsurfacestartup.h \
|
core/subsurfacestartup.h \
|
||||||
core/subsurfacesysinfo.h \
|
core/subsurfacesysinfo.h \
|
||||||
|
|||||||
@ -38,6 +38,12 @@
|
|||||||
<dt>DiveSystem</dt><dd><ul>
|
<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>
|
<li>Orca, iDive DAN, iDive Deep, iDive Easy, iDive Free, iDive Pro, iDive Reb, iDive Stealth, iDive Tech, iDive X3M</li></ul>
|
||||||
</dd>
|
</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>
|
<dt>Garmin</dt><dd><ul>
|
||||||
<li>Descent Mk1, Descent Mk2/Mk2i</li></ul>
|
<li>Descent Mk1, Descent Mk2/Mk2i</li></ul>
|
||||||
</dd>
|
</dd>
|
||||||
@ -66,7 +72,7 @@
|
|||||||
<li>S1</li></ul>
|
<li>S1</li></ul>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Ratio</dt><dd><ul>
|
<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>
|
</dd>
|
||||||
<dt>Reefnet</dt><dd><ul>
|
<dt>Reefnet</dt><dd><ul>
|
||||||
<li>Sensus, Sensus Pro, Sensus Ultra</li></ul>
|
<li>Sensus, Sensus Pro, Sensus Ultra</li></ul>
|
||||||
@ -75,7 +81,7 @@
|
|||||||
<li>Alpha</li></ul>
|
<li>Alpha</li></ul>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Scubapro</dt><dd><ul>
|
<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>
|
</dd>
|
||||||
<dt>Seabaer</dt><dd><ul>
|
<dt>Seabaer</dt><dd><ul>
|
||||||
<li>T1, H3, HUDC</li></ul>
|
<li>T1, H3, HUDC</li></ul>
|
||||||
@ -87,7 +93,7 @@
|
|||||||
<li>XP5</li></ul>
|
<li>XP5</li></ul>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Shearwater</dt><dd><ul>
|
<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>
|
</dd>
|
||||||
<dt>Sherwood</dt><dd><ul>
|
<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>
|
<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>
|
<li>DiveComputer.eu</li></ul>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Tusa</dt><dd><ul>
|
<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>
|
</dd>
|
||||||
<dt>Uemis</dt><dd><ul>
|
<dt>Uemis</dt><dd><ul>
|
||||||
<li>Zürich SDA</li></ul>
|
<li>Zürich SDA</li></ul>
|
||||||
|
|||||||
@ -12,6 +12,8 @@ Deep Six: Excursion
|
|||||||
Deepblu: Cosmiq+
|
Deepblu: Cosmiq+
|
||||||
Dive Rite: NiTek Q, NiTek Trio
|
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
|
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
|
Garmin: Descent Mk1, Descent Mk2/Mk2i
|
||||||
Genesis: Centauri, React Pro, React Pro White
|
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
|
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
|
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
|
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
|
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
|
Reefnet: Sensus, Sensus Pro, Sensus Ultra
|
||||||
Scorpena: Alpha
|
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
|
Seabaer: T1, H3, HUDC
|
||||||
Seac: Action, Guru, Jack, Screen
|
Seac: Action, Guru, Jack, Screen
|
||||||
Seemann: XP5
|
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
|
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
|
Sporasub: SP2
|
||||||
Subgear: XP Air, XP-10, XP-3G, XP-Air
|
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
|
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
|
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
|
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
|
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
|
Zeagle: N2iTiON3
|
||||||
@ -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");
|
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\\%scomputer{%s}\n", ssrf, dive->dc.model);
|
||||||
put_format(&buf, "\\def\\%scountry{%s}\n", ssrf, country ?: "");
|
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");
|
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);
|
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->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);
|
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;
|
std::string tags = taglist_get_tagstring(dive->tag_list);
|
||||||
QString tags;
|
put_format(&buf, "\\def\\%stype{%s}\n", ssrf, tags.c_str());
|
||||||
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));
|
|
||||||
put_format(&buf, "\\def\\%sviz{%s}\n", ssrf, qPrintable(viz));
|
put_format(&buf, "\\def\\%sviz{%s}\n", ssrf, qPrintable(viz));
|
||||||
put_format(&buf, "\\def\\%srating{%s}\n", ssrf, qPrintable(rating));
|
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);
|
put_format(&buf, "\\def\\%splot{\\includegraphics[width=9cm,height=4cm]{profile%d}}\n", ssrf, dive->number);
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
|
|
||||||
execute_process(
|
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}
|
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
|
||||||
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_4
|
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_4
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
execute_process(
|
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}
|
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
|
||||||
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_3
|
OUTPUT_VARIABLE CANONICAL_VERSION_STRING_3
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
execute_process(
|
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}
|
WORKING_DIRECTORY ${CMAKE_TOP_SRC_DIR}
|
||||||
OUTPUT_VARIABLE CANONICAL_VERSION_STRING
|
OUTPUT_VARIABLE CANONICAL_VERSION_STRING
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
|||||||
@ -100,6 +100,7 @@ enum class EditProfileType {
|
|||||||
ADD,
|
ADD,
|
||||||
REMOVE,
|
REMOVE,
|
||||||
MOVE,
|
MOVE,
|
||||||
|
EDIT,
|
||||||
};
|
};
|
||||||
void replanDive(dive *d); // dive computer(s) and cylinder(s) of first argument will be consumed!
|
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);
|
void editProfile(const dive *d, int dcNr, EditProfileType type, int count);
|
||||||
|
|||||||
@ -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
|
// When encountering filter presets with equal names, check whether they are
|
||||||
// the same. If they are, ignore them.
|
// the same. If they are, ignore them.
|
||||||
for (const filter_preset &preset: *log->filter_presets) {
|
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(),
|
auto it = std::find_if(divelog.filter_presets->begin(), divelog.filter_presets->end(),
|
||||||
[&name](const filter_preset &preset) { return preset.name == name; });
|
[&name](const filter_preset &preset) { return preset.name == name; });
|
||||||
if (it != divelog.filter_presets->end() && it->data == preset.data)
|
if (it != divelog.filter_presets->end() && it->data == preset.data)
|
||||||
continue;
|
continue;
|
||||||
filterPresetsToAdd.emplace_back(preset.name, preset.data);
|
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()
|
bool ImportDives::workToBeDone()
|
||||||
@ -580,7 +585,7 @@ void ImportDives::undoit()
|
|||||||
// Remove filter presets. Do this in reverse order.
|
// Remove filter presets. Do this in reverse order.
|
||||||
for (auto it = filterPresetsToRemove.rbegin(); it != filterPresetsToRemove.rend(); ++it) {
|
for (auto it = filterPresetsToRemove.rbegin(); it != filterPresetsToRemove.rend(); ++it) {
|
||||||
int index = *it;
|
int index = *it;
|
||||||
QString oldName = filter_preset_name_qstring(index);
|
std::string oldName = filter_preset_name(index);
|
||||||
FilterData oldData = filter_preset_get(index);
|
FilterData oldData = filter_preset_get(index);
|
||||||
filter_preset_delete(index);
|
filter_preset_delete(index);
|
||||||
emit diveListNotifier.filterPresetRemoved(index);
|
emit diveListNotifier.filterPresetRemoved(index);
|
||||||
|
|||||||
@ -112,7 +112,7 @@ private:
|
|||||||
|
|
||||||
// For redo
|
// For redo
|
||||||
std::vector<OwningDiveSitePtr> sitesToAdd;
|
std::vector<OwningDiveSitePtr> sitesToAdd;
|
||||||
std::vector<std::pair<QString,FilterData>>
|
std::vector<std::pair<std::string,FilterData>>
|
||||||
filterPresetsToAdd;
|
filterPresetsToAdd;
|
||||||
|
|
||||||
// For undo
|
// For undo
|
||||||
|
|||||||
@ -566,7 +566,7 @@ QStringList EditTags::data(struct dive *d) const
|
|||||||
{
|
{
|
||||||
QStringList res;
|
QStringList res;
|
||||||
for (const struct tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -879,6 +879,7 @@ QString editProfileTypeToString(EditProfileType type, int count)
|
|||||||
case EditProfileType::ADD: return Command::Base::tr("Add stop");
|
case EditProfileType::ADD: return Command::Base::tr("Add stop");
|
||||||
case EditProfileType::REMOVE: return Command::Base::tr("Remove %n stop(s)", "", count);
|
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::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_samples(sdc, &dc);
|
||||||
copy_events(sdc, &dc);
|
copy_events(sdc, &dc);
|
||||||
|
|
||||||
setText(editProfileTypeToString(type, count) + diveNumberOrDate(d));
|
setText(editProfileTypeToString(type, count) + " " + diveNumberOrDate(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
EditProfile::~EditProfile()
|
EditProfile::~EditProfile()
|
||||||
@ -925,6 +926,7 @@ void EditProfile::undo()
|
|||||||
std::swap(sdc->samples, dc.samples);
|
std::swap(sdc->samples, dc.samples);
|
||||||
std::swap(sdc->alloc_samples, dc.alloc_samples);
|
std::swap(sdc->alloc_samples, dc.alloc_samples);
|
||||||
std::swap(sdc->sample, dc.sample);
|
std::swap(sdc->sample, dc.sample);
|
||||||
|
std::swap(sdc->events, dc.events);
|
||||||
std::swap(sdc->maxdepth, dc.maxdepth);
|
std::swap(sdc->maxdepth, dc.maxdepth);
|
||||||
std::swap(d->maxdepth, maxdepth);
|
std::swap(d->maxdepth, maxdepth);
|
||||||
std::swap(d->meandepth, meandepth);
|
std::swap(d->meandepth, meandepth);
|
||||||
@ -1090,11 +1092,6 @@ EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
|
|||||||
dives.clear();
|
dives.clear();
|
||||||
return;
|
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()
|
EditWeight::~EditWeight()
|
||||||
@ -1105,6 +1102,7 @@ EditWeight::~EditWeight()
|
|||||||
void EditWeight::redo()
|
void EditWeight::redo()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < dives.size(); ++i) {
|
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);
|
set_weightsystem(dives[i], indices[i], new_ws);
|
||||||
emit diveListNotifier.weightEdited(dives[i], indices[i]);
|
emit diveListNotifier.weightEdited(dives[i], indices[i]);
|
||||||
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
|
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"));
|
setText(Command::Base::tr("Add cylinder"));
|
||||||
else
|
else
|
||||||
setText(Command::Base::tr("Add cylinder (%n dive(s))", "", dives.size()));
|
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());
|
indexes.reserve(dives.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1293,24 +1291,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
|
|||||||
else
|
else
|
||||||
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
|
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
|
||||||
|
|
||||||
// Try to untranslate the cylinder type
|
|
||||||
QString description = cylIn.type.description;
|
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
|
// The base class copied the cylinders for us, let's edit them
|
||||||
for (int i = 0; i < (int)indexes.size(); ++i) {
|
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()
|
void EditCylinder::redo()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < dives.size(); ++i) {
|
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]);
|
std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]);
|
||||||
update_cylinder_related_info(dives[i]);
|
update_cylinder_related_info(dives[i]);
|
||||||
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
|
emit diveListNotifier.cylinderEdited(dives[i], indexes[i]);
|
||||||
@ -1358,7 +1340,6 @@ EditSensors::EditSensors(int toCylinderIn, int fromCylinderIn, int dcNr)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
setText(Command::Base::tr("Edit sensors"));
|
setText(Command::Base::tr("Edit sensors"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditSensors::mapSensors(int toCyl, int fromCyl)
|
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;
|
changedFields |= DiveField::CHILL;
|
||||||
if (!same_string(oldDive->suit, newDive->suit))
|
if (!same_string(oldDive->suit, newDive->suit))
|
||||||
changedFields |= DiveField::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;
|
changedFields |= DiveField::TAGS;
|
||||||
if (oldDive->dc.divemode != newDive->dc.divemode)
|
if (oldDive->dc.divemode != newDive->dc.divemode)
|
||||||
changedFields |= DiveField::MODE;
|
changedFields |= DiveField::MODE;
|
||||||
|
|||||||
@ -6,16 +6,16 @@
|
|||||||
|
|
||||||
namespace Command {
|
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);
|
int index = filter_preset_add(name, data);
|
||||||
emit diveListNotifier.filterPresetAdded(index);
|
emit diveListNotifier.filterPresetAdded(index);
|
||||||
return 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);
|
FilterData oldData = filter_preset_get(index);
|
||||||
filter_preset_delete(index);
|
filter_preset_delete(index);
|
||||||
emit diveListNotifier.filterPresetRemoved(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) :
|
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));
|
setText(Command::Base::tr("Create filter preset %1").arg(nameIn));
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ void CreateFilterPreset::undo()
|
|||||||
|
|
||||||
RemoveFilterPreset::RemoveFilterPreset(int indexIn) : index(indexIn)
|
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()
|
bool RemoveFilterPreset::workToBeDone()
|
||||||
@ -68,7 +68,7 @@ void RemoveFilterPreset::undo()
|
|||||||
EditFilterPreset::EditFilterPreset(int indexIn, const FilterData &dataIn) :
|
EditFilterPreset::EditFilterPreset(int indexIn, const FilterData &dataIn) :
|
||||||
index(indexIn), data(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()
|
bool EditFilterPreset::workToBeDone()
|
||||||
|
|||||||
@ -17,7 +17,7 @@ public:
|
|||||||
CreateFilterPreset(const QString &name, const FilterData &data);
|
CreateFilterPreset(const QString &name, const FilterData &data);
|
||||||
private:
|
private:
|
||||||
// for redo
|
// for redo
|
||||||
QString name;
|
std::string name;
|
||||||
FilterData data;
|
FilterData data;
|
||||||
|
|
||||||
// for undo
|
// for undo
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
RemoveFilterPreset(int index);
|
RemoveFilterPreset(int index);
|
||||||
private:
|
private:
|
||||||
// for undo
|
// for undo
|
||||||
QString name;
|
std::string name;
|
||||||
FilterData data;
|
FilterData data;
|
||||||
|
|
||||||
// for redo
|
// for redo
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
#include "command_pictures.h"
|
#include "command_pictures.h"
|
||||||
|
#include "core/errorhelper.h"
|
||||||
#include "core/subsurface-qt/divelistnotifier.h"
|
#include "core/subsurface-qt/divelistnotifier.h"
|
||||||
#include "qt-models/divelocationmodel.h"
|
#include "qt-models/divelocationmodel.h"
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ void SetPictureOffset::redo()
|
|||||||
{
|
{
|
||||||
picture *pic = dive_get_picture(d, filename);
|
picture *pic = dive_get_picture(d, filename);
|
||||||
if (!pic) {
|
if (!pic) {
|
||||||
fprintf(stderr, "SetPictureOffset::redo(): picture disappeared!\n");
|
report_info("SetPictureOffset::redo(): picture disappeared!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::swap(pic->offset, offset);
|
std::swap(pic->offset, offset);
|
||||||
@ -73,7 +74,7 @@ static std::vector<PictureListForAddition> removePictures(std::vector<PictureLis
|
|||||||
for (const std::string &fn: list.filenames) {
|
for (const std::string &fn: list.filenames) {
|
||||||
int idx = get_picture_idx(&list.d->pictures, fn.c_str());
|
int idx = get_picture_idx(&list.d->pictures, fn.c_str());
|
||||||
if (idx < 0) {
|
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.
|
continue; // Huh? We made sure that this can't happen by filtering out non-existent pictures.
|
||||||
}
|
}
|
||||||
filenames.push_back(QString::fromStdString(fn));
|
filenames.push_back(QString::fromStdString(fn));
|
||||||
@ -103,7 +104,7 @@ static std::vector<PictureListForDeletion> addPictures(std::vector<PictureListFo
|
|||||||
for (const PictureObj &pic: list.pics) {
|
for (const PictureObj &pic: list.pics) {
|
||||||
int idx = get_picture_idx(&list.d->pictures, pic.filename.c_str()); // This should *not* already exist!
|
int idx = get_picture_idx(&list.d->pictures, pic.filename.c_str()); // This should *not* already exist!
|
||||||
if (idx >= 0) {
|
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.
|
continue; // Huh? We made sure that this can't happen by filtering out existing pictures.
|
||||||
}
|
}
|
||||||
picsForSignal.push_back(pic);
|
picsForSignal.push_back(pic);
|
||||||
|
|||||||
@ -41,7 +41,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
checkcloudconnection.h
|
checkcloudconnection.h
|
||||||
cloudstorage.cpp
|
cloudstorage.cpp
|
||||||
cloudstorage.h
|
cloudstorage.h
|
||||||
cochran.c
|
cochran.cpp
|
||||||
cochran.h
|
cochran.h
|
||||||
color.cpp
|
color.cpp
|
||||||
color.h
|
color.h
|
||||||
@ -51,15 +51,15 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
configuredivecomputerthreads.h
|
configuredivecomputerthreads.h
|
||||||
connectionlistmodel.cpp
|
connectionlistmodel.cpp
|
||||||
connectionlistmodel.h
|
connectionlistmodel.h
|
||||||
datatrak.c
|
datatrak.cpp
|
||||||
datatrak.h
|
datatrak.h
|
||||||
deco.c
|
deco.cpp
|
||||||
deco.h
|
deco.h
|
||||||
device.cpp
|
device.cpp
|
||||||
device.h
|
device.h
|
||||||
devicedetails.cpp
|
devicedetails.cpp
|
||||||
devicedetails.h
|
devicedetails.h
|
||||||
dive.c
|
dive.cpp
|
||||||
dive.h
|
dive.h
|
||||||
divecomputer.c
|
divecomputer.c
|
||||||
divecomputer.h
|
divecomputer.h
|
||||||
@ -85,11 +85,11 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
eventtype.h
|
eventtype.h
|
||||||
equipment.c
|
equipment.c
|
||||||
equipment.h
|
equipment.h
|
||||||
errorhelper.c
|
errorhelper.cpp
|
||||||
exif.cpp
|
exif.cpp
|
||||||
exif.h
|
exif.h
|
||||||
extradata.h
|
extradata.h
|
||||||
file.c
|
file.cpp
|
||||||
file.h
|
file.h
|
||||||
filterconstraint.cpp
|
filterconstraint.cpp
|
||||||
filterconstraint.h
|
filterconstraint.h
|
||||||
@ -107,24 +107,24 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
gettext.h
|
gettext.h
|
||||||
gettextfromc.cpp
|
gettextfromc.cpp
|
||||||
gettextfromc.h
|
gettextfromc.h
|
||||||
git-access.c
|
git-access.cpp
|
||||||
git-access.h
|
git-access.h
|
||||||
globals.cpp
|
globals.cpp
|
||||||
globals.h
|
globals.h
|
||||||
imagedownloader.cpp
|
imagedownloader.cpp
|
||||||
imagedownloader.h
|
imagedownloader.h
|
||||||
import-cobalt.c
|
import-cobalt.cpp
|
||||||
import-csv.c
|
import-csv.cpp
|
||||||
import-csv.h
|
import-csv.h
|
||||||
import-divinglog.c
|
import-divinglog.cpp
|
||||||
import-shearwater.c
|
import-shearwater.cpp
|
||||||
import-suunto.c
|
import-suunto.cpp
|
||||||
import-seac.c
|
import-seac.cpp
|
||||||
interpolate.h
|
interpolate.h
|
||||||
libdivecomputer.c
|
libdivecomputer.cpp
|
||||||
libdivecomputer.h
|
libdivecomputer.h
|
||||||
liquivision.c
|
liquivision.cpp
|
||||||
load-git.c
|
load-git.cpp
|
||||||
membuffer.cpp
|
membuffer.cpp
|
||||||
membuffer.h
|
membuffer.h
|
||||||
metadata.cpp
|
metadata.cpp
|
||||||
@ -134,32 +134,32 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
ostctools.c
|
ostctools.c
|
||||||
owning_ptrs.h
|
owning_ptrs.h
|
||||||
parse-gpx.cpp
|
parse-gpx.cpp
|
||||||
parse-xml.c
|
parse-xml.cpp
|
||||||
parse.c
|
parse.cpp
|
||||||
parse.h
|
parse.h
|
||||||
picture.c
|
picture.c
|
||||||
picture.h
|
picture.h
|
||||||
pictureobj.cpp
|
pictureobj.cpp
|
||||||
pictureobj.h
|
pictureobj.h
|
||||||
planner.c
|
planner.cpp
|
||||||
planner.h
|
planner.h
|
||||||
plannernotes.c
|
plannernotes.cpp
|
||||||
pref.h
|
pref.h
|
||||||
pref.c
|
pref.c
|
||||||
profile.c
|
profile.cpp
|
||||||
profile.h
|
profile.h
|
||||||
qt-gui.h
|
qt-gui.h
|
||||||
qt-init.cpp
|
qt-init.cpp
|
||||||
qthelper.cpp
|
qthelper.cpp
|
||||||
qthelper.h
|
qthelper.h
|
||||||
range.h
|
range.h
|
||||||
sample.c
|
sample.cpp
|
||||||
sample.h
|
sample.h
|
||||||
save-git.c
|
save-git.cpp
|
||||||
save-html.c
|
save-html.cpp
|
||||||
save-html.h
|
save-html.h
|
||||||
save-profiledata.c
|
save-profiledata.c
|
||||||
save-xml.c
|
save-xml.cpp
|
||||||
selection.cpp
|
selection.cpp
|
||||||
selection.h
|
selection.h
|
||||||
sha1.c
|
sha1.c
|
||||||
@ -167,26 +167,26 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
ssrf.h
|
ssrf.h
|
||||||
statistics.c
|
statistics.c
|
||||||
statistics.h
|
statistics.h
|
||||||
strndup.h
|
|
||||||
string-format.h
|
string-format.h
|
||||||
string-format.cpp
|
string-format.cpp
|
||||||
strtod.c
|
strtod.c
|
||||||
subsurface-float.h
|
subsurface-float.h
|
||||||
|
subsurface-string.cpp
|
||||||
subsurface-string.h
|
subsurface-string.h
|
||||||
subsurfacestartup.c
|
subsurfacestartup.cpp
|
||||||
subsurfacestartup.h
|
subsurfacestartup.h
|
||||||
subsurfacesysinfo.cpp
|
subsurfacesysinfo.cpp
|
||||||
subsurfacesysinfo.h
|
subsurfacesysinfo.h
|
||||||
tag.c
|
tag.cpp
|
||||||
tag.h
|
tag.h
|
||||||
taxonomy.c
|
taxonomy.c
|
||||||
taxonomy.h
|
taxonomy.h
|
||||||
time.c
|
time.cpp
|
||||||
timer.c
|
timer.c
|
||||||
timer.h
|
timer.h
|
||||||
trip.c
|
trip.c
|
||||||
trip.h
|
trip.h
|
||||||
uemis-downloader.c
|
uemis-downloader.cpp
|
||||||
uemis.c
|
uemis.c
|
||||||
uemis.h
|
uemis.h
|
||||||
units.h
|
units.h
|
||||||
@ -203,7 +203,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||||||
windowtitleupdate.cpp
|
windowtitleupdate.cpp
|
||||||
windowtitleupdate.h
|
windowtitleupdate.h
|
||||||
worldmap-options.h
|
worldmap-options.h
|
||||||
worldmap-save.c
|
worldmap-save.cpp
|
||||||
worldmap-save.h
|
worldmap-save.h
|
||||||
xmlparams.cpp
|
xmlparams.cpp
|
||||||
xmlparams.h
|
xmlparams.h
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#include "btdiscovery.h"
|
#include "btdiscovery.h"
|
||||||
#include "downloadfromdcthread.h"
|
#include "downloadfromdcthread.h"
|
||||||
#include "core/libdivecomputer.h"
|
#include "libdivecomputer.h"
|
||||||
|
#include "errorhelper.h"
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QDebug>
|
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
@ -62,6 +62,7 @@ static struct namePattern name[] = {
|
|||||||
{ "NERD 2", "Shearwater", "NERD 2" },
|
{ "NERD 2", "Shearwater", "NERD 2" },
|
||||||
{ "NERD", "Shearwater", "NERD" }, // order is important, test for the more specific one first
|
{ "NERD", "Shearwater", "NERD" }, // order is important, test for the more specific one first
|
||||||
{ "Predator", "Shearwater", "Predator" },
|
{ "Predator", "Shearwater", "Predator" },
|
||||||
|
{ "Tern", "Shearwater", "Tern" },
|
||||||
// Suunto dive computers
|
// Suunto dive computers
|
||||||
{ "EON Steel", "Suunto", "EON Steel" },
|
{ "EON Steel", "Suunto", "EON Steel" },
|
||||||
{ "EON Core", "Suunto", "EON Core" },
|
{ "EON Core", "Suunto", "EON Core" },
|
||||||
@ -69,9 +70,12 @@ static struct namePattern name[] = {
|
|||||||
// Scubapro dive computers
|
// Scubapro dive computers
|
||||||
{ "G2", "Scubapro", "G2" },
|
{ "G2", "Scubapro", "G2" },
|
||||||
{ "HUD", "Scubapro", "G2 HUD" },
|
{ "HUD", "Scubapro", "G2 HUD" },
|
||||||
|
{ "G3", "Scubapro", "G3" },
|
||||||
{ "Aladin", "Scubapro", "Aladin Sport Matrix" },
|
{ "Aladin", "Scubapro", "Aladin Sport Matrix" },
|
||||||
{ "A1", "Scubapro", "Aladin A1" },
|
{ "A1", "Scubapro", "Aladin A1" },
|
||||||
{ "A2", "Scubapro", "Aladin A2" },
|
{ "A2", "Scubapro", "Aladin A2" },
|
||||||
|
{ "Luna 2.0 AI", "Scubapro", "Luna 2.0 AI" },
|
||||||
|
{ "Luna 2.0", "Scubapro", "Luna 2.0" },
|
||||||
// Mares dive computers
|
// Mares dive computers
|
||||||
{ "Mares Genius", "Mares", "Genius" },
|
{ "Mares Genius", "Mares", "Genius" },
|
||||||
{ "Mares", "Mares", "Quad" }, // we actually don't know and just pick a common one - user needs to fix in UI
|
{ "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)
|
discoveryAgent(nullptr)
|
||||||
{
|
{
|
||||||
if (m_instance) {
|
if (m_instance) {
|
||||||
qDebug() << "trying to create an additional BTDiscovery object";
|
report_info("trying to create an additional BTDiscovery object");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
@ -191,11 +195,11 @@ void BTDiscovery::showNonDiveComputers(bool show)
|
|||||||
void BTDiscovery::BTDiscoveryReDiscover()
|
void BTDiscovery::BTDiscoveryReDiscover()
|
||||||
{
|
{
|
||||||
#if !defined(Q_OS_IOS)
|
#if !defined(Q_OS_IOS)
|
||||||
qDebug() << "BTDiscoveryReDiscover: localBtDevice.isValid()" << localBtDevice.isValid();
|
report_info("BTDiscoveryReDiscover: localBtDevice.isValid() %d", localBtDevice.isValid());
|
||||||
if (localBtDevice.isValid() &&
|
if (localBtDevice.isValid() &&
|
||||||
localBtDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
|
localBtDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
|
||||||
btPairedDevices.clear();
|
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
|
#else
|
||||||
// for iOS we can't use the localBtDevice as iOS is BLE only
|
// 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
|
// 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),
|
connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
|
||||||
#endif
|
#endif
|
||||||
[this](QBluetoothDeviceDiscoveryAgent::Error error){
|
[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)
|
#if defined(Q_OS_ANDROID)
|
||||||
// on Android, we cannot scan for classic devices - we just get the paired ones
|
// 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);
|
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
|
||||||
getBluetoothDevices();
|
getBluetoothDevices();
|
||||||
// and add the paired devices to the internal data
|
// and add the paired devices to the internal data
|
||||||
@ -231,10 +235,10 @@ void BTDiscovery::BTDiscoveryReDiscover()
|
|||||||
for (int i = 0; i < btPairedDevices.length(); i++)
|
for (int i = 0; i < btPairedDevices.length(); i++)
|
||||||
btDeviceDiscoveredMain(btPairedDevices[i], true);
|
btDeviceDiscoveredMain(btPairedDevices[i], true);
|
||||||
#else
|
#else
|
||||||
qDebug() << "starting BT/BLE discovery";
|
report_info("starting BT/BLE discovery");
|
||||||
discoveryAgent->start();
|
discoveryAgent->start();
|
||||||
for (int i = 0; i < btPairedDevices.length(); i++)
|
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
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_IOS) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
#if defined(Q_OS_IOS) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
||||||
@ -244,7 +248,7 @@ void BTDiscovery::BTDiscoveryReDiscover()
|
|||||||
timer.start(3000);
|
timer.start(3000);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "localBtDevice isn't valid or not connectable";
|
report_info("localBtDevice isn't valid or not connectable");
|
||||||
m_btValid = false;
|
m_btValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,10 +291,10 @@ QString markBLEAddress(const QBluetoothDeviceInfo *device)
|
|||||||
|
|
||||||
void BTDiscovery::btDeviceDiscoveryFinished()
|
void BTDiscovery::btDeviceDiscoveryFinished()
|
||||||
{
|
{
|
||||||
qDebug() << "BT/BLE finished discovery";
|
report_info("BT/BLE finished discovery");
|
||||||
QList<QBluetoothDeviceInfo> devList = discoveryAgent->discoveredDevices();
|
QList<QBluetoothDeviceInfo> devList = discoveryAgent->discoveredDevices();
|
||||||
for (QBluetoothDeviceInfo device: devList) {
|
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();
|
const auto serviceUuids = device.serviceUuids();
|
||||||
for (QBluetoothUuid id: serviceUuids) {
|
for (QBluetoothUuid id: serviceUuids) {
|
||||||
addBtUuid(id);
|
addBtUuid(id);
|
||||||
qDebug() << id.toByteArray();
|
report_info("%s", qPrintable(id.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_IOS) || defined(Q_OS_MACOS) || defined(Q_OS_WIN)
|
#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);
|
msg = QString("%1 device: '%2' [%3]: ").arg(fromPaired ? "Paired" : "Discovered new").arg(newDevice).arg(device.address);
|
||||||
if (newDC) {
|
if (newDC) {
|
||||||
QString vendor = dc_descriptor_get_vendor(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.btpdi = device;
|
||||||
btVP.dcDescriptor = newDC;
|
btVP.dcDescriptor = newDC;
|
||||||
btVP.vendorIdx = vendorList.indexOf(vendor);
|
btVP.vendorIdx = vendorList.indexOf(vendor);
|
||||||
@ -348,7 +352,7 @@ void BTDiscovery::btDeviceDiscoveredMain(const btPairedDevice &device, bool from
|
|||||||
newDevice += " ";
|
newDevice += " ";
|
||||||
connectionListModel.addAddress(newDevice + device.address);
|
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()
|
QList<BTDiscovery::btVendorProduct> BTDiscovery::getBtDcs()
|
||||||
@ -403,12 +407,12 @@ void BTDiscovery::getBluetoothDevices()
|
|||||||
result.address = dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString();
|
result.address = dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString();
|
||||||
result.name = dev.callObjectMethod("getName", "()Ljava/lang/String;").toString();
|
result.name = dev.callObjectMethod("getName", "()Ljava/lang/String;").toString();
|
||||||
if (btType & 1) { // DEVICE_TYPE_CLASSIC
|
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);
|
btPairedDevices.append(result);
|
||||||
}
|
}
|
||||||
if (btType & 2) { // DEVICE_TYPE_LE
|
if (btType & 2) { // DEVICE_TYPE_LE
|
||||||
result.address = QString("LE:%1").arg(result.address);
|
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);
|
btPairedDevices.append(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +451,7 @@ void BTDiscovery::discoverAddress(QString address)
|
|||||||
btAddress = extractBluetoothAddress(address);
|
btAddress = extractBluetoothAddress(address);
|
||||||
|
|
||||||
if (!btDeviceInfo.keys().contains(address) && !discoveryAgent->isActive()) {
|
if (!btDeviceInfo.keys().contains(address) && !discoveryAgent->isActive()) {
|
||||||
qDebug() << "restarting discovery agent";
|
report_info("restarting discovery agent");
|
||||||
discoveryAgent->start();
|
discoveryAgent->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,7 +460,7 @@ void BTDiscovery::stopAgent()
|
|||||||
{
|
{
|
||||||
if (!discoveryAgent)
|
if (!discoveryAgent)
|
||||||
return;
|
return;
|
||||||
qDebug() << "---> stopping the discovery agent";
|
report_info("---> stopping the discovery agent");
|
||||||
discoveryAgent->stop();
|
discoveryAgent->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +491,7 @@ QString extractBluetoothNameAddress(const QString &address, QString &name)
|
|||||||
name = m.captured(1).trimmed();
|
name = m.captured(1).trimmed();
|
||||||
return extractedAddress;
|
return extractedAddress;
|
||||||
}
|
}
|
||||||
qDebug() << "can't parse address" << address;
|
report_info("can't parse address %s", qPrintable(address));
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +507,7 @@ QBluetoothDeviceInfo getBtDeviceInfo(const QString &devaddr)
|
|||||||
return btDeviceInfo[devaddr];
|
return btDeviceInfo[devaddr];
|
||||||
}
|
}
|
||||||
if(!btDeviceInfo.keys().contains(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
|
// wait for a maximum of 30 more seconds
|
||||||
// yes, that seems crazy, but on my Mac I see this take more than 20 seconds
|
// yes, that seems crazy, but on my Mac I see this take more than 20 seconds
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
@ -517,7 +521,7 @@ QBluetoothDeviceInfo getBtDeviceInfo(const QString &devaddr)
|
|||||||
QThread::msleep(100);
|
QThread::msleep(100);
|
||||||
} while (timer.elapsed() < 30000);
|
} 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();
|
return QBluetoothDeviceInfo();
|
||||||
}
|
}
|
||||||
#endif // BT_SUPPORT
|
#endif // BT_SUPPORT
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "qthelper.h"
|
#include "qthelper.h"
|
||||||
#include "git-access.h"
|
#include "git-access.h"
|
||||||
#include "errorhelper.h"
|
#include "errorhelper.h"
|
||||||
|
#include "core/format.h"
|
||||||
#include "core/subsurface-string.h"
|
#include "core/subsurface-string.h"
|
||||||
#include "core/membuffer.h"
|
#include "core/membuffer.h"
|
||||||
#include "core/settings/qPrefCloudStorage.h"
|
#include "core/settings/qPrefCloudStorage.h"
|
||||||
@ -34,7 +35,7 @@ CheckCloudConnection::CheckCloudConnection(QObject *parent) :
|
|||||||
bool CheckCloudConnection::checkServer()
|
bool CheckCloudConnection::checkServer()
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "Checking cloud connection...\n");
|
report_info("Checking cloud connection...");
|
||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QNetworkAccessManager *mgr = new QNetworkAccessManager();
|
QNetworkAccessManager *mgr = new QNetworkAccessManager();
|
||||||
@ -72,10 +73,10 @@ bool CheckCloudConnection::checkServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose)
|
if (verbose)
|
||||||
qDebug() << "connection test to cloud server" << prefs.cloud_base_url << "failed" <<
|
report_info("connection test to cloud server %s failed %d %s %d %s", prefs.cloud_base_url,
|
||||||
reply->error() << reply->errorString() <<
|
static_cast<int>(reply->error()), qPrintable(reply->errorString()),
|
||||||
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() <<
|
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),
|
||||||
reply->readAll();
|
qPrintable(reply->readAll()));
|
||||||
} while (nextServer());
|
} while (nextServer());
|
||||||
// if none of the servers was reachable, update the user and switch to git_local_only
|
// 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")));
|
git_storage_update_progress(qPrintable(tr("Cloud connection failed")));
|
||||||
@ -89,9 +90,9 @@ bool CheckCloudConnection::checkServer()
|
|||||||
|
|
||||||
void CheckCloudConnection::sslErrors(const QList<QSslError> &errorList)
|
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)
|
for (QSslError err: errorList)
|
||||||
qDebug() << err.errorString();
|
report_info("%s", qPrintable(err.errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckCloudConnection::nextServer()
|
bool CheckCloudConnection::nextServer()
|
||||||
@ -119,12 +120,12 @@ bool CheckCloudConnection::nextServer()
|
|||||||
strcpy(baseurl, "https://");
|
strcpy(baseurl, "https://");
|
||||||
strncat(baseurl, server, s);
|
strncat(baseurl, server, s);
|
||||||
strcat(baseurl, "/");
|
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;
|
prefs.cloud_base_url = baseurl;
|
||||||
git_storage_update_progress(qPrintable(tr("Trying different cloud server...")));
|
git_storage_update_progress(qPrintable(tr("Trying different cloud server...")));
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +144,7 @@ void CheckCloudConnection::gotIP(QNetworkReply *reply)
|
|||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
// whatever, just use the default host
|
// whatever, just use the default host
|
||||||
if (verbose)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
QString addressString = reply->readAll();
|
QString addressString = reply->readAll();
|
||||||
@ -153,11 +154,11 @@ void CheckCloudConnection::gotIP(QNetworkReply *reply)
|
|||||||
if (addr.isNull()) {
|
if (addr.isNull()) {
|
||||||
// this isn't an address, don't try to update the cloud host
|
// this isn't an address, don't try to update the cloud host
|
||||||
if (verbose)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (verbose)
|
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
|
// now figure out which continent we are on
|
||||||
QNetworkRequest request(QString(GET_CONTINENT_API).arg(addressString));
|
QNetworkRequest request(QString(GET_CONTINENT_API).arg(addressString));
|
||||||
request.setRawHeader("Accept", "text/plain");
|
request.setRawHeader("Accept", "text/plain");
|
||||||
@ -172,7 +173,7 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
|
|||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
// whatever, just use the default host
|
// whatever, just use the default host
|
||||||
if (verbose)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
QString continentString = reply->readAll();
|
QString continentString = reply->readAll();
|
||||||
@ -193,7 +194,7 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
|
|||||||
base_url = "https://" CLOUD_HOST_EU "/";
|
base_url = "https://" CLOUD_HOST_EU "/";
|
||||||
if (!same_string(base_url, prefs.cloud_base_url)) {
|
if (!same_string(base_url, prefs.cloud_base_url)) {
|
||||||
if (verbose)
|
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);
|
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)
|
extern "C" bool canReachCloudServer(struct git_info *info)
|
||||||
{
|
{
|
||||||
if (verbose)
|
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();
|
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
|
// 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 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/..."
|
// 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);
|
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)
|
if (verbose)
|
||||||
qDebug() << "updating remote to: " << newremote;
|
report_info("updating remote to: %s", info->url.c_str());
|
||||||
free((void*)info->url);
|
}
|
||||||
info->url = newremote;
|
|
||||||
}
|
}
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,31 +74,30 @@ QNetworkReply* CloudStorageAuthenticate::deleteAccount(const QString& email, con
|
|||||||
|
|
||||||
void CloudStorageAuthenticate::deleteFinished()
|
void CloudStorageAuthenticate::deleteFinished()
|
||||||
{
|
{
|
||||||
QString cloudAuthReply(reply->readAll());
|
std::string cloudAuthReply = reply->readAll().toStdString();
|
||||||
qDebug() << "Completed connection with cloud storage backend, response" << cloudAuthReply;
|
report_info("Completed connection with cloud storage backend, response %s", cloudAuthReply.c_str());
|
||||||
emit finishedDelete();
|
emit finishedDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudStorageAuthenticate::uploadFinished()
|
void CloudStorageAuthenticate::uploadFinished()
|
||||||
{
|
{
|
||||||
static QString myLastError;
|
static std::string myLastError;
|
||||||
|
|
||||||
QString cloudAuthReply(reply->readAll());
|
std::string cloudAuthReply = reply->readAll().toStdString();
|
||||||
qDebug() << "Completed connection with cloud storage backend, response" << cloudAuthReply;
|
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);
|
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_VERIFIED);
|
||||||
/* TODO: Move this to a correct place
|
/* TODO: Move this to a correct place
|
||||||
NotificationWidget *nw = MainWindow::instance()->getNotificationWidget();
|
NotificationWidget *nw = MainWindow::instance()->getNotificationWidget();
|
||||||
if (nw->getNotificationText() == myLastError)
|
if (nw->getNotificationText().toStdString() == myLastError)
|
||||||
nw->hideNotification();
|
nw->hideNotification();
|
||||||
*/
|
*/
|
||||||
myLastError.clear();
|
myLastError.clear();
|
||||||
} else if (cloudAuthReply == QLatin1String("[VERIFY]") ||
|
} else if (cloudAuthReply == "[VERIFY]" || cloudAuthReply == "Invalid PIN") {
|
||||||
cloudAuthReply == QLatin1String("Invalid PIN")) {
|
|
||||||
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NEED_TO_VERIFY);
|
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NEED_TO_VERIFY);
|
||||||
report_error(qPrintable(tr("Cloud account verification required, enter PIN in preferences")));
|
report_error("%s", qPrintable(tr("Cloud account verification required, enter PIN in preferences")));
|
||||||
} else if (cloudAuthReply == QLatin1String("[PASSWDCHANGED]")) {
|
} else if (cloudAuthReply == "[PASSWDCHANGED]") {
|
||||||
qPrefCloudStorage::set_cloud_storage_password(cloudNewPassword);
|
qPrefCloudStorage::set_cloud_storage_password(cloudNewPassword);
|
||||||
cloudNewPassword.clear();
|
cloudNewPassword.clear();
|
||||||
emit passwordChangeSuccessful();
|
emit passwordChangeSuccessful();
|
||||||
@ -106,28 +105,28 @@ void CloudStorageAuthenticate::uploadFinished()
|
|||||||
} else {
|
} else {
|
||||||
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_INCORRECT_USER_PASSWD);
|
qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_INCORRECT_USER_PASSWD);
|
||||||
myLastError = cloudAuthReply;
|
myLastError = cloudAuthReply;
|
||||||
report_error("%s", qPrintable(cloudAuthReply));
|
report_error("%s", cloudAuthReply.c_str());
|
||||||
}
|
}
|
||||||
emit finishedAuthenticate();
|
emit finishedAuthenticate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudStorageAuthenticate::uploadError(QNetworkReply::NetworkError)
|
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)
|
void CloudStorageAuthenticate::sslErrors(const QList<QSslError> &errorList)
|
||||||
{
|
{
|
||||||
if (verbose) {
|
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) {
|
for (QSslError err: errorList) {
|
||||||
qDebug() << err.errorString();
|
report_info("%s", qPrintable(err.errorString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QSslConfiguration conf = reply->sslConfiguration();
|
QSslConfiguration conf = reply->sslConfiguration();
|
||||||
QSslCertificate cert = conf.peerCertificate();
|
QSslCertificate cert = conf.peerCertificate();
|
||||||
QByteArray hexDigest = cert.digest().toHex();
|
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()
|
QNetworkAccessManager *manager()
|
||||||
|
|||||||
@ -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,
|
static void cochran_parse_header(const unsigned char *decode, unsigned mod,
|
||||||
const unsigned char *in, unsigned size)
|
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' */
|
/* Do the "null decode" using a one-byte decode array of '\0' */
|
||||||
/* Copies in plaintext, will be overwritten later */
|
/* 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;
|
const unsigned char *s;
|
||||||
unsigned int offset = 0, profile_period = 1, sample_cnt = 0;
|
unsigned int offset = 0, profile_period = 1, sample_cnt = 0;
|
||||||
double depth = 0, temp = 0, depth_sample = 0, psi = 0, sgc_rate = 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 ndl = 0;
|
||||||
unsigned int in_deco = 0, deco_ceiling = 0, deco_time = 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) {
|
switch (config.type) {
|
||||||
case TYPE_COMMANDER:
|
case TYPE_COMMANDER:
|
||||||
switch (sample_cnt % 2) {
|
switch (sample_cnt % 2) {
|
||||||
case 0: // Ascent rate
|
case 0: // Ascent rate (unused)
|
||||||
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
|
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
|
||||||
break;
|
break;
|
||||||
case 1: // Temperature
|
case 1: // Temperature
|
||||||
temp = s[1] / 2 + 20;
|
temp = s[1] / 2 + 20;
|
||||||
@ -528,8 +528,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
|
|||||||
case TYPE_GEMINI:
|
case TYPE_GEMINI:
|
||||||
// Gemini with tank pressure and SAC rate.
|
// Gemini with tank pressure and SAC rate.
|
||||||
switch (sample_cnt % 4) {
|
switch (sample_cnt % 4) {
|
||||||
case 0: // Ascent rate
|
case 0: // Ascent rate (unused)
|
||||||
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
|
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
|
||||||
break;
|
break;
|
||||||
case 2: // PSI change
|
case 2: // PSI change
|
||||||
psi -= (double)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 4;
|
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;
|
break;
|
||||||
case TYPE_EMC:
|
case TYPE_EMC:
|
||||||
switch (sample_cnt % 2) {
|
switch (sample_cnt % 2) {
|
||||||
case 0: // Ascent rate
|
case 0: // Ascent rate (unused)
|
||||||
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
|
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
|
||||||
break;
|
break;
|
||||||
case 1: // Temperature
|
case 1: // Temperature
|
||||||
temp = (double)s[1] / 2 + 20;
|
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;
|
offset += config.sample_size;
|
||||||
sample_cnt++;
|
sample_cnt++;
|
||||||
}
|
}
|
||||||
UNUSED(ascent_rate); // mark the variable as unused
|
|
||||||
|
|
||||||
if (sample_cnt > 0)
|
if (sample_cnt > 0)
|
||||||
*duration = sample_cnt * profile_period - 1;
|
*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,
|
const unsigned char *in, unsigned size,
|
||||||
struct dive_table *table)
|
struct dive_table *table)
|
||||||
{
|
{
|
||||||
unsigned char *buf = malloc(size);
|
unsigned char *buf = (unsigned char *)malloc(size);
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
struct divecomputer *dc;
|
struct divecomputer *dc;
|
||||||
struct tm tm = {0};
|
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->duration.seconds = (log[CMD_BT] + log[CMD_BT + 1] * 256) * 60;
|
||||||
dc->surfacetime.seconds = (log[CMD_SIT] + log[CMD_SIT + 1] * 256) * 60;
|
dc->surfacetime.seconds = (log[CMD_SIT] + log[CMD_SIT + 1] * 256) * 60;
|
||||||
dc->maxdepth.mm = lrint((log[CMD_MAX_DEPTH] +
|
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] +
|
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->watertemp.mkelvin = F_to_mkelvin(log[CMD_MIN_TEMP]);
|
||||||
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
|
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
|
||||||
* (double) log[CMD_ALTITUDE] * 250 * FEET, 5.25588) * 1000);
|
* (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->duration.seconds = (log[EMC_BT] + log[EMC_BT + 1] * 256) * 60;
|
||||||
dc->surfacetime.seconds = (log[EMC_SIT] + log[EMC_SIT + 1] * 256) * 60;
|
dc->surfacetime.seconds = (log[EMC_SIT] + log[EMC_SIT + 1] * 256) * 60;
|
||||||
dc->maxdepth.mm = lrint((log[EMC_MAX_DEPTH] +
|
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] +
|
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->watertemp.mkelvin = F_to_mkelvin(log[EMC_MIN_TEMP]);
|
||||||
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
|
dc->surface_pressure.mbar = lrint(ATM / BAR * pow(1 - 0.0000225577
|
||||||
* (double) log[EMC_ALTITUDE] * 250 * FEET, 5.25588) * 1000);
|
* (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);
|
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 i;
|
||||||
unsigned int mod;
|
unsigned int mod;
|
||||||
unsigned int *offsets, dive1, dive2;
|
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;
|
return 0;
|
||||||
|
|
||||||
offsets = (unsigned int *) mem->buffer;
|
offsets = (unsigned int *) mem.data();
|
||||||
dive1 = offsets[0];
|
dive1 = offsets[0];
|
||||||
dive2 = offsets[1];
|
dive2 = offsets[1];
|
||||||
|
|
||||||
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
|
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem.size())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mod = decode[0x100] + 1;
|
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
|
// Decode each dive
|
||||||
for (i = 0; i < 65534; i++) {
|
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];
|
dive2 = offsets[i + 1];
|
||||||
if (dive2 < dive1)
|
if (dive2 < dive1)
|
||||||
break;
|
break;
|
||||||
if (dive2 > mem->size)
|
if (dive2 > mem.size())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cochran_parse_dive(decode, mod, mem->buffer + dive1,
|
cochran_parse_dive(decode, mod, (unsigned char *)mem.data() + dive1,
|
||||||
dive2 - dive1, log->dives);
|
dive2 - dive1, log->dives);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ void ConfigureDiveComputer::readSettings(device_data_t *data)
|
|||||||
readThread->start();
|
readThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDiveComputer::saveDeviceDetails(DeviceDetails *details, device_data_t *data)
|
void ConfigureDiveComputer::saveDeviceDetails(const DeviceDetails &details, device_data_t *data)
|
||||||
{
|
{
|
||||||
setState(WRITING);
|
setState(WRITING);
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ static QString writeGasDetails(gas g)
|
|||||||
}).join(QLatin1Char(','));
|
}).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 xml = "";
|
||||||
QString vendor = data->vendor;
|
QString vendor = data->vendor;
|
||||||
@ -80,37 +80,37 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
|
|||||||
writer.writeTextElement("Product", product);
|
writer.writeTextElement("Product", product);
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeStartElement("Settings");
|
writer.writeStartElement("Settings");
|
||||||
writer.writeTextElement("CustomText", details->customText);
|
writer.writeTextElement("CustomText", details.customText);
|
||||||
//Add gasses
|
//Add gasses
|
||||||
writer.writeTextElement("Gas1", writeGasDetails(details->gas1));
|
writer.writeTextElement("Gas1", writeGasDetails(details.gas1));
|
||||||
writer.writeTextElement("Gas2", writeGasDetails(details->gas2));
|
writer.writeTextElement("Gas2", writeGasDetails(details.gas2));
|
||||||
writer.writeTextElement("Gas3", writeGasDetails(details->gas3));
|
writer.writeTextElement("Gas3", writeGasDetails(details.gas3));
|
||||||
writer.writeTextElement("Gas4", writeGasDetails(details->gas4));
|
writer.writeTextElement("Gas4", writeGasDetails(details.gas4));
|
||||||
writer.writeTextElement("Gas5", writeGasDetails(details->gas5));
|
writer.writeTextElement("Gas5", writeGasDetails(details.gas5));
|
||||||
//
|
//
|
||||||
//Add dil values
|
//Add dil values
|
||||||
writer.writeTextElement("Dil1", writeGasDetails(details->dil1));
|
writer.writeTextElement("Dil1", writeGasDetails(details.dil1));
|
||||||
writer.writeTextElement("Dil2", writeGasDetails(details->dil2));
|
writer.writeTextElement("Dil2", writeGasDetails(details.dil2));
|
||||||
writer.writeTextElement("Dil3", writeGasDetails(details->dil3));
|
writer.writeTextElement("Dil3", writeGasDetails(details.dil3));
|
||||||
writer.writeTextElement("Dil4", writeGasDetails(details->dil4));
|
writer.writeTextElement("Dil4", writeGasDetails(details.dil4));
|
||||||
writer.writeTextElement("Dil5", writeGasDetails(details->dil5));
|
writer.writeTextElement("Dil5", writeGasDetails(details.dil5));
|
||||||
|
|
||||||
//Add setpoint values
|
//Add setpoint values
|
||||||
QString sp1 = QString("%1,%2")
|
QString sp1 = QString("%1,%2")
|
||||||
.arg(QString::number(details->sp1.sp),
|
.arg(QString::number(details.sp1.sp),
|
||||||
QString::number(details->sp1.depth));
|
QString::number(details.sp1.depth));
|
||||||
QString sp2 = QString("%1,%2")
|
QString sp2 = QString("%1,%2")
|
||||||
.arg(QString::number(details->sp2.sp),
|
.arg(QString::number(details.sp2.sp),
|
||||||
QString::number(details->sp2.depth));
|
QString::number(details.sp2.depth));
|
||||||
QString sp3 = QString("%1,%2")
|
QString sp3 = QString("%1,%2")
|
||||||
.arg(QString::number(details->sp3.sp),
|
.arg(QString::number(details.sp3.sp),
|
||||||
QString::number(details->sp3.depth));
|
QString::number(details.sp3.depth));
|
||||||
QString sp4 = QString("%1,%2")
|
QString sp4 = QString("%1,%2")
|
||||||
.arg(QString::number(details->sp4.sp),
|
.arg(QString::number(details.sp4.sp),
|
||||||
QString::number(details->sp4.depth));
|
QString::number(details.sp4.depth));
|
||||||
QString sp5 = QString("%1,%2")
|
QString sp5 = QString("%1,%2")
|
||||||
.arg(QString::number(details->sp5.sp),
|
.arg(QString::number(details.sp5.sp),
|
||||||
QString::number(details->sp5.depth));
|
QString::number(details.sp5.depth));
|
||||||
writer.writeTextElement("SetPoint1", sp1);
|
writer.writeTextElement("SetPoint1", sp1);
|
||||||
writer.writeTextElement("SetPoint2", sp2);
|
writer.writeTextElement("SetPoint2", sp2);
|
||||||
writer.writeTextElement("SetPoint3", sp3);
|
writer.writeTextElement("SetPoint3", sp3);
|
||||||
@ -118,60 +118,60 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
|
|||||||
writer.writeTextElement("SetPoint5", sp5);
|
writer.writeTextElement("SetPoint5", sp5);
|
||||||
|
|
||||||
//Other Settings
|
//Other Settings
|
||||||
writer.writeTextElement("DiveMode", QString::number(details->diveMode));
|
writer.writeTextElement("DiveMode", QString::number(details.diveMode));
|
||||||
writer.writeTextElement("Saturation", QString::number(details->saturation));
|
writer.writeTextElement("Saturation", QString::number(details.saturation));
|
||||||
writer.writeTextElement("Desaturation", QString::number(details->desaturation));
|
writer.writeTextElement("Desaturation", QString::number(details.desaturation));
|
||||||
writer.writeTextElement("LastDeco", QString::number(details->lastDeco));
|
writer.writeTextElement("LastDeco", QString::number(details.lastDeco));
|
||||||
writer.writeTextElement("Brightness", QString::number(details->brightness));
|
writer.writeTextElement("Brightness", QString::number(details.brightness));
|
||||||
writer.writeTextElement("Units", QString::number(details->units));
|
writer.writeTextElement("Units", QString::number(details.units));
|
||||||
writer.writeTextElement("SamplingRate", QString::number(details->samplingRate));
|
writer.writeTextElement("SamplingRate", QString::number(details.samplingRate));
|
||||||
writer.writeTextElement("Salinity", QString::number(details->salinity));
|
writer.writeTextElement("Salinity", QString::number(details.salinity));
|
||||||
writer.writeTextElement("DiveModeColor", QString::number(details->diveModeColor));
|
writer.writeTextElement("DiveModeColor", QString::number(details.diveModeColor));
|
||||||
writer.writeTextElement("Language", QString::number(details->language));
|
writer.writeTextElement("Language", QString::number(details.language));
|
||||||
writer.writeTextElement("DateFormat", QString::number(details->dateFormat));
|
writer.writeTextElement("DateFormat", QString::number(details.dateFormat));
|
||||||
writer.writeTextElement("CompassGain", QString::number(details->compassGain));
|
writer.writeTextElement("CompassGain", QString::number(details.compassGain));
|
||||||
writer.writeTextElement("SafetyStop", QString::number(details->safetyStop));
|
writer.writeTextElement("SafetyStop", QString::number(details.safetyStop));
|
||||||
writer.writeTextElement("GfHigh", QString::number(details->gfHigh));
|
writer.writeTextElement("GfHigh", QString::number(details.gfHigh));
|
||||||
writer.writeTextElement("GfLow", QString::number(details->gfLow));
|
writer.writeTextElement("GfLow", QString::number(details.gfLow));
|
||||||
writer.writeTextElement("PressureSensorOffset", QString::number(details->pressureSensorOffset));
|
writer.writeTextElement("PressureSensorOffset", QString::number(details.pressureSensorOffset));
|
||||||
writer.writeTextElement("PpO2Min", QString::number(details->ppO2Min));
|
writer.writeTextElement("PpO2Min", QString::number(details.ppO2Min));
|
||||||
writer.writeTextElement("PpO2Max", QString::number(details->ppO2Max));
|
writer.writeTextElement("PpO2Max", QString::number(details.ppO2Max));
|
||||||
writer.writeTextElement("FutureTTS", QString::number(details->futureTTS));
|
writer.writeTextElement("FutureTTS", QString::number(details.futureTTS));
|
||||||
writer.writeTextElement("CcrMode", QString::number(details->ccrMode));
|
writer.writeTextElement("CcrMode", QString::number(details.ccrMode));
|
||||||
writer.writeTextElement("DecoType", QString::number(details->decoType));
|
writer.writeTextElement("DecoType", QString::number(details.decoType));
|
||||||
writer.writeTextElement("AGFSelectable", QString::number(details->aGFSelectable));
|
writer.writeTextElement("AGFSelectable", QString::number(details.aGFSelectable));
|
||||||
writer.writeTextElement("AGFHigh", QString::number(details->aGFHigh));
|
writer.writeTextElement("AGFHigh", QString::number(details.aGFHigh));
|
||||||
writer.writeTextElement("AGFLow", QString::number(details->aGFLow));
|
writer.writeTextElement("AGFLow", QString::number(details.aGFLow));
|
||||||
writer.writeTextElement("CalibrationGas", QString::number(details->calibrationGas));
|
writer.writeTextElement("CalibrationGas", QString::number(details.calibrationGas));
|
||||||
writer.writeTextElement("FlipScreen", QString::number(details->flipScreen));
|
writer.writeTextElement("FlipScreen", QString::number(details.flipScreen));
|
||||||
writer.writeTextElement("SetPointFallback", QString::number(details->setPointFallback));
|
writer.writeTextElement("SetPointFallback", QString::number(details.setPointFallback));
|
||||||
writer.writeTextElement("LeftButtonSensitivity", QString::number(details->leftButtonSensitivity));
|
writer.writeTextElement("LeftButtonSensitivity", QString::number(details.leftButtonSensitivity));
|
||||||
writer.writeTextElement("RightButtonSensitivity", QString::number(details->rightButtonSensitivity));
|
writer.writeTextElement("RightButtonSensitivity", QString::number(details.rightButtonSensitivity));
|
||||||
writer.writeTextElement("BottomGasConsumption", QString::number(details->bottomGasConsumption));
|
writer.writeTextElement("BottomGasConsumption", QString::number(details.bottomGasConsumption));
|
||||||
writer.writeTextElement("DecoGasConsumption", QString::number(details->decoGasConsumption));
|
writer.writeTextElement("DecoGasConsumption", QString::number(details.decoGasConsumption));
|
||||||
writer.writeTextElement("ModWarning", QString::number(details->modWarning));
|
writer.writeTextElement("ModWarning", QString::number(details.modWarning));
|
||||||
writer.writeTextElement("DynamicAscendRate", QString::number(details->dynamicAscendRate));
|
writer.writeTextElement("DynamicAscendRate", QString::number(details.dynamicAscendRate));
|
||||||
writer.writeTextElement("GraphicalSpeedIndicator", QString::number(details->graphicalSpeedIndicator));
|
writer.writeTextElement("GraphicalSpeedIndicator", QString::number(details.graphicalSpeedIndicator));
|
||||||
writer.writeTextElement("AlwaysShowppO2", QString::number(details->alwaysShowppO2));
|
writer.writeTextElement("AlwaysShowppO2", QString::number(details.alwaysShowppO2));
|
||||||
|
|
||||||
// Suunto vyper settings.
|
// Suunto vyper settings.
|
||||||
writer.writeTextElement("Altitude", QString::number(details->altitude));
|
writer.writeTextElement("Altitude", QString::number(details.altitude));
|
||||||
writer.writeTextElement("PersonalSafety", QString::number(details->personalSafety));
|
writer.writeTextElement("PersonalSafety", QString::number(details.personalSafety));
|
||||||
writer.writeTextElement("TimeFormat", QString::number(details->timeFormat));
|
writer.writeTextElement("TimeFormat", QString::number(details.timeFormat));
|
||||||
|
|
||||||
writer.writeStartElement("Light");
|
writer.writeStartElement("Light");
|
||||||
writer.writeAttribute("enabled", QString::number(details->lightEnabled));
|
writer.writeAttribute("enabled", QString::number(details.lightEnabled));
|
||||||
writer.writeCharacters(QString::number(details->light));
|
writer.writeCharacters(QString::number(details.light));
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
writer.writeStartElement("AlarmTime");
|
writer.writeStartElement("AlarmTime");
|
||||||
writer.writeAttribute("enabled", QString::number(details->alarmTimeEnabled));
|
writer.writeAttribute("enabled", QString::number(details.alarmTimeEnabled));
|
||||||
writer.writeCharacters(QString::number(details->alarmTime));
|
writer.writeCharacters(QString::number(details.alarmTime));
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
writer.writeStartElement("AlarmDepth");
|
writer.writeStartElement("AlarmDepth");
|
||||||
writer.writeAttribute("enabled", QString::number(details->alarmDepthEnabled));
|
writer.writeAttribute("enabled", QString::number(details.alarmDepthEnabled));
|
||||||
writer.writeCharacters(QString::number(details->alarmDepth));
|
writer.writeCharacters(QString::number(details.alarmDepth));
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
@ -192,7 +192,7 @@ bool ConfigureDiveComputer::saveXMLBackup(const QString &fileName, DeviceDetails
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDetails *details)
|
bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDetails &details)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
@ -211,7 +211,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
QString keyString = reader.text().toString();
|
QString keyString = reader.text().toString();
|
||||||
|
|
||||||
if (settingName == "CustomText")
|
if (settingName == "CustomText")
|
||||||
details->customText = keyString;
|
details.customText = keyString;
|
||||||
|
|
||||||
if (settingName == "Gas1") {
|
if (settingName == "Gas1") {
|
||||||
QStringList gasData = keyString.split(",");
|
QStringList gasData = keyString.split(",");
|
||||||
@ -220,7 +220,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
gas1.helium = gasData.at(1).toInt();
|
gas1.helium = gasData.at(1).toInt();
|
||||||
gas1.type = gasData.at(2).toInt();
|
gas1.type = gasData.at(2).toInt();
|
||||||
gas1.depth = gasData.at(3).toInt();
|
gas1.depth = gasData.at(3).toInt();
|
||||||
details->gas1 = gas1;
|
details.gas1 = gas1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Gas2") {
|
if (settingName == "Gas2") {
|
||||||
@ -230,7 +230,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
gas2.helium = gasData.at(1).toInt();
|
gas2.helium = gasData.at(1).toInt();
|
||||||
gas2.type = gasData.at(2).toInt();
|
gas2.type = gasData.at(2).toInt();
|
||||||
gas2.depth = gasData.at(3).toInt();
|
gas2.depth = gasData.at(3).toInt();
|
||||||
details->gas2 = gas2;
|
details.gas2 = gas2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Gas3") {
|
if (settingName == "Gas3") {
|
||||||
@ -240,7 +240,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
gas3.helium = gasData.at(1).toInt();
|
gas3.helium = gasData.at(1).toInt();
|
||||||
gas3.type = gasData.at(2).toInt();
|
gas3.type = gasData.at(2).toInt();
|
||||||
gas3.depth = gasData.at(3).toInt();
|
gas3.depth = gasData.at(3).toInt();
|
||||||
details->gas3 = gas3;
|
details.gas3 = gas3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Gas4") {
|
if (settingName == "Gas4") {
|
||||||
@ -250,7 +250,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
gas4.helium = gasData.at(1).toInt();
|
gas4.helium = gasData.at(1).toInt();
|
||||||
gas4.type = gasData.at(2).toInt();
|
gas4.type = gasData.at(2).toInt();
|
||||||
gas4.depth = gasData.at(3).toInt();
|
gas4.depth = gasData.at(3).toInt();
|
||||||
details->gas4 = gas4;
|
details.gas4 = gas4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Gas5") {
|
if (settingName == "Gas5") {
|
||||||
@ -260,7 +260,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
gas5.helium = gasData.at(1).toInt();
|
gas5.helium = gasData.at(1).toInt();
|
||||||
gas5.type = gasData.at(2).toInt();
|
gas5.type = gasData.at(2).toInt();
|
||||||
gas5.depth = gasData.at(3).toInt();
|
gas5.depth = gasData.at(3).toInt();
|
||||||
details->gas5 = gas5;
|
details.gas5 = gas5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Dil1") {
|
if (settingName == "Dil1") {
|
||||||
@ -270,7 +270,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
dil1.helium = dilData.at(1).toInt();
|
dil1.helium = dilData.at(1).toInt();
|
||||||
dil1.type = dilData.at(2).toInt();
|
dil1.type = dilData.at(2).toInt();
|
||||||
dil1.depth = dilData.at(3).toInt();
|
dil1.depth = dilData.at(3).toInt();
|
||||||
details->dil1 = dil1;
|
details.dil1 = dil1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Dil2") {
|
if (settingName == "Dil2") {
|
||||||
@ -280,7 +280,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
dil2.helium = dilData.at(1).toInt();
|
dil2.helium = dilData.at(1).toInt();
|
||||||
dil2.type = dilData.at(2).toInt();
|
dil2.type = dilData.at(2).toInt();
|
||||||
dil2.depth = dilData.at(3).toInt();
|
dil2.depth = dilData.at(3).toInt();
|
||||||
details->dil1 = dil2;
|
details.dil1 = dil2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Dil3") {
|
if (settingName == "Dil3") {
|
||||||
@ -290,7 +290,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
dil3.helium = dilData.at(1).toInt();
|
dil3.helium = dilData.at(1).toInt();
|
||||||
dil3.type = dilData.at(2).toInt();
|
dil3.type = dilData.at(2).toInt();
|
||||||
dil3.depth = dilData.at(3).toInt();
|
dil3.depth = dilData.at(3).toInt();
|
||||||
details->dil3 = dil3;
|
details.dil3 = dil3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Dil4") {
|
if (settingName == "Dil4") {
|
||||||
@ -300,7 +300,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
dil4.helium = dilData.at(1).toInt();
|
dil4.helium = dilData.at(1).toInt();
|
||||||
dil4.type = dilData.at(2).toInt();
|
dil4.type = dilData.at(2).toInt();
|
||||||
dil4.depth = dilData.at(3).toInt();
|
dil4.depth = dilData.at(3).toInt();
|
||||||
details->dil4 = dil4;
|
details.dil4 = dil4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Dil5") {
|
if (settingName == "Dil5") {
|
||||||
@ -310,7 +310,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
dil5.helium = dilData.at(1).toInt();
|
dil5.helium = dilData.at(1).toInt();
|
||||||
dil5.type = dilData.at(2).toInt();
|
dil5.type = dilData.at(2).toInt();
|
||||||
dil5.depth = dilData.at(3).toInt();
|
dil5.depth = dilData.at(3).toInt();
|
||||||
details->dil5 = dil5;
|
details.dil5 = dil5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "SetPoint1") {
|
if (settingName == "SetPoint1") {
|
||||||
@ -318,7 +318,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
setpoint sp1;
|
setpoint sp1;
|
||||||
sp1.sp = spData.at(0).toInt();
|
sp1.sp = spData.at(0).toInt();
|
||||||
sp1.depth = spData.at(1).toInt();
|
sp1.depth = spData.at(1).toInt();
|
||||||
details->sp1 = sp1;
|
details.sp1 = sp1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "SetPoint2") {
|
if (settingName == "SetPoint2") {
|
||||||
@ -326,7 +326,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
setpoint sp2;
|
setpoint sp2;
|
||||||
sp2.sp = spData.at(0).toInt();
|
sp2.sp = spData.at(0).toInt();
|
||||||
sp2.depth = spData.at(1).toInt();
|
sp2.depth = spData.at(1).toInt();
|
||||||
details->sp2 = sp2;
|
details.sp2 = sp2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "SetPoint3") {
|
if (settingName == "SetPoint3") {
|
||||||
@ -334,7 +334,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
setpoint sp3;
|
setpoint sp3;
|
||||||
sp3.sp = spData.at(0).toInt();
|
sp3.sp = spData.at(0).toInt();
|
||||||
sp3.depth = spData.at(1).toInt();
|
sp3.depth = spData.at(1).toInt();
|
||||||
details->sp3 = sp3;
|
details.sp3 = sp3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "SetPoint4") {
|
if (settingName == "SetPoint4") {
|
||||||
@ -342,7 +342,7 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
setpoint sp4;
|
setpoint sp4;
|
||||||
sp4.sp = spData.at(0).toInt();
|
sp4.sp = spData.at(0).toInt();
|
||||||
sp4.depth = spData.at(1).toInt();
|
sp4.depth = spData.at(1).toInt();
|
||||||
details->sp4 = sp4;
|
details.sp4 = sp4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "SetPoint5") {
|
if (settingName == "SetPoint5") {
|
||||||
@ -350,139 +350,139 @@ bool ConfigureDiveComputer::restoreXMLBackup(const QString &fileName, DeviceDeta
|
|||||||
setpoint sp5;
|
setpoint sp5;
|
||||||
sp5.sp = spData.at(0).toInt();
|
sp5.sp = spData.at(0).toInt();
|
||||||
sp5.depth = spData.at(1).toInt();
|
sp5.depth = spData.at(1).toInt();
|
||||||
details->sp5 = sp5;
|
details.sp5 = sp5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "Saturation")
|
if (settingName == "Saturation")
|
||||||
details->saturation = keyString.toInt();
|
details.saturation = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Desaturation")
|
if (settingName == "Desaturation")
|
||||||
details->desaturation = keyString.toInt();
|
details.desaturation = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DiveMode")
|
if (settingName == "DiveMode")
|
||||||
details->diveMode = keyString.toInt();
|
details.diveMode = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "LastDeco")
|
if (settingName == "LastDeco")
|
||||||
details->lastDeco = keyString.toInt();
|
details.lastDeco = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Brightness")
|
if (settingName == "Brightness")
|
||||||
details->brightness = keyString.toInt();
|
details.brightness = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Units")
|
if (settingName == "Units")
|
||||||
details->units = keyString.toInt();
|
details.units = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "SamplingRate")
|
if (settingName == "SamplingRate")
|
||||||
details->samplingRate = keyString.toInt();
|
details.samplingRate = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Salinity")
|
if (settingName == "Salinity")
|
||||||
details->salinity = keyString.toInt();
|
details.salinity = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DiveModeColour")
|
if (settingName == "DiveModeColour")
|
||||||
details->diveModeColor = keyString.toInt();
|
details.diveModeColor = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Language")
|
if (settingName == "Language")
|
||||||
details->language = keyString.toInt();
|
details.language = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DateFormat")
|
if (settingName == "DateFormat")
|
||||||
details->dateFormat = keyString.toInt();
|
details.dateFormat = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "CompassGain")
|
if (settingName == "CompassGain")
|
||||||
details->compassGain = keyString.toInt();
|
details.compassGain = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "SafetyStop")
|
if (settingName == "SafetyStop")
|
||||||
details->safetyStop = keyString.toInt();
|
details.safetyStop = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "GfHigh")
|
if (settingName == "GfHigh")
|
||||||
details->gfHigh = keyString.toInt();
|
details.gfHigh = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "GfLow")
|
if (settingName == "GfLow")
|
||||||
details->gfLow = keyString.toInt();
|
details.gfLow = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "PressureSensorOffset")
|
if (settingName == "PressureSensorOffset")
|
||||||
details->pressureSensorOffset = keyString.toInt();
|
details.pressureSensorOffset = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "PpO2Min")
|
if (settingName == "PpO2Min")
|
||||||
details->ppO2Min = keyString.toInt();
|
details.ppO2Min = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "PpO2Max")
|
if (settingName == "PpO2Max")
|
||||||
details->ppO2Max = keyString.toInt();
|
details.ppO2Max = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "FutureTTS")
|
if (settingName == "FutureTTS")
|
||||||
details->futureTTS = keyString.toInt();
|
details.futureTTS = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "CcrMode")
|
if (settingName == "CcrMode")
|
||||||
details->ccrMode = keyString.toInt();
|
details.ccrMode = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DecoType")
|
if (settingName == "DecoType")
|
||||||
details->decoType = keyString.toInt();
|
details.decoType = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "AGFSelectable")
|
if (settingName == "AGFSelectable")
|
||||||
details->aGFSelectable = keyString.toInt();
|
details.aGFSelectable = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "AGFHigh")
|
if (settingName == "AGFHigh")
|
||||||
details->aGFHigh = keyString.toInt();
|
details.aGFHigh = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "AGFLow")
|
if (settingName == "AGFLow")
|
||||||
details->aGFLow = keyString.toInt();
|
details.aGFLow = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "CalibrationGas")
|
if (settingName == "CalibrationGas")
|
||||||
details->calibrationGas = keyString.toInt();
|
details.calibrationGas = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "FlipScreen")
|
if (settingName == "FlipScreen")
|
||||||
details->flipScreen = keyString.toInt();
|
details.flipScreen = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "SetPointFallback")
|
if (settingName == "SetPointFallback")
|
||||||
details->setPointFallback = keyString.toInt();
|
details.setPointFallback = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "LeftButtonSensitivity")
|
if (settingName == "LeftButtonSensitivity")
|
||||||
details->leftButtonSensitivity = keyString.toInt();
|
details.leftButtonSensitivity = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "RightButtonSensitivity")
|
if (settingName == "RightButtonSensitivity")
|
||||||
details->rightButtonSensitivity = keyString.toInt();
|
details.rightButtonSensitivity = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "BottomGasConsumption")
|
if (settingName == "BottomGasConsumption")
|
||||||
details->bottomGasConsumption = keyString.toInt();
|
details.bottomGasConsumption = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DecoGasConsumption")
|
if (settingName == "DecoGasConsumption")
|
||||||
details->decoGasConsumption = keyString.toInt();
|
details.decoGasConsumption = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "ModWarning")
|
if (settingName == "ModWarning")
|
||||||
details->modWarning = keyString.toInt();
|
details.modWarning = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "DynamicAscendRate")
|
if (settingName == "DynamicAscendRate")
|
||||||
details->dynamicAscendRate = keyString.toInt();
|
details.dynamicAscendRate = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "GraphicalSpeedIndicator")
|
if (settingName == "GraphicalSpeedIndicator")
|
||||||
details->graphicalSpeedIndicator = keyString.toInt();
|
details.graphicalSpeedIndicator = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "AlwaysShowppO2")
|
if (settingName == "AlwaysShowppO2")
|
||||||
details->alwaysShowppO2 = keyString.toInt();
|
details.alwaysShowppO2 = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Altitude")
|
if (settingName == "Altitude")
|
||||||
details->altitude = keyString.toInt();
|
details.altitude = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "PersonalSafety")
|
if (settingName == "PersonalSafety")
|
||||||
details->personalSafety = keyString.toInt();
|
details.personalSafety = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "TimeFormat")
|
if (settingName == "TimeFormat")
|
||||||
details->timeFormat = keyString.toInt();
|
details.timeFormat = keyString.toInt();
|
||||||
|
|
||||||
if (settingName == "Light") {
|
if (settingName == "Light") {
|
||||||
if (attributes.hasAttribute("enabled"))
|
if (attributes.hasAttribute("enabled"))
|
||||||
details->lightEnabled = attributes.value("enabled").toString().toInt();
|
details.lightEnabled = attributes.value("enabled").toString().toInt();
|
||||||
details->light = keyString.toInt();
|
details.light = keyString.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "AlarmDepth") {
|
if (settingName == "AlarmDepth") {
|
||||||
if (attributes.hasAttribute("enabled"))
|
if (attributes.hasAttribute("enabled"))
|
||||||
details->alarmDepthEnabled = attributes.value("enabled").toString().toInt();
|
details.alarmDepthEnabled = attributes.value("enabled").toString().toInt();
|
||||||
details->alarmDepth = keyString.toInt();
|
details.alarmDepth = keyString.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settingName == "AlarmTime") {
|
if (settingName == "AlarmTime") {
|
||||||
if (attributes.hasAttribute("enabled"))
|
if (attributes.hasAttribute("enabled"))
|
||||||
details->alarmTimeEnabled = attributes.value("enabled").toString().toInt();
|
details.alarmTimeEnabled = attributes.value("enabled").toString().toInt();
|
||||||
details->alarmTime = keyString.toInt();
|
details.alarmTime = keyString.toInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
@ -574,8 +574,8 @@ QString ConfigureDiveComputer::dc_open(device_data_t *data)
|
|||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
dc_status_t rc;
|
dc_status_t rc;
|
||||||
|
|
||||||
if (data->libdc_log)
|
if (data->libdc_log && !logfile_name.empty())
|
||||||
fp = subsurface_fopen(logfile_name, "w");
|
fp = subsurface_fopen(logfile_name.c_str(), "w");
|
||||||
|
|
||||||
data->libdc_logfile = fp;
|
data->libdc_logfile = fp;
|
||||||
|
|
||||||
@ -594,7 +594,7 @@ QString ConfigureDiveComputer::dc_open(device_data_t *data)
|
|||||||
rc = divecomputer_device_open(data);
|
rc = divecomputer_device_open(data);
|
||||||
|
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
report_error(errmsg(rc));
|
report_error("%s", errmsg(rc));
|
||||||
} else {
|
} else {
|
||||||
rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream);
|
rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,10 @@ public:
|
|||||||
|
|
||||||
QString lastError;
|
QString lastError;
|
||||||
states currentState;
|
states currentState;
|
||||||
void saveDeviceDetails(DeviceDetails *details, device_data_t *data);
|
void saveDeviceDetails(const DeviceDetails &details, device_data_t *data);
|
||||||
void fetchDeviceDetails();
|
void fetchDeviceDetails();
|
||||||
bool saveXMLBackup(const QString &fileName, DeviceDetails *details, device_data_t *data);
|
bool saveXMLBackup(const QString &fileName, const DeviceDetails &details, device_data_t *data);
|
||||||
bool restoreXMLBackup(const QString &fileName, DeviceDetails *details);
|
bool restoreXMLBackup(const QString &fileName, DeviceDetails &details);
|
||||||
void startFirmwareUpdate(const QString &fileName, device_data_t *data, bool forceUpdate);
|
void startFirmwareUpdate(const QString &fileName, device_data_t *data, bool forceUpdate);
|
||||||
void resetSettings(device_data_t *data);
|
void resetSettings(device_data_t *data);
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ signals:
|
|||||||
void message(QString msg);
|
void message(QString msg);
|
||||||
void error(QString err);
|
void error(QString err);
|
||||||
void stateChanged(states newState);
|
void stateChanged(states newState);
|
||||||
void deviceDetailsChanged(DeviceDetails *newDetails);
|
void deviceDetailsChanged(DeviceDetails newDetails);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ReadSettingsThread *readThread;
|
ReadSettingsThread *readThread;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -27,18 +27,18 @@ public:
|
|||||||
ReadSettingsThread(QObject *parent, device_data_t *data);
|
ReadSettingsThread(QObject *parent, device_data_t *data);
|
||||||
void run();
|
void run();
|
||||||
signals:
|
signals:
|
||||||
void devicedetails(DeviceDetails *newDeviceDetails);
|
void devicedetails(DeviceDetails newDeviceDetails);
|
||||||
};
|
};
|
||||||
|
|
||||||
class WriteSettingsThread : public DeviceThread {
|
class WriteSettingsThread : public DeviceThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
WriteSettingsThread(QObject *parent, device_data_t *data);
|
WriteSettingsThread(QObject *parent, device_data_t *data);
|
||||||
void setDeviceDetails(DeviceDetails *details);
|
void setDeviceDetails(const DeviceDetails &details);
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceDetails *m_deviceDetails;
|
DeviceDetails m_deviceDetails;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FirmwareUpdateThread : public DeviceThread {
|
class FirmwareUpdateThread : public DeviceThread {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ static char *to_utf8(unsigned char *in_string)
|
|||||||
inlen = strlen((char *)in_string);
|
inlen = strlen((char *)in_string);
|
||||||
outlen = inlen * 2 + 1;
|
outlen = inlen * 2 + 1;
|
||||||
|
|
||||||
char *out_string = calloc(outlen, 1);
|
char *out_string = (char *)calloc(outlen, 1);
|
||||||
for (i = 0; i < inlen; i++) {
|
for (i = 0; i < inlen; i++) {
|
||||||
if (in_string[i] < 127) {
|
if (in_string[i] < 127) {
|
||||||
out_string[j] = in_string[i];
|
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.
|
* 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.
|
* 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;
|
int rc, profile_length, libdc_model;
|
||||||
char *tmp_notes_str = NULL;
|
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;
|
struct dive_site *ds;
|
||||||
char is_nitrox = 0, is_O2 = 0, is_SCR = 0;
|
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;
|
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 : "",
|
tmp_notes_str ? tmp_notes_str : "",
|
||||||
QT_TRANSLATE_NOOP("gettextFromC", "Datatrak/Wlog notes"),
|
QT_TRANSLATE_NOOP("gettextFromC", "Datatrak/Wlog notes"),
|
||||||
tmp_string1);
|
tmp_string1);
|
||||||
dt_dive->notes = calloc((len +1), 1);
|
dt_dive->notes = (char *)calloc((len +1), 1);
|
||||||
dt_dive->notes = memcpy(dt_dive->notes, buffer, len);
|
memcpy(dt_dive->notes, buffer, len);
|
||||||
free(tmp_string1);
|
free(tmp_string1);
|
||||||
}
|
}
|
||||||
free(tmp_notes_str);
|
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);
|
((get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000);
|
||||||
}
|
}
|
||||||
free(devdata);
|
free(devdata);
|
||||||
return membuf;
|
return (char *)membuf;
|
||||||
bail:
|
bail:
|
||||||
free(locality);
|
free(locality);
|
||||||
free(devdata);
|
free(devdata);
|
||||||
@ -582,10 +582,10 @@ bail:
|
|||||||
* Parses the header of the .add file, returns the number of dives in
|
* 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).
|
* 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;
|
int tmp;
|
||||||
unsigned char *runner = (unsigned char *) mem->buffer;
|
unsigned char *runner = (unsigned char *) mem.data();
|
||||||
if (!runner)
|
if (!runner)
|
||||||
return -1;
|
return -1;
|
||||||
if (!memcmp(runner, "\x52\x02", 2)) {
|
if (!memcmp(runner, "\x52\x02", 2)) {
|
||||||
@ -600,7 +600,7 @@ static int wlog_header_parser (struct memblock *mem)
|
|||||||
|
|
||||||
#define NOTES_LENGTH 256
|
#define NOTES_LENGTH 256
|
||||||
#define SUIT_LENGTH 26
|
#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),
|
int tmp = 0, offset = 12 + (dcount * 850),
|
||||||
pos_weight = offset + 256,
|
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_tank_init = offset + 266,
|
||||||
pos_suit = offset + 268;
|
pos_suit = offset + 268;
|
||||||
char *wlog_notes = NULL, *wlog_suit = NULL, *buffer = NULL;
|
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
|
* 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);
|
wlog_notes = to_utf8((unsigned char *) wlog_notes_temp);
|
||||||
}
|
}
|
||||||
if (dt_dive->notes && wlog_notes) {
|
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);
|
sprintf(buffer, "%s%s", dt_dive->notes, wlog_notes);
|
||||||
free(dt_dive->notes);
|
free(dt_dive->notes);
|
||||||
dt_dive->notes = copy_string(buffer);
|
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]);
|
tmp = (int) two_bytes_to_int(runner[pos_weight + 1], runner[pos_weight]);
|
||||||
if (tmp != 0x7fff) {
|
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);
|
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.
|
* 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;
|
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
|
// 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) {
|
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;
|
goto bail;
|
||||||
}
|
}
|
||||||
// Verify WLog .add file, Beginning sequence and Nº dives
|
// 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);
|
int compl_dives_n = wlog_header_parser(wl_mem);
|
||||||
if (compl_dives_n != numdives) {
|
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);
|
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.clear();
|
||||||
wl_mem->buffer = NULL;
|
|
||||||
wl_mem = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Point to the expected begining of 1st. dive data
|
// Point to the expected begining of 1st. dive data
|
||||||
runner = (unsigned char *)mem->buffer;
|
runner = mem.data();
|
||||||
JUMP(runner, 12);
|
JUMP(runner, 12);
|
||||||
|
|
||||||
// Secuential parsing. Abort if received NULL from dt_dive_parser.
|
// 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();
|
struct dive *ptdive = alloc_dive();
|
||||||
|
|
||||||
runner = dt_dive_parser(runner, ptdive, log, maxbuf);
|
runner = dt_dive_parser((unsigned char *)runner, ptdive, log, maxbuf);
|
||||||
if (wl_mem)
|
if (!wl_mem.empty())
|
||||||
wlog_compl_parser(wl_mem, ptdive, i);
|
wlog_compl_parser(wl_mem, ptdive, i);
|
||||||
if (runner == NULL) {
|
if (runner == NULL) {
|
||||||
report_error(translate("gettextFromC", "Error: no dive"));
|
report_error("%s", translate("gettextFromC", "Error: no dive"));
|
||||||
free(ptdive);
|
free(ptdive);
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto out;
|
goto out;
|
||||||
@ -723,7 +721,6 @@ int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelo
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
taglist_cleanup(&g_tag_list);
|
|
||||||
sort_dive_table(log->dives);
|
sort_dive_table(log->dives);
|
||||||
return rc;
|
return rc;
|
||||||
bail:
|
bail:
|
||||||
@ -41,8 +41,8 @@ static const struct models_table_t g_models[] = {
|
|||||||
{0xEE, 0x44, "Uwatec Unknown model", DC_FAMILY_UWATEC_ALADIN},
|
{0xEE, 0x44, "Uwatec Unknown model", DC_FAMILY_UWATEC_ALADIN},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JUMP(_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 ((long) _ptr + _n > maxbuf) goto bail
|
#define CHECK(_ptr, _n) if ((char *) _ptr + _n > (char *)maxbuf) goto bail
|
||||||
#define read_bytes(_n) \
|
#define read_bytes(_n) \
|
||||||
switch (_n) { \
|
switch (_n) { \
|
||||||
case 1: \
|
case 1: \
|
||||||
@ -62,10 +62,12 @@ static const struct models_table_t g_models[] = {
|
|||||||
|
|
||||||
#define read_string(_property) \
|
#define read_string(_property) \
|
||||||
CHECK(membuf, tmp_1byte); \
|
CHECK(membuf, tmp_1byte); \
|
||||||
|
{ \
|
||||||
unsigned char *_property##tmp = (unsigned char *)calloc(tmp_1byte + 1, 1); \
|
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), ""); \
|
_property = (unsigned char *)strcat(to_utf8(_property##tmp), ""); \
|
||||||
free(_property##tmp);\
|
free(_property##tmp);\
|
||||||
JUMP(membuf, tmp_1byte);
|
JUMP(membuf, tmp_1byte); \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // DATATRAK_HEADER_H
|
#endif // DATATRAK_HEADER_H
|
||||||
|
|||||||
@ -13,8 +13,6 @@
|
|||||||
* set_gf() - set Buehlmann gradient factors
|
* set_gf() - set Buehlmann gradient factors
|
||||||
* set_vpmb_conservatism() - set VPM-B conservatism value
|
* set_vpmb_conservatism() - set VPM-B conservatism value
|
||||||
* clear_deco()
|
* clear_deco()
|
||||||
* cache_deco_state()
|
|
||||||
* restore_deco_state()
|
|
||||||
* dump_tissues()
|
* dump_tissues()
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#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;
|
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;
|
int ci = -1;
|
||||||
double ret_tolerance_limit_ambient_pressure = 0.0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpmb_start_gradient(struct deco_state *ds)
|
extern "C" void vpmb_start_gradient(struct deco_state *ds)
|
||||||
{
|
{
|
||||||
int ci;
|
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;
|
int ci;
|
||||||
double n2_b, n2_c;
|
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;
|
time /= 60.0;
|
||||||
int ci;
|
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
|
// 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;
|
int ci;
|
||||||
double gradient;
|
double gradient;
|
||||||
@ -438,16 +436,15 @@ void calc_crushing_pressure(struct deco_state *ds, double pressure)
|
|||||||
n2_crushing_pressure = pressure - n2_inner_pressure;
|
n2_crushing_pressure = pressure - n2_inner_pressure;
|
||||||
he_crushing_pressure = pressure - he_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_n2_crushing_pressure[ci] = std::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_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 */
|
/* 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;
|
int ci;
|
||||||
struct gas_pressures pressures;
|
struct gas_pressures pressures;
|
||||||
bool icd = false;
|
bool icd = false;
|
||||||
@ -479,7 +476,7 @@ void add_segment(struct deco_state *ds, double pressure, struct gasmix gasmix, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DECO_CALC_DEBUG
|
#if DECO_CALC_DEBUG
|
||||||
void dump_tissues(struct deco_state *ds)
|
extern "C" void dump_tissues(struct deco_state *ds)
|
||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
printf("N2 tissues:");
|
printf("N2 tissues:");
|
||||||
@ -492,7 +489,7 @@ void dump_tissues(struct deco_state *ds)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void clear_vpmb_state(struct deco_state *ds)
|
extern "C" void clear_vpmb_state(struct deco_state *ds)
|
||||||
{
|
{
|
||||||
int ci;
|
int ci;
|
||||||
for (ci = 0; ci < 16; 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;
|
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;
|
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;
|
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 = std::make_unique<deco_state>();
|
||||||
if (!data) {
|
|
||||||
data = malloc(sizeof(struct deco_state));
|
|
||||||
*cached_datap = data;
|
|
||||||
}
|
|
||||||
*data = *src;
|
*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) {
|
if (keep_vpmb_state) {
|
||||||
int ci;
|
int ci;
|
||||||
for (ci = 0; ci < 16; 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;
|
data->max_bottom_ceiling_pressure = target->max_bottom_ceiling_pressure;
|
||||||
}
|
}
|
||||||
*target = *data;
|
*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;
|
int depth;
|
||||||
double pressure_delta;
|
double pressure_delta;
|
||||||
@ -570,7 +564,7 @@ int deco_allowed_depth(double tissues_tolerance, double surface_pressure, const
|
|||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_gf(short gflow, short gfhigh)
|
extern "C" void set_gf(short gflow, short gfhigh)
|
||||||
{
|
{
|
||||||
if (gflow != -1)
|
if (gflow != -1)
|
||||||
buehlmann_config.gf_low = (double)gflow / 100.0;
|
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;
|
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)
|
if (conservatism < 0)
|
||||||
vpmb_config.conservatism = 0;
|
vpmb_config.conservatism = 0;
|
||||||
@ -588,21 +582,21 @@ void set_vpmb_conservatism(short conservatism)
|
|||||||
vpmb_config.conservatism = 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 surface_pressure_bar = get_surface_pressure_in_mbar(dive, true) / 1000.0;
|
||||||
double gf_low = buehlmann_config.gf_low;
|
double gf_low = buehlmann_config.gf_low;
|
||||||
double gf_high = buehlmann_config.gf_high;
|
double gf_high = buehlmann_config.gf_high;
|
||||||
double gf;
|
double gf;
|
||||||
if (ds->gf_low_pressure_this_dive > surface_pressure_bar)
|
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);
|
(ds->gf_low_pressure_this_dive - surface_pressure_bar) * (gf_low - gf_high) + gf_high);
|
||||||
else
|
else
|
||||||
gf = gf_low;
|
gf = gf_low;
|
||||||
return gf;
|
return gf;
|
||||||
}
|
}
|
||||||
|
|
||||||
double regressiona(const struct deco_state *ds)
|
extern "C" double regressiona(const struct deco_state *ds)
|
||||||
{
|
{
|
||||||
if (ds->sum1 > 1) {
|
if (ds->sum1 > 1) {
|
||||||
double avxy = ds->sumxy / ds->sum1;
|
double avxy = ds->sumxy / ds->sum1;
|
||||||
@ -615,7 +609,7 @@ double regressiona(const struct deco_state *ds)
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double regressionb(const struct deco_state *ds)
|
extern "C" double regressionb(const struct deco_state *ds)
|
||||||
{
|
{
|
||||||
if (ds->sum1)
|
if (ds->sum1)
|
||||||
return ds->sumy / ds->sum1 - ds->sumx * regressiona(ds) / 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;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_regression(struct deco_state *ds)
|
extern "C" void reset_regression(struct deco_state *ds)
|
||||||
{
|
{
|
||||||
ds->sum1 = 0;
|
ds->sum1 = 0;
|
||||||
ds->sumxx = ds->sumx = 0L;
|
ds->sumxx = ds->sumx = 0L;
|
||||||
ds->sumy = ds->sumxy = 0.0;
|
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)
|
if (!ds->plot_depth)
|
||||||
return;
|
return;
|
||||||
17
core/deco.h
17
core/deco.h
@ -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 dump_tissues(struct deco_state *ds);
|
||||||
extern void set_gf(short gflow, short gfhigh);
|
extern void set_gf(short gflow, short gfhigh);
|
||||||
extern void set_vpmb_conservatism(short conservatism);
|
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 nuclear_regeneration(struct deco_state *ds, double time);
|
||||||
extern void vpmb_start_gradient(struct deco_state *ds);
|
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);
|
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
|
#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
|
||||||
|
|
||||||
#endif // DECO_H
|
#endif // DECO_H
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include "divelist.h"
|
#include "divelist.h"
|
||||||
#include "divelog.h"
|
#include "divelog.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
#include "errorhelper.h" // for verbose flag
|
#include "errorhelper.h"
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include "core/settings/qPrefDiveComputer.h"
|
#include "core/settings/qPrefDiveComputer.h"
|
||||||
|
|
||||||
@ -60,9 +60,9 @@ void device::showchanges(const std::string &n) const
|
|||||||
{
|
{
|
||||||
if (nickName != n) {
|
if (nickName != n) {
|
||||||
if (!n.empty())
|
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
|
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;
|
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())
|
if (!table || i >= table->fingerprints.size())
|
||||||
return 0;
|
return std::string();
|
||||||
struct fingerprint_record *fpr = &table->fingerprints[i];
|
struct fingerprint_record *fpr = &table->fingerprints[i];
|
||||||
// fromRawData() avoids one copy of the raw_data
|
std::string res(fpr->fsize * 2, ' ');
|
||||||
QByteArray hex = QByteArray::fromRawData((char *)fpr->raw_data, fpr->fsize).toHex();
|
for (unsigned int i = 0; i < fpr->fsize; ++i) {
|
||||||
return strdup(hex.constData());
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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_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_deviceid(struct fingerprint_table *table, unsigned int i);
|
||||||
extern uint32_t fp_get_diveid(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 *);
|
extern int is_default_dive_computer_device(const char *);
|
||||||
|
|
||||||
@ -100,6 +99,8 @@ struct fingerprint_table {
|
|||||||
std::vector<fingerprint_record> fingerprints;
|
std::vector<fingerprint_record> fingerprints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string fp_get_data(struct fingerprint_table *table, unsigned int i);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // DEVICE_H
|
#endif // DEVICE_H
|
||||||
|
|||||||
@ -11,8 +11,7 @@ setpoint::setpoint(unsigned char sp, unsigned char depth) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceDetails::DeviceDetails(QObject *parent) :
|
DeviceDetails::DeviceDetails() :
|
||||||
QObject(parent),
|
|
||||||
syncTime(false),
|
syncTime(false),
|
||||||
setPointFallback(0),
|
setPointFallback(0),
|
||||||
ccrMode(0),
|
ccrMode(0),
|
||||||
|
|||||||
@ -20,11 +20,10 @@ struct setpoint {
|
|||||||
setpoint(unsigned char sp = 0, unsigned char depth = 0);
|
setpoint(unsigned char sp = 0, unsigned char depth = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceDetails : public QObject
|
class DeviceDetails
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
explicit DeviceDetails(QObject *parent = 0);
|
DeviceDetails();
|
||||||
|
|
||||||
QString serialNo;
|
QString serialNo;
|
||||||
QString firmwareVersion;
|
QString firmwareVersion;
|
||||||
@ -103,5 +102,6 @@ public:
|
|||||||
unsigned safetyStopResetDepth;
|
unsigned safetyStopResetDepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(DeviceDetails);
|
||||||
|
|
||||||
#endif // DEVICEDETAILS_H
|
#endif // DEVICEDETAILS_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
14
core/dive.h
14
core/dive.h
@ -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)
|
for (_dc = &_dive->dc; _dc; _dc = _dc->next)
|
||||||
|
|
||||||
#define for_each_relevant_dc(_dive, _dc) \
|
#define for_each_relevant_dc(_dive, _dc) \
|
||||||
bool _all_planned = !has_planned(_dive, false); \
|
for (_dc = &_dive->dc; _dc; _dc = _dc->next) if (!is_logged(_dive) || !is_dc_planner(_dc))
|
||||||
for (_dc = &_dive->dc; _dc; _dc = _dc->next) if (_all_planned || !is_dc_planner(_dc))
|
|
||||||
|
|
||||||
extern struct dive *get_dive_by_uniq_id(int id);
|
extern struct dive *get_dive_by_uniq_id(int id);
|
||||||
extern int get_idx_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 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 *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 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 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_used(const struct dive *dive, int idx);
|
||||||
extern bool is_cylinder_prot(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 int total_weight(const struct dive *);
|
||||||
|
|
||||||
extern const char *existing_filename;
|
extern bool is_planned(const struct dive *dive);
|
||||||
|
extern bool is_logged(const struct dive *dive);
|
||||||
extern bool has_planned(const struct dive *dive, bool planned);
|
|
||||||
|
|
||||||
/* Get gasmixes at increasing timestamps.
|
/* Get gasmixes at increasing timestamps.
|
||||||
* In "evp", pass a pointer to a "struct event *" which is NULL-initialized on first invocation.
|
* 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 */
|
/* 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 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);
|
extern void update_setpoint_events(const struct dive *dive, struct divecomputer *dc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -230,8 +227,11 @@ extern void update_setpoint_events(const struct dive *dive, struct divecomputer
|
|||||||
* QVariants and through QML.
|
* QVariants and through QML.
|
||||||
*/
|
*/
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <string>
|
||||||
Q_DECLARE_METATYPE(struct dive *);
|
Q_DECLARE_METATYPE(struct dive *);
|
||||||
|
|
||||||
|
extern std::string existing_filename;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // DIVE_H
|
#endif // DIVE_H
|
||||||
|
|||||||
@ -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
|
* Match two dive computer entries against each other, and
|
||||||
* tell if it's the same dive. Return 0 if "don't know",
|
* 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);
|
free(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *manual_dc_name = "manually added dive";
|
static const char *planner_dc_name = "planned dive";
|
||||||
bool is_manually_added_dc(const struct divecomputer *dc)
|
|
||||||
|
bool is_dc_planner(const struct divecomputer *dc)
|
||||||
{
|
{
|
||||||
return dc && dc->samples <= 50 &&
|
return dc && same_string(dc->model, planner_dc_name);
|
||||||
same_string(dc->model, manual_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);
|
free((void *)dc->model);
|
||||||
dc->model = strdup(manual_dc_name);
|
dc->model = strdup(manual_dc_name);
|
||||||
|
|||||||
@ -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 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 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 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 uint32_t calculate_string_hash(const char *str);
|
||||||
extern bool is_manually_added_dc(const struct divecomputer *dc);
|
extern bool is_dc_planner(const struct divecomputer *dc);
|
||||||
extern void make_manually_added_dc(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) */
|
/* 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);
|
extern int match_one_dc(const struct divecomputer *a, const struct divecomputer *b);
|
||||||
|
|||||||
@ -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);
|
add_segment(ds, surface_pressure, air, surface_time, 0, OC, prefs.decosac, in_planner);
|
||||||
#if DECO_CALC_DEBUG & 2
|
#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);
|
dump_tissues(ds);
|
||||||
#endif
|
#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);
|
add_segment(ds, surface_pressure, air, surface_time, 0, OC, prefs.decosac, in_planner);
|
||||||
#if DECO_CALC_DEBUG & 2
|
#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);
|
dump_tissues(ds);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -767,18 +767,6 @@ struct dive *unregister_dive(int idx)
|
|||||||
return dive;
|
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()
|
void process_loaded_dives()
|
||||||
{
|
{
|
||||||
sort_dive_table(divelog.dives);
|
sort_dive_table(divelog.dives);
|
||||||
@ -989,7 +977,7 @@ void add_imported_dives(struct divelog *import_log, int flags)
|
|||||||
/* Remove old dives */
|
/* Remove old dives */
|
||||||
for (i = 0; i < dives_to_remove.nr; i++) {
|
for (i = 0; i < dives_to_remove.nr; i++) {
|
||||||
idx = get_divenr(dives_to_remove.dives[i]);
|
idx = get_divenr(dives_to_remove.dives[i]);
|
||||||
delete_single_dive(idx);
|
delete_single_dive(&divelog, idx);
|
||||||
}
|
}
|
||||||
dives_to_remove.nr = 0;
|
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;
|
current_dive = divelog.dives->nr > 0 ? divelog.dives->dives[divelog.dives->nr - 1] : NULL;
|
||||||
|
|
||||||
free_device_table(devices_to_add);
|
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. */
|
/* Inform frontend of reset data. This should reset all the models. */
|
||||||
emit_reset_signal();
|
emit_reset_signal();
|
||||||
|
|||||||
@ -62,7 +62,6 @@ void clear_dive_file_data();
|
|||||||
void clear_dive_table(struct dive_table *table);
|
void clear_dive_table(struct dive_table *table);
|
||||||
void move_dive_table(struct dive_table *src, struct dive_table *dst);
|
void move_dive_table(struct dive_table *src, struct dive_table *dst);
|
||||||
struct dive *unregister_dive(int idx);
|
struct dive *unregister_dive(int idx);
|
||||||
extern void delete_single_dive(int idx);
|
|
||||||
extern bool has_dive(unsigned int deviceid, unsigned int diveid);
|
extern bool has_dive(unsigned int deviceid, unsigned int diveid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include "divelist.h"
|
#include "divelist.h"
|
||||||
#include "divesite.h"
|
#include "divesite.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "errorhelper.h"
|
||||||
#include "filterpreset.h"
|
#include "filterpreset.h"
|
||||||
#include "trip.h"
|
#include "trip.h"
|
||||||
|
|
||||||
@ -63,14 +64,28 @@ struct divelog &divelog::operator=(divelog &&log)
|
|||||||
return *this;
|
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()
|
void divelog::clear()
|
||||||
{
|
{
|
||||||
while (dives->nr)
|
while (dives->nr > 0)
|
||||||
delete_single_dive(0);
|
delete_single_dive(this, dives->nr - 1);
|
||||||
while (sites->nr)
|
while (sites->nr)
|
||||||
delete_dive_site(get_dive_site(0, sites), sites);
|
delete_dive_site(get_dive_site(0, sites), sites);
|
||||||
if (trips->nr != 0) {
|
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;
|
trips->nr = 0;
|
||||||
}
|
}
|
||||||
clear_device_table(devices);
|
clear_device_table(devices);
|
||||||
|
|||||||
@ -34,6 +34,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void clear_divelog(struct divelog *);
|
void clear_divelog(struct divelog *);
|
||||||
|
extern void delete_single_dive(struct divelog *, int idx);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,7 +149,7 @@ void exportHtmlInitLogic(const QString &filename, struct htmlExportSetting &hes)
|
|||||||
|
|
||||||
QString searchPath = getSubsurfaceDataPath("theme");
|
QString searchPath = getSubsurfaceDataPath("theme");
|
||||||
if (searchPath.isEmpty()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
#include "divelist.h"
|
#include "divelist.h"
|
||||||
#include "divelog.h"
|
#include "divelog.h"
|
||||||
|
#include "errorhelper.h"
|
||||||
#include "membuffer.h"
|
#include "membuffer.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
#include "table.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
|
/* 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,
|
* 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 */
|
* 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;
|
int i;
|
||||||
struct dive_site *ds;
|
struct dive_site *ds;
|
||||||
@ -371,17 +372,17 @@ void add_dive_to_dive_site(struct dive *d, struct dive_site *ds)
|
|||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
if (!d) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (!ds) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (d->dive_site == ds)
|
if (d->dive_site == ds)
|
||||||
return;
|
return;
|
||||||
if (d->dive_site) {
|
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);
|
unregister_dive_from_dive_site(d);
|
||||||
}
|
}
|
||||||
idx = dive_table_get_insertion_index(&ds->dives, d);
|
idx = dive_table_get_insertion_index(&ds->dives, d);
|
||||||
|
|||||||
@ -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 *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_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(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_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 *);
|
struct dive_site *get_same_dive_site(const struct dive_site *);
|
||||||
bool dive_site_is_empty(struct dive_site *ds);
|
bool dive_site_is_empty(struct dive_site *ds);
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "errorhelper.h"
|
#include "errorhelper.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
#include "qthelper.h"
|
#include "qthelper.h"
|
||||||
#include <QDebug>
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@ -124,7 +123,6 @@ taxonomy_data reverseGeoLookup(degrees_t latitude, degrees_t longitude)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
report_error("geonames.org did not provide reverse lookup information");
|
report_error("geonames.org did not provide reverse lookup information");
|
||||||
//qDebug() << "no reverse geo lookup; geonames returned\n" << fullReply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return taxonomy;
|
return taxonomy;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
#include "downloadfromdcthread.h"
|
#include "downloadfromdcthread.h"
|
||||||
|
#include "core/errorhelper.h"
|
||||||
#include "core/libdivecomputer.h"
|
#include "core/libdivecomputer.h"
|
||||||
#include "core/qthelper.h"
|
#include "core/qthelper.h"
|
||||||
#include "core/range.h"
|
#include "core/range.h"
|
||||||
#include "core/settings/qPrefDiveComputer.h"
|
#include "core/settings/qPrefDiveComputer.h"
|
||||||
#include "core/divelist.h"
|
#include "core/divelist.h"
|
||||||
#include <QDebug>
|
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
#include "core/subsurface-string.h"
|
#include "core/subsurface-string.h"
|
||||||
#endif
|
#endif
|
||||||
@ -91,7 +91,7 @@ void DownloadThread::run()
|
|||||||
internalData->log = &log;
|
internalData->log = &log;
|
||||||
internalData->btname = strdup(m_data->devBluetoothName().toUtf8());
|
internalData->btname = strdup(m_data->devBluetoothName().toUtf8());
|
||||||
if (!internalData->descriptor) {
|
if (!internalData->descriptor) {
|
||||||
qDebug() << "No download possible when DC type is unknown";
|
report_info("No download possible when DC type is unknown");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get the list of transports that this device supports and filter depending on Bluetooth option
|
// 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)
|
if (transports == DC_TRANSPORT_USBHID)
|
||||||
internalData->devname = "";
|
internalData->devname = "";
|
||||||
|
|
||||||
qDebug() << "Starting download from " << getTransportString(transports);
|
report_info("Starting download from %s", qPrintable(getTransportString(transports)));
|
||||||
qDebug() << "downloading" << (internalData->force_download ? "all" : "only new") << "dives";
|
report_info("downloading %s dives", internalData->force_download ? "all" : "only new");
|
||||||
clear_divelog(&log);
|
clear_divelog(&log);
|
||||||
|
|
||||||
Q_ASSERT(internalData->log != nullptr);
|
Q_ASSERT(internalData->log != nullptr);
|
||||||
@ -117,11 +117,11 @@ void DownloadThread::run()
|
|||||||
errorText = do_libdivecomputer_import(internalData);
|
errorText = do_libdivecomputer_import(internalData);
|
||||||
if (errorText) {
|
if (errorText) {
|
||||||
error = str_error(errorText, internalData->devname, internalData->vendor, internalData->product);
|
error = str_error(errorText, internalData->devname, internalData->vendor, internalData->product);
|
||||||
qDebug() << "Finishing download thread:" << error;
|
report_info("Finishing download thread: %s", qPrintable(error));
|
||||||
} else {
|
} else {
|
||||||
if (!log.dives->nr)
|
if (!log.dives->nr)
|
||||||
error = tr("No new dives downloaded from dive computer");
|
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_vendor(internalData->vendor);
|
||||||
qPrefDiveComputer::set_product(internalData->product);
|
qPrefDiveComputer::set_product(internalData->product);
|
||||||
@ -156,7 +156,7 @@ void fill_computer_list()
|
|||||||
descriptorLookup[QString(vendor).toLower() + QString(product).toLower()] = descriptor;
|
descriptorLookup[QString(vendor).toLower() + QString(product).toLower()] = descriptor;
|
||||||
}
|
}
|
||||||
dc_iterator_free(iterator);
|
dc_iterator_free(iterator);
|
||||||
Q_FOREACH (QString vendor, vendorList) {
|
for (const QString &vendor: vendorList) {
|
||||||
auto &l = productList[vendor];
|
auto &l = productList[vendor];
|
||||||
std::sort(l.begin(), l.end());
|
std::sort(l.begin(), l.end());
|
||||||
}
|
}
|
||||||
@ -193,17 +193,17 @@ void fill_computer_list()
|
|||||||
void show_computer_list()
|
void show_computer_list()
|
||||||
{
|
{
|
||||||
unsigned int transportMask = get_supported_transports(NULL);
|
unsigned int transportMask = get_supported_transports(NULL);
|
||||||
qDebug() << "Supported dive computers:";
|
report_info("Supported dive computers:");
|
||||||
Q_FOREACH (QString vendor, vendorList) {
|
for (const QString &vendor: vendorList) {
|
||||||
QString msg = vendor + ": ";
|
QString msg = vendor + ": ";
|
||||||
Q_FOREACH (QString product, productList[vendor]) {
|
for (const QString &product: productList[vendor]) {
|
||||||
dc_descriptor_t *descriptor = descriptorLookup[vendor.toLower() + product.toLower()];
|
dc_descriptor_t *descriptor = descriptorLookup[vendor.toLower() + product.toLower()];
|
||||||
unsigned int transport = dc_descriptor_get_transports(descriptor) & transportMask;
|
unsigned int transport = dc_descriptor_get_transports(descriptor) & transportMask;
|
||||||
QString transportString = getTransportString(transport);
|
QString transportString = getTransportString(transport);
|
||||||
msg += product + " (" + transportString + "), ";
|
msg += product + " (" + transportString + "), ";
|
||||||
}
|
}
|
||||||
msg.chop(2);
|
msg.chop(2);
|
||||||
qDebug() << msg;
|
report_info("%s", qPrintable(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ QString DCDeviceData::devBluetoothName() const
|
|||||||
|
|
||||||
QString DCDeviceData::descriptor() const
|
QString DCDeviceData::descriptor() const
|
||||||
{
|
{
|
||||||
return "";
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DCDeviceData::bluetoothMode() const
|
bool DCDeviceData::bluetoothMode() const
|
||||||
|
|||||||
@ -95,9 +95,7 @@ struct mydescriptor {
|
|||||||
* stay like this for now.
|
* stay like this for now.
|
||||||
*/
|
*/
|
||||||
void fill_computer_list();
|
void fill_computer_list();
|
||||||
extern "C" {
|
|
||||||
void show_computer_list();
|
void show_computer_list();
|
||||||
}
|
|
||||||
extern QStringList vendorList;
|
extern QStringList vendorList;
|
||||||
extern QHash<QString, QStringList> productList;
|
extern QHash<QString, QStringList> productList;
|
||||||
extern QMap<QString, dc_descriptor_t *> descriptorLookup;
|
extern QMap<QString, dc_descriptor_t *> descriptorLookup;
|
||||||
|
|||||||
103
core/equipment.c
103
core/equipment.c
@ -16,6 +16,7 @@
|
|||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
#include "divelist.h"
|
#include "divelist.h"
|
||||||
#include "divelog.h"
|
#include "divelog.h"
|
||||||
|
#include "errorhelper.h"
|
||||||
#include "pref.h"
|
#include "pref.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
#include "table.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")
|
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++) {
|
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])))
|
if (same_string(text, cylinderuse_text[i]) || same_string(text, translate("gettextFromC", cylinderuse_text[i])))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return (enum cylinderuse)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a metric or an imperial tank info structure. Copies the passed-in string. */
|
/* 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);
|
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 */
|
/* placeholders for a few functions that we need to redesign for the Qt UI */
|
||||||
void add_cylinder_description(const cylinder_type_t *type)
|
void add_cylinder_description(const cylinder_type_t *type)
|
||||||
{
|
{
|
||||||
@ -131,7 +178,7 @@ void add_weightsystem_description(const weightsystem_t *weightsystem)
|
|||||||
if (!desc)
|
if (!desc)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < MAX_WS_INFO && ws_info[i].name != NULL; i++) {
|
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;
|
ws_info[i].grams = weightsystem->weight.grams;
|
||||||
return;
|
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 clone_weightsystem(weightsystem_t ws)
|
||||||
{
|
{
|
||||||
weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled };
|
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_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 clone_cylinder(cylinder_t cyl)
|
||||||
{
|
{
|
||||||
cylinder_t res = 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. */
|
* 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) {
|
||||||
if (idx < 0 || idx >= d->cylinders.nr + 1 || idx >= d->cylinders.allocated) {
|
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 NULL;
|
||||||
}
|
}
|
||||||
return &d->cylinders.cylinders[idx];
|
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)
|
cylinder_t *get_or_create_cylinder(struct dive *d, int idx)
|
||||||
{
|
{
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
fprintf(stderr, "Warning: accessing invalid cylinder %d\n", idx);
|
report_info("Warning: accessing invalid cylinder %d", idx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
while (idx >= d->cylinders.nr)
|
while (idx >= d->cylinders.nr)
|
||||||
@ -459,11 +510,37 @@ cylinder_t create_new_cylinder(const struct dive *d)
|
|||||||
cylinder_t cyl = empty_cylinder;
|
cylinder_t cyl = empty_cylinder;
|
||||||
fill_default_cylinder(d, &cyl);
|
fill_default_cylinder(d, &cyl);
|
||||||
cyl.start = cyl.type.workingpressure;
|
cyl.start = cyl.type.workingpressure;
|
||||||
cyl.manually_added = true;
|
|
||||||
cyl.cylinder_use = OC_GAS;
|
cyl.cylinder_use = OC_GAS;
|
||||||
return cyl;
|
return cyl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
static bool show_cylinder(const struct dive *d, int i)
|
||||||
{
|
{
|
||||||
if (is_cylinder_used(d, i))
|
if (is_cylinder_used(d, i))
|
||||||
|
|||||||
@ -70,7 +70,7 @@ struct weightsystem_table {
|
|||||||
|
|
||||||
#define MAX_WS_INFO (100)
|
#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_weights(const struct weightsystem_table *s, struct weightsystem_table *d);
|
||||||
extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d);
|
extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d);
|
||||||
extern weightsystem_t clone_weightsystem(weightsystem_t ws);
|
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 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 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 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);
|
extern int first_hidden_cylinder(const struct dive *d);
|
||||||
#ifdef DEBUG_CYL
|
#ifdef DEBUG_CYL
|
||||||
extern void dump_cylinders(struct dive *dive, bool verbose);
|
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 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_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 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 {
|
struct ws_info_t {
|
||||||
const char *name;
|
const char *name;
|
||||||
int grams;
|
int grams;
|
||||||
};
|
};
|
||||||
extern struct ws_info_t ws_info[MAX_WS_INFO];
|
extern struct ws_info_t ws_info[MAX_WS_INFO];
|
||||||
|
extern struct ws_info_t *get_weightsystem_description(const char *name);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "errorhelper.h"
|
#include "errorhelper.h"
|
||||||
#include "membuffer.h"
|
#include "membuffer.h"
|
||||||
#include "qthelper.h"
|
|
||||||
|
|
||||||
#if !defined(Q_OS_ANDROID) && !defined(__ANDROID__)
|
#if !defined(Q_OS_ANDROID) && !defined(__ANDROID__)
|
||||||
#define LOG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
|
#define LOG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
|
||||||
@ -21,7 +20,7 @@ int verbose;
|
|||||||
|
|
||||||
void report_info(const char *fmt, ...)
|
void report_info(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct membuffer buf = { 0 };
|
struct membufferpp buf;
|
||||||
|
|
||||||
VA_BUF(&buf, fmt);
|
VA_BUF(&buf, fmt);
|
||||||
strip_mb(&buf);
|
strip_mb(&buf);
|
||||||
@ -32,7 +31,7 @@ static void (*error_cb)(char *) = NULL;
|
|||||||
|
|
||||||
int report_error(const char *fmt, ...)
|
int report_error(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct membuffer buf = { 0 };
|
struct membufferpp buf;
|
||||||
|
|
||||||
VA_BUF(&buf, fmt);
|
VA_BUF(&buf, fmt);
|
||||||
strip_mb(&buf);
|
strip_mb(&buf);
|
||||||
@ -8,10 +8,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define __printf(x, y) __attribute__((__format__(__printf__, x, y)))
|
||||||
|
#else
|
||||||
|
#define __printf(x, y)
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int verbose;
|
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
|
extern void set_error_cb(void(*cb)(char *)); // Callback takes ownership of passed string
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
#include "divelog.h"
|
#include "divelog.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
|
#include "format.h"
|
||||||
#include "errorhelper.h"
|
#include "errorhelper.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "git-access.h"
|
#include "git-access.h"
|
||||||
@ -31,68 +32,53 @@
|
|||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int readfile(const char *filename, struct memblock *mem)
|
std::pair<std::string, int> readfile(const char *filename)
|
||||||
{
|
{
|
||||||
int ret, fd;
|
int ret, fd;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *buf;
|
|
||||||
|
|
||||||
mem->buffer = NULL;
|
|
||||||
mem->size = 0;
|
|
||||||
|
|
||||||
|
std::string res;
|
||||||
fd = subsurface_open(filename, O_RDONLY | O_BINARY, 0);
|
fd = subsurface_open(filename, O_RDONLY | O_BINARY, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return std::make_pair(res, fd);
|
||||||
ret = fstat(fd, &st);
|
ret = fstat(fd, &st);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
return std::make_pair(res, ret);
|
||||||
ret = -EINVAL;
|
|
||||||
if (!S_ISREG(st.st_mode))
|
if (!S_ISREG(st.st_mode))
|
||||||
goto out;
|
return std::make_pair(res, -EINVAL);
|
||||||
ret = 0;
|
|
||||||
if (!st.st_size)
|
if (!st.st_size)
|
||||||
goto out;
|
return std::make_pair(res, 0);
|
||||||
buf = malloc(st.st_size + 1);
|
// Sadly, this 0-initializes the string, just before overwriting it.
|
||||||
ret = -1;
|
// However, we use std::string, because that automatically 0-terminates
|
||||||
errno = ENOMEM;
|
// the data and the code expects that.
|
||||||
if (!buf)
|
res.resize(st.st_size);
|
||||||
goto out;
|
ret = read(fd, res.data(), res.size());
|
||||||
mem->buffer = buf;
|
|
||||||
mem->size = st.st_size;
|
|
||||||
ret = read(fd, buf, mem->size);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto free;
|
return std::make_pair(res, ret);
|
||||||
buf[ret] = 0;
|
// converting to int loses a bit but size will never be that big
|
||||||
if (ret == (int)mem->size) // converting to int loses a bit but size will never be that big
|
if (ret == (int)res.size()) {
|
||||||
goto out;
|
return std::make_pair(res, ret);
|
||||||
|
} else {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ret = -1;
|
return std::make_pair(res, -1);
|
||||||
free:
|
}
|
||||||
free(mem->buffer);
|
|
||||||
mem->buffer = NULL;
|
|
||||||
mem->size = 0;
|
|
||||||
out:
|
|
||||||
close(fd);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void zip_read(struct zip_file *file, const char *filename, struct divelog *log)
|
static void zip_read(struct zip_file *file, const char *filename, struct divelog *log)
|
||||||
{
|
{
|
||||||
int size = 1024, n, read = 0;
|
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;
|
read += n;
|
||||||
size = read * 3 / 2;
|
size = read * 3 / 2;
|
||||||
mem = realloc(mem, size);
|
mem.resize(size + 1);
|
||||||
}
|
}
|
||||||
mem[read] = 0;
|
mem[read] = 0;
|
||||||
(void) parse_xml_buffer(filename, mem, read, log, NULL);
|
(void) parse_xml_buffer(filename, mem.data(), read, log, NULL);
|
||||||
free(mem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
int success = 0;
|
||||||
/* Grr. libzip needs to re-open the file, it can't take a buffer */
|
/* 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;
|
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';
|
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;
|
sqlite3 *handle;
|
||||||
char dm4_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%ProfileBlob%'";
|
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);
|
retval = sqlite3_open(filename, &handle);
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
fprintf(stderr, "Database connection failed '%s'.\n", filename);
|
report_info("Database connection failed '%s'", filename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Testing if DB schema resembles Suunto DM5 database format */
|
/* Testing if DB schema resembles Suunto DM5 database format */
|
||||||
retval = sqlite3_exec(handle, dm5_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, dm5_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Suunto DM4 database format */
|
||||||
retval = sqlite3_exec(handle, dm4_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, dm4_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Shearwater database format */
|
||||||
retval = sqlite3_exec(handle, shearwater_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, shearwater_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Shearwater cloud database format */
|
||||||
retval = sqlite3_exec(handle, shearwater_cloud_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, shearwater_cloud_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Atomic Cobalt database format */
|
||||||
retval = sqlite3_exec(handle, cobalt_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, cobalt_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Divinglog database format */
|
||||||
retval = sqlite3_exec(handle, divinglog_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, divinglog_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
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 */
|
/* Testing if DB schema resembles Seac database format */
|
||||||
retval = sqlite3_exec(handle, seacsync_test, &db_test_func, 0, NULL);
|
retval = sqlite3_exec(handle, seacsync_test, &db_test_func, 0, NULL);
|
||||||
if (!retval) {
|
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);
|
sqlite3_close(handle);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -224,10 +207,11 @@ 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).
|
* 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
|
// hack to be able to provide a comment for the translated string
|
||||||
static char *csv_warning = QT_TRANSLATE_NOOP3("gettextFromC",
|
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",
|
"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");
|
"'Import log file' should be the same text as corresponding label in Import menu");
|
||||||
|
|
||||||
@ -237,7 +221,7 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo
|
|||||||
|
|
||||||
/* CSV files */
|
/* CSV files */
|
||||||
if (!strcasecmp(fmt, "CSV"))
|
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 */
|
/* Truly nasty intentionally obfuscated Cochran Anal software */
|
||||||
if (!strcasecmp(fmt, "CAN"))
|
if (!strcasecmp(fmt, "CAN"))
|
||||||
return try_to_open_cochran(filename, mem, log);
|
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;
|
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;
|
int ret;
|
||||||
char *fmt = strrchr(filename, '.');
|
const char *fmt = strrchr(filename, '.');
|
||||||
if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, log)) != 0)
|
if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, log)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!mem->size || !mem->buffer)
|
if (mem.empty())
|
||||||
return report_error("Out of memory parsing file %s\n", filename);
|
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)
|
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)) {
|
if (is_git_repository(filename, info) && open_git_repository(info)) {
|
||||||
const char *sha = get_sha(info->repo, info->branch);
|
std::string sha = get_sha(info->repo, info->branch);
|
||||||
if (!empty_string(sha) && same_string(sha, current_sha)) {
|
if (!sha.empty() && current_sha == sha) {
|
||||||
fprintf(stderr, "already have loaded SHA %s - don't load again\n", sha);
|
report_info("already have loaded SHA %s - don't load again", sha.c_str());
|
||||||
free(current_sha);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either the repository couldn't be opened, or the SHA couldn't
|
// Either the repository couldn't be opened, or the SHA couldn't
|
||||||
// be found.
|
// be found.
|
||||||
free(current_sha);
|
|
||||||
return false;
|
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 git_info info;
|
||||||
struct memblock mem;
|
const char *fmt;
|
||||||
char *fmt;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (is_git_repository(filename, &info)) {
|
if (is_git_repository(filename, &info)) {
|
||||||
if (!open_git_repository(&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
|
* Opening the cloud storage repository failed for some reason
|
||||||
* give up here and don't send errors about git repositories
|
* give up here and don't send errors about git repositories
|
||||||
*/
|
*/
|
||||||
if (info.is_subsurface_cloud) {
|
if (info.is_subsurface_cloud)
|
||||||
cleanup_git_info(&info);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ret = git_load_dives(&info, log);
|
int ret = git_load_dives(&info, log);
|
||||||
cleanup_git_info(&info);
|
|
||||||
return ret;
|
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 */
|
/* we don't want to display an error if this was the default file */
|
||||||
if (same_string(filename, prefs.default_filename))
|
if (same_string(filename, prefs.default_filename))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
|
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);
|
return report_error(translate("gettextFromC", "Empty file '%s'"), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt = strrchr(filename, '.');
|
fmt = strrchr(filename, '.');
|
||||||
if (fmt && (!strcasecmp(fmt + 1, "DB") || !strcasecmp(fmt + 1, "BAK") || !strcasecmp(fmt + 1, "SQL"))) {
|
if (fmt && (!strcasecmp(fmt + 1, "DB") || !strcasecmp(fmt + 1, "BAK") || !strcasecmp(fmt + 1, "SQL"))) {
|
||||||
if (!try_to_open_db(filename, &mem, log)) {
|
if (!try_to_open_db(filename, mem, log))
|
||||||
free(mem.buffer);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Divesoft Freedom */
|
/* Divesoft Freedom */
|
||||||
if (fmt && (!strcasecmp(fmt + 1, "DLF"))) {
|
if (fmt && (!strcasecmp(fmt + 1, "DLF")))
|
||||||
ret = parse_dlf_buffer(mem.buffer, mem.size, log);
|
return parse_dlf_buffer((unsigned char *)mem.data(), mem.size(), log);
|
||||||
free(mem.buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DataTrak/Wlog */
|
/* DataTrak/Wlog */
|
||||||
if (fmt && !strcasecmp(fmt + 1, "LOG")) {
|
if (fmt && !strcasecmp(fmt + 1, "LOG")) {
|
||||||
struct memblock wl_mem;
|
|
||||||
const char *t = strrchr(filename, '.');
|
const char *t = strrchr(filename, '.');
|
||||||
char *wl_name = memcpy(calloc(t - filename + 1, 1), filename, t - filename);
|
std::string wl_name = std::string(filename, t - filename) + ".add";
|
||||||
wl_name = realloc(wl_name, strlen(wl_name) + 5);
|
auto [wl_mem, err] = readfile(wl_name.c_str());
|
||||||
wl_name = strcat(wl_name, ".add");
|
if (err < 0) {
|
||||||
if((ret = readfile(wl_name, &wl_mem)) < 0) {
|
report_info("No file %s found. No WLog extensions.", wl_name.c_str());
|
||||||
fprintf(stderr, "No file %s found. No WLog extensions.\n", wl_name);
|
wl_mem.clear();
|
||||||
ret = datatrak_import(&mem, NULL, log);
|
|
||||||
} else {
|
|
||||||
ret = datatrak_import(&mem, &wl_mem, log);
|
|
||||||
free(wl_mem.buffer);
|
|
||||||
}
|
}
|
||||||
free(mem.buffer);
|
return datatrak_import(mem, wl_mem, log);
|
||||||
free(wl_name);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OSTCtools */
|
/* OSTCtools */
|
||||||
if (fmt && (!strcasecmp(fmt + 1, "DIVE"))) {
|
if (fmt && (!strcasecmp(fmt + 1, "DIVE"))) {
|
||||||
free(mem.buffer);
|
|
||||||
ostctools_import(filename, log);
|
ostctools_import(filename, log);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = parse_file_buffer(filename, &mem, log);
|
return parse_file_buffer(filename, mem, log);
|
||||||
free(mem.buffer);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
22
core/file.h
22
core/file.h
@ -7,23 +7,14 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
struct memblock {
|
|
||||||
void *buffer;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct divelog;
|
struct divelog;
|
||||||
struct zip;
|
struct zip;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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 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 parse_file(const char *filename, struct divelog *log);
|
||||||
extern int try_to_open_zip(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);
|
extern int subsurface_zip_close(struct zip *zip);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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
|
||||||
|
|
||||||
#endif // FILE_H
|
#endif // FILE_H
|
||||||
|
|||||||
@ -622,33 +622,29 @@ filter_constraint::~filter_constraint()
|
|||||||
delete data.string_list;
|
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)) {
|
if (filter_constraint_is_timestamp(c->type)) {
|
||||||
char *from_s = format_datetime(c->data.timestamp_range.from);
|
std::string from_s = format_datetime(c->data.timestamp_range.from);
|
||||||
char *to_s = format_datetime(c->data.timestamp_range.to);
|
std::string to_s = format_datetime(c->data.timestamp_range.to);
|
||||||
s = QString(from_s) + ',' + QString(to_s);
|
return from_s + ',' + to_s;
|
||||||
free(from_s);
|
|
||||||
free(to_s);
|
|
||||||
} else if (filter_constraint_is_string(c->type)) {
|
} else if (filter_constraint_is_string(c->type)) {
|
||||||
// TODO: this obviously breaks if the strings contain ",".
|
// TODO: this obviously breaks if the strings contain ",".
|
||||||
// That is currently not supported by the UI, but one day we might
|
// That is currently not supported by the UI, but one day we might
|
||||||
// have to escape the strings.
|
// 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)) {
|
} 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 {
|
} else {
|
||||||
s = QString::number(c->data.numerical_range.from) + ',' +
|
return std::to_string(c->data.numerical_range.from) + ',' +
|
||||||
QString::number(c->data.numerical_range.to);
|
std::to_string(c->data.numerical_range.to);
|
||||||
}
|
}
|
||||||
return copy_qstring(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter_constraint_set_stringlist(filter_constraint &c, const QString &s)
|
void filter_constraint_set_stringlist(filter_constraint &c, const QString &s)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_string(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.string_list->clear();
|
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)
|
void filter_constraint_set_timestamp_from(filter_constraint &c, timestamp_t from)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_timestamp(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.timestamp_range.from = from;
|
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)
|
void filter_constraint_set_timestamp_to(filter_constraint &c, timestamp_t to)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_timestamp(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.timestamp_range.to = to;
|
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)
|
void filter_constraint_set_integer_from(filter_constraint &c, int from)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.numerical_range.from = from;
|
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)
|
void filter_constraint_set_integer_to(filter_constraint &c, int to)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.numerical_range.to = to;
|
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)
|
void filter_constraint_set_float_from(filter_constraint &c, double from)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.numerical_range.from = display_to_base_unit(from, c.type);
|
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)
|
void filter_constraint_set_float_to(filter_constraint &c, double to)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.numerical_range.to = display_to_base_unit(to, c.type);
|
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)
|
void filter_constraint_set_multiple_choice(filter_constraint &c, uint64_t multiple_choice)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_multiple_choice(c.type)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
c.data.multiple_choice = multiple_choice;
|
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)
|
QString filter_constraint_get_string(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_string(c.type)) {
|
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 QString();
|
||||||
}
|
}
|
||||||
return c.data.string_list->join(",");
|
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)
|
int filter_constraint_get_integer_from(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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 -1;
|
||||||
}
|
}
|
||||||
return c.data.numerical_range.from;
|
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)
|
int filter_constraint_get_integer_to(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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 -1;
|
||||||
}
|
}
|
||||||
return c.data.numerical_range.to;
|
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)
|
double filter_constraint_get_float_from(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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 0.0;
|
||||||
}
|
}
|
||||||
return base_to_display_unit(c.data.numerical_range.from, c.type);
|
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)
|
double filter_constraint_get_float_to(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!is_numerical_constraint(c.type)) {
|
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 0.0;
|
||||||
}
|
}
|
||||||
return base_to_display_unit(c.data.numerical_range.to, c.type);
|
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)
|
timestamp_t filter_constraint_get_timestamp_from(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_timestamp(c.type)) {
|
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 0;
|
||||||
}
|
}
|
||||||
return c.data.timestamp_range.from;
|
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)
|
timestamp_t filter_constraint_get_timestamp_to(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_timestamp(c.type)) {
|
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 0;
|
||||||
}
|
}
|
||||||
return c.data.timestamp_range.to;
|
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)
|
uint64_t filter_constraint_get_multiple_choice(const filter_constraint &c)
|
||||||
{
|
{
|
||||||
if (!filter_constraint_is_multiple_choice(c.type)) {
|
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 0;
|
||||||
}
|
}
|
||||||
return c.data.multiple_choice;
|
return c.data.multiple_choice;
|
||||||
@ -823,7 +819,7 @@ static bool has_tags(const filter_constraint &c, const struct dive *d)
|
|||||||
{
|
{
|
||||||
QStringList dive_tags;
|
QStringList dive_tags;
|
||||||
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
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());
|
dive_tags.append(gettextFromC::tr(divemode_text_ui[d->dc.divemode]).trimmed());
|
||||||
return check(c, dive_tags);
|
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:
|
case FILTER_CONSTRAINT_SAC:
|
||||||
return check_numerical_range_non_zero(c, d->sac);
|
return check_numerical_range_non_zero(c, d->sac);
|
||||||
case FILTER_CONSTRAINT_LOGGED:
|
case FILTER_CONSTRAINT_LOGGED:
|
||||||
return has_planned(d, false) != c.negate;
|
return is_logged(d) != c.negate;
|
||||||
case FILTER_CONSTRAINT_PLANNED:
|
case FILTER_CONSTRAINT_PLANNED:
|
||||||
return has_planned(d, true) != c.negate;
|
return is_planned(d) != c.negate;
|
||||||
case FILTER_CONSTRAINT_DIVE_MODE:
|
case FILTER_CONSTRAINT_DIVE_MODE:
|
||||||
return check_multiple_choice(c, (int)d->dc.divemode); // should we be smarter and check all DCs?
|
return check_multiple_choice(c, (int)d->dc.divemode); // should we be smarter and check all DCs?
|
||||||
case FILTER_CONSTRAINT_TAGS:
|
case FILTER_CONSTRAINT_TAGS:
|
||||||
|
|||||||
@ -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 bool filter_constraint_has_time_widget(enum filter_constraint_type);
|
||||||
extern int filter_constraint_num_decimals(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 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
|
#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_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);
|
void filter_constraint_set_multiple_choice(filter_constraint &c, uint64_t);
|
||||||
bool filter_constraint_match_dive(const filter_constraint &c, const struct dive *d);
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -14,14 +14,9 @@ extern "C" int filter_presets_count(void)
|
|||||||
return (int)global_table().size();
|
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));
|
return global_table()[preset].data.fullText.originalQuery.toStdString();
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" char *filter_preset_fulltext_query(int preset)
|
|
||||||
{
|
|
||||||
return copy_qstring(global_table()[preset].data.fullText.originalQuery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const char *filter_preset_fulltext_mode(int preset)
|
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];
|
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)
|
extern "C" void filter_preset_set_name(struct filter_preset *preset, const char *name)
|
||||||
{
|
{
|
||||||
preset->name = 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.
|
// std::lower_bound does a binary search - the vector must be sorted.
|
||||||
filter_preset newEntry { name, d };
|
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
|
// 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;
|
int count = 2;
|
||||||
while (std::find_if(table.begin(), table.end(),
|
while (std::find_if(table.begin(), table.end(),
|
||||||
[&res](const filter_preset &preset)
|
[&res](const filter_preset &preset)
|
||||||
{ return preset.name == res; }) != table.end()) {
|
{ return preset.name == res; }) != table.end()) {
|
||||||
res = orig + "#" + QString::number(count);
|
res = orig + "#" + std::to_string(count);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
return res;
|
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)
|
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);
|
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);
|
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(),
|
auto it = std::find_if(global_table().begin(), global_table().end(),
|
||||||
[&name] (filter_preset &p) { return p.name == name; });
|
[&name] (filter_preset &p) { return p.name == name; });
|
||||||
return it != global_table().end() ? it - global_table().begin() : -1;
|
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;
|
return global_table()[preset].name;
|
||||||
}
|
}
|
||||||
@ -132,9 +117,9 @@ FilterData filter_preset_get(int preset)
|
|||||||
return global_table()[preset].data;
|
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());
|
return filter_preset_add_to_table(name, d, global_table());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,9 +18,9 @@ struct filter_constraint;
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include "divefilter.h"
|
#include "divefilter.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QStringList>
|
#include <string>
|
||||||
struct filter_preset {
|
struct filter_preset {
|
||||||
QString name;
|
std::string name;
|
||||||
FilterData data;
|
FilterData data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,13 +44,9 @@ extern "C" {
|
|||||||
|
|
||||||
// The C IO code accesses the filter presets via integer indices.
|
// The C IO code accesses the filter presets via integer indices.
|
||||||
extern int filter_presets_count(void);
|
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 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 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 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_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 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);
|
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;
|
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.
|
int filter_preset_id(const std::string &s); // for now, we assume that names are unique. returns -1 if no preset with that name.
|
||||||
QString filter_preset_name_qstring(int preset);
|
|
||||||
void filter_preset_set(int preset, const FilterData &d); // this will override a preset if the name already exists.
|
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);
|
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);
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -343,67 +343,30 @@ QString vqasprintf_loc(const char *fmt, va_list ap_in)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put a formated string respecting the default locale into a C-style array in UTF-8 encoding.
|
// TODO: Avoid back-and-forth conversion between UTF16 and UTF8.
|
||||||
// The only complication arises from the fact that we don't want to cut through multi-byte UTF-8 code points.
|
std::string casprintf_loc(const char *cformat, ...)
|
||||||
extern "C" int snprintf_loc(char *dst, size_t size, const char *cformat, ...)
|
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, cformat);
|
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();
|
QByteArray utf8 = vqasprintf_loc(cformat, ap).toUtf8();
|
||||||
const char *data = utf8.constData();
|
va_end(ap);
|
||||||
size_t utf8_size = utf8.size();
|
return std::string(utf8.constData(), 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int asprintf_loc(char **dst, const char *cformat, ...)
|
std::string __printf(1, 2) format_string_std(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, cformat);
|
va_start(ap, fmt);
|
||||||
int res = vasprintf_loc(dst, cformat, ap);
|
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);
|
va_end(ap);
|
||||||
return res;
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -11,19 +11,8 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
__printf(1, 2) QString qasprintf_loc(const char *cformat, ...);
|
__printf(1, 2) QString qasprintf_loc(const char *cformat, ...);
|
||||||
__printf(1, 0) QString vqasprintf_loc(const char *cformat, va_list ap);
|
__printf(1, 0) QString vqasprintf_loc(const char *cformat, va_list ap);
|
||||||
#endif
|
__printf(1, 2) std::string casprintf_loc(const char *cformat, ...);
|
||||||
|
__printf(1, 2) std::string format_string_std(const char *fmt, ...);
|
||||||
#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
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user