Compare commits
125 Commits
master
...
v4.5-branc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d8d7c2a0f | ||
|
|
93e529f371 | ||
|
|
06843f1155 | ||
|
|
a5611c1d28 | ||
|
|
6a6f824caa | ||
|
|
5916a4e37b | ||
|
|
bd20b8c9a2 | ||
|
|
51b7de7812 | ||
|
|
f1a24f08fb | ||
|
|
f3abedd588 | ||
|
|
4393f59250 | ||
|
|
46fa803259 | ||
|
|
403a7b959c | ||
|
|
97a26166e7 | ||
|
|
21ad9ac62c | ||
|
|
4ef2ef1540 | ||
|
|
573489bebc | ||
|
|
14aafaa67d | ||
|
|
6df8752d7d | ||
|
|
9d26f40279 | ||
|
|
6cc6c04521 | ||
|
|
f7ec0b3dd0 | ||
|
|
d6f6a8c7f8 | ||
|
|
9fe0cbaae4 | ||
|
|
979dee2de7 | ||
|
|
696541e7b0 | ||
|
|
c52bbc660c | ||
|
|
3ce15d236b | ||
|
|
40af185902 | ||
|
|
e56e522ac5 | ||
|
|
410ea40229 | ||
|
|
a1fb31a2d8 | ||
|
|
a26c1c6df1 | ||
|
|
ed8e665242 | ||
|
|
15d07a879e | ||
|
|
b3b43e0140 | ||
|
|
7e15c2a7ad | ||
|
|
37e08d5e25 | ||
|
|
d0754138a4 | ||
|
|
669e2bf9fe | ||
|
|
fe8c2ba6ce | ||
|
|
e9caf75db0 | ||
|
|
916ed01830 | ||
|
|
3ba21027b9 | ||
|
|
90bd1b0af7 | ||
|
|
fd10342b24 | ||
|
|
c332bf2cfa | ||
|
|
e167506bdb | ||
|
|
0d080f3249 | ||
|
|
550f07da8b | ||
|
|
3f4d0e317d | ||
|
|
ea281b66a8 | ||
|
|
e15f13d861 | ||
|
|
ab1dc3ce38 | ||
|
|
122088c891 | ||
|
|
1bea93d6ee | ||
|
|
777ee8a5cd | ||
|
|
e90b409a14 | ||
|
|
2639281354 | ||
|
|
2368f3371b | ||
|
|
126ce41b5c | ||
|
|
2163ae026f | ||
|
|
b1c923cd59 | ||
|
|
563ff6bdc4 | ||
|
|
55fbddb756 | ||
|
|
d5f2bb2353 | ||
|
|
d38f50d128 | ||
|
|
875a9035fb | ||
|
|
7e1ba8e925 | ||
|
|
e15ec99dfe | ||
|
|
a5dde4c34a | ||
|
|
43ec76283b | ||
|
|
3c83b2218b | ||
|
|
9bd9850688 | ||
|
|
e8afb7120c | ||
|
|
7ae578ae6a | ||
|
|
c13da59ecc | ||
|
|
19caca1d36 | ||
|
|
57bb04a529 | ||
|
|
cf095489aa | ||
|
|
2a4ce01322 | ||
|
|
a01e4fefb4 | ||
|
|
b2eee9db6b | ||
|
|
403d6dcfb0 | ||
|
|
b73f56bc43 | ||
|
|
09cec219f7 | ||
|
|
cd44aabb5f | ||
|
|
5229c507cb | ||
|
|
4052fea817 | ||
|
|
f3c8ae2bf8 | ||
|
|
95020f5989 | ||
|
|
ca3b1bb6ef | ||
|
|
efc7117c21 | ||
|
|
9fe1e0fb34 | ||
|
|
06e704d98a | ||
|
|
f9d5fe56b3 | ||
|
|
e1768b4771 | ||
|
|
76c97f2e57 | ||
|
|
f577967629 | ||
|
|
d6b7ea5f7f | ||
|
|
e4c7c6e8eb | ||
|
|
27ea079928 | ||
|
|
3029bc872c | ||
|
|
16ce14a29e | ||
|
|
9c26da3e29 | ||
|
|
ea9303ff3c | ||
|
|
0a65fe500b | ||
|
|
965b67847f | ||
|
|
cd81f37200 | ||
|
|
d48a677259 | ||
|
|
8daf6128f6 | ||
|
|
731e964932 | ||
|
|
0c2df219ef | ||
|
|
f29cf77b4e | ||
|
|
31cdc9320e | ||
|
|
6b9d4669d1 | ||
|
|
d20f0662b4 | ||
|
|
00c1405535 | ||
|
|
8a43e07408 | ||
|
|
d69c9e08af | ||
|
|
2bf84e6a5e | ||
|
|
9a3532b0cd | ||
|
|
ffc8e0a661 | ||
|
|
3555361e44 | ||
|
|
77e259080f |
@ -1,5 +1,8 @@
|
||||
# cmake based build of Subsurface
|
||||
|
||||
# Uncomment his to see all commands cmake actually executes
|
||||
# set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
project(Subsurface)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
@ -87,7 +90,7 @@ else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_LIBGIT23_API")
|
||||
if(FORCE_LIBSSH)
|
||||
find_package(Libssh2 QUIET CONFIG)
|
||||
if ("${LIBSSH2_VERSION}" STRGREATER "1.6.1")
|
||||
if ("${LIBSSH2_VERSION}" STRLESS "1.7" AND "${LIBSSH2_VERSION}" STRGREATER "1.6.1")
|
||||
set(LIBSSH2_LIBRARIES Libssh2::libssh2)
|
||||
endif()
|
||||
if(!LIBSSH2_FOUND OR "${LIBSSH2_FOUND}" STREQUAL "")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
INSTALL
2
INSTALL
@ -94,7 +94,7 @@ sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-deve
|
||||
|
||||
On Debian Jessie and recent Ubuntu flavors this seems to work
|
||||
|
||||
sudo apt-get install git g++ make autoconf libtool cmake pkg-config \
|
||||
sudo apt-get install git g++ make autoconf automake libtool cmake pkg-config \
|
||||
libxml2-dev libxslt1-dev libzip-dev libsqlite3-dev \
|
||||
libusb-1.0-0-dev libgit2-dev \
|
||||
qt5-default qt5-qmake qtchooser qttools5-dev-tools libqt5svg5-dev \
|
||||
|
||||
6
README
6
README
@ -1,4 +1,4 @@
|
||||
This is the README file for Subsurface 4.5.1
|
||||
This is the README file for Subsurface 4.5.6
|
||||
|
||||
Please check the ReleaseNotes.txt for details about new features and
|
||||
changes since Subsurface 4.5 (and earlier versions).
|
||||
@ -24,11 +24,11 @@ If you want the latest release (instead of the bleeding edge
|
||||
development version) you can either get this via git or the release tar
|
||||
ball. After cloning run the following command:
|
||||
|
||||
git checkout v4.5.1 (or whatever the last release is)
|
||||
git checkout v4.5.6 (or whatever the last release is)
|
||||
|
||||
or download a tar ball from:
|
||||
|
||||
http://subsurface-divelog.org/downloads/Subsurface-4.5.1.tgz
|
||||
http://subsurface-divelog.org/downloads/Subsurface-4.5.6.tgz
|
||||
|
||||
Detailed build instructions can be found in the INSTALL file.
|
||||
|
||||
|
||||
@ -1,11 +1,85 @@
|
||||
// _Subsurface_ 4.5.1 Release Notes
|
||||
// _Subsurface_ 4.5.6 Release Notes
|
||||
|
||||
_Subsurface_ 4.5.1 - October 2015
|
||||
_Subsurface_ 4.5.6 - April 2016
|
||||
---------------------------------
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5.0
|
||||
Some of the changes since _Subsurface_ 4.5.5
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Fix crash when downloading from Bluetooth based dive computers
|
||||
- Small fixes to VPM-B ceiling calculations
|
||||
- Import picture URLs from divelogs.de
|
||||
- Add support for the new version of the Suunto DX
|
||||
- Don't get caught in endless loop of git authentication errors
|
||||
- Fix time parsing of Divesoft Freedom
|
||||
- Support DAN DL7 import
|
||||
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5.4
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Update to latest libdivecomputer which adds support for Cochran
|
||||
Commander and EMC, Uwatec Aladin Sport, Suunto Zoop/Vyper Novo,
|
||||
Suunto D4i and D6i with latest firmware, Heinrichs & Weikamp OSTC4,
|
||||
Aqualung i450T and Cressi Newton.
|
||||
- In the dive planner, switch pressure unit when planning in recreational
|
||||
mode and setting a tank reserve
|
||||
- In the dive planner, show the correct VPM-B + conservatism on the
|
||||
profile when planning in VPM-B mode and show the planner specific
|
||||
gradient factors in Bühlman mode.
|
||||
- Enable showing a VPM-B based "ceiling" on the profile
|
||||
- Fix bug regarding depth parameter in OSTC/OSTC3 configuration
|
||||
- Fix bug in CSV export
|
||||
- Fix bugs in Suunto DM5 import
|
||||
- Fix potential race when immediately switching to Add dive or Planner
|
||||
while accessing cloud storage
|
||||
- Fix issue for some users with cloud storage passwords
|
||||
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5.3
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Update to latest libdivecomputer to fix a number of issues in the
|
||||
parsing of dive computer data (Shearmos Amphos Air, Shearwater Predator,
|
||||
several Oceanic models)
|
||||
- Add support for Oceanic / Aeris F11, DiveSystem iX3M, Shearwater Perdix
|
||||
- Fix several issues with imports from CSV, divelogs.de and other sources
|
||||
- Add better support for OSTC3 configuration
|
||||
- Fix potential rounding error when exporting weight systems
|
||||
- If XML file contains actual salinity (instead of the density value that
|
||||
we call salinity), correctly interpret that value
|
||||
- Add statistics by dive type
|
||||
- Small UI fixes
|
||||
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Fix confusing warning about different number of tanks and gases on some
|
||||
Suunto dive computers
|
||||
- Fix missing temperatures on some Suunto dive computers
|
||||
- Fix several corner cases in the Uemis support
|
||||
- Fix a few random UI inconsistencies (UI elements not being cleared /
|
||||
removed / reset in certain circumstances)
|
||||
- Cloud storage: no longer store picture binary data in the Subsurface
|
||||
cloud storage - this can cause excessively long sync times
|
||||
- When matching dive site names when entering a location name, match
|
||||
anywhere in the location name, not just from the beginning (this makes
|
||||
it much easier to find existing dive locations if you remember only part
|
||||
of the name)
|
||||
- Some fixes for importing data from other formats
|
||||
- English user manual has been updated for language consistency and
|
||||
readability
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5.1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- No code changes to Subsurface, just an update to libdivecomputer and new
|
||||
binaries on all platforms.
|
||||
|
||||
Some of the changes since _Subsurface_ 4.5
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Subsurface no longer crashes on Windows when run in the German
|
||||
localization and using the planner
|
||||
- avoid a situation in the planner where the user ends up with no usable
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
#include "pref.h"
|
||||
#include "helpers.h"
|
||||
#include "subsurfacewebservices.h"
|
||||
|
||||
#include "checkcloudconnection.h"
|
||||
|
||||
@ -29,6 +30,9 @@ bool CheckCloudConnection::checkServer()
|
||||
request.setRawHeader("Accept", "text/plain");
|
||||
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
||||
request.setUrl(QString(prefs.cloud_base_url) + TEAPOT);
|
||||
// now set up an authentication test
|
||||
CloudStorageAuthenticate *csa = new CloudStorageAuthenticate(0);
|
||||
csa->backend(prefs.cloud_storage_email, prefs.cloud_storage_password);
|
||||
QNetworkAccessManager *mgr = new QNetworkAccessManager();
|
||||
reply = mgr->get(request);
|
||||
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#include "configuredivecomputerthreads.h"
|
||||
#include "libdivecomputer/hw.h"
|
||||
#include "libdivecomputer.h"
|
||||
#include <QDateTime>
|
||||
#include <QStringList>
|
||||
|
||||
#define OSTC3_GAS1 0x10
|
||||
#define OSTC3_GAS2 0x11
|
||||
@ -54,6 +52,11 @@
|
||||
#define OSTC3_DYNAMIC_ASCEND_RATE 0x3F
|
||||
#define OSTC3_GRAPHICAL_SPEED_INDICATOR 0x40
|
||||
#define OSTC3_ALWAYS_SHOW_PPO2 0x41
|
||||
#define OSTC3_TEMP_SENSOR_OFFSET 0x42
|
||||
#define OSTC3_SAFETY_STOP_LENGTH 0x43
|
||||
#define OSTC3_SAFETY_STOP_START_DEPTH 0x44
|
||||
#define OSTC3_SAFETY_STOP_END_DEPTH 0x45
|
||||
#define OSTC3_SAFETY_STOP_RESET_DEPTH 0x46
|
||||
|
||||
#define OSTC3_HW_OSTC_3 0x0A
|
||||
#define OSTC3_HW_OSTC_3P 0x1A
|
||||
@ -408,7 +411,7 @@ static dc_status_t read_ostc3_settings(dc_device_t *device, DeviceDetails *m_dev
|
||||
dc_status_t rc;
|
||||
dc_event_progress_t progress;
|
||||
progress.current = 0;
|
||||
progress.maximum = 52;
|
||||
progress.maximum = 57;
|
||||
unsigned char hardware[1];
|
||||
|
||||
//Read hardware type
|
||||
@ -648,17 +651,13 @@ static dc_status_t read_ostc3_settings(dc_device_t *device, DeviceDetails *m_dev
|
||||
READ_SETTING(OSTC3_BOTTOM_GAS_CONSUMPTION, bottomGasConsumption);
|
||||
READ_SETTING(OSTC3_DECO_GAS_CONSUMPTION, decoGasConsumption);
|
||||
READ_SETTING(OSTC3_MOD_WARNING, modWarning);
|
||||
|
||||
//Skip things not supported on the sport, if its a sport.
|
||||
if (m_deviceDetails->model == "Sport") {
|
||||
EMIT_PROGRESS();
|
||||
EMIT_PROGRESS();
|
||||
EMIT_PROGRESS();
|
||||
} else {
|
||||
READ_SETTING(OSTC3_DYNAMIC_ASCEND_RATE, dynamicAscendRate);
|
||||
READ_SETTING(OSTC3_GRAPHICAL_SPEED_INDICATOR, graphicalSpeedIndicator);
|
||||
READ_SETTING(OSTC3_ALWAYS_SHOW_PPO2, alwaysShowppO2);
|
||||
}
|
||||
READ_SETTING(OSTC3_DYNAMIC_ASCEND_RATE, dynamicAscendRate);
|
||||
READ_SETTING(OSTC3_GRAPHICAL_SPEED_INDICATOR, graphicalSpeedIndicator);
|
||||
READ_SETTING(OSTC3_ALWAYS_SHOW_PPO2, alwaysShowppO2);
|
||||
READ_SETTING(OSTC3_SAFETY_STOP_LENGTH, safetyStopLength);
|
||||
READ_SETTING(OSTC3_SAFETY_STOP_START_DEPTH, safetyStopStartDepth);
|
||||
READ_SETTING(OSTC3_SAFETY_STOP_END_DEPTH, safetyStopEndDepth);
|
||||
READ_SETTING(OSTC3_SAFETY_STOP_RESET_DEPTH, safetyStopResetDepth);
|
||||
|
||||
#undef READ_SETTING
|
||||
|
||||
@ -669,6 +668,13 @@ static dc_status_t read_ostc3_settings(dc_device_t *device, DeviceDetails *m_dev
|
||||
m_deviceDetails->pressureSensorOffset = (signed char)uData[0];
|
||||
EMIT_PROGRESS();
|
||||
|
||||
rc = hw_ostc3_device_config_read(device, OSTC3_TEMP_SENSOR_OFFSET, uData, sizeof(uData));
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
// OSTC3 stores the tempSensorOffset in two-complement
|
||||
m_deviceDetails->tempSensorOffset = (signed char)uData[0];
|
||||
EMIT_PROGRESS();
|
||||
|
||||
//read firmware settings
|
||||
unsigned char fData[64] = { 0 };
|
||||
rc = hw_ostc3_device_version(device, fData, sizeof(fData));
|
||||
@ -689,7 +695,7 @@ static dc_status_t write_ostc3_settings(dc_device_t *device, DeviceDetails *m_de
|
||||
dc_status_t rc;
|
||||
dc_event_progress_t progress;
|
||||
progress.current = 0;
|
||||
progress.maximum = 51;
|
||||
progress.maximum = 56;
|
||||
|
||||
//write gas values
|
||||
unsigned char gas1Data[4] = {
|
||||
@ -912,17 +918,14 @@ static dc_status_t write_ostc3_settings(dc_device_t *device, DeviceDetails *m_de
|
||||
WRITE_SETTING(OSTC3_BOTTOM_GAS_CONSUMPTION, bottomGasConsumption);
|
||||
WRITE_SETTING(OSTC3_DECO_GAS_CONSUMPTION, decoGasConsumption);
|
||||
WRITE_SETTING(OSTC3_MOD_WARNING, modWarning);
|
||||
|
||||
//Skip things not supported on the sport, if its a sport.
|
||||
if (m_deviceDetails->model == "Sport") {
|
||||
EMIT_PROGRESS();
|
||||
EMIT_PROGRESS();
|
||||
EMIT_PROGRESS();
|
||||
} else {
|
||||
WRITE_SETTING(OSTC3_DYNAMIC_ASCEND_RATE, dynamicAscendRate);
|
||||
WRITE_SETTING(OSTC3_GRAPHICAL_SPEED_INDICATOR, graphicalSpeedIndicator);
|
||||
WRITE_SETTING(OSTC3_ALWAYS_SHOW_PPO2, alwaysShowppO2);
|
||||
}
|
||||
WRITE_SETTING(OSTC3_DYNAMIC_ASCEND_RATE, dynamicAscendRate);
|
||||
WRITE_SETTING(OSTC3_GRAPHICAL_SPEED_INDICATOR, graphicalSpeedIndicator);
|
||||
WRITE_SETTING(OSTC3_ALWAYS_SHOW_PPO2, alwaysShowppO2);
|
||||
WRITE_SETTING(OSTC3_TEMP_SENSOR_OFFSET, tempSensorOffset);
|
||||
WRITE_SETTING(OSTC3_SAFETY_STOP_LENGTH, safetyStopLength);
|
||||
WRITE_SETTING(OSTC3_SAFETY_STOP_START_DEPTH, safetyStopStartDepth);
|
||||
WRITE_SETTING(OSTC3_SAFETY_STOP_END_DEPTH, safetyStopEndDepth);
|
||||
WRITE_SETTING(OSTC3_SAFETY_STOP_RESET_DEPTH, safetyStopResetDepth);
|
||||
|
||||
#undef WRITE_SETTING
|
||||
|
||||
@ -933,17 +936,19 @@ static dc_status_t write_ostc3_settings(dc_device_t *device, DeviceDetails *m_de
|
||||
return rc;
|
||||
EMIT_PROGRESS();
|
||||
|
||||
// OSTC3 stores the tempSensorOffset in two-complement
|
||||
data[0] = (unsigned char)m_deviceDetails->pressureSensorOffset;
|
||||
rc = hw_ostc3_device_config_write(device, OSTC3_TEMP_SENSOR_OFFSET, data, sizeof(data));
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
EMIT_PROGRESS();
|
||||
|
||||
//sync date and time
|
||||
if (m_deviceDetails->syncTime) {
|
||||
QDateTime timeToSet = QDateTime::currentDateTime();
|
||||
dc_datetime_t time;
|
||||
time.year = timeToSet.date().year();
|
||||
time.month = timeToSet.date().month();
|
||||
time.day = timeToSet.date().day();
|
||||
time.hour = timeToSet.time().hour();
|
||||
time.minute = timeToSet.time().minute();
|
||||
time.second = timeToSet.time().second();
|
||||
rc = hw_ostc3_device_clock(device, &time);
|
||||
dc_datetime_t now;
|
||||
dc_datetime_localtime(&now, dc_datetime_now());
|
||||
|
||||
rc = hw_ostc3_device_clock(device, &now);
|
||||
}
|
||||
EMIT_PROGRESS();
|
||||
|
||||
@ -1264,6 +1269,16 @@ static dc_status_t read_ostc_settings(dc_device_t *device, DeviceDetails *m_devi
|
||||
m_deviceDetails->aGFHigh = read_ostc_cf(data, 68);
|
||||
// CF69: Allow Gradient Factor change
|
||||
m_deviceDetails->aGFSelectable = read_ostc_cf(data, 69);
|
||||
// CF70: Safety Stop Duration [s]
|
||||
m_deviceDetails->safetyStopLength = read_ostc_cf(data, 70);
|
||||
// CF71: Safety Stop Start Depth [m]
|
||||
m_deviceDetails->safetyStopStartDepth = read_ostc_cf(data, 71);
|
||||
// CF72: Safety Stop End Depth [m]
|
||||
m_deviceDetails->safetyStopEndDepth = read_ostc_cf(data, 72);
|
||||
// CF73: Safety Stop Reset Depth [m]
|
||||
m_deviceDetails->safetyStopResetDepth = read_ostc_cf(data, 73);
|
||||
// CF74: Battery Timeout [min]
|
||||
|
||||
#ifdef DEBUG_OSTC_CF
|
||||
for (int cf = 64; cf <= 95 && cf <= max_CF; cf++)
|
||||
printf("CF %d: %d\n", cf, read_ostc_cf(data, cf));
|
||||
@ -1565,6 +1580,16 @@ static dc_status_t write_ostc_settings(dc_device_t *device, DeviceDetails *m_dev
|
||||
write_ostc_cf(data, 68, max_CF, m_deviceDetails->aGFHigh);
|
||||
// CF69: Allow Gradient Factor change
|
||||
write_ostc_cf(data, 69, max_CF, m_deviceDetails->aGFSelectable);
|
||||
// CF70: Safety Stop Duration [s]
|
||||
write_ostc_cf(data, 70, max_CF, m_deviceDetails->safetyStopLength);
|
||||
// CF71: Safety Stop Start Depth [m]
|
||||
write_ostc_cf(data, 71, max_CF, m_deviceDetails->safetyStopStartDepth);
|
||||
// CF72: Safety Stop End Depth [m]
|
||||
write_ostc_cf(data, 72, max_CF, m_deviceDetails->safetyStopEndDepth);
|
||||
// CF73: Safety Stop Reset Depth [m]
|
||||
write_ostc_cf(data, 73, max_CF, m_deviceDetails->safetyStopResetDepth);
|
||||
// CF74: Battery Timeout [min]
|
||||
|
||||
#ifdef DEBUG_OSTC_CF
|
||||
for (int cf = 64; cf <= 95 && cf <= max_CF; cf++)
|
||||
printf("CF %d: %d\n", cf, read_ostc_cf(data, cf));
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QVariant>
|
||||
#include "libdivecomputer.h"
|
||||
#include <QDateTime>
|
||||
#include "devicedetails.h"
|
||||
|
||||
class DeviceThread : public QThread {
|
||||
|
||||
4
deco.c
4
deco.c
@ -244,7 +244,7 @@ double tissue_tolerance_calc(const struct dive *dive, double pressure)
|
||||
double lowest_ceiling = 0.0;
|
||||
double tissue_lowest_ceiling[16];
|
||||
|
||||
if (prefs.deco_mode != VPMB || !in_planner()) {
|
||||
if (prefs.deco_mode != VPMB) {
|
||||
for (ci = 0; ci < 16; ci++) {
|
||||
tissue_inertgas_saturation[ci] = tissue_n2_sat[ci] + tissue_he_sat[ci];
|
||||
buehlmann_inertgas_a[ci] = ((buehlmann_N2_a[ci] * tissue_n2_sat[ci]) + (buehlmann_He_a[ci] * tissue_he_sat[ci])) / tissue_inertgas_saturation[ci];
|
||||
@ -509,7 +509,7 @@ void add_segment(double pressure, const struct gasmix *gasmix, int period_in_sec
|
||||
tissue_n2_sat[ci] += n2_satmult * pn2_oversat * n2_f;
|
||||
tissue_he_sat[ci] += he_satmult * phe_oversat * he_f;
|
||||
}
|
||||
if(prefs.deco_mode == VPMB && in_planner())
|
||||
if(prefs.deco_mode == VPMB)
|
||||
calc_crushing_pressure(pressure);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -73,6 +73,11 @@ DeviceDetails::DeviceDetails(QObject *parent) :
|
||||
modWarning(false),
|
||||
dynamicAscendRate(false),
|
||||
graphicalSpeedIndicator(false),
|
||||
alwaysShowppO2(false)
|
||||
alwaysShowppO2(false),
|
||||
tempSensorOffset(0),
|
||||
safetyStopLength(0),
|
||||
safetyStopStartDepth(0),
|
||||
safetyStopEndDepth(0),
|
||||
safetyStopResetDepth(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -91,6 +91,11 @@ public:
|
||||
bool dynamicAscendRate;
|
||||
bool graphicalSpeedIndicator;
|
||||
bool alwaysShowppO2;
|
||||
int tempSensorOffset;
|
||||
unsigned safetyStopLength;
|
||||
unsigned safetyStopStartDepth;
|
||||
unsigned safetyStopEndDepth;
|
||||
unsigned safetyStopResetDepth;
|
||||
};
|
||||
|
||||
|
||||
|
||||
48
dive.c
48
dive.c
@ -474,11 +474,10 @@ void copy_dive(struct dive *s, struct dive *d)
|
||||
d->weightsystem[i].description = copy_string(s->weightsystem[i].description);
|
||||
STRUCTURED_LIST_COPY(struct picture, s->picture_list, d->picture_list, copy_pl);
|
||||
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
|
||||
|
||||
/* Copy the embedded dc first, then copy the list */
|
||||
copy_dc(&s->dc, &d->dc);
|
||||
STRUCTURED_LIST_COPY(struct divecomputer, s->dc.next, d->dc.next, copy_dc);
|
||||
/* this only copied dive computers 2 and up. The first dive computer is part
|
||||
* of the struct dive, so let's make copies of its samples and events */
|
||||
copy_samples(&s->dc, &d->dc);
|
||||
copy_events(&s->dc, &d->dc);
|
||||
}
|
||||
|
||||
/* make a clone of the source dive and clean out the source dive;
|
||||
@ -525,6 +524,22 @@ void selective_copy_dive(struct dive *s, struct dive *d, struct dive_components
|
||||
}
|
||||
#undef CONDITIONAL_COPY_STRING
|
||||
|
||||
struct event *clone_event(const struct event *src_ev)
|
||||
{
|
||||
struct event *ev;
|
||||
if (!src_ev)
|
||||
return NULL;
|
||||
|
||||
size_t size = sizeof(*src_ev) + strlen(src_ev->name) + 1;
|
||||
ev = (struct event*) malloc(size);
|
||||
if (!ev)
|
||||
exit(1);
|
||||
memcpy(ev, src_ev, size);
|
||||
ev->next = NULL;
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/* copies all events in this dive computer */
|
||||
void copy_events(struct divecomputer *s, struct divecomputer *d)
|
||||
{
|
||||
@ -534,9 +549,7 @@ void copy_events(struct divecomputer *s, struct divecomputer *d)
|
||||
ev = s->events;
|
||||
pev = &d->events;
|
||||
while (ev != NULL) {
|
||||
int size = sizeof(*ev) + strlen(ev->name) + 1;
|
||||
struct event *new_ev = malloc(size);
|
||||
memcpy(new_ev, ev, size);
|
||||
struct event *new_ev = clone_event(ev);
|
||||
*pev = new_ev;
|
||||
pev = &new_ev->next;
|
||||
ev = ev->next;
|
||||
@ -1102,6 +1115,8 @@ static void fixup_water_salinity(struct dive *dive)
|
||||
|
||||
for_each_dc (dive, dc) {
|
||||
if (dc->salinity) {
|
||||
if (dc->salinity < 500)
|
||||
dc->salinity += FRESHWATER_SALINITY;
|
||||
sum += dc->salinity;
|
||||
nr++;
|
||||
}
|
||||
@ -2148,6 +2163,9 @@ static int find_sample_offset(struct divecomputer *a, struct divecomputer *b)
|
||||
*/
|
||||
static int similar(unsigned long a, unsigned long b, unsigned long expected)
|
||||
{
|
||||
if (!a && !b)
|
||||
return 1;
|
||||
|
||||
if (a && b) {
|
||||
unsigned long min, max, diff;
|
||||
|
||||
@ -2338,6 +2356,20 @@ static void free_pic(struct picture *picture)
|
||||
}
|
||||
}
|
||||
|
||||
// When handling pictures in different threads, we need to copy them so we don't
|
||||
// run into problems when the main thread frees the picture.
|
||||
|
||||
struct picture *clone_picture(struct picture *src)
|
||||
{
|
||||
struct picture *dst;
|
||||
|
||||
dst = alloc_picture();
|
||||
copy_pl(src, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int same_sample(struct sample *a, struct sample *b)
|
||||
{
|
||||
if (a->time.seconds != b->time.seconds)
|
||||
@ -3368,7 +3400,7 @@ void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture)
|
||||
}
|
||||
}
|
||||
|
||||
static void picture_free(struct picture *picture)
|
||||
void picture_free(struct picture *picture)
|
||||
{
|
||||
if (!picture)
|
||||
return;
|
||||
|
||||
5
dive.h
5
dive.h
@ -376,6 +376,7 @@ struct picture {
|
||||
for (struct picture *picture = (_divestruct).picture_list; picture; picture = picture->next)
|
||||
|
||||
extern struct picture *alloc_picture();
|
||||
extern struct picture *clone_picture(struct picture *src);
|
||||
extern bool dive_check_picture_time(struct dive *d, int shift_time, timestamp_t timestamp);
|
||||
extern void dive_create_picture(struct dive *d, char *filename, int shift_time, bool match_all);
|
||||
extern void dive_add_picture(struct dive *d, struct picture *newpic);
|
||||
@ -385,6 +386,7 @@ extern bool picture_check_valid(char *filename, int shift_time);
|
||||
extern void picture_load_exif_data(struct picture *p);
|
||||
extern timestamp_t picture_get_timestamp(char *filename);
|
||||
extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic);
|
||||
extern void picture_free(struct picture *picture);
|
||||
|
||||
extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc);
|
||||
extern int get_depth_at_time(struct divecomputer *dc, int time);
|
||||
@ -409,6 +411,8 @@ static inline int calculate_depth_to_mbar(int depth, pressure_t surface_pressure
|
||||
mbar = SURFACE_PRESSURE;
|
||||
if (!salinity)
|
||||
salinity = SEAWATER_SALINITY;
|
||||
if (salinity < 500)
|
||||
salinity += FRESHWATER_SALINITY;
|
||||
specific_weight = salinity / 10000.0 * 0.981;
|
||||
mbar += rint(depth / 10.0 * specific_weight);
|
||||
return mbar;
|
||||
@ -725,6 +729,7 @@ extern int split_dive(struct dive *);
|
||||
extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded);
|
||||
extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded);
|
||||
extern void renumber_dives(int start_nr, bool selected_only);
|
||||
extern struct event *clone_event(const struct event *src_ev);
|
||||
extern void copy_events(struct divecomputer *s, struct divecomputer *d);
|
||||
extern void free_events(struct event *ev);
|
||||
extern void copy_cylinders(struct dive *s, struct dive *d, bool used_only);
|
||||
|
||||
107
file.c
107
file.c
@ -105,6 +105,9 @@ int try_to_open_zip(const char *filename, struct memblock *mem)
|
||||
success++;
|
||||
}
|
||||
subsurface_zip_close(zip);
|
||||
|
||||
if (!success)
|
||||
return report_error(translate("gettextFromC", "No dives in the input file '%s'"), filename);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@ -828,7 +831,7 @@ int parse_txt_file(const char *filename, const char *csv)
|
||||
record_dive(dive);
|
||||
return 1;
|
||||
} else {
|
||||
return report_error(translate("gettextFromC", "No matching DC found for file '%s'"), csv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -856,22 +859,86 @@ int parse_csv_file(const char *filename, char **params, int pnr, const char *csv
|
||||
if (filename == NULL)
|
||||
return report_error("No CSV filename");
|
||||
|
||||
time(&now);
|
||||
timep = localtime(&now);
|
||||
|
||||
strftime(tmpbuf, MAXCOLDIGITS, "%Y%m%d", timep);
|
||||
params[pnr++] = "date";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
|
||||
/* As the parameter is numeric, we need to ensure that the leading zero
|
||||
* is not discarded during the transform, thus prepend time with 1 */
|
||||
|
||||
strftime(tmpbuf, MAXCOLDIGITS, "1%H%M", timep);
|
||||
params[pnr++] = "time";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
params[pnr++] = NULL;
|
||||
|
||||
mem.size = 0;
|
||||
if (!strcmp("DL7", csvtemplate)) {
|
||||
char *ptr = NULL;
|
||||
char *NL = NULL;
|
||||
char *iter = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
csvtemplate = "csv";
|
||||
if (readfile(filename, &mem) < 0)
|
||||
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
|
||||
|
||||
/* Determine NL (new line) character and the start of CSV data */
|
||||
if ((ptr = strstr(mem.buffer, "\r\n")) != NULL) {
|
||||
NL = "\r\n";
|
||||
} else if ((ptr = strstr(mem.buffer, "\n")) != NULL) {
|
||||
NL = "\n";
|
||||
} else {
|
||||
fprintf(stderr, "DEBUG: failed to detect NL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = strstr(mem.buffer, "ZDH");
|
||||
if (ptr) {
|
||||
iter = ptr + 1;
|
||||
for (i = 0; i <= 4 && iter; ++i) {
|
||||
iter = strchr(iter, '|');
|
||||
if (iter)
|
||||
++iter;
|
||||
}
|
||||
|
||||
/* Setting date */
|
||||
memcpy(tmpbuf, iter, 8);
|
||||
tmpbuf[8] = 0;
|
||||
params[pnr++] = "date";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
|
||||
/* Setting time, gotta prepend it with 1 to
|
||||
* avoid octal parsing (this is stripped out in
|
||||
* XSLT */
|
||||
tmpbuf[0] = '1';
|
||||
memcpy(tmpbuf + 1, iter + 8, 6);
|
||||
tmpbuf[7] = 0;
|
||||
params[pnr++] = "time";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
params[pnr++] = NULL;
|
||||
}
|
||||
|
||||
ptr = strstr(mem.buffer, "ZDP");
|
||||
if (ptr)
|
||||
ptr = strstr(ptr, NL);
|
||||
if (ptr)
|
||||
ptr += strlen(NL);
|
||||
|
||||
/* Move the CSV data to the start of mem buffer */
|
||||
memmove(mem.buffer, ptr, mem.size - (ptr - (char*)mem.buffer));
|
||||
ptr = strstr(mem.buffer, "ZDP");
|
||||
if (ptr) {
|
||||
*ptr = 0;
|
||||
} else {
|
||||
fprintf(stderr, "DEBUG: failed to find end ZDP\n");
|
||||
return -1;
|
||||
}
|
||||
mem.size = ptr - (char*)mem.buffer;
|
||||
} else if (strcmp(params[0], "date")) {
|
||||
time(&now);
|
||||
timep = localtime(&now);
|
||||
|
||||
strftime(tmpbuf, MAXCOLDIGITS, "%Y%m%d", timep);
|
||||
params[pnr++] = "date";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
|
||||
/* As the parameter is numeric, we need to ensure that the leading zero
|
||||
* is not discarded during the transform, thus prepend time with 1 */
|
||||
|
||||
strftime(tmpbuf, MAXCOLDIGITS, "1%H%M", timep);
|
||||
params[pnr++] = "time";
|
||||
params[pnr++] = strdup(tmpbuf);
|
||||
params[pnr++] = NULL;
|
||||
}
|
||||
|
||||
if (try_to_xslt_open_csv(filename, &mem, csvtemplate))
|
||||
return -1;
|
||||
|
||||
@ -1057,6 +1124,14 @@ int parse_manual_file(const char *filename, char **params, int pnr)
|
||||
if (try_to_xslt_open_csv(filename, &mem, "manualCSV"))
|
||||
return -1;
|
||||
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
if (verbose >= 2) {
|
||||
fprintf(stderr, "(echo '<manualCSV>'; cat %s;echo '</manualCSV>') | xsltproc ", filename);
|
||||
for (i=0; params[i]; i+=2)
|
||||
fprintf(stderr, "--stringparam %s %s ", params[i], params[i+1]);
|
||||
fprintf(stderr, "%s/xslt/manualcsv2xml.xslt -\n", SUBSURFACE_SOURCE);
|
||||
}
|
||||
#endif
|
||||
ret = parse_xml_buffer(filename, mem.buffer, mem.size, &dive_table, (const char **)params);
|
||||
|
||||
free(mem.buffer);
|
||||
|
||||
29
git-access.c
29
git-access.c
@ -188,8 +188,23 @@ int credential_ssh_cb(git_cred **out,
|
||||
unsigned int allowed_types,
|
||||
void *payload)
|
||||
{
|
||||
(void) url;
|
||||
(void) allowed_types;
|
||||
(void) payload;
|
||||
static int attempt = 0;
|
||||
|
||||
const char *priv_key = format_string("%s/%s", system_default_directory(), "ssrf_remote.key");
|
||||
const char *passphrase = prefs.cloud_storage_password ? strdup(prefs.cloud_storage_password) : strdup("");
|
||||
|
||||
/* Bail out from libgit authentication loop when credentials are
|
||||
* incorrect */
|
||||
|
||||
if (attempt++ > 2) {
|
||||
report_error("Authentication to cloud storage failed.");
|
||||
attempt = 0;
|
||||
return GIT_EUSER;
|
||||
}
|
||||
|
||||
return git_cred_ssh_key_new(out, username_from_url, NULL, priv_key, passphrase);
|
||||
}
|
||||
|
||||
@ -199,8 +214,22 @@ int credential_https_cb(git_cred **out,
|
||||
unsigned int allowed_types,
|
||||
void *payload)
|
||||
{
|
||||
(void) url;
|
||||
(void) username_from_url;
|
||||
(void) payload;
|
||||
(void) allowed_types;
|
||||
static int attempt = 0;
|
||||
const char *username = prefs.cloud_storage_email_encoded;
|
||||
const char *password = prefs.cloud_storage_password ? strdup(prefs.cloud_storage_password) : strdup("");
|
||||
|
||||
/* Bail out from libgit authentication loop when credentials are
|
||||
* incorrect */
|
||||
|
||||
if (attempt++ > 2) {
|
||||
report_error("Authentication to cloud storage failed.");
|
||||
attempt = 0;
|
||||
return GIT_EUSER;
|
||||
}
|
||||
return git_cred_userpass_plaintext_new(out, username, password);
|
||||
}
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
|
||||
int ntanks = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_TANK_COUNT, 0, &ntanks);
|
||||
if (rc == DC_STATUS_SUCCESS) {
|
||||
if (ntanks != ngases) {
|
||||
if (ntanks && ntanks != ngases) {
|
||||
shown_warning = true;
|
||||
report_error("different number of gases (%d) and tanks (%d)", ngases, ntanks);
|
||||
}
|
||||
@ -695,7 +695,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
|
||||
dc_parser_destroy(parser);
|
||||
|
||||
/* Various libdivecomputer interface fixups */
|
||||
if (first_temp_is_air && dive->dc.samples) {
|
||||
if (dive->dc.airtemp.mkelvin == 0 && first_temp_is_air && dive->dc.samples) {
|
||||
dive->dc.airtemp = dive->dc.sample[0].temperature;
|
||||
dive->dc.sample[0].temperature.mkelvin = 0;
|
||||
}
|
||||
|
||||
@ -114,17 +114,17 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int
|
||||
model = *(buf + ptr);
|
||||
switch (model) {
|
||||
case 0:
|
||||
dc->model = "Xen";
|
||||
dc->model = strdup("Xen");
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
dc->model = "Xeo";
|
||||
dc->model = strdup("Xeo");
|
||||
break;
|
||||
case 4:
|
||||
dc->model = "Lynx";
|
||||
dc->model = strdup("Lynx");
|
||||
break;
|
||||
default:
|
||||
dc->model = "Liquivision";
|
||||
dc->model = strdup("Liquivision");
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
|
||||
11
load-git.c
11
load-git.c
@ -9,6 +9,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <git2.h>
|
||||
#include <libdivecomputer/parser.h>
|
||||
|
||||
#include "gettext.h"
|
||||
|
||||
@ -744,6 +745,16 @@ static void parse_dc_event(char *line, struct membuffer *str, void *_dc)
|
||||
if (str->len)
|
||||
name = mb_cstring(str);
|
||||
ev = add_event(dc, event.time.seconds, event.type, event.flags, event.value, name);
|
||||
|
||||
/*
|
||||
* Older logs might mark the dive to be CCR by having an "SP change" event at time 0:00.
|
||||
* Better to mark them being CCR on import so no need for special treatments elsewhere on
|
||||
* the code.
|
||||
*/
|
||||
if (ev && event.time.seconds == 0 && event.type == SAMPLE_EVENT_PO2 && dc->divemode==OC) {
|
||||
dc->divemode = CCR;
|
||||
}
|
||||
|
||||
if (ev && event_is_gaschange(ev)) {
|
||||
/*
|
||||
* We subtract one here because "0" is "no index",
|
||||
|
||||
8
main.cpp
8
main.cpp
@ -58,6 +58,14 @@ int main(int argc, char **argv)
|
||||
#else
|
||||
git_libgit2_init();
|
||||
#endif
|
||||
/*
|
||||
* Initialize the random number generator - not really secure as
|
||||
* this is based only on current time, but it should not matter
|
||||
* that much in our context. Moreover this is better than
|
||||
* the constant numbers we used to get before.
|
||||
*/
|
||||
qsrand(time(NULL));
|
||||
|
||||
setup_system_prefs();
|
||||
copy_prefs(&default_prefs, &prefs);
|
||||
fill_profile_color();
|
||||
|
||||
@ -20,12 +20,35 @@ rm -rf ./Subsurface.app
|
||||
LIBRARY_PATH=${DIR}/install-root/lib make -j8
|
||||
LIBRARY_PATH=${DIR}/install-root/lib make install
|
||||
|
||||
# HACK TIME... QtXml is missing. screw this
|
||||
cp -a /Users/hohndel/Qt/5.5/clang_64/lib/QtXml.framework Subsurface.app/Contents/Frameworks
|
||||
rm -rf Subsurface.app/Contents/Frameworks/QtXml.framework/Versions/5/Headers
|
||||
rm -rf Subsurface.app/Contents/Frameworks/QtXml.framework/Headers
|
||||
rm -rf Subsurface.app/Contents/Frameworks/QtXml.framework/QtXml.prl
|
||||
rm -rf Subsurface.app/Contents/Frameworks/QtXml.framework/Versions/5/*_debug
|
||||
rm -rf Subsurface.app/Contents/Frameworks/QtXml.framework/*_debug*
|
||||
install_name_tool -id @executable_path/../Frameworks/QtXml Subsurface.app/Contents/Frameworks/QtXml.framework/QtXml
|
||||
install_name_tool -change @rpath/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/QtCore Subsurface.app/Contents/Frameworks/QtXml.framework/QtXml
|
||||
|
||||
# now adjust a few references that macdeployqt appears to miss
|
||||
EXECUTABLE=Subsurface.app/Contents/MacOS/Subsurface
|
||||
for i in libssrfmarblewidget libgit2; do
|
||||
for i in libssh libssrfmarblewidget libgit2; do
|
||||
OLD=$(otool -L ${EXECUTABLE} | grep $i | cut -d\ -f1 | tr -d "\t")
|
||||
cp ${DIR}/install-root/lib/$(basename ${OLD}) Subsurface.app/Contents/Frameworks
|
||||
SONAME=$(basename $OLD)
|
||||
install_name_tool -change ${OLD} @executable_path/../Frameworks/${SONAME} ${EXECUTABLE}
|
||||
if [[ "$i" = "libssh" ]] ; then
|
||||
LIBSSH=$(basename ${OLD})
|
||||
fi
|
||||
if [[ "$i" = "libgit2" ]] ; then
|
||||
install_name_tool -change ${LIBSSH} @executable_path/../Frameworks/${LIBSSH} Subsurface.app/Contents/Frameworks/${SONAME}
|
||||
fi
|
||||
done
|
||||
|
||||
# next deal with libGrantlee
|
||||
LIBG=Subsurface.app/Contents/Frameworks/libGrantlee_Templates.5.dylib
|
||||
for i in QtScript.framework/Versions/5/QtScript QtCore.framework/Versions/5/QtCore ; do
|
||||
install_name_tool -change @rpath/$i @executable_path/../Frameworks/$i ${LIBG}
|
||||
done
|
||||
|
||||
# it seems the compiler in XCode 4.6 doesn't build Grantlee5 correctly,
|
||||
@ -34,13 +57,16 @@ done
|
||||
#
|
||||
# -disabled for now as this is still under more investigation-
|
||||
# cp -a /Users/hohndel/src/tmp/Subsurface.app/Contents Subsurface.app/
|
||||
cp ${DIR}/tmp/Subsurface.app/Contents/Frameworks/lib{sql,usb,zip}* Subsurface.app/Contents/Frameworks
|
||||
|
||||
# clean up shared library dependency in the Grantlee plugins
|
||||
for i in Subsurface.app/Contents/PlugIns/grantlee/5.0/*.so; do
|
||||
OLD=$(otool -L $i | grep libGrantlee_Templates | cut -d\ -f1 | tr -d "\t")
|
||||
SONAME=$(basename $OLD )
|
||||
install_name_tool -change ${OLD} @executable_path/../Frameworks/${SONAME} $i;
|
||||
mv $i Subsurface.app/Contents/PlugIns/grantlee
|
||||
done
|
||||
rmdir Subsurface.app/Contents/PlugIns/grantlee/5.0
|
||||
|
||||
# copy things into staging so we can create a nice DMG
|
||||
rm -rf ./staging
|
||||
|
||||
@ -5,9 +5,10 @@
|
||||
echo -- signing staging/Subsurface.app
|
||||
cd staging
|
||||
|
||||
echo -- signing Qt frameworks
|
||||
echo -- signing Qt frameworks and shared libraries
|
||||
|
||||
codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk ./Subsurface.app//Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent \
|
||||
for i in \
|
||||
./Subsurface.app//Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent \
|
||||
./Subsurface.app//Contents/Frameworks/QtCore.framework/Versions/5/QtCore \
|
||||
./Subsurface.app//Contents/Frameworks/QtGui.framework/Versions/5/QtGui \
|
||||
./Subsurface.app//Contents/Frameworks/QtMultimedia.framework/Versions/5/QtMultimedia \
|
||||
@ -25,10 +26,20 @@ codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk ./Su
|
||||
./Subsurface.app//Contents/Frameworks/QtWebKit.framework/Versions/5/QtWebKit \
|
||||
./Subsurface.app//Contents/Frameworks/QtWebKitWidgets.framework/Versions/5/QtWebKitWidgets \
|
||||
./Subsurface.app//Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets \
|
||||
./Subsurface.app//Contents/Frameworks/QtXmlPatterns.framework/Versions/5/QtXMLPatterns
|
||||
./Subsurface.app//Contents/Frameworks/QtBluetooth.framework/Versions/5/QtBluetooth \
|
||||
./Subsurface.app//Contents/Frameworks/QtDbus.framework/Versions/5/QtDbus \
|
||||
./Subsurface.app//Contents/Frameworks/QtXml.framework/Versions/5/QtXml \
|
||||
./Subsurface.app//Contents/Frameworks/QtWebChannel.framework/Versions/5/QtWebChannel \
|
||||
./Subsurface.app//Contents/Frameworks/*.dylib
|
||||
do
|
||||
codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk $i
|
||||
done
|
||||
|
||||
echo -- signing plugins
|
||||
find ./Subsurface.app/Contents/PlugIns -name \*.dylib | xargs codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk
|
||||
for i in $(find ./Subsurface.app/Contents/PlugIns -name \*.dylib -o -name \*.so)
|
||||
do
|
||||
codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk $i
|
||||
done
|
||||
|
||||
echo -- finally sign .app
|
||||
codesign --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk ./Subsurface.app
|
||||
codesign -v --keychain /Users/hohndel/Library/Keychains/login.keychain -s Dirk ./Subsurface.app
|
||||
|
||||
@ -99,6 +99,12 @@ rel=wily
|
||||
sed -i "s/${prev}/${rel}/g" debian/changelog
|
||||
debuild -S
|
||||
|
||||
# and now for wily
|
||||
prev=wily
|
||||
rel=xenial
|
||||
sed -i "s/${prev}/${rel}/g" debian/changelog
|
||||
debuild -S
|
||||
|
||||
# and now for precise (precise can't build Qt5 based packages)
|
||||
# with the switch to cmake the amount of effort to build Qt4 packages
|
||||
# on precise just doesn't seem worth it anymore
|
||||
|
||||
67
parse-xml.c
67
parse-xml.c
@ -1398,32 +1398,36 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||
return;
|
||||
if (MATCH("visibility.dive", get_rating, &dive->visibility))
|
||||
return;
|
||||
if (MATCH("size.cylinder", cylindersize, &dive->cylinder[cur_cylinder_index].type.size))
|
||||
return;
|
||||
if (MATCH("workpressure.cylinder", pressure, &dive->cylinder[cur_cylinder_index].type.workingpressure))
|
||||
return;
|
||||
if (MATCH("description.cylinder", utf8_string, &dive->cylinder[cur_cylinder_index].type.description))
|
||||
return;
|
||||
if (MATCH("start.cylinder", pressure, &dive->cylinder[cur_cylinder_index].start))
|
||||
return;
|
||||
if (MATCH("end.cylinder", pressure, &dive->cylinder[cur_cylinder_index].end))
|
||||
return;
|
||||
if (MATCH("use.cylinder", cylinder_use, &dive->cylinder[cur_cylinder_index].cylinder_use))
|
||||
return;
|
||||
if (MATCH("description.weightsystem", utf8_string, &dive->weightsystem[cur_ws_index].description))
|
||||
return;
|
||||
if (MATCH("weight.weightsystem", weight, &dive->weightsystem[cur_ws_index].weight))
|
||||
return;
|
||||
if (MATCH("weight", weight, &dive->weightsystem[cur_ws_index].weight))
|
||||
return;
|
||||
if (MATCH("o2", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.o2))
|
||||
return;
|
||||
if (MATCH("o2percent", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.o2))
|
||||
return;
|
||||
if (MATCH("n2", gasmix_nitrogen, &dive->cylinder[cur_cylinder_index].gasmix))
|
||||
return;
|
||||
if (MATCH("he", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.he))
|
||||
return;
|
||||
if (cur_ws_index < MAX_WEIGHTSYSTEMS) {
|
||||
if (MATCH("description.weightsystem", utf8_string, &dive->weightsystem[cur_ws_index].description))
|
||||
return;
|
||||
if (MATCH("weight.weightsystem", weight, &dive->weightsystem[cur_ws_index].weight))
|
||||
return;
|
||||
if (MATCH("weight", weight, &dive->weightsystem[cur_ws_index].weight))
|
||||
return;
|
||||
}
|
||||
if (cur_cylinder_index < MAX_CYLINDERS) {
|
||||
if (MATCH("size.cylinder", cylindersize, &dive->cylinder[cur_cylinder_index].type.size))
|
||||
return;
|
||||
if (MATCH("workpressure.cylinder", pressure, &dive->cylinder[cur_cylinder_index].type.workingpressure))
|
||||
return;
|
||||
if (MATCH("description.cylinder", utf8_string, &dive->cylinder[cur_cylinder_index].type.description))
|
||||
return;
|
||||
if (MATCH("start.cylinder", pressure, &dive->cylinder[cur_cylinder_index].start))
|
||||
return;
|
||||
if (MATCH("end.cylinder", pressure, &dive->cylinder[cur_cylinder_index].end))
|
||||
return;
|
||||
if (MATCH("use.cylinder", cylinder_use, &dive->cylinder[cur_cylinder_index].cylinder_use))
|
||||
return;
|
||||
if (MATCH("o2", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.o2))
|
||||
return;
|
||||
if (MATCH("o2percent", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.o2))
|
||||
return;
|
||||
if (MATCH("n2", gasmix_nitrogen, &dive->cylinder[cur_cylinder_index].gasmix))
|
||||
return;
|
||||
if (MATCH("he", gasmix, &dive->cylinder[cur_cylinder_index].gasmix.he))
|
||||
return;
|
||||
}
|
||||
if (MATCH("air.divetemperature", temperature, &dive->airtemp))
|
||||
return;
|
||||
if (MATCH("water.divetemperature", temperature, &dive->watertemp))
|
||||
@ -1647,6 +1651,15 @@ static void event_end(void)
|
||||
ev = add_event(dc, cur_event.time.seconds,
|
||||
cur_event.type, cur_event.flags,
|
||||
cur_event.value, cur_event.name);
|
||||
|
||||
/*
|
||||
* Older logs might mark the dive to be CCR by having an "SP change" event at time 0:00. Better
|
||||
* to mark them being CCR on import so no need for special treatments elsewhere on the code.
|
||||
*/
|
||||
if (ev && cur_event.time.seconds == 0 && cur_event.type == SAMPLE_EVENT_PO2 && dc->divemode==OC) {
|
||||
dc->divemode = CCR;
|
||||
}
|
||||
|
||||
if (ev && event_is_gaschange(ev)) {
|
||||
/* See try_to_fill_event() on why the filled-in index is one too big */
|
||||
ev->gas.index = cur_event.gas.index-1;
|
||||
@ -3331,7 +3344,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size)
|
||||
while (ptr < buffer + size) {
|
||||
time = ((ptr[0] >> 4) & 0x0f) +
|
||||
((ptr[1] << 4) & 0xff0) +
|
||||
(ptr[2] & 0x0f) * 3600; /* hours */
|
||||
((ptr[2] << 12) & 0x1f000);
|
||||
event = ptr[0] & 0x0f;
|
||||
switch (event) {
|
||||
case 0:
|
||||
|
||||
@ -534,7 +534,8 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool
|
||||
const unsigned int sz_temp = 100000;
|
||||
char *buffer = (char *)malloc(sz_buffer);
|
||||
char *temp = (char *)malloc(sz_temp);
|
||||
char buf[1000], *deco;
|
||||
char *deco;
|
||||
static char buf[1000];
|
||||
int len, lastdepth = 0, lasttime = 0, lastsetpoint = -1, newdepth = 0, lastprintdepth = 0, lastprintsetpoint = -1;
|
||||
struct gasmix lastprintgasmix = {{ -1 }, { -1 }};
|
||||
struct divedatapoint *dp = diveplan->dp;
|
||||
@ -775,7 +776,8 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool
|
||||
lastsetpoint = dp->setpoint;
|
||||
lastentered = dp->entered;
|
||||
} while ((dp = nextdp) != NULL);
|
||||
len += snprintf(buffer + len, sz_buffer - len, "</tbody></table></div>");
|
||||
if (!plan_verbatim)
|
||||
len += snprintf(buffer + len, sz_buffer - len, "</tbody></table></div>");
|
||||
|
||||
dive->cns = 0;
|
||||
dive->maxcns = 0;
|
||||
|
||||
186
profile.c
186
profile.c
@ -28,6 +28,9 @@ unsigned int dc_number = 0;
|
||||
static struct plot_data *last_pi_entry_new = NULL;
|
||||
void populate_pressure_information(struct dive *, struct divecomputer *, struct plot_info *, int);
|
||||
|
||||
extern bool in_planner();
|
||||
extern pressure_t first_ceiling_pressure;
|
||||
|
||||
#ifdef DEBUG_PI
|
||||
/* debugging tool - not normally used */
|
||||
static void dump_pi(struct plot_info *pi)
|
||||
@ -866,6 +869,8 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
|
||||
int ascent_depth = entry->depth;
|
||||
/* at what time should we give up and say that we got enuff NDL? */
|
||||
int cylinderindex = entry->cylinderindex;
|
||||
/* If iterating through a dive, entry->tts_calc needs to be reset */
|
||||
entry->tts_calc = 0;
|
||||
|
||||
/* If we don't have a ceiling yet, calculate ndl. Don't try to calculate
|
||||
* a ndl for lower values than 3m it would take forever */
|
||||
@ -927,69 +932,136 @@ static void calculate_ndl_tts(struct plot_data *entry, struct dive *dive, double
|
||||
*/
|
||||
void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode)
|
||||
{
|
||||
int i;
|
||||
int i, count_iteration = 0;
|
||||
double surface_pressure = (dc->surface_pressure.mbar ? dc->surface_pressure.mbar : get_surface_pressure_in_mbar(dive, true)) / 1000.0;
|
||||
int last_ndl_tts_calc_time = 0;
|
||||
for (i = 1; i < pi->nr; i++) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
int j, t0 = (entry - 1)->sec, t1 = entry->sec;
|
||||
int time_stepsize = 20;
|
||||
bool first_iteration = true;
|
||||
int deco_time = 0, prev_deco_time = 10000000;
|
||||
char *cache_data_initial = NULL;
|
||||
/* For VPM-B outside the planner, cache the initial deco state for CVA iterations */
|
||||
if (prefs.deco_mode == VPMB && !in_planner())
|
||||
cache_deco_state(&cache_data_initial);
|
||||
/* For VPM-B outside the planner, iterate until deco time converges (usually one or two iterations after the initial)
|
||||
* Set maximum number of iterations to 10 just in case */
|
||||
while ((abs(prev_deco_time - deco_time) >= 30) && (count_iteration < 10)) {
|
||||
int last_ndl_tts_calc_time = 0, first_ceiling = 0, current_ceiling, final_tts = 0 , time_clear_ceiling = 0, time_deep_ceiling = 0;
|
||||
for (i = 1; i < pi->nr; i++) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
int j, t0 = (entry - 1)->sec, t1 = entry->sec;
|
||||
int time_stepsize = 20;
|
||||
|
||||
entry->ambpressure = depth_to_bar(entry->depth, dive);
|
||||
entry->gfline = MAX((double)prefs.gflow, (entry->ambpressure - surface_pressure) / (gf_low_pressure_this_dive - surface_pressure) *
|
||||
(prefs.gflow - prefs.gfhigh) +
|
||||
prefs.gfhigh) *
|
||||
(100.0 - AMB_PERCENTAGE) / 100.0 + AMB_PERCENTAGE;
|
||||
if (t0 > t1) {
|
||||
fprintf(stderr, "non-monotonous dive stamps %d %d\n", t0, t1);
|
||||
int xchg = t1;
|
||||
t1 = t0;
|
||||
t0 = xchg;
|
||||
}
|
||||
if (t0 != t1 && t1 - t0 < time_stepsize)
|
||||
time_stepsize = t1 - t0;
|
||||
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
|
||||
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
|
||||
add_segment(depth_to_bar(depth, dive),
|
||||
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
|
||||
if ((t1 - j < time_stepsize) && (j < t1))
|
||||
time_stepsize = t1 - j;
|
||||
}
|
||||
if (t0 == t1)
|
||||
entry->ceiling = (entry - 1)->ceiling;
|
||||
else
|
||||
entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m);
|
||||
for (j = 0; j < 16; j++) {
|
||||
double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
|
||||
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
|
||||
entry->percentages[j] = tissue_inertgas_saturation[j] < entry->ambpressure ?
|
||||
tissue_inertgas_saturation[j] / entry->ambpressure * AMB_PERCENTAGE :
|
||||
AMB_PERCENTAGE + (tissue_inertgas_saturation[j] - entry->ambpressure) / (m_value - entry->ambpressure) * (100.0 - AMB_PERCENTAGE);
|
||||
}
|
||||
|
||||
/* should we do more calculations?
|
||||
* We don't for print-mode because this info doesn't show up there */
|
||||
if (prefs.calcndltts && !print_mode) {
|
||||
/* only calculate ndl/tts on every 30 seconds */
|
||||
if ((entry->sec - last_ndl_tts_calc_time) < 30) {
|
||||
struct plot_data *prev_entry = (entry - 1);
|
||||
entry->stoptime_calc = prev_entry->stoptime_calc;
|
||||
entry->stopdepth_calc = prev_entry->stopdepth_calc;
|
||||
entry->tts_calc = prev_entry->tts_calc;
|
||||
entry->ndl_calc = prev_entry->ndl_calc;
|
||||
continue;
|
||||
entry->ambpressure = depth_to_bar(entry->depth, dive);
|
||||
entry->gfline = MAX((double)prefs.gflow, (entry->ambpressure - surface_pressure) / (gf_low_pressure_this_dive - surface_pressure) *
|
||||
(prefs.gflow - prefs.gfhigh) +
|
||||
prefs.gfhigh) *
|
||||
(100.0 - AMB_PERCENTAGE) / 100.0 + AMB_PERCENTAGE;
|
||||
if (t0 > t1) {
|
||||
fprintf(stderr, "non-monotonous dive stamps %d %d\n", t0, t1);
|
||||
int xchg = t1;
|
||||
t1 = t0;
|
||||
t0 = xchg;
|
||||
}
|
||||
if (t0 != t1 && t1 - t0 < time_stepsize)
|
||||
time_stepsize = t1 - t0;
|
||||
for (j = t0 + time_stepsize; j <= t1; j += time_stepsize) {
|
||||
int depth = interpolate(entry[-1].depth, entry[0].depth, j - t0, t1 - t0);
|
||||
add_segment(depth_to_bar(depth, dive),
|
||||
&dive->cylinder[entry->cylinderindex].gasmix, time_stepsize, entry->o2pressure.mbar, dive, entry->sac);
|
||||
if ((t1 - j < time_stepsize) && (j < t1))
|
||||
time_stepsize = t1 - j;
|
||||
}
|
||||
if (t0 == t1) {
|
||||
entry->ceiling = (entry - 1)->ceiling;
|
||||
} else {
|
||||
/* Keep updating the VPM-B gradients until the start of the ascent phase of the dive. */
|
||||
if (prefs.deco_mode == VPMB && !in_planner() && (entry - 1)->ceiling >= first_ceiling && first_iteration == true) {
|
||||
nuclear_regeneration(t1);
|
||||
vpmb_start_gradient();
|
||||
/* For CVA calculations, start by guessing deco time = dive time remaining */
|
||||
deco_time = pi->maxtime - t1;
|
||||
vpmb_next_gradient(deco_time, surface_pressure / 1000.0);
|
||||
}
|
||||
entry->ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, !prefs.calcceiling3m);
|
||||
if (prefs.calcceiling3m)
|
||||
current_ceiling = deco_allowed_depth(tissue_tolerance_calc(dive, depth_to_bar(entry->depth, dive)), surface_pressure, dive, true);
|
||||
else
|
||||
current_ceiling = entry->ceiling;
|
||||
/* If using VPM-B outside the planner, take first_ceiling_pressure as the deepest ceiling */
|
||||
if (prefs.deco_mode == VPMB && !in_planner()) {
|
||||
if (current_ceiling > first_ceiling) {
|
||||
time_deep_ceiling = t1;
|
||||
first_ceiling = current_ceiling;
|
||||
first_ceiling_pressure.mbar = depth_to_mbar(first_ceiling, dive);
|
||||
if (first_iteration) {
|
||||
nuclear_regeneration(t1);
|
||||
vpmb_start_gradient();
|
||||
/* For CVA calculations, start by guessing deco time = dive time remaining */
|
||||
deco_time = pi->maxtime - t1;
|
||||
vpmb_next_gradient(deco_time, surface_pressure / 1000.0);
|
||||
}
|
||||
}
|
||||
// Use the point where the ceiling clears as the end of deco phase for CVA calculations
|
||||
if (current_ceiling > 0)
|
||||
time_clear_ceiling = 0;
|
||||
else if (time_clear_ceiling == 0)
|
||||
time_clear_ceiling = t1;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
double m_value = buehlmann_inertgas_a[j] + entry->ambpressure / buehlmann_inertgas_b[j];
|
||||
entry->ceilings[j] = deco_allowed_depth(tolerated_by_tissue[j], surface_pressure, dive, 1);
|
||||
entry->percentages[j] = tissue_inertgas_saturation[j] < entry->ambpressure ?
|
||||
tissue_inertgas_saturation[j] / entry->ambpressure * AMB_PERCENTAGE :
|
||||
AMB_PERCENTAGE + (tissue_inertgas_saturation[j] - entry->ambpressure) / (m_value - entry->ambpressure) * (100.0 - AMB_PERCENTAGE);
|
||||
}
|
||||
last_ndl_tts_calc_time = entry->sec;
|
||||
|
||||
/* We are going to mess up deco state, so store it for later restore */
|
||||
char *cache_data = NULL;
|
||||
cache_deco_state(&cache_data);
|
||||
calculate_ndl_tts(entry, dive, surface_pressure);
|
||||
/* Restore "real" deco state for next real time step */
|
||||
restore_deco_state(cache_data);
|
||||
free(cache_data);
|
||||
/* should we do more calculations?
|
||||
* We don't for print-mode because this info doesn't show up there
|
||||
* If the ceiling hasn't cleared by the last data point, we need tts for VPM-B CVA calculation
|
||||
* It is not necessary to do these calculation on the first VPMB iteration, except for the last data point */
|
||||
if ((prefs.calcndltts && !print_mode && (prefs.deco_mode != VPMB || in_planner() || !first_iteration)) ||
|
||||
(prefs.deco_mode == VPMB && !in_planner() && i == pi->nr - 1)) {
|
||||
/* only calculate ndl/tts on every 30 seconds */
|
||||
if ((entry->sec - last_ndl_tts_calc_time) < 30 && i != pi->nr - 1) {
|
||||
struct plot_data *prev_entry = (entry - 1);
|
||||
entry->stoptime_calc = prev_entry->stoptime_calc;
|
||||
entry->stopdepth_calc = prev_entry->stopdepth_calc;
|
||||
entry->tts_calc = prev_entry->tts_calc;
|
||||
entry->ndl_calc = prev_entry->ndl_calc;
|
||||
continue;
|
||||
}
|
||||
last_ndl_tts_calc_time = entry->sec;
|
||||
|
||||
/* We are going to mess up deco state, so store it for later restore */
|
||||
char *cache_data = NULL;
|
||||
cache_deco_state(&cache_data);
|
||||
calculate_ndl_tts(entry, dive, surface_pressure);
|
||||
if (prefs.deco_mode == VPMB && !in_planner() && i == pi->nr - 1)
|
||||
final_tts = entry->tts_calc;
|
||||
/* Restore "real" deco state for next real time step */
|
||||
restore_deco_state(cache_data);
|
||||
free(cache_data);
|
||||
}
|
||||
}
|
||||
if (prefs.deco_mode == VPMB && !in_planner()) {
|
||||
prev_deco_time = deco_time;
|
||||
// Do we need to update deco_time?
|
||||
if (final_tts > 0)
|
||||
deco_time = pi->maxtime + final_tts - time_deep_ceiling;
|
||||
else if (time_clear_ceiling > 0)
|
||||
deco_time = time_clear_ceiling - time_deep_ceiling;
|
||||
vpmb_next_gradient(deco_time, surface_pressure / 1000.0);
|
||||
final_tts = 0;
|
||||
last_ndl_tts_calc_time = 0;
|
||||
first_ceiling = 0;
|
||||
first_iteration = false;
|
||||
count_iteration ++;
|
||||
restore_deco_state(cache_data_initial);
|
||||
} else {
|
||||
// With Buhlmann, or not in planner, iterating isn't needed. This makes the while condition false.
|
||||
prev_deco_time = deco_time = 0;
|
||||
}
|
||||
}
|
||||
free(cache_data_initial);
|
||||
#if DECO_CALC_DEBUG & 1
|
||||
dump_tissues();
|
||||
#endif
|
||||
|
||||
@ -5,19 +5,21 @@
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
extern QHash <QString, QImage > thumbnailCache;
|
||||
|
||||
|
||||
SPixmap scaleImages(picturepointer picture)
|
||||
{
|
||||
static QHash <QString, QImage > cache;
|
||||
SPixmap ret;
|
||||
ret.first = picture;
|
||||
if (cache.contains(picture->filename) && !cache.value(picture->filename).isNull()) {
|
||||
ret.second = cache.value(picture->filename);
|
||||
if (thumbnailCache.contains(picture->filename) && !thumbnailCache.value(picture->filename).isNull()) {
|
||||
ret.second = thumbnailCache.value(picture->filename);
|
||||
} else {
|
||||
int dim = defaultIconMetrics().sz_pic;
|
||||
QImage p = SHashedImage(picture);
|
||||
if(!p.isNull()) {
|
||||
p = p.scaled(dim, dim, Qt::KeepAspectRatio);
|
||||
cache.insert(picture->filename, p);
|
||||
thumbnailCache.insert(picture->filename, p);
|
||||
}
|
||||
ret.second = p;
|
||||
}
|
||||
|
||||
@ -479,7 +479,10 @@ void DivePlannerPointsModel::setSafetyStop(bool value)
|
||||
|
||||
void DivePlannerPointsModel::setReserveGas(int reserve)
|
||||
{
|
||||
prefs.reserve_gas = reserve * 1000;
|
||||
if (prefs.units.pressure == units::BAR)
|
||||
prefs.reserve_gas = reserve * 1000;
|
||||
else
|
||||
prefs.reserve_gas = psi_to_mbar(reserve);
|
||||
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, COLUMNS - 1));
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ int DivePlotDataModel::columnCount(const QModelIndex &parent) const
|
||||
|
||||
QVariant DivePlotDataModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ((!index.isValid()) || (index.row() >= pInfo.nr))
|
||||
if ((!index.isValid()) || (index.row() >= pInfo.nr) || pInfo.entry == 0)
|
||||
return QVariant();
|
||||
|
||||
plot_data item = pInfo.entry[index.row()];
|
||||
@ -167,6 +167,8 @@ void DivePlotDataModel::clear()
|
||||
if (rowCount() != 0) {
|
||||
beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
|
||||
pInfo.nr = 0;
|
||||
free(pInfo.entry);
|
||||
pInfo.entry = 0;
|
||||
diveId = -1;
|
||||
dcNr = -1;
|
||||
endRemoveRows();
|
||||
@ -179,7 +181,10 @@ void DivePlotDataModel::setDive(dive *d, const plot_info &info)
|
||||
Q_ASSERT(d != NULL);
|
||||
diveId = d->id;
|
||||
dcNr = dc_number;
|
||||
free(pInfo.entry);
|
||||
pInfo = info;
|
||||
pInfo.entry = (struct plot_data *)malloc(sizeof(struct plot_data) * pInfo.nr);
|
||||
memcpy(pInfo.entry, info.entry, sizeof(plot_data) * pInfo.nr);
|
||||
beginInsertRows(QModelIndex(), 0, pInfo.nr - 1);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@ -202,4 +202,18 @@ void YearlyStatisticsModel::update_yearly_stats()
|
||||
rootItem->children.append(item);
|
||||
item->parent = rootItem;
|
||||
}
|
||||
|
||||
/* Show the statistic sorted by dive type */
|
||||
if (stats_by_type != NULL && stats_by_type[0].selection_size) {
|
||||
YearStatisticsItem *item = new YearStatisticsItem(stats_by_type[0]);
|
||||
for (i = 1; i <= NUM_DC_TYPE; ++i) {
|
||||
if (stats_by_type[i].selection_size == 0)
|
||||
continue;
|
||||
YearStatisticsItem *iChild = new YearStatisticsItem(stats_by_type[i]);
|
||||
item->children.append(iChild);
|
||||
iChild->parent = item;
|
||||
}
|
||||
rootItem->children.append(item);
|
||||
item->parent = rootItem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,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-2015"
|
||||
"Linus Torvalds, Dirk Hohndel, Tomaz Canabrava, and others, 2011-2016"
|
||||
"</span>").arg(versionString));
|
||||
|
||||
QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this);
|
||||
|
||||
@ -470,6 +470,11 @@ void ConfigureDiveComputerDialog::populateDeviceDetailsOSTC3()
|
||||
deviceDetails->dynamicAscendRate = ui.dynamicAscendRate->isChecked();
|
||||
deviceDetails->graphicalSpeedIndicator = ui.graphicalSpeedIndicator->isChecked();
|
||||
deviceDetails->alwaysShowppO2 = ui.alwaysShowppO2->isChecked();
|
||||
deviceDetails->tempSensorOffset = ui.tempSensorOffsetDoubleSpinBox->value() * 10;
|
||||
deviceDetails->safetyStopLength = ui.safetyStopLengthSpinBox->value();
|
||||
deviceDetails->safetyStopStartDepth = ui.safetyStopStartDepthDoubleSpinBox->value() * 10;
|
||||
deviceDetails->safetyStopEndDepth = ui.safetyStopEndDepthDoubleSpinBox->value() * 10;
|
||||
deviceDetails->safetyStopResetDepth = ui.safetyStopResetDepthDoubleSpinBox->value() * 10;
|
||||
|
||||
//set gas values
|
||||
gas gas1;
|
||||
@ -599,6 +604,10 @@ void ConfigureDiveComputerDialog::populateDeviceDetailsOSTC()
|
||||
deviceDetails->bottomGasConsumption = ui.bottomGasConsumption_3->value();
|
||||
deviceDetails->decoGasConsumption = ui.decoGasConsumption_3->value();
|
||||
deviceDetails->graphicalSpeedIndicator = ui.graphicalSpeedIndicator_3->isChecked();
|
||||
deviceDetails->safetyStopLength = ui.safetyStopLengthSpinBox_3->value();
|
||||
deviceDetails->safetyStopStartDepth = ui.safetyStopStartDepthDoubleSpinBox_3->value() * 10;
|
||||
deviceDetails->safetyStopEndDepth = ui.safetyStopEndDepthDoubleSpinBox_3->value() * 10;
|
||||
deviceDetails->safetyStopResetDepth = ui.safetyStopResetDepthDoubleSpinBox_3->value() * 10;
|
||||
|
||||
//set gas values
|
||||
gas gas1;
|
||||
@ -845,6 +854,11 @@ void ConfigureDiveComputerDialog::reloadValuesOSTC3()
|
||||
ui.dynamicAscendRate->setChecked(deviceDetails->dynamicAscendRate);
|
||||
ui.graphicalSpeedIndicator->setChecked(deviceDetails->graphicalSpeedIndicator);
|
||||
ui.alwaysShowppO2->setChecked(deviceDetails->alwaysShowppO2);
|
||||
ui.tempSensorOffsetDoubleSpinBox->setValue((double)deviceDetails->tempSensorOffset / 10.0);
|
||||
ui.safetyStopLengthSpinBox->setValue(deviceDetails->safetyStopLength);
|
||||
ui.safetyStopStartDepthDoubleSpinBox->setValue(deviceDetails->safetyStopStartDepth / 10.0);
|
||||
ui.safetyStopEndDepthDoubleSpinBox->setValue(deviceDetails->safetyStopEndDepth / 10.0);
|
||||
ui.safetyStopResetDepthDoubleSpinBox->setValue(deviceDetails->safetyStopResetDepth / 10.0);
|
||||
|
||||
//load gas 1 values
|
||||
ui.ostc3GasTable->setItem(0, 1, new QTableWidgetItem(QString::number(deviceDetails->gas1.oxygen)));
|
||||
@ -968,6 +982,10 @@ setNumberOfDives
|
||||
ui.bottomGasConsumption_3->setValue(deviceDetails->bottomGasConsumption);
|
||||
ui.decoGasConsumption_3->setValue(deviceDetails->decoGasConsumption);
|
||||
ui.graphicalSpeedIndicator_3->setChecked(deviceDetails->graphicalSpeedIndicator);
|
||||
ui.safetyStopLengthSpinBox_3->setValue(deviceDetails->safetyStopLength);
|
||||
ui.safetyStopStartDepthDoubleSpinBox_3->setValue(deviceDetails->safetyStopStartDepth / 10.0);
|
||||
ui.safetyStopEndDepthDoubleSpinBox_3->setValue(deviceDetails->safetyStopEndDepth / 10.0);
|
||||
ui.safetyStopResetDepthDoubleSpinBox_3->setValue(deviceDetails->safetyStopResetDepth / 10.0);
|
||||
|
||||
//load gas 1 values
|
||||
ui.ostcGasTable->setItem(0, 1, new QTableWidgetItem(QString::number(deviceDetails->gas1.oxygen)));
|
||||
@ -1252,6 +1270,6 @@ void ConfigureDiveComputerDialog::dc_close()
|
||||
ui.DiveComputerList->setEnabled(true);
|
||||
ui.logToFile->setEnabled(true);
|
||||
ui.updateFirmwareButton->setEnabled(false);
|
||||
ui.progressBar->setFormat("Disonnected from device");
|
||||
ui.progressBar->setFormat("Disconnected from device");
|
||||
ui.progressBar->setValue(0);
|
||||
}
|
||||
|
||||
@ -253,6 +253,35 @@
|
||||
<string>Basic settings</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="5" column="4">
|
||||
<widget class="QComboBox" name="brightnessComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Eco</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QSpinBox" name="salinitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QComboBox" name="languageComboBox">
|
||||
<item>
|
||||
@ -324,23 +353,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLineEdit" name="firmwareVersionLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>languageComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QComboBox" name="dateFormatComboBox">
|
||||
<item>
|
||||
@ -360,23 +372,21 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QComboBox" name="brightnessComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Eco</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLineEdit" name="firmwareVersionLineEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>languageComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
@ -419,13 +429,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QSpinBox" name="salinitySpinBox">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
<item row="14" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>5</number>
|
||||
<property name="text">
|
||||
<string>Reset device to default settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -479,7 +489,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<item row="12" column="2">
|
||||
<spacer name="verticalSpacer1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -492,36 +502,6 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset device to default settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Compass gain</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>compassGainComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Custom text</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>customTextLlineEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="customTextLlineEdit">
|
||||
<property name="sizePolicy">
|
||||
@ -535,6 +515,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Compass gain</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>compassGainComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_62">
|
||||
<property name="text">
|
||||
@ -542,6 +532,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Custom text</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>customTextLlineEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLineEdit" name="modelLineEdit">
|
||||
<property name="readOnly">
|
||||
@ -549,16 +549,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Dive mode</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>diveModeComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="diveModeComboBox">
|
||||
<item>
|
||||
@ -583,13 +573,13 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Sampling rate</string>
|
||||
<string>Dive mode</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>samplingRateComboBox</cstring>
|
||||
<cstring>diveModeComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -607,13 +597,13 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Dive mode color</string>
|
||||
<string>Sampling rate</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>diveModeColour</cstring>
|
||||
<cstring>samplingRateComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -648,6 +638,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Dive mode color</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>diveModeColour</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="safetyStopCheckBox">
|
||||
<property name="text">
|
||||
@ -655,6 +655,122 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_65">
|
||||
<property name="text">
|
||||
<string>End Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="safetyStopLengthSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> s</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>240</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_63">
|
||||
<property name="text">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_64">
|
||||
<property name="text">
|
||||
<string>Start Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_66">
|
||||
<property name="text">
|
||||
<string>Reset Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopStartDepthDoubleSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>2.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>6.100000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopEndDepthDoubleSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.900000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>3.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.900000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopResetDepthDoubleSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>8.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>15.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>10.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advancedSettings">
|
||||
@ -1043,6 +1159,32 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="3">
|
||||
<widget class="QLabel" name="label_71">
|
||||
<property name="text">
|
||||
<string>Temperature sensor offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="4">
|
||||
<widget class="QDoubleSpinBox" name="tempSensorOffsetDoubleSpinBox">
|
||||
<property name="suffix">
|
||||
<string>°C</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-2.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="gasSettings">
|
||||
@ -1795,17 +1937,7 @@
|
||||
<string>Basic settings</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="text">
|
||||
<string>Salinity</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>salinitySpinBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_38">
|
||||
<property name="text">
|
||||
<string>Serial No.</string>
|
||||
@ -1815,7 +1947,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_68">
|
||||
<property name="text">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLineEdit" name="firmwareVersionLineEdit_3">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="serialNoLineEdit_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@ -1828,7 +1974,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="0" column="5">
|
||||
<widget class="QLabel" name="label_39">
|
||||
<property name="text">
|
||||
<string>Firmware version</string>
|
||||
@ -1838,14 +1984,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLineEdit" name="firmwareVersionLineEdit_3">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="text">
|
||||
<string>Custom text</string>
|
||||
@ -1855,7 +1994,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="customTextLlineEdit_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@ -1868,83 +2007,38 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QDoubleSpinBox" name="salinityDoubleSpinBox_3">
|
||||
<property name="suffix">
|
||||
<string>kg/ℓ</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.040000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>177</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="dateTimeSyncCheckBox_3">
|
||||
<property name="text">
|
||||
<string>Sync dive computer time with PC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="safetyStopCheckBox_3">
|
||||
<property name="text">
|
||||
<string>Show safety stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QComboBox" name="dateFormatComboBox_3">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MM/DD/YY</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DD/MM/YY</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>YY/MM/DD</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="label_41">
|
||||
<property name="text">
|
||||
<string>Number of dives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<item row="4" column="0" rowspan="2" colspan="4">
|
||||
<widget class="QCheckBox" name="safetyStopCheckBox_3">
|
||||
<property name="text">
|
||||
<string>Show safety stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="QSpinBox" name="numberOfDivesSpinBox_3">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_47">
|
||||
<property name="text">
|
||||
<string>Sampling rate</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>samplingRateComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QSpinBox" name="samplingRateSpinBox_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@ -1963,17 +2057,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_47">
|
||||
<property name="text">
|
||||
<string>Sampling rate</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>samplingRateComboBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="2" column="5">
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="text">
|
||||
<string>Date format</string>
|
||||
@ -1983,6 +2067,180 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
<widget class="QComboBox" name="dateFormatComboBox_3">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MM/DD/YY</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DD/MM/YY</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>YY/MM/DD</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="dateTimeSyncCheckBox_3">
|
||||
<property name="text">
|
||||
<string>Sync dive computer time with PC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QLabel" name="label_45">
|
||||
<property name="text">
|
||||
<string>Salinity</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>salinitySpinBox</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="6">
|
||||
<widget class="QDoubleSpinBox" name="salinityDoubleSpinBox_3">
|
||||
<property name="suffix">
|
||||
<string>kg/ℓ</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.040000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>177</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_67">
|
||||
<property name="text">
|
||||
<string>Start Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_69">
|
||||
<property name="text">
|
||||
<string>End Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_70">
|
||||
<property name="text">
|
||||
<string>Reset Depth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="safetyStopLengthSpinBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> s</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopStartDepthDoubleSpinBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>3.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>6.500000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopEndDepthDoubleSpinBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>2.500000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.900000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QDoubleSpinBox" name="safetyStopResetDepthDoubleSpinBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> m</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>7.500000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>20.100000000000001</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>10.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advancedSettings_3">
|
||||
@ -2754,5 +3012,133 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopLengthSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopStartDepthDoubleSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopEndDepthDoubleSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopResetDepthDoubleSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox_3</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopLengthSpinBox_3</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox_3</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopStartDepthDoubleSpinBox_3</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox_3</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopEndDepthDoubleSpinBox_3</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>safetyStopCheckBox_3</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>safetyStopResetDepthDoubleSpinBox_3</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <QShortcut>
|
||||
#include <QDrag>
|
||||
#include <QMimeData>
|
||||
#include <QRegExp>
|
||||
|
||||
static QString subsurface_mimedata = "subsurface/csvcolumns";
|
||||
static QString subsurface_index = "subsurface/csvindex";
|
||||
@ -15,6 +16,7 @@ const DiveLogImportDialog::CSVAppConfig DiveLogImportDialog::CSVApps[CSVAPPS] =
|
||||
{ "Manual import", },
|
||||
{ "APD Log Viewer - DC1", 0, 1, 15, 6, 3, 4, 5, 17, -1, -1, 18, -1, 2, "Tab" },
|
||||
{ "APD Log Viewer - DC2", 0, 1, 15, 6, 7, 8, 9, 17, -1, -1, 18, -1, 2, "Tab" },
|
||||
{ "DL7", 1, 2, -1, -1, -1, -1, -1, -1, -1, 8, -1, 10, -1, "|" },
|
||||
{ "XP5", 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Tab" },
|
||||
{ "SensusCSV", 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "," },
|
||||
{ "Seabear CSV", 0, 1, 5, -1, -1, -1, -1, -1, 2, 3, 4, 6, -1, ";" },
|
||||
@ -26,6 +28,7 @@ static enum {
|
||||
MANUAL,
|
||||
APD,
|
||||
APD2,
|
||||
DL7,
|
||||
XP5,
|
||||
SENSUS,
|
||||
SEABEAR,
|
||||
@ -331,15 +334,17 @@ DiveLogImportDialog::DiveLogImportDialog(QStringList fn, QWidget *parent) : QDia
|
||||
column = 0;
|
||||
delta = "0";
|
||||
hw = "";
|
||||
txtLog = false;
|
||||
|
||||
/* Add indexes of XSLTs requiring special handling to the list */
|
||||
specialCSV << SENSUS;
|
||||
specialCSV << SUBSURFACE;
|
||||
specialCSV << DL7;
|
||||
|
||||
for (int i = 0; !CSVApps[i].name.isNull(); ++i)
|
||||
ui->knownImports->addItem(CSVApps[i].name);
|
||||
|
||||
ui->CSVSeparator->addItems( QStringList() << tr("Tab") << "," << ";");
|
||||
ui->CSVSeparator->addItems( QStringList() << tr("Tab") << "," << ";" << "|");
|
||||
|
||||
loadFileContents(-1, INITIAL);
|
||||
|
||||
@ -378,6 +383,7 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
bool seabear = false;
|
||||
bool xp5 = false;
|
||||
bool apd = false;
|
||||
bool dl7 = false;
|
||||
|
||||
// reset everything
|
||||
ColumnNameProvider *provider = new ColumnNameProvider(this);
|
||||
@ -459,8 +465,38 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
blockSignals(true);
|
||||
ui->knownImports->setCurrentText("XP5");
|
||||
blockSignals(false);
|
||||
} else if (firstLine.contains("FSH")) {
|
||||
QString units = "Metric";
|
||||
dl7 = true;
|
||||
while ((firstLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) {
|
||||
/* DL7 actually defines individual units (e.g. depth, temp, pressure, etc.)
|
||||
* and there are quite a few other options as well, but let's use metric
|
||||
* unless depth unit is clearly Imperial. */
|
||||
|
||||
if (firstLine.contains("ThFt")) {
|
||||
units = "Imperial";
|
||||
}
|
||||
}
|
||||
firstLine = "|Sample time|Sample depth||||||Sample temperature||Sample pressure";
|
||||
blockSignals(true);
|
||||
ui->knownImports->setCurrentText("DL7");
|
||||
ui->CSVUnits->setCurrentText(units);
|
||||
blockSignals(false);
|
||||
} else if (firstLine.contains("Life Time Dive")) {
|
||||
txtLog = true;
|
||||
|
||||
while ((firstLine = f.readLine().trimmed()).length() >= 0 && !f.atEnd()) {
|
||||
if (firstLine.contains("Dive Profile")) {
|
||||
f.readLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
firstLine = f.readLine().trimmed();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Special handling for APD Log Viewer
|
||||
if ((triggeredBy == KNOWNTYPES && (value == APD || value == APD2)) || (triggeredBy == INITIAL && fileNames.first().endsWith(".apd", Qt::CaseInsensitive))) {
|
||||
apd=true;
|
||||
@ -479,11 +515,14 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
int tabs = firstLine.count('\t');
|
||||
int commas = firstLine.count(',');
|
||||
int semis = firstLine.count(';');
|
||||
if (tabs > commas && tabs > semis)
|
||||
int pipes = firstLine.count('|');
|
||||
if (tabs > commas && tabs > semis && tabs > pipes)
|
||||
separator = "\t";
|
||||
else if (commas > tabs && commas > semis)
|
||||
else if (commas > tabs && commas > semis && commas > pipes)
|
||||
separator = ",";
|
||||
else if (semis > tabs && semis > commas)
|
||||
else if (pipes > tabs && pipes > commas && pipes > semis)
|
||||
separator = "|";
|
||||
else if (semis > tabs && semis > commas && semis > pipes)
|
||||
separator = ";";
|
||||
if (ui->CSVSeparator->currentText() != separator) {
|
||||
blockSignals(true);
|
||||
@ -493,8 +532,14 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
}
|
||||
}
|
||||
if (triggeredBy == INITIAL || (triggeredBy == KNOWNTYPES && value == MANUAL) || triggeredBy == SEPARATOR) {
|
||||
int count = -1;
|
||||
QString line = f.readLine().trimmed();
|
||||
QStringList columns;
|
||||
if (line.length() > 0)
|
||||
columns = line.split(separator);
|
||||
// now try and guess the columns
|
||||
Q_FOREACH (QString columnText, currColumns) {
|
||||
count++;
|
||||
/*
|
||||
* We have to skip the conversion of 2 to ₂ for APD Log
|
||||
* viewer as that would mess up the sensor numbering. We
|
||||
@ -513,13 +558,28 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
provider->removeRow(idx);
|
||||
headers.append(foundHeading);
|
||||
matchedSome = true;
|
||||
if (foundHeading == QString::fromLatin1("Date") && columns.count() >= count) {
|
||||
QString date = columns.at(count);
|
||||
if (date.contains('-')) {
|
||||
ui->DateFormat->setCurrentText("yyyy-mm-dd");
|
||||
|
||||
} else if (date.contains('/')) {
|
||||
ui->DateFormat->setCurrentText("mm/dd/yyyy");
|
||||
}
|
||||
} else if (foundHeading == QString::fromLatin1("Time") && columns.count() >= count) {
|
||||
QString time = columns.at(count);
|
||||
if (time.contains(':')) {
|
||||
ui->DurationFormat->setCurrentText("Minutes:seconds");
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
headers.append("");
|
||||
}
|
||||
}
|
||||
if (matchedSome) {
|
||||
ui->dragInstructions->setText(tr("Some column headers were pre-populated; please drag and drop the headers so they match the column they are in."));
|
||||
if (triggeredBy != KNOWNTYPES && !seabear && !xp5 && !apd) {
|
||||
if (triggeredBy != KNOWNTYPES && !seabear && !xp5 && !apd && !dl7) {
|
||||
blockSignals(true);
|
||||
ui->knownImports->setCurrentIndex(0); // <- that's "Manual import"
|
||||
blockSignals(false);
|
||||
@ -633,6 +693,20 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
|
||||
* actual data.
|
||||
*/
|
||||
while (strlen(f.readLine()) > 3 && !f.atEnd());
|
||||
} else if (dl7) {
|
||||
while ((firstLine = f.readLine().trimmed()).length() > 0 && !f.atEnd()) {
|
||||
if (firstLine.contains("ZDP")) {
|
||||
firstLine = f.readLine().trimmed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (txtLog) {
|
||||
while ((firstLine = f.readLine().trimmed()).length() >= 0 && !f.atEnd()) {
|
||||
if (firstLine.contains("Dive Profile")) {
|
||||
firstLine = f.readLine().trimmed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (rows < 10 && !f.atEnd()) {
|
||||
@ -658,6 +732,14 @@ char *intdup(int index)
|
||||
|
||||
int DiveLogImportDialog::setup_csv_params(QStringList r, char **params, int pnr)
|
||||
{
|
||||
params[pnr++] = strdup("dateField");
|
||||
params[pnr++] = intdup(r.indexOf(tr("Date")));
|
||||
params[pnr++] = strdup("datefmt");
|
||||
params[pnr++] = intdup(ui->DateFormat->currentIndex());
|
||||
params[pnr++] = strdup("starttimeField");
|
||||
params[pnr++] = intdup(r.indexOf(tr("Time")));
|
||||
params[pnr++] = strdup("numberField");
|
||||
params[pnr++] = intdup(r.indexOf(tr("Dive #")));
|
||||
params[pnr++] = strdup("timeField");
|
||||
params[pnr++] = intdup(r.indexOf(tr("Sample time")));
|
||||
params[pnr++] = strdup("depthField");
|
||||
@ -699,6 +781,51 @@ int DiveLogImportDialog::setup_csv_params(QStringList r, char **params, int pnr)
|
||||
|
||||
return pnr;
|
||||
}
|
||||
int DiveLogImportDialog::parseTxtHeader(QString fileName, char **params, int pnr)
|
||||
{
|
||||
QFile f(fileNames.first());
|
||||
QString date;
|
||||
QString time;
|
||||
QString line;
|
||||
|
||||
f.open(QFile::ReadOnly);
|
||||
while ((line = f.readLine().trimmed()).length() >= 0 && !f.atEnd()) {
|
||||
if (line.contains("Dive Profile")) {
|
||||
f.readLine();
|
||||
break;
|
||||
} else if (line.contains("Dive Date: ")) {
|
||||
date = line.replace(QString::fromLatin1("Dive Date: "), QString::fromLatin1(""));
|
||||
|
||||
if (date.contains('-')) {
|
||||
QStringList fmtDate = date.split('-');
|
||||
date = fmtDate[0] + fmtDate[1] + fmtDate[2];
|
||||
} else if (date.contains('/')) {
|
||||
QStringList fmtDate = date.split('/');
|
||||
date = fmtDate[2] + fmtDate[0] + fmtDate[1];
|
||||
} else {
|
||||
QStringList fmtDate = date.split('.');
|
||||
date = fmtDate[2] + fmtDate[1] + fmtDate[0];
|
||||
}
|
||||
} else if (line.contains("Elapsed Dive Time: ")) {
|
||||
// Skipping dive duration for now
|
||||
} else if (line.contains("Dive Time: ")) {
|
||||
time = line.replace(QString::fromLatin1("Dive Time: "), QString::fromLatin1(""));
|
||||
|
||||
if (time.contains(':')) {
|
||||
QStringList fmtTime = time.split(':');
|
||||
time = fmtTime[0] + fmtTime[1];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
|
||||
params[pnr++] = strdup("date");
|
||||
params[pnr++] = strdup(date.toLatin1());
|
||||
params[pnr++] = strdup("time");
|
||||
params[pnr++] = strdup(time.toLatin1());
|
||||
return pnr;
|
||||
}
|
||||
|
||||
void DiveLogImportDialog::on_buttonBox_accepted()
|
||||
{
|
||||
@ -753,15 +880,24 @@ void DiveLogImportDialog::on_buttonBox_accepted()
|
||||
}
|
||||
// Seabear CSV stores NDL and TTS in Minutes, not seconds
|
||||
struct dive *dive = dive_table.dives[dive_table.nr - 1];
|
||||
for(int s_nr = 0 ; s_nr <= dive->dc.samples ; s_nr++) {
|
||||
for(int s_nr = 0 ; s_nr < dive->dc.samples ; s_nr++) {
|
||||
struct sample *sample = dive->dc.sample + s_nr;
|
||||
sample->ndl.seconds *= 60;
|
||||
sample->tts.seconds *= 60;
|
||||
}
|
||||
} else {
|
||||
char *params[37];
|
||||
char *params[49];
|
||||
int pnr = 0;
|
||||
|
||||
QRegExp apdRe("^.*[/\\][0-9a-zA-Z]*_([0-9]{6})_([0-9]{6})\\.apd");
|
||||
if (txtLog) {
|
||||
pnr = parseTxtHeader(fileNames[i], params, pnr);
|
||||
} else if (apdRe.exactMatch(fileNames[i])) {
|
||||
params[pnr++] = strdup("date");
|
||||
params[pnr++] = strdup("20" + apdRe.cap(1).toLatin1());
|
||||
params[pnr++] = strdup("time");
|
||||
params[pnr++] = strdup("1" + apdRe.cap(2).toLatin1());
|
||||
}
|
||||
pnr = setup_csv_params(r, params, pnr);
|
||||
parse_csv_file(fileNames[i].toUtf8().data(), params, pnr - 1,
|
||||
specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv");
|
||||
@ -826,9 +962,18 @@ void DiveLogImportDialog::on_buttonBox_accepted()
|
||||
|
||||
parse_manual_file(fileNames[i].toUtf8().data(), params, pnr - 1);
|
||||
} else {
|
||||
char *params[37];
|
||||
char *params[49];
|
||||
int pnr = 0;
|
||||
|
||||
QRegExp apdRe("^.*[/\\][0-9a-zA-Z]*_([0-9]{6})_([0-9]{6})\\.apd");
|
||||
if (txtLog) {
|
||||
pnr = parseTxtHeader(fileNames[i], params, pnr);
|
||||
} else if (apdRe.exactMatch(fileNames[i])) {
|
||||
params[pnr++] = strdup("date");
|
||||
params[pnr++] = strdup("20" + apdRe.cap(1).toLatin1());
|
||||
params[pnr++] = strdup("time");
|
||||
params[pnr++] = strdup("1" + apdRe.cap(2).toLatin1());
|
||||
}
|
||||
pnr = setup_csv_params(r, params, pnr);
|
||||
parse_csv_file(fileNames[i].toUtf8().data(), params, pnr - 1,
|
||||
specialCSV.contains(ui->knownImports->currentIndex()) ? CSVApps[ui->knownImports->currentIndex()].name.toUtf8().data() : "csv");
|
||||
|
||||
@ -87,6 +87,7 @@ slots:
|
||||
void loadFileContentsKnownTypesSelected(int value);
|
||||
void loadFileContents(int value, enum whatChanged triggeredBy);
|
||||
int setup_csv_params(QStringList r, char **params, int pnr);
|
||||
int parseTxtHeader(QString fileName, char **params, int pnr);
|
||||
|
||||
private:
|
||||
bool selector;
|
||||
@ -97,6 +98,7 @@ private:
|
||||
ColumnNameResult *resultModel;
|
||||
QString delta;
|
||||
QString hw;
|
||||
bool txtLog;
|
||||
|
||||
struct CSVAppConfig {
|
||||
QString name;
|
||||
@ -116,7 +118,7 @@ private:
|
||||
QString separator;
|
||||
};
|
||||
|
||||
#define CSVAPPS 8
|
||||
#define CSVAPPS 9
|
||||
static const CSVAppConfig CSVApps[CSVAPPS];
|
||||
};
|
||||
|
||||
|
||||
@ -23,16 +23,17 @@ void loadPicture(struct picture *picture)
|
||||
|
||||
SHashedImage::SHashedImage(struct picture *picture) : QImage()
|
||||
{
|
||||
QUrl url = QUrl::fromUserInput(QString(picture->filename));
|
||||
QUrl url = QUrl::fromUserInput(localFilePath(QString(picture->filename)));
|
||||
|
||||
if(url.isLocalFile())
|
||||
load(url.toLocalFile());
|
||||
if (isNull()) {
|
||||
// Hash lookup.
|
||||
load(fileFromHash(picture->hash));
|
||||
if (!isNull()) {
|
||||
QtConcurrent::run(updateHash, picture);
|
||||
QtConcurrent::run(updateHash, clone_picture(picture));
|
||||
} else {
|
||||
QtConcurrent::run(loadPicture, picture);
|
||||
QtConcurrent::run(loadPicture, clone_picture(picture));
|
||||
}
|
||||
} else {
|
||||
QByteArray hash = hashFile(url.toLocalFile());
|
||||
@ -46,6 +47,11 @@ ImageDownloader::ImageDownloader(struct picture *pic)
|
||||
picture = pic;
|
||||
}
|
||||
|
||||
ImageDownloader::~ImageDownloader()
|
||||
{
|
||||
picture_free(picture);
|
||||
}
|
||||
|
||||
void ImageDownloader::load(){
|
||||
QUrl url = QUrl::fromUserInput(QString(picture->filename));
|
||||
if (url.isValid()) {
|
||||
@ -64,6 +70,7 @@ void ImageDownloader::load(){
|
||||
void ImageDownloader::saveImage(QNetworkReply *reply)
|
||||
{
|
||||
QByteArray imageData = reply->readAll();
|
||||
qDebug() << "downloaded ";
|
||||
QImage image = QImage();
|
||||
image.loadFromData(imageData);
|
||||
if (image.isNull())
|
||||
|
||||
@ -11,6 +11,7 @@ class ImageDownloader : public QObject {
|
||||
Q_OBJECT;
|
||||
public:
|
||||
ImageDownloader(struct picture *picture);
|
||||
~ImageDownloader();
|
||||
void load();
|
||||
private:
|
||||
struct picture *picture;
|
||||
|
||||
@ -306,7 +306,6 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f)
|
||||
ui.display_runtime->setChecked(prefs.display_runtime);
|
||||
ui.display_transitions->setChecked(prefs.display_transitions);
|
||||
ui.safetystop->setChecked(prefs.safetystop);
|
||||
ui.reserve_gas->setValue(prefs.reserve_gas / 1000);
|
||||
ui.bottompo2->setValue(prefs.bottompo2 / 1000.0);
|
||||
ui.decopo2->setValue(prefs.decopo2 / 1000.0);
|
||||
ui.backgasBreaks->setChecked(prefs.doo2breaks);
|
||||
@ -448,6 +447,18 @@ void PlannerSettingsWidget::settingsChanged()
|
||||
ui.bottomSAC->setValue((double) prefs.bottomsac / 1000.0);
|
||||
ui.decoStopSAC->setValue((double) prefs.decosac / 1000.0);
|
||||
}
|
||||
if(get_units()->pressure == units::BAR) {
|
||||
ui.reserve_gas->setSuffix(tr("bar"));
|
||||
ui.reserve_gas->setSingleStep(1);
|
||||
ui.reserve_gas->setValue(prefs.reserve_gas / 1000);
|
||||
ui.reserve_gas->setMaximum(300);
|
||||
} else {
|
||||
ui.reserve_gas->setSuffix(tr("psi"));
|
||||
ui.reserve_gas->setSingleStep(10);
|
||||
ui.reserve_gas->setMaximum(5000);
|
||||
ui.reserve_gas->setValue(mbar_to_PSI(prefs.reserve_gas));
|
||||
}
|
||||
|
||||
ui.bottomSAC->blockSignals(false);
|
||||
ui.decoStopSAC->blockSignals(false);
|
||||
updateUnitsUI();
|
||||
|
||||
@ -290,7 +290,7 @@ bool DiveLocationFilterProxyModel::filterAcceptsRow(int source_row, const QModel
|
||||
return true;
|
||||
|
||||
QString sourceString = sourceModel()->index(source_row, DiveLocationModel::NAME).data(Qt::DisplayRole).toString();
|
||||
return sourceString.toLower().startsWith(location_line_edit->text().toLower());
|
||||
return sourceString.toLower().contains(location_line_edit->text().toLower());
|
||||
}
|
||||
|
||||
bool DiveLocationFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
@ -570,7 +570,7 @@ void DiveLocationLineEdit::fixPopupPosition()
|
||||
|
||||
view->setGeometry(pos.x(), pos.y(), w, h);
|
||||
if (!view->currentIndex().isValid() && view->model()->rowCount()) {
|
||||
view->setCurrentIndex(view->model()->index(0, 0));
|
||||
view->setCurrentIndex(view->model()->index(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -523,6 +523,9 @@ void MainTab::updateDiveInfo(bool clear)
|
||||
ui.TypeLabel->setVisible(false);
|
||||
ui.waterTempLabel->setVisible(false);
|
||||
ui.watertemp->setVisible(false);
|
||||
ui.dateEdit->setReadOnly(true);
|
||||
ui.label->setVisible(false);
|
||||
ui.timeEdit->setVisible(false);
|
||||
ui.diveTripLocation->show();
|
||||
ui.location->hide();
|
||||
ui.editDiveSiteButton->hide();
|
||||
@ -561,6 +564,9 @@ void MainTab::updateDiveInfo(bool clear)
|
||||
ui.DiveType->setVisible(true);
|
||||
ui.waterTempLabel->setVisible(true);
|
||||
ui.watertemp->setVisible(true);
|
||||
ui.dateEdit->setReadOnly(false);
|
||||
ui.label->setVisible(true);
|
||||
ui.timeEdit->setVisible(true);
|
||||
/* and fill them from the dive */
|
||||
ui.rating->setCurrentStars(displayed_dive.rating);
|
||||
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
||||
@ -674,6 +680,9 @@ void MainTab::updateDiveInfo(bool clear)
|
||||
if (amount_selected > 1) {
|
||||
ui.timeLimits->setMaximum(get_time_string_s(stats_selection.longest_time.seconds, 0, (displayed_dive.dc.divemode == FREEDIVE)));
|
||||
ui.timeLimits->setMinimum(get_time_string_s(stats_selection.shortest_time.seconds, 0, (displayed_dive.dc.divemode == FREEDIVE)));
|
||||
} else {
|
||||
ui.timeLimits->setMaximum("");
|
||||
ui.timeLimits->setMinimum("");
|
||||
}
|
||||
ui.timeLimits->overrideMaxToolTipText(tr("Longest dive"));
|
||||
ui.timeLimits->overrideMinToolTipText(tr("Shortest dive"));
|
||||
|
||||
@ -62,6 +62,7 @@ extern "C" int updateProgress(int percent)
|
||||
{
|
||||
if (progressDialog)
|
||||
progressDialog->setValue(percent);
|
||||
qApp->processEvents();
|
||||
return progressDialogCanceled;
|
||||
}
|
||||
|
||||
@ -686,6 +687,10 @@ void MainWindow::on_actionEditDeviceNames_triggered()
|
||||
|
||||
bool MainWindow::plannerStateClean()
|
||||
{
|
||||
if (progressDialog)
|
||||
// we are accessing the cloud, so let's not switch into Add or Plan mode
|
||||
return false;
|
||||
|
||||
if (DivePlannerPointsModel::instance()->currentMode() != DivePlannerPointsModel::NOTHING ||
|
||||
information()->isEditing()) {
|
||||
QMessageBox::warning(this, tr("Warning"), tr("Please save or cancel the current dive edit before trying to add a dive."));
|
||||
@ -1621,6 +1626,8 @@ void MainWindow::importFiles(const QStringList fileNames)
|
||||
|
||||
void MainWindow::importTxtFiles(const QStringList fileNames)
|
||||
{
|
||||
QStringList csvFiles;
|
||||
|
||||
if (fileNames.isEmpty())
|
||||
return;
|
||||
|
||||
@ -1630,7 +1637,18 @@ void MainWindow::importTxtFiles(const QStringList fileNames)
|
||||
fileNamePtr = QFile::encodeName(fileNames.at(i));
|
||||
csv = fileNamePtr.data();
|
||||
csv.replace(strlen(csv.data()) - 3, 3, "csv");
|
||||
parse_txt_file(fileNamePtr.data(), csv);
|
||||
|
||||
QFileInfo check_file(csv);
|
||||
if (check_file.exists() && check_file.isFile()) {
|
||||
if (parse_txt_file(fileNamePtr.data(), csv) == 0)
|
||||
csvFiles += fileNames.at(i);
|
||||
} else {
|
||||
csvFiles += fileNamePtr;
|
||||
}
|
||||
}
|
||||
if (csvFiles.size()) {
|
||||
DiveLogImportDialog *diveLogImport = new DiveLogImportDialog(csvFiles, this);
|
||||
diveLogImport->show();
|
||||
}
|
||||
process_dives(true, false);
|
||||
refreshDisplay();
|
||||
@ -1690,8 +1708,8 @@ void MainWindow::loadFiles(const QStringList fileNames)
|
||||
void MainWindow::on_actionImportDiveLog_triggered()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open dive log file"), lastUsedDir(),
|
||||
tr("Dive log files (*.ssrf *.can *.csv *.db *.sql *.dld *.jlb *.lvd *.sde *.udcf *.uddf *.xml *.txt *.dlf *.apd"
|
||||
"*.SSRF *.CAN *.CSV *.DB *.SQL *.DLD *.JLB *.LVD *.SDE *.UDCF *.UDDF *.xml *.TXT *.DLF *.APD);;"
|
||||
tr("Dive log files (*.ssrf *.can *.csv *.db *.sql *.dld *.jlb *.lvd *.sde *.udcf *.uddf *.xml *.txt *.dlf *.apd *.zxu *.zxl"
|
||||
"*.SSRF *.CAN *.CSV *.DB *.SQL *.DLD *.JLB *.LVD *.SDE *.UDCF *.UDDF *.xml *.TXT *.DLF *.APD *.ZXU *.ZXL);;"
|
||||
"Cochran files (*.can *.CAN);;"
|
||||
"CSV files (*.csv *.CSV);;"
|
||||
"DiveLog.de files (*.dld *.DLD);;"
|
||||
@ -1705,15 +1723,18 @@ void MainWindow::on_actionImportDiveLog_triggered()
|
||||
"APD log viewer (*.apd *.APD);;"
|
||||
"Datatrak/WLog Files (*.log *.LOG);;"
|
||||
"OSTCtools Files (*.dive *.DIVE);;"
|
||||
"DAN DL7 (*.zxu *.zxl *.ZXU *.ZXL);;"
|
||||
"All files (*)"));
|
||||
|
||||
if (fileNames.isEmpty())
|
||||
return;
|
||||
updateLastUsedDir(QFileInfo(fileNames[0]).dir().path());
|
||||
|
||||
QStringList logFiles = fileNames.filter(QRegExp("^.*\\.(?!(csv|txt|apd))", Qt::CaseInsensitive));
|
||||
QStringList logFiles = fileNames.filter(QRegExp("^(?!.*\\.(csv|txt|apd|zxu|zxl))", Qt::CaseInsensitive));
|
||||
QStringList csvFiles = fileNames.filter(".csv", Qt::CaseInsensitive);
|
||||
csvFiles += fileNames.filter(".apd", Qt::CaseInsensitive);
|
||||
csvFiles += fileNames.filter(".zxu", Qt::CaseInsensitive);
|
||||
csvFiles += fileNames.filter(".zxl", Qt::CaseInsensitive);
|
||||
QStringList txtFiles = fileNames.filter(".txt", Qt::CaseInsensitive);
|
||||
|
||||
if (logFiles.size()) {
|
||||
|
||||
@ -19,6 +19,10 @@ DiveEventItem::DiveEventItem(QObject *parent) : DivePixmapItem(parent),
|
||||
setFlag(ItemIgnoresTransformations);
|
||||
}
|
||||
|
||||
DiveEventItem::~DiveEventItem()
|
||||
{
|
||||
free(internalEvent);
|
||||
}
|
||||
|
||||
void DiveEventItem::setHorizontalAxis(DiveCartesianAxis *axis)
|
||||
{
|
||||
@ -48,7 +52,9 @@ void DiveEventItem::setEvent(struct event *ev)
|
||||
{
|
||||
if (!ev)
|
||||
return;
|
||||
internalEvent = ev;
|
||||
|
||||
free(internalEvent);
|
||||
internalEvent = clone_event(ev);
|
||||
setupPixmap();
|
||||
setupToolTipString();
|
||||
recalculatePos(true);
|
||||
|
||||
@ -11,6 +11,7 @@ class DiveEventItem : public DivePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DiveEventItem(QObject *parent = 0);
|
||||
virtual ~DiveEventItem();
|
||||
void setEvent(struct event *ev);
|
||||
struct event *getEvent();
|
||||
void eventVisibilityChanged(const QString &eventName, bool visible);
|
||||
|
||||
@ -87,7 +87,7 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent),
|
||||
gasPressureItem(new DiveGasPressureItem()),
|
||||
diveComputerText(new DiveTextItem()),
|
||||
diveCeiling(new DiveCalculatedCeiling()),
|
||||
gradientFactor(new DiveTextItem()),
|
||||
decoModelParameters(new DiveTextItem()),
|
||||
reportedCeiling(new DiveReportedCeiling()),
|
||||
pn2GasItem(new PartialPressureGasItem()),
|
||||
pheGasItem(new PartialPressureGasItem()),
|
||||
@ -204,7 +204,7 @@ void ProfileWidget2::addItemsToScene()
|
||||
diveComputerText->setData(SUBSURFACE_OBJ_DATA, SUBSURFACE_OBJ_DC_TEXT);
|
||||
scene()->addItem(diveComputerText);
|
||||
scene()->addItem(diveCeiling);
|
||||
scene()->addItem(gradientFactor);
|
||||
scene()->addItem(decoModelParameters);
|
||||
scene()->addItem(reportedCeiling);
|
||||
scene()->addItem(pn2GasItem);
|
||||
scene()->addItem(pheGasItem);
|
||||
@ -288,11 +288,11 @@ void ProfileWidget2::setupItemOnScene()
|
||||
rulerItem->setAxis(timeAxis, profileYAxis);
|
||||
tankItem->setHorizontalAxis(timeAxis);
|
||||
|
||||
// show the gradient factor at the top in the center
|
||||
gradientFactor->setY(0);
|
||||
gradientFactor->setX(50);
|
||||
gradientFactor->setBrush(getColor(PRESSURE_TEXT));
|
||||
gradientFactor->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
// show the deco model parameters at the top in the center
|
||||
decoModelParameters->setY(0);
|
||||
decoModelParameters->setX(50);
|
||||
decoModelParameters->setBrush(getColor(PRESSURE_TEXT));
|
||||
decoModelParameters->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
|
||||
setupItem(reportedCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1);
|
||||
setupItem(diveCeiling, timeAxis, profileYAxis, dataModel, DivePlotDataModel::CEILING, DivePlotDataModel::TIME, 1);
|
||||
@ -509,7 +509,10 @@ void ProfileWidget2::plotDive(struct dive *d, bool force)
|
||||
|
||||
// this copies the dive and makes copies of all the relevant additional data
|
||||
copy_dive(d, &displayed_dive);
|
||||
gradientFactor->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh));
|
||||
if (prefs.deco_mode == VPMB)
|
||||
decoModelParameters->setText(QString("VPM-B +%1").arg(prefs.conservatism_level));
|
||||
else
|
||||
decoModelParameters->setText(QString("GF %1/%2").arg(prefs.gflow).arg(prefs.gfhigh));
|
||||
} else {
|
||||
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
|
||||
plannerModel->createTemporaryPlan();
|
||||
@ -518,7 +521,10 @@ void ProfileWidget2::plotDive(struct dive *d, bool force)
|
||||
plannerModel->deleteTemporaryPlan();
|
||||
return;
|
||||
}
|
||||
gradientFactor->setText(QString("GF %1/%2").arg(diveplan.gflow).arg(diveplan.gfhigh));
|
||||
if (prefs.deco_mode == VPMB)
|
||||
decoModelParameters->setText(QString("VPM-B +%1").arg(prefs.conservatism_level));
|
||||
else
|
||||
decoModelParameters->setText(QString("GF %1/%2").arg(diveplan.gflow).arg(diveplan.gfhigh));
|
||||
}
|
||||
|
||||
// special handling for the first time we display things
|
||||
@ -926,7 +932,7 @@ void ProfileWidget2::setEmptyState()
|
||||
toolTipItem->setVisible(false);
|
||||
diveComputerText->setVisible(false);
|
||||
diveCeiling->setVisible(false);
|
||||
gradientFactor->setVisible(false);
|
||||
decoModelParameters->setVisible(false);
|
||||
reportedCeiling->setVisible(false);
|
||||
rulerItem->setVisible(false);
|
||||
tankItem->setVisible(false);
|
||||
@ -941,6 +947,8 @@ void ProfileWidget2::setEmptyState()
|
||||
gflineItem->setVisible(false);
|
||||
mouseFollowerHorizontal->setVisible(false);
|
||||
mouseFollowerVertical->setVisible(false);
|
||||
heartBeatAxis->setVisible(false);
|
||||
heartBeatItem->setVisible(false);
|
||||
|
||||
#define HIDE_ALL(TYPE, CONTAINER) \
|
||||
Q_FOREACH (TYPE *item, CONTAINER) item->setVisible(false);
|
||||
@ -1053,7 +1061,7 @@ void ProfileWidget2::setProfileState()
|
||||
diveComputerText->setPos(itemPos.dcLabel.on);
|
||||
|
||||
diveCeiling->setVisible(prefs.calcceiling);
|
||||
gradientFactor->setVisible(prefs.calcceiling);
|
||||
decoModelParameters->setVisible(prefs.calcceiling);
|
||||
reportedCeiling->setVisible(prefs.dcceiling);
|
||||
|
||||
if (prefs.calcalltissues) {
|
||||
@ -1131,7 +1139,7 @@ void ProfileWidget2::setAddState()
|
||||
/* show the same stuff that the profile shows. */
|
||||
currentState = ADD; /* enable the add state. */
|
||||
diveCeiling->setVisible(true);
|
||||
gradientFactor->setVisible(true);
|
||||
decoModelParameters->setVisible(true);
|
||||
setBackgroundBrush(QColor("#A7DCFF"));
|
||||
}
|
||||
|
||||
@ -1165,7 +1173,7 @@ void ProfileWidget2::setPlanState()
|
||||
/* show the same stuff that the profile shows. */
|
||||
currentState = PLAN; /* enable the add state. */
|
||||
diveCeiling->setVisible(true);
|
||||
gradientFactor->setVisible(true);
|
||||
decoModelParameters->setVisible(true);
|
||||
setBackgroundBrush(QColor("#D7E3EF"));
|
||||
}
|
||||
|
||||
|
||||
@ -171,7 +171,7 @@ private:
|
||||
QList<DiveEventItem *> eventItems;
|
||||
DiveTextItem *diveComputerText;
|
||||
DiveCalculatedCeiling *diveCeiling;
|
||||
DiveTextItem *gradientFactor;
|
||||
DiveTextItem *decoModelParameters;
|
||||
QList<DiveCalculatedTissue *> allTissues;
|
||||
DiveReportedCeiling *reportedCeiling;
|
||||
PartialPressureGasItem *pn2GasItem;
|
||||
|
||||
@ -818,7 +818,7 @@ void DivelogsDeWebServices::startDownload()
|
||||
|
||||
QUrlQuery body;
|
||||
body.addQueryItem("user", ui.userID->text());
|
||||
body.addQueryItem("pass", ui.password->text());
|
||||
body.addQueryItem("pass", ui.password->text().replace("+", "%2b"));
|
||||
|
||||
reply = manager()->post(request, body.query(QUrl::FullyEncoded).toLatin1());
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(listDownloadFinished()));
|
||||
@ -855,7 +855,7 @@ void DivelogsDeWebServices::listDownloadFinished()
|
||||
|
||||
QUrlQuery body;
|
||||
body.addQueryItem("user", ui.userID->text());
|
||||
body.addQueryItem("pass", ui.password->text());
|
||||
body.addQueryItem("pass", ui.password->text().replace("+", "%2b"));
|
||||
body.addQueryItem("ids", diveList.idList);
|
||||
|
||||
reply = manager()->post(request, body.query(QUrl::FullyEncoded).toLatin1());
|
||||
|
||||
15
qthelper.cpp
15
qthelper.cpp
@ -1108,6 +1108,7 @@ extern "C" void reverseGeoLookup(degrees_t latitude, degrees_t longitude, uint32
|
||||
QHash<QString, QByteArray> hashOf;
|
||||
QMutex hashOfMutex;
|
||||
QHash<QByteArray, QString> localFilenameOf;
|
||||
QHash <QString, QImage > thumbnailCache;
|
||||
|
||||
extern "C" char * hashstring(char * filename)
|
||||
{
|
||||
@ -1131,6 +1132,7 @@ void read_hashes()
|
||||
QDataStream stream(&hashfile);
|
||||
stream >> localFilenameOf;
|
||||
stream >> hashOf;
|
||||
stream >> thumbnailCache;
|
||||
hashfile.close();
|
||||
}
|
||||
}
|
||||
@ -1142,6 +1144,7 @@ void write_hashes()
|
||||
QDataStream stream(&hashfile);
|
||||
stream << localFilenameOf;
|
||||
stream << hashOf;
|
||||
stream << thumbnailCache;
|
||||
hashfile.commit();
|
||||
} else {
|
||||
qDebug() << "cannot open" << hashfile.fileName();
|
||||
@ -1179,9 +1182,11 @@ void learnHash(struct picture *picture, QByteArray hash)
|
||||
|
||||
QString localFilePath(const QString originalFilename)
|
||||
{
|
||||
if (hashOf.contains(originalFilename) && localFilenameOf.contains(hashOf[originalFilename]))
|
||||
return localFilenameOf[hashOf[originalFilename]];
|
||||
else
|
||||
if (hashOf.contains(originalFilename))
|
||||
if (localFilenameOf.contains(hashOf[originalFilename]))
|
||||
if (localFilenameOf[hashOf[originalFilename]] != "")
|
||||
return localFilenameOf[hashOf[originalFilename]];
|
||||
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@ -1197,6 +1202,7 @@ void updateHash(struct picture *picture) {
|
||||
char *old = picture->hash;
|
||||
picture->hash = strdup(hash.toHex());
|
||||
free(old);
|
||||
picture_free(picture);
|
||||
}
|
||||
|
||||
void hashPicture(struct picture *picture)
|
||||
@ -1206,13 +1212,14 @@ void hashPicture(struct picture *picture)
|
||||
if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash))
|
||||
mark_divelist_changed((true));
|
||||
free(oldHash);
|
||||
picture_free(picture);
|
||||
}
|
||||
|
||||
extern "C" void cache_picture(struct picture *picture)
|
||||
{
|
||||
QString filename = picture->filename;
|
||||
if (!hashOf.contains(filename))
|
||||
QtConcurrent::run(hashPicture, picture);
|
||||
QtConcurrent::run(hashPicture, clone_picture(picture));
|
||||
}
|
||||
|
||||
void learnImages(const QDir dir, int max_recursions, bool recursed)
|
||||
|
||||
@ -629,6 +629,8 @@ static int save_one_picture(git_repository *repo, struct dir *dir, struct pictur
|
||||
offset -= h *3600;
|
||||
error = blob_insert(repo, dir, &buf, "%c%02u=%02u=%02u",
|
||||
sign, h, FRACTION(offset, 60));
|
||||
#if 0
|
||||
/* storing pictures into git was a mistake. This makes for HUGE git repositories */
|
||||
if (!error) {
|
||||
/* next store the actual picture; we prefix all picture names
|
||||
* with "PIC-" to make things easier on the parsing side */
|
||||
@ -638,6 +640,7 @@ static int save_one_picture(git_repository *repo, struct dir *dir, struct pictur
|
||||
error = blob_insert_fromdisk(repo, dir, localfn, mb_cstring(&namebuf));
|
||||
free((void *)localfn);
|
||||
}
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
23
save-html.c
23
save-html.c
@ -259,6 +259,29 @@ void put_HTML_time(struct membuffer *b, struct dive *dive, const char *pre, cons
|
||||
put_format(b, "%s%02u:%02u:%02u%s", pre, tm.tm_hour, tm.tm_min, tm.tm_sec, post);
|
||||
}
|
||||
|
||||
void put_HTML_depth(struct membuffer *b, struct dive *dive, const char *pre, const char *post)
|
||||
{
|
||||
const char *unit;
|
||||
double value;
|
||||
struct units *units_p = get_units();
|
||||
|
||||
if (!dive->maxdepth.mm) {
|
||||
put_format(b, "%s--%s", pre, post);
|
||||
return;
|
||||
}
|
||||
value = get_depth_units(dive->maxdepth.mm, NULL, &unit);
|
||||
|
||||
switch (units_p->length) {
|
||||
case METERS:
|
||||
default:
|
||||
put_format(b, "%s%.1f %s%s", pre, value, unit, post);
|
||||
break;
|
||||
case FEET:
|
||||
put_format(b, "%s%.0f %s%s", pre, value, unit, post);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void put_HTML_airtemp(struct membuffer *b, struct dive *dive, const char *pre, const char *post)
|
||||
{
|
||||
const char *unit;
|
||||
|
||||
@ -9,6 +9,7 @@ extern "C" {
|
||||
#include "membuffer.h"
|
||||
|
||||
void put_HTML_date(struct membuffer *b, struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_depth(struct membuffer *b, struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_airtemp(struct membuffer *b, struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_watertemp(struct membuffer *b, struct dive *dive, const char *pre, const char *post);
|
||||
void put_HTML_time(struct membuffer *b, struct dive *dive, const char *pre, const char *post);
|
||||
|
||||
@ -28,6 +28,18 @@ if [[ ! -d "subsurface" ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify that the Xcode Command Line Tools are installed
|
||||
if [ $PLATFORM = Darwin ] ; then
|
||||
if [ ! -d /usr/include ] ; then
|
||||
echo "Error: Xcode Command Line Tools are not installed"
|
||||
echo ""
|
||||
echo "Please run:"
|
||||
echo " xcode-select --install"
|
||||
echo "to install them (you'll have to agree to Apple's licensing terms etc), then run build.sh again"
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p install-root
|
||||
INSTALL_ROOT=$SRC/install-root
|
||||
|
||||
@ -118,7 +130,7 @@ fi
|
||||
if [ ! -f configure ] ; then
|
||||
autoreconf --install
|
||||
fi
|
||||
./configure --prefix=$INSTALL_ROOT
|
||||
./configure --prefix=$INSTALL_ROOT --disable-examples
|
||||
make -j4
|
||||
make install
|
||||
|
||||
@ -142,7 +154,14 @@ fi
|
||||
mkdir -p build
|
||||
cd build
|
||||
if [ $PLATFORM = Darwin ] ; then
|
||||
export CMAKE_PREFIX_PATH=~/Qt/5.5/clang_64/lib/cmake
|
||||
if [ -d "~/Qt/5.5" ] ; then
|
||||
export CMAKE_PREFIX_PATH=~/Qt/5.5/clang_64/lib/cmake
|
||||
elif [ -d "~/Qt/5.6" ] ; then
|
||||
export CMAKE_PREFIX_PATH=~/Qt/5.6/clang_64/lib/cmake
|
||||
elif [ -d /usr/local/opt/qt5/lib ] ; then
|
||||
# Homebrew location for qt5 package
|
||||
export CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
|
||||
fi
|
||||
fi
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DQTONLY=TRUE -DQT5BUILD=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=$INSTALL_ROOT \
|
||||
@ -200,7 +219,7 @@ fi
|
||||
cd $SRC/subsurface
|
||||
mkdir -p build
|
||||
cd build
|
||||
export CMAKE_PREFIX_PATH=$INSTALL_ROOT/lib/cmake
|
||||
export CMAKE_PREFIX_PATH="$INSTALL_ROOT/lib/cmake;${CMAKE_PREFIX_PATH}"
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .. \
|
||||
-DLIBGIT2_INCLUDE_DIR=$INSTALL_ROOT/include \
|
||||
-DLIBGIT2_LIBRARIES=$INSTALL_ROOT/lib/libgit2.$SH_LIB_EXT \
|
||||
@ -208,6 +227,7 @@ cmake -DCMAKE_BUILD_TYPE=Debug .. \
|
||||
-DLIBDIVECOMPUTER_LIBRARIES=$INSTALL_ROOT/lib/libdivecomputer.a \
|
||||
-DMARBLE_INCLUDE_DIR=$INSTALL_ROOT/include \
|
||||
-DMARBLE_LIBRARIES=$INSTALL_ROOT/lib/libssrfmarblewidget.$SH_LIB_EXT \
|
||||
-DCMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH \
|
||||
-DNO_PRINTING=OFF \
|
||||
-DUSE_LIBGIT23_API=1
|
||||
|
||||
|
||||
29
statistics.c
29
statistics.c
@ -20,6 +20,7 @@ stats_t stats_selection;
|
||||
stats_t *stats_monthly = NULL;
|
||||
stats_t *stats_yearly = NULL;
|
||||
stats_t *stats_by_trip = NULL;
|
||||
stats_t *stats_by_type = NULL;
|
||||
|
||||
static void process_temperatures(struct dive *dp, stats_t *stats)
|
||||
{
|
||||
@ -100,7 +101,7 @@ void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||
int prev_month = 0, prev_year = 0;
|
||||
int trip_iter = 0;
|
||||
dive_trip_t *trip_ptr = 0;
|
||||
unsigned int size;
|
||||
unsigned int size, tsize;
|
||||
|
||||
*prev_dive = NULL;
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
@ -117,18 +118,35 @@ void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||
free(stats_yearly);
|
||||
free(stats_monthly);
|
||||
free(stats_by_trip);
|
||||
free(stats_by_type);
|
||||
|
||||
size = sizeof(stats_t) * (dive_table.nr + 1);
|
||||
tsize = sizeof(stats_t) * (NUM_DC_TYPE + 1);
|
||||
stats_yearly = malloc(size);
|
||||
stats_monthly = malloc(size);
|
||||
stats_by_trip = malloc(size);
|
||||
if (!stats_yearly || !stats_monthly || !stats_by_trip)
|
||||
stats_by_type = malloc(tsize);
|
||||
if (!stats_yearly || !stats_monthly || !stats_by_trip || !stats_by_type)
|
||||
return;
|
||||
memset(stats_yearly, 0, size);
|
||||
memset(stats_monthly, 0, size);
|
||||
memset(stats_by_trip, 0, size);
|
||||
memset(stats_by_type, 0, tsize);
|
||||
stats_yearly[0].is_year = true;
|
||||
|
||||
/* Setting the is_trip to true to show the location as first
|
||||
* field in the statistics window */
|
||||
stats_by_type[0].location = strdup("All (by type stats)");
|
||||
stats_by_type[0].is_trip = true;
|
||||
stats_by_type[1].location = strdup("OC");
|
||||
stats_by_type[1].is_trip = true;
|
||||
stats_by_type[2].location = strdup("CCR");
|
||||
stats_by_type[2].is_trip = true;
|
||||
stats_by_type[3].location = strdup("pSCR");
|
||||
stats_by_type[3].is_trip = true;
|
||||
stats_by_type[4].location = strdup("Freedive");
|
||||
stats_by_type[4].is_trip = true;
|
||||
|
||||
/* this relies on the fact that the dives in the dive_table
|
||||
* are in chronological order */
|
||||
for_each_dive (idx, dp) {
|
||||
@ -154,6 +172,13 @@ void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||
stats_yearly[year_iter].selection_size++;
|
||||
stats_yearly[year_iter].period = current_year;
|
||||
|
||||
/* stats_by_type[0] is all the dives combined */
|
||||
stats_by_type[0].selection_size++;
|
||||
process_dive(dp, &(stats_by_type[0]));
|
||||
|
||||
process_dive(dp, &(stats_by_type[dp->dc.divemode + 1]));
|
||||
stats_by_type[dp->dc.divemode + 1].selection_size++;
|
||||
|
||||
if (dp->divetrip != NULL) {
|
||||
if (trip_ptr != dp->divetrip) {
|
||||
trip_ptr = dp->divetrip;
|
||||
|
||||
@ -39,6 +39,7 @@ extern stats_t stats_selection;
|
||||
extern stats_t *stats_yearly;
|
||||
extern stats_t *stats_monthly;
|
||||
extern stats_t *stats_by_trip;
|
||||
extern stats_t *stats_by_type;
|
||||
|
||||
extern char *get_time_string_s(int seconds, int maxdays, bool freediving);
|
||||
extern char *get_minutes(int seconds);
|
||||
|
||||
@ -308,12 +308,5 @@ void copy_prefs(struct preferences *src, struct preferences *dest)
|
||||
*/
|
||||
void free_prefs(void)
|
||||
{
|
||||
free((void*)prefs.default_filename);
|
||||
free((void*)prefs.default_cylinder);
|
||||
free((void*)prefs.divelist_font);
|
||||
free((void*)prefs.cloud_storage_password);
|
||||
free(prefs.proxy_host);
|
||||
free(prefs.proxy_user);
|
||||
free(prefs.proxy_pass);
|
||||
free(prefs.userid);
|
||||
// nop
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM 1)
|
||||
set(TRANSLATION_FILES
|
||||
subsurface_source.ts
|
||||
subsurface_bg_BG.ts
|
||||
subsurface_ca.ts
|
||||
subsurface_cs.ts
|
||||
subsurface_da_DK.ts
|
||||
subsurface_de_CH.ts
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
9775
translations/subsurface_ca.ts
Normal file
9775
translations/subsurface_ca.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -73,6 +73,8 @@ static int max_mem_used = -1;
|
||||
static int next_table_index = 0;
|
||||
static int dive_to_read = 0;
|
||||
|
||||
static int max_deleted_seen = -1;
|
||||
|
||||
/* helper function to parse the Uemis data structures */
|
||||
static void uemis_ts(char *buffer, void *_when)
|
||||
{
|
||||
@ -172,6 +174,8 @@ static void uemis_info(const char *fmt, ...)
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
progress_bar_text = buffer;
|
||||
if (verbose)
|
||||
fprintf(stderr, "Uemis downloader: %s\n", buffer);
|
||||
}
|
||||
|
||||
static long bytes_available(int file)
|
||||
@ -512,6 +516,7 @@ static bool uemis_get_answer(const char *path, char *request, int n_param_in,
|
||||
}
|
||||
trigger_response(reqtxt_file, "n", filenr, file_length);
|
||||
usleep(timeout);
|
||||
free(mbuf);
|
||||
mbuf = NULL;
|
||||
mbuf_size = 0;
|
||||
while (searching || assembling_mbuf) {
|
||||
@ -969,6 +974,12 @@ static char *uemis_get_divenr(char *deviceidstr, int force)
|
||||
maxdiveid = dc->diveid;
|
||||
}
|
||||
}
|
||||
if (max_deleted_seen >= 0 && maxdiveid < max_deleted_seen) {
|
||||
maxdiveid = max_deleted_seen;
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "overriding max seen with max deleted seen %d\n", max_deleted_seen);
|
||||
#endif
|
||||
}
|
||||
snprintf(divenr, 10, "%d", maxdiveid);
|
||||
return strdup(divenr);
|
||||
}
|
||||
@ -1031,6 +1042,9 @@ static int get_memory(struct dive_table *td, int checkpoint)
|
||||
max_mem_used = filenr / td->nr;
|
||||
|
||||
/* check if a full block of dive logs + dive details and dive spot fit into the UEMIS buffer */
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "max_mem_used %d (from td->nr %d) * block_size %d > max_files %d - filenr %d?\n", max_mem_used, td->nr, UEMIS_LOG_BLOCK_SIZE, UEMIS_MAX_FILES, filenr);
|
||||
#endif
|
||||
if (max_mem_used * UEMIS_LOG_BLOCK_SIZE > UEMIS_MAX_FILES - filenr)
|
||||
return UEMIS_MEM_FULL;
|
||||
break;
|
||||
@ -1109,9 +1123,14 @@ static bool get_matching_dive(int idx, char *newmax, int *uemis_mem_status, stru
|
||||
char log_file_no_to_find[20];
|
||||
char dive_to_read_buf[10];
|
||||
bool found = false;
|
||||
bool found_below = false;
|
||||
bool found_above = false;
|
||||
int deleted_files = 0;
|
||||
|
||||
snprintf(log_file_no_to_find, sizeof(log_file_no_to_find), "logfilenr{int{%d", dive->dc.diveid);
|
||||
#if UEMIS_DEBUG & 2
|
||||
fprintf(debugfile, "Looking for dive details to go with divelog id %d\n", dive->dc.diveid);
|
||||
#endif
|
||||
while (!found) {
|
||||
if (import_thread_cancelled)
|
||||
break;
|
||||
@ -1154,10 +1173,11 @@ static bool get_matching_dive(int idx, char *newmax, int *uemis_mem_status, stru
|
||||
fprintf(debugfile, "TRY matching divelog id %d from %s with dive details %d but details are deleted\n", dive->dc.diveid, d_time, dive_to_read);
|
||||
#endif
|
||||
deleted_files++;
|
||||
max_deleted_seen = dive_to_read;
|
||||
/* mark this log entry as deleted and cleanup later, otherwise we mess up our array */
|
||||
dive->downloaded = false;
|
||||
#if UEMIS_DEBUG & 2
|
||||
fprintf(debugfile, "Deleted dive from %s, with id %d from table\n", d_time, dive->dc.diveid);
|
||||
fprintf(debugfile, "Deleted dive from %s, with id %d from table -- newmax is %s\n", d_time, dive->dc.diveid, newmax);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
@ -1165,13 +1185,19 @@ static bool get_matching_dive(int idx, char *newmax, int *uemis_mem_status, stru
|
||||
char *logfilenr = strstr(mbuf, "logfilenr");
|
||||
if (logfilenr) {
|
||||
sscanf(logfilenr, "logfilenr{int{%u", &nr_found);
|
||||
if (nr_found >= dive->dc.diveid)
|
||||
if (nr_found >= dive->dc.diveid || nr_found == 0) {
|
||||
found_above = true;
|
||||
dive_to_read = dive_to_read - 2;
|
||||
} else {
|
||||
found_below = true;
|
||||
}
|
||||
if (dive_to_read < -1)
|
||||
dive_to_read = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_above && found_below)
|
||||
break;
|
||||
dive_to_read++;
|
||||
} else {
|
||||
/* At this point the memory of the UEMIS is full, let's cleanup all divelog files were
|
||||
@ -1233,6 +1259,8 @@ const char *do_uemis_import(device_data_t *data)
|
||||
|
||||
param_buff[1] = "notempty";
|
||||
newmax = uemis_get_divenr(deviceid, force_download);
|
||||
if (verbose)
|
||||
fprintf(stderr, "Uemis downloader: start looking at dive nr %s", newmax);
|
||||
|
||||
first = start = atoi(newmax);
|
||||
dive_to_read = first;
|
||||
@ -1250,27 +1278,30 @@ const char *do_uemis_import(device_data_t *data)
|
||||
param_buff[3] = 0;
|
||||
success = uemis_get_answer(mountpath, "getDivelogs", 3, 0, &result);
|
||||
uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_DETAILS);
|
||||
if (success && mbuf && uemis_mem_status != UEMIS_MEM_FULL) {
|
||||
/* first, remove any leading garbage... this needs to start with a '{' */
|
||||
char *realmbuf = mbuf;
|
||||
if (mbuf)
|
||||
realmbuf = strchr(mbuf, '{');
|
||||
if (success && realmbuf && uemis_mem_status != UEMIS_MEM_FULL) {
|
||||
#if UEMIS_DEBUG & 16
|
||||
do_dump_buffer_to_file(mbuf, "Divelogs");
|
||||
do_dump_buffer_to_file(realmbuf, "Divelogs");
|
||||
#endif
|
||||
/* process the buffer we have assembled */
|
||||
|
||||
if (!process_raw_buffer(data, deviceidnr, mbuf, &newmax, keep_number, NULL)) {
|
||||
if (!process_raw_buffer(data, deviceidnr, realmbuf, &newmax, keep_number, NULL)) {
|
||||
/* if no dives were downloaded, mark end appropriately */
|
||||
if (end == -2)
|
||||
end = start - 1;
|
||||
success = false;
|
||||
}
|
||||
if (once) {
|
||||
char *t = first_object_id_val(mbuf);
|
||||
char *t = first_object_id_val(realmbuf);
|
||||
if (t && atoi(t) > start)
|
||||
start = atoi(t);
|
||||
free(t);
|
||||
once = false;
|
||||
}
|
||||
/* clean up mbuf */
|
||||
endptr = strstr(mbuf, "{{{");
|
||||
endptr = strstr(realmbuf, "{{{");
|
||||
if (endptr)
|
||||
*(endptr + 2) = '\0';
|
||||
/* last object_id we parsed */
|
||||
@ -1296,20 +1327,32 @@ const char *do_uemis_import(device_data_t *data)
|
||||
|
||||
/* Do some memory checking here */
|
||||
uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_LOG);
|
||||
if (uemis_mem_status != UEMIS_MEM_OK)
|
||||
if (uemis_mem_status != UEMIS_MEM_OK) {
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "d_u_i out of memory, bailing\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
/* if the user clicked cancel, exit gracefully */
|
||||
if (import_thread_cancelled)
|
||||
if (import_thread_cancelled) {
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "d_u_i thread cancelled, bailing\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
/* if we got an error or got nothing back, stop trying */
|
||||
if (!success || !param_buff[3])
|
||||
if (!success || !param_buff[3]) {
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "d_u_i after download nothing found, giving up\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#if UEMIS_DEBUG & 2
|
||||
if (debug_round != -1)
|
||||
if (debug_round-- == 0)
|
||||
if (debug_round-- == 0) {
|
||||
fprintf(debugfile, "d_u_i debug_round is now 0, bailing\n");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* some of the loading from the UEMIS failed at the divelog level
|
||||
@ -1319,6 +1362,9 @@ const char *do_uemis_import(device_data_t *data)
|
||||
*/
|
||||
if (uemis_mem_status == UEMIS_MEM_FULL)
|
||||
do_delete_dives(data->download_table, match_dive_and_log);
|
||||
#if UEMIS_DEBUG & 4
|
||||
fprintf(debugfile, "d_u_i out of memory, bailing instead of processing\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,5 +27,6 @@ void WindowTitleUpdate::emitSignal()
|
||||
extern "C" void updateWindowTitle()
|
||||
{
|
||||
WindowTitleUpdate *wt = WindowTitleUpdate::instance();
|
||||
wt->emitSignal();
|
||||
if (wt)
|
||||
wt->emitSignal();
|
||||
}
|
||||
|
||||
@ -40,9 +40,9 @@ void writeMarkers(struct membuffer *b, const bool selected_only)
|
||||
snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Duration:"));
|
||||
snprintf(post, sizeof(post), " %s</p>", translate("gettextFromC", "min"));
|
||||
put_duration(b, dive->duration, pre, post);
|
||||
snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Max. depth:"));
|
||||
snprintf(post, sizeof(post), " %s</p>", translate("gettextFromC", "m"));
|
||||
put_depth(b, dive->maxdepth, pre, post);
|
||||
put_string(b, "<p> ");
|
||||
put_HTML_quoted(b, translate("gettextFromC", "Max. depth:"));
|
||||
put_HTML_depth(b, dive, " ", "</p>");
|
||||
put_string(b, "<p> ");
|
||||
put_HTML_quoted(b, translate("gettextFromC", "Air temp.:"));
|
||||
put_HTML_airtemp(b, dive, " ", "</p>");
|
||||
|
||||
@ -25,10 +25,20 @@
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:attribute name="duration">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="DIVETIMESEC"/>
|
||||
<xsl:with-param name="units" select="$units"/>
|
||||
</xsl:call-template>
|
||||
<xsl:choose>
|
||||
<xsl:when test="DIVETIMESEC != ''">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="DIVETIMESEC"/>
|
||||
<xsl:with-param name="units" select="$units"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="SAMPLECNT * SAMPLEINTERVAL"/>
|
||||
<xsl:with-param name="units" select="$units"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:choose>
|
||||
@ -178,7 +188,36 @@
|
||||
<!-- dive sample - all the depth and temp readings -->
|
||||
<xsl:for-each select="SAMPLE">
|
||||
<xsl:choose>
|
||||
<xsl:when test="BOOKMARK = ''">
|
||||
<xsl:when test="BOOKMARK != ''">
|
||||
<xsl:choose>
|
||||
<xsl:when test="substring-before(BOOKMARK, ':') = 'Heading'">
|
||||
<event name="heading">
|
||||
<xsl:attribute name="value">
|
||||
<xsl:value-of select="substring-before(substring-after(BOOKMARK, ': '), '°')"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="SAMPLETIME"/>
|
||||
<xsl:with-param name="units" select="'si'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</event>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:if test="BOOKMARK != 'Surface'">
|
||||
<event name="{BOOKMARK}">
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="SAMPLETIME"/>
|
||||
<xsl:with-param name="units" select="'si'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</event>
|
||||
</xsl:if>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<sample>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
@ -201,31 +240,6 @@
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</sample>
|
||||
</xsl:when>
|
||||
<xsl:when test="substring-before(BOOKMARK, ':') = 'Heading'">
|
||||
<event name="heading">
|
||||
<xsl:attribute name="value">
|
||||
<xsl:value-of select="substring-before(substring-after(BOOKMARK, ': '), '°')"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="SAMPLETIME"/>
|
||||
<xsl:with-param name="units" select="'si'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</event>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:if test="BOOKMARK != 'Surface'">
|
||||
<event name="{BOOKMARK}">
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec" select="SAMPLETIME"/>
|
||||
<xsl:with-param name="units" select="'si'"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</event>
|
||||
</xsl:if>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:for-each>
|
||||
|
||||
@ -127,7 +127,7 @@
|
||||
|
||||
<!-- Handling last value -->
|
||||
<xsl:when test="count($values) = 1">
|
||||
<xsl:value-of select="format-number($value + $sum, '#.#')"/>
|
||||
<xsl:value-of select="format-number($value + $sum, '#.###')"/>
|
||||
</xsl:when>
|
||||
|
||||
<!-- More than one value to sum -->
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:include href="commonTemplates.xsl"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
<xsl:param name="dateField" select="dateField"/>
|
||||
<xsl:param name="datefmt" select="datefmt"/>
|
||||
<xsl:param name="starttimeField" select="starttimeField"/>
|
||||
<xsl:param name="timeField" select="timeField"/>
|
||||
<xsl:param name="depthField" select="depthField"/>
|
||||
<xsl:param name="tempField" select="tempField"/>
|
||||
@ -30,6 +33,7 @@
|
||||
<xsl:choose>
|
||||
<xsl:when test="$separatorIndex = 0"><xsl:text> </xsl:text></xsl:when>
|
||||
<xsl:when test="$separatorIndex = 2"><xsl:text>;</xsl:text></xsl:when>
|
||||
<xsl:when test="$separatorIndex = 3"><xsl:text>|</xsl:text></xsl:when>
|
||||
<xsl:otherwise><xsl:text>,</xsl:text></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
@ -39,12 +43,73 @@
|
||||
<dives>
|
||||
<dive>
|
||||
<xsl:attribute name="date">
|
||||
<xsl:value-of select="concat(substring($date, 1, 4), '-', substring($date, 5, 2), '-', substring($date, 7, 2))"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$dateField >= 0">
|
||||
<xsl:variable name="indate">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$dateField"/>
|
||||
<xsl:with-param name="line" select="substring-after(substring-after(., $lf), $lf)"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="separator">
|
||||
<xsl:choose>
|
||||
<xsl:when test="substring-before($indate, '.') != ''">
|
||||
<xsl:value-of select="'.'"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="substring-before($indate, '-') != ''">
|
||||
<xsl:value-of select="'-'"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="substring-before($indate, '/') != ''">
|
||||
<xsl:value-of select="'/'"/>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:choose>
|
||||
<!-- dd.mm.yyyy -->
|
||||
<xsl:when test="$datefmt = 0">
|
||||
<xsl:value-of select="translate(concat(substring-after(substring-after($indate, $separator), $separator), '-', substring-before(substring-after($indate, $separator), $separator), '-', substring-before($indate, $separator)), ' ', '')"/>
|
||||
</xsl:when>
|
||||
<!-- mm.yy.yyyy -->
|
||||
<xsl:when test="$datefmt = 1">
|
||||
<xsl:value-of select="translate(concat(substring-after(substring-after($indate, $separator), $separator), '-', substring-before($indate, $separator), '-', substring-before(substring-after($indate, $separator), $separator)), ' ', '')"/>
|
||||
</xsl:when>
|
||||
<!-- yyyy.mm.dd -->
|
||||
<xsl:when test="$datefmt = 2">
|
||||
<xsl:value-of select="translate(concat(substring-before($indate, $separator), '-', substring-before(substring-after($indate, $separator), $separator), '-', substring-after(substring-after($indate, $separator), $separator)), ' ', '')"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="'1900-1-1'"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat(substring($date, 1, 4), '-', substring($date, 5, 2), '-', substring($date, 7, 2))"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:value-of select="concat(substring($time, 2, 2), ':', substring($time, 4, 2))"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$starttimeField >= 0">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$starttimeField"/>
|
||||
<xsl:with-param name="line" select="substring-after(substring-after(., $lf), $lf)"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat(substring($time, 2, 2), ':', substring($time, 4, 2))"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:if test="$numberField >= 0">
|
||||
<xsl:attribute name="number">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$numberField"/>
|
||||
<xsl:with-param name="line" select="substring-after(substring-after(., $lf), $lf)"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<!-- If the dive is CCR, create oxygen and diluent cylinders -->
|
||||
|
||||
<xsl:if test="$po2Field >= 0 or $setpointField >= 0 or $o2sensor1Field >= 0 or $o2sensor2Field >= 0 or $o2sensor3Field >= 0">
|
||||
@ -165,7 +230,15 @@
|
||||
|
||||
<xsl:call-template name="sec2time">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="$value"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="substring-after($value, '.') != ''">
|
||||
<!-- Well, I suppose it was min.sec -->
|
||||
<xsl:value-of select="substring-before($value, '.') * 60 + substring-after($value, '.')" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$value"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
@ -334,10 +407,20 @@
|
||||
|
||||
<xsl:if test="$pressureField >= 0">
|
||||
<xsl:attribute name="pressure">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$pressureField"/>
|
||||
<xsl:with-param name="line" select="$line"/>
|
||||
</xsl:call-template>
|
||||
<xsl:variable name="pressure">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$pressureField"/>
|
||||
<xsl:with-param name="line" select="$line"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$units = 0">
|
||||
<xsl:value-of select="$pressure"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="concat(format-number(($pressure div 14.5037738007), '#'), ' bar')"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
</sample>
|
||||
|
||||
@ -164,6 +164,14 @@
|
||||
</xsl:attribute>
|
||||
</sample>
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="PICTURES/PICTURE">
|
||||
<picture>
|
||||
<xsl:attribute name="filename">
|
||||
<xsl:value-of select="concat('https://divelogs.de', @path, .)"/>
|
||||
</xsl:attribute>
|
||||
</picture>
|
||||
</xsl:for-each>
|
||||
</dive>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
||||
@ -264,10 +264,20 @@
|
||||
<cylinder>
|
||||
<xsl:if test="$cylindersizeField > 0">
|
||||
<xsl:attribute name="size">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$cylindersizeField"/>
|
||||
<xsl:with-param name="line" select="$line"/>
|
||||
</xsl:call-template>
|
||||
<xsl:variable name="size">
|
||||
<xsl:call-template name="getFieldByIndex">
|
||||
<xsl:with-param name="index" select="$cylindersizeField"/>
|
||||
<xsl:with-param name="line" select="$line"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
<xsl:choose>
|
||||
<xsl:when test="$units = 0">
|
||||
<xsl:value-of select="$size"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="format-number((translate($size, translate($size, '0123456789', ''), '') * 14.7 div 3000) div 0.35315, '#.#')"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test="$startpressureField > 0">
|
||||
|
||||
@ -90,13 +90,24 @@
|
||||
|
||||
<!-- samples recorded at irregular internal, but storing time stamp -->
|
||||
<xsl:when test="timedepthmode">
|
||||
<xsl:variable name="timeconvert">
|
||||
<xsl:choose>
|
||||
<xsl:when test="//units = 'si'">
|
||||
<xsl:value-of select="60"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<debug name="{$timeconvert}"/>
|
||||
<!-- gas change -->
|
||||
<xsl:for-each select="SAMPLES/SWITCH|samples/switch">
|
||||
<event name="gaschange">
|
||||
<xsl:variable name="timeSec" select="following-sibling::T|following-sibling::t"/>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:value-of select="concat(floor($timeSec div 60), ':',
|
||||
format-number(floor($timeSec mod 60), '00'), ' min')"/>
|
||||
<xsl:value-of select="concat(floor($timeSec div $timeconvert), ':',
|
||||
format-number(floor($timeSec mod $timeconvert), '00'), ' min')"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="value">
|
||||
<xsl:value-of select="ancestor::DIVE/GASES/MIX[MIXNAME=current()]/O2|ancestor::dive/gases/mix[mixname=current()]/o2 * 100" />
|
||||
@ -110,8 +121,8 @@
|
||||
<sample>
|
||||
<xsl:variable name="timeSec" select="preceding-sibling::T[position()=1]|preceding-sibling::t[position()=1]"/>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:value-of select="concat(floor($timeSec div 60), ':',
|
||||
format-number(floor($timeSec mod 60), '00'), ' min')"/>
|
||||
<xsl:value-of select="concat(floor($timeSec div $timeconvert), ':',
|
||||
format-number(floor($timeSec mod $timeconvert), '00'), ' min')"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(., ' m')"/>
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
|
||||
<xsl:template match="/divelog/settings"/>
|
||||
<xsl:template match="/divelog/divesites"/>
|
||||
|
||||
<xsl:template match="/divelog/dives">
|
||||
<uddf version="3.2.0" xmlns="http://www.streit.cc/uddf/3.2/">
|
||||
@ -121,7 +122,6 @@
|
||||
</diver>
|
||||
|
||||
<divesite>
|
||||
|
||||
<!-- There must be at least one divebase. Subsurface doesn't track this as a concept, so just assign them all to a single divebase. -->
|
||||
<divebase id="allbase">
|
||||
<name>Subsurface Divebase</name>
|
||||
@ -235,6 +235,13 @@
|
||||
<xsl:value-of select="substring-after(@gps, ' ')"/>
|
||||
</longitude>
|
||||
</geography>
|
||||
<xsl:if test="notes != ''">
|
||||
<sitedata>
|
||||
<notes>
|
||||
<xsl:value-of select="notes"/>
|
||||
</notes>
|
||||
</sitedata>
|
||||
</xsl:if>
|
||||
</site>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
195
xslt/uddf.xslt
195
xslt/uddf.xslt
@ -60,6 +60,9 @@
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="dive|u:dive|u1:dive">
|
||||
<xsl:variable name="tankdata">
|
||||
<xsl:value-of select="count(//tankdata|//u:tankdata|//u1:tankdata)"/>
|
||||
</xsl:variable>
|
||||
<dive>
|
||||
<!-- Count the amount of temeprature samples during the dive -->
|
||||
<xsl:variable name="temperatureSamples">
|
||||
@ -278,7 +281,7 @@
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="/uddf/gasdefinitions != ''">
|
||||
<xsl:if test="/uddf/gasdefinitions != '' and $tankdata = 0">
|
||||
<xsl:for-each select="/uddf/gasdefinitions/mix">
|
||||
<cylinder description="unknown">
|
||||
<xsl:attribute name="o2">
|
||||
@ -455,106 +458,108 @@
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:for-each select="samples/waypoint|u:samples/u:waypoint|u1:samples/u1:waypoint|samples/d">
|
||||
<sample>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="divetime|u:divetime|u1:divetime|preceding-sibling::t[1]"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="depth != ''">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(depth, '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:when test="u:depth|u1:depth != ''">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(u:depth|u1:depth, '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:when test=". != 0">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(., '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
|
||||
<xsl:if test="temperature != '' and $temperatureSamples > 0">
|
||||
<xsl:attribute name="temp">
|
||||
<xsl:value-of select="concat(format-number(temperature - 273.15, '0.0'), ' C')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="u:temperature|u1:temperature != '' and $temperatureSamples > 0">
|
||||
<xsl:attribute name="temp">
|
||||
<xsl:value-of select="concat(format-number(u:temperature|u1:temperature - 273.15, '0.0'), ' C')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="tankpressure|u:tankpressure|u1:tankpressure != ''">
|
||||
<xsl:attribute name="pressure">
|
||||
<xsl:value-of select="concat(format-number(tankpressure|u:tankpressure|u1:tankpressure div 100000, '0.0'), ' bar')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="otu|u:otu|u1:otu > 0">
|
||||
<xsl:attribute name="otu">
|
||||
<xsl:value-of select="otu|u:otu|u1:otu"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="cns|u:cns|u1:cns > 0">
|
||||
<xsl:attribute name="cns">
|
||||
<xsl:value-of select="cns|u:cns|u1:cns"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="setpo2|u:setpo2|u1:setpo2 != ''">
|
||||
<xsl:attribute name="po2">
|
||||
<xsl:call-template name="convertPascal">
|
||||
<xsl:with-param name="value">
|
||||
<xsl:value-of select="setpo2|u:setpo2|u1:setpo2"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="nodecotime|u:nodecotime|u1:nodecotime > 0">
|
||||
<xsl:attribute name="ndl">
|
||||
<xsl:if test="./depth|./u:depth|./u1:depth != ''">
|
||||
<sample>
|
||||
<xsl:attribute name="time">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="nodecotime|u:nodecotime|u1:nodecotime"/>
|
||||
<xsl:value-of select="divetime|u:divetime|u1:divetime|preceding-sibling::t[1]"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="decostop|u:decostop|u1:decostop">
|
||||
<xsl:attribute name="stoptime">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="decostop/@duration|u:decostop/@duration|u1:decostop/@duration"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="stopdepth">
|
||||
<xsl:value-of select="decostop/@decodepth|u:decostop/@decodepth|u1:decostop/@decodepth"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="in_deco">
|
||||
<xsl:choose>
|
||||
<xsl:when test="decostop/@kind|u:decostop/@kind|u1:decostop/@kind != 'mandatory'">
|
||||
<xsl:value-of select="0"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
</sample>
|
||||
<xsl:choose>
|
||||
<xsl:when test="depth != ''">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(depth, '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:when test="u:depth|u1:depth != ''">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(u:depth|u1:depth, '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:when test=". != 0">
|
||||
<xsl:attribute name="depth">
|
||||
<xsl:value-of select="concat(format-number(., '0.00'), ' m')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
|
||||
<xsl:if test="temperature != '' and $temperatureSamples > 0">
|
||||
<xsl:attribute name="temp">
|
||||
<xsl:value-of select="concat(format-number(temperature - 273.15, '0.0'), ' C')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="u:temperature|u1:temperature != '' and $temperatureSamples > 0">
|
||||
<xsl:attribute name="temp">
|
||||
<xsl:value-of select="concat(format-number(u:temperature|u1:temperature - 273.15, '0.0'), ' C')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="tankpressure|u:tankpressure|u1:tankpressure != ''">
|
||||
<xsl:attribute name="pressure">
|
||||
<xsl:value-of select="concat(format-number(tankpressure|u:tankpressure|u1:tankpressure div 100000, '0.0'), ' bar')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="otu|u:otu|u1:otu > 0">
|
||||
<xsl:attribute name="otu">
|
||||
<xsl:value-of select="otu|u:otu|u1:otu"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="cns|u:cns|u1:cns > 0">
|
||||
<xsl:attribute name="cns">
|
||||
<xsl:value-of select="cns|u:cns|u1:cns"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="setpo2|u:setpo2|u1:setpo2 != ''">
|
||||
<xsl:attribute name="po2">
|
||||
<xsl:call-template name="convertPascal">
|
||||
<xsl:with-param name="value">
|
||||
<xsl:value-of select="setpo2|u:setpo2|u1:setpo2"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="nodecotime|u:nodecotime|u1:nodecotime > 0">
|
||||
<xsl:attribute name="ndl">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="nodecotime|u:nodecotime|u1:nodecotime"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="decostop|u:decostop|u1:decostop">
|
||||
<xsl:attribute name="stoptime">
|
||||
<xsl:call-template name="timeConvert">
|
||||
<xsl:with-param name="timeSec">
|
||||
<xsl:value-of select="decostop/@duration|u:decostop/@duration|u1:decostop/@duration"/>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="stopdepth">
|
||||
<xsl:value-of select="decostop/@decodepth|u:decostop/@decodepth|u1:decostop/@decodepth"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="in_deco">
|
||||
<xsl:choose>
|
||||
<xsl:when test="decostop/@kind|u:decostop/@kind|u1:decostop/@kind != 'mandatory'">
|
||||
<xsl:value-of select="0"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="1"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
</sample>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</divecomputer>
|
||||
</dive>
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
<xsl:apply-templates select="dive|trip/dive"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="divesites/site/notes"/>
|
||||
|
||||
<xsl:template match="dive">
|
||||
<xsl:text>"</xsl:text>
|
||||
<xsl:value-of select="@number"/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user