]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Redo dive editing
authorDirk Hohndel <dirk@hohndel.org>
Wed, 15 Aug 2012 22:21:34 +0000 (15:21 -0700)
committerDirk Hohndel <dirk@hohndel.org>
Wed, 15 Aug 2012 22:32:36 +0000 (15:32 -0700)
This commit addresses two issues:

We now can add / edit / delete equipment from the edit dive dialog

We now can edit multiple dives at once

The latter feature has some interesting design constraints:
It picks the 'selected_dive' as the one to start the edit from - so if
this dive already has some information filled in, that information needs
to be overwritten before it is stored in all of the dives. Similarly, only
changes to the cylinders or weightsystems are recorded. Also, the notes
field is not editable in the multi dive edit mode (as that didn't seem
useful).

The workflow seems to work best if using the multi-edit right after
importing new dives from a dive computer. The user then can select all the
new dives and only needs to edit things like location, divemaster, buddy,
weights, etc. once.

This commit will create some obvious conflicts with the commit that adds
exposure protection tracking. It was implemented on top of the tree_view
changes as it reuses some of the infrastructure for tracking the selected
dives.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
display-gtk.h
dive.h
divelist.c
equipment.c
gtk-gui.c
info.c
main.c

index 3043c873b4ddacc95bdd78e5ce1212cc0a1622f7..1cf150bb622d18c5e649f30d20d28f3eab3290cb 100644 (file)
@@ -63,10 +63,11 @@ extern void update_progressbar_text(progressbar_t *progress, const char *text);
 extern GtkWidget *dive_profile_widget(void);
 extern GtkWidget *dive_info_frame(void);
 extern GtkWidget *extended_dive_info_widget(void);
-extern GtkWidget *equipment_widget(void);
+extern GtkWidget *equipment_widget(int w_idx);
 extern GtkWidget *single_stats_widget(void);
 extern GtkWidget *total_stats_widget(void);
-extern GtkWidget *cylinder_list_widget(void);
+extern GtkWidget *cylinder_list_widget(int w_idx);
+extern GtkWidget *weightsystem_list_widget(int w_idx);
 
 extern GtkWidget *dive_list_create(void);
 
diff --git a/dive.h b/dive.h
index a25fafb39e95cc4b0eee571f94b195165b2200f4..de95d5e6614c0d0b05ef77700454b6474de29dce 100644 (file)
--- a/dive.h
+++ b/dive.h
@@ -227,6 +227,8 @@ struct event {
 
 #define MAX_CYLINDERS (8)
 #define MAX_WEIGHTSYSTEMS (4)
+#define W_IDX_PRIMARY 0
+#define W_IDX_SECONDARY 1
 
 struct dive {
        int number;
@@ -282,7 +284,7 @@ extern int selected_dive;
 
 static inline struct dive *get_dive(unsigned int nr)
 {
-       if (nr >= dive_table.nr)
+       if (nr >= dive_table.nr || nr < 0)
                return NULL;
        return dive_table.dives[nr];
 }
@@ -299,7 +301,7 @@ extern xmlDoc *test_xslt_transforms(xmlDoc *doc);
 
 extern void show_dive_info(struct dive *);
 
-extern void show_dive_equipment(struct dive *);
+extern void show_dive_equipment(struct dive *, int w_idx);
 
 extern void show_dive_stats(struct dive *);
 
@@ -345,6 +347,7 @@ extern void evn_foreach(void (*callback)(const char *, int *, void *), void *dat
 
 extern int add_new_dive(struct dive *dive);
 extern int edit_dive_info(struct dive *dive);
+extern int edit_multi_dive_info(int nr, int *indices);
 extern void dive_list_update_dives(void);
 extern void flush_divelist(struct dive *dive);
 
index 112307a1c28fbc89d7d96f8899b99f0767d7fdfc..a4221f7b95b6dd5b410fa42c46eeb62aab4b57d0 100644 (file)
@@ -938,14 +938,27 @@ void add_dive_cb(GtkWidget *menuitem, gpointer data)
        free(dive);
 }
 
+void edit_dive_cb(GtkWidget *menuitem, gpointer data)
+{
+       edit_multi_dive_info(amount_selected, selectiontracker);
+}
+
 static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int button)
 {
        GtkWidget *menu, *menuitem;
+       char editlabel[] = "Edit dives";
 
        menu = gtk_menu_new();
        menuitem = gtk_menu_item_new_with_label("Add dive");
        g_signal_connect(menuitem, "activate", G_CALLBACK(add_dive_cb), NULL);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+       if (amount_selected) {
+               if (amount_selected == 1)
+                       editlabel[strlen(editlabel) - 1] = '\0';
+               menuitem = gtk_menu_item_new_with_label(editlabel);
+               g_signal_connect(menuitem, "activate", G_CALLBACK(edit_dive_cb), model);
+               gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+       }
        gtk_widget_show_all(menu);
 
        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
index b74d85b7b6509ab910620c3c2ffe9d8b2e91f099..ccfeb1270c7bb42883acca8e13558ea3f65024c4 100644 (file)
@@ -2,10 +2,10 @@
 /* creates the UI for the equipment page -
  * controlled through the following interfaces:
  *
- * void show_dive_equipment(struct dive *dive)
+ * void show_dive_equipment(struct dive *dive, int w_idx)
  *
  * called from gtk-ui:
- * GtkWidget *equipment_widget(void)
+ * GtkWidget *equipment_widget(int w_idx)
  */
 #include <stdio.h>
 #include <string.h>
@@ -40,10 +40,11 @@ enum {
 struct equipment_list {
        int max_index;
        GtkListStore *model;
+       GtkTreeView *tree_view;
        GtkWidget *edit, *add, *del;
 };
 
-static struct equipment_list cylinder_list, weightsystem_list;
+static struct equipment_list cylinder_list[2], weightsystem_list[2];
 
 
 struct cylinder_widget {
@@ -519,11 +520,11 @@ static void show_equipment(struct dive *dive, int max,
        }
 }
 
-void show_dive_equipment(struct dive *dive)
+void show_dive_equipment(struct dive *dive, int w_idx)
 {
-       show_equipment(dive, MAX_CYLINDERS, &cylinder_list,
+       show_equipment(dive, MAX_CYLINDERS, &cylinder_list[w_idx],
                &cyl_ptr, &cylinder_none, &set_one_cylinder);
-       show_equipment(dive, MAX_WEIGHTSYSTEMS, &weightsystem_list,
+       show_equipment(dive, MAX_WEIGHTSYSTEMS, &weightsystem_list[w_idx],
                &ws_ptr, &weightsystem_none, &set_one_weightsystem);
 }
 
@@ -1061,11 +1062,12 @@ static int get_model_index(GtkListStore *model, GtkTreeIter *iter)
        return index;
 }
 
-static void edit_cb(GtkButton *button, GtkTreeView *tree_view)
+static void edit_cb(GtkButton *button, int w_idx)
 {
        int index;
        GtkTreeIter iter;
-       GtkListStore *model = cylinder_list.model;
+       GtkListStore *model = cylinder_list[w_idx].model;
+       GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        cylinder_t cyl;
 
@@ -1083,11 +1085,12 @@ static void edit_cb(GtkButton *button, GtkTreeView *tree_view)
        repaint_dive();
 }
 
-static void add_cb(GtkButton *button, GtkTreeView *tree_view)
+static void add_cb(GtkButton *button, int w_idx)
 {
-       int index = cylinder_list.max_index;
+       int index = cylinder_list[w_idx].max_index;
        GtkTreeIter iter;
-       GtkListStore *model = cylinder_list.model;
+       GtkListStore *model = cylinder_list[w_idx].model;
+       GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        cylinder_t cyl;
 
@@ -1100,15 +1103,16 @@ static void add_cb(GtkButton *button, GtkTreeView *tree_view)
        selection = gtk_tree_view_get_selection(tree_view);
        gtk_tree_selection_select_iter(selection, &iter);
 
-       cylinder_list.max_index++;
-       gtk_widget_set_sensitive(cylinder_list.add, cylinder_list.max_index < MAX_CYLINDERS);
+       cylinder_list[w_idx].max_index++;
+       gtk_widget_set_sensitive(cylinder_list[w_idx].add, cylinder_list[w_idx].max_index < MAX_CYLINDERS);
 }
 
-static void del_cb(GtkButton *button, GtkTreeView *tree_view)
+static void del_cb(GtkButton *button, int w_idx)
 {
        int index, nr;
        GtkTreeIter iter;
-       GtkListStore *model = cylinder_list.model;
+       GtkListStore *model = cylinder_list[w_idx].model;
+       GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        struct dive *dive;
        cylinder_t *cyl;
@@ -1125,27 +1129,28 @@ static void del_cb(GtkButton *button, GtkTreeView *tree_view)
        if (!dive)
                return;
        cyl = dive->cylinder + index;
-       nr = cylinder_list.max_index - index - 1;
+       nr = cylinder_list[w_idx].max_index - index - 1;
 
        gtk_list_store_remove(model, &iter);
 
-       cylinder_list.max_index--;
+       cylinder_list[w_idx].max_index--;
        memmove(cyl, cyl+1, nr*sizeof(*cyl));
        memset(cyl+nr, 0, sizeof(*cyl));
 
        mark_divelist_changed(TRUE);
        flush_divelist(dive);
 
-       gtk_widget_set_sensitive(cylinder_list.edit, 0);
-       gtk_widget_set_sensitive(cylinder_list.del, 0);
-       gtk_widget_set_sensitive(cylinder_list.add, 1);
+       gtk_widget_set_sensitive(cylinder_list[w_idx].edit, 0);
+       gtk_widget_set_sensitive(cylinder_list[w_idx].del, 0);
+       gtk_widget_set_sensitive(cylinder_list[w_idx].add, 1);
 }
 
-static void ws_edit_cb(GtkButton *button, GtkTreeView *tree_view)
+static void ws_edit_cb(GtkButton *button, int w_idx)
 {
        int index;
        GtkTreeIter iter;
-       GtkListStore *model = weightsystem_list.model;
+       GtkListStore *model = weightsystem_list[w_idx].model;
+       GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        weightsystem_t ws;
 
@@ -1163,11 +1168,12 @@ static void ws_edit_cb(GtkButton *button, GtkTreeView *tree_view)
        repaint_dive();
 }
 
-static void ws_add_cb(GtkButton *button, GtkTreeView *tree_view)
+static void ws_add_cb(GtkButton *button, int w_idx)
 {
-       int index = weightsystem_list.max_index;
+       int index = weightsystem_list[w_idx].max_index;
        GtkTreeIter iter;
-       GtkListStore *model = weightsystem_list.model;
+       GtkListStore *model = weightsystem_list[w_idx].model;
+       GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        weightsystem_t ws;
 
@@ -1180,15 +1186,16 @@ static void ws_add_cb(GtkButton *button, GtkTreeView *tree_view)
        selection = gtk_tree_view_get_selection(tree_view);
        gtk_tree_selection_select_iter(selection, &iter);
 
-       weightsystem_list.max_index++;
-       gtk_widget_set_sensitive(weightsystem_list.add, weightsystem_list.max_index < MAX_WEIGHTSYSTEMS);
+       weightsystem_list[w_idx].max_index++;
+       gtk_widget_set_sensitive(weightsystem_list[w_idx].add, weightsystem_list[w_idx].max_index < MAX_WEIGHTSYSTEMS);
 }
 
-static void ws_del_cb(GtkButton *button, GtkTreeView *tree_view)
+static void ws_del_cb(GtkButton *button, int w_idx)
 {
        int index, nr;
        GtkTreeIter iter;
-       GtkListStore *model = weightsystem_list.model;
+       GtkListStore *model = weightsystem_list[w_idx].model;
+       GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
        GtkTreeSelection *selection;
        struct dive *dive;
        weightsystem_t *ws;
@@ -1205,20 +1212,20 @@ static void ws_del_cb(GtkButton *button, GtkTreeView *tree_view)
        if (!dive)
                return;
        ws = dive->weightsystem + index;
-       nr = weightsystem_list.max_index - index - 1;
+       nr = weightsystem_list[w_idx].max_index - index - 1;
 
        gtk_list_store_remove(model, &iter);
 
-       weightsystem_list.max_index--;
+       weightsystem_list[w_idx].max_index--;
        memmove(ws, ws+1, nr*sizeof(*ws));
        memset(ws+nr, 0, sizeof(*ws));
 
        mark_divelist_changed(TRUE);
        flush_divelist(dive);
 
-       gtk_widget_set_sensitive(weightsystem_list.edit, 0);
-       gtk_widget_set_sensitive(weightsystem_list.del, 0);
-       gtk_widget_set_sensitive(weightsystem_list.add, 1);
+       gtk_widget_set_sensitive(weightsystem_list[w_idx].edit, 0);
+       gtk_widget_set_sensitive(weightsystem_list[w_idx].del, 0);
+       gtk_widget_set_sensitive(weightsystem_list[w_idx].add, 1);
 }
 
 static GtkListStore *create_tank_size_model(void)
@@ -1338,33 +1345,33 @@ static void selection_cb(GtkTreeSelection *selection, struct equipment_list *lis
 static void row_activated_cb(GtkTreeView *tree_view,
                        GtkTreePath *path,
                        GtkTreeViewColumn *column,
-                       GtkTreeModel *model)
+                       int w_idx)
 {
-       edit_cb(NULL, tree_view);
+       edit_cb(NULL, w_idx);
 }
 
 static void ws_row_activated_cb(GtkTreeView *tree_view,
                        GtkTreePath *path,
                        GtkTreeViewColumn *column,
-                       GtkTreeModel *model)
+                       int w_idx)
 {
-       ws_edit_cb(NULL, tree_view);
+       ws_edit_cb(NULL, w_idx);
 }
 
-GtkWidget *cylinder_list_widget(void)
+GtkWidget *cylinder_list_widget(int w_idx)
 {
-       GtkListStore *model = cylinder_list.model;
+       GtkListStore *model = cylinder_list[w_idx].model;
        GtkWidget *tree_view;
        GtkTreeSelection *selection;
 
        tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
        gtk_widget_set_can_focus(tree_view, FALSE);
 
-       g_signal_connect(tree_view, "row-activated", G_CALLBACK(row_activated_cb), model);
+       g_signal_connect(tree_view, "row-activated", G_CALLBACK(row_activated_cb), GINT_TO_POINTER(w_idx));
 
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
        gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
-       g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &cylinder_list);
+       g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &cylinder_list[w_idx]);
 
        g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
                                          "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH,
@@ -1380,9 +1387,9 @@ GtkWidget *cylinder_list_widget(void)
        return tree_view;
 }
 
-GtkWidget *weightsystem_list_widget(void)
+GtkWidget *weightsystem_list_widget(int w_idx)
 {
-       GtkListStore *model = weightsystem_list.model;
+       GtkListStore *model = weightsystem_list[w_idx].model;
        GtkWidget *tree_view;
        GtkTreeSelection *selection;
 
@@ -1392,7 +1399,7 @@ GtkWidget *weightsystem_list_widget(void)
 
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
        gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
-       g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &weightsystem_list);
+       g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &weightsystem_list[w_idx]);
 
        g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
                                          "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH,
@@ -1405,7 +1412,7 @@ GtkWidget *weightsystem_list_widget(void)
        return tree_view;
 }
 
-static GtkWidget *cylinder_list_create(void)
+static GtkWidget *cylinder_list_create(int w_idx)
 {
        GtkListStore *model;
 
@@ -1418,11 +1425,11 @@ static GtkWidget *cylinder_list_create(void)
                G_TYPE_INT,             /* CYL_O2: permille */
                G_TYPE_INT              /* CYL_HE: permille */
                );
-       cylinder_list.model = model;
-       return cylinder_list_widget();
+       cylinder_list[w_idx].model = model;
+       return cylinder_list_widget(w_idx);
 }
 
-static GtkWidget *weightsystem_list_create(void)
+static GtkWidget *weightsystem_list_create(int w_idx)
 {
        GtkListStore *model;
 
@@ -1430,11 +1437,11 @@ static GtkWidget *weightsystem_list_create(void)
                G_TYPE_STRING,          /* WS_DESC: utf8 */
                G_TYPE_INT              /* WS_WEIGHT: grams */
                );
-       weightsystem_list.model = model;
-       return weightsystem_list_widget();
+       weightsystem_list[w_idx].model = model;
+       return weightsystem_list_widget(w_idx);
 }
 
-GtkWidget *equipment_widget(void)
+GtkWidget *equipment_widget(int w_idx)
 {
        GtkWidget *vbox, *hbox, *frame, *framebox, *tree_view;
        GtkWidget *add, *del, *edit;
@@ -1442,14 +1449,17 @@ GtkWidget *equipment_widget(void)
        vbox = gtk_vbox_new(FALSE, 3);
 
        /*
-        * We create the cylinder size model at startup, since
-        * we're going to share it across all cylinders and all
-        * dives. So if you add a new cylinder type in one dive,
-        * it will show up when you edit the cylinder types for
-        * another dive.
+        * We create the cylinder size (and weightsystem) models
+        * at startup for the primary cylinder / weightsystem widget,
+        * since we're going to share it across all cylinders and all
+        * dives. So if you add a new cylinder type or weightsystem in
+        * one dive, it will show up when you edit the cylinder types
+        * or weightsystems for another dive.
         */
-       cylinder_model = create_tank_size_model();
-       tree_view = cylinder_list_create();
+       if (w_idx == W_IDX_PRIMARY)
+               cylinder_model = create_tank_size_model();
+       tree_view = cylinder_list_create(w_idx);
+       cylinder_list[w_idx].tree_view = GTK_TREE_VIEW(tree_view);
 
        hbox = gtk_hbox_new(FALSE, 3);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
@@ -1475,19 +1485,21 @@ GtkWidget *equipment_widget(void)
        gtk_box_pack_start(GTK_BOX(hbox), add, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), del, FALSE, FALSE, 0);
 
-       cylinder_list.edit = edit;
-       cylinder_list.add = add;
-       cylinder_list.del = del;
+       cylinder_list[w_idx].edit = edit;
+       cylinder_list[w_idx].add = add;
+       cylinder_list[w_idx].del = del;
 
-       g_signal_connect(edit, "clicked", G_CALLBACK(edit_cb), tree_view);
-       g_signal_connect(add, "clicked", G_CALLBACK(add_cb), tree_view);
-       g_signal_connect(del, "clicked", G_CALLBACK(del_cb), tree_view);
+       g_signal_connect(edit, "clicked", G_CALLBACK(edit_cb), GINT_TO_POINTER(w_idx));
+       g_signal_connect(add, "clicked", G_CALLBACK(add_cb), GINT_TO_POINTER(w_idx));
+       g_signal_connect(del, "clicked", G_CALLBACK(del_cb), GINT_TO_POINTER(w_idx));
 
        hbox = gtk_hbox_new(FALSE, 3);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
 
-       weightsystem_model = create_weightsystem_model();
-       tree_view = weightsystem_list_create();
+       if (w_idx == W_IDX_PRIMARY)
+               weightsystem_model = create_weightsystem_model();
+       tree_view = weightsystem_list_create(w_idx);
+       weightsystem_list[w_idx].tree_view = GTK_TREE_VIEW(tree_view);
 
        frame = gtk_frame_new("Weight");
        gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, FALSE, 3);
@@ -1510,13 +1522,13 @@ GtkWidget *equipment_widget(void)
        gtk_box_pack_start(GTK_BOX(hbox), add, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), del, FALSE, FALSE, 0);
 
-       weightsystem_list.edit = edit;
-       weightsystem_list.add = add;
-       weightsystem_list.del = del;
+       weightsystem_list[w_idx].edit = edit;
+       weightsystem_list[w_idx].add = add;
+       weightsystem_list[w_idx].del = del;
 
-       g_signal_connect(edit, "clicked", G_CALLBACK(ws_edit_cb), tree_view);
-       g_signal_connect(add, "clicked", G_CALLBACK(ws_add_cb), tree_view);
-       g_signal_connect(del, "clicked", G_CALLBACK(ws_del_cb), tree_view);
+       g_signal_connect(edit, "clicked", G_CALLBACK(ws_edit_cb), GINT_TO_POINTER(w_idx));
+       g_signal_connect(add, "clicked", G_CALLBACK(ws_add_cb), GINT_TO_POINTER(w_idx));
+       g_signal_connect(del, "clicked", G_CALLBACK(ws_del_cb), GINT_TO_POINTER(w_idx));
 
        return vbox;
 }
index 45aa212638716e4550aa3c399436af1cfb7464dd..f7d3c500886ad69406efa336547af48daf9c4026 100644 (file)
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -794,7 +794,7 @@ void init_ui(int *argcp, char ***argvp)
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), nb_page, gtk_label_new("Dive Notes"));
 
        /* Frame for dive equipment */
-       nb_page = equipment_widget();
+       nb_page = equipment_widget(W_IDX_PRIMARY);
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), nb_page, gtk_label_new("Equipment"));
 
        /* Frame for single dive statistics */
diff --git a/info.c b/info.c
index 1847a49bf98ba8aef7e545d98e57ca58f2b6dfb8..842a150014505b1c31e00164efacac964908874f 100644 (file)
--- a/info.c
+++ b/info.c
@@ -344,25 +344,27 @@ static void save_dive_info_changes(struct dive *dive, struct dive_info *info)
                changed =1;
        }
 
-       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 (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 (changed) {
                mark_divelist_changed(TRUE);
                update_dive(dive);
        }
 }
 
-static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info *info)
+static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info *info, gboolean multi)
 {
-       GtkWidget *hbox, *label, *cylinder, *frame;
-       char buffer[80];
+       GtkWidget *hbox, *label, *frame, *equipment;
+       char buffer[80] = "Edit multiple dives";
 
-       divename(buffer, sizeof(buffer), dive);
+       if (!multi)
+               divename(buffer, sizeof(buffer), dive);
        label = gtk_label_new(buffer);
        gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);
 
@@ -379,28 +381,57 @@ static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info
 
        info->rating = text_entry(hbox, "Rating", star_list, star_strings[dive->rating]);
 
-       info->notes = text_view(box, "Notes", READ_WRITE);
-       if (dive->notes && *dive->notes)
-               gtk_text_buffer_set_text(gtk_text_view_get_buffer(info->notes), dive->notes, -1);
-
+       /* only show notes if editing a single dive */
+       if (multi) {
+               info->notes = NULL;
+       } else {
+               info->notes = text_view(box, "Notes", READ_WRITE);
+               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(box), hbox, FALSE, TRUE, 0);
 
-       frame = gtk_frame_new("Cylinder");
-       cylinder = cylinder_list_widget();
-       gtk_container_add(GTK_CONTAINER(frame), cylinder);
+       /* 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, FALSE, TRUE, 0);
 }
 
-int edit_dive_info(struct dive *dive)
+/* we use these to find out if we edited the cylinder or weightsystem entries */
+static cylinder_t remember_cyl[MAX_CYLINDERS];
+static weightsystem_t remember_ws[MAX_WEIGHTSYSTEMS];
+
+void save_equipment_data(struct dive *dive)
 {
-       int success;
+       if (dive) {
+               memcpy(remember_cyl, dive->cylinder, sizeof(cylinder_t) * MAX_CYLINDERS);
+               memcpy(remember_ws, dive->weightsystem, sizeof(weightsystem_t) * MAX_WEIGHTSYSTEMS);
+       }
+}
+
+void update_equipment_data(struct dive *dive, struct dive *master)
+{
+       if (dive == master)
+               return;
+       if (memcmp(remember_cyl, master->cylinder, sizeof(cylinder_t) * MAX_CYLINDERS)) {
+               memcpy(dive->cylinder, master->cylinder, sizeof(cylinder_t) * MAX_CYLINDERS);
+       }
+       if (memcmp(remember_ws, master->weightsystem, sizeof(weightsystem_t) * MAX_WEIGHTSYSTEMS)) {
+               memcpy(dive->weightsystem, master->weightsystem, sizeof(weightsystem_t) * MAX_WEIGHTSYSTEMS);
+       }
+}
+
+int edit_multi_dive_info(int nr, int *indices)
+{
+       int success, i;
        GtkWidget *dialog, *vbox;
        struct dive_info info;
+       struct dive *dive;
 
-       if (!dive)
+       if (!nr)
                return 0;
-
        dialog = gtk_dialog_new_with_buttons("Dive Info",
                GTK_WINDOW(main_window),
                GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -409,18 +440,44 @@ int edit_dive_info(struct dive *dive)
                NULL);
 
        vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-       dive_info_widget(vbox, dive, &info);
-
+       /* SCARY STUFF - IS THIS THE BEST WAY TO DO THIS???
+        *
+        * current_dive is one of our selected dives - and that is
+        * the one that is used to pre-fill the edit widget. Its
+        * data is used as the starting point for all selected dives
+        * I think it would be better to somehow collect and combine
+        * info from all the selected dives */
+       dive = current_dive;
+       dive_info_widget(vbox, dive, &info, (nr > 1));
+       show_dive_equipment(dive, W_IDX_SECONDARY);
+       save_equipment_data(dive);
        gtk_widget_show_all(dialog);
        success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
        if (success)
-               save_dive_info_changes(dive, &info);
-
+               for (i = 0; i < nr; i++) {
+                       /* copy all "info" fields */
+                       save_dive_info_changes(get_dive(indices[i]), &info);
+                       /* copy the cylinders / weightsystems */
+                       update_equipment_data(get_dive(indices[i]), dive);
+                       /* this is extremely inefficient... it loops through all
+                          dives to find the right one - but we KNOW the index already */
+                       flush_divelist(get_dive(indices[i]));
+               }
        gtk_widget_destroy(dialog);
 
        return success;
 }
 
+int edit_dive_info(struct dive *dive)
+{
+       int idx;
+
+       if (!dive)
+               return 0;
+       idx = dive->number;
+       return edit_multi_dive_info(1, &idx);
+}
+
 static GtkWidget *frame_box(GtkWidget *vbox, const char *fmt, ...)
 {
        va_list ap;
diff --git a/main.c b/main.c
index 60f2902e60f685d86b7c6d601f847b963b66a465..8e579f88c067b78891967684cc80b1469714ffb0 100644 (file)
--- a/main.c
+++ b/main.c
@@ -190,7 +190,7 @@ void update_dive(struct dive *new_dive)
        }
        if (new_dive) {
                show_dive_info(new_dive);
-               show_dive_equipment(new_dive);
+               show_dive_equipment(new_dive, W_IDX_PRIMARY);
                show_dive_stats(new_dive);
        }
        buffered_dive = new_dive;