Compare commits

...

114 Commits

Author SHA1 Message Date
Dirk Hohndel
2098529152 Update mobile version number
There aren't really any mobile changes in here, but in order to create a new
mobile version with the latest libdivecomputer, this is useful.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 23:34:21 -07:00
Dirk Hohndel
ddc7e754bc Updates for 4.8.6 release
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 23:33:07 -07:00
Dirk Hohndel
a55b3dd2c1 build-system: macOS: more hacking around paths
This really is mostly for my scripting and how I build the official packages.
But there isn't much harm having it in the repo. And it makes my life easier.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 23:25:12 -07:00
Dirk Hohndel
d43032f01f Travis: update build options
This pulls the latest .travis.yml from master. Which among other things uses a
new tool chain for Mac. Which requires some changes to the Travis Mac build
script.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 20:36:03 +03:00
Robert C. Helling
95326274be Add various enhancements to profile export and dive data copy
... as suggested by Lubomir.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 09:57:53 +03:00
Robert C. Helling
f72853a597 Make struct dive const in plotPicturesInternal
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-04-08 09:56:05 +03:00
Berthold Stoeger
e254820e6c CHANGELOG.md update
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-08 09:55:25 +03:00
Berthold Stoeger
ba70bb490f Profile: plot pictures of correct dive
The pictures of the current dive were plotted on the profile.
In principle OK, as this is what the user is shown. Only on
export this results in all profiles having the same pictures.

Therefore, pass a dive argument to the picture-plotting function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-08 09:54:59 +03:00
Berthold Stoeger
a16cca1fcb Profile: add "synchronous" mode for picture plotting
The thumbnails were fetched in the background to achieve a
snappier UI. The problem with that is that on LaTeX etc.
export only placeholder thumbnails were shown.

Therefore, implement a synchronous mode. This only tries
to fetch cached thumbnails or calculate thumbnails for
images. Videos and remote files are not supported.

Fixes #1963

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-08 09:54:47 +03:00
Robert C. Helling
403c920f29 Copy dive description to clipboard
Upon "Copy dive", store a text description of the items
on the system clipboard.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-04-08 09:54:39 +03:00
Robert C. Helling
c6732e9b26 Export profile image
With Facebook support gone, we should offer a way to export
the profile image. This has been part of the TeX support
but this makes it explicit.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 09:54:19 +03:00
Dirk Hohndel
3998cb8245 Update libdivecomputer
Shearwater Teric: add support for the TAG INFO_EVENT

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-08 08:17:49 +03:00
Dirk Hohndel
fec354075f Update CHANGELOG.md
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:22:39 -07:00
Jonas Jensen
a85598a0e7 Ubuntu 18.10 LGTM build
I'm about to update the build environment on lgtm.com from Ubuntu 18.04 to 18.10, and this breaks your project. It appears that [libgit2 now depends on libmbedtls](https://packages.ubuntu.com/cosmic/libgit2-dev), and it [didn't do this before](https://packages.ubuntu.com/bionic/libgit2-dev). By default, your project links statically with libgit2, but static linking requires specifying all dependencies of the library, and your builds doesn't specify libmbedtls. I'm working around the problem here by passing the `LIBGIT2_DYNAMIC` option to your CMake script, which makes libgit2 dynamically linked, and dynamically linked libraries don't need to have their transitive dependencies specified.

I'm taking this opportunity to make a few more changes to `.lgtm.yml` to prevent problems in the future when we upgrade the build environment.
1. Pass `-DNO_DOCS=ON` to avoid building things we don't need.
2. Pass `DCMAKE_VERBOSE_MAKEFILE=ON` for ease of debugging build problems.
3. Remove the manual list of dependency packages and instead rely on LGTM's automatic dependency detection. The manual dependency list contained version numbers and was therefore not likely to keep working over time. The automatic dependency detection only works in the `configure` and `index` steps, so I moved some lines from `after_prepare` to `configure`.

Signed-off-by: Jonas Jensen <jonas@semmle.com>
2019-04-04 15:18:40 -07:00
Dirk Hohndel
6bf980d85e Profile: ensure the correct settingsChanged() function is called
Found via LGTM.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:18:18 -07:00
Dirk Hohndel
c792c00f07 Core: simplify ConnectionListModel
The complicated setup with the AddressRole is unnecessary. All we want to be
able to do is get the index of a specific text in the list. In hindsight I am
puzzled why I implemented this in such a complex fashion.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:18:07 -07:00
Dirk Hohndel
f1371adbb8 Misc: replace some FIXME comments
All these aren't actually things that need fixing, they are observations about
the code.

Given that LGTM.com reports FIXME comments as Alerts, let's change the ones
that aren't about things that need fixing to something more harmless.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:17:06 -07:00
Robert C. Helling
43fb4ef36b Desktop: fix another variable name conflict
Addresses LGTM.com issue.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:16:09 -07:00
Robert C. Helling
1f9d7f29c5 Desktop: fix yet another variable name conflict
Addresses LGTM.com issue.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:15:59 -07:00
Robert C. Helling
d6a5fc5386 Core: let TTS calculation use correct ascent velocities
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:15:47 -07:00
Robert C. Helling
faf34db515 Core: change FIXME language
Addresses LGTM.com issue.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:15:34 -07:00
Robert C. Helling
f4021bcecd Core: fix another variable name conflict
Addresses LGTM.com issue.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:15:20 -07:00
Robert C. Helling
101be9e967 Core: remove variable name conflict
Addresses LGTM.com issue.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:15:07 -07:00
Berthold Stoeger
167b41b6e5 Cleanup: unglobalize variables in datatrak.c
It's a drop in the bucket, but let's remove some unnecessary
global variables. With one exception these variables were only
used in one function anyway. The other one can be passed as a
parameter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-04 15:14:25 -07:00
Berthold Stoeger
5c625d8116 Cleanup: remove unused global variables from datatrak.c
lector_bytes and lector_word were used nowhere.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-04 15:10:48 -07:00
Dirk Hohndel
450bad9d7b build-system: LGTM: don't warn about short global names
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:10:00 -07:00
Berthold Stoeger
ac71705b53 Leak fix: make ostcFirmwareCheck a unique_ptr
ostcFirmwareCheck in DownloadFromDCWidget was neither freed
in the destructor, not freed if a new object was allocated.

Simply make it a unique_ptr<> to do all the work for us.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-04 15:09:31 -07:00
Dirk Hohndel
072bf67303 Core: remove variable name conflict
Having a char parameter with the same name as a global char * variable is confusing.

Found via LGTM.com

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:07:00 -07:00
Dirk Hohndel
421e093afd Core: cast before multiplication to avoid potential overflow
Found via LGTM.com

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:06:46 -07:00
Dirk Hohndel
7a9203eda2 Core: cast to the correct type
While in the specific calculations here there isn't really a risk that float
might overflow, it seems odd to cast to float in order to assign to double.

This caused an Alert via LGTM.com

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:06:32 -07:00
Michał Sawicz
d1b4669304 [snap] pull the desktop-qt5 part in
snapcraft doesn't support remote parts any more, and there's no
extension (the replacement for remote parts) for Qt yet.

Signed-off-by: Michał Sawicz <michal.sawicz@canonical.com>
2019-04-04 15:06:18 -07:00
Michał Sawicz
737d8f9c9e [snap] add missing source: stanzas
snapcfraft no longer defaults to `source: .`

Signed-off-by: Michał Sawicz <michal.sawicz@canonical.com>
2019-04-04 15:06:02 -07:00
Dirk Hohndel
dbddbfeec3 Bluetooth: don't free a resource created by new
Found via LGTM.com

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:05:19 -07:00
Dirk Hohndel
c93f7e4f8c Core: fix missing argument to report_error
The format requires a string argument.

Found via LGTM.com

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:04:59 -07:00
Dirk Hohndel
9fefd10390 build-system: add script to build only libdivecomputer
This is used on LGTM (and initially got lost when I merged those changes).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:04:42 -07:00
Dirk Hohndel
8889552b70 Cleanup: deal with lgtm.com Alerts
Small, obvious fixes.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:04:12 -07:00
Dirk Hohndel
eb2f811be4 build-system: add LGTM yaml file
This should allow LGTM.com to build the C/C++ code.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:03:53 -07:00
Dirk Hohndel
72f37f14c6 build-system: explicitly add libgit2 dependencies for LGTM
For some reason on LGTM these two libraries aren't automatically added to the
link line for Subsurface.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:03:40 -07:00
Dirk Hohndel
5e192f3c6f build-system: try to find libdivecomputer on LGTM
On LGTM we end up installing in /opt/out.

Also, fix a silly error in the existing code - don't look for libraries in
include directories.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:03:14 -07:00
Rolf Eike Beer
c0421ab637 JavaScript: remove needless variable assignments
Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
2019-04-04 15:02:52 -07:00
Rolf Eike Beer
c7e9825fc6 mark JavaScript variables as local
Found by LGTM.

Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
2019-04-04 15:02:42 -07:00
Dirk Hohndel
30ea5aa9f6 Desktop: ensure cloud storage email address is all lower case
We already do that on mobile and I was certain we used to do this for
desktop as well, but apparently that got lost somewhere...

This should solve the problems we are seeing for people with mixed case
email addresses.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 15:01:37 -07:00
Alexander Wilms
268b453a81 Update appdata screenshots
Signed-off-by: Alexander Wilms <f.alexander.wilms@gmail.com>
2019-04-04 14:54:41 -07:00
Berthold Stoeger
a3a1a74d1f Edit: use correct offset when changing dive times
The undo-work reversed the direction of the offset. This was apparently
only fixed when using the menu entry, but not when editing dives directly.
Invert the offset to get the correct time.

While doing so, remove a redundant if: First it checked whether the
dates are the same, then whether the offset is non-zero.

Fixes #1975.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-04 14:53:24 -07:00
Dirk Hohndel
736941870a core: move updatecheck to its own domain
This make it easier to move backend services around.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 14:52:31 -07:00
Lubomir I. Ivanov
e685e7e9de facebook: remove the featute from the code base
Remove from:
- unit tests
- desktop widgets
- preferences
- core intergration
- cmakefiles
- build scripts
- icons
- docs

Also remove the plugins and social network integration.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 10:24:01 -07:00
Dirk Hohndel
41de2f66e3 Update libdivecomputer
Shearwater: fix (again) per-cell ppO2 reporting
      Update the list of the Ratio dive computers
      Don't pass a NULL pointer to memcpy
      Use symbolic constants for the commands
      Add clock synchronization support
      Skip empty logbook entries
      Add filters for BLE communication
      Ignore zero tank pressure values

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-04-04 09:52:19 -07:00
Dirk Hohndel
a6e0cb79d1 Update to version 4.8.5
And cleanup (partially incorrect, due to cherry-picking) CHANGELOG.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-24 20:53:48 +13:00
Dirk Hohndel
2b9da3504b Android: accept 'Release' argument
This is mostly an artifact of how I build release packages. Otherwise
this likely isn't important.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-23 17:40:37 +13:00
Dirk Hohndel
e8c1ce7e2c Update Supported Divecomputers list
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-23 17:37:07 +13:00
Dirk Hohndel
cb31d67f61 Update mobile version number
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-23 17:35:26 +13:00
Dirk Hohndel
ec8eac185b Bluetooth: don't crash if BT is turned off
At least on a Mac we can get here without a discoveryAgent if BT is off,
so don't derefence the NULL pointer in that case.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-23 14:35:23 +13:00
Dirk Hohndel
95e6f0c700 Update libdivecomputer
shearwater: properly initialize the string caches
    Shearwater parser: add new harware model nr for Teric
    Merge git://github.com/libdivecomputer/libdivecomputer into Subsurface-NG

    Update with Jef's upstream:

     - add support for Cressi Goa and Cartesio

     - update the Shearwater PNF parser to Jef's version

     - misc minor fixes

    * git://github.com/libdivecomputer/libdivecomputer:
      Use the timezone setting of the dive computer
      Add support for the Cressi Goa and Cartesio
      Add an extra parameter for the initial CRC value
      Add support for the Ratio iDive Color series
      Shearwater Petrel Native Format parsing
      Shearwater: detect which logbook format is support
      Shearwater: add Teric to list of supported dive computers
      Shearwater: skip deleted dives
      Fix a potential buffer overflow

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-23 14:02:27 +13:00
Dirk Hohndel
0e1bd02df6 BLE debug: make things less verbose
Unless run with '-v -v -v'.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:07:26 +13:00
Dirk Hohndel
c000123121 libdivecomputer: small wording change in a warning
While in theory the DEVINFO event should give us the correct detected
product, it's also possible that the code that usually detects the
product gave up and returns an unknown model.

Try to have the message reflect that situation more accurately.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:07:19 +13:00
Dirk Hohndel
50eec0231c Windows/MXE: actually build HIDAPI library
Otherwise Suunto EON Steel & EON Core, Scubapro G2 & Aladin Square and
other, future USB HID dive computers won't be supported on Windows.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:07:04 +13:00
Dirk Hohndel
37be26bd8d Android: make sure we have the correct platforms installed
This should fix the current Travis build failures for Android.
It is odd how we have ANDROID_PLATFORM and ANDROID_PLATFORMS,
buf for now all I care about is that the Travis build completes.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:06:50 +13:00
Robert C. Helling
fc66c767fb Don't allow empty username for git
When no real name is set in /etc/passwd the username ends
up being ",,,". Git does not like that. Actually, only the
part before the first comma is the name, the rest is office
and phone number. We don't want those.

Before we only testing for the username being a NULL pointer.

Reported-by: Keith Grimes
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-01-22 13:06:17 +13:00
Berthold Stoeger
7598e2fce7 Download: don't refresh display if thread finished
After the downloading finished, the mainwindow-display is reset
via a signal. This is probably an artifact of old times, when
downloading was done into the main dive-list. Nowadays, this seems
to make little sense, as the main dive-list is not changed by download.

Remove the signal.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-22 13:06:01 +13:00
Jan Mulder
4b42837327 Travis: OpenSUSE 42.3 / Qt5.6 build issue, use openssl and no libressl
... and remove install of the default (old) libgit2 from OS. That old
(0.24.0) libgit2 will be replaced by a newer anyway, so useless to
install.

But the real change to get this Travis build running again is using
the well known openssl instead of libressl.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:06:01 +13:00
Dirk Hohndel
3c5c0185dd Travis: OpenSUSE 42.3 / Qt5.6, add missing curl
The install was missing curl.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl> Removed upgrade to newer libgit2.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:06:01 +13:00
Jan Mulder
78ad59b22f Build: build libgit2 from source when less than 0.26.0
We currently require a minimal version of libgit2 of 0.24.0. From
issue #1926 it seems that this version is too old. So, a simple test on
Linux to see the behaviour with such an old libgit2, I tried that.
Interestingly, with the current version of openssl that old libgit2
version does not even compile from source (known error in libgit2).

So, bump our minimal version of libgit2 to 0.26.0. That is also the
version we currently use on the Travis and official builds, so well
tested.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:06:01 +13:00
Dirk Hohndel
0bd75c8e9e build system: try harder to checkout the right version
And actually fail a build if that doesn't work.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:05:03 +13:00
Miika Turkia
ddac55a3f1 Use state structure for sample rate info
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
5a9a7f005f Shearwater Cloud mentioned in changelog
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
39d5860602 Use correct value for PO2
averagePPO2 appears to be correct value instead of currentPPO2SetPoint.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
6aa51c6232 Grab correct setpoint on Shearwater cloud import
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
f78f3075c4 Use different time field as it seems to be more correct
The starTimestamp is 4 hours apart on 2 different DCs within the sample
log. DiveDate on the dive_logs table seems to be correct, but must be
converted from human readable format.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
4aac746bf0 Sample rate varies between dives
Seems that Shearwater cloud stores sample rate into the database and
it is not constant within the log.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
f5ef586c72 Initial support for Shearwater Cloud
This works to some extent to part of a sample log I received. However,
still quite a bit more work is needed.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:36 +13:00
Miika Turkia
536017f42e Shearwater import: dive id might be large than int
I encountered this while implementing Shearwater Cloud import, but it
makes sense to increase the size for dive id for Shearwater Desktop as
well.

Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
2019-01-22 13:04:13 +13:00
Lubomir I. Ivanov
9b0b5fd489 update year to 2019 in about screens
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2019-01-22 13:03:25 +13:00
Dirk Hohndel
4935f07c9a Desktop: change preferences dialog name to 'Preferences'
Fixes #1912

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:03:13 +13:00
Dirk Hohndel
9e83106ff7 Travis: use 5.12.03 Docker image for Android
With this we have working arm and arm64 images (except that the arm64
image crashes when using Bluetooth).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
ee53639306 Android Dockerfile: add latest cmake 3.13.2
cmake 3.10 (which comes with Ubuntu 18.04) in combination with Qt 5.12
and the current qt-android-cmake causes an odd bug. Paths are set with a
double slash at the start '//' and later in the process this causes
garbled path names for some of the objects which in return causes the
APKs built in the container to fail.

Upgrading the cmake inside the container to 3.13.2 fixes that problem.

All the credit for identifying the problem and figuring out a solution
goes to Jan Mulder.

The resulting container was pushed to Docker hub as version to 5.12.03.

Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Jan Mulder
e964bae5b9 Android Docker: give the docker build its own output tree
Again, this is relevant for developers that do local docker android
builds, and normal android builds. A normal build uses the directory
subsurface-mobile-build-arm(64), and when doing a docker android build
this directory is shared between host and container. That sharing is
good, as it nicely exposes the build tree to the host (for easy compare,
inspection, etc.). But reusing the same tree as the local one is
inconvenient (and possibly dangerous due to all kinds of caching
issues).

So, give the docker build its own output tree for the shared
subsurface-mobile-build-arm(64) build output.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
968b7c1f7c Android Docker: give the android builder its own name
Users that use docker locally for Windows style build and Android style
builds will (probably) not like that we use the same name for both
docker containers. So, give the android builder its own name.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
a875fd0d44 Android build: always reconfigure libdivecomputer
This fix makes no difference from usage of this script in Travis
context, as every build starts from a clean VM, but the very few
developers that build for Android locally, and that want to use the new
style docker container builds as well, things are broken.

libdivecomputer has build artifacts in its source tree (and that source
tree is shared between local and docker run). So it happens that
libdivecomputer is configured locally, and afterwards fails to build
in docker build as its already configured, but not for the docker
image its now running in.

The fix is simple. Always reconfigure libdivecomputer when using this
script.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
86d3e59d70 Android: build both 32 and 64 bit binaries
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
55a0bed59f Travis: find the Android apk in the right spot
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
2153b95bf6 Travis: Android build wrapper now runs inside our container
So we don't need the pre-built binaries anymore, and we don't need the
travis_wait hack anymore for potentially slow downloads as that is all
installed in the container already.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
071bce0fd1 Android Dockerfile: ugly hack to deal with current NDK compile problems
As explained in commit 449d4ee33d ("Android build: add explanation for
huge hack").

It seems reasonable to add this to our Travis image as that is custom
made just to build our Android binaries.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
af6da3090a Android Dockerfile: add comments and try to shrink the image more
This image is downloaded on every Travis run. Making it smaller is important.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
8628567e31 Travis: build against the Qt 5.12 Android image
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
247513ad08 Android: update for Qt 5.12.0
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Jan Mulder
94fa935818 Android build: add explanation for huge hack
This had to be embedded in the build process (or better, solved for
real).

Using Cmake, Clang, NDK 18b, Qt 5.12 beta 4, some Subsurface code does
not compile. At this point in time, its fully unclear to me why we see the
error as it is.

Thing fail deep down in Qt and NDK headers on #include <cmath>. Error like
"::signbit is not in the global namespace". The most logic reason is an
improper order in which include paths are constructed in the build process.
Any attempt to find the real reason failed. Even very similar command lines
from a qmake build that succeed fail with a cmake style build.

The very very dirty hack is commenting out some lines in NDK 18b:

"./android-ndk-r18b/sources/cxx-stl/llvm-libc++/include/cmath

Comment lines 313-325, and all build, links and runs with no errors
related to this known at this point.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
1e0ac92dd7 Android build: always use -fPIC
make sure that all lib code is compiled with -fPIC as things will not
link due to error "requires unsupported dynamic reloc R_ARM_REL32" (for
arm build).

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
5f0ce37559 Android build: build openssl before libzip
On very clean builds not using the wrapper script, the compile of libzip
simply fails because it depend on openssl include files. Simply swap them
around.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
7f4180a777 Android build: fix openssl build, no_asm
Mysteriously, openssl does not compile with clang with a
sha256-armv4.S:2638:2: error: invalid instruction, did you mean: adr?
The easiest way out is compiling without no_asm. This obviously lowers
the bandwidth on the SSL link (as the asm code is there for performance
reasons), but it has no visible performance loss in my tests.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
b29a6e4cd2 Android build: add arm64 target and compile with clang
With a preparation done in the 4 commits before, now add the arm64 and
use clang instead of gcc as compiler infrastructure.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
cd75fff054 Android build: openssl, do not move source tree
Very annoyingly, openssl is re-build and downloaded numerous times
when doing partial builds. Reason for this, is that the original checked
out git repo is moved away, and build in source (as openssl does ...).

So, this simple change leaves the checked out repo in place, and
copies the tree to build in.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
c4aefc0d29 Android build: always install libzip.a in lib directory
A subtle one. When compiling for arm64, libzip is the only package we
use in mobile that installs its product in lib64. There is no reason for
this given the way our build process is. So, simply force the library to
reside in lib, independent if we are building arm or arm64
architectures.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
a2fb9fde07 Android build: do not hard code armv7
Simple cleanup. Do not hard code armv7 as we have QT_ARCH. This
allows, in the future, for arm64 builds as well.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Jan Mulder
78d11ed687 Android build: set newer versions and parameterize ANDROID_PLATFORM
Hard coding desired ANDROID_PLATFORM on multiple places is simply bad.
Fix this. Further, set the variables to a much newer state.

CAVEAT: this will likely break android build, so be careful on
bisecting. All fixed in next, related commits.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
1219225729 Travis: use Android docker image for build
This should make it easier to make changes to our build environment.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
64528cd378 Android: cleanup build wrapper script
This way it can be run both to create the docker container or
independently for a full build.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
295c323d51 Android: create docker container
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
c8c6035d79 Android: add Dockerfile for build environment
We'll use that on Travis, but anyone can use that on their system.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Dirk Hohndel
e46fea155d Android: allow running android-build-wrapper without building
This way we can use it to fetch dependencies we need up front.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 13:02:39 +13:00
Berthold Stoeger
5819076130 Mobile: fix editing dive site
Commit 68961a169efc37039cd3fda334efb9ad9927444f made it impossible
to edit a dive site on mobile if a dive-site was already set: If
divesite was non-null, no actions were taken. Remove the conditional.

Reported-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-22 13:00:25 +13:00
Lubomir I. Ivanov
b0afca5815 windows.c: fix wrong usage of wcslen() for utf8 conversation
wcslen() returns the number of characters in a wchar_t string.
In the case of WideCharToMultiByte() an estimate for the size of
the utf8 buffer is needed. Using wcslen() is incorrect for such a buffer,
because for any non-ASCII character the estimate will be off by 1 byte.

Call the following instead to obtain the proper UTF8 buffer size
for the conversation:
  WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL);

Also fix some missing "\n" in fprintf() calls.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2019-01-22 12:59:23 +13:00
Jan Mulder
a5a191e850 Core: fix BT on Linux, workaround Qt bug on 5.12.0
After upgrading to Qt 5.12.0, download over BT from a DC did not work
any more. On the console the message "Connecting to port is not
supported (Uuid required)". Linus noticed earlier that we do rather
strange processing in this part of the code related to selecting port 1
or port 5. This all seems not needed (any more), but broader testing is
advised. This being stripped from the code, the mentioned error from Qt
persisted. That is strange in itself, as we did not reference port
numbers any more.

Step 2 in this commit is actually using an uuid to the call to
connectToService. Choosing an uuid seems relatively straightforward as
we can use the same one we already use for Android. That is the default
BT RFCOMM Serial Port Profile uuid. Interestingly, when changing to this
uuid we run immediately in a Qt runtime error telling us "QDBusPendingReply:
type ManagedObjectList is not registered with QtDBus.". For these 2
unexpected Qt messages, QTBUG-72742 was made. Studying the Qt source
code at this point reveals a possible workaround. Simply create a local
QBluetoothLocalDevice object, which, behind the scenes registers the Qt
internal ManagedObjectList with QtDBus.

In the meantime, Qt agrees that QTBUG-72742 is valid, and that a fix is
to be expected in a future version. At that point in time, the
declaration of the QBluetoothLocalDevice can be deleted again.

In the end, interfacing over BT works again.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:59:05 +13:00
Jan Mulder
873a4c8f07 Bluetooth: all states other than HostPoweredOff qualify as valid
This is an attempt to fix issue #1896. While this seems a Qt issue in
combination with very specific Android devices, this might be a fix. Do
not check for a very specific state of the local BT controller, but just
check if it is powered on.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:58:52 +13:00
John Plaxco
3865c1ec0a Improve error reporting when exporting a selection of 0 dives.
If no dives are selected when trying to export a selection, a message
is shown that no dives were selected, but it's immediately hidden
behind a message saying that a temporary file could not be created.
In fact, the creation of the temporary file wasn't never attempted,
so the message that the user actually sees is misleading.

The solution chosen here is to duplicate the check that at least some
dives are selected, and abort early if that case is detected, rather
than continuing on to show the additional misleading message. Not
elegant, but it gets the job done.

Better solutions to this include refactoring prepare_dives_for_divelogs
to return something more descriptive than a bool, remove that check
from prepare_dives_for_divelogs entirely since it doesn't seem to be
a good fit there, or switch to exceptions for handling these problems
rather than return values. I don't have sufficient familiarity with
the codebase to attempt these more invasive changes, but they
should be considered in the future.

On a final note, some of the other error messages in this file start
with a capital letter, but the one relevant to this particular PR
does not. Again, I'm not familiar enough with the codebase (or
translations) to know if that's safe to change, so I'll leave that
for another time or another developer.

