2015-06-04 10:29:50 +00:00
|
|
|
#include "qmlmanager.h"
|
2015-06-04 10:36:36 +00:00
|
|
|
#include <QUrl>
|
2015-07-10 07:47:26 +00:00
|
|
|
#include <QSettings>
|
2015-07-13 00:39:13 +00:00
|
|
|
#include <QDebug>
|
2015-12-05 03:34:59 +00:00
|
|
|
#include <QNetworkAccessManager>
|
|
|
|
#include <QAuthenticator>
|
2015-12-26 21:22:50 +00:00
|
|
|
#include <QDesktopServices>
|
2016-01-08 06:30:58 +00:00
|
|
|
#include <QTextDocument>
|
2015-06-04 10:29:50 +00:00
|
|
|
|
2015-06-11 06:56:18 +00:00
|
|
|
#include "qt-models/divelistmodel.h"
|
2016-01-08 15:11:49 +00:00
|
|
|
#include <gpslistmodel.h>
|
2015-06-11 06:56:18 +00:00
|
|
|
#include "divelist.h"
|
2016-01-29 06:04:13 +00:00
|
|
|
#include "device.h"
|
2015-07-10 07:47:26 +00:00
|
|
|
#include "pref.h"
|
2015-07-10 08:31:24 +00:00
|
|
|
#include "qthelper.h"
|
2015-07-13 00:39:13 +00:00
|
|
|
#include "qt-gui.h"
|
2015-12-15 07:00:19 +00:00
|
|
|
#include "git-access.h"
|
2016-01-26 14:45:03 +00:00
|
|
|
#include "subsurface-core/cloudstorage.h"
|
2015-07-13 00:39:13 +00:00
|
|
|
|
2015-12-03 23:59:40 +00:00
|
|
|
QMLManager *QMLManager::m_instance = NULL;
|
|
|
|
|
|
|
|
static void appendTextToLogStandalone(const char *text)
|
2015-07-13 00:39:13 +00:00
|
|
|
{
|
2016-01-26 14:45:03 +00:00
|
|
|
QMLManager *self = QMLManager::instance();
|
|
|
|
if (self)
|
|
|
|
self->appendTextToLog(QString(text));
|
2015-07-13 00:39:13 +00:00
|
|
|
}
|
2015-06-09 19:20:44 +00:00
|
|
|
|
2015-12-15 07:00:19 +00:00
|
|
|
extern "C" int gitProgressCB(int percent)
|
|
|
|
{
|
|
|
|
static int lastPercent = -10;
|
|
|
|
|
|
|
|
if (percent - lastPercent >= 10) {
|
|
|
|
lastPercent += 10;
|
2016-01-26 14:45:03 +00:00
|
|
|
QMLManager *self = QMLManager::instance();
|
|
|
|
if (self)
|
|
|
|
self->loadDiveProgress(percent);
|
2015-12-15 07:00:19 +00:00
|
|
|
}
|
|
|
|
// return 0 so that we don't end the download
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-11 14:14:45 +00:00
|
|
|
QMLManager::QMLManager() : m_locationServiceEnabled(false),
|
2016-01-07 00:56:08 +00:00
|
|
|
m_verboseEnabled(false),
|
2016-02-29 14:53:26 +00:00
|
|
|
reply(0),
|
|
|
|
deletedDive(0),
|
2016-03-09 03:29:56 +00:00
|
|
|
deletedTrip(0),
|
|
|
|
m_credentialStatus(UNKNOWN),
|
|
|
|
m_lastDevicePixelRatio(1.0)
|
2015-06-04 10:29:50 +00:00
|
|
|
{
|
2015-12-03 23:59:40 +00:00
|
|
|
m_instance = this;
|
2015-12-20 16:02:05 +00:00
|
|
|
appendTextToLog(getUserAgent());
|
2016-01-26 15:02:42 +00:00
|
|
|
appendTextToLog(QStringLiteral("build with Qt Version %1, runtime from Qt Version %2").arg(QT_VERSION_STR).arg(qVersion()));
|
2015-12-20 16:02:05 +00:00
|
|
|
qDebug() << "Starting" << getUserAgent();
|
2016-01-26 15:02:42 +00:00
|
|
|
qDebug() << QStringLiteral("build with Qt Version %1, runtime from Qt Version %2").arg(QT_VERSION_STR).arg(qVersion());
|
2016-02-11 01:31:52 +00:00
|
|
|
setStartPageText(tr("Starting..."));
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(false);
|
2015-11-11 20:32:54 +00:00
|
|
|
// create location manager service
|
2015-12-03 23:59:40 +00:00
|
|
|
locationProvider = new GpsLocation(&appendTextToLogStandalone, this);
|
2015-12-15 07:00:19 +00:00
|
|
|
set_git_update_cb(&gitProgressCB);
|
2016-02-08 19:08:49 +00:00
|
|
|
|
|
|
|
// make sure we know if the current cloud repo has been successfully synced
|
|
|
|
syncLoadFromCloud();
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
2015-11-11 20:32:54 +00:00
|
|
|
|
2016-02-09 15:53:22 +00:00
|
|
|
void QMLManager::openLocalThenRemote(QString url)
|
|
|
|
{
|
|
|
|
clear_dive_file_data();
|
|
|
|
QByteArray fileNamePrt = QFile::encodeName(url);
|
|
|
|
prefs.git_local_only = true;
|
|
|
|
int error = parse_file(fileNamePrt.data());
|
|
|
|
prefs.git_local_only = false;
|
|
|
|
if (error) {
|
|
|
|
appendTextToLog(QStringLiteral("loading dives from cache failed %1").arg(error));
|
|
|
|
} else {
|
2016-02-11 01:45:23 +00:00
|
|
|
// if we can load from the cache, we know that we have at least a valid email
|
|
|
|
if (credentialStatus() == UNKNOWN)
|
|
|
|
setCredentialStatus(VALID_EMAIL);
|
2016-02-09 15:53:22 +00:00
|
|
|
prefs.unit_system = informational_prefs.unit_system;
|
|
|
|
if (informational_prefs.unit_system == IMPERIAL)
|
|
|
|
informational_prefs.units = IMPERIAL_units;
|
|
|
|
prefs.units = informational_prefs.units;
|
|
|
|
int i;
|
|
|
|
struct dive *d;
|
|
|
|
process_dives(false, false);
|
|
|
|
DiveListModel::instance()->clear();
|
|
|
|
for_each_dive (i, d) {
|
|
|
|
DiveListModel::instance()->addDive(d);
|
|
|
|
}
|
|
|
|
appendTextToLog(QStringLiteral("%1 dives loaded from cache").arg(i));
|
|
|
|
}
|
|
|
|
appendTextToLog(QStringLiteral("have cloud credentials, trying to connect"));
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(true);
|
2016-02-09 15:53:22 +00:00
|
|
|
tryRetrieveDataFromBackend();
|
|
|
|
}
|
|
|
|
|
2015-12-05 03:34:59 +00:00
|
|
|
void QMLManager::finishSetup()
|
|
|
|
{
|
2015-11-11 20:32:54 +00:00
|
|
|
// Initialize cloud credentials.
|
2015-07-10 07:47:26 +00:00
|
|
|
setCloudUserName(prefs.cloud_storage_email);
|
|
|
|
setCloudPassword(prefs.cloud_storage_password);
|
2015-07-21 08:57:10 +00:00
|
|
|
setSaveCloudPassword(prefs.save_password_local);
|
2015-11-18 21:14:19 +00:00
|
|
|
// if the cloud credentials are valid, we should get the GPS Webservice ID as well
|
2015-12-27 16:32:15 +00:00
|
|
|
QString url;
|
2016-02-11 01:31:52 +00:00
|
|
|
if (!cloudUserName().isEmpty() &&
|
|
|
|
!cloudPassword().isEmpty() &&
|
2015-12-27 16:32:15 +00:00
|
|
|
getCloudURL(url) == 0) {
|
2016-02-09 15:53:22 +00:00
|
|
|
openLocalThenRemote(url);
|
2015-12-20 00:08:10 +00:00
|
|
|
} else {
|
2016-02-11 01:45:23 +00:00
|
|
|
setCredentialStatus(INCOMPLETE);
|
2016-02-11 01:31:52 +00:00
|
|
|
appendTextToLog(QStringLiteral("no cloud credentials"));
|
|
|
|
setStartPageText(tr("Please enter valid cloud credentials."));
|
2015-12-20 00:08:10 +00:00
|
|
|
}
|
2015-11-14 17:10:06 +00:00
|
|
|
setDistanceThreshold(prefs.distance_threshold);
|
|
|
|
setTimeThreshold(prefs.time_threshold / 60);
|
2015-06-04 10:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QMLManager::~QMLManager()
|
|
|
|
{
|
2015-12-03 23:59:40 +00:00
|
|
|
m_instance = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMLManager *QMLManager::instance()
|
|
|
|
{
|
|
|
|
return m_instance;
|
2015-06-04 10:29:50 +00:00
|
|
|
}
|
|
|
|
|
2015-07-10 07:47:26 +00:00
|
|
|
void QMLManager::savePreferences()
|
|
|
|
{
|
|
|
|
QSettings s;
|
2015-11-14 17:10:06 +00:00
|
|
|
s.beginGroup("LocationService");
|
|
|
|
s.setValue("time_threshold", timeThreshold() * 60);
|
|
|
|
prefs.time_threshold = timeThreshold() * 60;
|
|
|
|
s.setValue("distance_threshold", distanceThreshold());
|
|
|
|
prefs.distance_threshold = distanceThreshold();
|
2015-12-05 03:34:59 +00:00
|
|
|
s.sync();
|
2015-12-03 22:30:30 +00:00
|
|
|
}
|
|
|
|
|
2015-12-05 03:34:59 +00:00
|
|
|
#define CLOUDURL QString(prefs.cloud_base_url)
|
|
|
|
#define CLOUDREDIRECTURL CLOUDURL + "/cgi-bin/redirect.pl"
|
|
|
|
|
2015-12-03 22:30:30 +00:00
|
|
|
void QMLManager::saveCloudCredentials()
|
|
|
|
{
|
|
|
|
QSettings s;
|
|
|
|
bool cloudCredentialsChanged = false;
|
2015-07-10 07:47:26 +00:00
|
|
|
s.beginGroup("CloudStorage");
|
|
|
|
s.setValue("email", cloudUserName());
|
2015-07-21 08:57:10 +00:00
|
|
|
s.setValue("save_password_local", saveCloudPassword());
|
|
|
|
if (saveCloudPassword())
|
|
|
|
s.setValue("password", cloudPassword());
|
2015-07-10 07:47:26 +00:00
|
|
|
s.sync();
|
2015-07-13 00:39:13 +00:00
|
|
|
if (!same_string(prefs.cloud_storage_email, qPrintable(cloudUserName()))) {
|
|
|
|
free(prefs.cloud_storage_email);
|
|
|
|
prefs.cloud_storage_email = strdup(qPrintable(cloudUserName()));
|
2015-11-18 21:14:19 +00:00
|
|
|
cloudCredentialsChanged = true;
|
2015-07-13 00:39:13 +00:00
|
|
|
}
|
2015-11-18 21:12:34 +00:00
|
|
|
if (saveCloudPassword() != prefs.save_password_local)
|
2015-07-21 08:57:10 +00:00
|
|
|
prefs.save_password_local = saveCloudPassword();
|
2015-11-18 21:14:19 +00:00
|
|
|
|
|
|
|
cloudCredentialsChanged |= !same_string(prefs.cloud_storage_password, qPrintable(cloudPassword()));
|
|
|
|
|
2015-07-21 08:57:10 +00:00
|
|
|
if (saveCloudPassword()) {
|
|
|
|
if (!same_string(prefs.cloud_storage_password, qPrintable(cloudPassword()))) {
|
|
|
|
free(prefs.cloud_storage_password);
|
|
|
|
prefs.cloud_storage_password = strdup(qPrintable(cloudPassword()));
|
|
|
|
}
|
2015-07-13 00:39:13 +00:00
|
|
|
}
|
2016-02-13 06:06:38 +00:00
|
|
|
if (cloudUserName().isEmpty() || cloudPassword().isEmpty()) {
|
|
|
|
setStartPageText(tr("Please enter valid cloud credentials."));
|
|
|
|
} else if (cloudCredentialsChanged) {
|
2015-12-05 03:34:59 +00:00
|
|
|
free(prefs.userid);
|
|
|
|
prefs.userid = NULL;
|
2016-02-08 19:14:11 +00:00
|
|
|
syncLoadFromCloud();
|
2016-02-09 15:53:22 +00:00
|
|
|
QString url;
|
|
|
|
getCloudURL(url);
|
2016-02-11 02:14:09 +00:00
|
|
|
manager()->clearAccessCache(); // remove any chached credentials
|
2016-02-11 05:24:10 +00:00
|
|
|
clear_git_id(); // invalidate our remembered GIT SHA
|
2016-02-12 06:46:35 +00:00
|
|
|
clear_dive_file_data();
|
|
|
|
DiveListModel::instance()->clear();
|
|
|
|
GpsListModel::instance()->clear();
|
2016-02-12 14:54:52 +00:00
|
|
|
setStartPageText(tr("Attempting to open cloud storage with new credentials"));
|
2016-02-09 15:53:22 +00:00
|
|
|
openLocalThenRemote(url);
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::checkCredentialsAndExecute(execute_function_type execute)
|
|
|
|
{
|
|
|
|
// if the cloud credentials are present, we should try to get the GPS Webservice ID
|
|
|
|
// and (if we haven't done so) load the dive list
|
2015-11-18 21:14:19 +00:00
|
|
|
if (!same_string(prefs.cloud_storage_email, "") &&
|
|
|
|
!same_string(prefs.cloud_storage_password, "")) {
|
2016-01-02 08:04:59 +00:00
|
|
|
setStartPageText(tr("Testing cloud credentials"));
|
2015-12-05 03:34:59 +00:00
|
|
|
appendTextToLog("Have credentials, let's see if they are valid");
|
2016-01-26 14:45:03 +00:00
|
|
|
connect(manager(), &QNetworkAccessManager::authenticationRequired, this, &QMLManager::provideAuth, Qt::UniqueConnection);
|
|
|
|
connect(manager(), &QNetworkAccessManager::finished, this, execute, Qt::UniqueConnection);
|
2015-12-05 03:34:59 +00:00
|
|
|
QUrl url(CLOUDREDIRECTURL);
|
|
|
|
request = QNetworkRequest(url);
|
|
|
|
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
|
|
|
request.setRawHeader("Accept", "text/html");
|
2016-01-26 14:45:03 +00:00
|
|
|
reply = manager()->get(request);
|
2015-12-05 03:34:59 +00:00
|
|
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError(QNetworkReply::NetworkError)));
|
|
|
|
connect(reply, &QNetworkReply::sslErrors, this, &QMLManager::handleSslErrors);
|
2015-11-18 21:14:19 +00:00
|
|
|
}
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::tryRetrieveDataFromBackend()
|
|
|
|
{
|
|
|
|
checkCredentialsAndExecute(&QMLManager::retrieveUserid);
|
2015-07-10 07:47:26 +00:00
|
|
|
}
|
2015-07-10 08:31:24 +00:00
|
|
|
|
|
|
|
void QMLManager::loadDives()
|
|
|
|
{
|
2015-12-05 03:34:59 +00:00
|
|
|
checkCredentialsAndExecute(&QMLManager::loadDivesWithValidCredentials);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::provideAuth(QNetworkReply *reply, QAuthenticator *auth)
|
|
|
|
{
|
|
|
|
if (auth->user() == QString(prefs.cloud_storage_email) &&
|
|
|
|
auth->password() == QString(prefs.cloud_storage_password)) {
|
|
|
|
// OK, credentials have been tried and didn't work, so they are invalid
|
|
|
|
appendTextToLog("Cloud credentials are invalid");
|
2016-01-02 08:04:59 +00:00
|
|
|
setStartPageText(tr("Cloud credentials are invalid"));
|
2016-02-11 01:45:23 +00:00
|
|
|
setCredentialStatus(INVALID);
|
2015-12-05 03:34:59 +00:00
|
|
|
reply->disconnect();
|
|
|
|
reply->abort();
|
|
|
|
reply->deleteLater();
|
2015-11-30 18:15:04 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-12-05 03:34:59 +00:00
|
|
|
auth->setUser(prefs.cloud_storage_email);
|
|
|
|
auth->setPassword(prefs.cloud_storage_password);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::handleSslErrors(const QList<QSslError> &errors)
|
|
|
|
{
|
2015-12-15 07:00:19 +00:00
|
|
|
setStartPageText(tr("Cannot open cloud storage: Error creating https connection"));
|
2016-01-11 14:14:45 +00:00
|
|
|
Q_FOREACH (QSslError e, errors) {
|
2015-12-05 03:34:59 +00:00
|
|
|
qDebug() << e.errorString();
|
|
|
|
}
|
|
|
|
reply->abort();
|
|
|
|
reply->deleteLater();
|
2016-03-03 14:32:12 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
2015-11-30 18:15:04 +00:00
|
|
|
|
2015-12-05 03:34:59 +00:00
|
|
|
void QMLManager::handleError(QNetworkReply::NetworkError nError)
|
|
|
|
{
|
2015-12-15 07:00:19 +00:00
|
|
|
QString errorString = reply->errorString();
|
|
|
|
qDebug() << "handleError" << nError << errorString;
|
|
|
|
setStartPageText(tr("Cannot open cloud storage: %1").arg(errorString));
|
2015-12-05 03:34:59 +00:00
|
|
|
reply->abort();
|
|
|
|
reply->deleteLater();
|
2016-03-03 14:32:12 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::retrieveUserid()
|
|
|
|
{
|
|
|
|
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302) {
|
2016-01-26 15:02:42 +00:00
|
|
|
appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: ") + reply->readAll());
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-05 03:34:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-02-11 01:45:23 +00:00
|
|
|
setCredentialStatus(VALID);
|
2015-12-05 03:34:59 +00:00
|
|
|
QString userid(prefs.userid);
|
2015-12-20 00:20:20 +00:00
|
|
|
if (userid.isEmpty()) {
|
|
|
|
if (same_string(prefs.cloud_storage_email, "") || same_string(prefs.cloud_storage_password, "")) {
|
|
|
|
appendTextToLog("cloud user name or password are empty, can't retrieve web user id");
|
2016-03-03 14:32:12 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-20 00:20:20 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-01-26 15:02:42 +00:00
|
|
|
appendTextToLog(QStringLiteral("calling getUserid with user %1").arg(prefs.cloud_storage_email));
|
2015-12-05 03:34:59 +00:00
|
|
|
userid = locationProvider->getUserid(prefs.cloud_storage_email, prefs.cloud_storage_password);
|
2015-12-20 00:20:20 +00:00
|
|
|
}
|
2015-12-05 03:34:59 +00:00
|
|
|
if (!userid.isEmpty()) {
|
|
|
|
// overwrite the existing userid
|
|
|
|
free(prefs.userid);
|
|
|
|
prefs.userid = strdup(qPrintable(userid));
|
|
|
|
QSettings s;
|
|
|
|
s.setValue("subsurface_webservice_uid", prefs.userid);
|
|
|
|
s.sync();
|
|
|
|
}
|
2016-02-08 19:12:43 +00:00
|
|
|
loadDivesWithValidCredentials();
|
2015-12-05 03:34:59 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 07:00:19 +00:00
|
|
|
void QMLManager::loadDiveProgress(int percent)
|
|
|
|
{
|
|
|
|
QString text(tr("Loading dive list from cloud storage."));
|
2016-01-11 14:14:45 +00:00
|
|
|
while (percent > 0) {
|
2015-12-15 07:00:19 +00:00
|
|
|
text.append(".");
|
|
|
|
percent -= 10;
|
|
|
|
}
|
|
|
|
setStartPageText(text);
|
|
|
|
}
|
|
|
|
|
2015-12-05 03:34:59 +00:00
|
|
|
void QMLManager::loadDivesWithValidCredentials()
|
|
|
|
{
|
|
|
|
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302) {
|
2016-01-26 15:02:42 +00:00
|
|
|
appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: ") + reply->readAll());
|
2015-12-15 07:00:19 +00:00
|
|
|
setStartPageText(tr("Cannot connect to cloud storage"));
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-05 03:34:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-02-11 01:45:23 +00:00
|
|
|
setCredentialStatus(VALID);
|
2015-12-05 03:34:59 +00:00
|
|
|
appendTextToLog("Cloud credentials valid, loading dives...");
|
2016-02-12 20:17:47 +00:00
|
|
|
setStartPageText("Cloud credentials valid, loading dives...");
|
2015-12-15 07:00:19 +00:00
|
|
|
loadDiveProgress(0);
|
2015-07-10 08:31:24 +00:00
|
|
|
QString url;
|
|
|
|
if (getCloudURL(url)) {
|
2015-12-15 07:00:19 +00:00
|
|
|
QString errorString(get_error_string());
|
|
|
|
appendTextToLog(errorString);
|
|
|
|
setStartPageText(tr("Cloud storage error: %1").arg(errorString));
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(false);
|
2015-07-10 08:31:24 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-01-11 14:14:45 +00:00
|
|
|
QByteArray fileNamePrt = QFile::encodeName(url);
|
2016-01-05 01:48:34 +00:00
|
|
|
if (check_git_sha(fileNamePrt.data()) == 0) {
|
2015-12-27 18:05:19 +00:00
|
|
|
qDebug() << "local cache was current, no need to modify dive list";
|
|
|
|
appendTextToLog("Cloud sync shows local cache was current");
|
2016-01-07 19:49:29 +00:00
|
|
|
setLoadFromCloud(true);
|
2016-03-03 01:13:42 +00:00
|
|
|
setAccessingCloud(false);
|
2015-12-27 18:05:19 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-01-05 01:48:34 +00:00
|
|
|
clear_dive_file_data();
|
|
|
|
DiveListModel::instance()->clear();
|
2015-12-27 18:05:19 +00:00
|
|
|
|
2016-01-05 01:48:34 +00:00
|
|
|
int error = parse_file(fileNamePrt.data());
|
2016-03-03 14:32:12 +00:00
|
|
|
setAccessingCloud(false);
|
2015-07-10 08:31:24 +00:00
|
|
|
if (!error) {
|
2015-07-13 00:39:13 +00:00
|
|
|
report_error("filename is now %s", fileNamePrt.data());
|
2015-12-01 17:37:47 +00:00
|
|
|
const char *error_string = get_error_string();
|
|
|
|
appendTextToLog(error_string);
|
2015-07-10 08:31:24 +00:00
|
|
|
set_filename(fileNamePrt.data(), true);
|
2015-07-13 00:39:13 +00:00
|
|
|
} else {
|
2015-12-01 17:37:47 +00:00
|
|
|
report_error("failed to open file %s", fileNamePrt.data());
|
2015-12-15 07:00:19 +00:00
|
|
|
QString errorString(get_error_string());
|
|
|
|
appendTextToLog(errorString);
|
|
|
|
setStartPageText(tr("Cloud storage error: %1").arg(errorString));
|
2015-12-03 01:50:47 +00:00
|
|
|
return;
|
2015-07-10 08:31:24 +00:00
|
|
|
}
|
2016-01-07 05:58:02 +00:00
|
|
|
prefs.unit_system = informational_prefs.unit_system;
|
2016-01-20 16:45:43 +00:00
|
|
|
if (informational_prefs.unit_system == IMPERIAL)
|
|
|
|
informational_prefs.units = IMPERIAL_units;
|
2016-01-07 05:58:02 +00:00
|
|
|
prefs.units = informational_prefs.units;
|
2015-07-10 08:31:24 +00:00
|
|
|
process_dives(false, false);
|
2015-07-24 20:18:30 +00:00
|
|
|
|
2015-07-10 08:31:24 +00:00
|
|
|
int i;
|
|
|
|
struct dive *d;
|
|
|
|
|
2016-01-11 14:14:45 +00:00
|
|
|
for_each_dive (i, d) {
|
2015-07-24 20:18:30 +00:00
|
|
|
DiveListModel::instance()->addDive(d);
|
|
|
|
}
|
2016-01-26 15:02:42 +00:00
|
|
|
appendTextToLog(QStringLiteral("%1 dives loaded").arg(i));
|
2015-12-15 07:00:19 +00:00
|
|
|
if (dive_table.nr == 0)
|
|
|
|
setStartPageText(tr("Cloud storage open successfully. No dives in dive list."));
|
2015-12-03 02:49:02 +00:00
|
|
|
setLoadFromCloud(true);
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 03:34:21 +00:00
|
|
|
void QMLManager::refreshDiveList()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct dive *d;
|
|
|
|
DiveListModel::instance()->clear();
|
2016-01-11 14:14:45 +00:00
|
|
|
for_each_dive (i, d) {
|
2016-01-11 03:34:21 +00:00
|
|
|
DiveListModel::instance()->addDive(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-08 06:30:58 +00:00
|
|
|
// update the dive and return the notes field, stripped of the HTML junk
|
2016-02-28 14:43:54 +00:00
|
|
|
void QMLManager::commitChanges(QString diveId, QString date, QString location, QString gps, QString duration, QString depth,
|
|
|
|
QString airtemp, QString watertemp, QString suit, QString buddy, QString diveMaster, QString weight, QString notes,
|
|
|
|
QString startpressure, QString endpressure, QString gasmix)
|
2015-07-17 15:28:01 +00:00
|
|
|
{
|
2016-01-28 22:00:52 +00:00
|
|
|
#define DROP_EMPTY_PLACEHOLDER(_s) if ((_s) == QLatin1Literal("--")) (_s).clear()
|
|
|
|
|
|
|
|
DROP_EMPTY_PLACEHOLDER(location);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(duration);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(depth);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(airtemp);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(watertemp);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(suit);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(buddy);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(diveMaster);
|
2016-02-06 06:54:47 +00:00
|
|
|
DROP_EMPTY_PLACEHOLDER(weight);
|
2016-02-13 17:34:31 +00:00
|
|
|
DROP_EMPTY_PLACEHOLDER(gasmix);
|
2016-02-09 16:20:17 +00:00
|
|
|
DROP_EMPTY_PLACEHOLDER(startpressure);
|
|
|
|
DROP_EMPTY_PLACEHOLDER(endpressure);
|
2016-01-28 22:00:52 +00:00
|
|
|
DROP_EMPTY_PLACEHOLDER(notes);
|
|
|
|
|
|
|
|
#undef DROP_EMPTY_PLACEHOLDER
|
|
|
|
|
2015-07-17 15:28:01 +00:00
|
|
|
struct dive *d = get_dive_by_uniq_id(diveId.toInt());
|
2016-01-08 06:30:58 +00:00
|
|
|
// notes comes back as rich text - let's convert this into plain text
|
|
|
|
QTextDocument doc;
|
|
|
|
doc.setHtml(notes);
|
|
|
|
notes = doc.toPlainText();
|
2015-12-27 05:24:29 +00:00
|
|
|
|
|
|
|
if (!d) {
|
|
|
|
qDebug() << "don't touch this... no dive";
|
2016-02-28 14:43:54 +00:00
|
|
|
return;
|
2015-12-27 05:24:29 +00:00
|
|
|
}
|
2015-07-17 15:28:01 +00:00
|
|
|
bool diveChanged = false;
|
2016-01-06 06:57:40 +00:00
|
|
|
bool needResort = false;
|
2015-07-17 15:28:01 +00:00
|
|
|
|
2016-01-06 06:53:32 +00:00
|
|
|
if (date != get_dive_date_string(d->when)) {
|
2016-01-27 20:11:37 +00:00
|
|
|
diveChanged = needResort = true;
|
2016-01-06 06:53:32 +00:00
|
|
|
QDateTime newDate;
|
|
|
|
// what a pain - Qt will not parse dates if the day of the week is incorrect
|
|
|
|
// so if the user changed the date but didn't update the day of the week (most likely behavior, actually),
|
|
|
|
// we need to make sure we don't try to parse that
|
2016-01-26 15:02:42 +00:00
|
|
|
QString format(QString(prefs.date_format) + QChar(' ') + prefs.time_format);
|
|
|
|
if (format.contains(QLatin1String("ddd")) || format.contains(QLatin1String("dddd"))) {
|
|
|
|
QString dateFormatToDrop = format.contains(QLatin1String("ddd")) ? QStringLiteral("ddd") : QStringLiteral("dddd");
|
2016-01-06 06:53:32 +00:00
|
|
|
QDateTime ts;
|
|
|
|
QLocale loc = getLocale();
|
|
|
|
ts.setMSecsSinceEpoch(d->when * 1000L);
|
|
|
|
QString drop = loc.toString(ts.toUTC(), dateFormatToDrop);
|
|
|
|
format.replace(dateFormatToDrop, "");
|
|
|
|
date.replace(drop, "");
|
|
|
|
}
|
|
|
|
newDate = QDateTime::fromString(date, format);
|
2016-01-27 20:07:10 +00:00
|
|
|
if (newDate.isValid()) {
|
|
|
|
// stupid Qt... two digit years are always 19xx - WTF???
|
|
|
|
// so if adding a hundred years gets you into something before a year from now...
|
|
|
|
// add a hundred years.
|
|
|
|
if (newDate.addYears(100) < QDateTime::currentDateTime().addYears(1))
|
|
|
|
newDate = newDate.addYears(100);
|
2016-01-11 06:07:58 +00:00
|
|
|
d->dc.when = d->when = newDate.toMSecsSinceEpoch() / 1000 + gettimezoneoffset(newDate.toMSecsSinceEpoch() / 1000);
|
2016-01-27 20:07:10 +00:00
|
|
|
}
|
2016-01-06 06:53:32 +00:00
|
|
|
}
|
2015-12-27 06:57:47 +00:00
|
|
|
struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid);
|
|
|
|
char *locationtext = NULL;
|
|
|
|
if (ds)
|
|
|
|
locationtext = ds->name;
|
|
|
|
if (!same_string(locationtext, qPrintable(location))) {
|
|
|
|
diveChanged = true;
|
|
|
|
// this is not ideal - and it's missing the gps information
|
|
|
|
// but for now let's just create a new dive site
|
|
|
|
ds = get_dive_site_by_uuid(create_dive_site(qPrintable(location), d->when));
|
|
|
|
d->dive_site_uuid = ds->uuid;
|
|
|
|
}
|
2016-01-27 14:29:14 +00:00
|
|
|
if (!gps.isEmpty()) {
|
|
|
|
QString gpsString = getCurrentPosition();
|
|
|
|
if (gpsString != QString("waiting for the next gps location")) {
|
|
|
|
qDebug() << "from commitChanges call to getCurrentPosition returns" << gpsString;
|
|
|
|
double lat, lon;
|
|
|
|
if (parseGpsText(qPrintable(gpsString), &lat, &lon)) {
|
|
|
|
struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid);
|
|
|
|
if (ds) {
|
|
|
|
ds->latitude.udeg = lat * 1000000;
|
|
|
|
ds->longitude.udeg = lon * 1000000;
|
|
|
|
} else {
|
|
|
|
degrees_t latData, lonData;
|
|
|
|
latData.udeg = lat;
|
|
|
|
lonData.udeg = lon;
|
|
|
|
d->dive_site_uuid = create_dive_site_with_gps("new site", latData, lonData, d->when);
|
|
|
|
}
|
|
|
|
qDebug() << "set up dive site with new GPS data";
|
2016-01-02 01:23:29 +00:00
|
|
|
}
|
2016-01-27 14:29:14 +00:00
|
|
|
} else {
|
|
|
|
qDebug() << "still don't have a position - will need to implement some sort of callback";
|
2016-01-02 01:23:29 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-01 08:23:15 +00:00
|
|
|
if (get_dive_duration_string(d->duration.seconds, tr("h:"), tr("min")) != duration) {
|
|
|
|
diveChanged = true;
|
|
|
|
int h = 0, m = 0, s = 0;
|
2016-02-06 20:07:42 +00:00
|
|
|
QRegExp r1(QStringLiteral("(\\d*)\\s*%1[\\s,:]*(\\d*)\\s*%2[\\s,:]*(\\d*)\\s*%3").arg(tr("h")).arg(tr("min")).arg(tr("sec")), Qt::CaseInsensitive);
|
|
|
|
QRegExp r2(QStringLiteral("(\\d*)\\s*%1[\\s,:]*(\\d*)\\s*%2").arg(tr("h")).arg(tr("min")), Qt::CaseInsensitive);
|
|
|
|
QRegExp r3(QStringLiteral("(\\d*)\\s*%1").arg(tr("min")), Qt::CaseInsensitive);
|
2016-01-26 15:02:42 +00:00
|
|
|
QRegExp r4(QStringLiteral("(\\d*):(\\d*):(\\d*)"));
|
|
|
|
QRegExp r5(QStringLiteral("(\\d*):(\\d*)"));
|
2016-02-09 21:00:56 +00:00
|
|
|
QRegExp r6(QStringLiteral("(\\d*)"));
|
2016-01-01 08:23:15 +00:00
|
|
|
if (r1.indexIn(duration) >= 0) {
|
|
|
|
h = r1.cap(1).toInt();
|
|
|
|
m = r1.cap(2).toInt();
|
|
|
|
s = r1.cap(3).toInt();
|
|
|
|
} else if (r2.indexIn(duration) >= 0) {
|
|
|
|
h = r2.cap(1).toInt();
|
|
|
|
m = r2.cap(2).toInt();
|
|
|
|
} else if (r3.indexIn(duration) >= 0) {
|
|
|
|
m = r3.cap(1).toInt();
|
|
|
|
} else if (r4.indexIn(duration) >= 0) {
|
|
|
|
h = r4.cap(1).toInt();
|
|
|
|
m = r4.cap(2).toInt();
|
|
|
|
s = r4.cap(3).toInt();
|
|
|
|
} else if (r5.indexIn(duration) >= 0) {
|
|
|
|
h = r5.cap(1).toInt();
|
|
|
|
m = r5.cap(2).toInt();
|
2016-02-09 21:00:56 +00:00
|
|
|
} else if (r6.indexIn(duration) >= 0) {
|
|
|
|
m = r6.cap(1).toInt();
|
2016-01-01 08:23:15 +00:00
|
|
|
}
|
2016-01-11 06:08:42 +00:00
|
|
|
d->dc.duration.seconds = d->duration.seconds = h * 3600 + m * 60 + s;
|
2016-03-02 14:28:00 +00:00
|
|
|
if (same_string(d->dc.model, "manually added dive")) {
|
|
|
|
free(d->dc.sample);
|
|
|
|
d->dc.sample = 0;
|
|
|
|
d->dc.samples = 0;
|
|
|
|
} else {
|
|
|
|
qDebug() << "changing the duration on a dive that wasn't manually added - Uh-oh";
|
|
|
|
}
|
|
|
|
|
2016-01-01 08:23:15 +00:00
|
|
|
}
|
2016-01-01 08:32:30 +00:00
|
|
|
if (get_depth_string(d->maxdepth.mm, true, true) != depth) {
|
2016-02-21 06:11:03 +00:00
|
|
|
int depthValue = parseLengthToMm(depth);
|
|
|
|
// the QML code should stop negative depth, but massively huge depth can make
|
|
|
|
// the profile extremely slow or even run out of memory and crash, so keep
|
|
|
|
// the depth <= 500m
|
|
|
|
if (0 <= depthValue && depthValue <= 500000) {
|
|
|
|
diveChanged = true;
|
|
|
|
d->maxdepth.mm = depthValue;
|
|
|
|
if (same_string(d->dc.model, "manually added dive")) {
|
|
|
|
d->dc.maxdepth.mm = d->maxdepth.mm;
|
|
|
|
free(d->dc.sample);
|
|
|
|
d->dc.sample = 0;
|
|
|
|
d->dc.samples = 0;
|
|
|
|
}
|
2016-02-15 15:51:23 +00:00
|
|
|
}
|
2016-01-01 08:32:30 +00:00
|
|
|
}
|
2016-01-20 21:56:28 +00:00
|
|
|
if (get_temperature_string(d->airtemp, true) != airtemp) {
|
2016-01-01 01:34:20 +00:00
|
|
|
diveChanged = true;
|
|
|
|
d->airtemp.mkelvin = parseTemperatureToMkelvin(airtemp);
|
|
|
|
}
|
2016-01-20 21:56:28 +00:00
|
|
|
if (get_temperature_string(d->watertemp, true) != watertemp) {
|
2016-01-01 01:34:20 +00:00
|
|
|
diveChanged = true;
|
|
|
|
d->watertemp.mkelvin = parseTemperatureToMkelvin(watertemp);
|
|
|
|
}
|
2016-02-06 06:54:47 +00:00
|
|
|
// not sure what we'd do if there was more than one weight system
|
|
|
|
// defined - for now just ignore that case
|
|
|
|
if (weightsystem_none((void *)&d->weightsystem[1])) {
|
|
|
|
if (get_weight_string(d->weightsystem[0].weight, true) != weight) {
|
|
|
|
diveChanged = true;
|
|
|
|
d->weightsystem[0].weight.grams = parseWeightToGrams(weight);
|
|
|
|
}
|
|
|
|
}
|
2016-02-28 14:43:54 +00:00
|
|
|
// start and end pressures for first cylinder only
|
2016-02-09 16:20:17 +00:00
|
|
|
if (get_pressure_string(d->cylinder[0].start, true) != startpressure || get_pressure_string(d->cylinder[0].end, true) != endpressure) {
|
|
|
|
diveChanged = true;
|
|
|
|
d->cylinder[0].start.mbar = parsePressureToMbar(startpressure);
|
|
|
|
d->cylinder[0].end.mbar = parsePressureToMbar(endpressure);
|
|
|
|
}
|
2016-02-13 17:34:31 +00:00
|
|
|
// gasmix for first cylinder
|
|
|
|
if (get_gas_string(d->cylinder[0].gasmix) != gasmix) {
|
2016-02-21 06:11:03 +00:00
|
|
|
int o2 = parseGasMixO2(gasmix);
|
|
|
|
int he = parseGasMixHE(gasmix);
|
|
|
|
// the QML code SHOULD only accept valid gas mixes, but just to make sure
|
|
|
|
if (o2 >= 0 && o2 <= 100 &&
|
|
|
|
he >= 0 && he <= 100 &&
|
|
|
|
o2 + he <= 100) {
|
|
|
|
diveChanged = true;
|
|
|
|
d->cylinder[0].gasmix.o2.permille = o2;
|
|
|
|
d->cylinder[0].gasmix.he.permille = he;
|
|
|
|
}
|
2016-02-13 17:34:31 +00:00
|
|
|
}
|
2015-12-27 06:57:47 +00:00
|
|
|
if (!same_string(d->suit, qPrintable(suit))) {
|
2015-07-17 15:28:01 +00:00
|
|
|
diveChanged = true;
|
|
|
|
free(d->suit);
|
2015-12-27 06:57:47 +00:00
|
|
|
d->suit = strdup(qPrintable(suit));
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
2015-12-27 06:57:47 +00:00
|
|
|
if (!same_string(d->buddy, qPrintable(buddy))) {
|
2015-07-17 15:28:01 +00:00
|
|
|
diveChanged = true;
|
|
|
|
free(d->buddy);
|
2015-12-27 06:57:47 +00:00
|
|
|
d->buddy = strdup(qPrintable(buddy));
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
2015-12-27 06:57:47 +00:00
|
|
|
if (!same_string(d->divemaster, qPrintable(diveMaster))) {
|
2015-07-17 15:28:01 +00:00
|
|
|
diveChanged = true;
|
|
|
|
free(d->divemaster);
|
2015-12-27 06:57:47 +00:00
|
|
|
d->divemaster = strdup(qPrintable(diveMaster));
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
2015-12-27 06:57:47 +00:00
|
|
|
if (!same_string(d->notes, qPrintable(notes))) {
|
2015-07-17 15:28:01 +00:00
|
|
|
diveChanged = true;
|
|
|
|
free(d->notes);
|
2015-12-27 06:57:47 +00:00
|
|
|
d->notes = strdup(qPrintable(notes));
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
2016-03-02 12:52:44 +00:00
|
|
|
// now that we have it all figured out, let's see what we need
|
|
|
|
// to update
|
|
|
|
DiveListModel *dm = DiveListModel::instance();
|
|
|
|
int oldModelIdx = dm->getDiveIdx(d->id);
|
2016-01-27 20:11:37 +00:00
|
|
|
int oldIdx = get_idx_by_uniq_id(d->id);
|
|
|
|
if (needResort) {
|
|
|
|
// we know that the only thing that might happen in a resort is that
|
|
|
|
// this one dive moves to a different spot in the dive list
|
2016-01-06 06:57:40 +00:00
|
|
|
sort_table(&dive_table);
|
2016-01-27 20:11:37 +00:00
|
|
|
int newIdx = get_idx_by_uniq_id(d->id);
|
|
|
|
if (newIdx != oldIdx) {
|
|
|
|
DiveObjectHelper *newDive = new DiveObjectHelper(d);
|
2016-03-02 12:52:44 +00:00
|
|
|
DiveListModel::instance()->removeDive(oldModelIdx);
|
|
|
|
DiveListModel::instance()->insertDive(oldModelIdx - (newIdx - oldIdx), newDive);
|
2016-01-27 20:11:37 +00:00
|
|
|
diveChanged = false; // because we already modified things
|
|
|
|
}
|
|
|
|
}
|
2016-02-20 15:33:05 +00:00
|
|
|
if (diveChanged) {
|
|
|
|
if (d->maxdepth.mm == d->dc.maxdepth.mm &&
|
|
|
|
d->maxdepth.mm > 0 &&
|
|
|
|
same_string(d->dc.model, "manually added dive") &&
|
|
|
|
d->dc.samples == 0) {
|
|
|
|
// so we have depth > 0, a manually added dive and no samples
|
|
|
|
// let's create an actual profile so the desktop version can work it
|
|
|
|
// first clear out the mean depth (or the fake_dc() function tries
|
|
|
|
// to be too clever
|
|
|
|
d->meandepth.mm = d->dc.meandepth.mm = 0;
|
2016-02-20 17:36:14 +00:00
|
|
|
d->dc = *fake_dc(&d->dc, true);
|
2016-02-20 15:33:05 +00:00
|
|
|
}
|
2016-03-02 12:52:44 +00:00
|
|
|
DiveListModel::instance()->updateDive(oldModelIdx, d);
|
2016-02-20 15:33:05 +00:00
|
|
|
}
|
2016-01-06 06:57:40 +00:00
|
|
|
if (diveChanged || needResort) {
|
2015-11-19 03:26:07 +00:00
|
|
|
mark_divelist_changed(true);
|
2016-01-11 05:40:03 +00:00
|
|
|
// this is called "commit" for a reason - when the user saves an
|
|
|
|
// edit they have a reasonable expectation that their data is actually
|
|
|
|
// stored - so we need to store this to the local cache
|
|
|
|
qDebug() << "save dives to local cache";
|
|
|
|
prefs.cloud_background_sync = false;
|
2016-02-13 06:14:17 +00:00
|
|
|
prefs.git_local_only = true;
|
2016-01-11 05:40:03 +00:00
|
|
|
saveChanges();
|
|
|
|
prefs.cloud_background_sync = true;
|
2016-02-13 06:14:17 +00:00
|
|
|
prefs.git_local_only = false;
|
2015-12-08 06:24:56 +00:00
|
|
|
}
|
2015-07-17 15:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::saveChanges()
|
|
|
|
{
|
2015-12-03 02:49:02 +00:00
|
|
|
if (!loadFromCloud()) {
|
2015-12-03 23:59:40 +00:00
|
|
|
appendTextToLog("Don't save dives without loading from the cloud, first.");
|
2015-12-03 02:49:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-12-03 23:59:40 +00:00
|
|
|
appendTextToLog("Saving dives.");
|
2015-07-17 15:28:01 +00:00
|
|
|
QString fileName;
|
|
|
|
if (getCloudURL(fileName)) {
|
2015-08-19 07:17:52 +00:00
|
|
|
appendTextToLog(get_error_string());
|
2015-07-17 15:28:01 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-03 14:33:00 +00:00
|
|
|
setAccessingCloud(true);
|
2015-07-17 15:28:01 +00:00
|
|
|
if (save_dives(fileName.toUtf8().data())) {
|
2015-08-19 07:17:52 +00:00
|
|
|
appendTextToLog(get_error_string());
|
2016-03-03 14:33:00 +00:00
|
|
|
setAccessingCloud(false);
|
2015-07-17 15:28:01 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-03-03 14:33:00 +00:00
|
|
|
setAccessingCloud(false);
|
2016-02-23 12:39:40 +00:00
|
|
|
appendTextToLog("Updated dive list saved.");
|
2015-07-17 15:28:01 +00:00
|
|
|
set_filename(fileName.toUtf8().data(), true);
|
|
|
|
mark_divelist_changed(false);
|
2015-07-10 08:31:24 +00:00
|
|
|
}
|
2015-08-10 05:35:47 +00:00
|
|
|
|
2016-02-29 14:53:26 +00:00
|
|
|
void QMLManager::undoDelete(int id)
|
|
|
|
{
|
|
|
|
if (!deletedDive || deletedDive->id != id) {
|
|
|
|
qDebug() << "can't find the deleted dive";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (deletedTrip)
|
|
|
|
insert_trip(&deletedTrip);
|
|
|
|
if (deletedDive->divetrip) {
|
|
|
|
struct dive_trip *trip = deletedDive->divetrip;
|
|
|
|
tripflag_t tripflag = deletedDive->tripflag; // this gets overwritten in add_dive_to_trip()
|
|
|
|
deletedDive->divetrip = NULL;
|
|
|
|
deletedDive->next = NULL;
|
|
|
|
deletedDive->pprev = NULL;
|
|
|
|
add_dive_to_trip(deletedDive, trip);
|
|
|
|
deletedDive->tripflag = tripflag;
|
|
|
|
}
|
|
|
|
record_dive(deletedDive);
|
|
|
|
DiveListModel::instance()->addDive(deletedDive);
|
|
|
|
prefs.cloud_background_sync = false;
|
|
|
|
prefs.git_local_only = true;
|
|
|
|
saveChanges();
|
|
|
|
prefs.cloud_background_sync = true;
|
|
|
|
prefs.git_local_only = false;
|
|
|
|
deletedDive = NULL;
|
|
|
|
deletedTrip = NULL;
|
|
|
|
}
|
|
|
|
|
2016-02-23 12:39:40 +00:00
|
|
|
void QMLManager::deleteDive(int id)
|
|
|
|
{
|
|
|
|
struct dive *d = get_dive_by_uniq_id(id);
|
|
|
|
if (!d) {
|
|
|
|
qDebug() << "oops, trying to delete non-existing dive";
|
|
|
|
return;
|
|
|
|
}
|
2016-02-29 14:53:26 +00:00
|
|
|
// clean up (or create) the storage for the deleted dive and trip (if applicable)
|
|
|
|
if (!deletedDive)
|
|
|
|
deletedDive = alloc_dive();
|
|
|
|
else
|
|
|
|
clear_dive(deletedDive);
|
|
|
|
copy_dive(d, deletedDive);
|
|
|
|
if (!deletedTrip) {
|
|
|
|
deletedTrip = (struct dive_trip *)calloc(1, sizeof(struct dive_trip));
|
|
|
|
} else {
|
|
|
|
free(deletedTrip->location);
|
|
|
|
free(deletedTrip->notes);
|
|
|
|
memset(deletedTrip, 0, sizeof(struct dive_trip));
|
|
|
|
}
|
|
|
|
// if this is the last dive in that trip, remember the trip as well
|
|
|
|
if (d->divetrip && d->divetrip->nrdives == 1) {
|
|
|
|
deletedTrip = (struct dive_trip *)calloc(1, sizeof(struct dive_trip));
|
|
|
|
*deletedTrip = *d->divetrip;
|
|
|
|
deletedTrip->location = copy_string(d->divetrip->location);
|
|
|
|
deletedTrip->notes = copy_string(d->divetrip->notes);
|
|
|
|
deletedTrip->nrdives = 0;
|
|
|
|
deletedDive->divetrip = deletedTrip;
|
|
|
|
}
|
2016-02-23 12:39:40 +00:00
|
|
|
DiveListModel::instance()->removeDiveById(id);
|
|
|
|
delete_single_dive(get_idx_by_uniq_id(id));
|
|
|
|
prefs.cloud_background_sync = false;
|
|
|
|
prefs.git_local_only = true;
|
|
|
|
saveChanges();
|
|
|
|
prefs.cloud_background_sync = true;
|
|
|
|
prefs.git_local_only = false;
|
|
|
|
}
|
|
|
|
|
2015-12-27 05:37:18 +00:00
|
|
|
QString QMLManager::addDive()
|
2015-08-10 05:35:47 +00:00
|
|
|
{
|
2015-08-19 07:17:52 +00:00
|
|
|
appendTextToLog("Adding new dive.");
|
2015-12-27 05:37:18 +00:00
|
|
|
return DiveListModel::instance()->startAddDive();
|
2015-08-10 05:35:47 +00:00
|
|
|
}
|
|
|
|
|
2016-01-29 14:25:13 +00:00
|
|
|
void QMLManager::addDiveAborted(int id)
|
|
|
|
{
|
|
|
|
DiveListModel::instance()->removeDiveById(id);
|
|
|
|
}
|
|
|
|
|
2016-01-02 01:23:29 +00:00
|
|
|
QString QMLManager::getCurrentPosition()
|
|
|
|
{
|
|
|
|
return locationProvider->currentPosition();
|
|
|
|
}
|
|
|
|
|
2015-11-13 04:23:00 +00:00
|
|
|
void QMLManager::applyGpsData()
|
|
|
|
{
|
2016-01-11 03:34:21 +00:00
|
|
|
if (locationProvider->applyLocations())
|
|
|
|
refreshDiveList();
|
2015-11-13 04:23:00 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 01:21:43 +00:00
|
|
|
void QMLManager::sendGpsData()
|
|
|
|
{
|
|
|
|
locationProvider->uploadToServer();
|
|
|
|
}
|
|
|
|
|
2016-01-08 05:37:36 +00:00
|
|
|
void QMLManager::downloadGpsData()
|
|
|
|
{
|
|
|
|
locationProvider->downloadFromServer();
|
2016-01-08 15:11:49 +00:00
|
|
|
populateGpsData();
|
2016-01-08 05:37:36 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 05:40:15 +00:00
|
|
|
void QMLManager::populateGpsData()
|
|
|
|
{
|
2016-01-08 15:11:49 +00:00
|
|
|
if (GpsListModel::instance())
|
|
|
|
GpsListModel::instance()->update();
|
2016-01-08 05:40:15 +00:00
|
|
|
}
|
|
|
|
|
2015-11-14 01:20:45 +00:00
|
|
|
void QMLManager::clearGpsData()
|
|
|
|
{
|
|
|
|
locationProvider->clearGpsData();
|
2016-01-08 15:11:49 +00:00
|
|
|
populateGpsData();
|
2015-11-14 01:20:45 +00:00
|
|
|
}
|
|
|
|
|
2016-01-09 07:18:41 +00:00
|
|
|
void QMLManager::deleteGpsFix(quint64 when)
|
|
|
|
{
|
|
|
|
locationProvider->deleteGpsFix(when);
|
|
|
|
populateGpsData();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-19 07:17:52 +00:00
|
|
|
QString QMLManager::logText() const
|
|
|
|
{
|
2015-11-13 17:17:13 +00:00
|
|
|
QString logText = m_logText + QString("\nNumer of GPS fixes: %1").arg(locationProvider->getGpsNum());
|
|
|
|
return logText;
|
2015-08-19 07:17:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setLogText(const QString &logText)
|
|
|
|
{
|
|
|
|
m_logText = logText;
|
2015-08-20 09:08:59 +00:00
|
|
|
emit logTextChanged();
|
2015-08-19 07:17:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::appendTextToLog(const QString &newText)
|
|
|
|
{
|
|
|
|
m_logText += "\n" + newText;
|
2015-08-20 09:08:59 +00:00
|
|
|
emit logTextChanged();
|
2015-08-19 07:17:52 +00:00
|
|
|
}
|
|
|
|
|
2015-07-21 08:57:10 +00:00
|
|
|
bool QMLManager::saveCloudPassword() const
|
|
|
|
{
|
|
|
|
return m_saveCloudPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setSaveCloudPassword(bool saveCloudPassword)
|
|
|
|
{
|
|
|
|
m_saveCloudPassword = saveCloudPassword;
|
|
|
|
}
|
|
|
|
|
2015-11-11 20:34:56 +00:00
|
|
|
bool QMLManager::locationServiceEnabled() const
|
|
|
|
{
|
|
|
|
return m_locationServiceEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setLocationServiceEnabled(bool locationServiceEnabled)
|
|
|
|
{
|
|
|
|
m_locationServiceEnabled = locationServiceEnabled;
|
|
|
|
locationProvider->serviceEnable(m_locationServiceEnabled);
|
|
|
|
}
|
2015-07-10 08:31:24 +00:00
|
|
|
|
2015-12-20 02:41:10 +00:00
|
|
|
bool QMLManager::verboseEnabled() const
|
|
|
|
{
|
|
|
|
return m_verboseEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setVerboseEnabled(bool verboseMode)
|
|
|
|
{
|
|
|
|
m_verboseEnabled = verboseMode;
|
|
|
|
verbose = verboseMode;
|
|
|
|
qDebug() << "verbose is" << verbose;
|
|
|
|
emit verboseEnabledChanged();
|
|
|
|
}
|
|
|
|
|
2015-07-10 07:47:26 +00:00
|
|
|
QString QMLManager::cloudPassword() const
|
|
|
|
{
|
|
|
|
return m_cloudPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setCloudPassword(const QString &cloudPassword)
|
|
|
|
{
|
|
|
|
m_cloudPassword = cloudPassword;
|
|
|
|
emit cloudPasswordChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QMLManager::cloudUserName() const
|
|
|
|
{
|
|
|
|
return m_cloudUserName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setCloudUserName(const QString &cloudUserName)
|
|
|
|
{
|
|
|
|
m_cloudUserName = cloudUserName;
|
|
|
|
emit cloudUserNameChanged();
|
|
|
|
}
|
2015-11-14 01:14:22 +00:00
|
|
|
|
2015-11-14 17:10:06 +00:00
|
|
|
int QMLManager::distanceThreshold() const
|
|
|
|
{
|
|
|
|
return m_distanceThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setDistanceThreshold(int distance)
|
|
|
|
{
|
|
|
|
m_distanceThreshold = distance;
|
|
|
|
emit distanceThresholdChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
int QMLManager::timeThreshold() const
|
|
|
|
{
|
|
|
|
return m_timeThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setTimeThreshold(int time)
|
|
|
|
{
|
|
|
|
m_timeThreshold = time;
|
|
|
|
emit timeThresholdChanged();
|
|
|
|
}
|
2015-12-03 02:49:02 +00:00
|
|
|
|
|
|
|
bool QMLManager::loadFromCloud() const
|
|
|
|
{
|
|
|
|
return m_loadFromCloud;
|
|
|
|
}
|
|
|
|
|
2016-02-08 19:08:49 +00:00
|
|
|
void QMLManager::syncLoadFromCloud()
|
|
|
|
{
|
|
|
|
QSettings s;
|
|
|
|
QString cloudMarker = QLatin1Literal("loadFromCloud") + QString(prefs.cloud_storage_email);
|
|
|
|
m_loadFromCloud = s.contains(cloudMarker) && s.value(cloudMarker).toBool();
|
|
|
|
}
|
|
|
|
|
2015-12-03 02:49:02 +00:00
|
|
|
void QMLManager::setLoadFromCloud(bool done)
|
|
|
|
{
|
2016-01-11 05:38:44 +00:00
|
|
|
QSettings s;
|
2016-02-08 19:08:49 +00:00
|
|
|
QString cloudMarker = QLatin1Literal("loadFromCloud") + QString(prefs.cloud_storage_email);
|
|
|
|
s.setValue(cloudMarker, done);
|
2015-12-03 02:49:02 +00:00
|
|
|
m_loadFromCloud = done;
|
|
|
|
emit loadFromCloudChanged();
|
|
|
|
}
|
2015-12-15 07:00:19 +00:00
|
|
|
|
|
|
|
QString QMLManager::startPageText() const
|
|
|
|
{
|
|
|
|
return m_startPageText;
|
|
|
|
}
|
|
|
|
|
2016-01-26 15:02:42 +00:00
|
|
|
void QMLManager::setStartPageText(const QString& text)
|
2015-12-15 07:00:19 +00:00
|
|
|
{
|
|
|
|
m_startPageText = text;
|
|
|
|
emit startPageTextChanged();
|
|
|
|
}
|
2015-12-26 21:22:50 +00:00
|
|
|
|
2016-02-11 01:45:23 +00:00
|
|
|
// this is an enum, but I don't know how to do enums in QML
|
|
|
|
QMLManager::credentialStatus_t QMLManager::credentialStatus() const
|
|
|
|
{
|
|
|
|
return m_credentialStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setCredentialStatus(const credentialStatus_t value)
|
|
|
|
{
|
|
|
|
if (m_credentialStatus != value) {
|
|
|
|
m_credentialStatus = value;
|
|
|
|
emit credentialStatusChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-26 15:02:42 +00:00
|
|
|
void QMLManager::showMap(const QString& location)
|
2015-12-26 21:22:50 +00:00
|
|
|
{
|
|
|
|
if (!location.isEmpty()) {
|
2016-01-02 06:24:05 +00:00
|
|
|
QString link = QString("https://www.google.com/maps/place/%1/@%2,5000m/data=!3m1!1e3!4m2!3m1!1s0x0:0x0")
|
2016-01-11 14:14:45 +00:00
|
|
|
.arg(location)
|
|
|
|
.arg(location);
|
2015-12-26 21:22:50 +00:00
|
|
|
QDesktopServices::openUrl(link);
|
|
|
|
}
|
|
|
|
}
|
2015-12-27 04:02:23 +00:00
|
|
|
|
2016-03-02 12:41:36 +00:00
|
|
|
// where in the QML dive list is that dive?
|
|
|
|
int QMLManager::getIndex(const QString &diveId)
|
|
|
|
{
|
|
|
|
int dive_id = diveId.toInt();
|
|
|
|
int idx = DiveListModel::instance()->getDiveIdx(dive_id);
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2016-01-26 15:02:42 +00:00
|
|
|
QString QMLManager::getNumber(const QString& diveId)
|
2015-12-27 04:02:23 +00:00
|
|
|
{
|
|
|
|
int dive_id = diveId.toInt();
|
|
|
|
struct dive *d = get_dive_by_uniq_id(dive_id);
|
|
|
|
QString number;
|
|
|
|
if (d)
|
|
|
|
number = QString::number(d->number);
|
|
|
|
return number;
|
|
|
|
}
|
|
|
|
|
2016-01-26 15:02:42 +00:00
|
|
|
QString QMLManager::getDate(const QString& diveId)
|
2015-12-27 04:02:23 +00:00
|
|
|
{
|
|
|
|
int dive_id = diveId.toInt();
|
|
|
|
struct dive *d = get_dive_by_uniq_id(dive_id);
|
|
|
|
QString datestring;
|
|
|
|
if (d)
|
|
|
|
datestring = get_dive_date_string(d->when);
|
|
|
|
return datestring;
|
|
|
|
}
|
2016-02-10 20:53:58 +00:00
|
|
|
|
|
|
|
QString QMLManager::getVersion() const
|
|
|
|
{
|
2016-03-05 20:53:38 +00:00
|
|
|
QRegExp versionRe(".*:([()\\.,\\d]+).*");
|
2016-02-10 20:53:58 +00:00
|
|
|
if (!versionRe.exactMatch(getUserAgent()))
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
return versionRe.cap(1);
|
|
|
|
}
|
2016-03-03 01:13:42 +00:00
|
|
|
|
|
|
|
bool QMLManager::accessingCloud() const
|
|
|
|
{
|
|
|
|
return m_accessingCloud;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::setAccessingCloud(bool status)
|
|
|
|
{
|
|
|
|
m_accessingCloud = status;
|
|
|
|
emit accessingCloudChanged();
|
|
|
|
}
|
2016-03-09 03:31:05 +00:00
|
|
|
|
|
|
|
qreal QMLManager::lastDevicePixelRatio()
|
|
|
|
{
|
|
|
|
return m_lastDevicePixelRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QMLManager::screenChanged(QScreen *screen)
|
|
|
|
{
|
|
|
|
m_lastDevicePixelRatio = screen->devicePixelRatio();
|
|
|
|
emit sendScreenChanged(screen);
|
|
|
|
}
|