subsurface/core/subsurfacestartup.c

342 lines
9.3 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
#include "subsurfacestartup.h"
#include "version.h"
#include <stdbool.h>
#include <string.h>
#include "gettext.h"
#include "qthelper.h"
#include "git-access.h"
#include "libdivecomputer/version.h"
struct preferences prefs, git_prefs;
struct preferences default_prefs = {
.cloud_base_url = "https://cloud.subsurface-divelog.org/",
#if defined(SUBSURFACE_MOBILE)
.git_local_only = true,
#endif
.units = SI_UNITS,
.unit_system = METRIC,
.coordinates_traditional = true,
.pp_graphs = {
.po2 = false,
.pn2 = false,
.phe = false,
.po2_threshold_min = 0.16,
.po2_threshold_max = 1.6,
.pn2_threshold = 4.0,
.phe_threshold = 13.0,
},
.mod = false,
.modpO2 = 1.6,
.ead = false,
.hrgraph = false,
.percentagegraph = false,
.dcceiling = true,
.redceiling = false,
.calcceiling = false,
.calcceiling3m = false,
.calcndltts = false,
.gflow = 30,
.gfhigh = 75,
.animation_speed = 500,
.gf_low_at_maxdepth = false,
.show_ccr_setpoint = false,
.show_ccr_sensors = false,
.font_size = -1,
.display_invalid_dives = false,
.show_sac = false,
.display_unused_tanks = false,
.show_average_depth = true,
.show_icd = false,
.ascrate75 = 9000 / 60,
.ascrate50 = 9000 / 60,
.ascratestops = 9000 / 60,
.ascratelast6m = 9000 / 60,
.descrate = 18000 / 60,
.sacfactor = 400,
.problemsolvingtime = 4,
.bottompo2 = 1400,
.decopo2 = 1600,
.bestmixend.mm = 30000,
.doo2breaks = false,
.drop_stone_mode = false,
.switch_at_req_stop = false,
.min_switch_duration = 60,
.last_stop = false,
.verbatim_plan = false,
.display_runtime = true,
.display_duration = true,
.display_transitions = true,
.display_variations = false,
.safetystop = true,
.bottomsac = 20000,
.decosac = 17000,
.reserve_gas=40000,
.o2consumption = 720,
.pscr_ratio = 100,
.show_pictures_in_profile = true,
.tankbar = false,
.facebook = {
.user_id = NULL,
.album_id = NULL,
.access_token = NULL
},
.defaultsetpoint = 1100,
.geocoding = {
.category = { 0 }
},
.locale = {
.use_system_language = true,
},
.planner_deco_mode = BUEHLMANN,
.vpmb_conservatism = 3,
.distance_threshold = 100,
.time_threshold = 300,
#if defined(SUBSURFACE_MOBILE)
.cloud_timeout = 10,
#else
.cloud_timeout = 5,
#endif
};
int run_survey;
struct units *get_units()
{
return &prefs.units;
}
/* random helper functions, used here or elsewhere */
static int sortfn(const void *_a, const void *_b)
{
const struct dive *a = (const struct dive *)*(void **)_a;
const struct dive *b = (const struct dive *)*(void **)_b;
if (a->when < b->when)
return -1;
if (a->when > b->when)
return 1;
return 0;
}
void sort_table(struct dive_table *table)
{
qsort(table->dives, table->nr, sizeof(struct dive *), sortfn);
}
const char *monthname(int mon)
{
Conversion to gettext to allow localization This is just the first step - convert the string literals, try to catch all the places where this isn't possible and the program needs to convert string constants at runtime (those are the N_ macros). Add a very rough first German localization so I can at least test what I have done. Seriously, I have never used a localized OS, so I am certain that I have many of the 'standard' translations wrong. Someone please take over :-) Major issues with this: - right now it hardcodes the search path for the message catalog to be ./locale - that's of course bogus, but it works well while doing initial testing. Once the tooling support is there we just should use the OS default. - even though de_DE defaults to ISO-8859-15 (or ISO-8859-1 - the internets can't seem to agree) I went with UTF-8 as that is what Gtk appears to want to use internally. ISO-8859-15 encoded .mo files create funny looking artefacts instead of Umlaute. - no support at all in the Makefile - I was hoping someone with more experience in how to best set this up would contribute a good set of Makefile rules - likely this will help fix the first issue in that it will also install the .mo file(s) in the correct place(s) For now simply run msgfmt -c -o subsurface.mo deutsch.po to create the subsurface.mo file and then move it to ./locale/de_DE.UTF-8/LC_MESSAGES/subsurface.mo If you make changes to the sources and need to add new strings to be translated, this is what seems to work (again, should be tooled through the Makefile): xgettext -o subsurface-new.pot -s -k_ -kN_ --add-comments="++GETTEXT" *.c msgmerge -s -U po/deutsch.po subsurface-new.pot If you do this PLEASE do one commit that just has the new msgid as changes in line numbers create a TON of diff-noise. Do changes to translations in a SEPARATE commit. - no testing at all on Windows or Mac It builds on Windows :-) Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-10-11 00:42:59 +00:00
static const char month_array[12][7] = {
/*++GETTEXT: these are three letter months - we allow up to six code bytes*/
QT_TRANSLATE_NOOP("gettextFromC", "Jan"), QT_TRANSLATE_NOOP("gettextFromC", "Feb"), QT_TRANSLATE_NOOP("gettextFromC", "Mar"), QT_TRANSLATE_NOOP("gettextFromC", "Apr"), QT_TRANSLATE_NOOP("gettextFromC", "May"), QT_TRANSLATE_NOOP("gettextFromC", "Jun"),
QT_TRANSLATE_NOOP("gettextFromC", "Jul"), QT_TRANSLATE_NOOP("gettextFromC", "Aug"), QT_TRANSLATE_NOOP("gettextFromC", "Sep"), QT_TRANSLATE_NOOP("gettextFromC", "Oct"), QT_TRANSLATE_NOOP("gettextFromC", "Nov"), QT_TRANSLATE_NOOP("gettextFromC", "Dec"),
};
return translate("gettextFromC", month_array[mon]);
}
/*
* track whether we switched to importing dives
*/
bool imported = false;
bool version_printed = false;
void print_version()
{
if (version_printed)
return;
printf("Subsurface v%s,\n", subsurface_git_version());
printf("built with libdivecomputer v%s\n", dc_version(NULL));
print_qt_versions();
int git_maj, git_min, git_rev;
git_libgit2_version(&git_maj, &git_min, &git_rev);
printf("built with libgit2 %d.%d.%d\n", git_maj, git_min, git_rev);
version_printed = true;
}
void print_files()
{
const char *branch = 0;
const char *remote = 0;
const char *filename, *local_git;
printf("\nFile locations:\n\n");
if (!empty_string(prefs.cloud_storage_email) && !empty_string(prefs.cloud_storage_password)) {
filename = cloud_url();
is_git_repository(filename, &branch, &remote, true);
} else {
/* strdup so the free below works in either case */
filename = strdup("No valid cloud credentials set.\n");
}
if (branch && remote) {
local_git = get_local_dir(remote, branch);
printf("Local git storage: %s\n", local_git);
} else {
printf("Unable to get local git directory\n");
}
printf("Cloud URL: %s\n", filename);
free((void *)filename);
char *tmp = hashfile_name_string();
printf("Image hashes: %s\n", tmp);
free(tmp);
tmp = picturedir_string();
printf("Local picture directory: %s\n\n", tmp);
free(tmp);
}
static void print_help()
{
print_version();
printf("\nUsage: subsurface [options] [logfile ...] [--import logfile ...]");
printf("\n\noptions include:");
printf("\n --help|-h This help text");
printf("\n --import logfile ... Logs before this option is treated as base, everything after is imported");
printf("\n --verbose|-v Verbose debug (repeat to increase verbosity)");
printf("\n --version Prints current version");
printf("\n --survey Offer to submit a user survey");
printf("\n --user=<test> Choose configuration space for user <test>");
printf("\n --cloud-timeout=<nr> Set timeout for cloud connection (0 < timeout < 60)\n\n");
}
void parse_argument(const char *arg)
{
const char *p = arg + 1;
do {
switch (*p) {
case 'h':
print_help();
exit(0);
case 'v':
print_version();
verbose++;
continue;
case 'q':
quit++;
continue;
case '-':
/* 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 (strncmp(arg, "--cloud-timeout=", sizeof("--cloud-timeout=") - 1) == 0) {
const char *timeout = arg + sizeof("--cloud-timeout=") - 1;
int to = strtol(timeout, NULL, 10);
if (0 < to && to < 60)
default_prefs.cloud_timeout = to;
return;
}
if (strcmp(arg, "--help") == 0) {
print_help();
exit(0);
}
if (strcmp(arg, "--import") == 0) {
imported = true; /* mark the dives so far as the base, * everything after is imported */
return;
}
if (strcmp(arg, "--verbose") == 0) {
print_version();
verbose++;
return;
}
if (strcmp(arg, "--version") == 0) {
print_version();
exit(0);
}
if (strcmp(arg, "--survey") == 0) {
run_survey = true;
return;
}
if (strcmp(arg, "--allow_run_as_root") == 0) {
++force_root;
return;
}
/* fallthrough */
case 'p':
/* ignore process serial number argument when run as native macosx app */
if (strncmp(arg, "-psQT_TR_NOOP(", 5) == 0) {
return;
}
/* fallthrough */
default:
fprintf(stderr, "Bad argument '%s'\n", arg);
exit(1);
}
} while (*++p);
}
/*
* Under a POSIX setup, the locale string should have a format
* like [language[_territory][.codeset][@modifier]].
*
* So search for the underscore, and see if the "territory" is
* US, and turn on imperial units by default.
*
* I guess Burma and Liberia should trigger this too. I'm too
* lazy to look up the territory names, though.
*/
void setup_system_prefs(void)
{
const char *env;
default_prefs.divelist_font = strdup(system_divelist_default_font);
default_prefs.font_size = system_divelist_default_font_size;
#if !defined(SUBSURFACE_MOBILE)
default_prefs.default_filename = copy_string(system_default_filename());
#endif
env = getenv("LC_MEASUREMENT");
if (!env)
env = getenv("LC_ALL");
if (!env)
env = getenv("LANG");
if (!env)
return;
env = strchr(env, '_');
if (!env)
return;
env++;
if (strncmp(env, "US", 2))
return;
default_prefs.units = IMPERIAL_units;
}
/* copy a preferences block, including making copies of all included strings */
void copy_prefs(struct preferences *src, struct preferences *dest)
{
*dest = *src;
dest->divelist_font = copy_string(src->divelist_font);
dest->default_filename = copy_string(src->default_filename);
dest->default_cylinder = copy_string(src->default_cylinder);
dest->cloud_base_url = copy_string(src->cloud_base_url);
dest->cloud_git_url = copy_string(src->cloud_git_url);
dest->userid = copy_string(src->userid);
dest->proxy_host = copy_string(src->proxy_host);
dest->proxy_user = copy_string(src->proxy_user);
dest->proxy_pass = copy_string(src->proxy_pass);
dest->time_format = copy_string(src->time_format);
dest->date_format = copy_string(src->date_format);
dest->date_format_short = copy_string(src->date_format_short);
dest->cloud_storage_password = copy_string(src->cloud_storage_password);
dest->cloud_storage_newpassword = copy_string(src->cloud_storage_newpassword);
dest->cloud_storage_email = copy_string(src->cloud_storage_email);
dest->cloud_storage_email_encoded = copy_string(src->cloud_storage_email_encoded);
dest->facebook.access_token = copy_string(src->facebook.access_token);
dest->facebook.user_id = copy_string(src->facebook.user_id);
dest->facebook.album_id = copy_string(src->facebook.album_id);
}
/*
* Free strduped prefs before exit.
*
* These are not real leaks but they plug the holes found by eg.
* valgrind so you can find the real leaks.
*/
void free_prefs(void)
{
// nop
}