mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Delete code and files that are no longer used
Most of this is Gtk related, some of it is helpers that we don't need anymore. I love the diffstat. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
c3f07b9f81
commit
34db6dc2be
17 changed files with 4 additions and 7245 deletions
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* conversions.h
|
||||
*
|
||||
* Helpers to convert between different units
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void convert_volume_pressure(int ml, int mbar, double *v, double *p);
|
||||
int convert_pressure(int mbar, double *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
2
dive.h
2
dive.h
|
@ -694,9 +694,7 @@ typedef enum {
|
|||
} os_feature_t;
|
||||
|
||||
extern const char *existing_filename;
|
||||
extern const char *subsurface_gettext_domainpath(char *);
|
||||
extern bool subsurface_os_feature_available(os_feature_t);
|
||||
extern bool subsurface_launch_for_uri(const char *);
|
||||
extern void subsurface_command_line_init(int *, char ***);
|
||||
extern void subsurface_command_line_exit(int *, char ***);
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "display.h"
|
||||
#include "webservice.h"
|
||||
|
||||
static short dive_list_changed = FALSE;
|
||||
|
||||
|
|
|
@ -1,465 +0,0 @@
|
|||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "display.h"
|
||||
#include "libdivecomputer.h"
|
||||
|
||||
const char *default_dive_computer_vendor;
|
||||
const char *default_dive_computer_product;
|
||||
const char *default_dive_computer_device;
|
||||
|
||||
|
||||
|
||||
struct vendor *dc_list;
|
||||
|
||||
#if USE_GTK_UI
|
||||
static void render_dc_vendor(GtkCellLayout *cell,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
const char *vendor;
|
||||
|
||||
gtk_tree_model_get(model, iter, 0, &vendor, -1);
|
||||
g_object_set(renderer, "text", vendor, NULL);
|
||||
}
|
||||
|
||||
static void render_dc_product(GtkCellLayout *cell,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
dc_descriptor_t *descriptor = NULL;
|
||||
const char *product;
|
||||
|
||||
gtk_tree_model_get(model, iter, 0, &descriptor, -1);
|
||||
product = dc_descriptor_get_product(descriptor);
|
||||
g_object_set(renderer, "text", product, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int is_default_dive_computer(const char *vendor, const char *product)
|
||||
{
|
||||
return default_dive_computer_vendor && !strcmp(vendor, default_dive_computer_vendor) &&
|
||||
default_dive_computer_product && !strcmp(product, default_dive_computer_product);
|
||||
}
|
||||
|
||||
int is_default_dive_computer_device(const char *name)
|
||||
{
|
||||
return default_dive_computer_device && !strcmp(name, default_dive_computer_device);
|
||||
}
|
||||
|
||||
void set_default_dive_computer(const char *vendor, const char *product)
|
||||
{
|
||||
if (!vendor || !*vendor)
|
||||
return;
|
||||
if (!product || !*product)
|
||||
return;
|
||||
if (is_default_dive_computer(vendor, product))
|
||||
return;
|
||||
if (default_dive_computer_vendor)
|
||||
free((void *)default_dive_computer_vendor);
|
||||
if (default_dive_computer_product)
|
||||
free((void *)default_dive_computer_product);
|
||||
default_dive_computer_vendor = strdup(vendor);
|
||||
default_dive_computer_product = strdup(product);
|
||||
subsurface_set_conf("dive_computer_vendor", vendor);
|
||||
subsurface_set_conf("dive_computer_product", product);
|
||||
}
|
||||
|
||||
void set_default_dive_computer_device(const char *name)
|
||||
{
|
||||
if (!name || !*name)
|
||||
return;
|
||||
if (is_default_dive_computer_device(name))
|
||||
return;
|
||||
if (default_dive_computer_device)
|
||||
free((void *)default_dive_computer_device);
|
||||
default_dive_computer_device = strdup(name);
|
||||
subsurface_set_conf("dive_computer_device", name);
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
static void dive_computer_selector_changed(GtkWidget *combo, gpointer data)
|
||||
{
|
||||
GtkWidget *import, *button;
|
||||
|
||||
#if DC_VERSION_CHECK(0, 4, 0)
|
||||
GtkTreeIter iter;
|
||||
if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) {
|
||||
GtkTreeModel *model;
|
||||
dc_descriptor_t *descriptor;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX(combo));
|
||||
gtk_tree_model_get(model, &iter, 0, &descriptor, -1);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(data), dc_descriptor_get_transport (descriptor) == DC_TRANSPORT_SERIAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
import = gtk_widget_get_ancestor(combo, GTK_TYPE_DIALOG);
|
||||
button = gtk_dialog_get_widget_for_response(GTK_DIALOG(import), GTK_RESPONSE_ACCEPT);
|
||||
gtk_widget_set_sensitive(button, TRUE);
|
||||
}
|
||||
|
||||
static GtkListStore **product_model;
|
||||
static void dive_computer_vendor_changed(GtkComboBox *vendorcombo, GtkComboBox *productcombo)
|
||||
{
|
||||
int vendor = gtk_combo_box_get_active(vendorcombo);
|
||||
gtk_combo_box_set_model(productcombo, GTK_TREE_MODEL(product_model[vendor + 1]));
|
||||
gtk_combo_box_set_active(productcombo, -1);
|
||||
}
|
||||
|
||||
static GtkWidget *import_dive_computer(device_data_t *data, GtkDialog *dialog)
|
||||
{
|
||||
GError *error;
|
||||
GtkWidget *vbox, *info, *container, *label, *button;
|
||||
|
||||
/* HACK to simply include the Uemis Zurich in the list */
|
||||
if (! strcmp(data->vendor, "Uemis") && ! strcmp(data->product, "Zurich")) {
|
||||
error = uemis_download(data->devname, &data->progress, data->dialog, data->force_download);
|
||||
} else {
|
||||
error = do_import(data);
|
||||
}
|
||||
if (!error)
|
||||
return NULL;
|
||||
|
||||
button = gtk_dialog_get_widget_for_response(dialog, GTK_RESPONSE_ACCEPT);
|
||||
gtk_button_set_use_stock(GTK_BUTTON(button), 0);
|
||||
gtk_button_set_label(GTK_BUTTON(button), _("Retry"));
|
||||
|
||||
vbox = gtk_dialog_get_content_area(dialog);
|
||||
|
||||
info = gtk_info_bar_new();
|
||||
container = gtk_info_bar_get_content_area(GTK_INFO_BAR(info));
|
||||
label = gtk_label_new(error->message);
|
||||
gtk_container_add(GTK_CONTAINER(container), label);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), info, FALSE, FALSE, 0);
|
||||
return info;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create a list of lists and keep the elements sorted */
|
||||
void add_dc(const char *vendor, const char *product, dc_descriptor_t *descriptor)
|
||||
{
|
||||
struct vendor *dcl = dc_list;
|
||||
struct vendor **dclp = &dc_list;
|
||||
struct product *pl, **plp;
|
||||
|
||||
if (!vendor || !product)
|
||||
return;
|
||||
while (dcl && strcmp(dcl->vendor, vendor) < 0) {
|
||||
dclp = &dcl->next;
|
||||
dcl = dcl->next;
|
||||
}
|
||||
if (!dcl || strcmp(dcl->vendor, vendor)) {
|
||||
dcl = calloc(sizeof(struct vendor), 1);
|
||||
dcl->next = *dclp;
|
||||
*dclp = dcl;
|
||||
dcl->vendor = strdup(vendor);
|
||||
}
|
||||
/* we now have a pointer to the requested vendor */
|
||||
plp = &dcl->productlist;
|
||||
pl = *plp;
|
||||
while (pl && strcmp(pl->product, product) < 0) {
|
||||
plp = &pl->next;
|
||||
pl = pl->next;
|
||||
}
|
||||
if (!pl || strcmp(pl->product, product)) {
|
||||
pl = calloc(sizeof(struct product), 1);
|
||||
pl->next = *plp;
|
||||
*plp = pl;
|
||||
pl->product = strdup(product);
|
||||
}
|
||||
/* one would assume that the vendor / product combinations are unique,
|
||||
* but that is not the case. At the time of this writing, there are two
|
||||
* flavors of the Oceanic OC1 - but looking at the code in libdivecomputer
|
||||
* they are handled exactly the same, so we ignore this issue for now
|
||||
*
|
||||
if (pl->descriptor && memcmp(pl->descriptor, descriptor, sizeof(struct mydescriptor)))
|
||||
printf("duplicate entry with different descriptor for %s - %s\n", vendor, product);
|
||||
else
|
||||
*/
|
||||
pl->descriptor = descriptor;
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
/* fill the vendors and create and fill the respective product stores; return the longest product name
|
||||
* and also the indices of the default vendor / product */
|
||||
static int fill_computer_list(GtkListStore *vendorstore, GtkListStore ***productstore, int *vendor_index, int *product_index)
|
||||
{
|
||||
int i, j, numvendor, width = 10;
|
||||
GtkTreeIter iter;
|
||||
dc_iterator_t *iterator = NULL;
|
||||
dc_descriptor_t *descriptor = NULL;
|
||||
struct mydescriptor *mydescriptor;
|
||||
struct vendor *dcl;
|
||||
struct product *pl;
|
||||
GtkListStore **pstores;
|
||||
|
||||
dc_descriptor_iterator(&iterator);
|
||||
while (dc_iterator_next (iterator, &descriptor) == DC_STATUS_SUCCESS) {
|
||||
const char *vendor = dc_descriptor_get_vendor(descriptor);
|
||||
const char *product = dc_descriptor_get_product(descriptor);
|
||||
add_dc(vendor, product, descriptor);
|
||||
if (product && strlen(product) > width)
|
||||
width = strlen(product);
|
||||
}
|
||||
dc_iterator_free(iterator);
|
||||
/* and add the Uemis Zurich which we are handling internally
|
||||
THIS IS A HACK as we magically have a data structure here that
|
||||
happens to match a data structure that is internal to libdivecomputer;
|
||||
this WILL BREAK if libdivecomputer changes the dc_descriptor struct...
|
||||
eventually the UEMIS code needs to move into libdivecomputer, I guess */
|
||||
mydescriptor = malloc(sizeof(struct mydescriptor));
|
||||
mydescriptor->vendor = "Uemis";
|
||||
mydescriptor->product = "Zurich";
|
||||
mydescriptor->type = DC_FAMILY_NULL;
|
||||
mydescriptor->model = 0;
|
||||
add_dc("Uemis", "Zurich", (dc_descriptor_t *)mydescriptor);
|
||||
dcl = dc_list;
|
||||
numvendor = 0;
|
||||
while (dcl) {
|
||||
numvendor++;
|
||||
dcl = dcl->next;
|
||||
}
|
||||
/* we need an extra vendor for the empty one */
|
||||
numvendor += 1;
|
||||
dcl = dc_list;
|
||||
i = 0;
|
||||
*vendor_index = *product_index = -1;
|
||||
if (*productstore)
|
||||
free(*productstore);
|
||||
pstores = *productstore = malloc(numvendor * sizeof(GtkListStore *));
|
||||
while (dcl) {
|
||||
gtk_list_store_append(vendorstore, &iter);
|
||||
gtk_list_store_set(vendorstore, &iter,
|
||||
0, dcl->vendor,
|
||||
-1);
|
||||
pl = dcl->productlist;
|
||||
pstores[i + 1] = gtk_list_store_new(1, G_TYPE_POINTER);
|
||||
j = 0;
|
||||
while (pl) {
|
||||
gtk_list_store_append(pstores[i + 1], &iter);
|
||||
gtk_list_store_set(pstores[i + 1], &iter,
|
||||
0, pl->descriptor,
|
||||
-1);
|
||||
if (is_default_dive_computer(dcl->vendor, pl->product)) {
|
||||
*vendor_index = i;
|
||||
*product_index = j;
|
||||
}
|
||||
j++;
|
||||
pl = pl->next;
|
||||
}
|
||||
i++;
|
||||
dcl = dcl->next;
|
||||
}
|
||||
/* now add the empty product list in case no vendor is selected */
|
||||
pstores[0] = gtk_list_store_new(1, G_TYPE_POINTER);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static GtkComboBox *dive_computer_selector(GtkWidget *vbox)
|
||||
{
|
||||
GtkWidget *hbox, *vendor_combo_box, *product_combo_box, *frame;
|
||||
GtkListStore *vendor_model;
|
||||
GtkCellRenderer *vendor_renderer, *product_renderer;
|
||||
int vendor_default_index, product_default_index, width;
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
|
||||
|
||||
vendor_model = gtk_list_store_new(1, G_TYPE_POINTER);
|
||||
|
||||
width = fill_computer_list(vendor_model, &product_model, &vendor_default_index, &product_default_index);
|
||||
|
||||
frame = gtk_frame_new(_("Dive computer vendor and product"));
|
||||
gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 3);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
||||
|
||||
vendor_combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(vendor_model));
|
||||
product_combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(product_model[vendor_default_index + 1]));
|
||||
|
||||
g_signal_connect(G_OBJECT(vendor_combo_box), "changed", G_CALLBACK(dive_computer_vendor_changed), product_combo_box);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vendor_combo_box, FALSE, FALSE, 3);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), product_combo_box, FALSE, FALSE, 3);
|
||||
|
||||
vendor_renderer = gtk_cell_renderer_text_new();
|
||||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(vendor_combo_box), vendor_renderer, TRUE);
|
||||
gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(vendor_combo_box), vendor_renderer, render_dc_vendor, NULL, NULL);
|
||||
|
||||
product_renderer = gtk_cell_renderer_text_new();
|
||||
gtk_cell_renderer_set_fixed_size(product_renderer, 10 * width, -1);
|
||||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(product_combo_box), product_renderer, TRUE);
|
||||
gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(product_combo_box), product_renderer, render_dc_product, NULL, NULL);
|
||||
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(vendor_combo_box), vendor_default_index);
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(product_combo_box), product_default_index);
|
||||
|
||||
return GTK_COMBO_BOX(product_combo_box);
|
||||
}
|
||||
|
||||
static GtkComboBox *dc_device_selector(GtkWidget *vbox)
|
||||
{
|
||||
GtkWidget *hbox, *combo_box, *frame;
|
||||
GtkListStore *model;
|
||||
GtkCellRenderer *renderer;
|
||||
int default_index;
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
|
||||
|
||||
model = gtk_list_store_new(1, G_TYPE_STRING);
|
||||
default_index = subsurface_fill_device_list(model);
|
||||
|
||||
frame = gtk_frame_new(_("Device or mount point"));
|
||||
gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 3);
|
||||
|
||||
combo_box = combo_box_with_model_and_entry(model);
|
||||
gtk_container_add(GTK_CONTAINER(frame), combo_box);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), renderer, TRUE);
|
||||
|
||||
if (default_index != -1)
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), default_index);
|
||||
else
|
||||
if (default_dive_computer_device)
|
||||
set_active_text(GTK_COMBO_BOX(combo_box), default_dive_computer_device);
|
||||
|
||||
return GTK_COMBO_BOX(combo_box);
|
||||
}
|
||||
|
||||
/* this prevents clicking the [x] button, while the import thread is still running */
|
||||
static void download_dialog_delete(GtkWidget *w, gpointer data)
|
||||
{
|
||||
/* a no-op */
|
||||
}
|
||||
|
||||
void download_dialog(GtkWidget *w, gpointer data)
|
||||
{
|
||||
int result;
|
||||
char *devname, *ns, *ne;
|
||||
GtkWidget *dialog, *button, *okbutton, *hbox, *vbox, *label, *info = NULL;
|
||||
GtkComboBox *computer, *device;
|
||||
GtkTreeIter iter;
|
||||
device_data_t devicedata = {
|
||||
.devname = NULL,
|
||||
};
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons(_("Download From Dive Computer"),
|
||||
GTK_WINDOW(main_window),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
NULL);
|
||||
g_signal_connect(dialog, "delete-event", G_CALLBACK(download_dialog_delete), NULL);
|
||||
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
label = gtk_label_new(_(" Please select dive computer and device. "));
|
||||
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 3);
|
||||
computer = dive_computer_selector(vbox);
|
||||
device = dc_device_selector(vbox);
|
||||
g_signal_connect(G_OBJECT(computer), "changed", G_CALLBACK(dive_computer_selector_changed), device);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 3);
|
||||
devicedata.progress.bar = gtk_progress_bar_new();
|
||||
gtk_container_add(GTK_CONTAINER(hbox), devicedata.progress.bar);
|
||||
|
||||
force_download = FALSE;
|
||||
button = gtk_check_button_new_with_label(_("Force download of all dives"));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 6);
|
||||
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(force_toggle), NULL);
|
||||
|
||||
prefer_downloaded = FALSE;
|
||||
button = gtk_check_button_new_with_label(_("Always prefer downloaded dive"));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 6);
|
||||
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(prefer_dl_toggle), NULL);
|
||||
|
||||
okbutton = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||
if (!gtk_combo_box_get_active_iter(computer, &iter))
|
||||
gtk_widget_set_sensitive(okbutton, FALSE);
|
||||
|
||||
repeat:
|
||||
gtk_widget_show_all(dialog);
|
||||
gtk_widget_set_sensitive(okbutton, TRUE);
|
||||
result = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
switch (result) {
|
||||
dc_descriptor_t *descriptor;
|
||||
GtkTreeModel *model;
|
||||
|
||||
case GTK_RESPONSE_ACCEPT:
|
||||
/* once the accept event is triggered the dialog becomes non-modal.
|
||||
* lets re-set that */
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
|
||||
if (info)
|
||||
gtk_widget_destroy(info);
|
||||
const char *vendor, *product;
|
||||
|
||||
if (!gtk_combo_box_get_active_iter(computer, &iter))
|
||||
break;
|
||||
|
||||
gtk_widget_set_sensitive(okbutton, FALSE);
|
||||
|
||||
model = gtk_combo_box_get_model(computer);
|
||||
gtk_tree_model_get(model, &iter,
|
||||
0, &descriptor,
|
||||
-1);
|
||||
|
||||
vendor = dc_descriptor_get_vendor(descriptor);
|
||||
product = dc_descriptor_get_product(descriptor);
|
||||
|
||||
devicedata.descriptor = descriptor;
|
||||
devicedata.vendor = vendor;
|
||||
devicedata.product = product;
|
||||
set_default_dive_computer(vendor, product);
|
||||
|
||||
/* get the device name from the combo box entry and set as default */
|
||||
devname = strdup(get_active_text(device));
|
||||
set_default_dive_computer_device(devname);
|
||||
/* clear leading and trailing white space from the device name and also
|
||||
* everything after (and including) the first '(' char. */
|
||||
ns = devname;
|
||||
while (*ns == ' ' || *ns == '\t')
|
||||
ns++;
|
||||
ne = ns;
|
||||
while (*ne && *ne != '(')
|
||||
ne++;
|
||||
*ne = '\0';
|
||||
if (ne > ns)
|
||||
while (*(--ne) == ' ' || *ne == '\t')
|
||||
*ne = '\0';
|
||||
devicedata.devname = ns;
|
||||
devicedata.dialog = GTK_DIALOG(dialog);
|
||||
devicedata.force_download = force_download;
|
||||
force_download = FALSE; /* when retrying we don't want to restart */
|
||||
info = import_dive_computer(&devicedata, GTK_DIALOG(dialog));
|
||||
free((void *)devname);
|
||||
if (info)
|
||||
goto repeat;
|
||||
report_dives(TRUE, prefer_downloaded);
|
||||
break;
|
||||
default:
|
||||
/* it's possible that some dives were downloaded */
|
||||
report_dives(TRUE, prefer_downloaded);
|
||||
break;
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void update_progressbar(progressbar_t *progress, double value)
|
||||
{
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->bar), value);
|
||||
}
|
||||
|
||||
void update_progressbar_text(progressbar_t *progress, const char *text)
|
||||
{
|
||||
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress->bar), text);
|
||||
}
|
||||
#endif
|
1555
equipment.c
1555
equipment.c
File diff suppressed because it is too large
Load diff
264
gps.c
264
gps.c
|
@ -1,264 +0,0 @@
|
|||
/* gps.c */
|
||||
/* Creates the UI displaying the dives locations on a map.
|
||||
*/
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "osm-gps-map.h"
|
||||
|
||||
#include "dive.h"
|
||||
#include "display.h"
|
||||
#include "display-gtk.h"
|
||||
#include "divelist.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk-pixbuf/gdk-pixdata.h>
|
||||
#include "flag.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static OsmGpsMap *map = NULL;
|
||||
|
||||
static void on_close(GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GtkWidget **window = user_data;
|
||||
gtk_grab_remove(widget);
|
||||
gtk_widget_destroy(widget);
|
||||
*window = NULL;
|
||||
}
|
||||
|
||||
struct maplocation {
|
||||
OsmGpsMap *map;
|
||||
double x,y;
|
||||
void (* callback)(float, float);
|
||||
GtkWidget *mapwindow;
|
||||
};
|
||||
|
||||
static void add_location_cb(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
struct maplocation *maplocation = data;
|
||||
OsmGpsMap *map = maplocation->map;
|
||||
OsmGpsMapPoint *pt = osm_gps_map_point_new_degrees(0.0, 0.0);
|
||||
float mark_lat, mark_lon;
|
||||
|
||||
osm_gps_map_convert_screen_to_geographic(map, maplocation->x, maplocation->y, pt);
|
||||
osm_gps_map_point_get_degrees(pt, &mark_lat, &mark_lon);
|
||||
maplocation->callback(mark_lat, mark_lon);
|
||||
gtk_widget_destroy(gtk_widget_get_parent(maplocation->mapwindow));
|
||||
}
|
||||
|
||||
static void map_popup_menu_cb(GtkWidget *w, gpointer data)
|
||||
{
|
||||
GtkWidget *menu, *menuitem, *image;
|
||||
|
||||
menu = gtk_menu_new();
|
||||
menuitem = gtk_image_menu_item_new_with_label(_("Mark location here"));
|
||||
image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
|
||||
g_signal_connect(menuitem, "activate", G_CALLBACK(add_location_cb), data);
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
|
||||
gtk_widget_show_all(menu);
|
||||
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
|
||||
3, gtk_get_current_event_time());
|
||||
}
|
||||
|
||||
static gboolean button_cb(GtkWidget *widget, GdkEventButton *event, gpointer data)
|
||||
{
|
||||
static struct maplocation maplocation = {};
|
||||
if (data && event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||
maplocation.map = (OsmGpsMap *)widget;
|
||||
maplocation.x = event->x;
|
||||
maplocation.y = event->y;
|
||||
maplocation.callback = data;
|
||||
maplocation.mapwindow = widget;
|
||||
map_popup_menu_cb(widget, &maplocation);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* the osm gps map default is to scroll-and-recenter around the mouse position
|
||||
* that is BAT SHIT CRAZY.
|
||||
* So let's do our own scroll handling instead */
|
||||
static gboolean scroll_cb(GtkWidget *widget, GdkEventScroll *event, gpointer data)
|
||||
{
|
||||
OsmGpsMap *map = (OsmGpsMap *)widget;
|
||||
OsmGpsMapPoint *pt, *lt, *rb, *target;
|
||||
float target_lat, target_lon;
|
||||
gint ltx, lty, rbx, rby, target_x, target_y;
|
||||
gint zoom, max_zoom, min_zoom;
|
||||
|
||||
g_object_get(widget, "max-zoom", &max_zoom, "zoom", &zoom, "min-zoom", &min_zoom, NULL);
|
||||
|
||||
pt = osm_gps_map_point_new_degrees(0.0, 0.0);
|
||||
lt = osm_gps_map_point_new_degrees(0.0, 0.0);
|
||||
rb = osm_gps_map_point_new_degrees(0.0, 0.0);
|
||||
target = osm_gps_map_point_new_degrees(0.0, 0.0);
|
||||
|
||||
osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, pt);
|
||||
|
||||
osm_gps_map_get_bbox(map, lt, rb);
|
||||
osm_gps_map_convert_geographic_to_screen(map, lt, <x, <y);
|
||||
osm_gps_map_convert_geographic_to_screen(map, rb, &rbx, &rby);
|
||||
|
||||
if (event->direction == GDK_SCROLL_UP) {
|
||||
if (zoom == max_zoom)
|
||||
return TRUE;
|
||||
|
||||
target_x = event->x + ((ltx + rbx) / 2.0 - (gint)(event->x)) / 2;
|
||||
target_y = event->y + ((lty + rby) / 2.0 - (gint)(event->y)) / 2;
|
||||
|
||||
osm_gps_map_convert_screen_to_geographic(map, target_x, target_y, target);
|
||||
osm_gps_map_point_get_degrees(target, &target_lat, &target_lon);
|
||||
|
||||
osm_gps_map_zoom_in(map);
|
||||
osm_gps_map_set_center(map, target_lat, target_lon);
|
||||
} else if (event->direction == GDK_SCROLL_DOWN) {
|
||||
if (zoom == min_zoom)
|
||||
return TRUE;
|
||||
|
||||
target_x = event->x + ((ltx + rbx) / 2.0 - (gint)(event->x)) * 2;
|
||||
target_y = event->y + ((lty + rby) / 2.0 - (gint)(event->y)) * 2;
|
||||
|
||||
osm_gps_map_convert_screen_to_geographic(map, target_x, target_y, target);
|
||||
osm_gps_map_point_get_degrees(target, &target_lat, &target_lon);
|
||||
|
||||
osm_gps_map_zoom_out(map);
|
||||
osm_gps_map_set_center(map, target_lat, target_lon);
|
||||
}
|
||||
/* don't allow the insane default handler to get its hands on this event */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void add_gps_point(OsmGpsMap *map, float latitude, float longitude)
|
||||
{
|
||||
OsmGpsMapTrack *track;
|
||||
GdkColor dotColor = { 0, 0xFFFF, 0xFFFF, 0x4444 };
|
||||
|
||||
track = g_object_new(OSM_TYPE_GPS_MAP_TRACK,
|
||||
"color", &dotColor,
|
||||
"line-width", (gfloat) 10,
|
||||
"alpha", (gfloat) 0.7,
|
||||
NULL);
|
||||
|
||||
OsmGpsMapPoint *point = osm_gps_map_point_new_degrees(latitude, longitude);
|
||||
osm_gps_map_track_add_point(track, point);
|
||||
osm_gps_map_track_add(map, track);
|
||||
free((void *)point);
|
||||
}
|
||||
|
||||
static void key_press_event(GtkWidget *window, GdkEventKey *event, gpointer data)
|
||||
{
|
||||
if ((event->string != NULL && event->keyval == GDK_Escape) ||
|
||||
(event->string != NULL && event->keyval == GDK_w && (event->state & GDK_CONTROL_MASK))) {
|
||||
gtk_widget_destroy(window);
|
||||
}
|
||||
}
|
||||
|
||||
OsmGpsMap *init_map(void)
|
||||
{
|
||||
OsmGpsMap *map;
|
||||
OsmGpsMapLayer *osd;
|
||||
char *cachedir, *cachebasedir;
|
||||
|
||||
cachebasedir = osm_gps_map_get_default_cache_directory();
|
||||
cachedir = g_strdup(OSM_GPS_MAP_CACHE_AUTO);
|
||||
|
||||
map = g_object_new(OSM_TYPE_GPS_MAP,
|
||||
"map-source", prefs.map_provider,
|
||||
"tile-cache", cachedir,
|
||||
"tile-cache-base", cachebasedir,
|
||||
"proxy-uri", g_getenv("http_proxy"),
|
||||
NULL);
|
||||
osd = g_object_new(OSM_TYPE_GPS_MAP_OSD,
|
||||
"show-scale", TRUE,
|
||||
"show-coordinates", TRUE,
|
||||
"show-crosshair", FALSE,
|
||||
"show-dpad", TRUE,
|
||||
"show-zoom", TRUE,
|
||||
"show-gps-in-dpad", TRUE,
|
||||
"show-gps-in-zoom", FALSE,
|
||||
"dpad-radius", 30,
|
||||
NULL);
|
||||
|
||||
osm_gps_map_layer_add(OSM_GPS_MAP(map), osd);
|
||||
g_object_unref(G_OBJECT(osd));
|
||||
free((void*)cachebasedir);
|
||||
free((void*)cachedir);
|
||||
return map;
|
||||
}
|
||||
|
||||
void show_map(OsmGpsMap *map, GtkWidget **window, struct dive *dive, void (*callback)(float, float))
|
||||
{
|
||||
if (!*window) {
|
||||
/* Enable keyboard navigation */
|
||||
osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_FULLSCREEN, GDK_F11);
|
||||
osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_UP, GDK_Up);
|
||||
osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_DOWN, GDK_Down);
|
||||
osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_LEFT, GDK_Left);
|
||||
osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_RIGHT, GDK_Right);
|
||||
|
||||
*window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_position(GTK_WINDOW(*window), GTK_WIN_POS_MOUSE);
|
||||
gtk_window_set_default_size(GTK_WINDOW(*window), 560, 360);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(*window), 5);
|
||||
gtk_window_set_resizable(GTK_WINDOW(*window), TRUE);
|
||||
gtk_container_add(GTK_CONTAINER(*window), GTK_WIDGET(map));
|
||||
gtk_window_set_transient_for(GTK_WINDOW(*window), GTK_WINDOW(main_window));
|
||||
gtk_window_set_modal(GTK_WINDOW(*window), TRUE);
|
||||
g_signal_connect(*window, "destroy", G_CALLBACK(on_close), (gpointer)window);
|
||||
g_signal_connect(G_OBJECT(map), "scroll-event", G_CALLBACK(scroll_cb), NULL);
|
||||
g_signal_connect(*window, "key_press_event", G_CALLBACK (key_press_event), NULL);
|
||||
}
|
||||
if (callback) {
|
||||
g_signal_connect(G_OBJECT(map), "button-press-event", G_CALLBACK(button_cb), callback);
|
||||
gtk_window_set_title(GTK_WINDOW(*window), _("Use right click to mark dive location at cursor"));
|
||||
} else {
|
||||
gtk_window_set_title(GTK_WINDOW(*window), _("Dive locations"));
|
||||
}
|
||||
gtk_widget_show_all(*window);
|
||||
if (callback)
|
||||
gtk_grab_add(*window);
|
||||
}
|
||||
|
||||
void show_gps_location(struct dive *dive, void (*callback)(float, float))
|
||||
{
|
||||
GdkPixbuf *picture;
|
||||
GError *gerror = NULL;
|
||||
|
||||
double lat = dive->latitude.udeg / 1000000.0;
|
||||
double lng = dive->longitude.udeg / 1000000.0;
|
||||
|
||||
if (!map || !window)
|
||||
map = init_map();
|
||||
if (lat != 0 || lng != 0) {
|
||||
add_gps_point(map, lat, lng);
|
||||
osm_gps_map_set_center_and_zoom(map, lat, lng, 9);
|
||||
picture = gdk_pixbuf_from_pixdata(&flag_pixbuf, TRUE, NULL);
|
||||
if (picture) {
|
||||
osm_gps_map_image_add_with_alignment(map, lat, lng, picture, 0, 1);
|
||||
g_object_unref(picture);
|
||||
} else {
|
||||
printf("error message: %s\n", gerror->message);
|
||||
}
|
||||
} else {
|
||||
osm_gps_map_set_center_and_zoom(map, 0, 0, 1);
|
||||
}
|
||||
show_map(map, &window, dive, callback);
|
||||
}
|
||||
|
||||
void show_gps_locations()
|
||||
{
|
||||
struct dive *dive;
|
||||
int idx;
|
||||
|
||||
if (!window || !map)
|
||||
map = init_map();
|
||||
|
||||
for_each_dive(idx, dive) {
|
||||
if (dive_has_gps_location(dive)) {
|
||||
add_gps_point(map, dive->latitude.udeg / 1000000.0,
|
||||
dive->longitude.udeg / 1000000.0);
|
||||
}
|
||||
}
|
||||
osm_gps_map_set_center_and_zoom(map, 0, 0, 1);
|
||||
|
||||
show_map(map, &window, NULL, NULL);
|
||||
}
|
|
@ -7,9 +7,6 @@
|
|||
#include "device.h"
|
||||
#include "divelist.h"
|
||||
#include "display.h"
|
||||
#ifdef USE_GTK_UI
|
||||
#include "display-gtk.h"
|
||||
#endif
|
||||
|
||||
#include "libdivecomputer.h"
|
||||
#include "libdivecomputer/version.h"
|
||||
|
@ -28,21 +25,6 @@ double progress_bar_fraction = 0.0;
|
|||
static int stoptime, stopdepth, ndl, po2, cns;
|
||||
static bool in_deco, first_temp_is_air;
|
||||
|
||||
#if USE_GTK_UI
|
||||
static GError *error(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start(args, fmt);
|
||||
error = g_error_new_valist(
|
||||
g_quark_from_string("subsurface"),
|
||||
DIVE_ERROR_PARSE, fmt, args);
|
||||
va_end(args);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
static dc_status_t create_parser(device_data_t *devdata, dc_parser_t **parser)
|
||||
{
|
||||
return dc_parser_new(parser, devdata->device);
|
||||
|
|
26
linux.c
26
linux.c
|
@ -9,21 +9,6 @@
|
|||
|
||||
const char system_divelist_default_font[] = "Sans 8";
|
||||
|
||||
void subsurface_flush_conf(void)
|
||||
{
|
||||
/* this is a no-op */
|
||||
}
|
||||
|
||||
void subsurface_close_conf(void)
|
||||
{
|
||||
/* this is a no-op */
|
||||
}
|
||||
|
||||
const char *subsurface_icon_name()
|
||||
{
|
||||
return "subsurface-icon.svg";
|
||||
}
|
||||
|
||||
const char *system_default_filename(void)
|
||||
{
|
||||
const char *home, *user;
|
||||
|
@ -38,17 +23,6 @@ const char *system_default_filename(void)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
const char *subsurface_gettext_domainpath(char *argv0)
|
||||
{
|
||||
if (argv0[0] == '.') {
|
||||
/* we're starting a local copy */
|
||||
return "./share/locale";
|
||||
} else {
|
||||
/* subsurface is installed, so system dir should be fine */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void subsurface_command_line_init(int *argc, char ***argv)
|
||||
{
|
||||
/* this is a no-op */
|
||||
|
|
213
macos.c
213
macos.c
|
@ -5,9 +5,6 @@
|
|||
#include <fnmatch.h>
|
||||
#include "dive.h"
|
||||
#include "display.h"
|
||||
#if USE_GTK_UI
|
||||
#include "display-gtk.h"
|
||||
#endif /* USE_GTK_UI */
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach-o/dyld.h>
|
||||
|
@ -27,142 +24,6 @@
|
|||
|
||||
const char system_divelist_default_font[] = "Arial 10";
|
||||
|
||||
void subsurface_open_conf(void)
|
||||
{
|
||||
/* nothing at this time */
|
||||
}
|
||||
|
||||
void subsurface_unset_conf(const char *name)
|
||||
{
|
||||
CFPreferencesSetAppValue(CFSTR_VAR(name), NULL, SUBSURFACE_PREFERENCES);
|
||||
}
|
||||
|
||||
void subsurface_set_conf(const char *name, const char *value)
|
||||
{
|
||||
CFPreferencesSetAppValue(CFSTR_VAR(name), CFSTR_VAR(value), SUBSURFACE_PREFERENCES);
|
||||
}
|
||||
|
||||
void subsurface_set_conf_bool(const char *name, bool value)
|
||||
{
|
||||
CFPreferencesSetAppValue(CFSTR_VAR(name),
|
||||
value ? kCFBooleanTrue : kCFBooleanFalse, SUBSURFACE_PREFERENCES);
|
||||
}
|
||||
|
||||
void subsurface_set_conf_int(const char *name, int value)
|
||||
{
|
||||
CFNumberRef numRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
|
||||
CFPreferencesSetAppValue(CFSTR_VAR(name), numRef, SUBSURFACE_PREFERENCES);
|
||||
}
|
||||
|
||||
const char *subsurface_get_conf(const char *name)
|
||||
{
|
||||
CFPropertyListRef strpref;
|
||||
|
||||
strpref = CFPreferencesCopyAppValue(CFSTR_VAR(name), SUBSURFACE_PREFERENCES);
|
||||
if (!strpref)
|
||||
return NULL;
|
||||
return strdup(CFStringGetCStringPtr(strpref, kCFStringEncodingMacRoman));
|
||||
}
|
||||
|
||||
int subsurface_get_conf_bool(const char *name)
|
||||
{
|
||||
Boolean boolpref, exists;
|
||||
|
||||
boolpref = CFPreferencesGetAppBooleanValue(CFSTR_VAR(name), SUBSURFACE_PREFERENCES, &exists);
|
||||
if (!exists)
|
||||
return -1;
|
||||
return boolpref;
|
||||
}
|
||||
|
||||
int subsurface_get_conf_int(const char *name)
|
||||
{
|
||||
Boolean exists;
|
||||
CFIndex value;
|
||||
|
||||
value = CFPreferencesGetAppIntegerValue(CFSTR_VAR(name), SUBSURFACE_PREFERENCES, &exists);
|
||||
if (!exists)
|
||||
return -1;
|
||||
return value;
|
||||
}
|
||||
|
||||
void subsurface_flush_conf(void)
|
||||
{
|
||||
int ok = CFPreferencesAppSynchronize(SUBSURFACE_PREFERENCES);
|
||||
if (!ok)
|
||||
fprintf(stderr,"Could not save preferences\n");
|
||||
}
|
||||
|
||||
void subsurface_close_conf(void)
|
||||
{
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
int subsurface_fill_device_list(GtkListStore *store)
|
||||
{
|
||||
int i = 0;
|
||||
int index = -1;
|
||||
GtkTreeIter iter;
|
||||
GDir *dev;
|
||||
const char *name;
|
||||
|
||||
dev = g_dir_open("/dev", 0, NULL);
|
||||
while (dev && (name = g_dir_read_name(dev)) != NULL) {
|
||||
if (strstr(name, "usbserial") ||
|
||||
(strstr(name, "SerialPort") && strstr(name, "cu"))) {
|
||||
int len = strlen(name) + 6;
|
||||
char *devicename = malloc(len);
|
||||
snprintf(devicename, len, "/dev/%s", name);
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
0, devicename, -1);
|
||||
if (is_default_dive_computer_device(devicename))
|
||||
index = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (dev)
|
||||
g_dir_close(dev);
|
||||
dev = g_dir_open("/Volumes", 0, NULL);
|
||||
while (dev && (name = g_dir_read_name(dev)) != NULL) {
|
||||
if (strstr(name, "UEMISSDA")) {
|
||||
int len = strlen(name) + 10;
|
||||
char *devicename = malloc(len);
|
||||
snprintf(devicename, len, "/Volumes/%s", name);
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
0, devicename, -1);
|
||||
if (is_default_dive_computer_device(devicename))
|
||||
index = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (dev)
|
||||
g_dir_close(dev);
|
||||
if (i == 0) {
|
||||
/* if we can't find anything, use the default */
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
0, "/dev/tty.SLAB_USBtoUART", -1);
|
||||
if (is_default_dive_computer_device("/dev/tty.SLAB_USBtoUART"))
|
||||
index = i;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *subsurface_icon_name()
|
||||
{
|
||||
static char path[PATH_MAX];
|
||||
|
||||
#if USE_GTK_UI
|
||||
snprintf(path, sizeof(path), "%s/%s", gtkosx_application_get_resource_path(), ICON_NAME);
|
||||
#else
|
||||
/* need Qt path */
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
|
||||
const char *system_default_filename(void)
|
||||
{
|
||||
const char *home, *user;
|
||||
|
@ -177,71 +38,6 @@ const char *system_default_filename(void)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
const char *subsurface_gettext_domainpath(char *argv0)
|
||||
{
|
||||
/* on a Mac we ignore the argv0 argument and instead use the resource_path
|
||||
* to figure out where to find the translation files */
|
||||
#if USE_GTK_UI
|
||||
static char buffer[PATH_MAX];
|
||||
const char *resource_path = gtkosx_application_get_resource_path();
|
||||
if (resource_path) {
|
||||
snprintf(buffer, sizeof(buffer), "%s/share/locale", resource_path);
|
||||
return buffer;
|
||||
}
|
||||
#endif /* USE_GTK_UI */
|
||||
return "./share/locale";
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
static void show_main_window(GtkWidget *w, gpointer data)
|
||||
{
|
||||
gtk_widget_show(main_window);
|
||||
gtk_window_present(GTK_WINDOW(main_window));
|
||||
}
|
||||
|
||||
void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar,
|
||||
GtkWidget *vbox, GtkUIManager *ui_manager)
|
||||
{
|
||||
GtkWidget *menu_item, *sep;
|
||||
static char path[PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), "%s/xslt", gtkosx_application_get_resource_path());
|
||||
setenv("SUBSURFACE_XSLT_PATH", path, TRUE);
|
||||
|
||||
g_object_set(G_OBJECT(settings), "gtk-font-name", UI_FONT, NULL);
|
||||
|
||||
osx_app = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
|
||||
gtk_widget_hide (menubar);
|
||||
gtkosx_application_set_menu_bar(osx_app, GTK_MENU_SHELL(menubar));
|
||||
|
||||
sep = gtk_ui_manager_get_widget(ui_manager, "/MainMenu/FileMenu/Separator3");
|
||||
if (sep)
|
||||
gtk_widget_destroy(sep);
|
||||
|
||||
menu_item = gtk_ui_manager_get_widget(ui_manager, "/MainMenu/FileMenu/Quit");
|
||||
gtk_widget_hide (menu_item);
|
||||
menu_item = gtk_ui_manager_get_widget(ui_manager, "/MainMenu/Help/About");
|
||||
gtkosx_application_insert_app_menu_item(osx_app, menu_item, 0);
|
||||
|
||||
sep = gtk_separator_menu_item_new();
|
||||
g_object_ref(sep);
|
||||
gtkosx_application_insert_app_menu_item (osx_app, sep, 1);
|
||||
|
||||
menu_item = gtk_ui_manager_get_widget(ui_manager, "/MainMenu/FileMenu/Preferences");
|
||||
gtkosx_application_insert_app_menu_item(osx_app, menu_item, 2);
|
||||
|
||||
sep = gtk_separator_menu_item_new();
|
||||
g_object_ref(sep);
|
||||
gtkosx_application_insert_app_menu_item (osx_app, sep, 3);
|
||||
|
||||
gtkosx_application_set_use_quartz_accelerators(osx_app, TRUE);
|
||||
g_signal_connect(osx_app,"NSApplicationDidBecomeActive",G_CALLBACK(show_main_window),NULL);
|
||||
g_signal_connect(osx_app, "NSApplicationBlockTermination", G_CALLBACK(on_delete), NULL);
|
||||
|
||||
gtkosx_application_ready(osx_app);
|
||||
}
|
||||
#endif /* UES_GTK_UI */
|
||||
|
||||
void subsurface_command_line_init(int *argc, char ***argv)
|
||||
{
|
||||
/* this is a no-op */
|
||||
|
@ -257,15 +53,6 @@ bool subsurface_os_feature_available(os_feature_t f)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
bool subsurface_launch_for_uri(const char* uri)
|
||||
{
|
||||
CFURLRef urlref = CFURLCreateWithBytes(NULL, uri, strlen(uri), kCFStringEncodingMacRoman, NULL);
|
||||
OSStatus status = LSOpenCFURLRef(urlref, NULL);
|
||||
if (status)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int enumerate_devices (device_callback_t callback, void *userdata)
|
||||
{
|
||||
int index = -1;
|
||||
|
|
214
planner.c
214
planner.c
|
@ -496,7 +496,7 @@ static int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, int gnr)
|
|||
return stoplevels;
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
#if DO_WE_WANT_THIS_IN_QT
|
||||
static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
|
||||
{
|
||||
char buffer[20000];
|
||||
|
@ -722,12 +722,11 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
|||
record_dive(dive);
|
||||
stopidx--;
|
||||
}
|
||||
#if USE_GTK_UI
|
||||
|
||||
#if DO_WE_WANT_THIS_IN_QT
|
||||
add_plan_to_notes(diveplan, dive);
|
||||
/* now make the dive visible in the dive list */
|
||||
report_dives(FALSE, FALSE);
|
||||
show_and_select_dive(dive);
|
||||
#endif
|
||||
|
||||
error_exit:
|
||||
free(stoplevels);
|
||||
free(gaschanges);
|
||||
|
@ -761,30 +760,6 @@ static int get_tenths(const char *begin, const char **endp)
|
|||
return value;
|
||||
}
|
||||
|
||||
static int get_thousandths(const char *begin, const char **endp)
|
||||
{
|
||||
char *end;
|
||||
int value = strtol(begin, &end, 10);
|
||||
|
||||
if (begin == end)
|
||||
return -1;
|
||||
value *= 1000;
|
||||
|
||||
/* now deal with up to three more digits after decimal point */
|
||||
if (*end == '.') {
|
||||
int factor = 100;
|
||||
do {
|
||||
++end;
|
||||
if (!isdigit(*end))
|
||||
break;
|
||||
value += (*end - '0') * factor;
|
||||
factor /= 10;
|
||||
} while (factor);
|
||||
}
|
||||
*endp = end;
|
||||
return value;
|
||||
}
|
||||
|
||||
static int get_permille(const char *begin, const char **end)
|
||||
{
|
||||
int value = get_tenths(begin, end);
|
||||
|
@ -835,112 +810,6 @@ int validate_gas(const char *text, int *o2_p, int *he_p)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int validate_time(const char *text, int *sec_p, int *rel_p)
|
||||
{
|
||||
int min, sec, rel;
|
||||
char *end;
|
||||
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
|
||||
rel = 1;
|
||||
if (*text == '+') {
|
||||
rel = 1;
|
||||
text++;
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
} else if (*text == '@') {
|
||||
rel = 0;
|
||||
text++;
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
}
|
||||
|
||||
min = strtol(text, &end, 10);
|
||||
if (text == end)
|
||||
return 0;
|
||||
|
||||
if (min < 0 || min > 1000)
|
||||
return 0;
|
||||
|
||||
/* Ok, minutes look ok */
|
||||
text = end;
|
||||
sec = 0;
|
||||
if (*text == ':') {
|
||||
text++;
|
||||
sec = strtol(text, &end, 10);
|
||||
if (end != text+2)
|
||||
return 0;
|
||||
if (sec < 0)
|
||||
return 0;
|
||||
text = end;
|
||||
if (*text == ':') {
|
||||
if (sec >= 60)
|
||||
return 0;
|
||||
min = min*60 + sec;
|
||||
text++;
|
||||
sec = strtol(text, &end, 10);
|
||||
if (end != text+2)
|
||||
return 0;
|
||||
if (sec < 0)
|
||||
return 0;
|
||||
text = end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe we should accept 'min' at the end? */
|
||||
if (isspace(*text))
|
||||
text++;
|
||||
if (*text)
|
||||
return 0;
|
||||
|
||||
*sec_p = min*60 + sec;
|
||||
*rel_p = rel;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_depth(const char *text, int *mm_p)
|
||||
{
|
||||
int depth, imperial;
|
||||
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
depth = get_tenths(text, &text);
|
||||
if (depth < 0)
|
||||
return 0;
|
||||
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
|
||||
imperial = get_units()->length == FEET;
|
||||
if (*text == 'm') {
|
||||
imperial = 0;
|
||||
text++;
|
||||
} else if (!strcasecmp(text, tr("ft"))) {
|
||||
imperial = 1;
|
||||
text += 2;
|
||||
}
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
if (*text)
|
||||
return 0;
|
||||
|
||||
if (imperial) {
|
||||
depth = feet_to_mm(depth / 10.0);
|
||||
} else {
|
||||
depth *= 100;
|
||||
}
|
||||
*mm_p = depth;
|
||||
/* we don't support extreme depths */
|
||||
if (depth > 400000)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_po2(const char *text, int *mbar_po2)
|
||||
{
|
||||
int po2;
|
||||
|
@ -964,78 +833,3 @@ int validate_po2(const char *text, int *mbar_po2)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int validate_volume(const char *text, int *sac)
|
||||
{
|
||||
int volume, imperial;
|
||||
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
volume = get_thousandths(text, &text);
|
||||
if (volume < 0)
|
||||
return 0;
|
||||
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
|
||||
imperial = get_units()->volume == CUFT;
|
||||
if (*text == 'l') {
|
||||
imperial = 0;
|
||||
text++;
|
||||
} else if (!strncasecmp(text, tr("cuft"), 4)) {
|
||||
imperial = 1;
|
||||
text += 4;
|
||||
}
|
||||
while (isspace(*text) || *text == '/')
|
||||
text++;
|
||||
if (!strncasecmp(text, tr("min"), 3))
|
||||
text += 3;
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
if (*text)
|
||||
return 0;
|
||||
if (imperial)
|
||||
volume = cuft_to_l(volume) + 0.5; /* correct for mcuft -> ml */
|
||||
*sac = volume;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
struct diveplan diveplan = {};
|
||||
char *cache_data = NULL;
|
||||
struct dive *planned_dive = NULL;
|
||||
|
||||
/* make a copy of the diveplan so far and display the corresponding dive */
|
||||
void show_planned_dive(char **error_string_p)
|
||||
{
|
||||
struct diveplan tempplan;
|
||||
struct divedatapoint *dp, **dpp;
|
||||
|
||||
memcpy(&tempplan, &diveplan, sizeof(struct diveplan));
|
||||
dpp = &tempplan.dp;
|
||||
dp = diveplan.dp;
|
||||
while (dp && *dpp) {
|
||||
*dpp = malloc(sizeof(struct divedatapoint));
|
||||
memcpy(*dpp, dp, sizeof(struct divedatapoint));
|
||||
dp = dp->next;
|
||||
dpp = &(*dpp)->next;
|
||||
}
|
||||
#if DEBUG_PLAN & 1
|
||||
printf("in show_planned_dive:\n");
|
||||
dump_plan(&tempplan);
|
||||
#endif
|
||||
plan(&tempplan, &cache_data, &planned_dive, error_string_p);
|
||||
free_dps(tempplan.dp);
|
||||
}
|
||||
|
||||
/* Subsurface follows the lead of most divecomputers to use times
|
||||
* without timezone - so all times are implicitly assumed to be
|
||||
* local time of the dive location; so in order to give the current
|
||||
* time in that way we actually need to add the timezone offset */
|
||||
timestamp_t current_time_notz(void)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm *local = localtime(&now);
|
||||
return utc_mktime(local);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,10 +7,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
extern int validate_gas(const char *text, int *o2_p, int *he_p);
|
||||
extern int validate_time(const char *text, int *sec_p, int *rel_p);
|
||||
extern int validate_depth(const char *text, int *mm_p);
|
||||
extern int validate_po2(const char *text, int *mbar_po2);
|
||||
extern int validate_volume(const char *text, int *sac);
|
||||
extern timestamp_t current_time_notz(void);
|
||||
extern void show_planned_dive(char **error_string_p);
|
||||
extern int add_duration_to_nth_dp(struct diveplan *diveplan, int idx, int duration, bool is_rel);
|
||||
|
|
|
@ -26,9 +26,6 @@ struct preferences default_prefs = {
|
|||
.font_size = 14.0,
|
||||
.show_invalid = FALSE,
|
||||
.show_time = FALSE,
|
||||
#ifdef USE_GTK_UI
|
||||
.map_provider = OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct units *get_units()
|
||||
|
|
|
@ -25,9 +25,6 @@
|
|||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "display.h"
|
||||
#if USE_GTK_UI
|
||||
#include "display-gtk.h"
|
||||
#endif
|
||||
#define ERR_FS_ALMOST_FULL QT_TR_NOOP("Uemis Zurich: File System is almost full\nDisconnect/reconnect the dive computer\nand click \'Retry\'")
|
||||
#define ERR_FS_FULL QT_TR_NOOP("Uemis Zurich: File System is full\nDisconnect/reconnect the dive computer\nand try again")
|
||||
#define ERR_FS_SHORT_WRITE QT_TR_NOOP("Short write to req.txt file\nIs the Uemis Zurich plugged in correctly?")
|
||||
|
@ -52,35 +49,8 @@ static int number_of_files;
|
|||
static char *mbuf = NULL;
|
||||
static int mbuf_size = 0;
|
||||
|
||||
#if USE_GTK_UI
|
||||
struct argument_block {
|
||||
const char *mountpath;
|
||||
progressbar_t *progress;
|
||||
bool force_download;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int nr_divespots = 0;
|
||||
|
||||
#if USE_GTK_UI
|
||||
static int import_thread_done = 0, import_thread_cancelled;
|
||||
static const char *progress_bar_text = "";
|
||||
static double progress_bar_fraction = 0.0;
|
||||
|
||||
static GError *error(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
GError *error;
|
||||
|
||||
va_start(args, fmt);
|
||||
error = g_error_new_valist(
|
||||
g_quark_from_string("subsurface"),
|
||||
DIVE_ERROR_PARSE, fmt, args);
|
||||
va_end(args);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* helper function to parse the Uemis data structures */
|
||||
static void uemis_ts(char *buffer, void *_when)
|
||||
{
|
||||
|
@ -905,63 +875,3 @@ bail:
|
|||
return result;
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
static void *pthread_wrapper(void *_data)
|
||||
{
|
||||
struct argument_block *args = _data;
|
||||
const char *err_string = do_uemis_download(args);
|
||||
import_thread_done = 1;
|
||||
return (void *)err_string;
|
||||
}
|
||||
|
||||
/* this simply ends the dialog without a response and asks not to be fired again
|
||||
* as we set this function up in every loop while uemis_download is waiting for
|
||||
* the download to finish */
|
||||
static bool timeout_func(gpointer _data)
|
||||
{
|
||||
GtkDialog *dialog = _data;
|
||||
if (!import_thread_cancelled)
|
||||
gtk_dialog_response(dialog, GTK_RESPONSE_NONE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GError *uemis_download(const char *mountpath, progressbar_t *progress,
|
||||
GtkDialog *dialog, bool force_download)
|
||||
{
|
||||
pthread_t pthread;
|
||||
void *retval;
|
||||
struct argument_block args = {mountpath, progress, force_download};
|
||||
|
||||
/* I'm sure there is some better interface for waiting on a thread in a UI main loop */
|
||||
import_thread_done = 0;
|
||||
progress_bar_text = "";
|
||||
progress_bar_fraction = 0.0;
|
||||
pthread_create(&pthread, NULL, pthread_wrapper, &args);
|
||||
/* loop here until the import is done or was cancelled by the user;
|
||||
* in order to get control back from gtk we register a timeout function
|
||||
* that ends the dialog with no response every 100ms; we then update the
|
||||
* progressbar and setup the timeout again - unless of course the user
|
||||
* pressed cancel, in which case we just wait for the download thread
|
||||
* to react to that and exit */
|
||||
while (!import_thread_done) {
|
||||
if (!import_thread_cancelled) {
|
||||
int result;
|
||||
g_timeout_add(100, timeout_func, dialog);
|
||||
update_progressbar(args.progress, progress_bar_fraction);
|
||||
update_progressbar_text(args.progress, progress_bar_text);
|
||||
result = gtk_dialog_run(dialog);
|
||||
if (result == GTK_RESPONSE_CANCEL)
|
||||
import_thread_cancelled = TRUE;
|
||||
} else {
|
||||
update_progressbar(args.progress, progress_bar_fraction);
|
||||
update_progressbar_text(args.progress, tr("Cancelled, exiting cleanly..."));
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
if (pthread_join(pthread, &retval) < 0)
|
||||
return error("Pthread return with error");
|
||||
if (retval)
|
||||
return error(retval);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
409
webservice.c
409
webservice.c
|
@ -1,409 +0,0 @@
|
|||
#include <glib/gi18n.h>
|
||||
#include <libsoup/soup.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/parser.h>
|
||||
#include "dive.h"
|
||||
#include "divelist.h"
|
||||
#include "display-gtk.h"
|
||||
#include "file.h"
|
||||
|
||||
struct dive_table gps_location_table;
|
||||
static gboolean merge_locations_into_dives(void);
|
||||
|
||||
enum {
|
||||
DD_STATUS_OK,
|
||||
DD_STATUS_ERROR_CONNECT,
|
||||
DD_STATUS_ERROR_ID,
|
||||
DD_STATUS_ERROR_PARSE,
|
||||
};
|
||||
|
||||
static const gchar *download_dialog_status_text(const gint status)
|
||||
{
|
||||
switch (status) {
|
||||
case DD_STATUS_ERROR_CONNECT:
|
||||
return _("Connection Error: ");
|
||||
case DD_STATUS_ERROR_ID:
|
||||
return _("Invalid user identifier!");
|
||||
case DD_STATUS_ERROR_PARSE:
|
||||
return _("Cannot parse response!");
|
||||
}
|
||||
return _("Download Success!");
|
||||
}
|
||||
|
||||
/* provides a state of the download dialog contents and the downloaded xml */
|
||||
struct download_dialog_state {
|
||||
GtkWidget *uid;
|
||||
GtkWidget *status;
|
||||
GtkWidget *apply;
|
||||
gchar *xmldata;
|
||||
guint xmldata_len;
|
||||
};
|
||||
|
||||
/* this method uses libsoup as a backend. if there are some portability,
|
||||
* compatibility or speed issues, libcurl is a better choice. */
|
||||
gboolean webservice_request_user_xml(const gchar *user_id,
|
||||
gchar **data,
|
||||
guint *len,
|
||||
guint *status_code)
|
||||
{
|
||||
SoupMessage *msg;
|
||||
SoupSession *session;
|
||||
gboolean ret = FALSE;
|
||||
gchar url[256] = {0};
|
||||
|
||||
session = soup_session_async_new();
|
||||
strcat(url, "http://api.hohndel.org/api/dive/get/?login=");
|
||||
strncat(url, user_id, sizeof(url) - strlen(url) - 1);
|
||||
msg = soup_message_new("GET", url);
|
||||
soup_message_headers_append(msg->request_headers, "Accept", "text/xml");
|
||||
soup_session_send_message(session, msg);
|
||||
if SOUP_STATUS_IS_SUCCESSFUL(msg->status_code) {
|
||||
*len = (guint)msg->response_body->length;
|
||||
*data = strdup((gchar *)msg->response_body->data);
|
||||
ret = TRUE;
|
||||
} else {
|
||||
*len = 0;
|
||||
*data = NULL;
|
||||
}
|
||||
*status_code = msg->status_code;
|
||||
soup_session_abort(session);
|
||||
g_object_unref(G_OBJECT(msg));
|
||||
g_object_unref(G_OBJECT(session));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* requires that there is a <download> or <error> tag under the <root> tag */
|
||||
static void download_dialog_traverse_xml(xmlNodePtr node, guint *download_status)
|
||||
{
|
||||
xmlNodePtr cur_node;
|
||||
for (cur_node = node; cur_node; cur_node = cur_node->next) {
|
||||
if ((!strcmp((const char *)cur_node->name, (const char *)"download")) &&
|
||||
(!strcmp((const char *)xmlNodeGetContent(cur_node), (const char *)"ok"))) {
|
||||
*download_status = DD_STATUS_OK;
|
||||
return;
|
||||
} else if (!strcmp((const char *)cur_node->name, (const char *)"error")) {
|
||||
*download_status = DD_STATUS_ERROR_ID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static guint download_dialog_parse_response(gchar *xmldata, guint len)
|
||||
{
|
||||
xmlNodePtr root;
|
||||
xmlDocPtr doc = xmlParseMemory(xmldata, len);
|
||||
guint status = DD_STATUS_ERROR_PARSE;
|
||||
|
||||
if (!doc)
|
||||
return DD_STATUS_ERROR_PARSE;
|
||||
root = xmlDocGetRootElement(doc);
|
||||
if (!root) {
|
||||
status = DD_STATUS_ERROR_PARSE;
|
||||
goto end;
|
||||
}
|
||||
if (root->children)
|
||||
download_dialog_traverse_xml(root->children, &status);
|
||||
end:
|
||||
xmlFreeDoc(doc);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void download_dialog_connect_cb(GtkWidget *w, gpointer data)
|
||||
{
|
||||
struct download_dialog_state *state = (struct download_dialog_state *)data;
|
||||
const gchar *uid = gtk_entry_get_text(GTK_ENTRY(state->uid));
|
||||
guint len, status_connect, status_xml;
|
||||
gchar *xmldata;
|
||||
gboolean ret;
|
||||
gchar err[256] = {0};
|
||||
|
||||
gtk_label_set_text(GTK_LABEL(state->status), _("Connecting..."));
|
||||
gtk_widget_set_sensitive(state->apply, FALSE);
|
||||
ret = webservice_request_user_xml(uid, &xmldata, &len, &status_connect);
|
||||
if (ret) {
|
||||
status_xml = download_dialog_parse_response(xmldata, len);
|
||||
gtk_label_set_text(GTK_LABEL(state->status), download_dialog_status_text(status_xml));
|
||||
if (status_xml != DD_STATUS_OK)
|
||||
ret = FALSE;
|
||||
} else {
|
||||
snprintf(err, sizeof(err), "%s %u!", download_dialog_status_text(DD_STATUS_ERROR_CONNECT), status_connect);
|
||||
gtk_label_set_text(GTK_LABEL(state->status), err);
|
||||
}
|
||||
state->xmldata = xmldata;
|
||||
state->xmldata_len = len;
|
||||
gtk_widget_set_sensitive(state->apply, ret);
|
||||
}
|
||||
|
||||
static void download_dialog_release_xml(struct download_dialog_state *state)
|
||||
{
|
||||
if (state->xmldata)
|
||||
free((void *)state->xmldata);
|
||||
}
|
||||
|
||||
static void clear_table(struct dive_table *table)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < table->nr; i++)
|
||||
free(table->dives[i]);
|
||||
table->nr = 0;
|
||||
}
|
||||
|
||||
static void download_dialog_response_cb(GtkDialog *d, gint response, gpointer data)
|
||||
{
|
||||
struct download_dialog_state *state = (struct download_dialog_state *)data;
|
||||
switch (response) {
|
||||
case GTK_RESPONSE_HELP:
|
||||
/* open webservice api page */
|
||||
subsurface_launch_for_uri("http://api.hohndel.org/");
|
||||
break;
|
||||
case GTK_RESPONSE_ACCEPT:
|
||||
/* apply download */
|
||||
clear_table(&gps_location_table);
|
||||
parse_xml_buffer(_("Webservice"), state->xmldata, state->xmldata_len, &gps_location_table, NULL);
|
||||
/* now merge the data in the gps_location table into the dive_table */
|
||||
if (merge_locations_into_dives()) {
|
||||
mark_divelist_changed(TRUE);
|
||||
#if USE_GTK_UI
|
||||
dive_list_update_dives();
|
||||
#endif
|
||||
}
|
||||
/* store last entered uid in config */
|
||||
subsurface_set_conf("webservice_uid", gtk_entry_get_text(GTK_ENTRY(state->uid)));
|
||||
default:
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
gtk_widget_destroy(GTK_WIDGET(d));
|
||||
download_dialog_release_xml(state);
|
||||
free(state);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean is_automatic_fix(struct dive *gpsfix)
|
||||
{
|
||||
if (gpsfix && gpsfix->location &&
|
||||
(!strcmp(gpsfix->location, "automatic fix") ||
|
||||
!strcmp(gpsfix->location, "Auto-created dive")))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define SAME_GROUP 6 * 3600 // six hours
|
||||
|
||||
/* returns TRUE if dive_table was changed */
|
||||
static gboolean merge_locations_into_dives(void)
|
||||
{
|
||||
int i, nr = 0, changed = 0;
|
||||
struct dive *gpsfix, *last_named_fix = NULL, *dive;
|
||||
|
||||
sort_table(&gps_location_table);
|
||||
|
||||
for_each_gps_location(i, gpsfix) {
|
||||
if (is_automatic_fix(gpsfix)) {
|
||||
dive = find_dive_including(gpsfix->when);
|
||||
if (dive && !dive_has_gps_location(dive)) {
|
||||
#if DEBUG_WEBSERVICE
|
||||
struct tm tm;
|
||||
utc_mkdate(gpsfix->when, &tm);
|
||||
printf("found dive named %s @ %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||
gpsfix->location,
|
||||
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
#endif
|
||||
changed++;
|
||||
copy_gps_location(gpsfix, dive);
|
||||
}
|
||||
} else {
|
||||
if (last_named_fix && dive_within_time_range(last_named_fix, gpsfix->when, SAME_GROUP)) {
|
||||
nr++;
|
||||
} else {
|
||||
nr = 1;
|
||||
last_named_fix = gpsfix;
|
||||
}
|
||||
dive = find_dive_n_near(gpsfix->when, nr, SAME_GROUP);
|
||||
if (dive) {
|
||||
if (!dive_has_gps_location(dive)) {
|
||||
copy_gps_location(gpsfix, dive);
|
||||
changed++;
|
||||
}
|
||||
if (!dive->location) {
|
||||
dive->location = strdup(gpsfix->location);
|
||||
changed++;
|
||||
}
|
||||
} else {
|
||||
struct tm tm;
|
||||
utc_mkdate(gpsfix->when, &tm);
|
||||
#if DEBUG_WEBSERVICE
|
||||
printf("didn't find dive matching gps fix named %s @ %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||
gpsfix->location,
|
||||
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed > 0;
|
||||
}
|
||||
|
||||
void webservice_download_dialog(void)
|
||||
{
|
||||
const guint pad = 6;
|
||||
/* user entered value should be stored in the config */
|
||||
const gchar *current_uid = subsurface_get_conf("webservice_uid");
|
||||
GtkWidget *dialog, *vbox, *status, *info, *uid;
|
||||
GtkWidget *frame_uid, *frame_status, *download, *image, *apply;
|
||||
struct download_dialog_state *state = calloc(1, sizeof(struct download_dialog_state));
|
||||
gboolean has_previous_uid = TRUE;
|
||||
|
||||
if (!current_uid) {
|
||||
current_uid = "";
|
||||
has_previous_uid = FALSE;
|
||||
}
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons(_("Download From Web Service"),
|
||||
GTK_WINDOW(main_window),
|
||||
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_APPLY,
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_REJECT,
|
||||
GTK_STOCK_HELP,
|
||||
GTK_RESPONSE_HELP,
|
||||
NULL);
|
||||
|
||||
apply = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||
gtk_widget_set_sensitive(apply, FALSE);
|
||||
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
info = gtk_label_new(_("Enter a user identifier and press 'Download'."
|
||||
" Once the download is complete you can press 'Apply'"
|
||||
" if you wish to apply the changes."));
|
||||
gtk_label_set_line_wrap(GTK_LABEL(info), TRUE);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), info, FALSE, TRUE, 0);
|
||||
gtk_misc_set_padding(GTK_MISC(info), pad, pad);
|
||||
|
||||
frame_uid = gtk_frame_new(_("User Identifier"));
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame_uid, FALSE, TRUE, pad);
|
||||
uid = gtk_entry_new();
|
||||
gtk_container_add(GTK_CONTAINER(frame_uid), uid);
|
||||
gtk_entry_set_max_length(GTK_ENTRY(uid), 30);
|
||||
gtk_entry_set_text(GTK_ENTRY(uid), current_uid);
|
||||
|
||||
download = gtk_button_new_with_label(_(" Download"));
|
||||
image = gtk_image_new_from_stock(GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU);
|
||||
gtk_button_set_image(GTK_BUTTON(download), image);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), download, FALSE, TRUE, pad);
|
||||
g_signal_connect(download, "clicked", G_CALLBACK(download_dialog_connect_cb), (gpointer)state);
|
||||
|
||||
frame_status = gtk_frame_new(_("Status"));
|
||||
status = gtk_label_new(_("Idle"));
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame_status, FALSE, TRUE, pad);
|
||||
gtk_container_add(GTK_CONTAINER(frame_status), status);
|
||||
gtk_misc_set_padding(GTK_MISC(status), pad, pad);
|
||||
|
||||
state->uid = uid;
|
||||
state->status = status;
|
||||
state->apply = apply;
|
||||
|
||||
g_signal_connect(dialog, "response", G_CALLBACK(download_dialog_response_cb), (gpointer)state);
|
||||
gtk_widget_show_all(dialog);
|
||||
if (has_previous_uid)
|
||||
free((void *)current_uid);
|
||||
}
|
||||
|
||||
static gboolean divelogde_dialog(const char **user, const char **pass)
|
||||
{
|
||||
GtkWidget *dialog, *vbox, *info, *frame_user, *frame_pass, *uid, *pwd;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
*user = subsurface_get_conf("divelogde_user");
|
||||
*pass = subsurface_get_conf("divelogde_pass");
|
||||
dialog = gtk_dialog_new_with_buttons(_("Upload to divelogs.de"),
|
||||
GTK_WINDOW(main_window),
|
||||
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_APPLY,
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
info = gtk_label_new(_("Please enter your userid and password for divelogs.de. "
|
||||
"The selected dives will be added to your account"));
|
||||
gtk_label_set_line_wrap(GTK_LABEL(info), TRUE);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), info, FALSE, TRUE, 0);
|
||||
gtk_misc_set_padding(GTK_MISC(info), 6, 6);
|
||||
|
||||
frame_user = gtk_frame_new(_("User Identifier"));
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame_user, FALSE, TRUE, 6);
|
||||
uid = gtk_entry_new();
|
||||
gtk_container_add(GTK_CONTAINER(frame_user), uid);
|
||||
gtk_entry_set_max_length(GTK_ENTRY(uid), 40);
|
||||
gtk_entry_set_text(GTK_ENTRY(uid), *user ?: "");
|
||||
gtk_entry_set_activates_default(GTK_ENTRY(uid), TRUE);
|
||||
|
||||
frame_pass = gtk_frame_new(_("Password"));
|
||||
gtk_box_pack_start(GTK_BOX(vbox), frame_pass, FALSE, TRUE, 6);
|
||||
pwd = gtk_entry_new();
|
||||
gtk_container_add(GTK_CONTAINER(frame_pass), pwd);
|
||||
gtk_entry_set_max_length(GTK_ENTRY(pwd), 40);
|
||||
gtk_entry_set_text(GTK_ENTRY(pwd), *pass ?: "");
|
||||
gtk_entry_set_visibility(GTK_ENTRY(pwd), FALSE);
|
||||
gtk_entry_set_activates_default(GTK_ENTRY(pwd), TRUE);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||
|
||||
gtk_widget_show_all(dialog);
|
||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
free((void*)*user);
|
||||
free((void*)*pass);
|
||||
*user = strdup(gtk_entry_get_text(GTK_ENTRY(uid)));
|
||||
*pass = strdup(gtk_entry_get_text(GTK_ENTRY(pwd)));
|
||||
subsurface_set_conf("divelogde_user", *user);
|
||||
subsurface_set_conf("divelogde_pass", *pass);
|
||||
ret = TRUE;
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int divelogde_upload(char *fn, char **error)
|
||||
{
|
||||
SoupMessage *msg;
|
||||
SoupMultipart *multipart;
|
||||
SoupSession *session;
|
||||
SoupBuffer *sbuf;
|
||||
gboolean ret = FALSE;
|
||||
#ifdef __MINGW32__
|
||||
/* for odd reasons I can't seem to get https connections to work
|
||||
* with mingw32 when cross-building the Windows binaries... so fall
|
||||
* back to http for now */
|
||||
char url[256] = "http://divelogs.de/DivelogsDirectImport.php";
|
||||
#else
|
||||
char url[256] = "https://divelogs.de/DivelogsDirectImport.php";
|
||||
#endif
|
||||
const char *pass = NULL;
|
||||
const char *user = NULL;
|
||||
struct memblock mem;
|
||||
|
||||
if (readfile(fn, &mem) < 0)
|
||||
return ret;
|
||||
if (!divelogde_dialog(&user, &pass))
|
||||
return TRUE;
|
||||
sbuf = soup_buffer_new(SOUP_MEMORY_STATIC, mem.buffer, mem.size);
|
||||
session = soup_session_async_new();
|
||||
multipart = soup_multipart_new(SOUP_FORM_MIME_TYPE_MULTIPART);
|
||||
soup_multipart_append_form_string(multipart, "user", user);
|
||||
soup_multipart_append_form_string(multipart, "pass", pass);
|
||||
|
||||
soup_multipart_append_form_file(multipart, "userfile", fn, NULL, sbuf);
|
||||
msg = soup_form_request_new_from_multipart(url, multipart);
|
||||
soup_message_headers_append(msg->request_headers, "Accept", "text/xml");
|
||||
soup_session_send_message(session, msg);
|
||||
if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
|
||||
*error = strdup(msg->response_body->data);
|
||||
ret = TRUE;
|
||||
} else {
|
||||
*error = strdup(msg->reason_phrase);
|
||||
}
|
||||
soup_session_abort(session);
|
||||
g_object_unref(G_OBJECT(msg));
|
||||
g_object_unref(G_OBJECT(session));
|
||||
return ret;
|
||||
}
|
233
windows.c
233
windows.c
|
@ -2,209 +2,11 @@
|
|||
/* implements Windows specific functions */
|
||||
#include "dive.h"
|
||||
#include "display.h"
|
||||
#if USE_GTK_UI
|
||||
#include "display-gtk.h"
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
const char system_divelist_default_font[] = "Sans 8";
|
||||
|
||||
static HKEY hkey;
|
||||
|
||||
void subsurface_open_conf(void)
|
||||
{
|
||||
LONG success;
|
||||
|
||||
success = RegCreateKeyEx(HKEY_CURRENT_USER, (LPCTSTR)TEXT("Software\\subsurface"),
|
||||
0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
|
||||
NULL, &hkey, NULL);
|
||||
if (success != ERROR_SUCCESS)
|
||||
printf("CreateKey Software\\subsurface failed %ld\n", success);
|
||||
}
|
||||
|
||||
void subsurface_unset_conf(const char *name)
|
||||
{
|
||||
RegDeleteValue(hkey, (LPCTSTR)name);
|
||||
}
|
||||
|
||||
void subsurface_set_conf(const char *name, const char *value)
|
||||
{
|
||||
/* since we are using the pointer 'value' as both an actual
|
||||
* pointer to the string setting and as a way to pass the
|
||||
* numbers 0 and 1 to this function for booleans, one of the
|
||||
* calls to RegSetValueEx needs to pass &value (when we want
|
||||
* to pass the boolean value), the other one passes value (the
|
||||
* address of the string. */
|
||||
int wlen;
|
||||
wchar_t *wname, *wstring;
|
||||
|
||||
wname = (wchar_t *)g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
|
||||
if (!wname)
|
||||
return;
|
||||
|
||||
wlen = g_utf8_strlen((char *)value, -1);
|
||||
wstring = (wchar_t *)g_utf8_to_utf16((char *)value, -1, NULL, NULL, NULL);
|
||||
if (!wstring || !wlen) {
|
||||
free(wname);
|
||||
return;
|
||||
}
|
||||
RegSetValueExW(hkey, (LPCWSTR)wname, 0, REG_SZ, (const BYTE *)wstring,
|
||||
wlen * sizeof(wchar_t));
|
||||
free(wstring);
|
||||
free(wname);
|
||||
}
|
||||
|
||||
void subsurface_set_conf_int(const char *name, int value)
|
||||
{
|
||||
RegSetValueEx(hkey, (LPCTSTR)name, 0, REG_DWORD, (const BYTE *)&value, 4);
|
||||
}
|
||||
|
||||
void subsurface_set_conf_bool(const char *name, bool value)
|
||||
{
|
||||
subsurface_set_conf_int(name, value);
|
||||
}
|
||||
|
||||
const char *subsurface_get_conf(const char *name)
|
||||
{
|
||||
const int csize = 64;
|
||||
int blen = 0;
|
||||
LONG ret = ERROR_MORE_DATA;
|
||||
wchar_t *wstring = NULL, *wname;
|
||||
char *utf8_string;
|
||||
|
||||
wname = (wchar_t *)g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
|
||||
if (!wname)
|
||||
return NULL;
|
||||
blen = 0;
|
||||
/* lest try to load the string in chunks of 'csize' bytes until it fits */
|
||||
while (ret == ERROR_MORE_DATA) {
|
||||
blen += csize;
|
||||
wstring = (wchar_t *)realloc(wstring, blen * sizeof(wchar_t));
|
||||
ret = RegQueryValueExW(hkey, (LPCWSTR)wname, NULL, NULL,
|
||||
(LPBYTE)wstring, (LPDWORD)&blen);
|
||||
}
|
||||
/* that's what happens the first time we start - just return NULL */
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
free(wname);
|
||||
free(wstring);
|
||||
return NULL;
|
||||
}
|
||||
/* convert the returned string into utf-8 */
|
||||
utf8_string = g_utf16_to_utf8(wstring, -1, NULL, NULL, NULL);
|
||||
free(wstring);
|
||||
free(wname);
|
||||
if (!utf8_string)
|
||||
return NULL;
|
||||
if (!g_utf8_validate(utf8_string, -1, NULL)) {
|
||||
free(utf8_string);
|
||||
return NULL;
|
||||
}
|
||||
return utf8_string;
|
||||
}
|
||||
|
||||
int subsurface_get_conf_int(const char *name)
|
||||
{
|
||||
DWORD value = -1, len = 4;
|
||||
LONG ret = RegQueryValueEx(hkey, (LPCTSTR)TEXT(name), NULL, NULL,
|
||||
(LPBYTE)&value, (LPDWORD)&len);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
return -1;
|
||||
return value;
|
||||
}
|
||||
|
||||
int subsurface_get_conf_bool(const char *name)
|
||||
{
|
||||
int ret = subsurface_get_conf_int(name);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
void subsurface_flush_conf(void)
|
||||
{
|
||||
/* this is a no-op */
|
||||
}
|
||||
|
||||
void subsurface_close_conf(void)
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
int subsurface_fill_device_list(GtkListStore *store)
|
||||
{
|
||||
const int bufdef = 512;
|
||||
const char *dlabels[] = {"UEMISSDA", NULL};
|
||||
const char *devdef = "COM1";
|
||||
GtkTreeIter iter;
|
||||
int index = -1, nentries = 0, ret, i;
|
||||
char bufname[bufdef], bufval[bufdef], *p;
|
||||
DWORD nvalues, bufval_len, bufname_len;
|
||||
HKEY key;
|
||||
|
||||
/* add serial ports */
|
||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM",
|
||||
0, KEY_READ, &key);
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
ret = RegQueryInfoKeyA(key, NULL, NULL, NULL, NULL, NULL, NULL, &nvalues,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (ret == ERROR_SUCCESS)
|
||||
for (i = 0; i < nvalues; i++) {
|
||||
memset(bufval, 0, bufdef);
|
||||
memset(bufname, 0, bufdef);
|
||||
bufname_len = bufdef;
|
||||
bufval_len = bufdef;
|
||||
ret = RegEnumValueA(key, i, bufname, &bufname_len, NULL, NULL, bufval,
|
||||
&bufval_len);
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter, 0, bufval, -1);
|
||||
if (is_default_dive_computer_device(bufval))
|
||||
index = nentries;
|
||||
nentries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add drive letters that match labels */
|
||||
memset(bufname, 0, bufdef);
|
||||
bufname_len = bufdef;
|
||||
if (GetLogicalDriveStringsA(bufname_len, bufname)) {
|
||||
p = bufname;
|
||||
while (*p) {
|
||||
memset(bufval, 0, bufdef);
|
||||
if (GetVolumeInformationA(p, bufval, bufdef, NULL, NULL, NULL, NULL, 0)) {
|
||||
for (i = 0; dlabels[i] != NULL; i++)
|
||||
if (!strcmp(bufval, dlabels[i])) {
|
||||
char name[80];
|
||||
snprintf(name, sizeof(name), "%s (%s)", p, dlabels[i]);
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter, 0, name, -1);
|
||||
if (is_default_dive_computer_device(p))
|
||||
index = nentries;
|
||||
nentries++;
|
||||
}
|
||||
}
|
||||
p = &p[strlen(p) + 1];
|
||||
}
|
||||
}
|
||||
/* if we can't find anything, use the default */
|
||||
if (!nentries) {
|
||||
gtk_list_store_append(store, &iter);
|
||||
gtk_list_store_set(store, &iter,
|
||||
0, devdef, -1);
|
||||
if (is_default_dive_computer_device(devdef))
|
||||
index = 0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
#endif /* USE_GTK_UI */
|
||||
|
||||
const char *subsurface_icon_name()
|
||||
{
|
||||
return "subsurface.ico";
|
||||
}
|
||||
|
||||
const char *system_default_filename(void)
|
||||
{
|
||||
char datapath[MAX_PATH];
|
||||
|
@ -223,27 +25,6 @@ const char *system_default_filename(void)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
const char *subsurface_gettext_domainpath(char *argv0)
|
||||
{
|
||||
/* first hackishly make sure that the LANGUAGE information is correctly set up
|
||||
* in the environment */
|
||||
char buffer[80];
|
||||
gchar *locale = g_win32_getlocale();
|
||||
snprintf(buffer, sizeof(buffer), "LANGUAGE=%s.UTF-8", locale);
|
||||
putenv(buffer);
|
||||
g_free(locale);
|
||||
/* always use translation directory relative to install location, regardless of argv0 */
|
||||
return "./share/locale";
|
||||
}
|
||||
|
||||
#if USE_GTK_UI
|
||||
void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar,
|
||||
GtkWidget *vbox, GtkUIManager *ui_manager)
|
||||
{
|
||||
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
|
||||
}
|
||||
#endif /* USE_GTK_UI */
|
||||
|
||||
/* barely documented API */
|
||||
extern int __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);
|
||||
|
||||
|
@ -305,20 +86,6 @@ void subsurface_command_line_exit(gint *argc, gchar ***argv)
|
|||
g_free(*argv);
|
||||
}
|
||||
|
||||
bool subsurface_launch_for_uri(const char* uri)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
wchar_t *wuri = (wchar_t *)g_utf8_to_utf16(uri, -1, NULL, NULL, NULL);
|
||||
if (wuri) {
|
||||
if ((INT_PTR)ShellExecuteW(NULL, L"open", wuri, NULL, NULL, SW_SHOWNORMAL) > 32)
|
||||
ret = TRUE;
|
||||
free(wuri);
|
||||
}
|
||||
if (!ret)
|
||||
g_message("ShellExecute failed for: %s", uri);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check if we are running a newer OS version */
|
||||
bool subsurface_os_feature_available(os_feature_t f)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue