]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Merge branch 'freediving-tweaks' of git://github.com/mguentner/subsurface
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Aug 2012 20:20:23 +0000 (13:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Aug 2012 20:20:23 +0000 (13:20 -0700)
Merge freediving tweaks (zoom in on short dives etc) from Maximilian
Güntner.

Trivial conflicts in display.h due to unrelated printing stuff just
happening to be added nearby.

* 'freediving-tweaks' of git://github.com/mguentner/subsurface:
  moved zoomed_plot to display.h
  plot the time with a fixed padding (leading zero)
  updated/corrected comment
  added "Zoom" button and improved scaling
  fixed indentation
  use increments that make sense for 600 seconds
  Plot shorter (apnea) dives with a reasonable scale

1  2 
display.h
gtk-gui.c
profile.c

diff --combined display.h
index d054b699450161de1fc2e8699ac5e58173e06357,5f99849b7b496a699c6c9431f042f5cb725287f8..4e1511656ad5d20b38948b8819a5ad25aefe5ee0
+++ b/display.h
@@@ -26,9 -26,6 +26,11 @@@ extern void plot(struct graphics_contex
  extern void init_profile_background(struct graphics_context *gc);
  extern void attach_tooltip(int x, int y, int w, int h, const char *text);
  
 +struct options {
 +      enum { PRETTY, TABLE } type;
 +      gboolean print_profiles;
 +};
 +
+ extern char zoomed_plot;
  #endif
diff --combined gtk-gui.c
index 2a4d77ac9a78e60cc052ddbfdf3e36421b6d6109,9bd4f131d83e086d142e42877eb242001a32dfbd..7db777ab92e4254fdb14644ad2ac2c9348387dc4
+++ b/gtk-gui.c
@@@ -98,7 -98,7 +98,7 @@@ void report_error(GError* error
        {
                return;
        }
 -      
 +
        if (error_info_bar == NULL)
        {
                error_count = 1;
                g_signal_connect(error_info_bar, "response", G_CALLBACK(on_info_bar_response), NULL);
                gtk_info_bar_set_message_type(GTK_INFO_BAR(error_info_bar),
                                              GTK_MESSAGE_ERROR);
 -              
 +
                error_label = gtk_label_new(error->message);
                GtkWidget *container = gtk_info_bar_get_content_area(GTK_INFO_BAR(error_info_bar));
                gtk_container_add(GTK_CONTAINER(container), error_label);
 -              
 +
                gtk_box_pack_start(GTK_BOX(main_vbox), error_info_bar, FALSE, FALSE, 0);
                gtk_widget_show_all(main_vbox);
        }
@@@ -151,7 -151,7 +151,7 @@@ static void file_open(GtkWidget *w, gpo
                GSList *filenames, *fn_glist;
                char *filename;
                filenames = fn_glist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
 -              
 +
                GError *error = NULL;
                while(filenames != NULL) {
                        filename = filenames->data;
                                g_error_free(error);
                                error = NULL;
                        }
 -                      
 +
                        g_free(filename);
                        filenames = g_slist_next(filenames);
                }
        gtk_widget_destroy(dialog);
  }
  
 +/* return the path and the file component contained in the full path */
 +static char *path_and_file(char *pathin, char **fileout) {
 +      char *slash = pathin, *next;
 +      char *result;
 +      size_t len, n;
 +
 +      if (! pathin) {
 +              *fileout = strdup("");
 +              return strdup("");
 +      }
 +      while ((next = strpbrk(slash + 1, "\\/")))
 +              slash = next;
 +      if (pathin != slash)
 +              slash++;
 +      *fileout = strdup(slash);
 +
 +      /* strndup(pathin, slash - pathin) */
 +      n = slash - pathin;
 +      len = strlen(pathin);
 +      if (n < len)
 +              len = n;
 +
 +      result = (char *)malloc(len + 1);
 +      if (!result)
 +              return 0;
 +
 +      result[len] = '\0';
 +      return (char *)memcpy(result, pathin, len);
 +}
 +
  static void file_save_as(GtkWidget *w, gpointer data)
  {
        GtkWidget *dialog;
        char *filename = NULL;
 +      char *current_file;
 +      char *current_dir;
 +
        dialog = gtk_file_chooser_dialog_new("Save File As",
                GTK_WINDOW(main_window),
                GTK_FILE_CHOOSER_ACTION_SAVE,
                NULL);
        gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
  
 -      gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), existing_filename);
 +      current_dir = path_and_file(existing_filename, &current_file);
 +      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), current_dir);
 +      gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), current_file);
 +
 +      free(current_dir);
 +      free(current_file);
 +
        if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
                filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
        }
@@@ -262,7 -223,7 +262,7 @@@ static gboolean ask_save_changes(
                label = gtk_label_new (
                        "You have unsaved changes\nWould you like to save those before exiting the program?");
        } else {
 -              char *label_text = (char*) malloc(sizeof(char) * (92 + strlen(existing_filename)));
 +              char *label_text = (char*) malloc(sizeof(char) * (93 + strlen(existing_filename)));
                sprintf(label_text,
                        "You have unsaved changes to file: %s \nWould you like to save those before exiting the program?",
                        existing_filename);
@@@ -428,7 -389,6 +428,7 @@@ OPTIONCALLBACK(temperature_toggle, visi
  OPTIONCALLBACK(totalweight_toggle, visible_cols.totalweight)
  OPTIONCALLBACK(suit_toggle, visible_cols.suit)
  OPTIONCALLBACK(cylinder_toggle, visible_cols.cylinder)
 +OPTIONCALLBACK(autogroup_toggle, autogroup)
  
  static void event_toggle(GtkWidget *w, gpointer _data)
  {
@@@ -524,22 -484,8 +524,22 @@@ static void preferences_dialog(GtkWidge
        gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
        g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(suit_toggle), NULL);
  
 +      frame = gtk_frame_new("Divelist Font");
 +      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
 +
        font = gtk_font_button_new_with_font(divelist_font);
 -      gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
 +      gtk_container_add(GTK_CONTAINER(frame),font);
 +
 +      frame = gtk_frame_new("Misc. Options");
 +      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
 +
 +      box = gtk_hbox_new(FALSE, 6);
 +      gtk_container_add(GTK_CONTAINER(frame), box);
 +
 +      button = gtk_check_button_new_with_label("Automatically group dives in trips");
 +      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), autogroup);
 +      gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
 +      g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(autogroup_toggle), NULL);
  
        gtk_widget_show_all(dialog);
        result = gtk_dialog_run(GTK_DIALOG(dialog));
                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_set_conf("autogroup", PREF_BOOL, BOOL_TO_PTR(autogroup));
  
                /* Flush the changes out to the system */
                subsurface_flush_conf();
@@@ -729,6 -674,13 +729,13 @@@ static void view_three(GtkWidget *w, gp
        gtk_paned_set_position(GTK_PANED(vpane), requisition.height + 6);
  }
  
+ static void toggle_zoom(GtkWidget *w, gpointer data)
+ {
+       zoomed_plot = (zoomed_plot)?0 : 1;
+       /*Update dive*/
+       repaint_dive();
+ }
  static GtkActionEntry menu_items[] = {
        { "FileMenuAction", NULL, "File", NULL, NULL, NULL},
        { "LogMenuAction",  NULL, "Log", NULL, NULL, NULL},
        { "ViewList",       NULL, "List",  CTRLCHAR "1", NULL, G_CALLBACK(view_list) },
        { "ViewProfile",    NULL, "Profile", CTRLCHAR "2", NULL, G_CALLBACK(view_profile) },
        { "ViewInfo",       NULL, "Info", CTRLCHAR "3", NULL, G_CALLBACK(view_info) },
-       { "ViewThree",       NULL, "Three", CTRLCHAR "4", NULL, G_CALLBACK(view_three) },
+       { "ViewThree",      NULL, "Three", CTRLCHAR "4", NULL, G_CALLBACK(view_three) },
+       { "ToggleZoom",     NULL, "Toggle Zoom", CTRLCHAR "0", NULL, G_CALLBACK(toggle_zoom) },
  };
  static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
  
@@@ -771,6 -724,7 +779,7 @@@ static const gchar* ui_string = " 
                                <menuitem name=\"Add Dive\" action=\"AddDive\" /> \
                                <separator name=\"Separator\"/> \
                                <menuitem name=\"Renumber\" action=\"Renumber\" /> \
+                               <menuitem name=\"Toggle Zoom\" action=\"ToggleZoom\" /> \
                                <menu name=\"View\" action=\"ViewMenuAction\"> \
                                        <menuitem name=\"List\" action=\"ViewList\" /> \
                                        <menuitem name=\"Profile\" action=\"ViewProfile\" /> \
@@@ -849,8 -803,6 +858,8 @@@ void init_ui(int *argcp, char ***argvp
  
        divelist_font = subsurface_get_conf("divelist_font", PREF_STRING);
  
 +      autogroup = PTR_TO_BOOL(subsurface_get_conf("autogroup", PREF_BOOL));
 +
        default_dive_computer_vendor = subsurface_get_conf("dive_computer_vendor", PREF_STRING);
        default_dive_computer_product = subsurface_get_conf("dive_computer_product", PREF_STRING);
        default_dive_computer_device = subsurface_get_conf("dive_computer_device", PREF_STRING);
diff --combined profile.c
index 6a159cca85681fcc8436f159e6d0da9deb56e7c4,3ad11c0d0e97e4273f150ec5190a6ec42753105b..d4e88c02c21c498293d87a87ebf0f7a853a13ea0
+++ b/profile.c
@@@ -1,5 -1,5 +1,5 @@@
  /* profile.c */
 -/* creates all the necessary data for drawing the dive profile 
 +/* creates all the necessary data for drawing the dive profile
   * uses cairo to draw it
   */
  #include <stdio.h>
@@@ -14,6 -14,7 +14,7 @@@
  #include "color.h"
  
  int selected_dive = 0;
+ char zoomed_plot = 0;
  
  typedef enum { STABLE, SLOW, MODERATE, FAST, CRAZY } velocity_t;
  
