aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--callbacks-gtk.h17
-rw-r--r--display-gtk.h106
-rw-r--r--divelist-gtk.c2343
-rw-r--r--info-gtk.c1043
-rw-r--r--planner-gtk.c455
-rw-r--r--statistics-gtk.c659
6 files changed, 0 insertions, 4623 deletions
diff --git a/callbacks-gtk.h b/callbacks-gtk.h
deleted file mode 100644
index 568916f6c..000000000
--- a/callbacks-gtk.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#define UNITCALLBACK(name, type, value) \
-static void name(GtkWidget *w, gpointer data) \
-{ \
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) \
- prefs.units.type = value; \
- update_screen(); \
-}
-
-#define OPTIONCALLBACK(name, option) \
-static void name(GtkWidget *w, gpointer data) \
-{ \
- GtkWidget **entry = (GtkWidget**)data; \
- option = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); \
- update_screen(); \
- if (entry) \
- gtk_widget_set_sensitive(*entry, option);\
-}
diff --git a/display-gtk.h b/display-gtk.h
deleted file mode 100644
index 634f05cab..000000000
--- a/display-gtk.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef DISPLAY_GTK_H
-#define DISPLAY_GTK_H
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#if GTK_CHECK_VERSION(2,22,0)
-#include <gdk/gdkkeysyms-compat.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern GtkWidget *main_window;
-
-/* we want a progress bar as part of the device_data_t - let's abstract this out */
-typedef struct {
- GtkWidget *bar;
-} progressbar_t;
-
-#if defined __APPLE__
-#define CTRLCHAR "<Meta>"
-#define SHIFTCHAR "<Shift>"
-#define PREFERENCE_ACCEL "<Meta>comma"
-#else
-#define CTRLCHAR "<Control>"
-#define SHIFTCHAR "<Shift>"
-#define PREFERENCE_ACCEL NULL
-#endif
-
-extern int subsurface_fill_device_list(GtkListStore *store);
-extern const char *subsurface_icon_name(void);
-extern void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar,
- GtkWidget *vbox, GtkUIManager *ui_manager);
-extern gboolean on_delete(GtkWidget* w, gpointer data);
-
-extern void set_divelist_font(const char *);
-
-extern void update_screen(void);
-extern void download_dialog(GtkWidget *, gpointer);
-
-extern void add_dive_cb(GtkWidget *, gpointer);
-extern void update_progressbar(progressbar_t *progress, double value);
-extern void update_progressbar_text(progressbar_t *progress, const char *text);
-
-
-// info.c
-enum {
- MATCH_EXACT,
- MATCH_PREPEND,
- MATCH_AFTER
-} found_string_entry;
-
-extern GtkWidget *create_date_time_widget(struct tm *time, GtkWidget **cal, GtkWidget **h, GtkWidget **m, GtkWidget **timehbox);
-extern void add_string_list_entry(const char *string, GtkListStore *list);
-extern int match_list(GtkListStore *list, const char *string);
-
-extern GtkWidget *dive_info_frame(void);
-extern GtkWidget *extended_dive_info_widget(void);
-extern GtkWidget *equipment_widget(int w_idx);
-extern GtkWidget *single_stats_widget(void);
-extern GtkWidget *total_stats_widget(void);
-extern int select_cylinder(struct dive *dive, int when);
-extern GtkWidget *dive_list_create(void);
-extern void dive_list_destroy(void);
-extern void info_widget_destroy(void);
-extern GdkPixbuf *get_gps_icon(void);
-
-/* Helper functions for gtk combo boxes */
-extern GtkEntry *get_entry(GtkComboBox *);
-extern const char *get_active_text(GtkComboBox *);
-extern void set_active_text(GtkComboBox *, const char *);
-extern GtkWidget *combo_box_with_model_and_entry(GtkListStore *);
-
-extern GtkWidget *create_label(const char *fmt, ...);
-
-extern gboolean icon_click_cb(GtkWidget *w, GdkEventButton *event, gpointer data);
-
-extern void process_selected_dives(void);
-
-typedef void (*data_func_t)(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data);
-
-typedef gint (*sort_func_t)(GtkTreeModel *model,
- GtkTreeIter *a,
- GtkTreeIter *b,
- gpointer user_data);
-
-extern GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title,
- data_func_t data_func, unsigned int flags);
-extern GtkTreeViewColumn *tree_view_column_add_pixbuf(GtkWidget *tree_view, data_func_t data_func, GtkTreeViewColumn *col);
-
-GError *uemis_download(const char *path, progressbar_t *progress, GtkDialog *dialog, gboolean force_download);
-
-/* from planner.c */
-extern void input_plan(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/divelist-gtk.c b/divelist-gtk.c
deleted file mode 100644
index 49f4b143c..000000000
--- a/divelist-gtk.c
+++ /dev/null
@@ -1,2343 +0,0 @@
-/* divelist-gtk.c */
-/* this creates the UI for the dive list -
- * controlled through the following interfaces:
- *
- * GdkPixbuf *get_gps_icon(void)
- * void flush_divelist(struct dive *dive)
- * void set_divelist_font(const char *font)
- * void dive_list_update_dives(void)
- * void update_dive_list_units(void)
- * void update_dive_list_col_visibility(void)
- * void dive_list_update_dives(void)
- * void add_dive_cb(GtkWidget *menuitem, gpointer data)
- * gboolean icon_click_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
- * void export_all_dives_uddf_cb()
- * GtkWidget dive_list_create(void)
- * void dive_list_destroy(void)
- * void show_and_select_dive(struct dive *dive)
- * void select_next_dive(void)
- * void select_prev_dive(void)
- */
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-#include <glib/gi18n.h>
-#include <assert.h>
-#include <zip.h>
-#include <libxslt/transform.h>
-
-#include "dive.h"
-#include "divelist.h"
-#include "display.h"
-#include "display-gtk.h"
-#include "webservice.h"
-#include "profile.h"
-
-#include <gdk-pixbuf/gdk-pixdata.h>
-#include "satellite.h"
-
-struct DiveList {
- GtkWidget *tree_view;
- GtkWidget *container_widget;
- GtkTreeStore *model, *listmodel, *treemodel;
- GtkTreeViewColumn *nr, *date, *stars, *depth, *duration, *location;
- GtkTreeViewColumn *temperature, *cylinder, *totalweight, *suit, *nitrox, *sac, *otu, *maxcns;
- int changed;
-};
-
-static struct DiveList dive_list;
-#define MODEL(_dl) GTK_TREE_MODEL((_dl).model)
-#define TREEMODEL(_dl) GTK_TREE_MODEL((_dl).treemodel)
-#define LISTMODEL(_dl) GTK_TREE_MODEL((_dl).listmodel)
-#define STORE(_dl) GTK_TREE_STORE((_dl).model)
-#define TREESTORE(_dl) GTK_TREE_STORE((_dl).treemodel)
-#define LISTSTORE(_dl) GTK_TREE_STORE((_dl).listmodel)
-
-static gboolean ignore_selection_changes = FALSE;
-static gboolean in_set_cursor = FALSE;
-static gboolean set_selected(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data);
-
-/*
- * The dive list has the dive data in both string format (for showing)
- * and in "raw" format (for sorting purposes)
- */
-enum {
- DIVE_INDEX = 0,
- DIVE_NR, /* int: dive->nr */
- DIVE_DATE, /* timestamp_t: dive->when */
- DIVE_RATING, /* int: 0-5 stars */
- DIVE_DEPTH, /* int: dive->maxdepth in mm */
- DIVE_DURATION, /* int: in seconds */
- DIVE_TEMPERATURE, /* int: in mkelvin */
- DIVE_TOTALWEIGHT, /* int: in grams */
- DIVE_SUIT, /* "wet, 3mm" */
- DIVE_CYLINDER,
- DIVE_NITROX, /* int: dummy */
- DIVE_SAC, /* int: in ml/min */
- DIVE_OTU, /* int: in OTUs */
- DIVE_MAXCNS, /* int: in % */
- DIVE_LOCATION, /* "2nd Cathedral, Lanai" */
- DIVE_LOC_ICON, /* pixbuf for gps icon */
- DIVELIST_COLUMNS
-};
-
-static void merge_dive_into_trip_above_cb(GtkWidget *menuitem, GtkTreePath *path);
-
-#ifdef DEBUG_MODEL
-static gboolean dump_model_entry(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
-{
- char *location;
- int idx, nr, duration;
- struct dive *dive;
- timestamp_t when;
- struct tm tm;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, DIVE_DATE, &when,
- DIVE_DURATION, &duration, DIVE_LOCATION, &location, -1);
- utc_mkdate(when, &tm);
- printf("iter %x:%x entry #%d : nr %d @ %04d-%02d-%02d %02d:%02d:%02d duration %d location %s ",
- iter->stamp, iter->user_data, idx, nr,
- tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec,
- duration, location);
- dive = get_dive(idx);
- if (dive)
- printf("tripflag %d\n", dive->tripflag);
- else
- printf("without matching dive\n");
-
- free(location);
-
- return FALSE;
-}
-
-static void dump_model(GtkListStore *store)
-{
- gtk_tree_model_foreach(GTK_TREE_MODEL(store), dump_model_entry, NULL);
- printf("\n---\n\n");
-}
-#endif
-
-/* when subsurface starts we want to have the last dive selected. So we simply
- walk to the first leaf (and skip the summary entries - which have negative
- DIVE_INDEX) */
-static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
-{
- GtkTreeIter parent;
- GtkTreePath *tpath;
-
- while (*diveidx < 0) {
- memcpy(&parent, iter, sizeof(parent));
- tpath = gtk_tree_model_get_path(model, &parent);
- if (!gtk_tree_model_iter_children(model, iter, &parent)) {
- /* we should never have a parent without child */
- gtk_tree_path_free(tpath);
- return;
- }
- if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), tpath))
- gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
- gtk_tree_path_free(tpath);
- gtk_tree_model_get(model, iter, DIVE_INDEX, diveidx, -1);
- }
-}
-
-static struct dive *dive_from_path(GtkTreePath *path)
-{
- GtkTreeIter iter;
- int idx;
-
- if (gtk_tree_model_get_iter(MODEL(dive_list), &iter, path)) {
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
- return get_dive(idx);
- } else {
- return NULL;
- }
-
-}
-
-static int get_path_index(GtkTreePath *path)
-{
- GtkTreeIter iter;
- int idx;
-
- gtk_tree_model_get_iter(MODEL(dive_list), &iter, path);
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
- return idx;
-}
-
-/* make sure that if we expand a summary row that is selected, the children show
- up as selected, too */
-static void row_expanded_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
-{
- GtkTreeIter child;
- GtkTreeModel *model = MODEL(dive_list);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- dive_trip_t *trip;
-
- trip = find_trip_by_idx(get_path_index(path));
- if (!trip)
- return;
-
- trip->expanded = 1;
- if (!gtk_tree_model_iter_children(model, &child, iter))
- return;
-
- do {
- int idx;
- struct dive *dive;
-
- gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
- dive = get_dive(idx);
-
- if (dive->selected)
- gtk_tree_selection_select_iter(selection, &child);
- else
- gtk_tree_selection_unselect_iter(selection, &child);
- } while (gtk_tree_model_iter_next(model, &child));
-}
-
-/* Make sure that if we collapse a summary row with any selected children, the row
- shows up as selected too */
-static void row_collapsed_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
-{
- dive_trip_t *trip;
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
-
- trip = find_trip_by_idx(get_path_index(path));
- if (!trip)
- return;
-
- trip->expanded = 0;
- if (trip_has_selected_dives(trip)) {
- gtk_tree_selection_select_iter(selection, iter);
- trip->selected = 1;
- }
-}
-
-const char *star_strings[] = {
- ZERO_STARS,
- ONE_STARS,
- TWO_STARS,
- THREE_STARS,
- FOUR_STARS,
- FIVE_STARS
-};
-
-static void star_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int nr_stars, idx;
- char buffer[40];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_RATING, &nr_stars, -1);
- if (idx < 0) {
- *buffer = '\0';
- } else {
- if (nr_stars < 0 || nr_stars > 5)
- nr_stars = 0;
- snprintf(buffer, sizeof(buffer), "%s", star_strings[nr_stars]);
- }
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-static void date_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int idx, nr;
- timestamp_t when;
- /* this should be enought for most languages. if not increase the value. */
- char *buffer;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &when, -1);
- nr = gtk_tree_model_iter_n_children(model, iter);
-
- if (idx < 0) {
- buffer = get_trip_date_string(when, nr);
- } else {
- buffer = get_dive_date_string(when);
- }
- g_object_set(renderer, "text", buffer, NULL);
- free(buffer);
-}
-
-static void depth_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int depth, integer, frac, len, idx, show_decimal;
- char buffer[40];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DEPTH, &depth, -1);
-
- if (idx < 0) {
- *buffer = '\0';
- } else {
- get_depth_values(depth, &integer, &frac, &show_decimal);
- len = snprintf(buffer, sizeof(buffer), "%d", integer);
- if (show_decimal)
- len += snprintf(buffer+len, sizeof(buffer)-len, ".%d", frac);
- }
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-static void duration_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- unsigned int sec;
- int idx;
- char buffer[40];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DURATION, &sec, -1);
- if (idx < 0)
- *buffer = '\0';
- else
- snprintf(buffer, sizeof(buffer), "%d:%02d", sec / 60, sec % 60);
-
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-static void temperature_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int value, idx;
- char buffer[80];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_TEMPERATURE, &value, -1);
-
- *buffer = 0;
- if (idx >= 0 && value) {
- double deg;
- switch (prefs.units.temperature) {
- case CELSIUS:
- deg = mkelvin_to_C(value);
- break;
- case FAHRENHEIT:
- deg = mkelvin_to_F(value);
- break;
- default:
- return;
- }
- snprintf(buffer, sizeof(buffer), "%.1f", deg);
- }
-
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-static void gpsicon_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int idx;
- GdkPixbuf *icon;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_LOC_ICON, &icon, -1);
- g_object_set(renderer, "pixbuf", icon, NULL);
-}
-
-static void nr_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int idx, nr;
- char buffer[40];
- struct dive *dive;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, -1);
- if (idx < 0) {
- *buffer = '\0';
- } else {
- /* make dives that are not in trips stand out */
- dive = get_dive(idx);
- if (!DIVE_IN_TRIP(dive))
- snprintf(buffer, sizeof(buffer), "<b>%d</b>", nr);
- else
- snprintf(buffer, sizeof(buffer), "%d", nr);
- }
- g_object_set(renderer, "markup", buffer, NULL);
-}
-
-static void weight_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int indx, decimals;
- double value;
- char buffer[80];
- struct dive *dive;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &indx, -1);
- dive = get_dive(indx);
- value = get_weight_units(total_weight(dive), &decimals, NULL);
- if (value == 0.0)
- *buffer = '\0';
- else
- snprintf(buffer, sizeof(buffer), "%.*f", decimals, value);
-
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-static gint nitrox_sort_func(GtkTreeModel *model,
- GtkTreeIter *iter_a,
- GtkTreeIter *iter_b,
- gpointer user_data)
-{
- int index_a, index_b;
- struct dive *a, *b;
- int a_o2, b_o2;
- int a_he, b_he;
- int a_o2low, b_o2low;
-
- gtk_tree_model_get(model, iter_a, DIVE_INDEX, &index_a, -1);
- gtk_tree_model_get(model, iter_b, DIVE_INDEX, &index_b, -1);
- a = get_dive(index_a);
- b = get_dive(index_b);
- get_dive_gas(a, &a_o2, &a_he, &a_o2low);
- get_dive_gas(b, &b_o2, &b_he, &b_o2low);
-
- /* Sort by Helium first, O2 second */
- if (a_he == b_he) {
- if (a_o2 == b_o2)
- return a_o2low - b_o2low;
- return a_o2 - b_o2;
- }
- return a_he - b_he;
-}
-
-static void nitrox_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int idx;
- char *buffer;
- struct dive *dive;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx >= 0 && (dive = get_dive(idx))) {
- buffer = get_nitrox_string(dive);
- g_object_set(renderer, "text", buffer, NULL);
- free(buffer);
- } else {
- g_object_set(renderer, "text", "", NULL);
- }
-}
-
-/* Render the SAC data (integer value of "ml / min") */
-static void sac_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int value, idx;
- const char *fmt;
- char buffer[16];
- double sac;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_SAC, &value, -1);
-
- if (idx < 0 || !value) {
- *buffer = '\0';
- goto exit;
- }
-
- sac = value / 1000.0;
- switch (prefs.units.volume) {
- case LITER:
- fmt = "%4.1f";
- break;
- case CUFT:
- fmt = "%4.2f";
- sac = ml_to_cuft(sac * 1000);
- break;
- }
- snprintf(buffer, sizeof(buffer), fmt, sac);
-exit:
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-/* Render the OTU data (integer value of "OTU") */
-static void otu_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int value, idx;
- char buffer[16];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_OTU, &value, -1);
-
- if (idx < 0 || !value)
- *buffer = '\0';
- else
- snprintf(buffer, sizeof(buffer), "%d", value);
-
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-/* Render the CNS data (in full %) */
-static void cns_data_func(GtkTreeViewColumn *col,
- GtkCellRenderer *renderer,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- int value, idx;
- char buffer[16];
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_MAXCNS, &value, -1);
-
- if (idx < 0 || !value)
- *buffer = '\0';
- else
- snprintf(buffer, sizeof(buffer), "%d%%", value);
-
- g_object_set(renderer, "text", buffer, NULL);
-}
-
-GdkPixbuf *get_gps_icon(void)
-{
- return gdk_pixbuf_from_pixdata(&satellite_pixbuf, TRUE, NULL);
-}
-
-static GdkPixbuf *get_gps_icon_for_dive(struct dive *dive)
-{
- if (dive_has_gps_location(dive))
- return get_gps_icon();
- else
- return NULL;
-}
-
-/*
- * Set up anything that could have changed due to editing
- * of dive information; we need to do this for both models,
- * so we simply call set_one_dive again with the non-current model
- */
-/* forward declaration for recursion */
-static gboolean set_one_dive(GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data);
-
-static void fill_one_dive(struct dive *dive,
- GtkTreeModel *model,
- GtkTreeIter *iter)
-{
- char *location, *cylinder, *suit;
- GtkTreeModel *othermodel;
- GdkPixbuf *icon;
-
- get_cylinder(dive, &cylinder);
- get_location(dive, &location);
- get_suit(dive, &suit);
- icon = get_gps_icon_for_dive(dive);
- gtk_tree_store_set(GTK_TREE_STORE(model), iter,
- DIVE_NR, dive->number,
- DIVE_LOCATION, location,
- DIVE_LOC_ICON, icon,
- DIVE_CYLINDER, cylinder,
- DIVE_RATING, dive->rating,
- DIVE_SAC, dive->sac,
- DIVE_OTU, dive->otu,
- DIVE_MAXCNS, dive->maxcns,
- DIVE_TOTALWEIGHT, total_weight(dive),
- DIVE_SUIT, suit,
- -1);
-
- if (icon)
- g_object_unref(icon);
- free(location);
- free(cylinder);
- free(suit);
-
- if (model == TREEMODEL(dive_list))
- othermodel = LISTMODEL(dive_list);
- else
- othermodel = TREEMODEL(dive_list);
- if (othermodel != MODEL(dive_list))
- /* recursive call */
- gtk_tree_model_foreach(othermodel, set_one_dive, dive);
-}
-
-static gboolean set_one_dive(GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- int idx;
- struct dive *dive;
-
- /* Get the dive number */
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx < 0)
- return FALSE;
- dive = get_dive(idx);
- if (!dive)
- return TRUE;
- if (data && dive != data)
- return FALSE;
-
- fill_one_dive(dive, model, iter);
- return dive == data;
-}
-
-void flush_divelist(struct dive *dive)
-{
- GtkTreeModel *model = MODEL(dive_list);
-
- gtk_tree_model_foreach(model, set_one_dive, dive);
-}
-
-void set_divelist_font(const char *font)
-{
- PangoFontDescription *font_desc = pango_font_description_from_string(font);
- gtk_widget_modify_font(dive_list.tree_view, font_desc);
- pango_font_description_free(font_desc);
-}
-
-void update_dive_list_units(void)
-{
- const char *unit;
- GtkTreeModel *model = MODEL(dive_list);
-
- (void) get_depth_units(0, NULL, &unit);
- gtk_tree_view_column_set_title(dive_list.depth, unit);
-
- (void) get_temp_units(0, &unit);
- gtk_tree_view_column_set_title(dive_list.temperature, unit);
-
- (void) get_weight_units(0, NULL, &unit);
- gtk_tree_view_column_set_title(dive_list.totalweight, unit);
-
- gtk_tree_model_foreach(model, set_one_dive, NULL);
-}
-
-void update_dive_list_col_visibility(void)
-{
- gtk_tree_view_column_set_visible(dive_list.cylinder, prefs.visible_cols.cylinder);
- gtk_tree_view_column_set_visible(dive_list.temperature, prefs.visible_cols.temperature);
- gtk_tree_view_column_set_visible(dive_list.totalweight, prefs.visible_cols.totalweight);
- gtk_tree_view_column_set_visible(dive_list.suit, prefs.visible_cols.suit);
- gtk_tree_view_column_set_visible(dive_list.nitrox, prefs.visible_cols.nitrox);
- gtk_tree_view_column_set_visible(dive_list.sac, prefs.visible_cols.sac);
- gtk_tree_view_column_set_visible(dive_list.otu, prefs.visible_cols.otu);
- gtk_tree_view_column_set_visible(dive_list.maxcns, prefs.visible_cols.maxcns);
- return;
-}
-
-/* Select the iter asked for, and set the keyboard focus on it */
-static void go_to_iter(GtkTreeSelection *selection, GtkTreeIter *iter);
-static void fill_dive_list(void)
-{
- int i, trip_index = 0;
- GtkTreeIter iter, parent_iter, lookup, *parent_ptr = NULL;
- GtkTreeStore *liststore, *treestore;
- GdkPixbuf *icon;
-
- /* Do we need to create any dive groups automatically? */
- if (autogroup)
- autogroup_dives();
-
- treestore = TREESTORE(dive_list);
- liststore = LISTSTORE(dive_list);
-
- clear_trip_indexes();
-
- i = dive_table.nr;
- while (--i >= 0) {
- struct dive *dive = get_dive(i);
- dive_trip_t *trip;
- if (((dive->dive_tags & DTAG_INVALID) && !prefs.display_invalid_dives) ||
- (dive->dive_tags & dive_mask) != dive_mask)
- continue;
- trip = dive->divetrip;
-
- if (!trip) {
- parent_ptr = NULL;
- } else if (!trip->index) {
- trip->index = ++trip_index;
-
- /* Create new trip entry */
- gtk_tree_store_append(treestore, &parent_iter, NULL);
- parent_ptr = &parent_iter;
-
- /* a duration of 0 (and negative index) identifies a group */
- gtk_tree_store_set(treestore, parent_ptr,
- DIVE_INDEX, -trip_index,
- DIVE_DATE, trip->when,
- DIVE_LOCATION, trip->location,
- DIVE_DURATION, 0,
- -1);
- } else {
- int idx, ok;
- GtkTreeModel *model = TREEMODEL(dive_list);
-
- parent_ptr = NULL;
- ok = gtk_tree_model_get_iter_first(model, &lookup);
- while (ok) {
- gtk_tree_model_get(model, &lookup, DIVE_INDEX, &idx, -1);
- if (idx == -trip->index) {
- parent_ptr = &lookup;
- break;
- }
- ok = gtk_tree_model_iter_next(model, &lookup);
- }
- }
-
- /* store dive */
- update_cylinder_related_info(dive);
- gtk_tree_store_append(treestore, &iter, parent_ptr);
- icon = get_gps_icon_for_dive(dive);
- gtk_tree_store_set(treestore, &iter,
- DIVE_INDEX, i,
- DIVE_NR, dive->number,
- DIVE_DATE, dive->when,
- DIVE_DEPTH, dive->maxdepth,
- DIVE_DURATION, dive->duration.seconds,
- DIVE_LOCATION, dive->location,
- DIVE_LOC_ICON, icon,
- DIVE_RATING, dive->rating,
- DIVE_TEMPERATURE, dive->watertemp.mkelvin,
- DIVE_SAC, 0,
- -1);
- if (icon)
- g_object_unref(icon);
- gtk_tree_store_append(liststore, &iter, NULL);
- gtk_tree_store_set(liststore, &iter,
- DIVE_INDEX, i,
- DIVE_NR, dive->number,
- DIVE_DATE, dive->when,
- DIVE_DEPTH, dive->maxdepth,
- DIVE_DURATION, dive->duration.seconds,
- DIVE_LOCATION, dive->location,
- DIVE_LOC_ICON, icon,
- DIVE_RATING, dive->rating,
- DIVE_TEMPERATURE, dive->watertemp.mkelvin,
- DIVE_TOTALWEIGHT, 0,
- DIVE_SUIT, dive->suit,
- DIVE_SAC, 0,
- -1);
- }
-
- update_dive_list_units();
- if (amount_selected == 0 && gtk_tree_model_get_iter_first(MODEL(dive_list), &iter)) {
- GtkTreeSelection *selection;
-
- /* select the last dive (and make sure it's an actual dive that is selected) */
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &selected_dive, -1);
- first_leaf(MODEL(dive_list), &iter, &selected_dive);
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- go_to_iter(selection, &iter);
- }
-}
-
-static void restore_tree_state(void);
-
-void dive_list_update_dives(void)
-{
- dive_table.preexisting = dive_table.nr;
- ignore_selection_changes = TRUE;
- gtk_tree_store_clear(TREESTORE(dive_list));
- gtk_tree_store_clear(LISTSTORE(dive_list));
- ignore_selection_changes = FALSE;
- fill_dive_list();
- restore_tree_state();
- repaint_dive();
-}
-
-static gint gtk_dive_nr_sort(GtkTreeModel *model,
- GtkTreeIter *iter_a,
- GtkTreeIter *iter_b,
- gpointer user_data)
-{
- int idx_a, idx_b;
- timestamp_t when_a, when_b;
-
- gtk_tree_model_get(model, iter_a, DIVE_INDEX, &idx_a, DIVE_DATE, &when_a, -1);
- gtk_tree_model_get(model, iter_b, DIVE_INDEX, &idx_b, DIVE_DATE, &when_b, -1);
-
- return dive_nr_sort(idx_a, idx_b, when_a, when_b);
-}
-
-static struct divelist_column {
- const char *header;
- data_func_t data;
- sort_func_t sort;
- unsigned int flags;
- int *visible;
-} dl_column[] = {
- [DIVE_NR] = { "#", nr_data_func, gtk_dive_nr_sort, ALIGN_RIGHT },
- [DIVE_DATE] = { N_("Date"), date_data_func, NULL, ALIGN_LEFT },
- [DIVE_RATING] = { UTF8_BLACKSTAR, star_data_func, NULL, ALIGN_LEFT },
- [DIVE_DEPTH] = { N_("ft"), depth_data_func, NULL, ALIGN_RIGHT },
- [DIVE_DURATION] = { N_("min"), duration_data_func, NULL, ALIGN_RIGHT },
- [DIVE_TEMPERATURE] = { UTF8_DEGREE "F", temperature_data_func, NULL, ALIGN_RIGHT, &prefs.visible_cols.temperature },
- [DIVE_TOTALWEIGHT] = { N_("lbs"), weight_data_func, NULL, ALIGN_RIGHT, &prefs.visible_cols.totalweight },
- [DIVE_SUIT] = { N_("Suit"), NULL, NULL, ALIGN_LEFT, &prefs.visible_cols.suit },
- [DIVE_CYLINDER] = { N_("Cyl"), NULL, NULL, 0, &prefs.visible_cols.cylinder },
- [DIVE_NITROX] = { "O" UTF8_SUBSCRIPT_2 "%", nitrox_data_func, nitrox_sort_func, 0, &prefs.visible_cols.nitrox },
- [DIVE_SAC] = { N_("SAC"), sac_data_func, NULL, 0, &prefs.visible_cols.sac },
- [DIVE_OTU] = { N_("OTU"), otu_data_func, NULL, 0, &prefs.visible_cols.otu },
- [DIVE_MAXCNS] = { N_("maxCNS"), cns_data_func, NULL, 0, &prefs.visible_cols.maxcns },
- [DIVE_LOCATION] = { N_("Location"), NULL, NULL, ALIGN_LEFT },
-};
-
-
-static GtkTreeViewColumn *divelist_column(struct DiveList *dl, struct divelist_column *col)
-{
- int index = col - &dl_column[0];
- const char *title = _(col->header);
- data_func_t data_func = col->data;
- sort_func_t sort_func = col->sort;
- unsigned int flags = col->flags;
- int *visible = col->visible;
- GtkWidget *tree_view = dl->tree_view;
- GtkTreeStore *treemodel = dl->treemodel;
- GtkTreeStore *listmodel = dl->listmodel;
- GtkTreeViewColumn *ret;
-
- if (visible && !*visible)
- flags |= INVISIBLE;
- ret = tree_view_column(tree_view, index, title, data_func, flags);
- if (sort_func) {
- /* the sort functions are needed in the corresponding models */
- if (index == DIVE_NR)
- gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(treemodel), index, sort_func, NULL, NULL);
- else
- gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(listmodel), index, sort_func, NULL, NULL);
- }
- return ret;
-}
-
-/*
- * This is some crazy crap. The only way to get default focus seems
- * to be to grab focus as the widget is being shown the first time.
- */
-static void realize_cb(GtkWidget *tree_view, gpointer userdata)
-{
- gtk_widget_grab_focus(tree_view);
-}
-
-/*
- * Double-clicking on a group entry will expand a collapsed group
- * and vice versa.
- */
-static void collapse_expand(GtkTreeView *tree_view, GtkTreePath *path)
-{
- if (!gtk_tree_view_row_expanded(tree_view, path))
- gtk_tree_view_expand_row(tree_view, path, FALSE);
- else
- gtk_tree_view_collapse_row(tree_view, path);
-
-}
-
-/* Double-click on a dive list */
-static void row_activated_cb(GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- gpointer userdata)
-{
- int index;
- GtkTreeIter iter;
-
- if (!gtk_tree_model_get_iter(MODEL(dive_list), &iter, path))
- return;
-
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &index, -1);
- /* a negative index is special for the "group by date" entries */
- if (index < 0) {
- collapse_expand(tree_view, path);
- return;
- }
- edit_dive_info(get_dive(index), FALSE);
-}
-
-void report_dives(bool is_imported, bool prefer_imported)
-{
- process_dives(is_imported, prefer_imported);
- dive_list_update_dives();
-}
-
-void add_dive_cb(GtkWidget *menuitem, gpointer data)
-{
- struct dive *dive;
-
- dive = alloc_dive();
- if (add_new_dive(dive)) {
- record_dive(dive);
- report_dives(TRUE, FALSE);
- return;
- }
- free(dive);
-}
-
-static void edit_trip_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int idx;
- GtkTreeIter iter;
- dive_trip_t *dive_trip;
-
- gtk_tree_model_get_iter(MODEL(dive_list), &iter, path);
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
- dive_trip = find_trip_by_idx(idx);
- if (edit_trip(dive_trip))
- gtk_tree_store_set(STORE(dive_list), &iter, DIVE_LOCATION, dive_trip->location, -1);
-}
-
-static void edit_selected_dives_cb(GtkWidget *menuitem, gpointer data)
-{
- edit_multi_dive_info(NULL);
-}
-
-static void edit_dive_from_path_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- struct dive *dive = dive_from_path(path);
-
- edit_multi_dive_info(dive);
-}
-
-static void edit_dive_when_cb(GtkWidget *menuitem, struct dive *dive)
-{
- GtkWidget *dialog, *cal, *h, *m, *timehbox;
- timestamp_t when;
-
- guint yval, mval, dval;
- int success;
- struct tm tm;
-
- if (!dive)
- return;
-
- when = dive->when;
- utc_mkdate(when, &tm);
- dialog = create_date_time_widget(&tm, &cal, &h, &m, &timehbox);
-
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- if (!success) {
- gtk_widget_destroy(dialog);
- return;
- }
- memset(&tm, 0, sizeof(tm));
- gtk_calendar_get_date(GTK_CALENDAR(cal), &yval, &mval, &dval);
- tm.tm_year = yval;
- tm.tm_mon = mval;
- tm.tm_mday = dval;
- tm.tm_hour = gtk_spin_button_get_value(GTK_SPIN_BUTTON(h));
- tm.tm_min = gtk_spin_button_get_value(GTK_SPIN_BUTTON(m));
-
- gtk_widget_destroy(dialog);
- when = utc_mktime(&tm);
- if (dive->when != when) {
- /* if this is the only dive in the trip, just change the trip time */
- if (dive->divetrip && dive->divetrip->nrdives == 1)
- dive->divetrip->when = when;
- /* if this is suddenly before the start of the trip, remove it from the trip */
- else if (dive->divetrip && dive->divetrip->when > when)
- remove_dive_from_trip(dive);
- else if (find_matching_trip(when) != dive->divetrip)
- remove_dive_from_trip(dive);
- dive->when = when;
- mark_divelist_changed(TRUE);
- report_dives(FALSE, FALSE);
- dive_list_update_dives();
- }
-}
-
-static void show_gps_location_cb(GtkWidget *menuitem, struct dive *dive)
-{
- show_gps_location(dive, NULL);
-}
-
-gboolean icon_click_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
-{
- GtkTreePath *path = NULL;
- GtkTreeIter iter;
- GtkTreeViewColumn *col;
- int idx;
- struct dive *dive;
-
- /* left click ? */
- if (event->button == 1 &&
- gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dive_list.tree_view), event->x, event->y, &path, &col, NULL, NULL)) {
- /* is it the icon column ? (we passed the correct column in when registering the callback) */
- if (col == data) {
- gtk_tree_model_get_iter(MODEL(dive_list), &iter, path);
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
- dive = get_dive(idx);
- if (dive && dive_has_gps_location(dive))
- show_gps_location(dive, NULL);
- }
- if (path)
- gtk_tree_path_free(path);
- }
- /* keep processing the click */
- return FALSE;
-}
-
-static void save_as_cb(GtkWidget *menuitem, struct dive *dive)
-{
- GtkWidget *dialog;
- char *filename = NULL;
-
- dialog = gtk_file_chooser_dialog_new(_("Save File As"),
- GTK_WINDOW(main_window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- }
- gtk_widget_destroy(dialog);
-
- if (filename){
- save_dives_logic(filename, TRUE);
- g_free(filename);
- }
-}
-
-static void invalid_dives_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int i;
- int changed = 0;
- struct dive *dive;
-
- if (!amount_selected)
- return;
- /* walk the dive list in chronological order */
- for_each_dive(i, dive) {
- if (!dive->selected)
- continue;
- /* now swap the invalid tag if just 1 dive was selected
- * otherwise set all to invalid */
- if(amount_selected == 1) {
- if (dive->dive_tags & DTAG_INVALID)
- dive->dive_tags &= ~DTAG_INVALID;
- else
- dive->dive_tags |= DTAG_INVALID;
- changed = 1;
- } else {
- if (! dive->dive_tags & DTAG_INVALID) {
- dive->dive_tags |= DTAG_INVALID;
- changed = 1;
- }
- }
- /* if invalid dives aren't shown they need to be
- * de-selected here to avoid confusion */
- if (dive->selected && !prefs.display_invalid_dives) {
- dive->selected = 0;
- amount_selected--;
- }
- }
- if (amount_selected == 0)
- selected_dive = -1;
- if (changed) {
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
- }
-}
-
-static void expand_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view)
-{
- gtk_tree_view_expand_all(tree_view);
-}
-
-static void collapse_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view)
-{
- gtk_tree_view_collapse_all(tree_view);
-}
-
-/* Move a top-level dive into the trip above it */
-static void merge_dive_into_trip_above_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int idx;
- struct dive *dive;
- dive_trip_t *trip;
-
- idx = get_path_index(path);
- dive = get_dive(idx);
-
- /* Needs to be a dive, and at the top level */
- if (!dive || dive->divetrip)
- return;
-
- /* Find the "trip above". */
- for (;;) {
- if (!gtk_tree_path_prev(path))
- return;
- idx = get_path_index(path);
- trip = find_trip_by_idx(idx);
- if (trip)
- break;
- }
-
- add_dive_to_trip(dive, trip);
- if (dive->selected) {
- for_each_dive(idx, dive) {
- if (!dive->selected)
- continue;
- add_dive_to_trip(dive, trip);
- }
- }
-
- trip->expanded = 1;
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
-}
-
-static void insert_trip_before_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int idx;
- struct dive *dive;
- dive_trip_t *trip;
-
- idx = get_path_index(path);
- dive = get_dive(idx);
- if (!dive)
- return;
- trip = create_and_hookup_trip_from_dive(dive);
- if (dive->selected) {
- for_each_dive(idx, dive) {
- if (!dive->selected)
- continue;
- add_dive_to_trip(dive, trip);
- }
- }
- trip->expanded = 1;
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
-}
-
-static void remove_from_trip_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- struct dive *dive;
- int idx;
-
- idx = get_path_index(path);
- if (idx < 0)
- return;
- dive = get_dive(idx);
-
- if (dive->selected) {
- /* remove all the selected dives */
- for_each_dive(idx, dive) {
- if (!dive->selected)
- continue;
- remove_dive_from_trip(dive);
- }
- } else {
- /* just remove the dive the mouse pointer is on */
- remove_dive_from_trip(dive);
- }
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
-}
-
-static void remove_trip(GtkTreePath *trippath)
-{
- int idx, i;
- dive_trip_t *trip;
- struct dive *dive;
-
- idx = get_path_index(trippath);
- trip = find_trip_by_idx(idx);
- if (!trip)
- return;
-
- for_each_dive(i, dive) {
- if (dive->divetrip != trip)
- continue;
- remove_dive_from_trip(dive);
- }
-
- dive_list_update_dives();
-
-#ifdef DEBUG_TRIP
- dump_trip_list();
-#endif
-}
-
-static void remove_trip_cb(GtkWidget *menuitem, GtkTreePath *trippath)
-{
- int success;
- GtkWidget *dialog;
-
- dialog = gtk_dialog_new_with_buttons(_("Remove Trip"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
-
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- gtk_widget_destroy(dialog);
- if (!success)
- return;
-
- remove_trip(trippath);
- mark_divelist_changed(TRUE);
-}
-
-static void merge_trips_cb(GtkWidget *menuitem, GtkTreePath *trippath)
-{
- GtkTreePath *prevpath;
- GtkTreeIter thistripiter, prevtripiter;
- GtkTreeModel *tm = MODEL(dive_list);
- dive_trip_t *thistrip, *prevtrip;
- timestamp_t when;
-
- /* this only gets called when we are on a trip and there is another trip right before */
- prevpath = gtk_tree_path_copy(trippath);
- gtk_tree_path_prev(prevpath);
- gtk_tree_model_get_iter(tm, &thistripiter, trippath);
- gtk_tree_model_get(tm, &thistripiter, DIVE_DATE, &when, -1);
- thistrip = find_matching_trip(when);
- gtk_tree_model_get_iter(tm, &prevtripiter, prevpath);
- gtk_tree_model_get(tm, &prevtripiter, DIVE_DATE, &when, -1);
- prevtrip = find_matching_trip(when);
- /* move dives from trip */
- assert(thistrip != prevtrip);
- while (thistrip->dives)
- add_dive_to_trip(thistrip->dives, prevtrip);
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
-}
-
-static gboolean restore_node_state(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
- int idx;
- struct dive *dive;
- dive_trip_t *trip;
- GtkTreeView *tree_view = GTK_TREE_VIEW(dive_list.tree_view);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- trip = find_trip_by_idx(idx);
- if (trip && trip->expanded)
- gtk_tree_view_expand_row(tree_view, path, FALSE);
- if (trip && trip->selected)
- gtk_tree_selection_select_iter(selection, iter);
- } else {
- dive = get_dive(idx);
- if (dive && dive->selected)
- gtk_tree_selection_select_iter(selection, iter);
- }
- /* continue foreach */
- return FALSE;
-}
-
-/* restore expanded and selected state */
-static void restore_tree_state(void)
-{
- gtk_tree_model_foreach(MODEL(dive_list), restore_node_state, NULL);
-}
-
-/* called when multiple dives are selected and one of these is right-clicked for delete */
-static void delete_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int i;
- struct dive *dive;
- int success;
- GtkWidget *dialog;
- char *dialog_title;
-
- if (!amount_selected)
- return;
- if (amount_selected == 1)
- dialog_title = _("Delete dive");
- else
- dialog_title = _("Delete dives");
-
- dialog = gtk_dialog_new_with_buttons(dialog_title,
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
-
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- gtk_widget_destroy(dialog);
- if (!success)
- return;
-
- /* walk the dive list in chronological order */
- for (i = 0; i < dive_table.nr; i++) {
- dive = get_dive(i);
- if (!dive)
- continue;
- if (!dive->selected)
- continue;
- /* now remove the dive from the table and free it. also move the iterator back,
- * so that we don't skip a dive */
- delete_single_dive(i);
- i--;
- }
- dive_list_update_dives();
-
- /* if no dives are selected at this point clear the display widgets */
- if (!amount_selected) {
- selected_dive = -1;
- process_selected_dives();
- clear_stats_widgets();
- clear_equipment_widgets();
- show_dive_info(NULL);
- }
- mark_divelist_changed(TRUE);
-}
-
-/* this gets called with path pointing to a dive, either in the top level
- * or as part of a trip */
-static void delete_dive_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- int idx;
- GtkTreeIter iter;
- int success;
- GtkWidget *dialog;
-
- dialog = gtk_dialog_new_with_buttons(_("Delete dive"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
-
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- gtk_widget_destroy(dialog);
- if (!success)
- return;
-
- if (!gtk_tree_model_get_iter(MODEL(dive_list), &iter, path))
- return;
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
- delete_single_dive(idx);
- dive_list_update_dives();
- mark_divelist_changed(TRUE);
-}
-
-void divelogs_status_dialog(char *error, GtkMessageType type)
-{
- GtkWidget *dialog, *vbox, *label;
-
- dialog = gtk_message_dialog_new(
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- type,
- GTK_BUTTONS_OK,
- _("%s: Response from divelogs.de"), type == GTK_MESSAGE_INFO ? _("Info") : _("Error")
- );
-
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
- label = create_label("%s", error);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-
- gtk_widget_show_all(dialog);
- gtk_dialog_run(GTK_DIALOG(dialog));
-
- gtk_widget_destroy(dialog);
-
-}
-
-static void upload_dives_divelogs(const gboolean selected)
-{
- int i;
- struct dive *dive;
- FILE *f;
- char filename[PATH_MAX], *tempfile;
- size_t streamsize;
- char *membuf;
- xmlDoc *doc;
- xsltStylesheetPtr xslt = NULL;
- xmlDoc *transformed;
- struct zip_source *s[dive_table.nr];
- struct zip *zip;
- const gchar *tmpdir = g_get_tmp_dir();
- GtkMessageType type;
- char *error = NULL;
- char *parsed = NULL, *endat = NULL;
-
- /*
- * Creating a temporary .DLD file to be eventually uploaded to
- * divelogs.de. I wonder if this could be done in-memory.
- */
- tempfile = g_build_filename(tmpdir, "export.DLD-XXXXXX", NULL);
- int fd = g_mkstemp(tempfile);
- if (fd != -1)
- close(fd);
- zip = zip_open(tempfile, ZIP_CREATE, NULL);
-
- if (!zip)
- return;
-
- if (!amount_selected)
- return;
-
- /* walk the dive list in chronological order */
- for (i = 0; i < dive_table.nr; i++) {
-
- dive = get_dive(i);
- if (!dive)
- continue;
- if (selected && !dive->selected)
- continue;
-
- f = tmpfile();
- if (!f)
- return;
- save_dive(f, dive);
- fseek(f, 0, SEEK_END);
- streamsize = ftell(f);
- rewind(f);
- membuf = malloc(streamsize + 1);
- if (!membuf || !fread(membuf, streamsize, 1, f))
- return;
- membuf[streamsize] = 0;
- fclose(f);
-
- /*
- * Parse the memory buffer into XML document and
- * transform it to divelogs.de format, finally dumping
- * the XML into a character buffer.
- */
- doc = xmlReadMemory(membuf, strlen(membuf), "divelog", NULL, 0);
- if (!doc)
- continue;
-
- free((void *)membuf);
- xslt = get_stylesheet("divelogs-export.xslt");
- if (!xslt)
- return;
- transformed = xsltApplyStylesheet(xslt, doc, NULL);
- xsltFreeStylesheet(xslt);
- xmlDocDumpMemory(transformed, (xmlChar **) &membuf, (int *)&streamsize);
- xmlFreeDoc(doc);
- xmlFreeDoc(transformed);
-
- /*
- * Save the XML document into a zip file.
- */
- snprintf(filename, PATH_MAX, "%d.xml", i + 1);
- s[i] = zip_source_buffer(zip, membuf, streamsize, 1);
- if (s[i]) {
- int64_t ret = zip_add(zip, filename, s[i]);
- if (ret == -1)
- fprintf(stderr, "failed to include dive %d\n", i);
- }
- }
- zip_close(zip);
- if (!divelogde_upload(tempfile, &error)) {
- type = GTK_MESSAGE_ERROR;
- } else {
- /* The upload status XML message should be parsed
- * properly and displayed in a sensible manner. But just
- * displaying the information part of the raw message is
- * better than nothing.
- * And at least the dialog is customized to indicate
- * error or success.
- */
- if (error) {
- parsed = strstr(error, "<Login>");
- endat = strstr(error, "</divelogsDataImport>");
- if (parsed && endat)
- *endat = '\0';
- }
- if (error && strstr(error, "failed"))
- type = GTK_MESSAGE_ERROR;
- else
- type = GTK_MESSAGE_INFO;
- }
- if (parsed)
- divelogs_status_dialog(parsed, type);
- else if (error)
- divelogs_status_dialog(error, type);
- free(error);
-
- g_unlink(tempfile);
- g_free(tempfile);
-}
-
-void upload_selected_dives_divelogs_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- upload_dives_divelogs(TRUE);
-}
-
-void upload_all_dives_divelogs_cb()
-{
- upload_dives_divelogs(FALSE);
-}
-
-static void export_dives_uddf(const gboolean selected)
-{
- FILE *f;
- char *filename = NULL;
- size_t streamsize;
- char *membuf;
- xmlDoc *doc;
- xsltStylesheetPtr xslt = NULL;
- xmlDoc *transformed;
- GtkWidget *dialog;
-
- dialog = gtk_file_chooser_dialog_new(_("Export As UDDF File"),
- GTK_WINDOW(main_window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
-
- if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- }
- gtk_widget_destroy(dialog);
-
- if (!filename)
- return;
-
- /* Save XML to file and convert it into a memory buffer */
- save_dives_logic(filename, selected);
- f = fopen(filename, "r");
- fseek(f, 0, SEEK_END);
- streamsize = ftell(f);
- rewind(f);
-
- membuf = malloc(streamsize + 1);
- if (!membuf || !fread(membuf, streamsize, 1, f)) {
- fprintf(stderr, "Failed to read memory buffer\n");
- return;
- }
- membuf[streamsize] = 0;
- fclose(f);
- g_unlink(filename);
-
- /*
- * Parse the memory buffer into XML document and
- * transform it to UDDF format, finally dumping
- * the XML into a character buffer.
- */
- doc = xmlReadMemory(membuf, strlen(membuf), "divelog", NULL, 0);
- if (!doc) {
- fprintf(stderr, "Failed to read XML memory\n");
- return;
- }
- free((void *)membuf);
-
- /* Convert to UDDF format */
- xslt = get_stylesheet("uddf-export.xslt");
- if (!xslt) {
- fprintf(stderr, "Failed to open UDDF conversion stylesheet\n");
- return;
- }
- transformed = xsltApplyStylesheet(xslt, doc, NULL);
- xsltFreeStylesheet(xslt);
- xmlFreeDoc(doc);
-
- /* Write the transformed XML to file */
- f = g_fopen(filename, "w");
- xmlDocFormatDump(f, transformed, 1);
- xmlFreeDoc(transformed);
-
- fclose(f);
- g_free(filename);
-}
-
-static void export_selected_dives_uddf_cb(GtkWidget *menuitem, GtkTreePath *path)
-{
- export_dives_uddf(TRUE);
-}
-
-void export_all_dives_uddf_cb()
-{
- export_dives_uddf(FALSE);
-}
-
-static void merge_dives_cb(GtkWidget *menuitem, void *unused)
-{
- int i;
- struct dive *dive;
-
- for_each_dive(i, dive) {
- if (dive->selected) {
- merge_dive_index(i, dive);
- return;
- }
- }
-}
-
-/* Called if there are exactly two selected dives and the dive at idx is one of them */
-static void add_dive_merge_label(int idx, GtkMenuShell *menu)
-{
- struct dive *a, *b;
- GtkWidget *menuitem;
-
- /* The other selected dive must be next to it.. */
- a = get_dive(idx);
- b = get_dive(idx+1);
- if (!b || !b->selected) {
- b = a;
- a = get_dive(idx-1);
- if (!a || !a->selected)
- return;
- }
-
- /* .. and they had better be in the same dive trip */
- if (a->divetrip != b->divetrip)
- return;
-
- /* .. and if the surface interval is excessive, you must be kidding us */
- if (b->when > a->when + a->duration.seconds + 30*60)
- return;
-
- /* If so, we can add a "merge dive" menu entry */
- menuitem = gtk_menu_item_new_with_label(_("Merge dives"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(merge_dives_cb), NULL);
- gtk_menu_shell_append(menu, menuitem);
-}
-
-static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int button, GdkEventButton *event)
-{
- GtkWidget *menu, *menuitem, *image;
- char editplurallabel[] = N_("Edit dives");
- char editsinglelabel[] = N_("Edit dive");
- char *editlabel;
- char deleteplurallabel[] = N_("Delete dives");
- char deletesinglelabel[] = N_("Delete dive");
- char *deletelabel;
- char exportuddflabel[] = N_("Export dive(s) to UDDF");
- char uploaddivelogslabel[] = N_("Upload dive(s) to divelogs.de");
- GtkTreePath *path, *prevpath, *nextpath;
- GtkTreeIter iter, previter, nextiter;
- int idx, previdx, nextidx;
- struct dive *dive;
-
- if (!event || !gtk_tree_view_get_path_at_pos(tree_view, event->x, event->y, &path, NULL, NULL, NULL))
- return;
- gtk_tree_model_get_iter(MODEL(dive_list), &iter, path);
- gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
-
- menu = gtk_menu_new();
- menuitem = gtk_image_menu_item_new_with_label(_("Add dive"));
- 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_dive_cb), NULL);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- if (idx < 0) {
- /* mouse pointer is on a trip summary entry */
- menuitem = gtk_menu_item_new_with_label(_("Edit Trip Summary"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(edit_trip_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- prevpath = gtk_tree_path_copy(path);
- if (gtk_tree_path_prev(prevpath) &&
- gtk_tree_model_get_iter(MODEL(dive_list), &previter, prevpath)) {
- gtk_tree_model_get(MODEL(dive_list), &previter, DIVE_INDEX, &previdx, -1);
- if (previdx < 0) {
- menuitem = gtk_menu_item_new_with_label(_("Merge trip with trip above"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(merge_trips_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- }
- nextpath = gtk_tree_path_copy(path);
- gtk_tree_path_next(nextpath);
- if (gtk_tree_model_get_iter(MODEL(dive_list), &nextiter, nextpath)) {
- gtk_tree_model_get(MODEL(dive_list), &nextiter, DIVE_INDEX, &nextidx, -1);
- if (nextidx < 0) {
- menuitem = gtk_menu_item_new_with_label(_("Merge trip with trip below"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(merge_trips_cb), nextpath);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- }
- menuitem = gtk_menu_item_new_with_label(_("Remove Trip"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(remove_trip_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- } else {
- dive = get_dive(idx);
- /* if we right click on selected dive(s), edit, delete or tag them as invalid */
- if (dive->selected) {
- if (amount_selected == 1) {
- deletelabel = _(deletesinglelabel);
- editlabel = _(editsinglelabel);
- menuitem = gtk_menu_item_new_with_label(_("Edit dive date/time"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(edit_dive_when_cb), dive);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- } else {
- deletelabel = _(deleteplurallabel);
- editlabel = _(editplurallabel);
- }
- menuitem = gtk_menu_item_new_with_label(_("Save as"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(save_as_cb), dive);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- if (amount_selected == 1) {
- if (dive->dive_tags & DTAG_INVALID)
- menuitem = gtk_menu_item_new_with_label(_("Mark valid"));
- else
- menuitem = gtk_menu_item_new_with_label(_("Mark invalid"));
- } else {
- menuitem = gtk_menu_item_new_with_label(_("Mark invalid"));
- }
- g_signal_connect(menuitem, "activate", G_CALLBACK(invalid_dives_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label(deletelabel);
- g_signal_connect(menuitem, "activate", G_CALLBACK(delete_selected_dives_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label(_(uploaddivelogslabel));
- g_signal_connect(menuitem, "activate", G_CALLBACK(upload_selected_dives_divelogs_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label(_(exportuddflabel));
- g_signal_connect(menuitem, "activate", G_CALLBACK(export_selected_dives_uddf_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label(editlabel);
- g_signal_connect(menuitem, "activate", G_CALLBACK(edit_selected_dives_cb), NULL);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- /* Two contiguous selected dives? */
- if (amount_selected == 2)
- add_dive_merge_label(idx, GTK_MENU_SHELL(menu));
- } else {
- menuitem = gtk_menu_item_new_with_label(_("Edit dive date/time"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(edit_dive_when_cb), dive);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- deletelabel = _(deletesinglelabel);
- menuitem = gtk_menu_item_new_with_label(deletelabel);
- g_signal_connect(menuitem, "activate", G_CALLBACK(delete_dive_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- editlabel = _(editsinglelabel);
- menuitem = gtk_menu_item_new_with_label(editlabel);
- g_signal_connect(menuitem, "activate", G_CALLBACK(edit_dive_from_path_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- /* Only offer to show on map if it has a location. */
- if (dive_has_gps_location(dive)) {
- menuitem = gtk_menu_item_new_with_label(_("Show in map"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(show_gps_location_cb), dive);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- /* only offer trip editing options when we are displaying the tree model */
- if (dive_list.model == dive_list.treemodel) {
- int depth = gtk_tree_path_get_depth(path);
- int *indices = gtk_tree_path_get_indices(path);
- /* top level dive or child dive that is not the first child */
- if (depth == 1 || indices[1] > 0) {
- menuitem = gtk_menu_item_new_with_label(_("Create new trip above"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(insert_trip_before_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- prevpath = gtk_tree_path_copy(path);
- /* top level dive with a trip right before it */
- if (depth == 1 &&
- gtk_tree_path_prev(prevpath) &&
- gtk_tree_model_get_iter(MODEL(dive_list), &previter, prevpath) &&
- gtk_tree_model_iter_n_children(model, &previter)) {
- menuitem = gtk_menu_item_new_with_label(_("Add to trip above"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(merge_dive_into_trip_above_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- if (DIVE_IN_TRIP(dive)) {
- if (dive->selected && amount_selected > 1)
- menuitem = gtk_menu_item_new_with_label(_("Remove selected dives from trip"));
- else
- menuitem = gtk_menu_item_new_with_label(_("Remove dive from trip"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(remove_from_trip_cb), path);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
- }
- }
- }
- menuitem = gtk_menu_item_new_with_label(_("Expand all"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(expand_all_cb), tree_view);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_label(_("Collapse all"));
- g_signal_connect(menuitem, "activate", G_CALLBACK(collapse_all_cb), tree_view);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
- gtk_widget_show_all(menu);
-
- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
- button, gtk_get_current_event_time());
-}
-
-static void popup_menu_cb(GtkTreeView *tree_view, gpointer userdata)
-{
- popup_divelist_menu(tree_view, MODEL(dive_list), 0, NULL);
-}
-
-static gboolean button_press_cb(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
-{
- /* Right-click? Bring up the menu */
- if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
- popup_divelist_menu(GTK_TREE_VIEW(treeview), MODEL(dive_list), 3, event);
- return TRUE;
- }
- return FALSE;
-}
-
-/* make sure 'path' is shown in the divelist widget; since set_cursor changes the
- * selection to be only 'path' we need to let our selection handling callbacks know
- * that we didn't really mean this */
-static void scroll_to_path(GtkTreePath *path)
-{
- GtkTreeSelection *selection;
-
- gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
- gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(dive_list.tree_view), path, NULL, FALSE, 0, 0);
- in_set_cursor = TRUE;
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(dive_list.tree_view), path, NULL, FALSE);
- in_set_cursor = FALSE;
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- gtk_tree_model_foreach(MODEL(dive_list), set_selected, selection);
-
-}
-
-/* we need to have a temporary copy of the selected dives while
- switching model as the selection_cb function keeps getting called
- when gtk_tree_selection_select_path is called. We also need to
- keep copies of the sort order so we can restore that as well after
- switching models. */
-static gboolean second_call = FALSE;
-static GtkSortType sortorder[] = { [0 ... DIVELIST_COLUMNS - 1] = GTK_SORT_DESCENDING, };
-static int lastcol = DIVE_NR;
-
-/* Check if this dive was selected previously and select it again in the new model;
- * This is used after we switch models to maintain consistent selections.
- * We always return FALSE to iterate through all dives */
-static gboolean set_selected(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
-{
- GtkTreeSelection *selection = GTK_TREE_SELECTION(data);
- int idx, selected;
- struct dive *dive;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- /* this is a trip - restore its state */
- dive_trip_t *trip = find_trip_by_idx(idx);
- if (trip && trip->expanded)
- gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
- if (trip && trip->selected)
- gtk_tree_selection_select_path(selection, path);
- } else {
- dive = get_dive(idx);
- selected = dive && dive->selected;
- if (selected) {
- gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
- gtk_tree_selection_select_path(selection, path);
- }
- }
- return FALSE;
-}
-
-static gboolean scroll_to_this(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
-{
- int idx;
- struct dive *dive;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- dive = get_dive(idx);
- if (dive == current_dive) {
- scroll_to_path(path);
- return TRUE;
- }
- return FALSE;
-}
-
-static void scroll_to_current(GtkTreeModel *model)
-{
- if (current_dive)
- gtk_tree_model_foreach(model, scroll_to_this, current_dive);
-}
-
-static void update_column_and_order(int colid)
-{
- /* Careful: the index into treecolumns is off by one as we don't have a
- tree_view column for DIVE_INDEX */
- GtkTreeViewColumn **treecolumns = &dive_list.nr;
-
- /* this will trigger a second call into sort_column_change_cb,
- so make sure we don't start an infinite recursion... */
- second_call = TRUE;
- gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dive_list.model), colid, sortorder[colid]);
- gtk_tree_view_column_set_sort_order(treecolumns[colid - 1], sortorder[colid]);
- second_call = FALSE;
- scroll_to_current(GTK_TREE_MODEL(dive_list.model));
-}
-
-/* If the sort column is nr (default), show the tree model.
- For every other sort column only show the list model.
- If the model changed, inform the new model of the chosen sort column and make
- sure the same dives are still selected.
-
- The challenge with this function is that once we change the model
- we also need to change the sort column again (as it was changed in
- the other model) and that causes this function to be called
- recursively - so we need to catch that.
-*/
-static void sort_column_change_cb(GtkTreeSortable *treeview, gpointer data)
-{
- int colid;
- GtkSortType order;
- GtkTreeStore *currentmodel = dive_list.model;
-
- gtk_widget_grab_focus(dive_list.tree_view);
- if (second_call)
- return;
-
- gtk_tree_sortable_get_sort_column_id(treeview, &colid, &order);
- if (colid == lastcol) {
- /* we just changed sort order */
- sortorder[colid] = order;
- return;
- } else {
- lastcol = colid;
- }
- if (colid == DIVE_NR)
- dive_list.model = dive_list.treemodel;
- else
- dive_list.model = dive_list.listmodel;
- if (dive_list.model != currentmodel) {
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
-
- gtk_tree_view_set_model(GTK_TREE_VIEW(dive_list.tree_view), MODEL(dive_list));
- update_column_and_order(colid);
- gtk_tree_model_foreach(MODEL(dive_list), set_selected, selection);
- } else {
- if (order != sortorder[colid]) {
- update_column_and_order(colid);
- }
- }
-}
-
-static gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model,
- GtkTreePath *path, gboolean was_selected, gpointer userdata)
-{
- int idx;
- GtkTreeIter iter;
-
- if (!was_selected || in_set_cursor)
- return TRUE;
- gtk_tree_model_get_iter(model, &iter, path);
- gtk_tree_model_get(model, &iter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- int i;
- struct dive *dive;
- dive_trip_t *trip = find_trip_by_idx(idx);
- if (!trip)
- return TRUE;
-
- trip->selected = 0;
- /* If this is expanded, let the gtk selection happen for each dive under it */
- if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), path))
- return TRUE;
- /* Otherwise, consider each dive under it deselected */
- for_each_dive(i, dive) {
- if (dive->divetrip == trip)
- deselect_dive(i);
- }
- } else {
- deselect_dive(idx);
- }
- return TRUE;
-}
-
-/* This gets called for each selected entry after a selection has changed */
-static void entry_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
- int idx;
-
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- int i;
- struct dive *dive;
- dive_trip_t *trip = find_trip_by_idx(idx);
-
- if (!trip)
- return;
- trip->selected = 1;
-
- /* If this is expanded, let the gtk selection happen for each dive under it */
- if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), path)) {
- trip->fixup = 1;
- return;
- }
-
- /* Otherwise, consider each dive under it selected */
- for_each_dive(i, dive) {
- if (dive->divetrip == trip)
- select_dive(i);
- }
- trip->fixup = 0;
- } else {
- select_dive(idx);
- }
-}
-
-static void update_gtk_selection(GtkTreeSelection *selection, GtkTreeModel *model)
-{
- GtkTreeIter iter;
-
- if (!gtk_tree_model_get_iter_first(model, &iter))
- return;
- do {
- GtkTreeIter child;
-
- if (!gtk_tree_model_iter_children(model, &child, &iter))
- continue;
-
- do {
- int idx;
- struct dive *dive;
- dive_trip_t *trip;
-
- gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
- dive = get_dive(idx);
- if (!dive || !dive->selected)
- break;
- trip = dive->divetrip;
- if (!trip)
- break;
- gtk_tree_selection_select_iter(selection, &child);
- } while (gtk_tree_model_iter_next(model, &child));
- } while (gtk_tree_model_iter_next(model, &iter));
-}
-
-/* this is called when gtk thinks that the selection has changed */
-static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
-{
- int i, fixup;
- struct dive *dive;
-
- if (ignore_selection_changes)
- return;
-
- gtk_tree_selection_selected_foreach(selection, entry_selected, model);
-
- /*
- * Go through all the dives, if there is a trip that is selected but no
- * dives under it are selected, force-select all the dives
- */
-
- /* First, clear "fixup" for any trip that has selected dives */
- for_each_dive(i, dive) {
- dive_trip_t *trip = dive->divetrip;
- if (!trip || !trip->fixup)
- continue;
- if (dive->selected || !trip->selected)
- trip->fixup = 0;
- }
-
- /*
- * Ok, not fixup is only set for trips that are selected
- * but have no selected dives in them. Select all dives
- * for such trips.
- */
- fixup = 0;
- for_each_dive(i, dive) {
- dive_trip_t *trip = dive->divetrip;
- if (!trip || !trip->fixup)
- continue;
- fixup = 1;
- select_dive(i);
- }
-
- /*
- * Ok, we did a forced selection of dives, now we need to update the gtk
- * view of what is selected too..
- */
- if (fixup)
- update_gtk_selection(selection, model);
-
-#if DEBUG_SELECTION_TRACKING
- dump_selection();
-#endif
-
- process_selected_dives();
- repaint_dive();
-}
-
-GtkWidget *dive_list_create(void)
-{
- GtkTreeSelection *selection;
-
- dive_list.listmodel = gtk_tree_store_new(DIVELIST_COLUMNS,
- G_TYPE_INT, /* index */
- G_TYPE_INT, /* nr */
- G_TYPE_INT64, /* Date */
- G_TYPE_INT, /* Star rating */
- G_TYPE_INT, /* Depth */
- G_TYPE_INT, /* Duration */
- G_TYPE_INT, /* Temperature */
- G_TYPE_INT, /* Total weight */
- G_TYPE_STRING, /* Suit */
- G_TYPE_STRING, /* Cylinder */
- G_TYPE_INT, /* Nitrox */
- G_TYPE_INT, /* SAC */
- G_TYPE_INT, /* OTU */
- G_TYPE_INT, /* MAXCNS */
- G_TYPE_STRING, /* Location */
- GDK_TYPE_PIXBUF /* GPS icon */
- );
- dive_list.treemodel = gtk_tree_store_new(DIVELIST_COLUMNS,
- G_TYPE_INT, /* index */
- G_TYPE_INT, /* nr */
- G_TYPE_INT64, /* Date */
- G_TYPE_INT, /* Star rating */
- G_TYPE_INT, /* Depth */
- G_TYPE_INT, /* Duration */
- G_TYPE_INT, /* Temperature */
- G_TYPE_INT, /* Total weight */
- G_TYPE_STRING, /* Suit */
- G_TYPE_STRING, /* Cylinder */
- G_TYPE_INT, /* Nitrox */
- G_TYPE_INT, /* SAC */
- G_TYPE_INT, /* OTU */
- G_TYPE_INT, /* MAXCNS */
- G_TYPE_STRING, /* Location */
- GDK_TYPE_PIXBUF /* GPS icon */
- );
- dive_list.model = dive_list.treemodel;
- dive_list.tree_view = gtk_tree_view_new_with_model(TREEMODEL(dive_list));
- set_divelist_font(prefs.divelist_font);
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
-
- gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
- gtk_widget_set_size_request(dive_list.tree_view, 200, 200);
-
- /* check if utf8 stars are available as a default OS feature */
- if (!subsurface_os_feature_available(UTF8_FONT_WITH_STARS))
- dl_column[3].header = "*";
-
- dive_list.nr = divelist_column(&dive_list, dl_column + DIVE_NR);
- dive_list.date = divelist_column(&dive_list, dl_column + DIVE_DATE);
- dive_list.stars = divelist_column(&dive_list, dl_column + DIVE_RATING);
- dive_list.depth = divelist_column(&dive_list, dl_column + DIVE_DEPTH);
- dive_list.duration = divelist_column(&dive_list, dl_column + DIVE_DURATION);
- dive_list.temperature = divelist_column(&dive_list, dl_column + DIVE_TEMPERATURE);
- dive_list.totalweight = divelist_column(&dive_list, dl_column + DIVE_TOTALWEIGHT);
- dive_list.suit = divelist_column(&dive_list, dl_column + DIVE_SUIT);
- dive_list.cylinder = divelist_column(&dive_list, dl_column + DIVE_CYLINDER);
- dive_list.nitrox = divelist_column(&dive_list, dl_column + DIVE_NITROX);
- dive_list.sac = divelist_column(&dive_list, dl_column + DIVE_SAC);
- dive_list.otu = divelist_column(&dive_list, dl_column + DIVE_OTU);
- dive_list.maxcns = divelist_column(&dive_list, dl_column + DIVE_MAXCNS);
- dive_list.location = divelist_column(&dive_list, dl_column + DIVE_LOCATION);
- gtk_tree_view_column_set_sort_indicator(dive_list.nr, TRUE);
- gtk_tree_view_column_set_sort_order(dive_list.nr, GTK_SORT_DESCENDING);
- /* now add the GPS icon to the location column */
- tree_view_column_add_pixbuf(dive_list.tree_view, gpsicon_data_func, dive_list.location);
-
- fill_dive_list();
-
- g_object_set(G_OBJECT(dive_list.tree_view), "headers-visible", TRUE,
- "search-column", DIVE_LOCATION,
- "rules-hint", TRUE,
- NULL);
-
- g_signal_connect_after(dive_list.tree_view, "realize", G_CALLBACK(realize_cb), NULL);
- g_signal_connect(dive_list.tree_view, "row-activated", G_CALLBACK(row_activated_cb), NULL);
- g_signal_connect(dive_list.tree_view, "row-expanded", G_CALLBACK(row_expanded_cb), NULL);
- g_signal_connect(dive_list.tree_view, "row-collapsed", G_CALLBACK(row_collapsed_cb), NULL);
- g_signal_connect(dive_list.tree_view, "button-press-event", G_CALLBACK(button_press_cb), NULL);
- g_signal_connect(dive_list.tree_view, "popup-menu", G_CALLBACK(popup_menu_cb), NULL);
- g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), dive_list.model);
- g_signal_connect(dive_list.listmodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL);
- g_signal_connect(dive_list.treemodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL);
-
- gtk_tree_selection_set_select_function(selection, modify_selection_cb, NULL, NULL);
-
- dive_list.container_widget = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_container_add(GTK_CONTAINER(dive_list.container_widget), dive_list.tree_view);
-
- dive_list.changed = 0;
-
- return dive_list.container_widget;
-}
-
-void dive_list_destroy(void)
-{
- gtk_widget_destroy(dive_list.tree_view);
- g_object_unref(dive_list.treemodel);
- g_object_unref(dive_list.listmodel);
-}
-
-struct iteridx {
- int idx;
- GtkTreeIter *iter;
-};
-
-static gboolean iter_has_idx(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer _data)
-{
- struct iteridx *iteridx = _data;
- int idx;
- /* Get the dive number */
- gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
- if (idx == iteridx->idx) {
- iteridx->iter = gtk_tree_iter_copy(iter);
- return TRUE; /* end foreach */
- }
- return FALSE;
-}
-
-static GtkTreeIter *get_iter_from_idx(int idx)
-{
- struct iteridx iteridx = {idx, };
- gtk_tree_model_foreach(MODEL(dive_list), iter_has_idx, &iteridx);
- return iteridx.iter;
-}
-
-static void scroll_to_selected(GtkTreeIter *iter)
-{
- GtkTreePath *treepath;
- treepath = gtk_tree_model_get_path(MODEL(dive_list), iter);
- scroll_to_path(treepath);
- gtk_tree_path_free(treepath);
-}
-
-static void go_to_iter(GtkTreeSelection *selection, GtkTreeIter *iter)
-{
- gtk_tree_selection_unselect_all(selection);
- gtk_tree_selection_select_iter(selection, iter);
- scroll_to_selected(iter);
-}
-
-void show_and_select_dive(struct dive *dive)
-{
- GtkTreeSelection *selection;
- GtkTreeIter *iter;
- struct dive *odive;
- int i, divenr;
-
- divenr = get_divenr(dive);
- if (divenr < 0)
- /* we failed to find the dive */
- return;
- iter = get_iter_from_idx(divenr);
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- for_each_dive(i, odive)
- odive->selected = FALSE;
- amount_selected = 1;
- selected_dive = divenr;
- dive->selected = TRUE;
- go_to_iter(selection, iter);
- gtk_tree_iter_free(iter);
-}
-
-void select_next_dive(void)
-{
- GtkTreeIter *nextiter, *parent = NULL;
- GtkTreeIter *iter = get_iter_from_idx(selected_dive);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- int idx;
-
- if (!iter)
- return;
- nextiter = gtk_tree_iter_copy(iter);
- if (!gtk_tree_model_iter_next(MODEL(dive_list), nextiter)) {
- if (!gtk_tree_model_iter_parent(MODEL(dive_list), nextiter, iter)) {
- /* we're at the last top level node */
- goto free_iter;
- }
- if (!gtk_tree_model_iter_next(MODEL(dive_list), nextiter)) {
- /* last trip */
- goto free_iter;
- }
- }
- gtk_tree_model_get(MODEL(dive_list), nextiter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- /* need the first child */
- parent = gtk_tree_iter_copy(nextiter);
- if (! gtk_tree_model_iter_children(MODEL(dive_list), nextiter, parent))
- goto free_iter;
- }
- go_to_iter(selection, nextiter);
-free_iter:
- if (nextiter)
- gtk_tree_iter_free(nextiter);
- if (parent)
- gtk_tree_iter_free(parent);
- gtk_tree_iter_free(iter);
-}
-
-void select_prev_dive(void)
-{
- GtkTreeIter previter, *parent = NULL;
- GtkTreeIter *iter = get_iter_from_idx(selected_dive);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
- GtkTreePath *treepath;
- int idx;
-
- if (!iter)
- return;
- treepath = gtk_tree_model_get_path(MODEL(dive_list), iter);
- if (!gtk_tree_path_prev(treepath)) {
- if (!gtk_tree_model_iter_parent(MODEL(dive_list), &previter, iter))
- /* we're at the last top level node */
- goto free_iter;
- gtk_tree_path_free(treepath);
- treepath = gtk_tree_model_get_path(MODEL(dive_list), &previter);
- if (!gtk_tree_path_prev(treepath))
- /* first trip */
- goto free_iter;
- if (!gtk_tree_model_get_iter(MODEL(dive_list), &previter, treepath))
- goto free_iter;
- }
- if (!gtk_tree_model_get_iter(MODEL(dive_list), &previter, treepath))
- goto free_iter;
- gtk_tree_model_get(MODEL(dive_list), &previter, DIVE_INDEX, &idx, -1);
- if (idx < 0) {
- /* need the last child */
- parent = gtk_tree_iter_copy(&previter);
- if (! gtk_tree_model_iter_nth_child(MODEL(dive_list), &previter, parent,
- gtk_tree_model_iter_n_children(MODEL(dive_list), parent) - 1))
- goto free_iter;
- }
- go_to_iter(selection, &previter);
-free_iter:
- gtk_tree_path_free(treepath);
- if (parent)
- gtk_tree_iter_free(parent);
- gtk_tree_iter_free(iter);
-}
diff --git a/info-gtk.c b/info-gtk.c
deleted file mode 100644
index 4ba9058cf..000000000
--- a/info-gtk.c
+++ /dev/null
@@ -1,1043 +0,0 @@
-/* info-gtk.c
- * creates the UI for the info frame -
- * controlled through the following interfaces:
- *
- * void show_dive_info(struct dive *dive)
- *
- * called from gtk-ui:
- * GtkWidget *extended_dive_info_widget(void)
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <glib/gi18n.h>
-
-#include "dive.h"
-#include "display.h"
-#include "display-gtk.h"
-#include "divelist.h"
-#include "info.h"
-
-typedef enum { EDIT_NEW_DIVE, EDIT_ALL, EDIT_WHEN } edit_control_t;
-static GtkEntry *location, *buddy, *divemaster, *rating, *suit;
-static GtkTextView *notes;
-static GtkListStore *location_list, *people_list, *star_list, *suit_list;
-
-static char *get_text(GtkTextView *view)
-{
- GtkTextBuffer *buffer;
- GtkTextIter start;
- GtkTextIter end;
-
- buffer = gtk_text_view_get_buffer(view);
- gtk_text_buffer_get_start_iter(buffer, &start);
- gtk_text_buffer_get_end_iter(buffer, &end);
- return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
-}
-
-/*
- * Get the string from a combo box.
- *
- * The "master" string is the string of the current dive - we only consider it
- * changed if the old string is either empty, or matches that master string.
- */
-static char *get_combo_box_entry_text(GtkComboBox *combo_box, char **textp, const char *master)
-{
- const char *newstring = get_active_text(combo_box);
- return evaluate_string_change(newstring, textp, master);
-}
-
-#define SET_TEXT_VALUE(x) \
- gtk_entry_set_text(x, dive && dive->x ? dive->x : "")
-
-void show_dive_info(struct dive *dive)
-{
- const char *title = get_window_title(dive);
- gtk_window_set_title(GTK_WINDOW(main_window), title);
- free((void *)title);
- SET_TEXT_VALUE(divemaster);
- SET_TEXT_VALUE(buddy);
- SET_TEXT_VALUE(location);
- SET_TEXT_VALUE(suit);
- gtk_entry_set_text(rating, star_strings[dive ? dive->rating : 0]);
- gtk_text_buffer_set_text(gtk_text_view_get_buffer(notes),
- dive && dive->notes ? dive->notes : "", -1);
- /* I'm not quite sure /why/ this is only called when we have no dive
- * -- need to investigate */
- if (!dive)
- show_dive_equipment(NULL, W_IDX_PRIMARY);
-}
-
-static void info_menu_edit_cb(GtkMenuItem *menuitem, gpointer user_data)
-{
- if (amount_selected)
- edit_multi_dive_info(NULL);
-}
-
-static void add_menu_item(GtkMenuShell *menu, const char *label, const char *icon, void (*cb)(GtkMenuItem *, gpointer))
-{
- GtkWidget *item;
- if (icon) {
- GtkWidget *image;
- item = gtk_image_menu_item_new_with_label(label);
- image = gtk_image_new_from_stock(icon, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
- } else {
- item = gtk_menu_item_new_with_label(label);
- }
- g_signal_connect(item, "activate", G_CALLBACK(cb), NULL);
- gtk_widget_show(item); /* Yes, really */
- gtk_menu_shell_prepend(menu, item);
-}
-
-static void populate_popup_cb(GtkTextView *entry, GtkMenuShell *menu, gpointer user_data)
-{
- if (amount_selected)
- add_menu_item(menu, _("Edit"), GTK_STOCK_EDIT, info_menu_edit_cb);
-}
-
-static GtkEntry *text_value(GtkWidget *box, const char *label)
-{
- GtkWidget *widget;
- GtkWidget *frame = gtk_frame_new(label);
-
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, TRUE, 0);
- widget = gtk_entry_new();
- gtk_widget_set_can_focus(widget, FALSE);
- gtk_editable_set_editable(GTK_EDITABLE(widget), FALSE);
- gtk_container_add(GTK_CONTAINER(frame), widget);
- g_signal_connect(widget, "populate-popup", G_CALLBACK(populate_popup_cb), NULL);
- return GTK_ENTRY(widget);
-}
-
-static GtkEntry *single_text_entry(GtkWidget *box, const char *label, const char *text)
-{
- GtkEntry *entry;
- GtkWidget *frame = gtk_frame_new(label);
-
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, TRUE, 0);
- entry = GTK_ENTRY(gtk_entry_new());
- gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(entry));
- if (text && *text)
- gtk_entry_set_text(entry, text);
- return entry;
-}
-
-static GtkComboBox *text_entry(GtkWidget *box, const char *label, GtkListStore *completions, const char *text)
-{
- GtkWidget *combo_box;
- GtkWidget *frame = gtk_frame_new(label);
-
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, TRUE, 0);
-
- combo_box = combo_box_with_model_and_entry(completions);
- gtk_container_add(GTK_CONTAINER(frame), combo_box);
-
- if (text && *text)
- set_active_text(GTK_COMBO_BOX(combo_box), text);
-
- return GTK_COMBO_BOX(combo_box);
-}
-
-enum writable {
- READ_ONLY,
- READ_WRITE
-};
-
-static GtkTextView *text_view(GtkWidget *box, const char *label, enum writable writable)
-{
- GtkWidget *view, *vbox;
- GtkWidget *frame = gtk_frame_new(label);
-
- gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 0);
- box = gtk_hbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(frame), box);
- vbox = gtk_vbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(box), vbox);
-
- GtkWidget* scrolled_window = gtk_scrolled_window_new(0, 0);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
-
- view = gtk_text_view_new();
- if (writable == READ_ONLY) {
- gtk_widget_set_can_focus(view, FALSE);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
- gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE);
- g_signal_connect(view, "populate-popup", G_CALLBACK(populate_popup_cb), NULL);
- }
- gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
- gtk_container_add(GTK_CONTAINER(scrolled_window), view);
- gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
- return GTK_TEXT_VIEW(view);
-}
-
-static GtkTreeIter string_entry_location;
-
-static gboolean match_string_entry(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
- const char *string = data;
- char *entry;
- int cmp;
-
- gtk_tree_model_get(model, iter, 0, &entry, -1);
- cmp = strcmp(entry, string);
- if (entry)
- free(entry);
-
- /* Stop. The entry is bigger than the new one */
- if (cmp > 0)
- return TRUE;
-
- /* Exact match */
- if (!cmp) {
- found_string_entry = MATCH_EXACT;
- return TRUE;
- }
-
- string_entry_location = *iter;
- found_string_entry = MATCH_AFTER;
- return FALSE;
-}
-
-int match_list(GtkListStore *list, const char *string)
-{
- found_string_entry = MATCH_PREPEND;
- gtk_tree_model_foreach(GTK_TREE_MODEL(list), match_string_entry, (void *)string);
- return found_string_entry;
-}
-
-void add_string_list_entry(const char *string, GtkListStore *list)
-{
- GtkTreeIter *iter, loc;
-
- if (!string || !*string)
- return;
-
- switch (match_list(list, string)) {
- case MATCH_EXACT:
- return;
- case MATCH_PREPEND:
- iter = NULL;
- break;
- case MATCH_AFTER:
- iter = &string_entry_location;
- break;
- }
- gtk_list_store_insert_after(list, &loc, iter);
- gtk_list_store_set(list, &loc, 0, string, -1);
-}
-
-void add_people(const char *string)
-{
- add_string_list_entry(string, people_list);
-}
-
-void add_location(const char *string)
-{
- add_string_list_entry(string, location_list);
-}
-
-void add_suit(const char *string)
-{
- add_string_list_entry(string, suit_list);
-}
-
-/* this helper function is completely Gtk independent... but I really
- * hope that a new UI would just have a decent star rating widget and
- * we won't need this kludge... so I'll leave this in the -gtk file */
-static int get_rating(const char *string)
-{
- int rating_val = 0;
- int i;
-
- for (i = 0; i <= 5; i++)
- if (!strcmp(star_strings[i],string))
- rating_val = i;
- return rating_val;
-}
-
-struct dive_info {
- GtkComboBox *location, *divemaster, *buddy, *rating, *suit, *viz;
- GtkEntry *airtemp, *gps;
- GtkWidget *gps_icon;
- GtkTextView *notes;
-};
-
-static void save_dive_info_changes(struct dive *dive, struct dive *master, struct dive_info *info, int tags_shown)
-{
- char *old_text, *new_text;
- const char *gps_text;
- char *rating_string;
- double newtemp;
- int changed = 0;
-
- new_text = get_combo_box_entry_text(info->location, &dive->location, master->location);
- if (new_text) {
- add_location(new_text);
- changed = 1;
- }
-
- gps_text = gtk_entry_get_text(info->gps);
- if (gps_changed(dive, master, gps_text))
- changed = 1;
-
- new_text = get_combo_box_entry_text(info->divemaster, &dive->divemaster, master->divemaster);
- if (new_text) {
- add_people(new_text);
- changed = 1;
- }
-
- new_text = get_combo_box_entry_text(info->buddy, &dive->buddy, master->buddy);
- if (new_text) {
- add_people(new_text);
- changed = 1;
- }
-
- new_text = get_combo_box_entry_text(info->suit, &dive->suit, master->suit);
- if (new_text) {
- add_suit(new_text);
- changed = 1;
- }
-
- rating_string = strdup(star_strings[dive->rating]);
- new_text = get_combo_box_entry_text(info->rating, &rating_string, star_strings[master->rating]);
- if (new_text) {
- dive->rating = get_rating(rating_string);
- changed = 1;
- }
- free(rating_string);
-
- rating_string = strdup(star_strings[dive->visibility]);
- new_text = get_combo_box_entry_text(info->viz, &rating_string, star_strings[master->visibility]);
- if (new_text) {
- dive->visibility = get_rating(rating_string);
- changed = 1;
- }
- free(rating_string);
-
- new_text = (char *)gtk_entry_get_text(info->airtemp);
- if (sscanf(new_text, "%lf", &newtemp) == 1) {
- unsigned long mkelvin;
- switch (prefs.units.temperature) {
- case CELSIUS:
- mkelvin = C_to_mkelvin(newtemp);
- break;
- case FAHRENHEIT:
- mkelvin = F_to_mkelvin(newtemp);
- break;
- default:
- mkelvin = 0;
- }
- if (mkelvin != dive->airtemp.mkelvin && dive->airtemp.mkelvin == master->airtemp.mkelvin) {
- dive->airtemp.mkelvin = mkelvin;
- changed = 1;
- }
- }
-
- if (info->notes) {
- old_text = dive->notes;
- dive->notes = get_text(info->notes);
- if (text_changed(old_text,dive->notes))
- changed = 1;
- if (old_text)
- g_free(old_text);
- }
- if (tags_shown && dive->dive_tags != master->dive_tags) {
- changed = 1;
- dive->dive_tags = master->dive_tags;
- /* if a dive is selected and we aren't showing invalid dives and it is
- * now marked as invalid we need to deselect it to keep the selection
- * state consistent */
- if (!prefs.display_invalid_dives && dive->selected && dive->dive_tags & DTAG_INVALID) {
- dive->selected = 0;
- amount_selected--;
- }
- }
- if (changed) {
- mark_divelist_changed(TRUE);
- update_dive(dive);
- }
-}
-
-static void dive_trip_widget(GtkWidget *box, dive_trip_t *trip, struct dive_info *info)
-{
- GtkWidget *hbox, *label;
- char buffer[128] = N_("Edit trip summary");
-
- label = gtk_label_new(_(buffer));
- gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);
-
- info->location = text_entry(box, _("Location"), location_list, trip->location);
-
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
-
- info->notes = text_view(box, _("Notes"), READ_WRITE);
- if (trip->notes && *trip->notes)
- gtk_text_buffer_set_text(gtk_text_view_get_buffer(info->notes), trip->notes, -1);
-}
-
-struct location_update {
- char text[45];
- char set_by_hand;
- GtkEntry *entry;
- struct dive *dive;
- void (*callback)(float, float);
-} location_update;
-
-static void update_gps_entry(int lat, int lon)
-{
- if (location_update.entry) {
- print_gps_coordinates(location_update.text, 45, lat, lon);
- gtk_entry_set_text(location_update.entry, location_update.text);
- }
-}
-
-static void update_gps_entry_callback(float lat, float lon)
-{
- update_gps_entry(lat * 1000000, lon * 1000000);
- location_update.set_by_hand = 1;
-}
-
-static gboolean gps_map_callback(GtkWidget *w, gpointer data)
-{
- double latitude, longitude;
- const char *gps_text = NULL;
- struct dive fake_dive;
-
- memset(&fake_dive, 0, sizeof(fake_dive));
- if (location_update.entry) {
- gps_text = gtk_entry_get_text(location_update.entry);
- parse_gps_text(gps_text, &latitude, &longitude);
- fake_dive.latitude.udeg = rint(latitude * 1000000);
- fake_dive.longitude.udeg = rint(longitude * 1000000);
- }
- show_gps_location(&fake_dive, update_gps_entry_callback);
- return TRUE;
-}
-
-/*
- * If somebody sets the string by editing the text entry,
- * we consider a clear string an opportunity to set things
- * automatically.
- *
- * A non-empty string, on the other hand, means that we
- * should *not* touch it when we change the location field.
- */
-static gboolean gps_entry_change_cb(GtkEntry *gps, GdkEvent *event, gpointer userdata)
-{
- const char *string = gtk_entry_get_text(gps);
-
- /* A clear string is never considered to be "set" */
- if (!string) {
- location_update.set_by_hand = 0;
- return FALSE;
- }
-
- /*
- * If it wasn't set by hand, and it hasn't changed,
- * it's still not set by hand
- */
- if (!location_update.set_by_hand) {
- if (!strcmp(location_update.text, string))
- return FALSE;
- }
-
- /* Otherwise, check if it's all empty.. */
- while (g_ascii_isspace(*string))
- string++;
- location_update.set_by_hand = !!*string;
-
- return FALSE;
-}
-
-static void location_entry_change_cb(GtkComboBox *location, gpointer *userdata)
-{
- int i;
- struct dive *dive;
- const char *name;
-
- /*
- * Don't do any automatic gps changes of entries that have been
- * explicitly set to some value!
- */
- if (location_update.set_by_hand)
- return;
-
- name = get_active_text(location);
- for_each_dive(i, dive) {
- if (!dive_has_gps_location(dive))
- continue;
- if (!dive->location || strcasecmp(dive->location, name))
- continue;
- update_gps_entry(dive->latitude.udeg, dive->longitude.udeg);
- return;
- }
- update_gps_entry(0, 0);
-}
-
-static void set_dive_button_label(GtkWidget *button, struct dive *dive)
-{
- char buffer[256];
-
- /* if there is only one dc and it has no samples we can edit the depth, too */
- if (dive->dc.next || dive->dc.samples)
- divename(buffer, sizeof(buffer), dive, _("(click to edit date/time)"));
- else
- divename(buffer, sizeof(buffer), dive, _("(click to edit date/time/depth)"));
- gtk_button_set_label(GTK_BUTTON(button), buffer);
-}
-
-static int dive_time_widget(struct dive *dive, edit_control_t editing);
-
-static gboolean base_data_cb(GtkWidget *w, GdkEvent *event, gpointer _data)
-{
- struct dive *dive = _data;
-
- /* if there are more than one divecomputers or if there are any sample
- * then only the start time (well, date and time) can be changed,
- * otherwise (this is most likely a dive that was added manually in Subsurface
- * and we can edit duration, max and mean depth, too */
- if (dive->dc.next || dive->dc.samples)
- dive_time_widget(dive, EDIT_WHEN);
- else
- dive_time_widget(dive, EDIT_ALL);
- set_dive_button_label(w, dive);
- return FALSE;
-}
-
-void divetag_toggle_cb(GtkWidget *widget, gpointer data)
-{
- int togglebit = GPOINTER_TO_INT (data);
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
- edit_dive.dive_tags |= togglebit;
- else
- edit_dive.dive_tags &= ~togglebit;
-}
-
-static void dive_info_widget(GtkWidget *obox, struct dive *dive, struct dive_info *info, int multi, int *show_tags)
-{
- GtkWidget *hbox, *frame, *equipment, *ibox, *box, *button, *sbox, *framebox;
- GtkWidget *image;
- char buffer[256];
- char airtemp[10];
- const char *unit;
- double value;
- int i, tags;
- struct dive *otherdive;
-
- if (multi) {
- GtkWidget *label;
- snprintf(buffer, sizeof(buffer), "%s", _("Edit multiple dives"));
- label = gtk_label_new(buffer);
- gtk_box_pack_start(GTK_BOX(obox), label, FALSE, TRUE, 0);
- } else {
- GtkWidget *basedata;
- snprintf(buffer, sizeof(buffer), "%s", _("Edit dive"));
- basedata = gtk_button_new_with_label(buffer);
- set_dive_button_label(basedata, dive);
- g_signal_connect(G_OBJECT(basedata), "button-press-event", G_CALLBACK(base_data_cb), dive);
- gtk_box_pack_start(GTK_BOX(obox), basedata, FALSE, TRUE, 0);
- }
- /* two column layout (inner hbox ibox) within the outer vbox (obox) we are given */
- ibox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(obox), ibox, TRUE, TRUE, 0);
- box = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(ibox), box, TRUE, TRUE, 0);
-
- info->location = text_entry(box, _("Location"), location_list, dive->location);
- g_signal_connect(G_OBJECT(info->location), "changed", G_CALLBACK(location_entry_change_cb), NULL);
-
- hbox = gtk_hbox_new(FALSE, 2);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
- info->gps = single_text_entry(hbox, _("GPS (WGS84 or GPS format)"), NULL);
-
- location_update.entry = info->gps;
- location_update.dive = dive;
- update_gps_entry(dive->latitude.udeg, dive->longitude.udeg);
- location_update.set_by_hand = !!location_update.text[0];
-
- gtk_widget_add_events(GTK_WIDGET(info->gps), GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(G_OBJECT(info->gps), "focus-out-event", G_CALLBACK(gps_entry_change_cb), NULL);
- gtk_entry_set_width_chars(info->gps, 30);
- info->gps_icon = gtk_button_new_with_label(_("Pick on map"));
- gtk_box_pack_start(GTK_BOX(hbox), info->gps_icon, FALSE, FALSE, 6);
- image = gtk_image_new_from_pixbuf(get_gps_icon());
- gtk_image_set_pixel_size(GTK_IMAGE(image), 128);
- gtk_button_set_image(GTK_BUTTON(info->gps_icon), image);
-
- g_signal_connect(G_OBJECT(info->gps_icon), "clicked", G_CALLBACK(gps_map_callback), NULL);
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
-
- info->divemaster = text_entry(hbox, _("Dive master"), people_list, dive->divemaster);
- info->buddy = text_entry(hbox, _("Buddy"), people_list, dive->buddy);
-
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
-
- info->rating = text_entry(hbox, _("Rating"), star_list, star_strings[dive->rating]);
- info->suit = text_entry(hbox, _("Suit"), suit_list, dive->suit);
-
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
-
- info->viz = text_entry(hbox, _("Visibility"), star_list, star_strings[dive->visibility]);
-
- value = get_temp_units(dive->airtemp.mkelvin, &unit);
- snprintf(buffer, sizeof(buffer), _("Air Temp in %s"), unit);
- if (dive->airtemp.mkelvin)
- snprintf(airtemp, sizeof(airtemp), "%.1f", value);
- else
- airtemp[0] = '\0';
- info->airtemp = single_text_entry(hbox, buffer, airtemp);
-
- frame = gtk_frame_new(_("Dive Tags"));
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
-
- framebox = gtk_vbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(frame), framebox);
-
- /* we only want to show the tags if we have a single dive or if all selected
- * dives have the exact same set of tags (like none at all right after import) */
- i = 0;
- *show_tags = 1;
- tags = dive->dive_tags;
- for_each_dive(i, otherdive)
- if (otherdive && otherdive->selected && otherdive->dive_tags != tags)
- *show_tags = 0;
- if (*show_tags) {
- /* check boxes for the (currently fixed) list of tags;
- * let's do 5 per row */
- const int cols = 5;
- int rows = DTAG_NR / cols + (DTAG_NR % cols) ? 1 : 0;
- GtkWidget *table = gtk_table_new(rows, cols, TRUE);
- for (i = 0; i < DTAG_NR; i++) {
- int x = i % cols;
- int y = i / cols;
- button = gtk_check_button_new_with_label(_(dtag_names[i]));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), dive->dive_tags & (1 << i));
- gtk_table_attach_defaults(GTK_TABLE(table), button, x, x+1, y, y+1);
- g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(divetag_toggle_cb),
- GINT_TO_POINTER(1 << i));
- }
- gtk_box_pack_start(GTK_BOX(framebox), table, TRUE, FALSE, 3);
- } else {
- sbox = gtk_label_new(_("Tags are only shown if they are identical for all edited dives"));
- gtk_box_pack_start(GTK_BOX(framebox), sbox, TRUE, FALSE, 3);
- }
- /* only show notes if editing a single dive */
- if (multi) {
- info->notes = NULL;
- } else {
- info->notes = text_view(box, _("Notes"), READ_WRITE);
- gtk_widget_set_size_request(GTK_WIDGET(info->notes), -1, 128);
- if (dive->notes && *dive->notes)
- gtk_text_buffer_set_text(gtk_text_view_get_buffer(info->notes), dive->notes, -1);
- }
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(ibox), hbox, TRUE, TRUE, 0);
-
- /* create a secondary Equipment widget */
- frame = gtk_frame_new(_("Equipment"));
- equipment = equipment_widget(W_IDX_SECONDARY);
- gtk_container_add(GTK_CONTAINER(frame), equipment);
- gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
-}
-
-gboolean edit_trip(dive_trip_t *trip)
-{
- GtkWidget *dialog, *vbox;
- int success;
- gboolean changed = FALSE;
- char *old_text, *new_text;
- struct dive_info info;
-
- memset(&info, 0, sizeof(struct dive_info));
- dialog = gtk_dialog_new_with_buttons(_("Edit Trip Info"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
- gtk_window_set_default_size(GTK_WINDOW(dialog), 400, 300);
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
- dive_trip_widget(vbox, trip, &info);
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- if (success) {
- /* we need to store the edited location and notes */
- new_text = get_combo_box_entry_text(info.location, &trip->location, trip->location);
- if (new_text) {
- add_location(new_text);
- changed = TRUE;
- }
- if (info.notes) {
- old_text = trip->notes;
- trip->notes = get_text(info.notes);
- if (text_changed(old_text, trip->notes))
- changed = TRUE;
- if (old_text)
- g_free(old_text);
- }
- if (changed)
- mark_divelist_changed(TRUE);
- }
- gtk_widget_destroy(dialog);
- return changed;
-}
-
-int edit_multi_dive_info(struct dive *single_dive)
-{
- int success;
- GtkWidget *dialog, *vbox, *scrolled_window, *viewport;
- GtkRequisition size;
- struct dive_info info;
- struct dive *master;
- int multi;
- int tags_shown;
-
- scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- dialog = gtk_dialog_new_with_buttons(_("Dive Info"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
-
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
- gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
- vbox = g_object_new(GTK_TYPE_VBOX, NULL);
- gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), vbox);
- master = single_dive;
- if (!master)
- master = current_dive;
- if (!master)
- return 0;
- /* See if we should use multi dive mode */
- multi = FALSE;
- if (!single_dive) {
- int i;
- struct dive *dive;
-
- for_each_dive(i, dive) {
- if (dive != master && dive->selected) {
- multi = TRUE;
- break;
- }
- }
- }
- /* edit a temporary copy of the master dive;
- * edit_dive is a global dive structure that is modified by the
- * cylinder / weightsystem dialogs if we open W_IDX_SECONDARY
- * edit widgets as we do here */
- memcpy(&edit_dive, master, sizeof(struct dive));
-
- dive_info_widget(vbox, &edit_dive, &info, multi, &tags_shown);
- save_equipment_data(&edit_dive);
- gtk_widget_show_all(dialog);
- viewport = gtk_widget_get_ancestor(vbox, GTK_TYPE_VIEWPORT);
-#if GTK_CHECK_VERSION(3,0,0)
- gtk_widget_get_preferred_size(viewport, NULL, &size);
-#else
- gtk_widget_size_request(viewport, &size);
-#endif
- gtk_widget_set_size_request(scrolled_window, size.width, size.height);
- /* add the equipment post the "blank" layout estimate */
- show_dive_equipment(&edit_dive, W_IDX_SECONDARY);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- if (success) {
- mark_divelist_changed(TRUE);
- /* Update the non-current selected dives first */
- if (!single_dive) {
- int i;
- struct dive *dive;
-
- for_each_dive(i, dive) {
- if (dive == master || !dive->selected)
- continue;
- /* copy all "info" fields */
- save_dive_info_changes(dive, &edit_dive, &info, tags_shown);
- /* copy the cylinders / weightsystems */
- update_equipment_data(dive, &edit_dive);
- /* this is extremely inefficient... it loops through all
- dives to find the right one - but we KNOW the index already */
- update_cylinder_related_info(dive);
- flush_divelist(dive);
- }
- }
-
- /* Update the master dive last! */
- save_dive_info_changes(master, &edit_dive, &info, tags_shown);
- update_equipment_data(master, &edit_dive);
- update_cylinder_related_info(master);
- /* if there was only one dive we might also have changed dive->when
- * or even the duration and depth information (in a dive without samples) */
- if (! multi) {
- update_time_depth(master, &edit_dive);
- /* these values could have changed because of the edit - so let's
- * recreate them */
- master->duration.seconds = 0;
- master->maxdepth.mm = 0;
- master->meandepth.mm = 0;
- (void)fixup_dive(master);
- }
- dive_list_update_dives();
- }
- gtk_widget_destroy(dialog);
- location_update.entry = NULL;
-
- return success;
-}
-
-int edit_dive_info(struct dive *dive, gboolean newdive)
-{
- if (!dive || (!newdive && !amount_selected))
- return 0;
-
- return edit_multi_dive_info(dive);
-}
-
-static GtkWidget *frame_box(GtkWidget *vbox, const char *fmt, ...)
-{
- va_list ap;
- char buffer[128];
- GtkWidget *frame, *hbox;
-
- va_start(ap, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, ap);
- va_end(ap);
-
- frame = gtk_frame_new(buffer);
- gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0);
- hbox = gtk_hbox_new(0, 3);
- gtk_container_add(GTK_CONTAINER(frame), hbox);
- return hbox;
-}
-
-/* returns the dialog plus pointers to the calendar, hour and minute widget
- * plus the hbox that holds the time entry (in case the caller wants to put
- * a duration entry widget next to the time entry widget */
-GtkWidget *create_date_time_widget(struct tm *time, GtkWidget **cal, GtkWidget **h,
- GtkWidget **m, GtkWidget **timehbox)
-{
- GtkWidget *dialog;
- GtkWidget *hbox, *vbox;
- GtkWidget *label;
-
- dialog = gtk_dialog_new_with_buttons(_("Date and Time"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
- NULL);
-
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
- /* Calendar hbox */
- hbox = frame_box(vbox, _("Date:"));
- *cal = gtk_calendar_new();
- gtk_box_pack_start(GTK_BOX(hbox), *cal, FALSE, TRUE, 0);
-
- /* Time hbox */
- *timehbox = gtk_hbox_new(TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), *timehbox, FALSE, FALSE, 0);
- hbox = frame_box(*timehbox, _("Time"));
-
- *h = gtk_spin_button_new_with_range (0.0, 23.0, 1.0);
- *m = gtk_spin_button_new_with_range (0.0, 59.0, 1.0);
-
- gtk_calendar_select_month(GTK_CALENDAR(*cal), time->tm_mon, time->tm_year + 1900);
- gtk_calendar_select_day(GTK_CALENDAR(*cal), time->tm_mday);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(*h), time->tm_hour);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(*m), time->tm_min);
-
- gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(*h), TRUE);
- gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(*m), TRUE);
-
- gtk_box_pack_end(GTK_BOX(hbox), *m, FALSE, FALSE, 0);
- label = gtk_label_new(":");
- gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_end(GTK_BOX(hbox), *h, FALSE, FALSE, 0);
-
- return dialog;
-}
-
-static int mm_from_spinbutton(GtkWidget *depth)
-{
- int result;
- double val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(depth));
- if (prefs.units.length == FEET) {
- result = feet_to_mm(val);
- } else {
- result = val * 1000 + 0.5;
- }
- return result;
-}
-
-static int dive_time_widget(struct dive *dive, edit_control_t editing)
-{
- GtkWidget *dialog;
- GtkWidget *cal, *vbox, *hbox, *box;
- GtkWidget *h, *m;
- GtkWidget *duration, *depth, *avgdepth;
- guint yval, mval, dval;
- struct tm tm, *time;
- int success;
- double depthinterval;
-
- /*
- * If we have a dive selected, 'add dive' will default
- * to one hour after the end of that dive. Otherwise,
- * we'll just take the current time.
- */
- if (editing != EDIT_NEW_DIVE) {
- utc_mkdate(dive->when, &tm);
- time = &tm;
- } else if (amount_selected == 1) {
- timestamp_t when = current_dive->when;
- when += current_dive->duration.seconds;
- when += 60*60;
- utc_mkdate(when, &tm);
- time = &tm;
- } else {
- time_t now;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- now = tv.tv_sec;
- time = localtime(&now);
- }
- dialog = create_date_time_widget(time, &cal, &h, &m, &hbox);
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
- if (editing != EDIT_WHEN) {
- /* Duration box */
- box = frame_box(hbox, _("Duration (min)"));
- duration = gtk_spin_button_new_with_range (0.0, 1000.0, 1.0);
- if (editing != EDIT_NEW_DIVE)
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(duration), dive->dc.duration.seconds / 60.0);
- gtk_box_pack_end(GTK_BOX(box), duration, FALSE, FALSE, 0);
-
- hbox = gtk_hbox_new(TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
- /* Depth box */
- box = frame_box(hbox, _("Max Depth (%s):"), prefs.units.length == FEET ? _("ft") : _("m"));
- if (prefs.units.length == FEET) {
- depthinterval = 1.0;
- } else {
- depthinterval = 0.1;
- }
- depth = gtk_spin_button_new_with_range (0.0, 1000.0, depthinterval);
- if (editing != EDIT_NEW_DIVE) {
- if (prefs.units.length == FEET) {
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(depth), mm_to_feet(dive->dc.maxdepth.mm));
- } else {
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(depth), dive->dc.maxdepth.mm / 1000.0);
- }
- }
- gtk_box_pack_end(GTK_BOX(box), depth, FALSE, FALSE, 0);
-
- box = frame_box(hbox, _("Avg Depth (%s):"), prefs.units.length == FEET ? _("ft") : _("m"));
- if (prefs.units.length == FEET) {
- depthinterval = 1.0;
- } else {
- depthinterval = 0.1;
- }
- avgdepth = gtk_spin_button_new_with_range (0.0, 1000.0, depthinterval);
- if (editing != EDIT_NEW_DIVE) {
- if (prefs.units.length == FEET) {
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(avgdepth), mm_to_feet(dive->dc.meandepth.mm));
- } else {
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(avgdepth), dive->dc.meandepth.mm / 1000.0);
- }
- }
- gtk_box_pack_end(GTK_BOX(box), avgdepth, FALSE, FALSE, 0);
- }
- /* All done, show it and wait for editing */
- gtk_widget_show_all(dialog);
- success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
- if (!success) {
- gtk_widget_destroy(dialog);
- return 0;
- }
-
- memset(&tm, 0, sizeof(tm));
- gtk_calendar_get_date(GTK_CALENDAR(cal), &yval, &mval, &dval);
- tm.tm_year = yval;
- tm.tm_mon = mval;
- tm.tm_mday = dval;
-
- tm.tm_hour = gtk_spin_button_get_value(GTK_SPIN_BUTTON(h));
- tm.tm_min = gtk_spin_button_get_value(GTK_SPIN_BUTTON(m));
-
- if (editing != EDIT_WHEN) {
- dive->dc.maxdepth.mm = mm_from_spinbutton(depth);
- dive->dc.meandepth.mm = mm_from_spinbutton(avgdepth);
- dive->dc.duration.seconds = gtk_spin_button_get_value(GTK_SPIN_BUTTON(duration))*60;
- }
- gtk_widget_destroy(dialog);
- dive->when = utc_mktime(&tm);
-
- return 1;
-}
-
-int add_new_dive(struct dive *dive)
-{
- if (!dive)
- return 0;
-
- if (!dive_time_widget(dive, EDIT_NEW_DIVE))
- return 0;
-
- return edit_dive_info(dive, TRUE);
-}
-
-GtkWidget *extended_dive_info_widget(void)
-{
- GtkWidget *vbox, *hbox;
- vbox = gtk_vbox_new(FALSE, 6);
-
- people_list = gtk_list_store_new(1, G_TYPE_STRING);
- location_list = gtk_list_store_new(1, G_TYPE_STRING);
- star_list = gtk_list_store_new(1, G_TYPE_STRING);
- add_string_list_entry(star_strings[0], star_list);
- add_string_list_entry(star_strings[1], star_list);
- add_string_list_entry(star_strings[2], star_list);
- add_string_list_entry(star_strings[3], star_list);
- add_string_list_entry(star_strings[4], star_list);
- add_string_list_entry(star_strings[5], star_list);
- suit_list = gtk_list_store_new(1, G_TYPE_STRING);
-
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
- location = text_value(vbox, _("Location"));
-
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
-
- divemaster = text_value(hbox, _("Divemaster"));
- buddy = text_value(hbox, _("Buddy"));
-
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
-
- rating = text_value(hbox, _("Rating"));
- suit = text_value(hbox, _("Suit"));
-
- notes = text_view(vbox, _("Notes"), READ_ONLY);
- return vbox;
-}
-
-void info_widget_destroy(void)
-{
- g_object_unref(people_list);
- g_object_unref(location_list);
- g_object_unref(star_list);
- g_object_unref(suit_list);
-}
diff --git a/planner-gtk.c b/planner-gtk.c
deleted file mode 100644
index b6306bdee..000000000
--- a/planner-gtk.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/* planner.c
- *
- * code that allows us to plan future dives
- *
- * (c) Dirk Hohndel 2013
- */
-#include <glib/gi18n.h>
-#include <unistd.h>
-#include <ctype.h>
-#include "dive.h"
-#include "divelist.h"
-#include "display-gtk.h"
-#include "planner.h"
-
-GtkWidget *planner, *planner_error_bar, *error_label;
-
-static void on_error_bar_response(GtkWidget *widget, gint response, gpointer data)
-{
- if (response == GTK_RESPONSE_OK)
- {
- gtk_widget_destroy(widget);
- planner_error_bar = NULL;
- error_label = NULL;
- }
-}
-
-static void show_error(const char *fmt, ...)
-{
- va_list args;
- GError *error;
- GtkWidget *box, *container;
- gboolean bar_is_visible = TRUE;
-
- va_start(args, fmt);
- error = g_error_new_valist(g_quark_from_string("subsurface"), DIVE_ERROR_PLAN, fmt, args);
- va_end(args);
- if (!planner_error_bar) {
- planner_error_bar = gtk_info_bar_new_with_buttons(GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- g_signal_connect(planner_error_bar, "response", G_CALLBACK(on_error_bar_response), NULL);
- gtk_info_bar_set_message_type(GTK_INFO_BAR(planner_error_bar), GTK_MESSAGE_ERROR);
- bar_is_visible = FALSE;
- }
- container = gtk_info_bar_get_content_area(GTK_INFO_BAR(planner_error_bar));
- if (error_label)
- gtk_container_remove(GTK_CONTAINER(container), error_label);
- error_label = gtk_label_new(error->message);
- gtk_container_add(GTK_CONTAINER(container), error_label);
- box = gtk_dialog_get_content_area(GTK_DIALOG(planner));
- if (!bar_is_visible)
- gtk_box_pack_start(GTK_BOX(box), planner_error_bar, FALSE, FALSE, 0);
- gtk_widget_show_all(box);
- /* make sure this actually gets shown BEFORE the calculations run */
- while (gtk_events_pending())
- gtk_main_iteration_do(FALSE);
-}
-
-
-static GtkWidget *add_entry_to_box(GtkWidget *box, const char *label)
-{
- GtkWidget *entry, *frame;
-
- entry = gtk_entry_new();
- gtk_entry_set_max_length(GTK_ENTRY(entry), 16);
- if (label) {
- frame = gtk_frame_new(label);
- gtk_container_add(GTK_CONTAINER(frame), entry);
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
- } else {
- gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 2);
- }
- return entry;
-}
-
-#define MAX_WAYPOINTS 12
-GtkWidget *entry_depth[MAX_WAYPOINTS], *entry_duration[MAX_WAYPOINTS], *entry_gas[MAX_WAYPOINTS], *entry_po2[MAX_WAYPOINTS];
-int nr_waypoints = 0;
-static GtkListStore *gas_model = NULL;
-
-static gboolean gas_focus_out_cb(GtkWidget *entry, GdkEvent *event, gpointer data)
-{
- const char *gastext;
- int o2, he;
- int idx = data - NULL;
- char *error_string = NULL;
-
- gastext = gtk_entry_get_text(GTK_ENTRY(entry));
- o2 = he = 0;
- if (validate_gas(gastext, &o2, &he))
- add_string_list_entry(gastext, gas_model);
- add_gas_to_nth_dp(&diveplan, idx, o2, he);
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- return FALSE;
-}
-
-static void gas_changed_cb(GtkWidget *combo, gpointer data)
-{
- const char *gastext;
- int o2, he;
- int idx = data - NULL;
- char *error_string = NULL;
-
- gastext = get_active_text(GTK_COMBO_BOX(combo));
- /* stupidly this gets called for two reasons:
- * a) any keystroke into the entry field
- * b) mouse selection of a dropdown
- * we only care about b) (a) is handled much better with the focus-out event)
- * so let's check that the text returned is actually in our model before going on
- */
- if (match_list(gas_model, gastext) != MATCH_EXACT)
- return;
- o2 = he = 0;
- if (!validate_gas(gastext, &o2, &he)) {
- /* this should never happen as only validated texts should be
- * in the dropdown */
- show_error(_("Invalid gas for row %d"),idx);
- }
- add_gas_to_nth_dp(&diveplan, idx, o2, he);
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
-}
-
-static gboolean depth_focus_out_cb(GtkWidget *entry, GdkEvent *event, gpointer data)
-{
- const char *depthtext;
- int depth = -1;
- int idx = data - NULL;
- char *error_string = NULL;
-
- depthtext = gtk_entry_get_text(GTK_ENTRY(entry));
-
- if (validate_depth(depthtext, &depth)) {
- if (depth > 150000)
- show_error(_("Warning - planning very deep dives can take excessive amounts of time"));
- add_depth_to_nth_dp(&diveplan, idx, depth);
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- } else {
- /* it might be better to instead change the color of the input field or something */
- if (depth == -1)
- show_error(_("Invalid depth - could not parse \"%s\""), depthtext);
- else
- show_error(_("Invalid depth - values deeper than 400m not supported"));
- }
- return FALSE;
-}
-
-static gboolean duration_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *durationtext;
- int duration, is_rel;
- int idx = data - NULL;
- char *error_string = NULL;
-
- durationtext = gtk_entry_get_text(GTK_ENTRY(entry));
- if (validate_time(durationtext, &duration, &is_rel))
- if (add_duration_to_nth_dp(&diveplan, idx, duration, is_rel) < 0)
- show_error(_("Warning - extremely long dives can cause long calculation time"));
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- return FALSE;
-}
-
-static gboolean po2_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *po2text;
- int po2;
- int idx = data - NULL;
- char *error_string = NULL;
-
- po2text = gtk_entry_get_text(GTK_ENTRY(entry));
- if (validate_po2(po2text, &po2))
- add_po2_to_nth_dp(&diveplan, idx, po2);
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- return FALSE;
-}
-
-static gboolean starttime_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *starttimetext;
- int starttime, is_rel;
- char *error_string = NULL;
-
- starttimetext = gtk_entry_get_text(GTK_ENTRY(entry));
- if (validate_time(starttimetext, &starttime, &is_rel)) {
- /* we alway make this relative - either from the current time or from the
- * end of the last dive, whichever is later */
- timestamp_t cur = current_time_notz();
- if (diveplan.lastdive_nr >= 0) {
- struct dive *last_dive = get_dive(diveplan.lastdive_nr);
- if (last_dive && last_dive->when + last_dive->dc.duration.seconds > cur)
- cur = last_dive->when + last_dive->dc.duration.seconds;
- }
- diveplan.when = cur + starttime;
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- } else {
- /* it might be better to instead change the color of the input field or something */
- show_error(_("Invalid starttime"));
- }
- return FALSE;
-}
-
-static gboolean surfpres_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *surfprestext;
- char *error_string = NULL;
-
- surfprestext = gtk_entry_get_text(GTK_ENTRY(entry));
- diveplan.surface_pressure = atoi(surfprestext);
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- return FALSE;
-}
-
-static gboolean sac_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *sactext;
- char *error_string = NULL;
-
- sactext = gtk_entry_get_text(GTK_ENTRY(entry));
- if (validate_volume(sactext, data)) {
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- }
- return FALSE;
-}
-
-static gboolean gf_focus_out_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- const char *gftext;
- int gf;
- double *gfp = data;
- char *error_string = NULL;
-
- gftext = gtk_entry_get_text(GTK_ENTRY(entry));
- if (sscanf(gftext, "%d", &gf) == 1) {
- *gfp = gf / 100.0;
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- }
- return FALSE;
-}
-
-static gboolean last_stop_toggled_cb(GtkWidget *entry, GdkEvent * event, gpointer data)
-{
- char *error_string = NULL;
- set_last_stop(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(entry)));
- show_planned_dive(&error_string);
- if (error_string)
- show_error(error_string);
- return FALSE;
-}
-
-static GtkWidget *add_gas_combobox_to_box(GtkWidget *box, const char *label, int idx)
-{
- GtkWidget *frame, *combo;
-
- if (!gas_model) {
- gas_model = gtk_list_store_new(1, G_TYPE_STRING);
- add_string_list_entry(_("AIR"), gas_model);
- add_string_list_entry(_("EAN32"), gas_model);
- add_string_list_entry(_("EAN36"), gas_model);
- }
- combo = combo_box_with_model_and_entry(gas_model);
- gtk_widget_add_events(combo, GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(gtk_bin_get_child(GTK_BIN(combo)), "focus-out-event", G_CALLBACK(gas_focus_out_cb), NULL + idx);
- g_signal_connect(combo, "changed", G_CALLBACK(gas_changed_cb), NULL + idx);
- if (label) {
- frame = gtk_frame_new(label);
- gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 0);
- gtk_container_add(GTK_CONTAINER(frame), combo);
- } else {
- gtk_box_pack_start(GTK_BOX(box), combo, FALSE, FALSE, 2);
- }
-
- return combo;
-}
-
-static void add_waypoint_widgets(GtkWidget *box, int idx)
-{
- GtkWidget *hbox;
-
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
- if (idx == 0) {
- entry_depth[idx] = add_entry_to_box(hbox, _("Ending Depth"));
- entry_duration[idx] = add_entry_to_box(hbox, _("Segment Time"));
- entry_gas[idx] = add_gas_combobox_to_box(hbox, C_("Type of","Gas Used"), idx);
- entry_po2[idx] = add_entry_to_box(hbox, _("CC SetPoint"));
- } else {
- entry_depth[idx] = add_entry_to_box(hbox, NULL);
- entry_duration[idx] = add_entry_to_box(hbox, NULL);
- entry_gas[idx] = add_gas_combobox_to_box(hbox, NULL, idx);
- entry_po2[idx] = add_entry_to_box(hbox, NULL);
- }
- gtk_widget_add_events(entry_depth[idx], GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(entry_depth[idx], "focus-out-event", G_CALLBACK(depth_focus_out_cb), NULL + idx);
- gtk_widget_add_events(entry_duration[idx], GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(entry_duration[idx], "focus-out-event", G_CALLBACK(duration_focus_out_cb), NULL + idx);
- gtk_widget_add_events(entry_po2[idx], GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(entry_po2[idx], "focus-out-event", G_CALLBACK(po2_focus_out_cb), NULL + idx);
-}
-
-static void add_waypoint_cb(GtkButton *button, gpointer _data)
-{
- GtkWidget *vbox = _data;
- if (nr_waypoints < MAX_WAYPOINTS) {
- GtkWidget *ovbox, *dialog;
- add_waypoint_widgets(vbox, nr_waypoints);
- nr_waypoints++;
- ovbox = gtk_widget_get_parent(GTK_WIDGET(button));
- dialog = gtk_widget_get_parent(ovbox);
- gtk_widget_show_all(dialog);
- } else {
- show_error(_("Too many waypoints"));
- }
-}
-
-static void add_entry_with_callback(GtkWidget *box, int length, char *label, char *initialtext,
- gboolean (*callback)(GtkWidget *, GdkEvent *, gpointer), gpointer data)
-{
- GtkWidget *entry = add_entry_to_box(box, label);
- gtk_entry_set_max_length(GTK_ENTRY(entry), length);
- gtk_entry_set_text(GTK_ENTRY(entry), initialtext);
- gtk_widget_add_events(entry, GDK_FOCUS_CHANGE_MASK);
- g_signal_connect(entry, "focus-out-event", G_CALLBACK(callback), data);
-}
-
-/* set up the dialog where the user can input their dive plan */
-void input_plan()
-{
- GtkWidget *content, *vbox, *hbox, *outervbox, *add_row, *label;
- char *bottom_sac, *deco_sac, gflowstring[4], gfhighstring[4];
- char *explanationtext = _("<small>Add segments below.\nEach line describes part of the planned dive.\n"
- "An entry with depth, time and gas describes a segment that ends "
- "at the given depth, takes the given time (if relative, e.g. '+3:30') "
- "or ends at the given time (if absolute e.g '@5:00', 'runtime'), and uses the given gas.\n"
- "An empty gas means 'use previous gas' (or AIR if no gas was specified).\n"
- "An entry that has a depth and a gas given but no time is special; it "
- "informs the planner that the gas specified is available for the ascent "
- "once the depth given has been reached.\n"
- "CC SetPoint specifies CC (rebreather) dives, leave empty for OC.</small>\n");
- char *labeltext;
- char *error_string = NULL;
- int len;
-
- disclaimer = _("DISCLAIMER / WARNING: THIS IS A NEW IMPLEMENTATION OF THE BUHLMANN "
- "ALGORITHM AND A DIVE PLANNER IMPLEMENTION BASED ON THAT WHICH HAS "
- "RECEIVED ONLY A LIMITED AMOUNT OF TESTING. WE STRONGLY RECOMMEND NOT TO "
- "PLAN DIVES SIMPLY BASED ON THE RESULTS GIVEN HERE.");
- if (diveplan.dp)
- free_dps(diveplan.dp);
- memset(&diveplan, 0, sizeof(diveplan));
- diveplan.lastdive_nr = dive_table.nr - 1;
- free(cache_data);
- cache_data = NULL;
- planned_dive = NULL;
- planner = gtk_dialog_new_with_buttons(_("Dive Plan - THIS IS JUST A SIMULATION; DO NOT USE FOR DIVING"),
- GTK_WINDOW(main_window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NULL);
- content = gtk_dialog_get_content_area (GTK_DIALOG (planner));
- outervbox = gtk_vbox_new(FALSE, 2);
- gtk_container_add (GTK_CONTAINER (content), outervbox);
-
- len = strlen(explanationtext) + strlen(disclaimer) + sizeof("<span foreground='red'></span>");
- labeltext = malloc(len);
- snprintf(labeltext, len, "%s<span foreground='red'>%s</span>", explanationtext, disclaimer);
- label = gtk_label_new(labeltext);
- gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
- gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
- gtk_label_set_width_chars(GTK_LABEL(label), 60);
- gtk_box_pack_start(GTK_BOX(outervbox), label, TRUE, TRUE, 0);
- vbox = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(outervbox), vbox, TRUE, TRUE, 0);
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
- add_entry_with_callback(hbox, 12, _("Dive starts when?"), "+60:00", starttime_focus_out_cb, NULL);
- add_entry_with_callback(hbox, 12, _("Surface Pressure (mbar)"), SURFACE_PRESSURE_STRING, surfpres_focus_out_cb, NULL);
-
- if (get_units()->length == METERS)
- labeltext = _("Last stop at 6 Meters");
- else
- labeltext = _("Last stop at 20 Feet");
-
- set_last_stop(FALSE);
- content = gtk_check_button_new_with_label(labeltext);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(content), 0);
- gtk_box_pack_start(GTK_BOX(hbox), content, FALSE, FALSE, 6);
- g_signal_connect(G_OBJECT(content), "toggled", G_CALLBACK(last_stop_toggled_cb), NULL);
-
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
- if (get_units()->volume == CUFT) {
- bottom_sac = _("0.7 cuft/min");
- deco_sac = _("0.6 cuft/min");
- diveplan.bottomsac = 1000 * cuft_to_l(0.7);
- diveplan.decosac = 1000 * cuft_to_l(0.6);
- } else {
- bottom_sac = _("20 l/min");
- deco_sac = _("17 l/min");
- diveplan.bottomsac = 20000;
- diveplan.decosac = 17000;
- }
- add_entry_with_callback(hbox, 12, _("SAC during dive"), bottom_sac, sac_focus_out_cb, &diveplan.bottomsac);
- add_entry_with_callback(hbox, 12, _("SAC during decostop"), deco_sac, sac_focus_out_cb, &diveplan.decosac);
- plangflow = prefs.gflow;
- plangfhigh = prefs.gfhigh;
- snprintf(gflowstring, sizeof(gflowstring), "%3.0f", 100 * plangflow);
- snprintf(gfhighstring, sizeof(gflowstring), "%3.0f", 100 * plangfhigh);
- add_entry_with_callback(hbox, 5, _("GFlow for plan"), gflowstring, gf_focus_out_cb, &plangflow);
- add_entry_with_callback(hbox, 5, _("GFhigh for plan"), gfhighstring, gf_focus_out_cb, &plangfhigh);
- diveplan.when = current_time_notz() + 3600;
- diveplan.surface_pressure = SURFACE_PRESSURE;
- nr_waypoints = 4;
- add_waypoint_widgets(vbox, 0);
- add_waypoint_widgets(vbox, 1);
- add_waypoint_widgets(vbox, 2);
- add_waypoint_widgets(vbox, 3);
- add_row = gtk_button_new_with_label(_("Add waypoint"));
- g_signal_connect(G_OBJECT(add_row), "clicked", G_CALLBACK(add_waypoint_cb), vbox);
- gtk_box_pack_start(GTK_BOX(outervbox), add_row, FALSE, FALSE, 0);
- gtk_widget_show_all(planner);
- if (gtk_dialog_run(GTK_DIALOG(planner)) == GTK_RESPONSE_ACCEPT) {
- plan(&diveplan, &cache_data, &planned_dive, &error_string);
- if (error_string)
- show_error(error_string);
- mark_divelist_changed(TRUE);
- } else {
- if (planned_dive) {
- /* we have added a dive during the dynamic construction
- * in the dialog; get rid of it */
- delete_single_dive(dive_table.nr - 1);
- report_dives(FALSE, FALSE);
- planned_dive = NULL;
- }
- }
- gtk_widget_destroy(planner);
- planner_error_bar = NULL;
- error_label = NULL;
- set_gf(prefs.gflow, prefs.gfhigh);
-}
diff --git a/statistics-gtk.c b/statistics-gtk.c
deleted file mode 100644
index b35516d3d..000000000
--- a/statistics-gtk.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/* statistics-gtk.c */
-/* creates the UI for the Info & Stats page -
- * controlled through the following interfaces:
- *
- * void show_dive_stats(struct dive *dive)
- *
- * called from gtk-ui:
- * GtkWidget *stats_widget(void)
- */
-#include <glib/gi18n.h>
-#include <ctype.h>
-
-#include "dive.h"
-#include "display.h"
-#include "display-gtk.h"
-#include "divelist.h"
-#include "statistics.h"
-
-typedef struct {
- GtkWidget *date,
- *dive_time,
- *surf_intv,
- *max_depth,
- *avg_depth,
- *viz,
- *water_temp,
- *air_temp,
- *air_press,
- *sac,
- *otu,
- *o2he,
- *gas_used,
- *dive_type;
-} single_stat_widget_t;
-
-static single_stat_widget_t single_w;
-
-typedef struct {
- GtkWidget *total_time,
- *avg_time,
- *shortest_time,
- *longest_time,
- *max_overall_depth,
- *min_overall_depth,
- *avg_overall_depth,
- *min_sac,
- *avg_sac,
- *max_sac,
- *selection_size,
- *max_temp,
- *avg_temp,
- *min_temp,
- *framelabel;
-} total_stats_widget_t;
-
-static total_stats_widget_t stats_w;
-
-GtkWidget *yearly_tree = NULL;
-
-enum {
- YEAR,
- DIVES,
- TOTAL_TIME,
- AVERAGE_TIME,
- SHORTEST_TIME,
- LONGEST_TIME,
- AVG_DEPTH,
- MIN_DEPTH,
- MAX_DEPTH,
- AVG_SAC,
- MIN_SAC,
- MAX_SAC,
- AVG_TEMP,
- MIN_TEMP,
- MAX_TEMP,
- N_COLUMNS
-};
-
-static void init_tree()
-{
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- GtkTreeStore *store;
- int i;
- PangoFontDescription *font_desc = pango_font_description_from_string(prefs.divelist_font);
-
- gtk_widget_modify_font(yearly_tree, font_desc);
- pango_font_description_free(font_desc);
-
- renderer = gtk_cell_renderer_text_new ();
- /* don't use empty strings "" - they confuse gettext */
- char *columnstop[] = { N_("Year"), N_("#"), N_("Duration"), " ", " ", " ", N_("Depth"), " ", " ", N_("SAC"), " ", " ", N_("Temperature"), " ", " " };
- const char *columnsbot[15];
- columnsbot[0] = C_("Stats", " > Month");
- columnsbot[1] = " ";
- columnsbot[2] = C_("Duration","Total");
- columnsbot[3] = C_("Duration","Average");
- columnsbot[4] = C_("Duration","Shortest");
- columnsbot[5] = C_("Duration","Longest");
- columnsbot[6] = C_("Depth", "Average");
- columnsbot[7] = C_("Depth","Minimum");
- columnsbot[8] = C_("Depth","Maximum");
- columnsbot[9] = C_("SAC","Average");
- columnsbot[10]= C_("SAC","Minimum");
- columnsbot[11]= C_("SAC","Maximum");
- columnsbot[12]= C_("Temp","Average");
- columnsbot[13]= C_("Temp","Minimum");
- columnsbot[14]= C_("Temp","Maximum");
-
- /* Add all the columns to the tree view */
- for (i = 0; i < N_COLUMNS; ++i) {
- char buf[256];
- column = gtk_tree_view_column_new();
- snprintf(buf, sizeof(buf), "%s\n%s", _(columnstop[i]), columnsbot[i]);
- gtk_tree_view_column_set_title(column, buf);
- gtk_tree_view_append_column(GTK_TREE_VIEW(yearly_tree), column);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text", i);
- gtk_tree_view_column_set_resizable(column, TRUE);
- }
-
- /* Field types */
- store = gtk_tree_store_new (
- N_COLUMNS, // Columns in structure
- G_TYPE_STRING, // Period (year or month)
- G_TYPE_STRING, // Number of dives
- G_TYPE_STRING, // Total duration
- G_TYPE_STRING, // Average dive duation
- G_TYPE_STRING, // Shortest dive
- G_TYPE_STRING, // Longest dive
- G_TYPE_STRING, // Average depth
- G_TYPE_STRING, // Shallowest dive
- G_TYPE_STRING, // Deepest dive
- G_TYPE_STRING, // Average air consumption (SAC)
- G_TYPE_STRING, // Minimum SAC
- G_TYPE_STRING, // Maximum SAC
- G_TYPE_STRING, // Average temperature
- G_TYPE_STRING, // Minimum temperature
- G_TYPE_STRING // Maximum temperature
- );
-
- gtk_tree_view_set_model (GTK_TREE_VIEW (yearly_tree), GTK_TREE_MODEL (store));
- g_object_unref (store);
-}
-
-static void add_row_to_tree(GtkTreeStore *store, char *value, int index, GtkTreeIter *row_iter, GtkTreeIter *parent)
-{
- gtk_tree_store_append(store, row_iter, parent);
- gtk_tree_store_set(store, row_iter, index, value, -1);
-}
-
-static void add_cell_to_tree(GtkTreeStore *store, char *value, int index, GtkTreeIter *parent)
-{
- gtk_tree_store_set(store, parent, index, value, -1);
-}
-
-static void add_cell(GtkTreeStore *store, GtkTreeIter *parent, unsigned int val, int cell, gboolean depth_not_volume)
-{
- double value;
- int decimals;
- const char *unit;
- char value_str[40];
-
- if (depth_not_volume) {
- value = get_depth_units(val, &decimals, &unit);
- snprintf(value_str, sizeof(value_str), "%.*f %s", decimals, value, unit);
- } else {
- value = get_volume_units(val, &decimals, &unit);
- snprintf(value_str, sizeof(value_str), _("%.*f %s/min"), decimals, value, unit);
- }
- add_cell_to_tree(store, value_str, cell, parent);
-}
-
-static void process_interval_stats(stats_t stats_interval, GtkTreeIter *parent, GtkTreeIter *row)
-{
- double value;
- const char *unit;
- char value_str[40];
- GtkTreeStore *store;
-
- store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(yearly_tree)));
-
- /* Year or month */
- snprintf(value_str, sizeof(value_str), "%d", stats_interval.period);
- add_row_to_tree(store, value_str, 0, row, parent);
- /* Dives */
- snprintf(value_str, sizeof(value_str), "%d", stats_interval.selection_size);
- add_cell_to_tree(store, value_str, 1, row);
- /* Total duration */
- add_cell_to_tree(store, get_time_string(stats_interval.total_time.seconds, 0), 2, row);
- /* Average dive duration */
- add_cell_to_tree(store, get_minutes(stats_interval.total_time.seconds / stats_interval.selection_size), 3, row);
- /* Shortest duration */
- add_cell_to_tree(store, get_minutes(stats_interval.shortest_time.seconds), 4, row);
- /* Longest duration */
- add_cell_to_tree(store, get_minutes(stats_interval.longest_time.seconds), 5, row);
- /* Average depth */
- add_cell(store, row, stats_interval.avg_depth.mm, 6, TRUE);
- /* Smallest maximum depth */
- add_cell(store, row, stats_interval.min_depth.mm, 7, TRUE);
- /* Deepest maximum depth */
- add_cell(store, row, stats_interval.max_depth.mm, 8, TRUE);
- /* Average air consumption */
- add_cell(store, row, stats_interval.avg_sac.mliter, 9, FALSE);
- /* Smallest average air consumption */
- add_cell(store, row, stats_interval.min_sac.mliter, 10, FALSE);
- /* Biggest air consumption */
- add_cell(store, row, stats_interval.max_sac.mliter, 11, FALSE);
- /* Average water temperature */
- value = get_temp_units(stats_interval.min_temp, &unit);
- if (stats_interval.combined_temp && stats_interval.combined_count) {
- snprintf(value_str, sizeof(value_str), "%.1f %s", stats_interval.combined_temp / stats_interval.combined_count, unit);
- add_cell_to_tree(store, value_str, 12, row);
- } else {
- add_cell_to_tree(store, "", 12, row);
- }
- /* Coldest water temperature */
- if (value > -100.0) {
- snprintf(value_str, sizeof(value_str), "%.1f %s\t", value, unit);
- add_cell_to_tree(store, value_str, 13, row);
- } else {
- add_cell_to_tree(store, "", 13, row);
- }
- /* Warmest water temperature */
- value = get_temp_units(stats_interval.max_temp, &unit);
- if (value > -100.0) {
- snprintf(value_str, sizeof(value_str), "%.1f %s", value, unit);
- add_cell_to_tree(store, value_str, 14, row);
- } else {
- add_cell_to_tree(store, "", 14, row);
- }
-}
-
-static void clear_statistics()
-{
- GtkTreeStore *store;
-
- store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(yearly_tree)));
- gtk_tree_store_clear(store);
- yearly_tree = NULL;
-}
-
-static gboolean stat_on_delete(GtkWidget *window, GdkEvent *event, gpointer data)
-{
- clear_statistics();
- gtk_widget_destroy(window);
- return TRUE;
-}
-
-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)) {
- clear_statistics();
- gtk_widget_destroy(window);
- }
-}
-
-static void update_yearly_stats()
-{
- int i, j, combined_months, month = 0;
- GtkTreeIter year_iter, month_iter;
- GtkTreeStore *store;
-
- store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(yearly_tree)));
- gtk_tree_store_clear(store);
-
- for (i = 0; stats_yearly != NULL && stats_yearly[i].period; ++i) {
- process_interval_stats(stats_yearly[i], NULL, &year_iter);
- combined_months = 0;
-
- for (j = 0; combined_months < stats_yearly[i].selection_size; ++j) {
- combined_months += stats_monthly[month].selection_size;
- process_interval_stats(stats_monthly[month], &year_iter, &month_iter);
- month++;
- }
- }
-}
-
-void show_yearly_stats()
-{
- GtkWidget *window;
- GtkWidget *sw;
-
- if (yearly_tree)
- return;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- sw = gtk_scrolled_window_new (NULL, NULL);
- yearly_tree = gtk_tree_view_new ();
-
- gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
- gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
- gtk_window_set_title(GTK_WINDOW(window), _("Yearly Statistics"));
- gtk_container_set_border_width(GTK_CONTAINER(window), 5);
- gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
-
- gtk_container_add (GTK_CONTAINER (sw), yearly_tree);
- gtk_container_add (GTK_CONTAINER (window), sw);
-
- /* Display the yearly statistics on top level
- * Monthly statistics are available by expanding a year */
- init_tree();
- update_yearly_stats();
-
- g_signal_connect (G_OBJECT (window), "key_press_event", G_CALLBACK (key_press_event), NULL);
- g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (stat_on_delete), NULL);
- gtk_widget_show_all(window);
-}
-
-static void set_label(GtkWidget *w, const char *fmt, ...)
-{
- char buf[256];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- gtk_label_set_text(GTK_LABEL(w), buf);
-}
-
-/* we try to show the data from the currently selected divecomputer
- * right now for some values (e.g., surface pressure) we could fall back
- * to dive data, but for consistency we don't. */
-static void show_single_dive_stats(struct dive *dive)
-{
- char buf[256];
- double value;
- int decimals;
- const char *unit;
- int idx, offset, gas_used, mbar;
- struct dive *prev_dive;
- struct tm tm;
- struct divecomputer *dc;
- int more = 0;
-
- process_all_dives(dive, &prev_dive);
- if (yearly_tree)
- update_yearly_stats();
- if (!dive)
- return;
- dc = select_dc(&dive->dc);
- utc_mkdate(dive->when, &tm);
- snprintf(buf, sizeof(buf),
- /*++GETTEXT 80 chars: weekday, monthname, day, year, hour, min */
- _("%1$s, %2$s %3$d, %4$d %5$2d:%6$02d"),
- weekday(tm.tm_wday),
- monthname(tm.tm_mon),
- tm.tm_mday, tm.tm_year + 1900,
- tm.tm_hour, tm.tm_min);
-
- set_label(single_w.date, buf);
- set_label(single_w.dive_time, _("%d min"), (dive->duration.seconds + 30) / 60);
- if (prev_dive)
- set_label(single_w.surf_intv,
- get_time_string(dive->when - (prev_dive->when + prev_dive->duration.seconds), 4));
- else
- set_label(single_w.surf_intv, _("unknown"));
- value = get_depth_units(dc->maxdepth.mm, &decimals, &unit);
- set_label(single_w.max_depth, "%.*f %s", decimals, value, unit);
- value = get_depth_units(dc->meandepth.mm, &decimals, &unit);
- set_label(single_w.avg_depth, "%.*f %s", decimals, value, unit);
- set_label(single_w.viz, star_strings[dive->visibility]);
- if (dc->watertemp.mkelvin) {
- value = get_temp_units(dc->watertemp.mkelvin, &unit);
- set_label(single_w.water_temp, "%.1f %s", value, unit);
- } else {
- set_label(single_w.water_temp, "");
- }
- if (dc->airtemp.mkelvin) {
- value = get_temp_units(dc->airtemp.mkelvin, &unit);
- set_label(single_w.air_temp, "%.1f %s", value, unit);
- } else {
- if (dive->airtemp.mkelvin) {
- value = get_temp_units(dive->airtemp.mkelvin, &unit);
- set_label(single_w.air_temp, "%.1f %s", value, unit);
- } else {
- set_label(single_w.air_temp, "");
- }
- }
- mbar = dc->surface_pressure.mbar;
- /* it would be easy to get dive data here:
- * if (!mbar)
- * mbar = get_surface_pressure_in_mbar(dive, FALSE);
- */
- if (mbar) {
- set_label(single_w.air_press, "%d mbar", mbar);
- } else {
- set_label(single_w.air_press, "");
- }
- value = get_volume_units(dive->sac, &decimals, &unit);
- if (value > 0)
- set_label(single_w.sac, _("%.*f %s/min"), decimals, value, unit);
- else
- set_label(single_w.sac, "");
- set_label(single_w.otu, "%d", dive->otu);
- offset = 0;
- gas_used = 0;
- buf[0] = '\0';
- /* for the O2/He readings just create a list of them */
- for (idx = 0; idx < MAX_CYLINDERS; idx++) {
- cylinder_t *cyl = &dive->cylinder[idx];
- pressure_t start, end;
-
- start = cyl->start.mbar ? cyl->start : cyl->sample_start;
- end = cyl->end.mbar ?cyl->sample_end : cyl->sample_end;
- if (!cylinder_none(cyl)) {
- /* 0% O2 strangely means air, so 21% - I don't like that at all */
- int o2 = get_o2(&cyl->gasmix);
- int he = get_he(&cyl->gasmix);
- if (offset > 0) {
- snprintf(buf+offset, 80-offset, ", ");
- offset += 2;
- }
- snprintf(buf+offset, 80-offset, "%d/%d", (o2 + 5) / 10, (he + 5) / 10);
- offset = strlen(buf);
- }
- /* and if we have size, start and end pressure, we can
- * calculate the total gas used */
- if (start.mbar && end.mbar)
- gas_used += gas_volume(cyl, start) - gas_volume(cyl, end);
- }
- set_label(single_w.o2he, buf);
- if (gas_used) {
- value = get_volume_units(gas_used, &decimals, &unit);
- set_label(single_w.gas_used, "%.*f %s", decimals, value, unit);
- } else {
- set_label(single_w.gas_used, "");
- }
-
- /* Dive type */
- *buf = '\0';
- if (dive->dive_tags) {
- int i;
-
- for (i = 0; i < DTAG_NR; i++)
- if(dive->dive_tags & (1 << i)) {
- if (more)
- strcat(buf, ", ");
- strcat(buf, _(dtag_names[i]));
- more = 1;
- }
- }
- if (!(dive->dive_tags & DTAG_FRESH) && dc->salinity == 10000) {
- if (more)
- strcat(buf, ", ");
- strcat(buf, _(dtag_names[DTAG_FRESH_NR]));
- }
- set_label(single_w.dive_type, buf);
-}
-
-static void show_total_dive_stats(void)
-{
- double value;
- int decimals, seconds;
- const char *unit;
- char buffer[60];
- stats_t *stats_ptr;
-
- if (!stats_w.framelabel)
- return;
- stats_ptr = &stats_selection;
-
- get_selected_dives_text(buffer, sizeof(buffer));
- set_label(stats_w.framelabel, _("Statistics %s"), buffer);
- set_label(stats_w.selection_size, "%d", stats_ptr->selection_size);
- if (stats_ptr->selection_size == 0) {
- clear_stats_widgets();
- return;
- }
- if (stats_ptr->min_temp) {
- value = get_temp_units(stats_ptr->min_temp, &unit);
- set_label(stats_w.min_temp, "%.1f %s", value, unit);
- }
- if (stats_ptr->combined_temp && stats_ptr->combined_count)
- set_label(stats_w.avg_temp, "%.1f %s", stats_ptr->combined_temp / stats_ptr->combined_count, unit);
- if (stats_ptr->max_temp) {
- value = get_temp_units(stats_ptr->max_temp, &unit);
- set_label(stats_w.max_temp, "%.1f %s", value, unit);
- }
- set_label(stats_w.total_time, get_time_string(stats_ptr->total_time.seconds, 0));
- seconds = stats_ptr->total_time.seconds;
- if (stats_ptr->selection_size)
- seconds /= stats_ptr->selection_size;
- set_label(stats_w.avg_time, get_time_string(seconds, 0));
- set_label(stats_w.longest_time, get_time_string(stats_ptr->longest_time.seconds, 0));
- set_label(stats_w.shortest_time, get_time_string(stats_ptr->shortest_time.seconds, 0));
- value = get_depth_units(stats_ptr->max_depth.mm, &decimals, &unit);
- set_label(stats_w.max_overall_depth, "%.*f %s", decimals, value, unit);
- value = get_depth_units(stats_ptr->min_depth.mm, &decimals, &unit);
- set_label(stats_w.min_overall_depth, "%.*f %s", decimals, value, unit);
- value = get_depth_units(stats_ptr->avg_depth.mm, &decimals, &unit);
- set_label(stats_w.avg_overall_depth, "%.*f %s", decimals, value, unit);
- value = get_volume_units(stats_ptr->max_sac.mliter, &decimals, &unit);
- set_label(stats_w.max_sac, _("%.*f %s/min"), decimals, value, unit);
- value = get_volume_units(stats_ptr->min_sac.mliter, &decimals, &unit);
- set_label(stats_w.min_sac, _("%.*f %s/min"), decimals, value, unit);
- value = get_volume_units(stats_ptr->avg_sac.mliter, &decimals, &unit);
- set_label(stats_w.avg_sac, _("%.*f %s/min"), decimals, value, unit);
-}
-
-void show_dive_stats(struct dive *dive)
-{
- /* they have to be called in this order, as 'total' depends on
- * calculations done in 'single' */
- show_single_dive_stats(dive);
- show_total_dive_stats();
-}
-
-static GtkWidget *new_info_label_in_frame(GtkWidget *box, const char *label)
-{
- GtkWidget *label_widget;
- GtkWidget *frame;
-
- frame = gtk_frame_new(label);
- label_widget = gtk_label_new(NULL);
- gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 3);
- gtk_container_add(GTK_CONTAINER(frame), label_widget);
-
- return label_widget;
-}
-
-GtkWidget *total_stats_widget(void)
-{
- GtkWidget *vbox, *hbox, *statsframe, *framebox;
-
- vbox = gtk_vbox_new(FALSE, 3);
-
- statsframe = gtk_frame_new(_("Statistics"));
- stats_w.framelabel = gtk_frame_get_label_widget(GTK_FRAME(statsframe));
- gtk_label_set_max_width_chars(GTK_LABEL(stats_w.framelabel), 60);
- gtk_box_pack_start(GTK_BOX(vbox), statsframe, FALSE, FALSE, 3);
- framebox = gtk_vbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(statsframe), framebox);
-
- /* first row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
- stats_w.selection_size = new_info_label_in_frame(hbox, _("Dives"));
- stats_w.max_temp = new_info_label_in_frame(hbox, _("Max Temp"));
- stats_w.min_temp = new_info_label_in_frame(hbox, _("Min Temp"));
- stats_w.avg_temp = new_info_label_in_frame(hbox, _("Avg Temp"));
-
- /* second row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- stats_w.total_time = new_info_label_in_frame(hbox, _("Total Time"));
- stats_w.avg_time = new_info_label_in_frame(hbox, _("Avg Time"));
- stats_w.longest_time = new_info_label_in_frame(hbox, _("Longest Dive"));
- stats_w.shortest_time = new_info_label_in_frame(hbox, _("Shortest Dive"));
-
- /* third row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- stats_w.max_overall_depth = new_info_label_in_frame(hbox, _("Max Depth"));
- stats_w.min_overall_depth = new_info_label_in_frame(hbox, _("Min Depth"));
- stats_w.avg_overall_depth = new_info_label_in_frame(hbox, _("Avg Depth"));
-
- /* fourth row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- stats_w.max_sac = new_info_label_in_frame(hbox, _("Max SAC"));
- stats_w.min_sac = new_info_label_in_frame(hbox, _("Min SAC"));
- stats_w.avg_sac = new_info_label_in_frame(hbox, _("Avg SAC"));
-
- return vbox;
-}
-
-GtkWidget *single_stats_widget(void)
-{
- GtkWidget *vbox, *hbox, *infoframe, *framebox;
-
- vbox = gtk_vbox_new(FALSE, 3);
-
- infoframe = gtk_frame_new(_("Dive Info"));
- gtk_box_pack_start(GTK_BOX(vbox), infoframe, FALSE, FALSE, 3);
- framebox = gtk_vbox_new(FALSE, 3);
- gtk_container_add(GTK_CONTAINER(infoframe), framebox);
-
- /* first row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- single_w.date = new_info_label_in_frame(hbox, _("Date"));
- single_w.dive_time = new_info_label_in_frame(hbox, _("Dive Time"));
- single_w.surf_intv = new_info_label_in_frame(hbox, _("Surf Intv"));
-
- /* second row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- single_w.max_depth = new_info_label_in_frame(hbox, _("Max Depth"));
- single_w.avg_depth = new_info_label_in_frame(hbox, _("Avg Depth"));
- single_w.viz = new_info_label_in_frame(hbox, _("Visibility"));
-
- /* third row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- single_w.water_temp = new_info_label_in_frame(hbox, _("Water Temp"));
- single_w.air_temp = new_info_label_in_frame(hbox, _("Air Temp"));
- single_w.air_press = new_info_label_in_frame(hbox, _("Air Press"));
-
- /* fourth row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- single_w.sac = new_info_label_in_frame(hbox, _("SAC"));
- single_w.otu = new_info_label_in_frame(hbox, _("OTU"));
- single_w.o2he = new_info_label_in_frame(hbox, "O" UTF8_SUBSCRIPT_2 " / He");
- single_w.gas_used = new_info_label_in_frame(hbox, C_("Amount","Gas Used"));
-
- /* fifth row */
- hbox = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
-
- single_w.dive_type = new_info_label_in_frame(hbox, _("Dive Tags"));
-
- return vbox;
-}
-
-void clear_stats_widgets(void)
-{
- set_label(single_w.date, "");
- set_label(single_w.dive_time, "");
- set_label(single_w.surf_intv, "");
- set_label(single_w.max_depth, "");
- set_label(single_w.avg_depth, "");
- set_label(single_w.viz, "");
- set_label(single_w.water_temp, "");
- set_label(single_w.air_temp, "");
- set_label(single_w.air_press, "");
- set_label(single_w.sac, "");
- set_label(single_w.sac, "");
- set_label(single_w.otu, "");
- set_label(single_w.o2he, "");
- set_label(single_w.gas_used, "");
- set_label(single_w.dive_type, "");
- set_label(stats_w.total_time,"");
- set_label(stats_w.avg_time,"");
- set_label(stats_w.shortest_time,"");
- set_label(stats_w.longest_time,"");
- set_label(stats_w.max_overall_depth,"");
- set_label(stats_w.min_overall_depth,"");
- set_label(stats_w.avg_overall_depth,"");
- set_label(stats_w.min_sac,"");
- set_label(stats_w.avg_sac,"");
- set_label(stats_w.max_sac,"");
- set_label(stats_w.selection_size,"");
- set_label(stats_w.max_temp,"");
- set_label(stats_w.avg_temp,"");
- set_label(stats_w.min_temp,"");
-}