Reported-by: John Plaxco
Signed-off-by: John Plaxco <john@johnplaxco.com>
2019-01-22 12:58:03 +13:00
Dirk Hohndel
db29fb4e68 Mobile: deal with BT name and address when tapping Download
Instead of trying to update this whenever the connection text changes,
instead deal with it right before it actually gets used.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 12:57:37 +13:00
Dirk Hohndel
0f350bef98 Mobile: add helper function to fill in the BT name
For some devices the BT device name is different from the product name.
Make sure that name is available to the mobile UI. This helper fills it
in from the scan data (based on the device address).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 12:57:26 +13:00
Dirk Hohndel
f7a4327cd4 core: recognize Oceanic Pro Plus X over BLE
Just like with the Aqualung i770R in 7697003498 this name follows the
pattern of a model number in ASCII encoding, followed by the serial
number of the device.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 12:57:13 +13:00
Jan Mulder
cfc4fca6ad core: shift dive time in correct direction
Unsure where this bug got introduced, but when asking for the dive
time to be shifted 1 hour later, the divelist and the dive details
showed 1 our earlier.

Fixes: #1893

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:56:49 +13:00
Jan Mulder
fa4dd05dfd Android build: use our own gradle build spec
At this point in time there seems something wrong with jcenter that
is used to download all Android build artifacts from. It simply does
not find the needed stuff on there and our build fails. Its unclear
if this is a temporary issue at jcenter, or its just an intended change.

This fix is a bit of a hack. It provides our own gradle build spec
instead of the one that is provided from Qt (which is pulled in using
androiddeployqt). Added is a working download link to maven, and a
newer com.android.tools.build:gradle is used compared to Qt.

All this makes Travis happy again.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:55:03 +13:00
Dirk Hohndel
0d69b420a4 Travis: fix the windows-container build
Call apt update before trying to install things.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-01-22 12:54:44 +13:00
Jan Mulder
18c9db16a5 Android build: explicitly install using sdkmanager
Make sure all required Android SDK components are explicitly installed
before starting the actual build.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:54:30 +13:00
Jan Mulder
97178896d1 Android build: buildtools version is automatically detected
With commit 0d8fc7ef970e of qt-android-cmake, the buildtools version
is automatically detected. So do not try to pass it any more, as
this breaks the build.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-22 12:54:18 +13:00
Daniel Krupp
ad7f4e8656 Fix Cressi interface ftdi opening bug
The Cressi specific PID was not used
when  serial_ftdi_open_device tried
to open the device.

Reported-by: Daniel Krupp
Signed-off-by: Daniel Krupp <daniel.krupp@gmail.com>
2019-01-22 12:52:06 +13:00
Berthold Stoeger
df1586da22 Dive list: correctly translate trip date
Adapt get_trip_date_string() to use the same logic as get_dive_date_string():
Use the static "loc" object to translate date. Before, the trip
date was shown in C locale.

Reported-by: Philippe Massart <philippe@philmassart.net>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-22 12:50:54 +13:00
129 changed files with 1011 additions and 2093 deletions

17
.lgtm.yml Normal file
View File

@ -0,0 +1,17 @@
path_classifiers:
test:
- "tests/*"
extraction:
cpp:
configure:
command:
- export INSTALL_ROOT=/opt/out
- export PKG_CONFIG_PATH=$INSTALL_ROOT/lib/pkgconfig:$PKG_CONFIG_PATH
- bash -x ./scripts/build-libdivecomputer.sh
- mkdir _lgtm_build_dir
- cd _lgtm_build_dir
- cmake -DLIBGIT2_DYNAMIC=ON -DNO_DOCS=ON -DCMAKE_VERBOSE_MAKEFILE=ON ..
queries:
- exclude: "cpp/short-global-name"

View File

@ -9,13 +9,26 @@ matrix:
- env: SUBSURFACE_PLATFORM='mac'
os: osx
osx_image: xcode8
language: c++ ruby
osx_image: xcode10.1
language: c++
addons:
homebrew:
packages:
- xz
- hidapi
- libusb
- libxml2
- libxslt
- libzip
- openssl
- pkg-config
- libgit2
- libssh2
update: true
- env: SUBSURFACE_PLATFORM='windows'
os: linux
dist: trusty
sudo: required
language: c++
- env: SUBSURFACE_PLATFORM='windows-container'
@ -28,7 +41,6 @@ matrix:
- env: SUBSURFACE_PLATFORM='linux'
os: linux
dist: trusty
sudo: required
language: c++
addons:
apt:
@ -65,7 +77,6 @@ matrix:
- env: SUBSURFACE_PLATFORM='linux2'
os: linux
dist: trusty
sudo: required
language: c++
addons:
apt:
@ -156,6 +167,6 @@ after_success:
- source ${TRAVIS_BUILD_DIR}/scripts/${SUBSURFACE_PLATFORM}/after_success.sh
branches:
except:
- # Do not build tags that we create when we upload to GitHub Releases
- /^(?i:continuous)/
only:
- master
- /^v\d+\.\d+(\.\d+)?(-branch)?$/

View File

@ -1,4 +1,4 @@
- Tag: high level what changed (please replace this line with your first CHANGELOG entry)
---
* Always add new entries at the very top of this file above other existing entries and this note.
* Use this layout for new entries: `[Area]: [Details about the change] [reference thread / issue]`

View File

@ -40,7 +40,6 @@ option(NO_PRINTING "disable the printing support" OFF)
option(NO_USERMANUAL "don't include a viewer for the user manual" OFF)
#Options regarding enabling parts of subsurface
option(FBSUPPORT "allow posting to Facebook" ON)
option(BTSUPPORT "enable support for QtBluetooth (requires Qt5.4 or newer)" ON)
option(FTDISUPPORT "enable support for libftdi based serial" OFF)
option(USE_WEBENGINE "Use QWebEngine instead of QWebKit" OFF)
@ -270,6 +269,11 @@ endif()
set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} ${LIBDIVECOMPUTER_LIBRARIES} ${LIBGIT2_LIBRARIES} ${LIBUSB_LIBRARIES})
qt5_add_resources(SUBSURFACE_RESOURCES subsurface.qrc map-widget/qml/map-widget.qrc)
# hack to build successfully on LGTM
if(DEFINED ENV{LGTM_SRC})
set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} -lgssapi_krb5 -lhttp_parser)
endif()
# include translations
add_subdirectory(translations)
add_subdirectory(core)
@ -335,15 +339,10 @@ elseif(${SUBSURFACE_TARGET_EXECUTABLE} MATCHES "DesktopExecutable")
add_executable(${SUBSURFACE_TARGET} MACOSX_BUNDLE WIN32 ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES})
endif()
if(FBSUPPORT)
set(FACEBOOK_INTEGRATION facebook_integration)
add_dependencies(facebook_integration subsurface_generated_ui)
endif()
target_link_libraries(
${SUBSURFACE_TARGET}
subsurface_generated_ui
subsurface_interface
${FACEBOOK_INTEGRATION}
subsurface_profile
subsurface_statistics
subsurface_models_desktop
@ -411,14 +410,12 @@ if(ANDROID)
if((DEFINED ENV{KEYSTORE}) AND (DEFINED ENV{KEYSTORE_PASSWORD}))
add_qt_android_apk(${SUBSURFACE_TARGET}.apk ${SUBSURFACE_TARGET}
PACKAGE_SOURCES ${CMAKE_BINARY_DIR}/android-mobile DEPENDS ${ANDROID_NATIVE_LIBSSL} ${ANDROID_NATIVE_LIBCRYPT}
BUILDTOOLS_REVISION ${BUILDTOOLS_REVISION}
KEYSTORE $ENV{KEYSTORE} Subsurface-mobile KEYSTORE_PASSWORD $ENV{KEYSTORE_PASSWORD}
)
message(STATUS "KEYSTORE=$ENV{KEYSTORE} KEYSTORE_PASSWORD=$ENV{KEYSTORE_PASSWORD}")
else()
add_qt_android_apk(${SUBSURFACE_TARGET}.apk ${SUBSURFACE_TARGET}
PACKAGE_SOURCES ${CMAKE_BINARY_DIR}/android-mobile DEPENDS ${ANDROID_NATIVE_LIBSSL} ${ANDROID_NATIVE_LIBCRYPT}
BUILDTOOLS_REVISION ${BUILDTOOLS_REVISION}
)
message(STATUS "no KEYSTORE")
endif()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -2719,44 +2719,6 @@ There are two ways to export dive information from Subsurface:
- xref:S_Export_other[Export dive information to other destinations or formats]
[[S_Facebook]]
=== Exporting dive information to _Facebook_
Export of dives to _Facebook_ is handled differently from other types of export because
a connection to _Facebook_ is required, needing a _Facebook_ userID and password.
From the *Main Menu*, select _Share on -> Connect to -> Facebook_ (image *A* below)
A _Facebook_ login screen appears (image *B* below). Provide a _Facebook_ userID and password.
From the _Subsurface_ window its easy to determine whether _Subsurface_ has a valid connection to _Facebook_:
from the *Main Menu*, select _Share on_ (image *A*, below). Normally, the _Facebook_ option is greyed out. But
if there is a connection to _Facebook_, this option is active (i.e. in black color and can be selected).
Once logged into to _Facebook_ , a panel is shown with a message:
"_To disconnect Subsurface from your Facebook account, use the 'Share on' menu entry_."
Close this message panel.
image::images/facebook1.jpg["Figure: Facebook login",align="center"]
Having established a login to _Facebook_, transferring a dive profile to a _Facebook_ timeline is easy.
In the _Subsurface_ *Dive List* panel, highlight the dive to be transferred.
Then, from the *Main Menu*, select _Share on -> Facebook_. A dialogue box
is shown, determining the amount of additional information to be transferred
with the dive profile (image *A*, below). To transfer a dive profile to _Facebook_, the name of a
_Facebook_ album is needed. The checkboxes on the left hand side determine how much
additional information is added to the dive profile, shown in the text box
on the right hand side of the panel (image *A*, below). Customise the message that will be posted
with the dive profile by editing any of the information. After specifying additional information
and verifying the text, select the _OK_ button that triggers the transfer to _Facebook_. After the transfer
is done, an acknowledgement dialogue appears, indicating it was successful.
Both the album created and the post to your timeline are marked as
private. In order for friends to be able to see the post,
log into _Facebook_ using a browser or Facebook app and change its permissions.
image::images/facebook2.jpg["Figure: Facebook data submission",align="center"]
If required, then close the _Facebook_ connection by selecting, from the *Main Menu*,
_Share on -> Disconnect from -> Facebook_ (image *B* above).
[[S_Export_other]]
=== Export dive information to other destinations or formats
For non-_Facebook exports_, the export function can be found by selecting _File -> Export_, which brings up
@ -2790,6 +2752,8 @@ A dive log or part of it can be saved in several formats:
* _CSV dive profile_, that includes a large amount of detail for each dive, including
the depth profile, temperature and pressure information of each dive.
* _dive profile_, saves the Subsurface dive profile as a .png file
* _HTML_ format, in which the dive(s) are stored in HTML files, readable
with an Internet browser. Most modern web browsers are supported, but JavaScript
must be enabled. The HTML export cannot be changed or edited.

View File

@ -2934,55 +2934,6 @@ Hay dos posibilidades de exportar información de buceo desde _Subsurface_:
- xref:S_Export_other[Exportar información de buceo a otros destinos o formatos]
[[S_Facebook]]
=== Exportar información de buceo a _Facebook_
La exportación de inmersiones a _Facebook_ se maneja de forma diferente a otros
tipos de exportación porque se requiere una
conexión a esta red social y se necesita un usuario de _Facebook_ y su password.
Si, desde el menú principal, seleccionamos _Compartir -> Conectar a ->
Facebook_ (imagen *A* siguiente), se nos presentará una pantalla de acceso
(imagen *B* a continuación). Introducimos nuestro usuario y password de
_Facebook_.
Desde la ventana de _Subsurface_ es fácil saber si se tiene una conexión válida
con _Facebook_. Desde el *Menú principal*, selecciona _Compartir_
(ver imagen *A* a continuación). Normalmente la opción _Facebook_ está
desactivada, pero, si hay una conexión establecida, la opción está activa y
puede ser seleccionada.
Tras haber establecido una conexión con _Facebook_, se mostrará un panel con
un mensaje: "_Para desconectar Subsurface de tu cuenta de Facebook, utiliza la
entrada del menú 'Compartir'_."
Cierra este panel.
image::images/facebook1.jpg["Figure: Facebook login",align="center"]
Habiendo establecido una conexión a _Facebook_, transferir un perfil al
historial es fácil.
Selecciona en la *Lista de Inmersiones* de _Subsurface_ el buceo que quieras
transferir; entonces, desde el *Menú* selecciona _Compartir -> Facebook_,
aparecerá un diálogo en el que se definirá la cantidad de información
adicional que se desea compartir en el historial junto con el perfil (ver imagen
*A*, a continuación). Se necesita proporcionar el nombre de un álbum de _Facebook_
para poder enviar el perfil de inmersión. Las casillas seleccionables de la
izquierda nos permiten seleccionar la información que vamos a enviar. Esta
información se muestra en la ventana de texto de la derecha (ver imagen *A*
a continuación). El mensaje que se va a enviar se puede editar directamente en
esta ventana de texto. Tras haber elegido la información y verificado lo que se va
a subir, se selecciona el botón _OK_ lo que inicia la transferencia a _Facebook_.
Unos momentos después aparecerá un mensaje indicando una transferencia correcta.
El álbum creado y el post al historial se marcarán como privados. Para que
los amigos puedan ver el post habrá que cambiar los permisos desde un acceso
normal a _Facebook_ desde un navegador o desde la app de _Facebook_. Aunque
esto suponga un paso de más, los desarrolladores entienden que esta es la mejor
solución para evitar subidas no deseadas en el historial público.
image::images/facebook2.jpg["Figure: Facebook data submission",align="center"]
Si se considera necesario, cierra la conexión a _Facebook_, seleccionando
desde el *Menú principal*, _Compartir -> Desconectar de -> Facebook_ (imagen
*B* anterior).
[[S_Export_other]]
=== Exportar información de buceo a otros destinos o formatos
Para exportar a otros destinos,

View File

@ -2987,53 +2987,6 @@ Il y a deux façons d'exporter des informations de plongée depuis Subsurface:
- xref:S_Export_other[Exporter des informations de plongée vers d'autres
destinations ou formats]
[[S_Facebook]]
=== Export des informations de plongée vers _Facebook_
L'export des plongées vers _Facebook_ est géré différemment des autres types
d'export car une connexion vers _Facebook_ est nécessaire, nécessitant un
identifiant et un mot de passe. À partir du menu principal, sélectionnez
_Partager sur -> Connecter à -> Facebook_ (image *A* ci-dessous). Un écran
de connexion s'affiche (image *B* ci dessous). Entrez l'identifiant et le
mot de passe _Facebook_. Depuis la fenêtre _Subsurface_, il est facile de
vérifier si _Subsurface_ a une connection valide vers _Facebook_ : Depuis le
"Menu principal", sélectionnez _Partager sur_ (image *A*
ci-dessous). Normalement, l'option _Facebook_ est grisée. Mais si une
connection vers _Facebook_ existe, cette option est active (c'est à dire
écrit en noir et sélectionnable).
Once logged into to _Facebook_ , a panel is shown with a message: "_To
disconnect Subsurface from your Facebook account, use the 'Share on' menu
entry_." Close this message panel.
image::images/facebook1.jpg["Figure: Facebook login", align="center"]
Une fois qu'une connexion à _Facebook_ est établie, transférer un profil de
plongée vers _Facebook_ est facile. Dans le panneau *Liste des plongées* de
_Subsurface_, sélectionnez la plongée à transférer. Ensuite, à partir du
*menu principal*, sélectionnez _Partager sur -> Facebook_. Une fenêtre
s'affiche, pour déterminer quelles informations seront transférées avec le
profil de plongée (image *A* ci-dessous). Pour transférer un profil de
plongée vers _Facebook_, le nom d'un album _Facebook_ doit être fourni. Les
cases à cocher sur la partie gauche permettent de sélectionner des
informations supplémentaires à transférer avec le profil de plongée. Ces
informations sont affichées dans le champs de texte sur la partie droite du
panneau. (image *A* ci dessous). Personnalisez le message qui sera envoyé
avec le profil de plongée en modifiant les informations. Une fois les
informations supplémentaires ajoutées et vérifiées, sélectionner le bouton
_OK_ qui effectue le transfert vers _Facebook_. Après le transfert, une
fenêtre de confirmation apparait ,indiquant le succès du transfert.
À la fois l'album créé et la publication sur votre ligne temporelle seront
marquées comme privés. Pour que vos amis puissent la voir, connectez-vous à
_Facebook_ depuis un navigateur ou l'application Facebook et modifiez les
permissions.
image::images/facebook2.jpg["Figure: Facebook data submission", align="center"]
If required, then close the _Facebook_ connection by selecting, from the
*Main Menu*, _Share on -> Disconnect from -> Facebook_ (image *B* above).
[[S_Export_other]]
=== Exporter des informations de plongée vers d'autres destinations ou formats
For non-_Facebook exports_, the export function can be found by selecting

View File

@ -2545,49 +2545,6 @@ Er zijn twee manieren om duik informatie uit _Subsurface_ te exporteren:
- xref:S_Export_other[Exporteer duikinformatie naar andere bestemmingen of formaten]
[[S_Facebook]]
=== Exporteer duikinformatie naar _Facebook_
Exporteren naar _Facebook_ werkt op een andere manier dan andere vormen van
export, met name omdat er een verbinding met _Facebook_ aanwezig moet zijn die
is ingelogd. Selecteer vanuit het hoofdmenu _Deel via -> Facebook_ (zie figuur
*A* hieronder). Een inlogscherm voor _Facebook_ verschijnt (zie figuur
*B* hieronder), en log in bij _Facebook_.
Het is eenvoudig te zien in het hoofdmenu of er een verbinding met _Facebook_
actief is. In het _Deel via_ menu is de _Facebook knop_ grijs en niet-selecteerbaar
als er geen verbinding is (figuur *A* hieronder).
Eenmaal ingelogd op _Facebook_ wordt er een paneel getoond met het bericht:
"Gebruik het 'Deel via' menu om de verbinding van Subsurface met uw Facebook
account te sluiten.". Sluit dit paneel.
image::images/facebook1.jpg["Figuur: Facebook login",align="center"]
Met de verbinding met _Facebook_ geactiveerd is het overdragen van een duik naar
_Facebook_ eenvoudig. Selecteer eerst de duik in de *Duiklijst*. Selecteer dan
uit het hoofdmenu _Deel via -> Facebook_. Er verschijnt een dialoog, waarin
aangegeven kan worden welke informatie naast het duikprofiel, moet worden
overgedragen naar _Facebook_ (zie figuur *A* hieronder).
Om een duikprofiel naar _Facebook_ te exporteren is de naam van een (foto) album
nodig. De keuzevakjes aan de linker zijde bepalen welke data uit het logboek
eveneens wordt geëxporteerd. Deze verschijnen in het tekst veld aan de rechter zijde,
welke verder handmatig kan worden aangepast. Nadat alles naar wens is ingevuld,
kan via de _OK_ knop de feitelijke export worden gedaan. Als de export gereed is
volgt een bevestiging.
Zowel het album als de geëxporteerde profiel (met annotaties) is in _Facebook_ als
privé aangemerkt, en de rechten van de geëxporteerde data moeten dus handmatig
in _Facebook_ worden gezet zoals gewenst.
image::images/facebook2.jpg["Figuur: Facebook data submission",align="center"]
De verbinding met _Facebook_ kan nu worden afgesloten als dat gewenst is. Gebruik
hiervoor uit het hoofdmenu _Deel via -> Verbinding verbreken met -> Facebook_ (
figuur *B* hierboven).
[[S_Export_other]]
=== Exporteer duikinformatie naar andere bestemmingen of formaten
Andere dan _Facebook_ exports kunnen gevonden worden door in het hoofdmenu

View File

@ -2824,44 +2824,6 @@ image::images/Filterpanel.jpg["Рисунок: Панель фильтров",al
- xref:S_Export_other[Экспорт данных погружения в другие форматы]
[[S_Facebook]]
=== Экспорт информации о погружении в _Facebook_
Экспорт в _Facebook_ отличается от всех других видов экспорта, поскольку он требует подключения
учетной записи, что в свою очередь требует от вас логин и пароль _Facebook_. Для авторизации
необходимо в главном меню выбрать _Файл -> Настройки_ и там выбрать вкладку _Facebook_, на которой
вам будет представлена форма авторизации (см. рисунок *А* слева внизу). Авторизуйтесь своими логином
и паролем, после чего экран должен выглядеть как показано на рисунке *В*. При необходимости вы
можете отключить _Subsurface_ от _Facebook_, нажав на соответствующую кнопку.
image::images/facebook1.jpg["Рисунок: Авторизация Facebook",align="center"]
После того как соединение с _Facebook_ установлено, публикация профиля погружения в вашей Хронике не
составит проблем. Выберите погружение в списке и убедитесь в том, что именно этот дайв должен быть
опубликован. Нажмите кнопку с логотипом _Facebook_, расположенную в *Информационной панели* справа
от поля _Примечания_ (см. рисунок *А* ниже). По нажатию на эту кнопку вам будет представлено окно, в
котором вы можете выбрать какую дополнительную информацию опубликовать вместе с профилем погружения
(рисунок *В*). Обязательным является только поле _Альбом_. Кроме указания стандартных параметров
погружения, вы можете вручную отредактировать сопроводительный текст. Для отправки профиля
погружения в вашу Хронику _Facebook_ нажмите кнопку _ОК_. Спустя короткое время вы должны получить
подтверждение, что запись опубликована.
Созданный альбом и запись в хронике по умолчанию будут доступны только вам. Для того, чтобы ваши
друзья смогли увидеть эти записи, вам необходимо изменить настройки безопасности приложений,
войдя в _Facebook_ с помощью обычного броузера или приложения _Facebook_. Возможно это и является
некоторым неудобством, но разработчики придерживаются мнения, что такой дополнительный шаг позволит избежать нежелательных записей в вашей Хронике.
image::images/facebook2.jpg["Рисунок: Авторизация в Facebook",align="center"]
Разорвать соединение с _Facebook_ можно из *Настроек* приложения, либо просто закрыв _Subsurface_.
[[S_Export_other]]
=== Экспорт данных погружения в другие форматы
Функция экспорта доступна через главное меню _Файл -> Экспорт_. Диалог

View File

@ -1,9 +1,9 @@
# Subsurface [![Build Status](https://travis-ci.org/Subsurface-divelog/subsurface.svg?branch=master)](https://travis-ci.org/Subsurface-divelog/subsurface)
This is the README file for Subsurface 4.8.4
This is the README file for Subsurface 4.8.6
Please check the `ReleaseNotes.txt` for details about new features and
changes since Subsurface 4.8.3 (and earlier versions).
changes since Subsurface 4.8.5 (and earlier versions).
Subsurface can be found at http://subsurface-divelog.org
@ -38,10 +38,10 @@ development version) you can either get this via git or the release tar
ball. After cloning run the following command:
```
git checkout v4.8.4 (or whatever the last release is)
git checkout v4.8.6 (or whatever the last release is)
```
or download a tarball from http://subsurface-divelog.org/downloads/Subsurface-4.8.4.tgz
or download a tarball from http://subsurface-divelog.org/downloads/Subsurface-4.8.6.tgz
Detailed build instructions can be found in the INSTALL file.

View File

@ -2,6 +2,34 @@
= _Subsurface_ Release Notes
New in _Subsurface_ 4.8.6
~~~~~~~~~~~~~~~~~~~~~~~~~
- Desktop: update snap and appdata meta data
- Desktop: make sure cloud storage email addresses are lower case only
- Desktop: Fix editing of dive-time [#1975]
- Desktop: Add export option for profile picture [#1962]
- Export: fix picture thumbnails [#1963]
- Desktop: remove support for the "Share on Facebook" feature.
Rationale: It is fairly easy to share images on Facebook, thus it was decided
that this feature is redundant and should be removed from Subsurface.
- Dive computer support:
- Add initial support for tag events on Shearwater Teric
- Add support for additional Ratio dive computers
- several bug fixes for existing dive computers
New in _Subsurface_ 4.8.5
~~~~~~~~~~~~~~~~~~~~~~~~~
- Shearwater import: add suppport for importing Shearwater Cloud logs
- Core, Mobile: all controller states other than powered off are valid [#1903]
- Core: shift dive time in correct direction [#1893]
- Desktop: translate trip date
- Dive computer support:
- Fix support for Shearwater Teric with firmware v11
- Add support for Oceanic Pro Plus X over BLE
- Add support for the Cressi Goa and Cartesio
- Add support for the Ratio iDive Color series
- Add support for the Aqualung i300C
New in _Subsurface_ 4.8.4
~~~~~~~~~~~~~~~~~~~~~~~~~
- Windows: add experimental support for BTLE dive computers.

View File

@ -6,7 +6,7 @@
<li>Quantum X</li></ul>
</dd>
<dt>Aqualung</dt><dd><ul>
<li>i100, i200, i300, i450T, i550, i750TC, i770R</li></ul>
<li>i100, i200, i300, i300C, i450T, i550, i750TC, i770R</li></ul>
</dd>
<dt>Atomic Aquatics</dt><dd><ul>
<li>Cobalt, Cobalt 2</li></ul>
@ -21,7 +21,7 @@
<li>Commander I, Commander II, Commander TM, EMC-14, EMC-16, EMC-20H</li></ul>
</dd>
<dt>Cressi</dt><dd><ul>
<li>Drake, Edy, Giotto, Leonardo, Newton</li></ul>
<li>Cartesio, Drake, Edy, Giotto, Goa, Leonardo, Newton</li></ul>
</dd>
<dt>Dive Rite</dt><dd><ul>
<li>NiTek Q, NiTek Trio</li></ul>
@ -48,7 +48,7 @@
<li>Atom 1.0, Atom 2.0, Atom 3.0, Atom 3.1, Datamask, F10, F11, Geo, Geo 2.0, OC1, OCS, OCi, Pro Plus 2, Pro Plus 2.1, Pro Plus 3, 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, Versa Pro</li></ul>
</dd>
<dt>Ratio</dt><dd><ul>
<li>iDive Deep, iDive Easy, iDive Free, iDive Tech+, iX3M Deep, iX3M Easy, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Tech+, iX3M Reb, iX3M Tech+</li></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 Deep, iX3M Easy, iX3M Fancy, iX3M Pro , iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+, iX3M Reb, iX3M Tech+</li></ul>
</dd>
<dt>Reefnet</dt><dd><ul>
<li>Sensus, Sensus Pro, Sensus Ultra</li></ul>

View File

@ -1,12 +1,12 @@
# This file is automatically generated, please edit scripts/parse-descriptor.pl
Aeris: 500 AI, A300, A300 AI, A300CS, Atmos 2, Atmos AI, Atmos AI 2, Compumask, Elite, Elite T3, Epic, F10, F11, Manta, XR-1 NX, XR-2
Apeks: Quantum X
Aqualung: i100, i200, i300, i450T, i550, i750TC, i770R
Aqualung: i100, i200, i300, i300C, i450T, i550, i750TC, i770R
Atomic Aquatics: Cobalt, Cobalt 2
Beuchat: Mundial 2, Mundial 3, Voyager 2G
Citizen: Hyper Aqualand
Cochran: Commander I, Commander II, Commander TM, EMC-14, EMC-16, EMC-20H
Cressi: Drake, Edy, Giotto, Leonardo, Newton
Cressi: Cartesio, Drake, Edy, Giotto, Goa, Leonardo, Newton
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
Garmin: Descent Mk1
@ -15,7 +15,7 @@ Heinrichs Weikamp: Frog, OSTC, OSTC 2, OSTC 2 TR, OSTC 2C, OSTC 2N, OSTC 3, OSTC
Hollis: DG02, DG03, TX1
Mares: Airlab, Darwin, Darwin Air, Icon HD, Icon HD Net Ready, M1, M2, Matrix, Nemo, Nemo Air, Nemo Apneist, Nemo Excel, Nemo Steel, Nemo Titanium, Nemo Wide, Nemo Wide 2, Puck, Puck 2, Puck Air, Puck Pro, Quad, Quad Air, Smart, Smart Air, Smart Apnea
Oceanic: Atom 1.0, Atom 2.0, Atom 3.0, Atom 3.1, Datamask, F10, F11, Geo, Geo 2.0, OC1, OCS, OCi, Pro Plus 2, Pro Plus 2.1, Pro Plus 3, 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, Versa Pro
Ratio: iDive Deep, iDive Easy, iDive Free, iDive Tech+, iX3M Deep, iX3M Easy, iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Tech+, iX3M Reb, iX3M Tech+
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 Deep, iX3M Easy, iX3M Fancy, iX3M Pro , iX3M Pro Deep, iX3M Pro Easy, iX3M Pro Fancy, iX3M Pro Pro, iX3M Pro Reb, iX3M Pro Tech+, iX3M Reb, iX3M Tech+
Reefnet: Sensus, Sensus Pro, Sensus Ultra
Scubapro: Aladin Sport Matrix, Aladin Square, Chromis, G2, G2 Console, Mantis, Mantis 2, Meridian, XTender 5
Seabaer: T1, H3, HUDC

View File

@ -83,7 +83,7 @@
</activity>
</application>
<uses-sdk android:minSdkVersion="16"
<uses-sdk android:minSdkVersion="21"
android:targetSdkVersion="26" />
<supports-screens

View File

@ -0,0 +1,64 @@
/*******************************************************
* SPDX-License-Identifier: GPL-2.0
* Subsurface-Mobile own Gradle build spec. Derived from
* the one supplied by Qt.
*******************************************************/
buildscript {
repositories {
jcenter()
maven { url "https://dl.bintray.com/android/android-tools/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
allprojects {
repositories {
jcenter()
maven { url "https://dl.bintray.com/android/android-tools/" }
}
}
apply plugin: 'com.android.application'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
}

BIN
appdata/diveplanner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 827 KiB

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@ -21,13 +21,10 @@
</description>
<screenshots>
<screenshot type="default">
<image>https://subsurface-divelog.org/screenshots/main.png</image>
<image>https://raw.githubusercontent.com/Subsurface-divelog/subsurface/master/appdata/main.png</image>
</screenshot>
<screenshot>
<image>https://subsurface-divelog.org/screenshots/preferences.png</image>
</screenshot>
<screenshot>
<image>https://subsurface-divelog.org/screenshots/preferences2.png</image>
<image>https://raw.githubusercontent.com/Subsurface-divelog/subsurface/master/appdata/diveplanner.png</image>
</screenshot>
</screenshots>
<url type="homepage">https://subsurface-divelog.org</url>

View File

@ -22,6 +22,7 @@ HINTS
${CMAKE_CURRENT_SOURCE_DIR}/../libdivecomputer/include/
/usr/local/include
/usr/include
/opt/out/include
)
FIND_LIBRARY( LIBDIVECOMPUTER_LIBRARIES
@ -31,8 +32,9 @@ NAMES
HINTS
${CMAKE_CURRENT_SOURCE_DIR}/../install-root/lib
${CMAKE_CURRENT_SOURCE_DIR}/../libdivecomputer/src/.libs/
/usr/local/include
/usr/include
/usr/local/lib
/usr/lib
/opt/out/lib
)
INCLUDE( FindPackageHandleStandardArgs )

View File

@ -10,7 +10,7 @@ execute_process(
OUTPUT_VARIABLE CANONICAL_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(MOBILE_VERSION_STRING "2.1.5")
set(MOBILE_VERSION_STRING "2.1.7")
configure_file(${SRC} ${DST} @ONLY)
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")

View File

@ -63,7 +63,6 @@ set(SUBSURFACE_CORE_LIB_SRCS
git-access.c
gpslocation.cpp
imagedownloader.cpp
isocialnetworkintegration.cpp
libdivecomputer.c
liquivision.c
load-git.c
@ -81,7 +80,6 @@ set(SUBSURFACE_CORE_LIB_SRCS
import-csv.c
planner.c
plannernotes.c
pluginmanager.cpp
profile.c
qthelper.cpp
qt-init.cpp
@ -108,7 +106,6 @@ set(SUBSURFACE_CORE_LIB_SRCS
settings/qPrefDisplay.cpp
settings/qPrefDiveComputer.cpp
settings/qPrefDivePlanner.cpp
settings/qPrefFacebook.cpp
settings/qPrefGeneral.cpp
settings/qPrefGeocoding.cpp
settings/qPrefLanguage.cpp

View File

@ -74,6 +74,11 @@ static dc_descriptor_t *getDeviceType(QString btName)
product = "i770R";
}
if (btName.contains(QRegularExpression("^ER\\d{6}$"))) {
vendor = "Oceanic";
product = "Pro Plus X";
}
if (!vendor.isEmpty() && !product.isEmpty())
return descriptorLookup.value(vendor + product);
@ -97,10 +102,11 @@ BTDiscovery::BTDiscovery(QObject*) : m_btValid(false),
void BTDiscovery::BTDiscoveryReDiscover()
{
#if !defined(Q_OS_IOS)
qDebug() << "BTDiscoveryReDiscover: localBtDevice.isValid()" << localBtDevice.isValid();
if (localBtDevice.isValid() &&
localBtDevice.hostMode() == QBluetoothLocalDevice::HostConnectable) {
localBtDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff) {
btPairedDevices.clear();
qDebug() << "localDevice " + localBtDevice.name() + " is valid, starting discovery";
qDebug() << "BTDiscoveryReDiscover: localDevice " + localBtDevice.name() + " is powered on, starting discovery";
#else
// for iOS we can't use the localBtDevice as iOS is BLE only
// we need to find some other way to test if Bluetooth is enabled, though
@ -142,7 +148,7 @@ BTDiscovery::~BTDiscovery()
{
m_instance = NULL;
#if defined(BT_SUPPORT)
free(discoveryAgent);
delete discoveryAgent;
#endif
}
@ -310,6 +316,12 @@ bool BTDiscovery::checkException(const char* method, const QAndroidJniObject *ob
void BTDiscovery::discoverAddress(QString address)
{
// if we have a discovery agent, check if we know about the address and if not
// make sure we are looking for it
// (if we don't have a discoveryAgent then likely BT is off or something else went wrong)
if (!discoveryAgent)
return;
// let's make sure there is no device name mixed in with the address
QString btAddress;
btAddress = extractBluetoothAddress(address);

View File

@ -450,23 +450,23 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
// Get starting depth and temp (tank PSI???)
switch (config.type) {
case TYPE_GEMINI:
depth = (float) (log[CMD_START_DEPTH]
depth = (double) (log[CMD_START_DEPTH]
+ log[CMD_START_DEPTH + 1] * 256) / 4;
temp = log[CMD_START_TEMP];
psi = log[CMD_START_PSI] + log[CMD_START_PSI + 1] * 256;
sgc_rate = (float)(log[CMD_START_SGC]
sgc_rate = (double)(log[CMD_START_SGC]
+ log[CMD_START_SGC + 1] * 256) / 2;
profile_period = log[CMD_PROFILE_PERIOD];
break;
case TYPE_COMMANDER:
depth = (float) (log[CMD_START_DEPTH]
depth = (double) (log[CMD_START_DEPTH]
+ log[CMD_START_DEPTH + 1] * 256) / 4;
temp = log[CMD_START_TEMP];
profile_period = log[CMD_PROFILE_PERIOD];
break;
case TYPE_EMC:
depth = (float) log [EMC_START_DEPTH] / 256
depth = (double) log [EMC_START_DEPTH] / 256
+ log[EMC_START_DEPTH + 1];
temp = log[EMC_START_TEMP];
profile_period = log[EMC_PROFILE_PERIOD];
@ -503,7 +503,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
}
// Depth is in every sample
depth_sample = (float)(s[0] & 0x3F) / 4 * (s[0] & 0x40 ? -1 : 1);
depth_sample = (double)(s[0] & 0x3F) / 4 * (s[0] & 0x40 ? -1 : 1);
depth += depth_sample;
#ifdef COCHRAN_DEBUG
@ -528,13 +528,13 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
break;
case 2: // PSI change
psi -= (float)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 4;
psi -= (double)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 4;
break;
case 1: // SGC rate
sgc_rate -= (float)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 2;
sgc_rate -= (double)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 2;
break;
case 3: // Temperature
temp = (float)s[1] / 2 + 20;
temp = (double)s[1] / 2 + 20;
break;
}
break;
@ -544,7 +544,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
break;
case 1: // Temperature
temp = (float)s[1] / 2 + 20;
temp = (double)s[1] / 2 + 20;
break;
}
// Get NDL and deco information

View File

@ -1442,7 +1442,7 @@ static dc_status_t read_ostc_settings(dc_device_t *device, DeviceDetails *m_devi
unsigned char data[256] = {};
#ifdef DEBUG_OSTC_CF
// FIXME: how should we report settings not supported back?
// open question: how should we report settings not supported back?
unsigned char max_CF = 0;
#endif
rc = hw_ostc_device_eeprom_read(device, 0, data, sizeof(data));
@ -1829,7 +1829,7 @@ static dc_status_t write_ostc_settings(dc_device_t *device, DeviceDetails *m_dev
else if (gas5.type == 2)
data[33] = 5;
else
// FIXME: No gas was First?
// odd: No gas was First?
// Set gas 1 to first
data[33] = 1;
@ -1956,7 +1956,7 @@ static dc_status_t write_ostc_settings(dc_device_t *device, DeviceDetails *m_dev
else if (dil5.type == 2)
data[115] = 5;
else
// FIXME: No first diluent?
// odd: No first diluent?
// Set gas 1 to fist
data[115] = 1;
@ -2178,7 +2178,7 @@ void WriteSettingsThread::run()
}
break;
case DC_FAMILY_HW_OSTC3:
// FIXME: Is this the best way?
// Is this the best way?
if (m_deviceDetails->model == "OSTC 4")
rc = write_ostc4_settings(m_data->device, m_deviceDetails, DeviceThread::event_cb, this);
else

View File

@ -7,29 +7,15 @@ ConnectionListModel::ConnectionListModel(QObject *parent) :
{
}
QHash <int, QByteArray> ConnectionListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[AddressRole] = "address";
return roles;
}
QVariant ConnectionListModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= m_addresses.count())
return QVariant();
if (role != AddressRole)
if (role != Qt::DisplayRole)
return QVariant();
return m_addresses[index.row()];
}
QString ConnectionListModel::address(int idx) const
{
if (idx < 0 || idx >> m_addresses.count())
return QString();
return m_addresses[idx];
}
int ConnectionListModel::rowCount(const QModelIndex&) const
{
return m_addresses.count();

View File

@ -6,13 +6,8 @@
class ConnectionListModel : public QAbstractListModel {
Q_OBJECT
public:
enum CLMRole {
AddressRole = Qt::UserRole + 1
};
ConnectionListModel(QObject *parent = 0);
QHash<int, QByteArray> roleNames() const;
QVariant data(const QModelIndex &index, int role = AddressRole) const;
QString address(int idx) const;
QVariant data(const QModelIndex &index, int role) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
void addAddress(const QString address);
void removeAllAddresses();

View File

@ -15,12 +15,6 @@
#include "device.h"
#include "file.h"
unsigned char lector_bytes[2], lector_word[4], tmp_1byte, *byte;
unsigned int tmp_2bytes;
char is_nitrox, is_O2, is_SCR;
unsigned long tmp_4bytes;
long maxbuf;
static unsigned int two_bytes_to_int(unsigned char x, unsigned char y)
{
return (x << 8) + y;
@ -31,12 +25,12 @@ static unsigned long four_bytes_to_long(unsigned char x, unsigned char y, unsign
return ((long)x << 24) + ((long)y << 16) + ((long)z << 8) + (long)t;
}
static unsigned char *byte_to_bits(unsigned char byte)
static unsigned char *byte_to_bits(unsigned char byte_value)
{
unsigned char i, *bits = (unsigned char *)malloc(8);
for (i = 0; i < 8; i++)
bits[i] = byte & (1 << i);
bits[i] = byte_value & (1 << i);
return bits;
}
@ -146,7 +140,7 @@ static dc_status_t dt_libdc_buffer(unsigned char *ptr, int prf_length, int dc_mo
* Parses a mem buffer extracting its data and filling a subsurface's dive structure.
* Returns a pointer to last position in buffer, or NULL on failure.
*/
unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive)
static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, long maxbuf)
{
int rc, profile_length, libdc_model;
char *tmp_notes_str = NULL;
@ -156,13 +150,13 @@ unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive)
*compl_buffer,
*membuf = runner;
char buffer[1024];
unsigned char tmp_1byte, *byte;
unsigned int tmp_2bytes;
unsigned long tmp_4bytes;
struct dive_site *ds;
device_data_t *devdata = calloc(1, sizeof(device_data_t));
char is_nitrox = 0, is_O2 = 0, is_SCR = 0;
/*
* Reset global variables for new dive
*/
is_nitrox = is_O2 = is_SCR = 0;
device_data_t *devdata = calloc(1, sizeof(device_data_t));
/*
* Parse byte to byte till next dive entry
@ -581,7 +575,7 @@ int datatrak_import(struct memblock *mem, struct dive_table *table)
unsigned char *runner;
int i = 0, numdives = 0, rc = 0;
maxbuf = (long) mem->buffer + mem->size;
long maxbuf = (long) mem->buffer + mem->size;
// Verify fileheader, get number of dives in datatrak divelog, zero on error
numdives = read_file_header((unsigned char *)mem->buffer);
@ -597,7 +591,7 @@ int datatrak_import(struct memblock *mem, struct dive_table *table)
while ((i < numdives) && ((long) runner < maxbuf)) {
struct dive *ptdive = alloc_dive();
runner = dt_dive_parser(runner, ptdive);
runner = dt_dive_parser(runner, ptdive, maxbuf);
if (runner == NULL) {
report_error(translate("gettextFromC", "Error: no dive"));
free(ptdive);

View File

@ -292,7 +292,7 @@ double tissue_tolerance_calc(struct deco_state *ds, const struct dive *dive, dou
if (plot_depth) {
++sum1;
sumx += plot_depth;
sumxx += plot_depth * plot_depth;
sumxx += (long)plot_depth * plot_depth;
double n2_gradient, he_gradient, total_gradient;
n2_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_n2_gradient[ds->ci_pointing_to_guiding_tissue]);
he_gradient = update_gradient(ds, depth_to_bar(plot_depth, &displayed_dive), ds->bottom_he_gradient[ds->ci_pointing_to_guiding_tissue]);

View File

@ -1577,7 +1577,7 @@ static void simplify_dc_pressures(struct divecomputer *dc)
}
}
/* FIXME! sensor -> cylinder mapping? */
/* Do we need a sensor -> cylinder mapping? */
static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
{
if (idx >= 0 && idx < MAX_CYLINDERS) {
@ -2366,7 +2366,7 @@ static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, unsign
if (different_manual_pressures(cyl, target))
continue;
/* FIXME! Should we check sizes too? */
/* open question: Should we check sizes too? */
return i;
}
return -1;

View File

@ -500,6 +500,7 @@ extern void set_filename(const char *filename);
extern int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_shearwater_cloud_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_cobalt_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_divinglog_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table);
extern int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *table);

View File

@ -297,12 +297,8 @@ QStringList DCDeviceData::getProductListFromVendor(const QString &vendor)
int DCDeviceData::getMatchingAddress(const QString &vendor, const QString &product)
{
for (int i = 0; i < connectionListModel.rowCount(); i++) {
QString address = connectionListModel.address(i);
if (address.contains(product))
return i;
}
return -1;
Q_UNUSED(vendor)
return connectionListModel.indexOf(product);
}
DCDeviceData *DownloadThread::data()

View File

@ -132,6 +132,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
char dm4_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%ProfileBlob%'";
char dm5_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%SampleBlob%'";
char shearwater_test[] = "select count(*) from sqlite_master where type='table' and name='system' and sql like '%dbVersion%'";
char shearwater_cloud_test[] = "select count(*) from sqlite_master where type='table' and name='SyncV3MetadataDiveLog' and sql like '%CreatedDevice%'";
char cobalt_test[] = "select count(*) from sqlite_master where type='table' and name='TrackPoints' and sql like '%DepthPressure%'";
char divinglog_test[] = "select count(*) from sqlite_master where type='table' and name='DBInfo' and sql like '%PrgName%'";
int retval;
@ -167,6 +168,14 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
return retval;
}
/* Testing if DB schema resembles Shearwater cloud database format */
retval = sqlite3_exec(handle, shearwater_cloud_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_shearwater_cloud_buffer(handle, filename, mem->buffer, mem->size, table);
sqlite3_close(handle);
return retval;
}
/* Testing if DB schema resembles Atomic Cobalt database format */
retval = sqlite3_exec(handle, cobalt_test, &db_test_func, 0, NULL);
if (!retval) {

View File

@ -836,7 +836,7 @@ static struct git_repository *get_remote_repo(const char *localdir, const char *
if (is_subsurface_cloud)
(void)cleanup_local_cache(remote, branch);
else
report_error("local git cache at '%s' is corrupt");
report_error("local git cache at '%s' is corrupt", localdir);
return NULL;
}
return update_local_repo(localdir, remote, branch, rt);

View File

@ -84,9 +84,9 @@ static bool hasVideoFileExtension(const QString &filename)
// If the input-flag "tryDownload" is set to false, no download attempt is made. This is to
// prevent infinite loops, where failed image downloads would be repeated ad infinitum.
// Returns: fetched image, type
Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &filename, const QString &originalFilename, bool tryDownload)
Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &urlfilename, const QString &originalFilename, bool tryDownload)
{
QUrl url = QUrl::fromUserInput(filename);
QUrl url = QUrl::fromUserInput(urlfilename);
if (url.isLocalFile()) {
// We try to determine the type first by peeking into the file.
QString filename = url.toLocalFile();
@ -456,8 +456,23 @@ void Thumbnailer::imageDownloadFailed(QString filename)
workingOn.remove(filename);
}
QImage Thumbnailer::fetchThumbnail(const QString &filename)
QImage Thumbnailer::fetchThumbnail(const QString &filename, bool synchronous)
{
if (synchronous) {
// In synchronous mode, first try the thumbnail cache.
Thumbnail thumbnail = getThumbnailFromCache(filename);
if (!thumbnail.img.isNull())
return thumbnail.img;
// If that didn't work, try to thumbnail the image.
thumbnail = getHashedImage(filename, false);
if (thumbnail.type == MEDIATYPE_STILL_LOADING || thumbnail.img.isNull())
return failImage; // No support for delayed thumbnails (web).
int size = maxThumbnailSize();
return thumbnail.img.scaled(size, size, Qt::KeepAspectRatio);
}
QMutexLocker l(&lock);
// We are not currently fetching this thumbnail - add it to the list.

View File

@ -31,9 +31,13 @@ public:
static Thumbnailer *instance();
// Schedule a thumbnail for fetching or calculation.
// Returns a placeholder thumbnail. The actual thumbnail will be sent
// via a signal later.
QImage fetchThumbnail(const QString &filename);
// If synchronous is false, returns a placeholder thumbnail.
// The actual thumbnail will be sent via a signal later.
// If synchronous is true, try to fetch the actual thumbnail.
// In this mode only precalculated thumbnails or thumbnails
// from pictures are returned. Video extraction and remote
// images are not supported.
QImage fetchThumbnail(const QString &filename, bool synchronous);
// Schedule multiple thumbnails for forced recalculation
void calculateThumbnails(const QVector<QString> &filenames);

View File

@ -73,7 +73,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **colu
i = state->cur_cylinder_index;
}
add_gas_switch_event(state->cur_dive, get_dc(state), atoi(data[0]), i);
add_gas_switch_event(state->cur_dive, get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), i);
return 0;
}
@ -86,7 +86,7 @@ static int shearwater_profile_sample(void *param, int columns, char **data, char
sample_start(state);
if (data[0])
state->cur_sample->time.seconds = atoi(data[0]);
state->cur_sample->time.seconds = state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]);
if (data[1])
state->cur_sample->depth.mm = state->metric ? lrint(strtod_flags(data[1], NULL, 0) * 1000) : feet_to_mm(strtod_flags(data[1], NULL, 0));
if (data[2])
@ -137,7 +137,7 @@ static int shearwater_ai_profile_sample(void *param, int columns, char **data, c
sample_start(state);
if (data[0])
state->cur_sample->time.seconds = atoi(data[0]);
state->cur_sample->time.seconds = state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]);
if (data[1])
state->cur_sample->depth.mm = state->metric ? lrint(strtod_flags(data[1], NULL, 0) * 1000) : feet_to_mm(strtod_flags(data[1], NULL, 0));
if (data[2])
@ -202,11 +202,11 @@ static int shearwater_dive(void *param, int columns, char **data, char **column)
struct parser_state *state = (struct parser_state *)param;
sqlite3 *handle = state->sql_handle;
char *err = NULL;
char get_profile_template[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,firstStopDepth,firstStopTime from dive_log_records where diveLogId=%d";
char get_profile_template_ai[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,aiSensor0_PressurePSI,aiSensor1_PressurePSI,firstStopDepth,firstStopTime from dive_log_records where diveLogId = %d";
char get_cylinder_template[] = "select fractionO2,fractionHe from dive_log_records where diveLogId = %d group by fractionO2,fractionHe";
char get_changes_template[] = "select a.currentTime,a.fractionO2,a.fractionHe from dive_log_records as a,dive_log_records as b where (a.id - 1) = b.id and (a.fractionO2 != b.fractionO2 or a.fractionHe != b.fractionHe) and a.diveLogId=b.divelogId and a.diveLogId = %d";
char get_mode_template[] = "select distinct currentCircuitSetting from dive_log_records where diveLogId = %d";
char get_profile_template[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,firstStopDepth,firstStopTime from dive_log_records where diveLogId=%ld";
char get_profile_template_ai[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,aiSensor0_PressurePSI,aiSensor1_PressurePSI,firstStopDepth,firstStopTime from dive_log_records where diveLogId = %ld";
char get_cylinder_template[] = "select fractionO2,fractionHe from dive_log_records where diveLogId = %ld group by fractionO2,fractionHe";
char get_changes_template[] = "select a.currentTime,a.fractionO2,a.fractionHe from dive_log_records as a,dive_log_records as b where (a.id - 1) = b.id and (a.fractionO2 != b.fractionO2 or a.fractionHe != b.fractionHe) and a.diveLogId=b.divelogId and a.diveLogId = %ld";
char get_mode_template[] = "select distinct currentCircuitSetting from dive_log_records where diveLogId = %ld";
char get_buffer[1024];
dive_start(state);
@ -214,7 +214,131 @@ static int shearwater_dive(void *param, int columns, char **data, char **column)
state->cur_dive->when = (time_t)(atol(data[1]));
int dive_id = atoi(data[11]);
long int dive_id = atol(data[11]);
if (data[2])
add_dive_site(data[2], state->cur_dive, state);
if (data[3])
utf8_string(data[3], &state->cur_dive->buddy);
if (data[4])
utf8_string(data[4], &state->cur_dive->notes);
state->metric = atoi(data[5]) == 1 ? 0 : 1;
/* TODO: verify that metric calculation is correct */
if (data[6])
state->cur_dive->dc.maxdepth.mm = state->metric ? lrint(strtod_flags(data[6], NULL, 0) * 1000) : feet_to_mm(strtod_flags(data[6], NULL, 0));
if (data[7])
state->cur_dive->dc.duration.seconds = atoi(data[7]) * 60;
if (data[8])
state->cur_dive->dc.surface_pressure.mbar = atoi(data[8]);
/*
* TODO: the deviceid hash should be calculated here.
*/
settings_start(state);
dc_settings_start(state);
if (data[9])
utf8_string(data[9], &state->cur_settings.dc.serial_nr);
if (data[10]) {
switch (atoi(data[10])) {
case 2:
state->cur_settings.dc.model = strdup("Shearwater Petrel/Perdix");
break;
case 4:
state->cur_settings.dc.model = strdup("Shearwater Predator");
break;
default:
state->cur_settings.dc.model = strdup("Shearwater import");
break;
}
}
state->cur_settings.dc.deviceid = atoi(data[9]);
dc_settings_end(state);
settings_end(state);
if (data[10]) {
switch (atoi(data[10])) {
case 2:
state->cur_dive->dc.model = strdup("Shearwater Petrel/Perdix");
break;
case 4:
state->cur_dive->dc.model = strdup("Shearwater Predator");
break;
default:
state->cur_dive->dc.model = strdup("Shearwater import");
break;
}
}
if (data[11]) {
snprintf(get_buffer, sizeof(get_buffer) - 1, get_mode_template, dive_id);
retval = sqlite3_exec(handle, get_buffer, &shearwater_mode, state, &err);
if (retval != SQLITE_OK) {
fprintf(stderr, "%s", "Database query shearwater_mode failed.\n");
return 1;
}
}
snprintf(get_buffer, sizeof(get_buffer) - 1, get_cylinder_template, dive_id);
retval = sqlite3_exec(handle, get_buffer, &shearwater_cylinders, state, &err);
if (retval != SQLITE_OK) {
fprintf(stderr, "%s", "Database query shearwater_cylinders failed.\n");
return 1;
}
snprintf(get_buffer, sizeof(get_buffer) - 1, get_changes_template, dive_id);
retval = sqlite3_exec(handle, get_buffer, &shearwater_changes, state, &err);
if (retval != SQLITE_OK) {
fprintf(stderr, "%s", "Database query shearwater_changes failed.\n");
return 1;
}
snprintf(get_buffer, sizeof(get_buffer) - 1, get_profile_template_ai, dive_id);
retval = sqlite3_exec(handle, get_buffer, &shearwater_ai_profile_sample, state, &err);
if (retval != SQLITE_OK) {
snprintf(get_buffer, sizeof(get_buffer) - 1, get_profile_template, dive_id);
retval = sqlite3_exec(handle, get_buffer, &shearwater_profile_sample, state, &err);
if (retval != SQLITE_OK) {
fprintf(stderr, "%s", "Database query shearwater_profile_sample failed.\n");
return 1;
}
}
dive_end(state);
return SQLITE_OK;
}
static int shearwater_cloud_dive(void *param, int columns, char **data, char **column)
{
UNUSED(columns);
UNUSED(column);
int retval = 0;
struct parser_state *state = (struct parser_state *)param;
sqlite3 *handle = state->sql_handle;
char *err = NULL;
char get_profile_template[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,firstStopDepth,firstStopTime from dive_log_records where diveLogId=%ld";
char get_profile_template_ai[] = "select currentTime,currentDepth,waterTemp,averagePPO2,currentNdl,CNSPercent,decoCeiling,aiSensor0_PressurePSI,aiSensor1_PressurePSI,firstStopDepth,firstStopTime from dive_log_records where diveLogId = %ld";
char get_cylinder_template[] = "select fractionO2 / 100,fractionHe / 100 from dive_log_records where diveLogId = %ld group by fractionO2,fractionHe";
char get_changes_template[] = "select a.currentTime,a.fractionO2 / 100,a.fractionHe /100 from dive_log_records as a,dive_log_records as b where (a.id - 1) = b.id and (a.fractionO2 != b.fractionO2 or a.fractionHe != b.fractionHe) and a.diveLogId=b.divelogId and a.diveLogId = %ld";
char get_mode_template[] = "select distinct currentCircuitSetting from dive_log_records where diveLogId = %ld";
char get_buffer[1024];
dive_start(state);
state->cur_dive->number = atoi(data[0]);
state->cur_dive->when = (time_t)(atol(data[1]));
long int dive_id = atol(data[11]);
if (data[12])
state->sample_rate = atoi(data[12]);
else
state->sample_rate = 0;
if (data[2])
add_dive_site(data[2], state->cur_dive, state);
@ -327,6 +451,9 @@ int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char *buffer
state.target_table = table;
state.sql_handle = handle;
// So far have not seen any sample rate in Shearwater Desktop
state.sample_rate = 0;
char get_dives[] = "select l.number,timestamp,location||' / '||site,buddy,notes,imperialUnits,maxDepth,maxTime,startSurfacePressure,computerSerial,computerModel,i.diveId FROM dive_info AS i JOIN dive_logs AS l ON i.diveId=l.diveId";
retval = sqlite3_exec(handle, get_dives, &shearwater_dive, &state, &err);
@ -340,3 +467,29 @@ int parse_shearwater_buffer(sqlite3 *handle, const char *url, const char *buffer
return 0;
}
int parse_shearwater_cloud_buffer(sqlite3 *handle, const char *url, const char *buffer, int size,
struct dive_table *table)
{
UNUSED(buffer);
UNUSED(size);
int retval;
char *err = NULL;
struct parser_state state;
init_parser_state(&state);
state.target_table = table;
state.sql_handle = handle;
char get_dives[] = "select l.number,strftime('%s', DiveDate),location||' / '||site,buddy,notes,imperialUnits,maxDepth,maxTime,startSurfacePressure,computerSerial,computerModel,d.diveId,l.sampleRateMs FROM dive_details AS d JOIN dive_logs AS l ON d.diveId=l.diveId";
retval = sqlite3_exec(handle, get_dives, &shearwater_cloud_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);
return 1;
}
return 0;
}

View File

@ -1,7 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "isocialnetworkintegration.h"
//Hack for moc.
ISocialNetworkIntegration::ISocialNetworkIntegration(QObject* parent) : QObject(parent)
{
}

View File

@ -1,74 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef ISOCIALNETWORKINTEGRATION_H
#define ISOCIALNETWORKINTEGRATION_H
#include <QtPlugin>
/* This Interface represents a Plugin for Social Network integration,
* with it you may be able to create plugins for facebook, instagram,
* twitpic, google plus and any other thing you may imagine.
*
* We bundle facebook integration as an example.
*/
class ISocialNetworkIntegration : public QObject {
Q_OBJECT
public:
ISocialNetworkIntegration(QObject* parent = 0);
/*!
* @name socialNetworkName
* @brief The name of this social network
* @return The name of this social network
*
* The name of this social network will be used to populate the Menu to toggle states
* between connected/disconnected, and also submit stuff to it.
*/
virtual QString socialNetworkName() const = 0;
/*!
* @name socialNetworkIcon
* @brief The icon of this social network
* @return The icon of this social network
*
* The icon of this social network will be used to populate the menu, and can also be
* used on a toolbar if requested.
*/
virtual QString socialNetworkIcon() const = 0;
/*!
* @name isConnected
* @brief returns true if connected to this social network, false otherwise
* @return true if connected to this social network, false otherwise
*/
virtual bool isConnected() = 0;
/*!
* @name requestLogin
* @brief try to login on this social network.
*
* Try to login on this social network. All widget implementation that
* manages login should be done inside this function.
*/
virtual void requestLogin() = 0;
/*!
* @name requestLogoff
* @brief tries to logoff from this social network
*
* Try to logoff from this social network.
*/
virtual void requestLogoff() = 0;
/*!
* @name uploadCurrentDive
* @brief send the current dive info to the Social Network
*
* Should format all the options and pixmaps from the current dive
* to update to the social network. All widget stuff related to sendint
* dive information should be executed inside this function.
*/
virtual void requestUpload() = 0;
};
#endif

View File

@ -1069,14 +1069,17 @@ static void event_cb(dc_device_t *device, dc_event_type_t event, const void *dat
break;
case DC_EVENT_DEVINFO:
if (dc_descriptor_get_model(devdata->descriptor) != devinfo->model) {
fprintf(stderr, "EVENT_DEVINFO gave us the correct detected product (model %d instead of %d)\n",
devinfo->model, dc_descriptor_get_model(devdata->descriptor));
dc_descriptor_t *better_descriptor = get_descriptor(dc_descriptor_get_type(devdata->descriptor), devinfo->model);
if (better_descriptor != NULL) {
fprintf(stderr, "EVENT_DEVINFO gave us a different detected product (model %d instead of %d), which we are using now.\n",
devinfo->model, dc_descriptor_get_model(devdata->descriptor));
devdata->descriptor = better_descriptor;
devdata->product = dc_descriptor_get_product(better_descriptor);
devdata->vendor = dc_descriptor_get_vendor(better_descriptor);
devdata->model = str_printf("%s %s", devdata->vendor, devdata->product);
} else {
fprintf(stderr, "EVENT_DEVINFO gave us a different detected product (model %d instead of %d), but that one is unknown.\n",
devinfo->model, dc_descriptor_get_model(devdata->descriptor));
}
}
dev_info(devdata, translate("gettextFromC", "model=%s firmware=%u serial=%u"),

View File

@ -2139,19 +2139,19 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
/* Recording the starting battery status to extra data */
if (battery_start.volt1) {
size_t size = snprintf(NULL, 0, "%dmV (%d%%)", battery_start.volt1, battery_start.percent1) + 1;
size_t stringsize = snprintf(NULL, 0, "%dmV (%d%%)", battery_start.volt1, battery_start.percent1) + 1;
char *ptr = malloc(size);
if (ptr) {
snprintf(ptr, size, "%dmV (%d%%)", battery_start.volt1, battery_start.percent1);
snprintf(ptr, stringsize, "%dmV (%d%%)", battery_start.volt1, battery_start.percent1);
add_extra_data(state.cur_dc, "Battery 1 (start)", ptr);
free(ptr);
}
size = snprintf(NULL, 0, "%dmV (%d%%)", battery_start.volt2, battery_start.percent2) + 1;
ptr = malloc(size);
stringsize = snprintf(NULL, 0, "%dmV (%d%%)", battery_start.volt2, battery_start.percent2) + 1;
ptr = malloc(stringsize);
if (ptr) {
snprintf(ptr, size, "%dmV (%d%%)", battery_start.volt2, battery_start.percent2);
snprintf(ptr, stringsize, "%dmV (%d%%)", battery_start.volt2, battery_start.percent2);
add_extra_data(state.cur_dc, "Battery 2 (start)", ptr);
free(ptr);
}
@ -2159,19 +2159,19 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
/* Recording the ending battery status to extra data */
if (battery_end.volt1) {
size_t size = snprintf(NULL, 0, "%dmV (%d%%)", battery_end.volt1, battery_end.percent1) + 1;
char *ptr = malloc(size);
size_t stringsize = snprintf(NULL, 0, "%dmV (%d%%)", battery_end.volt1, battery_end.percent1) + 1;
char *ptr = malloc(stringsize);
if (ptr) {
snprintf(ptr, size, "%dmV (%d%%)", battery_end.volt1, battery_end.percent1);
snprintf(ptr, stringsize, "%dmV (%d%%)", battery_end.volt1, battery_end.percent1);
add_extra_data(state.cur_dc, "Battery 1 (end)", ptr);
free(ptr);
}
size = snprintf(NULL, 0, "%dmV (%d%%)", battery_end.volt2, battery_end.percent2) + 1;
ptr = malloc(size);
stringsize = snprintf(NULL, 0, "%dmV (%d%%)", battery_end.volt2, battery_end.percent2) + 1;
ptr = malloc(stringsize);
if (ptr) {
snprintf(ptr, size, "%dmV (%d%%)", battery_end.volt2, battery_end.percent2);
snprintf(ptr, stringsize, "%dmV (%d%%)", battery_end.volt2, battery_end.percent2);
add_extra_data(state.cur_dc, "Battery 2 (end)", ptr);
free(ptr);
}

View File

@ -21,6 +21,7 @@ void init_parser_state(struct parser_state *state)
memset(state, 0, sizeof(*state));
state->metric = true;
state->cur_event.deleted = 1;
state->sample_rate = 0;
}
void free_parser_state(struct parser_state *state)

View File

@ -55,6 +55,7 @@ struct parser_state {
int cur_cylinder_index, cur_ws_index;
int lastcylinderindex, next_o2_sensor;
int o2pressure_sensor;
int sample_rate;
struct extra_data cur_extra_data;
struct units xml_parsing_units;
struct dive_table *target_table; /* non-owning */

View File

@ -715,7 +715,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
bottom_time = clock = previous_point_time = dive->dc.sample[dive->dc.samples - 1].time.seconds;
current_cylinder = get_cylinderid_at_time(dive, &dive->dc, sample->time);
// FIXME: This needs a function to find the divemode at the end of the dive like in
// Find the divemode at the end of the dive
const struct event *ev = NULL;
divemode = UNDEF_COMP_TYPE;
divemode = get_current_divemode(&dive->dc, bottom_time, &ev, &divemode);

View File

@ -1,54 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "pluginmanager.h"
#include <QApplication>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>
static QList<ISocialNetworkIntegration*> _socialNetworks;
// no point in including dive.h for this
extern int verbose;
PluginManager& PluginManager::instance()
{
static PluginManager self;
return self;
}
PluginManager::PluginManager()
{
}
void PluginManager::loadPlugins()
{
QDir pluginsDir(qApp->applicationDirPath());
#if defined(Q_OS_WIN)
if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
pluginsDir.cdUp();
#elif defined(Q_OS_MAC)
if (pluginsDir.dirName() == "MacOS") {
pluginsDir.cdUp();
pluginsDir.cdUp();
pluginsDir.cdUp();
}
#endif
pluginsDir.cd("plugins");
if (verbose)
qDebug() << "Plugins Directory: " << pluginsDir;
foreach (const QString& fileName, pluginsDir.entryList(QDir::Files)) {
QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = loader.instance();
if(!plugin)
continue;
if (ISocialNetworkIntegration *social = qobject_cast<ISocialNetworkIntegration*>(plugin)) {
qDebug() << "Adding the plugin: " << social->socialNetworkName();
_socialNetworks.push_back(social);
}
}
}

View File

@ -1,19 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef PLUGINMANAGER_H
#define PLUGINMANAGER_H
#include <QObject>
#include "isocialnetworkintegration.h"
class PluginManager {
public:
static PluginManager& instance();
void loadPlugins();
private:
PluginManager();
PluginManager(const PluginManager&);
PluginManager& operator=(const PluginManager&);
};
#endif

View File

@ -22,12 +22,6 @@ typedef struct
double phe_threshold;
} partial_pressure_graphs_t;
typedef struct {
const char *access_token;
const char *user_id;
const char *album_id;
} facebook_prefs_t;
typedef struct {
enum taxonomy_category category[3];
} geocoding_prefs_t;
@ -111,9 +105,6 @@ struct preferences {
double mobile_scale;
bool show_developer;
// ********** Facebook **********
facebook_prefs_t facebook;
// ********** General **********
bool auto_recalculate_thumbnails;
bool extract_video_thumbnails;

View File

@ -26,6 +26,7 @@
#define MAX_PROFILE_DECO 7200
extern int ascent_velocity(int depth, int avg_depth, int bottom_time);
struct dive *current_dive = NULL;
unsigned int dc_number = 0;
@ -914,13 +915,10 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
/* calculate DECO STOP / TTS / NDL */
static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, struct plot_data *entry, struct gasmix gasmix, double surface_pressure,enum divemode_t divemode)
{
/* FIXME: This should be configurable */
/* should this be configurable? */
/* ascent speed up to first deco stop */
const int ascent_s_per_step = 1;
const int ascent_mm_per_step = 200; /* 12 m/min */
/* ascent speed between deco stops */
const int ascent_s_per_deco_step = 1;
const int ascent_mm_per_deco_step = 16; /* 1 m/min */
/* how long time steps in deco calculations? */
const int time_stepsize = 60;
const int deco_stepsize = 3000;
@ -957,7 +955,7 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
entry->in_deco_calc = true;
/* Add segments for movement to stopdepth */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_step, entry->tts_calc += ascent_s_per_step) {
for (; ascent_depth > next_stop; ascent_depth -= ascent_s_per_step * ascent_velocity(ascent_depth, entry->running_sum / entry->sec, 0), entry->tts_calc += ascent_s_per_step) {
add_segment(ds, depth_to_bar(ascent_depth, dive),
gasmix, ascent_s_per_step, entry->o2pressure.mbar, divemode, prefs.decosac);
next_stop = ROUND_UP(deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth, dive)),
@ -984,7 +982,7 @@ static void calculate_ndl_tts(struct deco_state *ds, const struct dive *dive, st
if (deco_allowed_depth(tissue_tolerance_calc(ds, dive, depth_to_bar(ascent_depth,dive)), surface_pressure, dive, 1) <= next_stop) {
/* move to the next stop and add the travel between stops */
for (; ascent_depth > next_stop; ascent_depth -= ascent_mm_per_deco_step, entry->tts_calc += ascent_s_per_deco_step)
for (; ascent_depth > next_stop; ascent_depth -= ascent_s_per_deco_step * ascent_velocity(ascent_depth, entry->running_sum / entry->sec, 0), entry->tts_calc += ascent_s_per_deco_step)
add_segment(ds, depth_to_bar(ascent_depth, dive),
gasmix, ascent_s_per_deco_step, entry->o2pressure.mbar, divemode, prefs.decosac);
ascent_depth = next_stop;

View File

@ -52,15 +52,18 @@ extern "C" {
void BLEObject::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
qDebug() << "serviceStateChanged";
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << "serviceStateChanged";
auto service = qobject_cast<QLowEnergyService*>(sender());
if (service)
qDebug() << service->serviceUuid() << newState;
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << service->serviceUuid() << newState;
}
void BLEObject::characteristcStateChanged(const QLowEnergyCharacteristic &c, const QByteArray &value)
{
qDebug() << QTime::currentTime() << "packet RECV" << value.toHex();
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << QTime::currentTime() << "packet RECV" << value.toHex();
if (IS_HW(device)) {
if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_DATA_TX]) {
hw_credit--;
@ -84,14 +87,15 @@ void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const Q
isCharacteristicWritten = true;
}
} else {
if (debugCounter < DEBUG_THRESHOLD)
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << "BLEObject::characteristicWritten";
}
}
void BLEObject::writeCompleted(const QLowEnergyDescriptor&, const QByteArray&)
{
qDebug() << "BLE write completed";
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << "BLE write completed";
desc_written++;
}
@ -178,7 +182,8 @@ dc_status_t BLEObject::write(const void *data, size_t size, size_t *actual)
continue;
QByteArray bytes((const char *)data, (int) size);
qDebug() << QTime::currentTime() << "packet SEND" << bytes.toHex();
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << QTime::currentTime() << "packet SEND" << bytes.toHex();
QLowEnergyService::WriteMode mode;
mode = (c.properties() & QLowEnergyCharacteristic::WriteNoResponse) ?
@ -202,7 +207,8 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
if (list.isEmpty())
return DC_STATUS_IO;
qDebug() << QTime::currentTime() << "packet WAIT";
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << QTime::currentTime() << "packet WAIT";
WAITFOR(!receivedPackets.isEmpty(), timeout);
if (receivedPackets.isEmpty())
@ -225,7 +231,8 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
if (actual)
*actual += packet.size();
qDebug() << QTime::currentTime() << "packet READ" << packet.toHex();
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << QTime::currentTime() << "packet READ" << packet.toHex();
return DC_STATUS_SUCCESS;
}

View File

@ -972,16 +972,12 @@ QString get_trip_date_string(timestamp_t when, int nr, bool getday)
utc_mkdate(when, &tm);
QDateTime localTime = QDateTime::fromMSecsSinceEpoch(1000*when,Qt::UTC);
localTime.setTimeSpec(Qt::UTC);
QString ret ;
QString suffix = " " + gettextFromC::tr("(%n dive(s))", "", nr);
if (getday) {
ret = localTime.date().toString(prefs.date_format) + suffix;
} else {
ret = localTime.date().toString("MMM yyyy") + suffix;
}
return ret;
if (getday)
return loc.toString(localTime, prefs.date_format) + suffix;
else
return loc.toString(localTime, "MMM yyyy") + suffix;
}
static QMutex hashOfMutex;

View File

@ -3,6 +3,7 @@
#include <QtBluetooth/QBluetoothAddress>
#include <QtBluetooth/QBluetoothSocket>
#include <QBluetoothLocalDevice>
#include <QEventLoop>
#include <QTimer>
#include <QDebug>
@ -114,34 +115,6 @@ static dc_status_t qt_serial_open(qt_serial_t **io, dc_context_t*, const char* d
timer.setSingleShot(true);
loop.connect(&timer, SIGNAL(timeout()), SLOT(quit()));
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
// First try to connect on RFCOMM channel 1. This is the default channel for most devices
QBluetoothAddress remoteDeviceAddress(devaddr);
serial_port->socket->connectToService(remoteDeviceAddress, 1, QIODevice::ReadWrite | QIODevice::Unbuffered);
timer.start(msec);
loop.exec();
if (serial_port->socket->state() == QBluetoothSocket::ConnectingState) {
// It seems that the connection on channel 1 took more than expected. Wait another 15 seconds
qDebug() << "The connection on RFCOMM channel number 1 took more than expected. Wait another 15 seconds.";
timer.start(3 * msec);
loop.exec();
} else if (serial_port->socket->state() == QBluetoothSocket::UnconnectedState) {
// Try to connect on channel number 5. Maybe this is a Shearwater Petrel2 device.
qDebug() << "Connection on channel 1 failed. Trying on channel number 5.";
serial_port->socket->connectToService(remoteDeviceAddress, 5, QIODevice::ReadWrite | QIODevice::Unbuffered);
timer.start(msec);
loop.exec();
if (serial_port->socket->state() == QBluetoothSocket::ConnectingState) {
// It seems that the connection on channel 5 took more than expected. Wait another 15 seconds
qDebug() << "The connection on RFCOMM channel number 5 took more than expected. Wait another 15 seconds.";
timer.start(3 * msec);
loop.exec();
}
}
#elif defined(Q_OS_ANDROID) || (QT_VERSION >= 0x050500 && defined(Q_OS_MAC))
// Try to connect to the device using the uuid of the Serial Port Profile service
QBluetoothAddress remoteDeviceAddress(devaddr);
#if defined(Q_OS_ANDROID)
QBluetoothUuid uuid = QBluetoothUuid(QUuid("{00001101-0000-1000-8000-00805f9b34fb}"));
@ -149,7 +122,10 @@ static dc_status_t qt_serial_open(qt_serial_t **io, dc_context_t*, const char* d
serial_port->socket->setPreferredSecurityFlags(QBluetooth::NoSecurity);
serial_port->socket->connectToService(remoteDeviceAddress, uuid, QIODevice::ReadWrite | QIODevice::Unbuffered);
#else
serial_port->socket->connectToService(remoteDeviceAddress, 1, QIODevice::ReadWrite | QIODevice::Unbuffered);
QBluetoothLocalDevice dev;
QBluetoothUuid uuid = QBluetoothUuid(QUuid("{00001101-0000-1000-8000-00805f9b34fb}"));
qDebug() << "Linux Bluez connecting to Uuid" << uuid;
serial_port->socket->connectToService(remoteDeviceAddress, uuid, QIODevice::ReadWrite | QIODevice::Unbuffered);
#endif
timer.start(msec);
loop.exec();
@ -161,7 +137,7 @@ static dc_status_t qt_serial_open(qt_serial_t **io, dc_context_t*, const char* d
timer.start(4 * msec);
loop.exec();
}
#endif
if (serial_port->socket->state() != QBluetoothSocket::ConnectedState) {
// Get the latest error and try to match it with one from libdivecomputer

View File

@ -1040,7 +1040,7 @@ static int get_authorship(git_repository *repo, git_signature **authorp)
/* try to fetch the user info from the OS, otherwise use default values. */
struct user_info user = { .name = NULL, .email = NULL };
subsurface_user_info(&user);
if (!user.name)
if (!user.name || !*user.name)
user.name = strdup("Subsurface");
if (!user.email)
user.email = strdup("subsurface-app-account@subsurface-divelog.org");

View File

@ -156,7 +156,7 @@ static int serial_ftdi_open_device (struct ftdi_context *ftdi_ctx)
0xF680, // Suunto
0x87D0, // Cressi (Leonardo)
};
int num_accepted_pids = 6;
int num_accepted_pids = sizeof(accepted_pids) / sizeof(accepted_pids[0]);
int i, pid, ret;
for (i = 0; i < num_accepted_pids; i++) {
pid = accepted_pids[i];

View File

@ -5,7 +5,6 @@
#include "qPrefDisplay.h"
#include "qPrefDiveComputer.h"
#include "qPrefDivePlanner.h"
#include "qPrefFacebook.h"
#include "qPrefGeneral.h"
#include "qPrefGeocoding.h"
#include "qPrefLanguage.h"
@ -51,7 +50,6 @@ void qPref::loadSync(bool doSync)
qPrefDisplay::loadSync(doSync);
qPrefDiveComputer::loadSync(doSync);
qPrefDivePlanner::loadSync(doSync);
qPrefFacebook::loadSync(doSync);
qPrefGeneral::loadSync(doSync);
qPrefGeocoding::loadSync(doSync);
qPrefLanguage::loadSync(doSync);
@ -76,7 +74,6 @@ void qPref::registerQML(QQmlEngine *engine)
ct->setContextProperty("PrefDisplay", qPrefDisplay::instance());
ct->setContextProperty("PrefDiveComputer", qPrefDiveComputer::instance());
ct->setContextProperty("PrefDivePlanner", qPrefDivePlanner::instance());
ct->setContextProperty("PrefFacebook", qPrefFacebook::instance());
ct->setContextProperty("PrefGeneral", qPrefGeneral::instance());
ct->setContextProperty("PrefGeocoding", qPrefGeocoding::instance());
ct->setContextProperty("PrefLanguage", qPrefLanguage::instance());

View File

@ -1,44 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "qPrefFacebook.h"
#include "qPrefPrivate.h"
static const QString group = QStringLiteral("WebApps/Facebook");
qPrefFacebook::qPrefFacebook(QObject *parent) : QObject(parent)
{
}
qPrefFacebook*qPrefFacebook::instance()
{
static qPrefFacebook *self = new qPrefFacebook;
return self;
}
void qPrefFacebook::loadSync(bool doSync)
{
// Empty, because FB probs are not loaded/synced to disk
}
void qPrefFacebook::set_access_token(const QString &value)
{
if (value != prefs.facebook.access_token) {
qPrefPrivate::copy_txt(&prefs.facebook.access_token, value);
emit instance()->access_tokenChanged(value);
}
}
void qPrefFacebook::set_album_id(const QString &value)
{
if (value != prefs.facebook.album_id) {
qPrefPrivate::copy_txt(&prefs.facebook.album_id, value);
emit instance()->album_idChanged(value);
}
}
void qPrefFacebook::set_user_id(const QString &value)
{
if (value != prefs.facebook.user_id) {
qPrefPrivate::copy_txt(&prefs.facebook.user_id, value);
emit instance()->user_idChanged(value);
}
}

View File

@ -1,45 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef QPREFSFACEBOOK_H
#define QPREFSFACEBOOK_H
#include "core/pref.h"
#include <QObject>
class qPrefFacebook : public QObject {
Q_OBJECT
Q_PROPERTY(QString access_token READ access_token WRITE set_access_token NOTIFY access_tokenChanged);
Q_PROPERTY(QString album_id READ album_id WRITE set_album_id NOTIFY album_idChanged);
Q_PROPERTY(QString user_id READ user_id WRITE set_user_id NOTIFY user_idChanged);
public:
qPrefFacebook(QObject *parent = NULL);
static qPrefFacebook *instance();
// Load/Sync local settings (disk) and struct preference
static void loadSync(bool doSync);
static void load() {loadSync(false); }
static void sync() {loadSync(true); }
public:
static QString access_token() { return prefs.facebook.access_token; }
static QString album_id() { return prefs.facebook.album_id; }
static QString user_id() { return prefs.facebook.user_id; }
public slots:
static void set_access_token(const QString& value);
static void set_album_id(const QString& value);
static void set_user_id(const QString& value);
signals:
void access_tokenChanged(const QString& value);
void album_idChanged(const QString& value);
void user_idChanged(const QString& value);
private:
static void disk_access_token(bool doSync);
static void disk_album_id(bool doSync);
static void disk_user_id(bool doSync);
};
#endif

View File

@ -76,11 +76,6 @@ struct preferences default_prefs = {
.pscr_ratio = 100,
.show_pictures_in_profile = true,
.tankbar = false,
.facebook = {
.user_id = NULL,
.album_id = NULL,
.access_token = NULL
},
.defaultsetpoint = 1100,
.geocoding = {
.category = { 0 }
@ -311,9 +306,6 @@ void copy_prefs(struct preferences *src, struct preferences *dest)
dest->cloud_storage_password = copy_string(src->cloud_storage_password);
dest->cloud_storage_email = copy_string(src->cloud_storage_email);
dest->cloud_storage_email_encoded = copy_string(src->cloud_storage_email_encoded);
dest->facebook.access_token = copy_string(src->facebook.access_token);
dest->facebook.user_id = copy_string(src->facebook.user_id);
dest->facebook.album_id = copy_string(src->facebook.album_id);
dest->ffmpeg_executable = copy_string(src->ffmpeg_executable);
}

View File

@ -38,8 +38,18 @@ void subsurface_user_info(struct user_info *user)
const char *username = getenv("USER");
if (pwd) {
if (!empty_string(pwd->pw_gecos))
if (!empty_string(pwd->pw_gecos)) {
user->name = strdup(pwd->pw_gecos);
// We only want the name, not the office or phone number
char *c = user->name;
while (*c) {
if (*c == ',') {
*c = '\0';
break;
}
++c;
}
}
if (!username)
username = pwd->pw_name;
}

View File

@ -50,16 +50,20 @@ static char *utf16_to_utf8_fl(const wchar_t *utf16, char *file, int line)
assert(file != NULL);
assert(line);
/* estimate buffer size */
const int sz = wcslen(utf16) + 1;
const int sz = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL);
if (!sz) {
fprintf(stderr, "%s:%d: cannot estimate buffer size\n", file, line);
return NULL;
}
char *utf8 = (char *)malloc(sz);
if (!utf8) {
fprintf(stderr, "%s:%d: %s %d.", file, line, "cannot allocate buffer of size", sz);
fprintf(stderr, "%s:%d: cannot allocate buffer of size: %d\n", file, line, sz);
return NULL;
}
if (WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, sz, NULL, NULL)) {
return utf8;
}
fprintf(stderr, "%s:%d: %s", file, line, "cannot convert string.");
fprintf(stderr, "%s:%d: cannot convert string\n", file, line);
free((void *)utf8);
return NULL;
}
@ -78,12 +82,12 @@ static wchar_t *utf8_to_utf16_fl(const char *utf8, char *file, int line)
const int sz = strlen(utf8) + 1;
wchar_t *utf16 = (wchar_t *)malloc(sizeof(wchar_t) * sz);
if (!utf16) {
fprintf(stderr, "%s:%d: %s %d.", file, line, "cannot allocate buffer of size", sz);
fprintf(stderr, "%s:%d: cannot allocate buffer of size: %d\n", file, line, sz);
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, sz))
return utf16;
fprintf(stderr, "%s:%d: %s", file, line, "cannot convert string.");
fprintf(stderr, "%s:%d: cannot convert string\n", file, line);
free((void *)utf16);
return NULL;
}

View File

@ -72,7 +72,7 @@ static timestamp_t extract_timestamp_from_attributes(const xmlNode *node)
return 0;
}
static timestamp_t extract_timestamp(const xmlNode *node)
static timestamp_t extract_timestamp(const xmlNode *firstnode)
{
// We use a private stack, so that we can return in one go without
// having to unwind the call-stack. We only recurse to a fixed depth,
@ -80,7 +80,7 @@ static timestamp_t extract_timestamp(const xmlNode *node)
// This can be increased on demand.
static const int max_recursion_depth = 16;
const xmlNode *stack[max_recursion_depth];
stack[0] = node;
stack[0] = firstnode;
int stack_depth = 1;
while (stack_depth > 0) {

View File

@ -7,20 +7,12 @@ if(BTSUPPORT)
set(BT_SRC_FILES btdeviceselectiondialog.cpp)
endif()
if (FBSUPPORT)
add_definitions(-DFBSUPPORT)
endif()
include_directories(.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
)
add_subdirectory(preferences)
if(NOT DISABLE_PLUGINS)
add_subdirectory(plugins)
endif()
set (SUBSURFACE_UI
about.ui

View File

@ -21,7 +21,7 @@ SubsurfaceAbout::SubsurfaceAbout(QWidget *parent, Qt::WindowFlags f) : QDialog(p
"Subsurface %1 </span><br><br>"
"Multi-platform divelog software<br>"
"<span style='font-size: 8pt'>"
"Linus Torvalds, Dirk Hohndel, Tomaz Canabrava, and others, 2011-2018"
"Linus Torvalds, Dirk Hohndel, Tomaz Canabrava, and others, 2011-2019"
"</span>").arg(versionString));
QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this);

View File

@ -600,7 +600,7 @@ ShiftTime::ShiftTime(const QVector<dive *> &changedDives, int amount)
void ShiftTime::redoit()
{
for (dive *d: diveList)
d->when -= timeChanged;
d->when += timeChanged;
// Changing times may have unsorted the dive table
sort_table(&dive_table);

View File

@ -49,7 +49,7 @@
</sizepolicy>
</property>
<property name="title">
<string>Which components would you like to copy</string>
<string>Which components would you like to copy?</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
@ -67,34 +67,6 @@
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="divesite">
<property name="text">
<string>Dive site</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="suit">
<property name="text">
<string>Suit</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="visibility">
<property name="text">
<string>Visibility</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="notes">
<property name="text">
<string>Notes</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="tags">
<property name="text">
@ -109,6 +81,20 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="divesite">
<property name="text">
<string>Dive site</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="visibility">
<property name="text">
<string>Visibility</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="cylinders">
<property name="text">
@ -116,6 +102,20 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="buddy">
<property name="text">
<string>Buddy</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="notes">
<property name="text">
<string>Notes</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="divemaster">
<property name="text">
@ -123,10 +123,10 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="buddy">
<item row="0" column="1">
<widget class="QCheckBox" name="suit">
<property name="text">
<string>Buddy</string>
<string>Suit</string>
</property>
</widget>
</item>
@ -140,6 +140,19 @@
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>You can paste these to another dive or as text to another application.</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">

View File

@ -94,6 +94,8 @@ void DiveLogExportDialog::showExplanation()
ui->description->setText(tr("Write depths of images to file."));
} else if (ui->exportTeX->isChecked()) {
ui->description->setText(tr("Write dive as TeX macros to file."));
} else if (ui->exportProfile->isChecked()) {
ui->description->setText(tr("Write the profile image as PNG file."));
}
}
@ -167,6 +169,10 @@ void DiveLogExportDialog::on_buttonBox_accepted()
filename = QFileDialog::getSaveFileName(this, tr("Export to TeX file"), lastDir, tr("TeX files") + " (*.tex)");
if (!filename.isNull() && !filename.isEmpty())
export_TeX(qPrintable(filename), ui->exportSelected->isChecked());
} else if (ui->exportProfile->isChecked()) {
filename = QFileDialog::getSaveFileName(this, tr("Save profile image"), lastDir);
if (!filename.isNull() && !filename.isEmpty())
exportProfile(qPrintable(filename), ui->exportSelected->isChecked());
}
break;
case 1:
@ -227,6 +233,36 @@ void DiveLogExportDialog::export_depths(const char *filename, const bool selecte
free_buffer(&buf);
}
void DiveLogExportDialog::exportProfile(QString filename, const bool selected_only)
{
struct dive *dive;
int i;
int count = 0;
if (!filename.endsWith(".png", Qt::CaseInsensitive))
filename = filename.append(".png");
QFileInfo fi(filename);
for_each_dive (i, dive) {
if (selected_only && !dive->selected)
continue;
if (count)
saveProfile(dive, fi.path() + QDir::separator() + fi.completeBaseName().append(QString("-%1.").arg(count)) + fi.suffix());
else
saveProfile(dive, filename);
++count;
}
}
void DiveLogExportDialog::saveProfile(const struct dive *dive, const QString filename)
{
ProfileWidget2 *profile = MainWindow::instance()->graphics;
profile->plotDive(dive, true, false, true);
profile->setToolTipVisibile(false);
QPixmap pix = profile->grab();
profile->setToolTipVisibile(true);
pix.save(filename);
}
void DiveLogExportDialog::export_TeX(const char *filename, const bool selected_only)
{
FILE *f;
@ -275,14 +311,7 @@ void DiveLogExportDialog::export_TeX(const char *filename, const bool selected_o
if (selected_only && !dive->selected)
continue;
ProfileWidget2 *profile = MainWindow::instance()->graphics;
profile->plotDive(dive, true);
profile->setToolTipVisibile(false);
QPixmap pix = QPixmap::grabWidget(profile);
profile->setToolTipVisibile(true);
pix.save(texdir.filePath(QString("profile%1.png").arg(dive->number)));
saveProfile(dive, texdir.filePath(QString("profile%1.png").arg(dive->number)));
struct tm tm;
utc_mkdate(dive->when, &tm);

View File

@ -34,6 +34,8 @@ private:
void exportHtmlInit(const QString &filename);
void export_depths(const char *filename, const bool selected_only);
void export_TeX(const char *filename, const bool selected_only);
void exportProfile(QString filename, const bool selected_only);
void saveProfile(const struct dive *dive, const QString filename);
};
#endif // DIVELOGEXPORTDIALOG_H

View File

@ -181,6 +181,16 @@
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="exportProfile">
<property name="text">
<string>Dive profile</string>
</property>
<attribute name="buttonGroup">
<string notr="true">exportGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="exportWorldMap">
<property name="text">

View File

@ -22,7 +22,6 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
previousLast(0),
timer(new QTimer(this)),
dumpWarningShown(false),
ostcFirmwareCheck(0),
#if defined (BT_SUPPORT)
btd(nullptr),
#endif
@ -72,10 +71,6 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
connect(&thread, SIGNAL(finished()),
this, SLOT(onDownloadThreadFinished()), Qt::QueuedConnection);
//TODO: Don't call mainwindow.
MainWindow *w = MainWindow::instance();
connect(&thread, SIGNAL(finished()), w, SLOT(refreshDisplay()));
if (!qPrefDiveComputer::vendor().isEmpty()) {
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor()));
productModel.setStringList(productList[qPrefDiveComputer::vendor()]);
@ -412,7 +407,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
if ((product == "OSTC 3" || product == "OSTC 3+" || product == "OSTC cR" ||
product == "OSTC Sport" || product == "OSTC 4" || product == "OSTC Plus") &&
!data->saveDump()) {
ostcFirmwareCheck = new OstcFirmwareCheck(product);
ostcFirmwareCheck.reset(new OstcFirmwareCheck(product));
}
}

View File

@ -7,6 +7,7 @@
#include <QHash>
#include <QMap>
#include <QAbstractTableModel>
#include <memory>
#include "core/libdivecomputer.h"
#include "desktop-widgets/configuredivecomputerdialog.h"
@ -79,7 +80,7 @@ private:
void fill_device_list(unsigned int transport);
QTimer *timer;
bool dumpWarningShown;
OstcFirmwareCheck *ostcFirmwareCheck;
std::unique_ptr<OstcFirmwareCheck> ostcFirmwareCheck;
DiveImportedModel *diveImportedModel;
#if defined(BT_SUPPORT)
BtDeviceSelectionDialog *btDeviceSelectionDialog;

View File

@ -93,7 +93,7 @@ struct Dir {
double progressFrom, progressTo;
};
QVector<FindMovedImagesDialog::Match> FindMovedImagesDialog::learnImages(const QString &dir, int maxRecursions, QVector<QString> imagePathsIn)
QVector<FindMovedImagesDialog::Match> FindMovedImagesDialog::learnImages(const QString &rootdir, int maxRecursions, QVector<QString> imagePathsIn)
{
QMap<QString, ImageMatch> matches;
@ -112,7 +112,7 @@ QVector<FindMovedImagesDialog::Match> FindMovedImagesDialog::learnImages(const Q
QVector<QVector<Dir>> stack; // Use a stack to recurse into directories
stack.reserve(maxRecursions + 1);
stack.append({ { dir, 0.0, 1.0 } });
stack.append({ { rootdir, 0.0, 1.0 } });
while (!stack.isEmpty()) {
if (stack.last().isEmpty()) {
stack.removeLast();

View File

@ -22,10 +22,8 @@
#include "core/divesitehelpers.h"
#include "core/gettextfromc.h"
#include "core/git-access.h"
#include "core/isocialnetworkintegration.h"
#include "core/import-csv.h"
#include "core/planner.h"
#include "core/pluginmanager.h"
#include "core/qthelper.h"
#include "core/subsurface-string.h"
#include "core/version.h"
@ -75,11 +73,6 @@
#include "usermanual.h"
#endif
#if defined(FBSUPPORT)
#include "plugins/facebook/facebook_integration.h"
#include "plugins/facebook/facebookconnectwidget.h"
#endif
namespace {
QProgressDialog *progressDialog = nullptr;
bool progressDialogCanceled = false;
@ -381,63 +374,6 @@ MainWindow::~MainWindow()
void MainWindow::setupSocialNetworkMenu()
{
#ifdef FBSUPPORT
connections = new QMenu(tr("Connect to"));
FacebookPlugin *facebookPlugin = new FacebookPlugin();
QAction *toggle_connection = new QAction(this);
QObject *obj = facebookPlugin;
toggle_connection->setText(facebookPlugin->socialNetworkName());
toggle_connection->setIcon(QIcon(facebookPlugin->socialNetworkIcon()));
toggle_connection->setData(QVariant::fromValue(obj));
connect(toggle_connection, SIGNAL(triggered()), this, SLOT(socialNetworkRequestConnect()));
FacebookManager *fb = FacebookManager::instance();
connect(fb, &FacebookManager::justLoggedIn, this, &MainWindow::facebookLoggedIn);
connect(fb, &FacebookManager::justLoggedOut, this, &MainWindow::facebookLoggedOut);
connect(fb, &FacebookManager::sendMessage, [this](const QString& msg) {
statusBar()->showMessage(msg, 10000); // show message for 10 secs on the statusbar.
});
share_on_fb = new QAction(this);
share_on_fb->setText(facebookPlugin->socialNetworkName());
share_on_fb->setIcon(QIcon(facebookPlugin->socialNetworkIcon()));
share_on_fb->setData(QVariant::fromValue(obj));
share_on_fb->setEnabled(false);
ui.menuShare_on->addAction(share_on_fb);
connections->addAction(toggle_connection);
connect(share_on_fb, SIGNAL(triggered()), this, SLOT(socialNetworkRequestUpload()));
ui.menuShare_on->addSeparator();
ui.menuShare_on->addMenu(connections);
ui.menubar->show();
#endif
}
void MainWindow::facebookLoggedIn()
{
connections->setTitle(tr("Disconnect from"));
share_on_fb->setEnabled(true);
}
void MainWindow::facebookLoggedOut()
{
connections->setTitle(tr("Connect to"));
share_on_fb->setEnabled(false);
}
void MainWindow::socialNetworkRequestConnect()
{
qDebug() << "Requesting connect on the social network";
QAction *action = qobject_cast<QAction*>(sender());
ISocialNetworkIntegration *plugin = qobject_cast<ISocialNetworkIntegration*>(action->data().value<QObject*>());
if (plugin->isConnected())
plugin->requestLogoff();
else
plugin->requestLogin();
}
void MainWindow::socialNetworkRequestUpload()
{
QAction *action = qobject_cast<QAction*>(sender());
ISocialNetworkIntegration *plugin = action->data().value<ISocialNetworkIntegration*>();
plugin->requestUpload();
}
void MainWindow::setStateProperties(const QByteArray& state, const PropertyList& tl, const PropertyList& tr, const PropertyList& bl, const PropertyList& br)

View File

@ -174,11 +174,6 @@ slots:
// should only be enabled when the profile's visible.
void disableShortcuts(bool disablePaste = true);
void enableShortcuts();
void socialNetworkRequestConnect();
void socialNetworkRequestUpload();
void facebookLoggedIn();
void facebookLoggedOut();
void updateVariations(QString);

View File

@ -131,18 +131,11 @@
<string>&amp;Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuShare_on">
<property name="title">
<string>Share on</string>
</property>
<addaction name="separator"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menu_Edit"/>
<addaction name="menuImport"/>
<addaction name="menuLog"/>
<addaction name="menuView"/>
<addaction name="menuShare_on"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionNew">
@ -694,11 +687,6 @@
<string>Dive Site &amp;Edit</string>
</property>
</action>
<action name="actionFacebook">
<property name="text">
<string>Facebook</string>
</property>
</action>
<action name="actionCloudOnline">
<property name="checkable">
<bool>true</bool>

View File

@ -1 +0,0 @@
add_subdirectory(facebook)

View File

@ -1,22 +0,0 @@
if (ANDROID)
set(FACEBOOK_INTEGRATION "")
elseif (${FBSUPPORT})
add_definitions(-DFBSUPPORT)
set(FACEBOOK_INTEGRATION facebook_integration)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(FACEBOOK_PLUGIN_UI
facebookconnectwidget.ui
socialnetworksdialog.ui
)
set(FACEBOOK_PLUGIN_SRCS
facebook_integration.cpp
facebookconnectwidget.cpp
)
qt5_wrap_ui(FACEBOOK_PLUGIN_UI_SRCS ${FACEBOOK_PLUGIN_UI})
add_library(facebook_integration STATIC ${FACEBOOK_PLUGIN_SRCS} ${FACEBOOK_PLUGIN_UI_SRCS})
target_link_libraries(facebook_integration ${QT_LIBRARIES})
add_dependencies(facebook_integration subsurface_corelib)
endif()

View File

@ -1,43 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "facebook_integration.h"
#include "facebookconnectwidget.h"
#include <QDebug>
FacebookPlugin::FacebookPlugin(QObject*) :
fbConnectWidget(new FacebookConnectWidget())
{
}
bool FacebookPlugin::isConnected()
{
FacebookManager *instance = FacebookManager::instance();
return instance->loggedIn();
}
void FacebookPlugin::requestLogin()
{
fbConnectWidget->exec();
}
void FacebookPlugin::requestLogoff()
{
FacebookManager::instance()->logout();
}
QString FacebookPlugin::socialNetworkIcon() const
{
return QString();
}
QString FacebookPlugin::socialNetworkName() const
{
return tr("Facebook");
}
void FacebookPlugin::requestUpload()
{
FacebookManager *instance = FacebookManager::instance();
if (instance->loggedIn())
instance->sendDiveInit();
}

View File

@ -1,26 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef FACEBOOK_INTEGRATION_H
#define FACEBOOK_INTEGRATION_H
#include "core/isocialnetworkintegration.h"
#include <QString>
class FacebookConnectWidget;
class SocialNetworkDialog;
class FacebookManager;
class FacebookPlugin : public ISocialNetworkIntegration {
Q_OBJECT
public:
explicit FacebookPlugin(QObject* parent = 0);
bool isConnected() override;
void requestLogin() override;
void requestLogoff() override;
QString socialNetworkIcon() const override;
QString socialNetworkName() const override;
void requestUpload() override;
private:
FacebookConnectWidget *fbConnectWidget;
};
#endif

View File

@ -1,421 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "facebookconnectwidget.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkCookieJar>
#include <QUrlQuery>
#include <QHttpMultiPart>
#include <QFile>
#include <QBuffer>
#include <QDebug>
#include <QMessageBox>
#include <QInputDialog>
#include <QLoggingCategory>
#ifdef USE_WEBENGINE
#include <QWebEngineView>
#else
#include <QWebView>
#endif
#include "mainwindow.h"
#include "profile-widget/profilewidget2.h"
#include "core/pref.h"
#include "core/qthelper.h"
#include "core/settings/qPrefFacebook.h"
#include "ui_socialnetworksdialog.h"
#include "ui_facebookconnectwidget.h"
Q_LOGGING_CATEGORY(lcFacebook, "subsurface.facebook")
FacebookManager *FacebookManager::instance()
{
static FacebookManager *self = new FacebookManager();
return self;
}
FacebookManager::FacebookManager(QObject *parent) :
QObject(parent),
manager(new QNetworkAccessManager(this))
{
// log only in verbose mode
QLoggingCategory::setFilterRules(QStringLiteral("subsurface.facebook=%1").arg(verbose ? "true" : "false"));
connect(this, &FacebookManager::albumIdReceived, this, &FacebookManager::sendDiveToAlbum);
}
static QString graphApi = QStringLiteral("https://graph.facebook.com/v2.10/");
QUrl FacebookManager::albumListUrl()
{
return QUrl("https://graph.facebook.com/me/albums?access_token=" + QString(prefs.facebook.access_token));
}
QUrl FacebookManager::connectUrl() {
return QUrl("https://www.facebook.com/dialog/oauth?"
"client_id=427722490709000"
"&redirect_uri=http://www.facebook.com/connect/login_success.html"
"&response_type=token,granted_scopes"
"&display=popup"
"&scope=publish_actions,user_photos"
);
}
bool FacebookManager::loggedIn() {
return prefs.facebook.access_token != NULL;
}
void FacebookManager::tryLogin(const QUrl& loginResponse)
{
qCDebug(lcFacebook) << "Current url call" << loginResponse;
QString result = loginResponse.toString();
if (!result.contains("access_token")) {
qCDebug(lcFacebook) << "Response without access token!";
return;
}
if (result.contains("denied_scopes=publish_actions") || result.contains("denied_scopes=user_photos")) {
qCDebug(lcFacebook) << "user did not allow us access" << result;
return;
}
int from = result.indexOf("access_token=") + strlen("access_token=");
int to = result.indexOf("&expires_in");
QString securityToken = result.mid(from, to-from);
qPrefFacebook::set_access_token(securityToken);
qCDebug(lcFacebook) << "Got securityToken" << securityToken;
requestUserId();
}
void FacebookManager::logout()
{
qPrefFacebook::set_access_token(QString());
qPrefFacebook::set_user_id(QString());
qPrefFacebook::set_album_id(QString());
emit justLoggedOut(true);
}
void FacebookManager::requestAlbumId()
{
qCDebug(lcFacebook) << "Starting to request the album id" << albumListUrl();
QNetworkReply *reply = manager->get(QNetworkRequest(albumListUrl()));
connect(reply, &QNetworkReply::finished, this, &FacebookManager::albumListReceived);
}
void FacebookManager::albumListReceived()
{
qCDebug(lcFacebook) << "Reply for the album id";
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
QJsonDocument albumsDoc = QJsonDocument::fromJson(reply->readAll());
QJsonArray albumObj = albumsDoc.object().value("data").toArray();
reply->deleteLater();
foreach(const QJsonValue &v, albumObj){
QJsonObject obj = v.toObject();
if (obj.value("name").toString() == fbInfo.albumName) {
qPrefFacebook::set_album_id(obj.value("id").toString());
qCDebug(lcFacebook) << "Album" << fbInfo.albumName << "already exists, using id" << obj.value("id").toString();
emit albumIdReceived(qPrefFacebook::album_id());
return;
}
}
// No album with the name we requested, create a new one.
createFacebookAlbum();
}
void FacebookManager::createFacebookAlbum()
{
qCDebug(lcFacebook) << "Album with name" << fbInfo.albumName << "doesn't exists, creating it.";
QUrlQuery params;
params.addQueryItem("name", fbInfo.albumName );
params.addQueryItem("description", "Subsurface Album");
params.addQueryItem("privacy", "{'value': 'SELF'}");
QNetworkRequest request(albumListUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
QNetworkReply *reply = manager->post(request, params.query().toUtf8());
connect(reply, &QNetworkReply::finished, this, &FacebookManager::facebookAlbumCreated);
}
void FacebookManager::facebookAlbumCreated()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
QJsonDocument albumsDoc = QJsonDocument::fromJson(reply->readAll());
QJsonObject album = albumsDoc.object();
reply->deleteLater();
if (album.contains("id")) {
qCDebug(lcFacebook) << "Album" << fbInfo.albumName << "created successfully with id" << album.value("id").toString();
qPrefFacebook::set_album_id(album.value("id").toString());
emit albumIdReceived(qPrefFacebook::album_id());
return;
} else {
qCDebug(lcFacebook) << "It was not possible to create the album with name" << fbInfo.albumName;
qCDebug(lcFacebook).noquote() << "Reply was: " << QString(albumsDoc.toJson(QJsonDocument::Indented));
// FIXME: we are lacking 'user_photos' facebook permission to create an album,
// but we are able to upload the image to Facebook (album will be named 'Subsurface Photos')
qCDebug(lcFacebook) << "But we are still able to upload data. Album name will be 'Subsurface Photos'";
emit albumIdReceived(qPrefFacebook::album_id());
}
}
void FacebookManager::requestUserId()
{
qCDebug(lcFacebook) << "Requesting user id";
QUrl userIdRequest("https://graph.facebook.com/me?fields=id&access_token=" + QString(prefs.facebook.access_token));
QNetworkReply *reply = manager->get(QNetworkRequest(userIdRequest));
connect(reply, &QNetworkReply::finished, this, &FacebookManager::userIdReceived);
}
void FacebookManager::userIdReceived()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
QJsonObject obj = jsonDoc.object();
if (obj.keys().contains("id")) {
qCDebug(lcFacebook) << "User id requested successfully:" << obj.value("id").toString();
qPrefFacebook::set_user_id(obj.value("id").toString());
emit sendMessage(tr("Facebook logged in successfully"));
emit justLoggedIn(true);
} else {
emit sendMessage(tr("Error, unknown user id, cannot login."));
qCDebug(lcFacebook) << "Error, unknown user id, cannot login.";
}
reply->deleteLater();
}
QPixmap FacebookManager::grabProfilePixmap()
{
qCDebug(lcFacebook) << "Grabbing Dive Profile pixmap";
ProfileWidget2 *profile = MainWindow::instance()->graphics;
QSize size = fbInfo.profileSize == FacebookInfo::SMALL ? QSize(800,600) :
fbInfo.profileSize == FacebookInfo::MEDIUM ? QSize(1024,760) :
fbInfo.profileSize == FacebookInfo::BIG ? QSize(1280,1024) : QSize();
auto currSize = profile->size();
profile->resize(size);
profile->setToolTipVisibile(false);
QPixmap pix = profile->grab();
profile->setToolTipVisibile(true);
profile->resize(currSize);
return pix;
}
/* to be changed to export the currently selected dive as shown on the profile.
* Much much easier, and its also good to people do not select all the dives
* and send erroniously *all* of them to facebook. */
void FacebookManager::sendDiveInit()
{
qCDebug(lcFacebook) << "Starting to upload the dive to facebook";
SocialNetworkDialog dialog(qApp->activeWindow());
if (dialog.exec() != QDialog::Accepted) {
qCDebug(lcFacebook) << "User cancelled.";
return;
}
fbInfo.bodyText = dialog.text();
fbInfo.profileSize = dialog.profileSize();
fbInfo.profileData = grabProfilePixmap();
fbInfo.albumName = dialog.album();
fbInfo.albumId = QString(); // request Album Id wil handle that.
// will emit albumIdReceived, that's connected to sendDiveToAlbum
requestAlbumId();
}
void FacebookManager::sendDiveToAlbum(const QString& albumId)
{
qCDebug(lcFacebook) << "Starting to upload the dive to album" << fbInfo.albumName << "id" << albumId;
QUrl url(graphApi + albumId + "/photos?" +
"&access_token=" + QString(prefs.facebook.access_token) +
"&source=image" +
"&message=" + fbInfo.bodyText.replace("&quot;", "%22"));
QNetworkRequest request(url);
QString bound="margin";
//according to rfc 1867 we need to put this string here:
QByteArray data(QString("--" + bound + "\r\n").toUtf8());
data.append("Content-Disposition: form-data; name=\"action\"\r\n\r\n");
data.append(graphApi + "\r\n");
data.append("--" + bound + "\r\n"); //according to rfc 1867
//name of the input is "uploaded" in my form, next one is a file name.
data.append("Content-Disposition: form-data; name=\"uploaded\"; filename=\"" + QString::number(qrand()) + ".png\"\r\n");
data.append("Content-Type: image/jpeg\r\n\r\n"); //data type
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
fbInfo.profileData.save(&buffer, "PNG");
data.append(bytes); //let's read the file
data.append("\r\n");
data.append("--" + bound + "--\r\n"); //closing boundary according to rfc 1867
request.setRawHeader(QByteArray("Content-Type"),QString("multipart/form-data; boundary=" + bound).toUtf8());
request.setRawHeader(QByteArray("Content-Length"), QString::number(data.length()).toUtf8());
QNetworkReply *reply = manager->post(request,data);
connect(reply, &QNetworkReply::finished, this, &FacebookManager::uploadFinished);
}
void FacebookManager::uploadFinished()
{
qCDebug(lcFacebook) << "Upload finish";
auto reply = qobject_cast<QNetworkReply*>(sender());
QByteArray response = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
QJsonObject obj = jsonDoc.object();
reply->deleteLater();
if (obj.keys().contains("id")){
emit sendMessage(tr("Dive uploaded successfully to Facebook"));
} else {
emit sendMessage(tr("Dive upload failed. Please see debug output and send to Subsurface mailing list"));
qCDebug(lcFacebook) << "Dive upload failed" << response;
}
emit sendDiveFinished();
}
void FacebookConnectWidget::showEvent(QShowEvent *event)
{
if (FacebookManager::instance()->loggedIn()) {
facebookLoggedIn();
} else {
facebookDisconnect();
}
return QDialog::showEvent(event);
}
FacebookConnectWidget::FacebookConnectWidget(QWidget *parent) : QDialog(parent), ui(new Ui::FacebookConnectWidget) {
ui->setupUi(this);
FacebookManager *fb = FacebookManager::instance();
#ifdef USE_WEBENGINE
facebookWebView = new QWebEngineView(this);
#else
facebookWebView = new QWebView(this);
#endif
ui->fbWebviewContainer->layout()->addWidget(facebookWebView);
#ifdef USE_WEBENGINE
connect(facebookWebView, &QWebEngineView::urlChanged, fb, &FacebookManager::tryLogin);
#else
connect(facebookWebView, &QWebView::urlChanged, fb, &FacebookManager::tryLogin);
#endif
connect(fb, &FacebookManager::justLoggedIn, this, &FacebookConnectWidget::facebookLoggedIn);
connect(fb, &FacebookManager::justLoggedOut, this, &FacebookConnectWidget::facebookDisconnect);
}
void FacebookConnectWidget::facebookLoggedIn()
{
ui->fbWebviewContainer->hide();
ui->fbWebviewContainer->setEnabled(false);
ui->FBLabel->setText(tr("To disconnect Subsurface from your Facebook account, use the 'Share on' menu entry."));
close();
}
void FacebookConnectWidget::facebookDisconnect()
{
qCDebug(lcFacebook) << "Disconnecting from facebook";
// remove the connect/disconnect button
// and instead add the login view
ui->fbWebviewContainer->show();
ui->fbWebviewContainer->setEnabled(true);
ui->FBLabel->setText(tr("To connect to Facebook, please log in. This enables Subsurface to publish dives to your timeline"));
if (facebookWebView) {
#ifdef USE_WEBENGINE
//FIX ME
#else
facebookWebView->page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
#endif
facebookWebView->setUrl(FacebookManager::instance()->connectUrl());
}
}
SocialNetworkDialog::SocialNetworkDialog(QWidget *parent) :
QDialog(parent),
ui( new Ui::SocialnetworksDialog())
{
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
connect(ui->date, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->duration, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->Buddy, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->Divemaster, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->Location, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->Notes, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged);
connect(ui->album, &QLineEdit::textChanged, this, &SocialNetworkDialog::albumChanged);
}
FacebookInfo::Size SocialNetworkDialog::profileSize() const
{
QString currText = ui->profileSize->currentText();
return currText.startsWith(tr("Small")) ? FacebookInfo::SMALL :
currText.startsWith(tr("Medium")) ? FacebookInfo::MEDIUM :
/* currText.startsWith(tr("Big")) ? */ FacebookInfo::BIG;
}
void SocialNetworkDialog::albumChanged()
{
QAbstractButton *button = ui->buttonBox->button(QDialogButtonBox::Ok);
button->setEnabled(!ui->album->text().isEmpty());
}
void SocialNetworkDialog::selectionChanged()
{
struct dive *d = current_dive;
QString fullText;
if (!d)
return;
if (ui->date->isChecked()) {
fullText += tr("Dive date: %1 \n").arg(get_short_dive_date_string(d->when));
}
if (ui->duration->isChecked()) {
fullText += tr("Duration: %1 \n").arg(get_dive_duration_string(d->duration.seconds,
tr("h", "abbreviation for hours"),
tr("min", "abbreviation for minutes")));
}
if (ui->Location->isChecked()) {
fullText += tr("Dive location: %1 \n").arg(get_dive_location(d));
}
if (ui->Buddy->isChecked()) {
fullText += tr("Buddy: %1 \n").arg(d->buddy);
}
if (ui->Divemaster->isChecked()) {
fullText += tr("Divemaster: %1 \n").arg(d->divemaster);
}
if (ui->Notes->isChecked()) {
fullText += tr("\n%1").arg(d->notes);
}
ui->text->setPlainText(fullText);
}
QString SocialNetworkDialog::text() const {
return ui->text->toPlainText().toHtmlEscaped();
}
QString SocialNetworkDialog::album() const {
return ui->album->text().toHtmlEscaped();
}

View File

@ -1,99 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef FACEBOOKCONNECTWIDGET_H
#define FACEBOOKCONNECTWIDGET_H
#include <QDialog>
#include <QUrl>
#ifdef USE_WEBENGINE
class QWebEngineView;
#else
class QWebView;
#endif
class QNetworkReply;
class QNetworkAccessManager;
namespace Ui {
class FacebookConnectWidget;
class SocialnetworksDialog;
}
struct FacebookInfo {
enum Size {SMALL, MEDIUM, BIG};
QString bodyText;
QString albumId;
QString albumName;
Size profileSize;
QPixmap profileData;
};
class FacebookManager : public QObject
{
Q_OBJECT
public:
static FacebookManager *instance();
void requestAlbumId();
void requestUserId();
QUrl connectUrl();
QUrl albumListUrl();
bool loggedIn();
QPixmap grabProfilePixmap();
signals:
void justLoggedIn(bool triggererd);
void justLoggedOut(bool triggered);
void albumIdReceived(const QString& albumId);
void sendDiveFinished();
void sendMessage(const QString& message);
public slots:
void tryLogin(const QUrl& loginResponse);
void logout();
void sendDiveInit();
void sendDiveToAlbum(const QString& album);
void uploadFinished();
void albumListReceived();
void userIdReceived();
void createFacebookAlbum();
void facebookAlbumCreated();
private:
explicit FacebookManager(QObject *parent = 0);
FacebookInfo fbInfo;
QNetworkAccessManager *manager;
};
class FacebookConnectWidget : public QDialog {
Q_OBJECT
public:
explicit FacebookConnectWidget(QWidget* parent = 0);
void facebookLoggedIn();
void facebookDisconnect();
void showEvent(QShowEvent *event);
private:
Ui::FacebookConnectWidget *ui;
#ifdef USE_WEBENGINE
QWebEngineView *facebookWebView;
#else
QWebView *facebookWebView;
#endif
};
class SocialNetworkDialog : public QDialog {
Q_OBJECT
public:
SocialNetworkDialog(QWidget *parent = 0);
QString text() const;
QString album() const;
FacebookInfo::Size profileSize() const;
public slots:
void selectionChanged();
void albumChanged();
private:
Ui::SocialnetworksDialog *ui;
};
#endif

View File

@ -1,104 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FacebookConnectWidget</class>
<widget class="QDialog" name="FacebookConnectWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>835</width>
<height>698</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<property name="windowIcon">
<iconset>
<normalon>:subsurface-icon</normalon>
</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QHBoxLayout" name="mainHorizontalLayout">
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="facebook_page">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="fbLayout" stretch="0">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="FBLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connect to Facebook text placeholder</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="fbWebviewContainer" native="true">
<layout class="QVBoxLayout" name="verticalLayout_10"/>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,189 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SocialnetworksDialog</class>
<widget class="QDialog" name="SocialnetworksDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>591</width>
<height>619</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
<property name="margin">
<number>1</number>
</property>
<item row="7" column="0">
<widget class="QComboBox" name="profileSize">
<item>
<property name="text">
<string>Small</string>
</property>
</item>
<item>
<property name="text">
<string>Medium</string>
</property>
</item>
<item>
<property name="text">
<string>Big</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>The text to the right will be posted as the description with your dive profile graph to Facebook. The album name is required (the profile graph will be posted to that album).</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Album</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLineEdit" name="album">
<property name="toolTip">
<string>The profile picture will be posted in this album (required)</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Include</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="date">
<property name="text">
<string>Date and time</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="duration">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QCheckBox" name="Location">
<property name="text">
<string>Location</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="Divemaster">
<property name="text">
<string>Divemaster</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QCheckBox" name="Buddy">
<property name="text">
<string>Buddy</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QCheckBox" name="Notes">
<property name="text">
<string>Notes</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Facebook post preview</string>
</property>
</widget>
</item>
<item row="4" column="1" rowspan="11">
<widget class="QPlainTextEdit" name="text"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Image Size</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SocialnetworksDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SocialnetworksDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -53,7 +53,7 @@ void PreferencesNetwork::syncSettings()
proxy->set_proxy_user(ui->proxyUsername->text());
proxy->set_proxy_pass(ui->proxyPassword->text());
QString email = ui->cloud_storage_email->text();
QString email = ui->cloud_storage_email->text().toLower();
QString password = ui->cloud_storage_password->text();
QString newpassword = ui->cloud_storage_new_passwd->text();

View File

@ -39,6 +39,7 @@ PreferencesDialog::PreferencesDialog()
//s.endGroup();
setWindowIcon(QIcon(":subsurface-icon"));
setWindowTitle(tr("Preferences"));
pagesList = new QListWidget();
pagesStack = new QStackedWidget();
buttonBox = new QDialogButtonBox(

View File

@ -10,6 +10,7 @@
#include <QAction>
#include <QDesktopServices>
#include <QToolTip>
#include <QClipboard>
#include "core/file.h"
#include "desktop-widgets/mainwindow.h"
@ -490,6 +491,50 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button)
COMPONENT_FROM_UI(cylinders);
COMPONENT_FROM_UI(weights);
selective_copy_dive(&displayed_dive, targetDive, *what, true);
QClipboard *clipboard = QApplication::clipboard();
QTextStream text;
QString cliptext;
text.setString(&cliptext);
if (what->divesite)
text << tr("Dive site: ") << displayed_dive.dive_site->name << "\n";
if (what->divemaster)
text << tr("Dive master: ") << displayed_dive.divemaster << "\n";
if (what->buddy)
text << tr("Buddy: ") << displayed_dive.buddy << "\n";
if (what->rating)
text << tr("Rating: ") + QString("*").repeated(displayed_dive.rating) << "\n";
if (what->visibility)
text << tr("Visibility: ") + QString("*").repeated(displayed_dive.visibility) << "\n";
if (what->notes)
text << tr("Notes:\n") << displayed_dive.notes << "\n";
if (what->suit)
text << tr("Suit: ") << displayed_dive.suit << "\n";
if (what-> tags) {
text << tr("Tags: ");
tag_entry *entry = displayed_dive.tag_list;
while (entry) {
text << entry->tag->name << " ";
entry = entry->next;
}
text << "\n";
}
if (what->cylinders) {
int cyl;
text << tr("Cylinders:\n");
for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
if (is_cylinder_used(&displayed_dive, cyl))
text << displayed_dive.cylinder[cyl].type.description << " " << gasname(displayed_dive.cylinder[cyl].gasmix) << "\n";
}
}
if (what->weights) {
int w;
text << tr("Weights:\n");
for (w = 0; w < MAX_WEIGHTSYSTEMS; w++) {
if (displayed_dive.weightsystem[w].weight.grams)
text << displayed_dive.weightsystem[w].description << displayed_dive.weightsystem[w].weight.grams / 1000 << "kg\n";
}
}
clipboard->setText(cliptext);
}
}

View File

@ -484,6 +484,10 @@ void DivelogsDeWebServices::prepareDivesForUpload(bool selected)
{
/* generate a random filename and create/open that file with zip_open */
QString filename = QDir::tempPath() + "/import-" + QString::number(qrand() % 99999999) + ".dld";
if (!amount_selected) {
report_error(tr("no dives were selected").toUtf8());
return;
}
if (prepare_dives_for_divelogs(filename, selected)) {
QFile f(filename);
if (f.open(QIODevice::ReadOnly)) {
@ -531,7 +535,7 @@ DivelogsDeWebServices::DivelogsDeWebServices(QWidget *parent, Qt::WindowFlags f)
multipart(NULL),
uploadMode(false)
{
//FIXME: DivelogDE user and pass should be on the prefs struct or something?
// should DivelogDE user and pass be stored in the prefs struct or something?
QSettings s;
ui.userID->setText(s.value("divelogde_user").toString());
ui.password->setText(s.value("divelogde_pass").toString());

View File

@ -903,11 +903,9 @@ void MainTab::acceptChanges()
}
}
if (displayed_dive.when != cd->when) {
timestamp_t offset = cd->when - displayed_dive.when;
if (offset)
Command::shiftTime(selectedDives, (int)offset);
}
timestamp_t offset = displayed_dive.when - cd->when;
if (offset)
Command::shiftTime(selectedDives, (int)offset);
}
if (editMode != TRIP && current_dive->divetrip) {
current_dive->divetrip->when = current_dive->when;

View File

@ -43,7 +43,7 @@ void UpdateManager::checkForUpdates(bool automatic)
isAutomaticCheck = automatic;
QString version = subsurface_canonical_version();
QString uuidString = getUUID();
QString url = QString("http://subsurface-divelog.org/updatecheck.html?os=%1&version=%2&uuid=%3").arg(os, version, uuidString);
QString url = QString("http://updatecheck.subsurface-divelog.org/updatecheck.html?os=%1&version=%2&uuid=%3").arg(os, version, uuidString);
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Accept", "text/xml");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

@ -1 +1 @@
Subproject commit abde311d3a6ea97c7a586e4cc879e07d4ce0fd4f
Subproject commit e4698c484461426a4cf4ef3fc1bdbb304b676f06

View File

@ -46,7 +46,7 @@ Kirigami.ScrollablePage {
}
Kirigami.Heading {
text: qsTr("Version: %1\n\n© Subsurface developer team\n2011-2018").arg(manager.getVersion())
text: qsTr("Version: %1\n\n© Subsurface developer team\n2011-2019").arg(manager.getVersion())
level: 5
font.pointSize: subsurfaceTheme.smallPointSize + 1
Layout.alignment: Qt.AlignHCenter

View File

@ -167,18 +167,6 @@ Kirigami.Page {
elide: Text.ElideRight
}
onCurrentTextChanged: {
// pattern that matches BT addresses
var btAddr = /[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]/ ;
// On iOS we store UUID instead of device address.
if (Qt.platform.os === 'ios')
btAddr = /\{?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}/;
if (btAddr.test(currentText))
manager.DC_bluetoothMode = true
else
manager.DC_bluetoothMode = false
manager.DC_devName = currentText
dc1.enabled = dc2.enabled = dc3.enabled = dc4.enabled = true
for (var i = 1; i < 5; i++) {
if (comboProduct.currentIndex === -1 && currentText === "FTDI"){
@ -198,7 +186,6 @@ Kirigami.Page {
}
}
download.text = qsTr("Download")
}
}
}
@ -277,10 +264,28 @@ Kirigami.Page {
comboConnection.currentIndex != -1
onClicked: {
text = qsTr("Retry")
// strip any BT Name from the address
var devName = manager.DC_devName
if (devName != qsTr("USB device"))
manager.DC_devName = devName.replace(/^(.*) /, "")
var connectionString = comboConnection.currentText
// separate BT address and BT name (if applicable)
// pattern that matches BT addresses
var btAddr = "(LE:)?([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}";
// On iOS we store UUID instead of device address.
if (Qt.platform.os === 'ios')
btAddr = "(LE:)?\{?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}";
var pattern = new RegExp(btAddr);
var devAddress = "";
devAddress = pattern.exec(connectionString);
if (devAddress !== null) {
manager.DC_bluetoothMode = true;
manager.DC_devName = devAddress[0]; // exec returns an array with the matched text in element 0
manager.retrieveBluetoothName();
manager.appendTextToLog("setting btName to " + manager.DC_devBluetoothName);
} else {
manager.DC_bluetoothMode = false;
manager.DC_devName = connectionString;
}
manager.appendTextToLog("DCDownloadThread started for " + manager.DC_vendor + " " + manager.DC_product + " on "+ manager.DC_devName)
progressBar.visible = true
downloadThread.start()
@ -392,7 +397,7 @@ Kirigami.Page {
comboVendor.currentIndex = manager.getDetectedVendorIndex()
comboProduct.currentIndex = manager.getDetectedProductIndex(comboVendor.currentText)
comboConnection.currentIndex = manager.getMatchingAddress(comboVendor.currentText, comboProduct.currentText)
}
}
}

View File

@ -876,11 +876,9 @@ bool QMLManager::checkLocation(DiveObjectHelper *myDive, struct dive *d, QString
qDebug() << "checkLocation" << location << "gps" << gps << "dive had" << myDive->location() << "gps" << myDive->gas();
if (myDive->location() != location) {
diveChanged = true;
if (!ds)
ds = get_dive_site_by_name(qPrintable(location));
if (!ds && !location.isEmpty()) {
ds = get_dive_site_by_name(qPrintable(location));
if (!ds && !location.isEmpty())
ds = create_dive_site(qPrintable(location), d->when);
}
d->dive_site = ds;
}
// now make sure that the GPS coordinates match - if the user changed the name but not
@ -1637,6 +1635,17 @@ void QMLManager::setStatusbarColor(QColor)
#endif
void QMLManager::retrieveBluetoothName()
{
QString name = DC_devName();
QList<BTDiscovery::btVendorProduct> btDCs = BTDiscovery::instance()->getBtDcs();
foreach (BTDiscovery::btVendorProduct btDC, btDCs) {
qDebug() << "compare" <<name << btDC.btpdi.address;
if (name.contains(btDC.btpdi.address))
DC_setDevBluetoothName(btDC.btpdi.name);
}
}
QString QMLManager::DC_vendor() const
{
return m_device_data->vendor();

View File

@ -62,6 +62,8 @@ public:
QString DC_devName() const;
void DC_setDevName(const QString& devName);
Q_INVOKABLE void retrieveBluetoothName();
QString DC_devBluetoothName() const;
void DC_setDevBluetoothName(const QString& devBluetoothName);

View File

@ -17,26 +17,33 @@ exec 1> >(tee ./build.log) 2>&1
USE_X=$(case $- in *x*) echo "-x" ;; esac)
# these are the current versions for Qt, Android SDK & NDK:
source subsurface/packaging/android/variables.sh
# deal with the command line arguments
while [[ $# -gt 0 ]] ; do
arg="$1"
case $arg in
-prep-only)
# only download the dependencies, don't build
PREP_ONLY="1"
;;
release|Release)
# simply pass through to build.sh
;;
*)
echo "Unknown command line argument $arg"
echo "Usage: $0 [-prep-only]"
exit 1
;;
esac
shift
done
# avoid timeouts on Travis when downloads take a long time
SLOW_PROG=""
if [ -n "${TRAVIS:-}" ]; then
source subsurface/scripts/travis-wait.sh
set -x # make debugging Travis easier
SLOW_PROG="travis_wait"
# since we are running on Travis, let's just get our minimal Qt install
mkdir -p Qt/"${LATEST_QT}"
$SLOW_PROG wget -q https://storage.googleapis.com/travis-cache/Qt-"${LATEST_QT}"-android.tar.xz
tar -xJ -C Qt/"${LATEST_QT}" -f Qt-"${LATEST_QT}"-android.tar.xz
fi
# these are the current versions for Qt, Android SDK & NDK:
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
source "$SCRIPTDIR"/variables.sh
PLATFORM=$(uname)
pushd $(dirname "$0")/../../
export SUBSURFACE_SOURCE=$PWD
popd
export SUBSURFACE_SOURCE="$SCRIPTDIR"/../..
if [ "$PLATFORM" = Linux ] ; then
QT_BINARIES=qt-opensource-linux-x64-${LATEST_QT}.run
@ -68,25 +75,28 @@ fi
# first we need to get the Android SDK and NDK
if [ ! -d "$ANDROID_NDK" ] ; then
if [ ! -f "$NDK_BINARIES" ] ; then
$SLOW_PROG wget -q https://dl.google.com/android/repository/"$NDK_BINARIES"
wget -q https://dl.google.com/android/repository/"$NDK_BINARIES"
fi
unzip -q "$NDK_BINARIES"
fi
if [ ! -d "$ANDROID_SDK"/build-tools/"${ANDROID_BUILDTOOLS_REVISION}" ] ; then
if [ ! -d "$ANDROID_SDK"/build-tools/"${ANDROID_BUILDTOOLS_REVISION}" ] ||
[ ! -d "$ANDROID_SDK"/platforms/android-"${ANDROID_PLATFORMS}" ] ||
[ ! -d "$ANDROID_SDK"/platforms/android-"${ANDROID_PLATFORM}" ] ; then
if [ ! -d "$ANDROID_SDK" ] ; then
if [ ! -f "$SDK_TOOLS" ] ; then
$SLOW_PROG wget -q https://dl.google.com/android/repository/"$SDK_TOOLS"
wget -q https://dl.google.com/android/repository/"$SDK_TOOLS"
fi
mkdir "$ANDROID_SDK"
pushd "$ANDROID_SDK"
unzip -q ../"$SDK_TOOLS"
yes | tools/bin/sdkmanager --licenses > /dev/null 2>&1 || echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > licenses/android-sdk-license
cat licenses/android-sdk-license
yes | tools/bin/sdkmanager tools platform-tools 'platforms;'"${ANDROID_PLATFORM}" 'platforms;'"${ANDROID_PLATFORMS}" 'build-tools;'"${ANDROID_BUILDTOOLS_REVISION}" > /dev/null
echo ""
else
pushd "$ANDROID_SDK"
tools/bin/sdkmanager tools platform-tools 'platforms;'"${ANDROID_PLATFORMS}" 'build-tools;'"${ANDROID_BUILDTOOLS_REVISION}"
yes | tools/bin/sdkmanager tools platform-tools 'platforms;'"${ANDROID_PLATFORM}" 'platforms;'"${ANDROID_PLATFORMS}" 'build-tools;'"${ANDROID_BUILDTOOLS_REVISION}" > /dev/null
fi
popd
fi
@ -101,15 +111,19 @@ if [ ! -d Qt/"${LATEST_QT}"/android_armv7 ] ; then
echo "Qt installation found, backing it up to Qt_OLD."
fi
if [ ! -f "${QT_BINARIES}" ] ; then
$SLOW_PROG wget -q "${QT_DOWNLOAD_URL}"
wget -q "${QT_DOWNLOAD_URL}"
fi
chmod +x ./"${QT_BINARIES}"
./"${QT_BINARIES}" --platform minimal --script "$SUBSURFACE_SOURCE"/qt-installer-noninteractive.qs --no-force-installations
./"${QT_BINARIES}" --platform minimal --script "$SCRIPTDIR"/qt-installer-noninteractive.qs --no-force-installations
fi
# patch the cmake / Qt5.7.1 incompatibility mentioned above
sed -i 's/set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)/# set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_FEATURES cxx_decltype)/' Qt/"${LATEST_QT}"/android_armv7/lib/cmake/Qt5Core/Qt5CoreConfigExtras.cmake
if [ ! -z ${PREP_ONLY+x} ] ; then
exit 0
fi
if [ ! -d subsurface/libdivecomputer/src ] ; then
pushd subsurface
git submodule init
@ -117,12 +131,12 @@ if [ ! -d subsurface/libdivecomputer/src ] ; then
popd
fi
if [ ! -f subsurface/libdivecomputer/configure ] ; then
pushd subsurface/libdivecomputer
autoreconf --install
autoreconf --install
popd
fi
# always reconfigure here
rm -f subsurface/libdivecomputer/configure
pushd subsurface/libdivecomputer
autoreconf --install --force
autoreconf --install --force
popd
# and now we need a monotonic build number...
if [ ! -f ./buildnr.dat ] ; then
@ -140,8 +154,10 @@ rm -df ./subsurface-mobile-build-arm/AndroidManifest.xml
if [ "$USE_X" ] ; then
bash "$USE_X" "$SUBSURFACE_SOURCE"/packaging/android/build.sh -buildnr "$BUILDNR" arm "$@"
bash "$USE_X" "$SUBSURFACE_SOURCE"/packaging/android/build.sh -buildnr "$BUILDNR" arm64 "$@"
else
bash "$SUBSURFACE_SOURCE"/packaging/android/build.sh -buildnr "$BUILDNR" arm "$@"
bash "$SUBSURFACE_SOURCE"/packaging/android/build.sh -buildnr "$BUILDNR" arm64 "$@"
fi
ls -l ./subsurface-mobile-build-arm/build/outputs/apk/*.apk

View File

@ -63,7 +63,7 @@ while [ "$#" -gt 0 ] ; do
SUBSURFACE_DESKTOP=ON
shift
;;
arm|x86)
arm|arm64|x86)
ARCH=$1
shift
;;
@ -117,10 +117,17 @@ if [ "$ARCH" = "arm" ] ; then
QT_ARCH=armv7
BUILDCHAIN=arm-linux-androideabi
OPENSSL_MACHINE=armv7
ANDROID_ABI=armeabi-v7a
elif [ "$ARCH" = "arm64" ] ; then # requires Qt 5.12
QT_ARCH=arm64_v8a
BUILDCHAIN=aarch64-linux-android
ANDROID_ABI=arm64-v8a
OPENSSL_MACHINE=aarch64
elif [ "$ARCH" = "x86" ] ; then
QT_ARCH=$ARCH
BUILDCHAIN=i686-linux-android
OPENSSL_MACHINE=i686
ANDROID_ABI=x86
fi
# Verify Qt install and adjust for single-arch Qt install layout
@ -136,21 +143,20 @@ else
fi
if [ ! -e ndk-"$ARCH" ] ; then
"$ANDROID_NDK_ROOT/build/tools/make_standalone_toolchain.py" --arch="$ARCH" --install-dir=ndk-"$ARCH" --api=16
"$ANDROID_NDK_ROOT/build/tools/make_standalone_toolchain.py" --arch="$ARCH" --install-dir=ndk-"$ARCH" --api=$ANDROID_PLATFORM_LEVEL
fi
export BUILDROOT=$PWD
export PATH=${BUILDROOT}/ndk-$ARCH/bin:$PATH
export PREFIX=${BUILDROOT}/ndk-$ARCH/sysroot/usr
export PKG_CONFIG_LIBDIR=$PREFIX/lib/pkgconfig
export CC=${BUILDROOT}/ndk-$ARCH/bin/${BUILDCHAIN}-gcc
export CXX=${BUILDROOT}/ndk-$ARCH/bin/${BUILDCHAIN}-g++
export CC=${BUILDROOT}/ndk-$ARCH/bin/clang
export CXX=${BUILDROOT}/ndk-$ARCH/bin/clang++
# autoconf seems to get lost without this
export SYSROOT=${BUILDROOT}/ndk-$ARCH/sysroot
export CFLAGS=--sysroot=${SYSROOT}
export CPPFLAGS=--sysroot=${SYSROOT}
export CXXFLAGS=--sysroot=${SYSROOT}
# Junk needed for qt-android-cmake
export ANDROID_STANDALONE_TOOLCHAIN=${BUILDROOT}/ndk-$ARCH
export CFLAGS="--sysroot=${SYSROOT} -fPIC"
export CPPFLAGS="--sysroot=${SYSROOT} -fPIC"
export CXXFLAGS="--sysroot=${SYSROOT} -fPIC"
if [ "$PLATFORM" = "Darwin" ] ; then
JAVA_HOME=$(/usr/libexec/java_home)
export JAVA_HOME
@ -159,7 +165,8 @@ else
fi
# find qmake
QMAKE=$QT5_ANDROID/android_armv7/bin/qmake
QMAKE=$QT5_ANDROID/android_$QT_ARCH/bin/qmake
echo $QMAKE
$QMAKE -query
# if we are just doing a quick rebuild, don't bother with any of the dependencies
@ -170,7 +177,7 @@ if [ "$QUICK" = "" ] ; then
# build google maps plugin
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . googlemaps
# find qmake
QMAKE=$QT5_ANDROID/android_armv7/bin/qmake
QMAKE=$QT5_ANDROID/android_$QT_ARCH/bin/qmake
$QMAKE -query
QT_PLUGINS_PATH=$($QMAKE -query QT_INSTALL_PLUGINS)
GOOGLEMAPS_BIN=libqtgeoservices_googlemaps.so
@ -228,8 +235,33 @@ if [ "$QUICK" = "" ] ; then
make install
popd
fi
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libzip
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . openssl
if [ ! -e "$PKG_CONFIG_LIBDIR/libssl.pc" ] ; then
mkdir -p openssl-build-"$ARCH"
cp -r openssl/* openssl-build-"$ARCH"
pushd openssl-build-"$ARCH"
perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
perl -pi -e 's/-mandroid//g' Configure
# Use env to make all these temporary, so they don't pollute later builds.
env SYSTEM=android \
CROSS_COMPILE=${BUILDCHAIN}- \
MACHINE=$OPENSSL_MACHINE \
HOSTCC=clang \
CC=clang \
ANDROID_DEV="$PREFIX" \
bash -x ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine no-asm --openssldir="$PREFIX"
# sed -i.bak -e 's/soname=\$\$SHLIB\$\$SHLIB_SOVER\$\$SHLIB_SUFFIX/soname=\$\$SHLIB/g' Makefile.shared
make depend
make
# now fix the reference to libcrypto.so.1.0.0 to be just to libcrypto.so
perl -pi -e 's/libcrypto.so.1.0.0/libcrypto.so\x00\x00\x00\x00\x00\x00/' libssl.so.1.0.0
make install_sw
popd
fi
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libzip
if [ ! -e "$PKG_CONFIG_LIBDIR/libzip.pc" ] ; then
# libzip expects a predefined macro that isn't there for our compiler
pushd libzip
@ -244,6 +276,7 @@ if [ "$QUICK" = "" ] ; then
-DCMAKE_C_COMPILER="$CC" \
-DCMAKE_LINKER="$CC" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_INSTALL_LIBDIR="lib" \
-DBUILD_SHARED_LIBS=OFF \
../libzip/
make
@ -251,30 +284,6 @@ if [ "$QUICK" = "" ] ; then
popd
fi
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . openssl
if [ ! -e openssl-build-"$ARCH" ] ; then
mv openssl openssl-build-"$ARCH"
fi
if [ ! -e "$PKG_CONFIG_LIBDIR/libssl.pc" ] ; then
pushd openssl-build-"$ARCH"
perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
# Use env to make all these temporary, so they don't pollute later builds.
env SYSTEM=android \
CROSS_COMPILE=${BUILDCHAIN}- \
MACHINE=$OPENSSL_MACHINE \
HOSTCC=gcc \
CC=gcc \
ANDROID_DEV="$PREFIX" \
bash -x ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir="$PREFIX"
# sed -i.bak -e 's/soname=\$\$SHLIB\$\$SHLIB_SOVER\$\$SHLIB_SUFFIX/soname=\$\$SHLIB/g' Makefile.shared
make depend
make
# now fix the reference to libcrypto.so.1.0.0 to be just to libcrypto.so
perl -pi -e 's/libcrypto.so.1.0.0/libcrypto.so\x00\x00\x00\x00\x00\x00/' libssl.so.1.0.0
make install_sw
popd
fi
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libgit2
if [ ! -e "$PKG_CONFIG_LIBDIR/libgit2.pc" ] ; then
# We don't want to find the HTTP_Parser package of the build host by mistake
@ -395,28 +404,27 @@ fi
PKGCONF=$(which pkg-config)
cmake $MOBILE_CMAKE \
-DPKG_CONFIG_EXECUTABLE="$PKGCONF" \
-DCMAKE_SYSTEM_NAME="Android" \
-DANDROID_ABI=$ANDROID_ABI \
-DANDROID_PLATFORM="$ANDROID_PLATFORM" \
-DQT_ANDROID_SDK_ROOT="$ANDROID_SDK_ROOT" \
-DQT_ANDROID_NDK_ROOT="$ANDROID_NDK_ROOT" \
-DANDROID_TOOLCHAIN="gcc" \
-DANDROID_PLATFORM="android-16" \
-DPKG_CONFIG_EXECUTABLE="$PKGCONF" \
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_ROOT"/build/cmake/android.toolchain.cmake \
-DQT_ANDROID_CMAKE="$BUILDROOT"/qt-android-cmake/AddQtAndroidApk.cmake \
-DANDROID_STL="gnustl_shared" \
-DANDROID_STL="c++_shared" \
-DFORCE_LIBSSH=OFF \
-DLIBDC_FROM_PKGCONFIG=ON \
-DLIBGIT2_FROM_PKGCONFIG=ON \
-DNO_PRINTING=ON \
-DNO_USERMANUAL=ON \
-DNO_DOCS=ON \
-DFBSUPPORT=OFF \
-DCMAKE_PREFIX_PATH:UNINITIALIZED="$QT5_ANDROID_CMAKE" \
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
-DMAKE_TESTS=OFF \
-DFTDISUPPORT=${FTDI} \
-DANDROID_NATIVE_LIBSSL="$BUILDROOT/ndk-$ARCH/sysroot/usr/lib/libssl.so" \
-DANDROID_NATIVE_LIBCRYPT="$BUILDROOT/ndk-$ARCH/sysroot/usr/lib/libcrypto.so" \
-DBUILDTOOLS_REVISION="$ANDROID_BUILDTOOLS_REVISION" \
-DCMAKE_MAKE_PROGRAM="make" \
"$SUBSURFACE_SOURCE"

View File

@ -32,7 +32,8 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
widget.deselectAll();
widget.selectComponent('qt.qt5.5111.android_armv7');
widget.selectComponent('qt.qt5.5120.android_armv7');
widget.selectComponent('qt.qt5.5120.android_arm64_v8a');
gui.clickButton(buttons.NextButton);
}

View File

@ -1,11 +1,13 @@
#!/bin/bash
# When changing Qt version remember to update the
# qt-installer-noninteractive file as well.
QT_VERSION=5.11
LATEST_QT=5.11.1
NDK_VERSION=r14b
SDK_VERSION=3859397
ANDROID_BUILDTOOLS_REVISION=25.0.3
QT_VERSION=5.12
LATEST_QT=5.12.0
NDK_VERSION=r18b
SDK_VERSION=4333796
ANDROID_BUILDTOOLS_REVISION=28.0.2
ANDROID_PLATFORM_LEVEL=21
ANDROID_PLATFORM=android-21
ANDROID_PLATFORMS=android-27
ANDROID_NDK=android-ndk-${NDK_VERSION}
ANDROID_SDK=android-sdk-linux

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