@@@ -180,22 -181,40 +181,40 @@@ static void dump_pi (struct plot_info *
   * When showing dive profiles, we scale things to the
   * current dive. However, we don't scale past less than
   * 30 minutes or 90 ft, just so that small dives show
-  * up as such.
-  * we also need to add 180 seconds at the end so the min/max
+  * up as such unless zoom is enabled.
+  * We also need to add 180 seconds at the end so the min/max
   * plots correctly
   */
  static int get_maxtime(struct plot_info *pi)
  {
        int seconds = pi->maxtime;
-       /* min 30 minutes, rounded up to 5 minutes, with at least 2.5 minutes to spare */
-       return MAX(30*60, ROUND_UP(seconds+150, 60*5));
+       if (zoomed_plot) {
+               /* Rounded up to one minute, with at least 2.5 minutes to
+                * spare.
+                * For dive times shorter than 10 minutes, we use seconds/4 to
+                * calculate the space dynamically.
+                * This is seamless since 600/4 = 150.
+                */
+               if ( seconds < 600 )
+                       return ROUND_UP(seconds+seconds/4, 60);
+               else
+                       return ROUND_UP(seconds+150, 60);
+       } else {
+               /* min 30 minutes, rounded up to 5 minutes, with at least 2.5 minutes to spare */
+               return MAX(30*60, ROUND_UP(seconds+150, 60*5));
+       }
  }
  
  static int get_maxdepth(struct plot_info *pi)
  {
        unsigned mm = pi->maxdepth;
-       /* Minimum 30m, rounded up to 10m, with at least 3m to spare */
-       return MAX(30000, ROUND_UP(mm+3000, 10000));
+       if (zoomed_plot) {
+               /* Rounded up to 10m, with at least 3m to spare */
+               return ROUND_UP(mm+3000, 10000);
+       } else {
+               /* Minimum 30m, rounded up to 10m, with at least 3m to spare */
+               return MAX(30000, ROUND_UP(mm+3000, 10000));
+       }
  }
  
  typedef struct {
@@@ -443,20 -462,21 +462,21 @@@ static void plot_depth_profile(struct g
        int sec, depth;
        struct plot_data *entry;
        int maxtime, maxdepth, marker;
-       int increments[4] = { 5*60, 10*60, 15*60, 30*60 };
+       int increments[8] = { 10, 20, 30, 60, 5*60, 10*60, 15*60, 30*60 };
  
        /* Get plot scaling limits */
        maxtime = get_maxtime(pi);
        maxdepth = get_maxdepth(pi);
  
-       /* Time markers: at most every 5 min, but no more than 12 markers
-        * and for convenience we do 5, 10, 15 or 30 min intervals.
+       /* Time markers: at most every 10 seconds, but no more than 12 markers.
+        * We start out with 10 seconds and increment up to 30 minutes,
+        * depending on the dive time.
         * This allows for 6h dives - enough (I hope) for even the craziest
         * divers - but just in case, for those 8h depth-record-breaking dives,
         * we double the interval if this still doesn't get us to 12 or fewer
         * time markers */
        i = 0;
-       while (maxtime / increments[i] > 12 && i < 4)
+       while (maxtime / increments[i] > 12 && i < 8)
                i++;
        incr = increments[i];
        while (maxtime / incr > 12)
        }
        cairo_stroke(cr);
  
-       /* now the text on every second time marker */
+       /* now the text on the time markers */
        text_render_options_t tro = {10, TIME_TEXT, CENTER, TOP};
-       for (i = incr; i < maxtime; i += 2 * incr)
-               plot_text(gc, &tro, i, 1, "%d", i/60);
+       if (maxtime < 600) {
+               /* Be a bit more verbose with shorter dives */
+               for (i = incr; i < maxtime; i += incr)
+                       plot_text(gc, &tro, i, 1, "%02d:%02d", i/60, i%60);
+       } else {
+               /* Only render the time on every second marker for normal dives */
+               for (i = incr; i < maxtime; i += 2 * incr)
+                       plot_text(gc, &tro, i, 1, "%d", i/60);
+       }
        /* Depth markers: every 30 ft or 10 m*/
        gc->leftx = 0; gc->rightx = 1.0;
        gc->topy = 0; gc->bottomy = maxdepth;
@@@ -873,7 -899,7 +899,7 @@@ static velocity_t velocity(int speed
        else if (speed < -25) /* -5ft/min */
                v = SLOW;
        else if (speed < 25) /* very hard to find data, but it appears that the recommendations
 -                              for descent are usually about 2x ascent rate; still, we want 
 +                              for descent are usually about 2x ascent rate; still, we want
                                stable to mean stable */
                v = STABLE;
        else if (speed < 152) /* between 5 and 30ft/min is considered slow */
@@@ -929,7 -955,7 +955,7 @@@ static struct plot_info *analyze_plot_i
                                int past = -2;
                                while (i+past > 0 && entry[0].sec - entry[past].sec < 15)
                                        past--;
 -                              entry->velocity = velocity((entry[0].depth - entry[past].depth) / 
 +                              entry->velocity = velocity((entry[0].depth - entry[past].depth) /
                                                        (entry[0].sec - entry[past].sec));
                        }
                } else
                struct plot_data *entry = pi->entry +i;
                analyze_plot_info_minmax(entry, pi->entry, pi->entry+nr);
        }
 -      
 +
        return pi;
  }