mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Merge branch 'offlineDefault'
This commit is contained in:
commit
241dd7cb81
18 changed files with 327 additions and 77 deletions
|
@ -16,6 +16,7 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:screenOrientation="unspecified" >
|
android:screenOrientation="unspecified" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
|
@ -485,7 +485,7 @@ int parse_file(const char *filename)
|
||||||
/* opening the cloud storage repository failed for some reason
|
/* opening the cloud storage repository failed for some reason
|
||||||
* give up here and don't send errors about git repositories */
|
* give up here and don't send errors about git repositories */
|
||||||
free(current_sha);
|
free(current_sha);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
/* if this is a git repository, do we already have this exact state loaded ?
|
/* if this is a git repository, do we already have this exact state loaded ?
|
||||||
* get the SHA and compare with what we currently have */
|
* get the SHA and compare with what we currently have */
|
||||||
|
|
|
@ -450,6 +450,11 @@ static int try_to_update(git_repository *repo, git_remote *origin, git_reference
|
||||||
return report_error("Unable to get local or remote SHA1");
|
return report_error("Unable to get local or remote SHA1");
|
||||||
}
|
}
|
||||||
if (git_merge_base(&base, repo, local_id, remote_id)) {
|
if (git_merge_base(&base, repo, local_id, remote_id)) {
|
||||||
|
// TODO:
|
||||||
|
// if they have no merge base, they actually are different repos
|
||||||
|
// so instead merge this as merging a commit into a repo - git_merge() appears to do that
|
||||||
|
// but needs testing and cleanup afterwards
|
||||||
|
//
|
||||||
if (is_subsurface_cloud)
|
if (is_subsurface_cloud)
|
||||||
goto cloud_data_error;
|
goto cloud_data_error;
|
||||||
else
|
else
|
||||||
|
@ -940,3 +945,17 @@ struct git_repository *is_git_repository(const char *filename, const char **bran
|
||||||
*branchp = branch;
|
*branchp = branch;
|
||||||
return repo;
|
return repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_create_local_repo(const char *filename)
|
||||||
|
{
|
||||||
|
git_repository *repo;
|
||||||
|
char *path = strdup(filename);
|
||||||
|
char *branch = strchr(path, '[');
|
||||||
|
if (branch)
|
||||||
|
*branch = '\0';
|
||||||
|
int ret = git_repository_init(&repo, path, false);
|
||||||
|
free(path);
|
||||||
|
if (ret != 0)
|
||||||
|
(void)report_error("Create local repo failed with error code %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern void set_git_id(const struct git_oid *);
|
||||||
void set_git_update_cb(int(*)(bool, const char *));
|
void set_git_update_cb(int(*)(bool, const char *));
|
||||||
int git_storage_update_progress(bool reset, const char *text);
|
int git_storage_update_progress(bool reset, const char *text);
|
||||||
char *get_local_dir(const char *remote, const char *branch);
|
char *get_local_dir(const char *remote, const char *branch);
|
||||||
|
int git_create_local_repo(const char *filename);
|
||||||
|
|
||||||
extern int last_git_storage_update_val;
|
extern int last_git_storage_update_val;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
|
char *settings_suffix = NULL;
|
||||||
|
|
||||||
void init_qt_late()
|
void init_qt_late()
|
||||||
{
|
{
|
||||||
QApplication *application = qApp;
|
QApplication *application = qApp;
|
||||||
|
@ -19,7 +21,14 @@ void init_qt_late()
|
||||||
|
|
||||||
QCoreApplication::setOrganizationName("Subsurface");
|
QCoreApplication::setOrganizationName("Subsurface");
|
||||||
QCoreApplication::setOrganizationDomain("subsurface.hohndel.org");
|
QCoreApplication::setOrganizationDomain("subsurface.hohndel.org");
|
||||||
|
// enable user specific settings (based on command line argument)
|
||||||
|
if (settings_suffix) {
|
||||||
|
if (verbose)
|
||||||
|
qDebug() << "using custom config for" << QString("Subsurface-%1").arg(settings_suffix);
|
||||||
|
QCoreApplication::setApplicationName(QString("Subsurface-%1").arg(settings_suffix));
|
||||||
|
} else {
|
||||||
QCoreApplication::setApplicationName("Subsurface");
|
QCoreApplication::setApplicationName("Subsurface");
|
||||||
|
}
|
||||||
// find plugins installed in the application directory (without this SVGs don't work on Windows)
|
// find plugins installed in the application directory (without this SVGs don't work on Windows)
|
||||||
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
|
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
|
||||||
QLocale loc;
|
QLocale loc;
|
||||||
|
|
|
@ -1315,6 +1315,7 @@ int GeneralSettingsObjectWrapper::pscrRatio() const
|
||||||
void GeneralSettingsObjectWrapper::setDefaultFilename(const QString& value)
|
void GeneralSettingsObjectWrapper::setDefaultFilename(const QString& value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("default_filename", value);
|
s.setValue("default_filename", value);
|
||||||
prefs.default_filename = copy_string(qPrintable(value));
|
prefs.default_filename = copy_string(qPrintable(value));
|
||||||
emit defaultFilenameChanged(value);
|
emit defaultFilenameChanged(value);
|
||||||
|
@ -1323,6 +1324,7 @@ void GeneralSettingsObjectWrapper::setDefaultFilename(const QString& value)
|
||||||
void GeneralSettingsObjectWrapper::setDefaultCylinder(const QString& value)
|
void GeneralSettingsObjectWrapper::setDefaultCylinder(const QString& value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("default_cylinder", value);
|
s.setValue("default_cylinder", value);
|
||||||
prefs.default_cylinder = copy_string(qPrintable(value));
|
prefs.default_cylinder = copy_string(qPrintable(value));
|
||||||
emit defaultCylinderChanged(value);
|
emit defaultCylinderChanged(value);
|
||||||
|
@ -1331,6 +1333,7 @@ void GeneralSettingsObjectWrapper::setDefaultCylinder(const QString& value)
|
||||||
void GeneralSettingsObjectWrapper::setDefaultFileBehavior(short value)
|
void GeneralSettingsObjectWrapper::setDefaultFileBehavior(short value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("default_file_behavior", value);
|
s.setValue("default_file_behavior", value);
|
||||||
prefs.default_file_behavior = value;
|
prefs.default_file_behavior = value;
|
||||||
if (prefs.default_file_behavior == UNDEFINED_DEFAULT_FILE) {
|
if (prefs.default_file_behavior == UNDEFINED_DEFAULT_FILE) {
|
||||||
|
@ -1347,6 +1350,7 @@ void GeneralSettingsObjectWrapper::setDefaultFileBehavior(short value)
|
||||||
void GeneralSettingsObjectWrapper::setUseDefaultFile(bool value)
|
void GeneralSettingsObjectWrapper::setUseDefaultFile(bool value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("use_default_file", value);
|
s.setValue("use_default_file", value);
|
||||||
prefs.use_default_file = value;
|
prefs.use_default_file = value;
|
||||||
emit useDefaultFileChanged(value);
|
emit useDefaultFileChanged(value);
|
||||||
|
@ -1355,6 +1359,7 @@ void GeneralSettingsObjectWrapper::setUseDefaultFile(bool value)
|
||||||
void GeneralSettingsObjectWrapper::setDefaultSetPoint(int value)
|
void GeneralSettingsObjectWrapper::setDefaultSetPoint(int value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("defaultsetpoint", value);
|
s.setValue("defaultsetpoint", value);
|
||||||
prefs.defaultsetpoint = value;
|
prefs.defaultsetpoint = value;
|
||||||
emit defaultSetPointChanged(value);
|
emit defaultSetPointChanged(value);
|
||||||
|
@ -1363,6 +1368,7 @@ void GeneralSettingsObjectWrapper::setDefaultSetPoint(int value)
|
||||||
void GeneralSettingsObjectWrapper::setO2Consumption(int value)
|
void GeneralSettingsObjectWrapper::setO2Consumption(int value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("o2consumption", value);
|
s.setValue("o2consumption", value);
|
||||||
prefs.o2consumption = value;
|
prefs.o2consumption = value;
|
||||||
emit o2ConsumptionChanged(value);
|
emit o2ConsumptionChanged(value);
|
||||||
|
@ -1371,6 +1377,7 @@ void GeneralSettingsObjectWrapper::setO2Consumption(int value)
|
||||||
void GeneralSettingsObjectWrapper::setPscrRatio(int value)
|
void GeneralSettingsObjectWrapper::setPscrRatio(int value)
|
||||||
{
|
{
|
||||||
QSettings s;
|
QSettings s;
|
||||||
|
s.beginGroup(group);
|
||||||
s.setValue("pscr_ratio", value);
|
s.setValue("pscr_ratio", value);
|
||||||
prefs.pscr_ratio = value;
|
prefs.pscr_ratio = value;
|
||||||
emit pscrRatioChanged(value);
|
emit pscrRatioChanged(value);
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
struct preferences prefs, informational_prefs;
|
struct preferences prefs, informational_prefs;
|
||||||
struct preferences default_prefs = {
|
struct preferences default_prefs = {
|
||||||
.cloud_base_url = "https://cloud.subsurface-divelog.org/",
|
.cloud_base_url = "https://cloud.subsurface-divelog.org/",
|
||||||
|
#if defined(SUBSURFACE_MOBILE)
|
||||||
|
.git_local_only = true,
|
||||||
|
#endif
|
||||||
.units = SI_UNITS,
|
.units = SI_UNITS,
|
||||||
.unit_system = METRIC,
|
.unit_system = METRIC,
|
||||||
.coordinates_traditional = true,
|
.coordinates_traditional = true,
|
||||||
|
@ -197,6 +200,11 @@ void parse_argument(const char *arg)
|
||||||
continue;
|
continue;
|
||||||
case '-':
|
case '-':
|
||||||
/* long options with -- */
|
/* long options with -- */
|
||||||
|
/* first test for --user=bla which allows the use of user specific settings */
|
||||||
|
if (strncmp(arg, "--user=", sizeof("--user=") - 1) == 0) {
|
||||||
|
settings_suffix = strdup(arg + sizeof("--user=") - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (strcmp(arg, "--help") == 0) {
|
if (strcmp(arg, "--help") == 0) {
|
||||||
print_help();
|
print_help();
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -254,8 +262,10 @@ void setup_system_prefs(void)
|
||||||
subsurface_OS_pref_setup();
|
subsurface_OS_pref_setup();
|
||||||
default_prefs.divelist_font = strdup(system_divelist_default_font);
|
default_prefs.divelist_font = strdup(system_divelist_default_font);
|
||||||
default_prefs.font_size = system_divelist_default_font_size;
|
default_prefs.font_size = system_divelist_default_font_size;
|
||||||
default_prefs.default_filename = system_default_filename();
|
|
||||||
|
|
||||||
|
#if !defined(SUBSURFACE_MOBILE)
|
||||||
|
default_prefs.default_filename = system_default_filename();
|
||||||
|
#endif
|
||||||
env = getenv("LC_MEASUREMENT");
|
env = getenv("LC_MEASUREMENT");
|
||||||
if (!env)
|
if (!env)
|
||||||
env = getenv("LC_ALL");
|
env = getenv("LC_ALL");
|
||||||
|
|
|
@ -19,6 +19,8 @@ void free_prefs(void);
|
||||||
void copy_prefs(struct preferences *src, struct preferences *dest);
|
void copy_prefs(struct preferences *src, struct preferences *dest);
|
||||||
void print_files(void);
|
void print_files(void);
|
||||||
|
|
||||||
|
extern char *settings_suffix;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,17 @@ Item {
|
||||||
id: outerLayout
|
id: outerLayout
|
||||||
width: loginWindow.width - loginWindow.leftPadding - loginWindow.rightPadding - 2 * Kirigami.Units.gridUnit
|
width: loginWindow.width - loginWindow.leftPadding - loginWindow.rightPadding - 2 * Kirigami.Units.gridUnit
|
||||||
|
|
||||||
|
function goToNext() {
|
||||||
|
for (var i = 0; i < children.length; ++i)
|
||||||
|
if (children[i].focus) {
|
||||||
|
children[i].nextItemInFocusChain().forceActiveFocus()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: goToNext()
|
||||||
|
Keys.onTabPressed: goToNext()
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible && manager.accessingCloud < 0) {
|
if (visible && manager.accessingCloud < 0) {
|
||||||
manager.appendTextToLog("Credential scrn: show kbd was: " + (Qt.inputMethod.isVisible ? "visible" : "invisible"))
|
manager.appendTextToLog("Credential scrn: show kbd was: " + (Qt.inputMethod.isVisible ? "visible" : "invisible"))
|
||||||
|
|
|
@ -30,8 +30,6 @@ Kirigami.Page {
|
||||||
property alias gpsCheckbox: detailsEdit.gpsCheckbox
|
property alias gpsCheckbox: detailsEdit.gpsCheckbox
|
||||||
property int updateCurrentIdx: manager.updateSelectedDive
|
property int updateCurrentIdx: manager.updateSelectedDive
|
||||||
|
|
||||||
property bool contentItem: true // HACK to work around Kirigami issue - remove once that's addressed upstream
|
|
||||||
|
|
||||||
title: diveDetailsListView.currentItem ? diveDetailsListView.currentItem.modelData.dive.location : "Dive details"
|
title: diveDetailsListView.currentItem ? diveDetailsListView.currentItem.modelData.dive.location : "Dive details"
|
||||||
state: "view"
|
state: "view"
|
||||||
leftPadding: 0
|
leftPadding: 0
|
||||||
|
|
|
@ -211,18 +211,24 @@ Kirigami.ScrollablePage {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
id: startPageWrapper
|
id: startPageWrapper
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
opacity: (diveListView.count > 0 && (credentialStatus == QMLManager.VALID || credentialStatus == QMLManager.VALID_EMAIL)) ? 0 : 1
|
opacity: credentialStatus === QMLManager.NOCLOUD || (diveListView.count > 0 && (credentialStatus === QMLManager.VALID || credentialStatus === QMLManager.VALID_EMAIL)) ? 0 : 1
|
||||||
visible: opacity > 0
|
visible: opacity > 0
|
||||||
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
|
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
|
print("startPageWrapper onVisibleChanged credentialStatus " + credentialStatus + " diveListView.count " + diveListView.count)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
page.actions.main = page.saveAction
|
page.actions.main = page.saveAction
|
||||||
|
page.actions.right = page.offlineAction
|
||||||
title = "Cloud credentials"
|
title = "Cloud credentials"
|
||||||
} else if(manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL) {
|
} else if(manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD) {
|
||||||
page.actions.main = page.addDiveAction
|
page.actions.main = page.addDiveAction
|
||||||
|
page.actions.right = null
|
||||||
title = "Dive list"
|
title = "Dive list"
|
||||||
|
if (diveListView.count === 0)
|
||||||
|
showPassiveNotification(qsTr("Please tap the '+' button to add a dive"), 3000)
|
||||||
} else {
|
} else {
|
||||||
page.actions.main = null
|
page.actions.main = null
|
||||||
|
page.actions.right = null
|
||||||
title = "Dive list"
|
title = "Dive list"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,15 +285,25 @@ Kirigami.ScrollablePage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property QtObject offlineAction: Action {
|
||||||
|
iconName: "qrc:/qml/nocloud.svg"
|
||||||
|
onTriggered: {
|
||||||
|
manager.syncToCloud = false
|
||||||
|
manager.credentialStatus = QMLManager.NOCLOUD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onBackRequested: {
|
onBackRequested: {
|
||||||
if (startPageWrapper.visible && diveListView.count > 0 && manager.credentialStatus != QMLManager.INVALID) {
|
if (startPageWrapper.visible && diveListView.count > 0 && manager.credentialStatus !== QMLManager.INVALID) {
|
||||||
manager.credentialStatus = oldStatus
|
manager.credentialStatus = oldStatus
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
if (!startPageWrapper.visible) {
|
if (!startPageWrapper.visible) {
|
||||||
|
if (Qt.platform.os != "ios") {
|
||||||
manager.quit()
|
manager.quit()
|
||||||
// we shouldn't come back from there, but just in case
|
// we shouldn't come back from there, but just in case
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: Kirigami.Units.gridUnit
|
Layout.margins: Kirigami.Units.gridUnit
|
||||||
Layout.topMargin: Kirigami.Units.gridUnit * 3
|
Layout.topMargin: Kirigami.Units.gridUnit * 3
|
||||||
text: "In order to use Subsurface-mobile you need to have a Subsurface cloud storage account " +
|
text: "To use Subsurface-mobile with Subsurface cloud storage, please enter " +
|
||||||
"(which can be created with the Subsurface desktop application)."
|
"your cloud credentials.\n\n" +
|
||||||
|
"To use Subsurface-mobile only with local data on this device, tap " +
|
||||||
|
"on the no cloud icon below."
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
Kirigami.Label {
|
Kirigami.Label {
|
||||||
|
|
71
mobile-widgets/qml/icons/nocloud.svg
Normal file
71
mobile-widgets/qml/icons/nocloud.svg
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
viewBox="0 0 22 22"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="nocloud.svg">
|
||||||
|
<metadata
|
||||||
|
id="metadata10">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1022"
|
||||||
|
inkscape:window-height="740"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="10.727273"
|
||||||
|
inkscape:cx="-2.8898305"
|
||||||
|
inkscape:cy="11"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<defs
|
||||||
|
id="defs3051">
|
||||||
|
<style
|
||||||
|
type="text/css"
|
||||||
|
id="current-color-scheme">
|
||||||
|
.ColorScheme-Text {
|
||||||
|
color:#4d4d4d;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
style="fill:currentColor;fill-opacity:1;stroke:none"
|
||||||
|
d="M 11 4 A 6 6 0 0 0 5 10 A 6 6 0 0 0 5.0039062 10.128906 A 4 4 0 0 0 2 14 A 4 4 0 0 0 6 18 L 15 18 A 5 5 0 0 0 20 13 A 5 5 0 0 0 16.757812 8.3242188 A 6 6 0 0 0 11 4 z M 11 5 A 5 5 0 0 1 15.919922 9.1113281 A 4.0000019 4.0000019 0 0 1 19 13 A 4.0000019 4.0000019 0 0 1 15 17 L 6 17 A 2.9999979 2.9999979 0 0 1 3 14 A 2.9999979 2.9999979 0 0 1 6 11 A 2.9999979 2.9999979 0 0 1 6.1074219 11.005859 A 5 5 0 0 1 6 10 A 5 5 0 0 1 11 5 z "
|
||||||
|
class="ColorScheme-Text"
|
||||||
|
id="path6" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.20000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 4.0550844,20.042373 18.877119,4.0084751"
|
||||||
|
id="path3338-1"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:1"
|
||||||
|
d="M 3.8220339,19.855932 18.644068,3.8220339"
|
||||||
|
id="path3338"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
|
@ -124,7 +124,6 @@ Kirigami.ApplicationWindow {
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: "Manage dives"
|
text: "Manage dives"
|
||||||
enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL
|
|
||||||
/*
|
/*
|
||||||
* disable for the beta to avoid confusion
|
* disable for the beta to avoid confusion
|
||||||
Action {
|
Action {
|
||||||
|
@ -137,6 +136,7 @@ Kirigami.ApplicationWindow {
|
||||||
*/
|
*/
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: "Add dive manually"
|
text: "Add dive manually"
|
||||||
|
enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
returnTopPage() // otherwise odd things happen with the page stack
|
returnTopPage() // otherwise odd things happen with the page stack
|
||||||
startAddDive()
|
startAddDive()
|
||||||
|
@ -144,24 +144,34 @@ Kirigami.ApplicationWindow {
|
||||||
}
|
}
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: "Manual sync with cloud"
|
text: "Manual sync with cloud"
|
||||||
|
enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL || manager.credentialStatus === QMLManager.NOCLOUD
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
|
if (manager.credentialStatus === QMLManager.NOCLOUD) {
|
||||||
|
returnTopPage()
|
||||||
|
oldStatus = manager.credentialStatus
|
||||||
|
manager.startPageText = "Enter valid cloud storage credentials"
|
||||||
|
manager.credentialStatus = QMLManager.UNKNOWN
|
||||||
|
globalDrawer.close()
|
||||||
|
} else {
|
||||||
globalDrawer.close()
|
globalDrawer.close()
|
||||||
detailsWindow.endEditMode()
|
detailsWindow.endEditMode()
|
||||||
manager.saveChangesCloud(true);
|
manager.saveChangesCloud(true);
|
||||||
globalDrawer.close()
|
globalDrawer.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: syncToCloud ? "Disable auto cloud sync" : "Enable auto cloud sync"
|
text: syncToCloud ? "Offline mode" : "Enable auto cloud sync"
|
||||||
|
enabled: manager.credentialStatus !== QMLManager.NOCLOUD
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
syncToCloud = !syncToCloud
|
syncToCloud = !syncToCloud
|
||||||
if (!syncToCloud) {
|
if (!syncToCloud) {
|
||||||
var alertText = "Turning off automatic sync to cloud causes all data\n"
|
var alertText = "Turning off automatic sync to cloud causes all data\n"
|
||||||
alertText +=" to only be stored locally.\n"
|
alertText +="to only be stored locally.\n"
|
||||||
alertText += "This can be very useful in situations with\n"
|
alertText += "This can be very useful in situations with\n"
|
||||||
alertText += " limited or no network access.\n"
|
alertText += "limited or no network access.\n"
|
||||||
alertText += "Please chose 'Manual sync with cloud' if you have network\n"
|
alertText += "Please chose 'Manual sync with cloud' if you have network\n"
|
||||||
alertText += " connectivity and want to sync your data to cloud storage."
|
alertText += "connectivity and want to sync your data to cloud storage."
|
||||||
showPassiveNotification(alertText, 10000)
|
showPassiveNotification(alertText, 10000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,8 +336,7 @@ Kirigami.ApplicationWindow {
|
||||||
DiveDetails {
|
DiveDetails {
|
||||||
id: detailsWindow
|
id: detailsWindow
|
||||||
visible: false
|
visible: false
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadFromDiveComputer {
|
DownloadFromDiveComputer {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
<file alias="context-menu.png">icons/context-menu.png</file>
|
<file alias="context-menu.png">icons/context-menu.png</file>
|
||||||
<file alias="menu-edit.png">icons/menu-edit.png</file>
|
<file alias="menu-edit.png">icons/menu-edit.png</file>
|
||||||
<file alias="menu-back.png">icons/menu-back.png</file>
|
<file alias="menu-back.png">icons/menu-back.png</file>
|
||||||
|
<file alias="nocloud.svg">icons/nocloud.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/imports">
|
<qresource prefix="/imports">
|
||||||
<file alias="org/kde/kirigami/qmldir">kirigami/qmldir</file>
|
<file alias="org/kde/kirigami/qmldir">kirigami/qmldir</file>
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
<file alias="org/kde/kirigami/private/ActionButton.qml">kirigami/private/ActionButton.qml</file>
|
<file alias="org/kde/kirigami/private/ActionButton.qml">kirigami/private/ActionButton.qml</file>
|
||||||
<file alias="org/kde/kirigami/private/BackButton.qml">kirigami/private/BackButton.qml</file>
|
<file alias="org/kde/kirigami/private/BackButton.qml">kirigami/private/BackButton.qml</file>
|
||||||
<file alias="org/kde/kirigami/private/ContextIcon.qml">kirigami/private/ContextIcon.qml</file>
|
<file alias="org/kde/kirigami/private/ContextIcon.qml">kirigami/private/ContextIcon.qml</file>
|
||||||
|
<file alias="org/kde/kirigami/private/DefaultListItemBackground.qml">kirigami/private/DefaultListItemBackground.qml</file>
|
||||||
<file alias="org/kde/kirigami/private/EdgeShadow.qml">kirigami/private/EdgeShadow.qml</file>
|
<file alias="org/kde/kirigami/private/EdgeShadow.qml">kirigami/private/EdgeShadow.qml</file>
|
||||||
<file alias="org/kde/kirigami/private/MenuIcon.qml">kirigami/private/MenuIcon.qml</file>
|
<file alias="org/kde/kirigami/private/MenuIcon.qml">kirigami/private/MenuIcon.qml</file>
|
||||||
<file alias="org/kde/kirigami/private/DefaultListItemBackground.qml">kirigami/private/DefaultListItemBackground.qml</file>
|
<file alias="org/kde/kirigami/private/DefaultListItemBackground.qml">kirigami/private/DefaultListItemBackground.qml</file>
|
||||||
|
|
|
@ -19,12 +19,16 @@
|
||||||
#include "core/qt-gui.h"
|
#include "core/qt-gui.h"
|
||||||
#include "core/git-access.h"
|
#include "core/git-access.h"
|
||||||
#include "core/cloudstorage.h"
|
#include "core/cloudstorage.h"
|
||||||
|
#include "core/subsurface-qt/SettingsObjectWrapper.h"
|
||||||
|
#include "core/membuffer.h"
|
||||||
|
|
||||||
QMLManager *QMLManager::m_instance = NULL;
|
QMLManager *QMLManager::m_instance = NULL;
|
||||||
|
|
||||||
#define RED_FONT QLatin1Literal("<font color=\"red\">")
|
#define RED_FONT QLatin1Literal("<font color=\"red\">")
|
||||||
#define END_FONT QLatin1Literal("</font>")
|
#define END_FONT QLatin1Literal("</font>")
|
||||||
|
|
||||||
|
#define NOCLOUD_LOCALSTORAGE format_string("%s/cloudstorage/localrepo[master]", system_default_directory())
|
||||||
|
|
||||||
static void appendTextToLogStandalone(const char *text)
|
static void appendTextToLogStandalone(const char *text)
|
||||||
{
|
{
|
||||||
QMLManager *self = QMLManager::instance();
|
QMLManager *self = QMLManager::instance();
|
||||||
|
@ -153,6 +157,11 @@ void QMLManager::openLocalThenRemote(QString url)
|
||||||
DiveListModel::instance()->addAllDives();
|
DiveListModel::instance()->addAllDives();
|
||||||
appendTextToLog(QStringLiteral("%1 dives loaded from cache").arg(dive_table.nr));
|
appendTextToLog(QStringLiteral("%1 dives loaded from cache").arg(dive_table.nr));
|
||||||
}
|
}
|
||||||
|
if (oldStatus() == NOCLOUD) {
|
||||||
|
// if we switch to credentials from NOCLOUD, we take things online temporarily
|
||||||
|
prefs.git_local_only = false;
|
||||||
|
appendTextToLog(QStringLiteral("taking things online to be able to switch to cloud account"));
|
||||||
|
}
|
||||||
set_filename(fileNamePrt.data(), true);
|
set_filename(fileNamePrt.data(), true);
|
||||||
if (prefs.git_local_only) {
|
if (prefs.git_local_only) {
|
||||||
appendTextToLog(QStringLiteral("have cloud credentials, but user asked not to connect to network"));
|
appendTextToLog(QStringLiteral("have cloud credentials, but user asked not to connect to network"));
|
||||||
|
@ -163,6 +172,13 @@ void QMLManager::openLocalThenRemote(QString url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QMLManager::mergeLocalRepo()
|
||||||
|
{
|
||||||
|
char *filename = NOCLOUD_LOCALSTORAGE;
|
||||||
|
parse_file(filename);
|
||||||
|
process_dives(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
void QMLManager::finishSetup()
|
void QMLManager::finishSetup()
|
||||||
{
|
{
|
||||||
// Initialize cloud credentials.
|
// Initialize cloud credentials.
|
||||||
|
@ -178,9 +194,23 @@ void QMLManager::finishSetup()
|
||||||
// but we need to make sure we stay the only ones accessing git storage
|
// but we need to make sure we stay the only ones accessing git storage
|
||||||
alreadySaving = true;
|
alreadySaving = true;
|
||||||
openLocalThenRemote(url);
|
openLocalThenRemote(url);
|
||||||
|
} else if (!same_string(existing_filename, "")) {
|
||||||
|
setCredentialStatus(NOCLOUD);
|
||||||
|
appendTextToLog(tr("working in no-cloud mode"));
|
||||||
|
int error = parse_file(existing_filename);
|
||||||
|
if (error) {
|
||||||
|
// we got an error loading the local file
|
||||||
|
appendTextToLog(QString("got error %2 when parsing file %1").arg(existing_filename, get_error_string()));
|
||||||
|
set_filename(NULL, "");
|
||||||
|
} else {
|
||||||
|
// successfully opened the local file, now add thigs to the dive list
|
||||||
|
consumeFinishedLoad(0);
|
||||||
|
setAccessingCloud(-1);
|
||||||
|
appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(dive_table.nr).arg(existing_filename));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setCredentialStatus(INCOMPLETE);
|
setCredentialStatus(INCOMPLETE);
|
||||||
appendTextToLog(QStringLiteral("no cloud credentials"));
|
appendTextToLog(tr("no cloud credentials"));
|
||||||
setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT);
|
setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT);
|
||||||
}
|
}
|
||||||
setDistanceThreshold(prefs.distance_threshold);
|
setDistanceThreshold(prefs.distance_threshold);
|
||||||
|
@ -231,6 +261,7 @@ void QMLManager::saveCloudCredentials()
|
||||||
// just go back to the dive list
|
// just go back to the dive list
|
||||||
setCredentialStatus(oldStatus());
|
setCredentialStatus(oldStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!same_string(prefs.cloud_storage_password, qPrintable(cloudPassword()))) {
|
if (!same_string(prefs.cloud_storage_password, qPrintable(cloudPassword()))) {
|
||||||
free(prefs.cloud_storage_password);
|
free(prefs.cloud_storage_password);
|
||||||
prefs.cloud_storage_password = strdup(qPrintable(cloudPassword()));
|
prefs.cloud_storage_password = strdup(qPrintable(cloudPassword()));
|
||||||
|
@ -238,6 +269,9 @@ void QMLManager::saveCloudCredentials()
|
||||||
if (cloudUserName().isEmpty() || cloudPassword().isEmpty()) {
|
if (cloudUserName().isEmpty() || cloudPassword().isEmpty()) {
|
||||||
setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT);
|
setStartPageText(RED_FONT + tr("Please enter valid cloud credentials.") + END_FONT);
|
||||||
} else if (cloudCredentialsChanged) {
|
} else if (cloudCredentialsChanged) {
|
||||||
|
// let's make sure there are no unsaved changes
|
||||||
|
saveChangesLocal();
|
||||||
|
|
||||||
free(prefs.userid);
|
free(prefs.userid);
|
||||||
prefs.userid = NULL;
|
prefs.userid = NULL;
|
||||||
syncLoadFromCloud();
|
syncLoadFromCloud();
|
||||||
|
@ -252,6 +286,10 @@ void QMLManager::saveCloudCredentials()
|
||||||
// we therefore know that no one else is already accessing THIS git repo;
|
// we therefore know that no one else is already accessing THIS git repo;
|
||||||
// let's make sure we stay the only ones doing so
|
// let's make sure we stay the only ones doing so
|
||||||
alreadySaving = true;
|
alreadySaving = true;
|
||||||
|
// since we changed credentials, we need to try to connect to the cloud, regardless
|
||||||
|
// of whether we're in offline mode or not, to make sure the repository is synced
|
||||||
|
currentGitLocalOnly = prefs.git_local_only;
|
||||||
|
prefs.git_local_only = false;
|
||||||
openLocalThenRemote(url);
|
openLocalThenRemote(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +306,6 @@ void QMLManager::checkCredentialsAndExecute(execute_function_type execute)
|
||||||
CloudStorageAuthenticate *csa = new CloudStorageAuthenticate(this);
|
CloudStorageAuthenticate *csa = new CloudStorageAuthenticate(this);
|
||||||
csa->backend(prefs.cloud_storage_email, prefs.cloud_storage_password);
|
csa->backend(prefs.cloud_storage_email, prefs.cloud_storage_password);
|
||||||
connect(manager(), &QNetworkAccessManager::authenticationRequired, this, &QMLManager::provideAuth, Qt::UniqueConnection);
|
connect(manager(), &QNetworkAccessManager::authenticationRequired, this, &QMLManager::provideAuth, Qt::UniqueConnection);
|
||||||
connect(manager(), &QNetworkAccessManager::finished, this, execute, Qt::UniqueConnection);
|
|
||||||
QUrl url(CLOUDREDIRECTURL);
|
QUrl url(CLOUDREDIRECTURL);
|
||||||
request = QNetworkRequest(url);
|
request = QNetworkRequest(url);
|
||||||
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
request.setRawHeader("User-Agent", getUserAgent().toUtf8());
|
||||||
|
@ -276,6 +313,7 @@ void QMLManager::checkCredentialsAndExecute(execute_function_type execute)
|
||||||
reply = manager()->get(request);
|
reply = manager()->get(request);
|
||||||
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError(QNetworkReply::NetworkError)));
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError(QNetworkReply::NetworkError)));
|
||||||
connect(reply, &QNetworkReply::sslErrors, this, &QMLManager::handleSslErrors);
|
connect(reply, &QNetworkReply::sslErrors, this, &QMLManager::handleSslErrors);
|
||||||
|
connect(reply, &QNetworkReply::finished, this, execute, Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,10 +363,11 @@ void QMLManager::handleError(QNetworkReply::NetworkError nError)
|
||||||
void QMLManager::retrieveUserid()
|
void QMLManager::retrieveUserid()
|
||||||
{
|
{
|
||||||
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302) {
|
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302) {
|
||||||
appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: %1").arg(QString(reply->readAll())));
|
appendTextToLog(QStringLiteral("Cloud storage connection not working correctly: (%1) %2")
|
||||||
|
.arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt())
|
||||||
|
.arg(QString(reply->readAll())));
|
||||||
setStartPageText(RED_FONT + tr("Cannot connect to cloud storage") + END_FONT);
|
setStartPageText(RED_FONT + tr("Cannot connect to cloud storage") + END_FONT);
|
||||||
setAccessingCloud(-1);
|
revertToNoCloudIfNeeded();
|
||||||
alreadySaving = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCredentialStatus(VALID);
|
setCredentialStatus(VALID);
|
||||||
|
@ -336,8 +375,7 @@ void QMLManager::retrieveUserid()
|
||||||
if (userid.isEmpty()) {
|
if (userid.isEmpty()) {
|
||||||
if (same_string(prefs.cloud_storage_email, "") || same_string(prefs.cloud_storage_password, "")) {
|
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");
|
appendTextToLog("cloud user name or password are empty, can't retrieve web user id");
|
||||||
setAccessingCloud(-1);
|
revertToNoCloudIfNeeded();
|
||||||
alreadySaving = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
appendTextToLog(QStringLiteral("calling getUserid with user %1").arg(prefs.cloud_storage_email));
|
appendTextToLog(QStringLiteral("calling getUserid with user %1").arg(prefs.cloud_storage_email));
|
||||||
|
@ -366,12 +404,12 @@ void QMLManager::loadDiveProgress(int percent)
|
||||||
void QMLManager::loadDivesWithValidCredentials()
|
void QMLManager::loadDivesWithValidCredentials()
|
||||||
{
|
{
|
||||||
QString url;
|
QString url;
|
||||||
|
timestamp_t currentDiveTimestamp = selectedDiveTimestamp();
|
||||||
if (getCloudURL(url)) {
|
if (getCloudURL(url)) {
|
||||||
QString errorString(get_error_string());
|
QString errorString(get_error_string());
|
||||||
appendTextToLog(errorString);
|
appendTextToLog(errorString);
|
||||||
setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(errorString) + END_FONT);
|
setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(errorString) + END_FONT);
|
||||||
setAccessingCloud(-1);
|
revertToNoCloudIfNeeded();
|
||||||
alreadySaving = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QByteArray fileNamePrt = QFile::encodeName(url);
|
QByteArray fileNamePrt = QFile::encodeName(url);
|
||||||
|
@ -381,13 +419,9 @@ void QMLManager::loadDivesWithValidCredentials()
|
||||||
if (check_git_sha(fileNamePrt.data(), &git, &branch) == 0) {
|
if (check_git_sha(fileNamePrt.data(), &git, &branch) == 0) {
|
||||||
qDebug() << "local cache was current, no need to modify dive list";
|
qDebug() << "local cache was current, no need to modify dive list";
|
||||||
appendTextToLog("Cloud sync shows local cache was current");
|
appendTextToLog("Cloud sync shows local cache was current");
|
||||||
setLoadFromCloud(true);
|
goto successful_exit;
|
||||||
setAccessingCloud(-1);
|
|
||||||
alreadySaving = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
appendTextToLog("Cloud sync brought newer data, reloading the dive list");
|
appendTextToLog("Cloud sync brought newer data, reloading the dive list");
|
||||||
timestamp_t currentDiveTimestamp = selectedDiveTimestamp();
|
|
||||||
|
|
||||||
clear_dive_file_data();
|
clear_dive_file_data();
|
||||||
if (git != dummy_git_repository) {
|
if (git != dummy_git_repository) {
|
||||||
|
@ -407,10 +441,71 @@ void QMLManager::loadDivesWithValidCredentials()
|
||||||
report_error("failed to open file %s", fileNamePrt.data());
|
report_error("failed to open file %s", fileNamePrt.data());
|
||||||
QString errorString(get_error_string());
|
QString errorString(get_error_string());
|
||||||
appendTextToLog(errorString);
|
appendTextToLog(errorString);
|
||||||
setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(errorString) + END_FONT);
|
revertToNoCloudIfNeeded();
|
||||||
alreadySaving = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
consumeFinishedLoad(currentDiveTimestamp);
|
||||||
|
|
||||||
|
successful_exit:
|
||||||
|
alreadySaving = false;
|
||||||
|
setLoadFromCloud(true);
|
||||||
|
// if we came from local storage mode, let's merge the local data into the local cache
|
||||||
|
// for the remote data - which then later gets merged with the remote data if necessary
|
||||||
|
if (oldStatus() == NOCLOUD) {
|
||||||
|
git_storage_update_progress(false, "import dives from nocloud local storage");
|
||||||
|
dive_table.preexisting = dive_table.nr;
|
||||||
|
mergeLocalRepo();
|
||||||
|
DiveListModel::instance()->clear();
|
||||||
|
DiveListModel::instance()->addAllDives();
|
||||||
|
appendTextToLog(QStringLiteral("%1 dives loaded after importing nocloud local storage").arg(dive_table.nr));
|
||||||
|
saveChangesLocal();
|
||||||
|
if (syncToCloud() == false) {
|
||||||
|
appendTextToLog(QStringLiteral("taking things back offline now that storage is synced"));
|
||||||
|
prefs.git_local_only = syncToCloud();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAccessingCloud(-1);
|
||||||
|
// if we got here just for an initial connection to the cloud, reset to offline
|
||||||
|
if (currentGitLocalOnly) {
|
||||||
|
currentGitLocalOnly = false;
|
||||||
|
prefs.git_local_only = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMLManager::revertToNoCloudIfNeeded()
|
||||||
|
{
|
||||||
|
if (currentGitLocalOnly) {
|
||||||
|
// we tried to connect to the cloud for the first time and that failed
|
||||||
|
currentGitLocalOnly = false;
|
||||||
|
prefs.git_local_only = true;
|
||||||
|
}
|
||||||
|
if (oldStatus() == NOCLOUD) {
|
||||||
|
// we tried to switch to a cloud account and had previously used local data,
|
||||||
|
// but connecting to the cloud account (and subsequently merging the local
|
||||||
|
// and cloud data) failed - so let's delete the cloud credentials and go
|
||||||
|
// back to NOCLOUD mode in order to prevent us from losing the locally stored
|
||||||
|
// dives
|
||||||
|
if (syncToCloud() == false) {
|
||||||
|
appendTextToLog(QStringLiteral("taking things back offline since sync with cloud failed"));
|
||||||
|
prefs.git_local_only = syncToCloud();
|
||||||
|
}
|
||||||
|
free(prefs.cloud_storage_email);
|
||||||
|
prefs.cloud_storage_email = NULL;
|
||||||
|
free(prefs.cloud_storage_password);
|
||||||
|
prefs.cloud_storage_password = NULL;
|
||||||
|
setCloudUserName("");
|
||||||
|
setCloudPassword("");
|
||||||
|
setCredentialStatus(INCOMPLETE);
|
||||||
|
set_filename(NOCLOUD_LOCALSTORAGE, true);
|
||||||
|
setStartPageText(RED_FONT + tr("Failed to connect to cloud server, reverting to no cloud status") + END_FONT);
|
||||||
|
}
|
||||||
|
setAccessingCloud(-1);
|
||||||
|
alreadySaving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMLManager::consumeFinishedLoad(timestamp_t currentDiveTimestamp)
|
||||||
|
{
|
||||||
prefs.unit_system = informational_prefs.unit_system;
|
prefs.unit_system = informational_prefs.unit_system;
|
||||||
if (informational_prefs.unit_system == IMPERIAL)
|
if (informational_prefs.unit_system == IMPERIAL)
|
||||||
informational_prefs.units = IMPERIAL_units;
|
informational_prefs.units = IMPERIAL_units;
|
||||||
|
@ -420,12 +515,9 @@ void QMLManager::loadDivesWithValidCredentials()
|
||||||
DiveListModel::instance()->addAllDives();
|
DiveListModel::instance()->addAllDives();
|
||||||
if (currentDiveTimestamp)
|
if (currentDiveTimestamp)
|
||||||
setUpdateSelectedDive(dlSortModel->getIdxForId(get_dive_id_closest_to(currentDiveTimestamp)));
|
setUpdateSelectedDive(dlSortModel->getIdxForId(get_dive_id_closest_to(currentDiveTimestamp)));
|
||||||
else
|
|
||||||
setUpdateSelectedDive(0);
|
|
||||||
appendTextToLog(QStringLiteral("%1 dives loaded").arg(dive_table.nr));
|
appendTextToLog(QStringLiteral("%1 dives loaded").arg(dive_table.nr));
|
||||||
if (dive_table.nr == 0)
|
if (dive_table.nr == 0)
|
||||||
setStartPageText(tr("Cloud storage open successfully. No dives in dive list."));
|
setStartPageText(tr("Cloud storage open successfully. No dives in dive list."));
|
||||||
setLoadFromCloud(true);
|
|
||||||
alreadySaving = false;
|
alreadySaving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,11 +874,10 @@ void QMLManager::changesNeedSaving()
|
||||||
// to be reasonably fast), but don't save at all (and only remember that we need to save things
|
// to be reasonably fast), but don't save at all (and only remember that we need to save things
|
||||||
// on iOS
|
// on iOS
|
||||||
// on all other platforms we just save the changes and be done with it
|
// on all other platforms we just save the changes and be done with it
|
||||||
#if defined(Q_OS_IOS)
|
|
||||||
mark_divelist_changed(true);
|
mark_divelist_changed(true);
|
||||||
#elif defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
saveChangesLocal();
|
saveChangesLocal();
|
||||||
#else
|
#elif !defined(Q_OS_IOS)
|
||||||
saveChangesCloud(false);
|
saveChangesCloud(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -794,7 +885,18 @@ void QMLManager::saveChangesLocal()
|
||||||
{
|
{
|
||||||
if (unsaved_changes()) {
|
if (unsaved_changes()) {
|
||||||
git_storage_update_progress(true, "saving dives locally"); // reset the timers
|
git_storage_update_progress(true, "saving dives locally"); // reset the timers
|
||||||
if (!loadFromCloud()) {
|
if (credentialStatus() == NOCLOUD) {
|
||||||
|
if (same_string(existing_filename, "")) {
|
||||||
|
char *filename = NOCLOUD_LOCALSTORAGE;
|
||||||
|
if (git_create_local_repo(filename))
|
||||||
|
appendTextToLog(get_error_string());
|
||||||
|
set_filename(filename, true);
|
||||||
|
GeneralSettingsObjectWrapper s(this);
|
||||||
|
s.setDefaultFilename(filename);
|
||||||
|
s.setDefaultFileBehavior(LOCAL_DEFAULT_FILE);
|
||||||
|
qDebug() << "setting default file to" << filename;
|
||||||
|
}
|
||||||
|
} else if (!loadFromCloud()) {
|
||||||
// this seems silly, but you need a common ancestor in the repository in
|
// this seems silly, but you need a common ancestor in the repository in
|
||||||
// order to be able to merge che changes later
|
// order to be able to merge che changes later
|
||||||
appendTextToLog("Don't save dives without loading from the cloud, first.");
|
appendTextToLog("Don't save dives without loading from the cloud, first.");
|
||||||
|
@ -809,6 +911,7 @@ void QMLManager::saveChangesLocal()
|
||||||
prefs.git_local_only = true;
|
prefs.git_local_only = true;
|
||||||
if (save_dives(existing_filename)) {
|
if (save_dives(existing_filename)) {
|
||||||
appendTextToLog(get_error_string());
|
appendTextToLog(get_error_string());
|
||||||
|
set_filename(NULL, true);
|
||||||
setAccessingCloud(-1);
|
setAccessingCloud(-1);
|
||||||
prefs.git_local_only = glo;
|
prefs.git_local_only = glo;
|
||||||
alreadySaving = false;
|
alreadySaving = false;
|
||||||
|
@ -825,14 +928,10 @@ void QMLManager::saveChangesLocal()
|
||||||
|
|
||||||
void QMLManager::saveChangesCloud(bool forceRemoteSync)
|
void QMLManager::saveChangesCloud(bool forceRemoteSync)
|
||||||
{
|
{
|
||||||
if (!unsaved_changes()) {
|
if (!unsaved_changes() && !forceRemoteSync) {
|
||||||
appendTextToLog("asked to save changes but no unsaved changes");
|
appendTextToLog("asked to save changes but no unsaved changes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!loadFromCloud()) {
|
|
||||||
appendTextToLog("Don't save dives without loading from the cloud, first.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (alreadySaving) {
|
if (alreadySaving) {
|
||||||
appendTextToLog("save operation in progress already");
|
appendTextToLog("save operation in progress already");
|
||||||
return;
|
return;
|
||||||
|
@ -844,6 +943,11 @@ void QMLManager::saveChangesCloud(bool forceRemoteSync)
|
||||||
if (prefs.git_local_only && !forceRemoteSync)
|
if (prefs.git_local_only && !forceRemoteSync)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!loadFromCloud()) {
|
||||||
|
appendTextToLog("Don't save dives without loading from the cloud, first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool glo = prefs.git_local_only;
|
bool glo = prefs.git_local_only;
|
||||||
git_storage_update_progress(false, "start save change to cloud");
|
git_storage_update_progress(false, "start save change to cloud");
|
||||||
prefs.git_local_only = false;
|
prefs.git_local_only = false;
|
||||||
|
@ -1119,6 +1223,8 @@ QMLManager::credentialStatus_t QMLManager::credentialStatus() const
|
||||||
void QMLManager::setCredentialStatus(const credentialStatus_t value)
|
void QMLManager::setCredentialStatus(const credentialStatus_t value)
|
||||||
{
|
{
|
||||||
if (m_credentialStatus != value) {
|
if (m_credentialStatus != value) {
|
||||||
|
if (value == NOCLOUD)
|
||||||
|
appendTextToLog("Switching to no cloud mode");
|
||||||
m_credentialStatus = value;
|
m_credentialStatus = value;
|
||||||
emit credentialStatusChanged();
|
emit credentialStatusChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,8 @@ public:
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
INVALID,
|
INVALID,
|
||||||
VALID_EMAIL,
|
VALID_EMAIL,
|
||||||
VALID
|
VALID,
|
||||||
|
NOCLOUD
|
||||||
};
|
};
|
||||||
|
|
||||||
static QMLManager *instance();
|
static QMLManager *instance();
|
||||||
|
@ -127,11 +128,14 @@ public slots:
|
||||||
void clearGpsData();
|
void clearGpsData();
|
||||||
void finishSetup();
|
void finishSetup();
|
||||||
void openLocalThenRemote(QString url);
|
void openLocalThenRemote(QString url);
|
||||||
|
void mergeLocalRepo();
|
||||||
QString getNumber(const QString& diveId);
|
QString getNumber(const QString& diveId);
|
||||||
QString getDate(const QString& diveId);
|
QString getDate(const QString& diveId);
|
||||||
QString getCurrentPosition();
|
QString getCurrentPosition();
|
||||||
QString getVersion() const;
|
QString getVersion() const;
|
||||||
void deleteGpsFix(quint64 when);
|
void deleteGpsFix(quint64 when);
|
||||||
|
void revertToNoCloudIfNeeded();
|
||||||
|
void consumeFinishedLoad(timestamp_t currentDiveTimestamp);
|
||||||
void refreshDiveList();
|
void refreshDiveList();
|
||||||
void screenChanged(QScreen *screen);
|
void screenChanged(QScreen *screen);
|
||||||
qreal lastDevicePixelRatio();
|
qreal lastDevicePixelRatio();
|
||||||
|
@ -170,6 +174,7 @@ private:
|
||||||
bool checkLocation(DiveObjectHelper *myDive, struct dive *d, QString location, QString gps);
|
bool checkLocation(DiveObjectHelper *myDive, struct dive *d, QString location, QString gps);
|
||||||
bool checkDuration(DiveObjectHelper *myDive, struct dive *d, QString duration);
|
bool checkDuration(DiveObjectHelper *myDive, struct dive *d, QString duration);
|
||||||
bool checkDepth(DiveObjectHelper *myDive, struct dive *d, QString depth);
|
bool checkDepth(DiveObjectHelper *myDive, struct dive *d, QString depth);
|
||||||
|
bool currentGitLocalOnly;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void cloudUserNameChanged();
|
void cloudUserNameChanged();
|
||||||
|
|
|
@ -22,12 +22,9 @@ QTranslator *qtTranslator, *ssrfTranslator;
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
bool no_filenames = true;
|
|
||||||
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
|
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
|
||||||
QApplication *application = new QApplication(argc, argv);
|
QApplication *application = new QApplication(argc, argv);
|
||||||
(void)application;
|
(void)application;
|
||||||
QStringList files;
|
|
||||||
QStringList importedFiles;
|
|
||||||
QStringList arguments = QCoreApplication::arguments();
|
QStringList arguments = QCoreApplication::arguments();
|
||||||
|
|
||||||
bool dedicated_console = arguments.length() > 1 &&
|
bool dedicated_console = arguments.length() > 1 &&
|
||||||
|
@ -40,18 +37,8 @@ int main(int argc, char **argv)
|
||||||
parse_argument(a.toLocal8Bit().data());
|
parse_argument(a.toLocal8Bit().data());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (imported) {
|
|
||||||
importedFiles.push_back(a);
|
|
||||||
} else {
|
|
||||||
no_filenames = false;
|
|
||||||
files.push_back(a);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#if !LIBGIT2_VER_MAJOR && LIBGIT2_VER_MINOR < 22
|
|
||||||
git_threads_init();
|
|
||||||
#else
|
|
||||||
git_libgit2_init();
|
git_libgit2_init();
|
||||||
#endif
|
|
||||||
setup_system_prefs();
|
setup_system_prefs();
|
||||||
if (uiLanguage(0).contains("-US"))
|
if (uiLanguage(0).contains("-US"))
|
||||||
default_prefs.units = IMPERIAL_units;
|
default_prefs.units = IMPERIAL_units;
|
||||||
|
@ -61,6 +48,11 @@ int main(int argc, char **argv)
|
||||||
taglist_init_global();
|
taglist_init_global();
|
||||||
init_ui();
|
init_ui();
|
||||||
loadPreferences();
|
loadPreferences();
|
||||||
|
if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE)
|
||||||
|
set_filename(prefs.default_filename, true);
|
||||||
|
else
|
||||||
|
set_filename(NULL, true);
|
||||||
|
|
||||||
// some hard coded settings
|
// some hard coded settings
|
||||||
prefs.animation_speed = 0; // we render the profile to pixmap, no animations
|
prefs.animation_speed = 0; // we render the profile to pixmap, no animations
|
||||||
|
|
||||||
|
@ -69,17 +61,6 @@ int main(int argc, char **argv)
|
||||||
prefs.redceiling = 1;
|
prefs.redceiling = 1;
|
||||||
|
|
||||||
init_proxy();
|
init_proxy();
|
||||||
if (no_filenames) {
|
|
||||||
if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE) {
|
|
||||||
QString defaultFile(prefs.default_filename);
|
|
||||||
if (!defaultFile.isEmpty())
|
|
||||||
files.push_back(QString(prefs.default_filename));
|
|
||||||
} else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) {
|
|
||||||
QString cloudURL;
|
|
||||||
if (getCloudURL(cloudURL) == 0)
|
|
||||||
files.push_back(cloudURL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!quit)
|
if (!quit)
|
||||||
run_ui();
|
run_ui();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue