X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=gtk-gui.c;h=dce537232fdbd9ba81ca5dfb69b332f28d269228;hb=269b5c02864d26722669bc47d779f72dbccf2fc7;hp=b889f114d86a7a6301aed3a38b8eed407051d79c;hpb=b6f6107be1be09536f16a84c20af1604e99d6d5c;p=ext%2Fsubsurface.git diff --git a/gtk-gui.c b/gtk-gui.c index b889f11..dce5372 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -8,8 +8,6 @@ #include #include -#include - #include "dive.h" #include "divelist.h" #include "display.h" @@ -21,16 +19,14 @@ GtkWidget *main_window; GtkWidget *main_vbox; GtkWidget *error_info_bar; GtkWidget *error_label; +GtkWidget *vpane, *hpane; int error_count; #define DIVELIST_DEFAULT_FONT "Sans 8" const char *divelist_font; -GConfClient *gconf; struct units output_units; -#define GCONF_NAME(x) "/apps/subsurface/" #x - static GtkWidget *dive_profile; visible_cols_t visible_cols = {TRUE, FALSE}; @@ -43,6 +39,7 @@ void repaint_dive(void) } static char *existing_filename; +static gboolean need_icon = TRUE; static void on_info_bar_response(GtkWidget *widget, gint response, gpointer data) @@ -116,7 +113,7 @@ static void file_open(GtkWidget *w, gpointer data) GError *error = NULL; while(filenames != NULL) { - filename = (char *)filenames->data; + filename = filenames->data; parse_xml_file(filename, &error); if (error != NULL) { @@ -205,17 +202,25 @@ static void quit(GtkWidget *w, gpointer data) } GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title, - data_func_t data_func, PangoAlignment align, gboolean visible) + data_func_t data_func, unsigned int flags) { GtkCellRenderer *renderer; GtkTreeViewColumn *col; double xalign = 0.0; /* left as default */ + PangoAlignment align; + gboolean visible; + + align = (flags & ALIGN_LEFT) ? PANGO_ALIGN_LEFT : + (flags & ALIGN_RIGHT) ? PANGO_ALIGN_RIGHT : + PANGO_ALIGN_CENTER; + visible = !(flags & INVISIBLE); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col, title); - gtk_tree_view_column_set_sort_column_id(col, index); + if (!(flags & UNSORTABLE)) + gtk_tree_view_column_set_sort_column_id(col, index); gtk_tree_view_column_set_resizable(col, TRUE); gtk_tree_view_column_pack_start(col, renderer, TRUE); if (data_func) @@ -300,6 +305,16 @@ static void name(GtkWidget *w, gpointer data) \ OPTIONCALLBACK(otu_toggle, visible_cols.otu) OPTIONCALLBACK(sac_toggle, visible_cols.sac) +OPTIONCALLBACK(nitrox_toggle, visible_cols.nitrox) +OPTIONCALLBACK(temperature_toggle, visible_cols.temperature) +OPTIONCALLBACK(cylinder_toggle, visible_cols.cylinder) + +static void event_toggle(GtkWidget *w, gpointer _data) +{ + gboolean *plot_ev = _data; + + *plot_ev = GTK_TOGGLE_BUTTON(w)->active; +} static void preferences_dialog(GtkWidget *w, gpointer data) { @@ -348,6 +363,21 @@ static void preferences_dialog(GtkWidget *w, gpointer data) box = gtk_hbox_new(FALSE, 6); gtk_container_add(GTK_CONTAINER(frame), box); + button = gtk_check_button_new_with_label("Show Temp"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.temperature); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(temperature_toggle), NULL); + + button = gtk_check_button_new_with_label("Show Cyl"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.cylinder); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(cylinder_toggle), NULL); + + button = gtk_check_button_new_with_label("Show O" UTF8_SUBSCRIPT_2 "%"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.nitrox); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(nitrox_toggle), NULL); + button = gtk_check_button_new_with_label("Show SAC"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.sac); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); @@ -374,13 +404,76 @@ static void preferences_dialog(GtkWidget *w, gpointer data) update_dive_list_units(); repaint_dive(); update_dive_list_col_visibility(); - gconf_client_set_bool(gconf, GCONF_NAME(feet), output_units.length == FEET, NULL); - gconf_client_set_bool(gconf, GCONF_NAME(psi), output_units.pressure == PSI, NULL); - gconf_client_set_bool(gconf, GCONF_NAME(cuft), output_units.volume == CUFT, NULL); - gconf_client_set_bool(gconf, GCONF_NAME(fahrenheit), output_units.temperature == FAHRENHEIT, NULL); - gconf_client_set_bool(gconf, GCONF_NAME(SAC), ! visible_cols.sac, NULL); /* inverted to get the correct default */ - gconf_client_set_bool(gconf, GCONF_NAME(OTU), visible_cols.otu, NULL); - gconf_client_set_string(gconf, GCONF_NAME(divelist_font), divelist_font, NULL); + + subsurface_set_conf("feet", PREF_BOOL, BOOL_TO_PTR(output_units.length == FEET)); + subsurface_set_conf("psi", PREF_BOOL, BOOL_TO_PTR(output_units.pressure == PSI)); + subsurface_set_conf("cuft", PREF_BOOL, BOOL_TO_PTR(output_units.volume == CUFT)); + subsurface_set_conf("fahrenheit", PREF_BOOL, BOOL_TO_PTR(output_units.temperature == FAHRENHEIT)); + subsurface_set_conf("TEMPERATURE", PREF_BOOL, BOOL_TO_PTR(visible_cols.temperature)); + subsurface_set_conf("CYLINDER", PREF_BOOL, BOOL_TO_PTR(visible_cols.cylinder)); + subsurface_set_conf("NITROX", PREF_BOOL, BOOL_TO_PTR(visible_cols.nitrox)); + subsurface_set_conf("SAC", PREF_BOOL, BOOL_TO_PTR(visible_cols.sac)); + subsurface_set_conf("OTU", PREF_BOOL, BOOL_TO_PTR(visible_cols.otu)); + subsurface_set_conf("divelist_font", PREF_STRING, divelist_font); + subsurface_close_conf(); + } + gtk_widget_destroy(dialog); +} + +static void create_toggle(const char* label, int *on, void *_data) +{ + GtkWidget *button, *table = _data; + int rows, cols, x, y; + static int count; + + if (table == NULL) { + /* magic way to reset the number of toggle buttons + * that we have already added - call this before you + * create the dialog */ + count = 0; + return; + } + g_object_get(G_OBJECT(table), "n-columns", &cols, "n-rows", &rows, NULL); + if (count > rows * cols) { + gtk_table_resize(GTK_TABLE(table),rows+1,cols); + rows++; + } + x = count % cols; + y = count / cols; + button = gtk_check_button_new_with_label(label); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *on); + gtk_table_attach_defaults(GTK_TABLE(table), button, x, x+1, y, y+1); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(event_toggle), on); + count++; +} + +static void selectevents_dialog(GtkWidget *w, gpointer data) +{ + int result; + GtkWidget *dialog, *frame, *vbox, *table; + + dialog = gtk_dialog_new_with_buttons("SelectEvents", + GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + /* initialize the function that fills the table */ + create_toggle(NULL, NULL, NULL); + + frame = gtk_frame_new("Enable / Disable Events"); + vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); + + table = gtk_table_new(1, 4, TRUE); + gtk_container_add(GTK_CONTAINER(frame), table); + + evn_foreach(&create_toggle, table); + + gtk_widget_show_all(dialog); + result = gtk_dialog_run(GTK_DIALOG(dialog)); + if (result == GTK_RESPONSE_ACCEPT) { + repaint_dive(); } gtk_widget_destroy(dialog); } @@ -428,11 +521,18 @@ static void about_dialog(GtkWidget *w, gpointer data) { const char *logo_property = NULL; GdkPixbuf *logo = NULL; - GtkWidget *image = gtk_image_new_from_file("icon.svg"); - if (image) { - logo = gtk_image_get_pixbuf(GTK_IMAGE(image)); - logo_property = "logo"; + if (need_icon) { +#if defined __linux__ || defined __APPLE__ + GtkWidget *image = gtk_image_new_from_file("subsurface.svg"); +#elif defined WIN32 + GtkWidget *image = gtk_image_new_from_file("subsurface.ico"); +#endif + + if (image) { + logo = gtk_image_get_pixbuf(GTK_IMAGE(image)); + logo_property = "logo"; + } } gtk_show_about_dialog(NULL, @@ -441,14 +541,41 @@ static void about_dialog(GtkWidget *w, gpointer data) "license", "GPLv2", "version", VERSION_STRING, "copyright", "Linus Torvalds 2011", + "logo-icon-name", "subsurface", /* Must be last: */ logo_property, logo, NULL); } +static void view_list(GtkWidget *w, gpointer data) +{ + gtk_paned_set_position(GTK_PANED(vpane), 0); +} + +static void view_profile(GtkWidget *w, gpointer data) +{ + gtk_paned_set_position(GTK_PANED(hpane), 0); + gtk_paned_set_position(GTK_PANED(vpane), 65535); +} + +static void view_info(GtkWidget *w, gpointer data) +{ + gtk_paned_set_position(GTK_PANED(vpane), 65535); + gtk_paned_set_position(GTK_PANED(hpane), 65535); +} + +/* Ooh. I don't know how to get the half-way size. So I'm just using random numbers */ +static void view_three(GtkWidget *w, gpointer data) +{ + gtk_paned_set_position(GTK_PANED(hpane), 400); + gtk_paned_set_position(GTK_PANED(vpane), 200); +} + static GtkActionEntry menu_items[] = { { "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL}, { "LogMenuAction", GTK_STOCK_FILE, "Log", NULL, NULL, NULL}, + { "ViewMenuAction", GTK_STOCK_FILE, "View", NULL, NULL, NULL}, + { "FilterMenuAction", GTK_STOCK_FILE, "Filter", NULL, NULL, NULL}, { "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL}, { "OpenFile", GTK_STOCK_OPEN, NULL, "O", NULL, G_CALLBACK(file_open) }, { "SaveFile", GTK_STOCK_SAVE, NULL, "S", NULL, G_CALLBACK(file_save) }, @@ -456,8 +583,13 @@ static GtkActionEntry menu_items[] = { { "Import", NULL, "Import", NULL, NULL, G_CALLBACK(import_dialog) }, { "Preferences", NULL, "Preferences", NULL, NULL, G_CALLBACK(preferences_dialog) }, { "Renumber", NULL, "Renumber", NULL, NULL, G_CALLBACK(renumber_dialog) }, + { "SelectEvents", NULL, "SelectEvents", NULL, NULL, G_CALLBACK(selectevents_dialog) }, { "Quit", GTK_STOCK_QUIT, NULL, "Q", NULL, G_CALLBACK(quit) }, - { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) }, + { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK(about_dialog) }, + { "ViewList", NULL, "List", "1", NULL, G_CALLBACK(view_list) }, + { "ViewProfile", NULL, "Profile", "2", NULL, G_CALLBACK(view_profile) }, + { "ViewInfo", NULL, "Info", "3", NULL, G_CALLBACK(view_info) }, + { "ViewThree", NULL, "Three", "4", NULL, G_CALLBACK(view_three) }, }; static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); @@ -477,6 +609,15 @@ static const gchar* ui_string = " \ \ \ \ + \ + \ + \ + \ + \ + \ + \ + \ + \ \ \ \ @@ -506,128 +647,67 @@ static void switch_page(GtkNotebook *notebook, gint arg1, gpointer user_data) repaint_dive(); } -static const char notebook_group[] = "123"; -#define GRP_ID ((void *)notebook_group) -typedef struct { - char *name; - GtkWidget *widget; - GtkWidget *box; - gulong delete_handler; - gulong destroy_handler; -} notebook_data_t; - -static notebook_data_t nbd[2]; /* we rip at most two notebook pages off */ - -static GtkNotebook *create_new_notebook_window(GtkNotebook *source, - GtkWidget *page, - gint x, gint y, gpointer data) -{ - GtkWidget *win, *notebook, *vbox; - notebook_data_t *nbdp; - - /* pick the right notebook page data and return if both are detached */ - if (nbd[0].widget == NULL) - nbdp = nbd; - else if (nbd[1].widget == NULL) - nbdp = nbd + 1; - else - return NULL; - - nbdp->name = strdup(gtk_widget_get_name(page)); - nbdp->widget = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(win), nbdp->name); - gtk_window_move(GTK_WINDOW(win), x, y); - - /* Destroying the dive list will kill the application */ - nbdp->delete_handler = g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL); - nbdp->destroy_handler = g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); - - nbdp->box = vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(win), vbox); - - notebook = gtk_notebook_new(); - gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); - gtk_widget_set_name(notebook, nbdp->name); - /* disallow drop events */ - gtk_drag_dest_set(notebook, 0, NULL, 0, 0); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); - gtk_widget_set_size_request(notebook, 450, 350); - - gtk_widget_show_all(win); - return GTK_NOTEBOOK(notebook); -} - -static void drag_cb(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, guint time, - gpointer user_data) -{ - GtkWidget *source; - notebook_data_t *nbdp; - - source = gtk_drag_get_source_widget(context); - if (nbd[0].name && ! strcmp(nbd[0].name,gtk_widget_get_name(source))) - nbdp = nbd; - else if (nbd[1].name && ! strcmp(nbd[1].name,gtk_widget_get_name(source))) - nbdp = nbd + 1; - else - /* HU? */ - return; - - gtk_drag_finish(context, TRUE, TRUE, time); - - /* we no longer need the widget - but getting rid of this is hard; - * remove the signal handler, remove the notebook from the box - * then destroy the widget (and clear out our data structure) */ - g_signal_handler_disconnect(nbdp->widget,nbdp->delete_handler); - g_signal_handler_disconnect(nbdp->widget,nbdp->destroy_handler); - gtk_container_remove(GTK_CONTAINER(nbdp->box), source); - gtk_widget_destroy(nbdp->widget); - nbdp->widget = NULL; - free(nbdp->name); - nbdp->name = NULL; -} - -void init_ui(int argc, char **argv) +void init_ui(int *argcp, char ***argvp) { GtkWidget *win; GtkWidget *notebook; GtkWidget *dive_info; GtkWidget *dive_list; GtkWidget *equipment; + GtkWidget *stats; GtkWidget *menubar; GtkWidget *vbox; + GdkScreen *screen; + GtkIconTheme *icon_theme=NULL; GtkSettings *settings; - static const GtkTargetEntry notebook_target = { - "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 - }; - gtk_init(&argc, &argv); + gtk_init(argcp, argvp); settings = gtk_settings_get_default(); gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "subsurface setting"); g_type_init(); - gconf = gconf_client_get_default(); - if (gconf_client_get_bool(gconf, GCONF_NAME(feet), NULL)) + subsurface_open_conf(); + if (subsurface_get_conf("feet", PREF_BOOL)) output_units.length = FEET; - if (gconf_client_get_bool(gconf, GCONF_NAME(psi), NULL)) + if (subsurface_get_conf("psi", PREF_BOOL)) output_units.pressure = PSI; - if (gconf_client_get_bool(gconf, GCONF_NAME(cuft), NULL)) + if (subsurface_get_conf("cuft", PREF_BOOL)) output_units.volume = CUFT; - if (gconf_client_get_bool(gconf, GCONF_NAME(fahrenheit), NULL)) + if (subsurface_get_conf("fahrenheit", PREF_BOOL)) output_units.temperature = FAHRENHEIT; - /* an unset key is FALSE - so in order to get the default behavior right we - invert the meaning of the SAC key */ - visible_cols.otu = gconf_client_get_bool(gconf, GCONF_NAME(OTU), NULL); - visible_cols.sac = ! gconf_client_get_bool(gconf, GCONF_NAME(SAC), NULL); - - divelist_font = gconf_client_get_string(gconf, GCONF_NAME(divelist_font), NULL); + /* an unset key is FALSE - all these are hidden by default */ + visible_cols.cylinder = PTR_TO_BOOL(subsurface_get_conf("CYLINDER", PREF_BOOL)); + visible_cols.temperature = PTR_TO_BOOL(subsurface_get_conf("TEMPERATURE", PREF_BOOL)); + visible_cols.nitrox = PTR_TO_BOOL(subsurface_get_conf("NITROX", PREF_BOOL)); + visible_cols.otu = PTR_TO_BOOL(subsurface_get_conf("OTU", PREF_BOOL)); + visible_cols.sac = PTR_TO_BOOL(subsurface_get_conf("SAC", PREF_BOOL)); + + divelist_font = subsurface_get_conf("divelist_font", PREF_STRING); + if (!divelist_font) divelist_font = DIVELIST_DEFAULT_FONT; error_info_bar = NULL; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_icon_from_file(GTK_WINDOW(win), "icon.svg", NULL); + g_set_application_name ("subsurface"); + /* Let's check if the subsurface icon has been installed or if + * we need to try to load it from the current directory */ + screen = gdk_screen_get_default(); + if (screen) + icon_theme = gtk_icon_theme_get_for_screen(screen); + if (icon_theme) { + if (gtk_icon_theme_has_icon(icon_theme, "subsurface")) { + need_icon = FALSE; + gtk_window_set_default_icon_name ("subsurface"); + } + } + if (need_icon) +#if defined __linux__ || defined __APPLE__ + gtk_window_set_icon_from_file(GTK_WINDOW(win), "subsurface.svg", NULL); +#elif defined WIN32 + gtk_window_set_icon_from_file(GTK_WINDOW(win), "subsurface.ico", NULL); +#endif g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); main_window = win; @@ -639,28 +719,26 @@ void init_ui(int argc, char **argv) menubar = get_menubar_menu(win); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); + vpane = gtk_vpaned_new(); + gtk_box_pack_start(GTK_BOX(vbox), vpane, TRUE, TRUE, 3); + + hpane = gtk_hpaned_new(); + gtk_paned_add1(GTK_PANED(vpane), hpane); + /* Notebook for dive info vs profile vs .. */ notebook = gtk_notebook_new(); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); - gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); - g_signal_connect(notebook, "create-window", G_CALLBACK(create_new_notebook_window), NULL); - gtk_drag_dest_set(notebook, GTK_DEST_DEFAULT_ALL, ¬ebook_target, 1, GDK_ACTION_MOVE); - g_signal_connect(notebook, "drag-drop", G_CALLBACK(drag_cb), notebook); + gtk_paned_add1(GTK_PANED(hpane), notebook); g_signal_connect(notebook, "switch-page", G_CALLBACK(switch_page), NULL); /* Create the actual divelist */ dive_list = dive_list_create(); gtk_widget_set_name(dive_list, "Dive List"); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_list, gtk_label_new("Dive List")); - gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_list, 1); - gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_list, 1); + gtk_paned_add2(GTK_PANED(vpane), dive_list); /* Frame for dive profile */ dive_profile = dive_profile_widget(); gtk_widget_set_name(dive_profile, "Dive Profile"); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_profile, gtk_label_new("Dive Profile")); - gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_profile, 1); - gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_profile, 1); + gtk_paned_add2(GTK_PANED(hpane), dive_profile); /* Frame for extended dive info */ dive_info = extended_dive_info_widget(); @@ -670,6 +748,10 @@ void init_ui(int argc, char **argv) equipment = equipment_widget(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), equipment, gtk_label_new("Equipment")); + /* Frame for dive statistics */ + stats = stats_widget(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), stats, gtk_label_new("Info & Stats")); + gtk_widget_set_app_paintable(win, TRUE); gtk_widget_show_all(win); @@ -739,7 +821,7 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer gc.cr = gdk_cairo_create(widget->window); g_object_set(widget, "has-tooltip", TRUE, NULL); g_signal_connect(widget, "query-tooltip", G_CALLBACK(profile_tooltip), &drawing_area); - set_source_rgb(&gc, 0, 0, 0); + init_profile_background(&gc); cairo_paint(gc.cr); if (dive) { @@ -883,7 +965,7 @@ static GtkWidget *xml_file_selector(GtkWidget *vbox, GtkWidget *main_dialog) static void do_import_file(gpointer data, gpointer user_data) { GError *error = NULL; - parse_xml_file((char *)data, &error); + parse_xml_file(data, &error); if (error != NULL) { @@ -967,7 +1049,7 @@ void update_progressbar(progressbar_t *progress, double value) void set_filename(const char *filename) { - if (filename) + if (!existing_filename && filename) existing_filename = strdup(filename); return; }