diff options
-rw-r--r-- | dive.h | 2 | ||||
-rw-r--r-- | divelist.c | 444 | ||||
-rw-r--r-- | info.c | 62 |
3 files changed, 474 insertions, 34 deletions
@@ -241,6 +241,7 @@ extern const char *tripflag_names[NUM_TRIPFLAGS]; struct dive { int number; tripflag_t tripflag; + struct dive *divetrip; int selected; time_t when; char *location; @@ -433,6 +434,7 @@ extern void remember_event(const char *eventname); extern void evn_foreach(void (*callback)(const char *, int *, void *), void *data); extern int add_new_dive(struct dive *dive); +extern gboolean edit_trip(struct dive *trip); extern int edit_dive_info(struct dive *dive); extern int edit_multi_dive_info(struct dive *single_dive); extern void dive_list_update_dives(void); diff --git a/divelist.c b/divelist.c index 49166c8b5..4e0f940bb 100644 --- a/divelist.c +++ b/divelist.c @@ -903,6 +903,28 @@ void update_dive_list_col_visibility(void) return; } +static GList *find_matching_trip(time_t when) +{ + GList *trip = dive_trip_list; + if (!trip || DIVE_TRIP(trip)->when > when) + return NULL; + while (trip->next && DIVE_TRIP(trip->next)->when <= when) + trip = trip->next; + return trip; +} + +static struct dive *create_and_hookup_trip_from_dive(struct dive *dive) +{ + struct dive *dive_trip = alloc_dive(); + dive_trip->when = dive->when; + if (dive->location) + dive_trip->location = strdup(dive->location); + insert_trip(dive_trip); + dive->divetrip = dive_trip; + dive->tripflag = IN_TRIP; + return dive_trip; +} + static void fill_dive_list(void) { int i; @@ -945,35 +967,20 @@ static void fill_dive_list(void) if ( ! dive_trip || ! DIVE_FITS_TRIP(dive, dive_trip)) { /* allocate new trip - all fields default to 0 and get filled in further down */ - dive_trip = alloc_dive(); - insert_trip(dive_trip); + dive_trip = create_and_hookup_trip_from_dive(dive); trip = FIND_TRIP(dive_trip->when); } - } else { /* either the dive has a trip or we aren't creating trips */ - if (! (trip && DIVE_FITS_TRIP(dive, DIVE_TRIP(trip)))) { - GList *last_trip = trip; - trip = PREV_TRIP(trip); - if (! (trip && DIVE_FITS_TRIP(dive, DIVE_TRIP(trip)))) { - /* we could get here if there are no trips in the XML file - * and we aren't creating trips, either. - * Otherwise we need to create a new trip */ - if (autogroup) { - dive_trip = alloc_dive(); - insert_trip(dive_trip); - trip = FIND_TRIP(dive_trip->when); - } else { - /* let's go back to the last valid trip */ - trip = last_trip; - } - } else { - dive_trip = trip->data; - } - } + } else if (DIVE_IN_TRIP(dive)) { + trip = find_matching_trip(dive->when); + dive_trip = DIVE_TRIP(trip); } - /* update dive_trip time and (if necessary) location */ + /* update dive as part of dive_trip and + * (if necessary) update dive_trip time and location */ if (dive_trip) { dive->tripflag = IN_TRIP; - dive_trip->when = dive->when; + dive->divetrip = dive_trip; + if (dive_trip->when > dive->when) + dive_trip->when = dive->when; if (!dive_trip->location && dive->location) dive_trip->location = dive->location; if (dive_trip != last_trip) { @@ -1152,11 +1159,39 @@ void add_dive_cb(GtkWidget *menuitem, gpointer data) free(dive); } -void edit_dive_cb(GtkWidget *menuitem, gpointer data) +void edit_trip_cb(GtkWidget *menuitem, GtkTreePath *path) +{ + GtkTreeIter iter; + time_t when; + struct dive *dive_trip; + GList *trip; + + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + gtk_tree_model_get(TREEMODEL(dive_list), &iter, DIVE_DATE, &when, -1); + trip = FIND_TRIP(when); + dive_trip = DIVE_TRIP(trip); + if (edit_trip(dive_trip)) + gtk_tree_store_set(TREESTORE(dive_list), &iter, DIVE_LOCATION, dive_trip->location, -1); +} + +void edit_selected_dives_cb(GtkWidget *menuitem, gpointer data) { edit_multi_dive_info(NULL); } +void edit_dive_from_path_cb(GtkWidget *menuitem, GtkTreePath *path) +{ + GtkTreeIter iter; + int idx; + struct dive *dive; + + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + gtk_tree_model_get(TREEMODEL(dive_list), &iter, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + + edit_multi_dive_info(dive); +} + static void expand_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view) { gtk_tree_view_expand_all(tree_view); @@ -1167,10 +1202,309 @@ static void collapse_all_cb(GtkWidget *menuitem, GtkTreeView *tree_view) gtk_tree_view_collapse_all(tree_view); } -static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int button) +/* copy the node and return the index */ +static int copy_tree_node(GtkTreeIter *a, GtkTreeIter *b) +{ + struct dive store_dive; + int totalweight, idx; + char *cylinder_text; + + gtk_tree_model_get(TREEMODEL(dive_list), a, + DIVE_INDEX, &idx, + DIVE_NR, &store_dive.number, + DIVE_DATE, &store_dive.when, + DIVE_RATING, &store_dive.rating, + DIVE_DEPTH, &store_dive.maxdepth, + DIVE_DURATION, &store_dive.duration, + DIVE_TEMPERATURE, &store_dive.duration, + DIVE_TOTALWEIGHT, &totalweight, + DIVE_SUIT, &store_dive.suit, + DIVE_CYLINDER, &cylinder_text, + DIVE_SAC, &store_dive.sac, + DIVE_OTU, &store_dive.otu, + DIVE_LOCATION, &store_dive.location, + -1); + gtk_tree_store_set(TREESTORE(dive_list), b, + DIVE_INDEX, idx, + DIVE_NR, store_dive.number, + DIVE_DATE, store_dive.when, + DIVE_RATING, store_dive.rating, + DIVE_DEPTH, store_dive.maxdepth, + DIVE_DURATION, store_dive.duration, + DIVE_TEMPERATURE, store_dive.duration, + DIVE_TOTALWEIGHT, totalweight, + DIVE_SUIT, store_dive.suit, + DIVE_CYLINDER, cylinder_text, + DIVE_SAC, store_dive.sac, + DIVE_OTU, store_dive.otu, + DIVE_LOCATION, store_dive.location, + -1); + return idx; +} + +/* to avoid complicated special cases based on ordering or number of children, + we always take the first and last child and pick the smaller time_t (which + works regardless of ordering and also with just one child) */ +static void update_trip_timestamp(GtkTreeIter *parent, struct dive *divetrip) +{ + GtkTreeIter first_child, last_child; + int nr; + time_t t1, t2, tnew; + + if (gtk_tree_store_iter_depth(TREESTORE(dive_list), parent) != 0) + return; + nr = gtk_tree_model_iter_n_children(TREEMODEL(dive_list), parent); + gtk_tree_model_iter_nth_child(TREEMODEL(dive_list), &first_child, parent, 0); + gtk_tree_model_get(TREEMODEL(dive_list), &first_child, DIVE_DATE, &t1, -1); + gtk_tree_model_iter_nth_child(TREEMODEL(dive_list), &last_child, parent, nr - 1); + gtk_tree_model_get(TREEMODEL(dive_list), &last_child, DIVE_DATE, &t2, -1); + tnew = MIN(t1, t2); + gtk_tree_store_set(TREESTORE(dive_list), parent, DIVE_DATE, tnew, -1); + if (divetrip) + divetrip->when = tnew; +} + +/* move dive_iter, which is a child of old_trip (could be NULL) to new_trip (could be NULL); + * either of the trips being NULL means that this was (or will be) a dive without a trip; + * update the dive trips (especially the starting times) accordingly + * maintain the selected status of the dive + * IMPORTANT - the move needs to keep the tree consistant - so no out of order moving... */ +static GtkTreeIter *move_dive_between_trips(GtkTreeIter *dive_iter, GtkTreeIter *old_trip, GtkTreeIter *new_trip, + GtkTreeIter *sibling, gboolean before) +{ + int idx; + time_t old_when, new_when; + struct dive *dive, *old_divetrip, *new_divetrip; + GtkTreeIter *new_iter = malloc(sizeof(GtkTreeIter)); + + if (before) + gtk_tree_store_insert_before(GTK_TREE_STORE(TREEMODEL(dive_list)), new_iter, new_trip, sibling); + else + gtk_tree_store_insert_after(GTK_TREE_STORE(TREEMODEL(dive_list)), new_iter, new_trip, sibling); + idx = copy_tree_node(dive_iter, new_iter); + gtk_tree_model_get(TREEMODEL(dive_list), new_iter, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + gtk_tree_store_remove(GTK_TREE_STORE(TREEMODEL(dive_list)), dive_iter); + if (old_trip) { + gtk_tree_model_get(TREEMODEL(dive_list), old_trip, DIVE_DATE, &old_when, -1); + old_divetrip = DIVE_TRIP(find_matching_trip(old_when)); + update_trip_timestamp(old_trip, old_divetrip); + } + if (new_trip) { + gtk_tree_model_get(TREEMODEL(dive_list), new_trip, DIVE_DATE, &new_when, -1); + new_divetrip = dive->divetrip; + update_trip_timestamp(new_trip, new_divetrip); + } + if (dive->selected) { + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view)); + gtk_tree_selection_select_iter(selection, new_iter); + } + return new_iter; +} + +static void turn_dive_into_trip(GtkTreePath *path) +{ + GtkTreeIter iter, *newiter, newparent; + GtkTreePath *treepath; + time_t when; + char *location; + int idx; + struct dive *dive; + + /* this is a dive on the top level, insert trip AFTER it, populate its date / location, and + * then move the dive below that trip */ + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + gtk_tree_store_insert_after(TREESTORE(dive_list), &newparent, NULL, &iter); + gtk_tree_model_get(TREEMODEL(dive_list), &iter, + DIVE_INDEX, &idx, DIVE_DATE, &when, DIVE_LOCATION, &location, -1); + gtk_tree_store_set(TREESTORE(dive_list), &newparent, + DIVE_INDEX, -1, DIVE_DATE, when, DIVE_LOCATION, location, -1); + free(location); + newiter = move_dive_between_trips(&iter, NULL, &newparent, NULL, FALSE); + treepath = gtk_tree_model_get_path(TREEMODEL(dive_list), newiter); + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), treepath); + dive = get_dive(idx); + /* we don't need the return value - everything is hooked up in the function */ + (void)create_and_hookup_trip_from_dive(dive); +} + +/* we know that path is pointing at a dive in a trip and are asked to split this trip into two */ +static void insert_trip_before(GtkTreePath *path) +{ + GtkTreeIter iter, prev_iter, parent, newparent, nextsibling; + GtkTreePath *treepath, *prev_path; + struct dive *dive, *prev_dive, *new_divetrip; + int idx, nr, i; + + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + prev_path = gtk_tree_path_copy(path); + if (!gtk_tree_path_prev(prev_path) || + !gtk_tree_model_iter_parent(TREEMODEL(dive_list), &parent, &iter)) + return; + gtk_tree_model_get_iter(TREEMODEL(dive_list), &prev_iter, prev_path); + gtk_tree_model_get(TREEMODEL(dive_list), &prev_iter, DIVE_INDEX, &idx, -1); + prev_dive = get_dive(idx); + gtk_tree_store_insert_after(TREESTORE(dive_list), &newparent, NULL, &parent); + copy_tree_node(&parent, &newparent); + gtk_tree_model_get(TREEMODEL(dive_list), &iter, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + /* make sure that the time_t of the previous divetrip is correct before + * inserting a new one */ + if (dive->when < prev_dive->when) + if (prev_dive->divetrip && prev_dive->divetrip->when < prev_dive->when) + prev_dive->divetrip->when = prev_dive->when; + new_divetrip = create_and_hookup_trip_from_dive(dive); + + /* in order for the data structures to stay consistent we need to walk from + * the last child backwards to this one. The easiest way seems to be to do + * this with the nth iterator API */ + nr = gtk_tree_model_iter_n_children(TREEMODEL(dive_list), &parent); + for (i = nr - 1; i >= 0; i--) { + gtk_tree_model_iter_nth_child(TREEMODEL(dive_list), &nextsibling, &parent, i); + treepath = gtk_tree_model_get_path(TREEMODEL(dive_list), &nextsibling); + gtk_tree_model_get(TREEMODEL(dive_list), &nextsibling, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + dive->divetrip = new_divetrip; + if (dive->when < dive->divetrip->when) + dive->divetrip->when = dive->when; + (void) move_dive_between_trips(&nextsibling, &parent, &newparent, NULL, FALSE); + if (gtk_tree_path_compare(path, treepath) == 0) + /* we copied the dive we were called with; we are done */ + break; + } + treepath = gtk_tree_model_get_path(TREEMODEL(dive_list), &newparent); + gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), treepath); +#ifdef DEBUG_TRIP + dump_trip_list(); +#endif +} + +static void insert_trip_before_cb(GtkWidget *menuitem, GtkTreePath *path) +{ + /* is this splitting a trip or turning a dive into a trip? */ + if (gtk_tree_path_get_depth(path) == 2) + insert_trip_before(path); + else + turn_dive_into_trip(path); +} + +static void remove_from_trip_cb(GtkWidget *menuitem, GtkTreePath *path) +{ + GtkTreeIter iter, newiter, parent; + GtkTreePath *nextpath; + struct dive *dive; + int idx; + + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + if (!gtk_tree_model_iter_parent(TREEMODEL(dive_list), &parent, &iter)) + return; + + /* if this isn't the last dive in a trip we simply split the trip + in two right after this dive */ + nextpath = gtk_tree_path_copy(path); + gtk_tree_path_next(nextpath); + if (gtk_tree_model_get_iter(TREEMODEL(dive_list), &newiter, nextpath)) + insert_trip_before(nextpath); + /* now create a new node as sibling right after the current parent */ + gtk_tree_store_insert_after(TREESTORE(dive_list), &newiter, NULL, &parent); + copy_tree_node(&iter, &newiter); + + gtk_tree_model_get(TREEMODEL(dive_list), &iter, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + if (dive->selected) { + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view)); + gtk_tree_selection_select_iter(selection, &newiter); + } + gtk_tree_store_remove(TREESTORE(dive_list), &iter); + /* if this was the last dive on the trip, remove the trip */ + if (! gtk_tree_model_iter_has_child(TREEMODEL(dive_list), &parent)) { + gtk_tree_store_remove(TREESTORE(dive_list), &parent); + delete_trip(FIND_TRIP(dive->divetrip->when)); + } + dive->tripflag = NO_TRIP; + dive->divetrip = NULL; +} + +void remove_trip_cb(GtkWidget *menuitem, GtkTreePath *trippath) +{ + GtkTreeIter newiter, parent, child, *lastiter = &parent; + struct dive *dive, *dive_trip = NULL; + int idx; + GtkTreePath *childpath; + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view)); + + /* what a pain - we can't just move the nodes, we have to + * create new ones and delete the existing ones instead */ + gtk_tree_model_get_iter(TREEMODEL(dive_list), &parent, trippath); + childpath = gtk_tree_path_copy(trippath); + gtk_tree_path_down(childpath); + for (;;) { + if( ! gtk_tree_model_get_iter(TREEMODEL(dive_list), &child, childpath)) + break; + gtk_tree_store_insert_after(TREESTORE(dive_list), &newiter, NULL, lastiter); + copy_tree_node(&child, &newiter); + /* we need to track what was selected */ + gtk_tree_model_get(TREEMODEL(dive_list), &child, DIVE_INDEX, &idx, -1); + dive = get_dive(idx); + if (dive->selected) + gtk_tree_selection_select_iter(selection, &newiter); + dive->tripflag = NO_TRIP; + if (!dive_trip) + dive_trip = dive->divetrip; + dive->divetrip = NULL; + /* this removes the child - now childpath points to the next child */ + gtk_tree_store_remove(TREESTORE(dive_list), &child); + lastiter = &newiter; + } + /* finally, remove the trip */ + gtk_tree_store_remove(TREESTORE(dive_list), &parent); + delete_trip(FIND_TRIP(dive_trip->when)); + free(dive_trip); +} + +void merge_trips_cb(GtkWidget *menuitem, GtkTreePath *trippath) +{ + GtkTreePath *prevpath; + GtkTreeIter thistripiter, prevtripiter, newiter, iter; + GtkTreeModel *tm = TREEMODEL(dive_list); + GList *trip, *prevtrip; + time_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); + trip = 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); + while (gtk_tree_model_iter_children(tm, &iter, &thistripiter)) { + int idx; + gtk_tree_store_insert_before(TREESTORE(dive_list), &newiter, &prevtripiter, NULL); + idx = copy_tree_node(&iter, &newiter); + gtk_tree_store_remove(TREESTORE(dive_list), &iter); + get_dive(idx)->divetrip = DIVE_TRIP(prevtrip); + } + update_trip_timestamp(&prevtripiter, DIVE_TRIP(prevtrip)); + free(DIVE_TRIP(trip)); + delete_trip(trip); + gtk_tree_store_remove(TREESTORE(dive_list), &thistripiter); +} + +static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int button, GdkEventButton *event) { GtkWidget *menu, *menuitem, *image; char editlabel[] = "Edit dives"; + GtkTreePath *path, *prevpath; + GtkTreeIter iter, previter; + int idx, previdx; + struct dive *dive; + + if (!gtk_tree_view_get_path_at_pos(tree_view, event->x, event->y, &path, NULL, NULL, NULL)) + return; + gtk_tree_model_get_iter(TREEMODEL(dive_list), &iter, path); + gtk_tree_model_get(TREEMODEL(dive_list), &iter, DIVE_INDEX, &idx, -1); menu = gtk_menu_new(); menuitem = gtk_image_menu_item_new_with_label("Add dive"); @@ -1178,12 +1512,56 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int 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 (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); + + 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(TREEMODEL(dive_list), &previter, prevpath)) { + gtk_tree_model_get(TREEMODEL(dive_list), &previter, DIVE_INDEX, &previdx, -1); + if (previdx < 0) { + menuitem = gtk_menu_item_new_with_label("Merge trip with previous"); + g_signal_connect(menuitem, "activate", G_CALLBACK(merge_trips_cb), path); + 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 those */ + if (dive->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_selected_dives_cb), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } else { + editlabel[strlen(editlabel) - 1] = '\0'; + 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 trip editing options when we are displaying the tree model */ + if (dive_list.model == dive_list.treemodel) { + int depth; + int *indices = gtk_tree_path_get_indices_with_depth(path, &depth); + + if (depth == 1 || indices[1] > 0) { + menuitem = gtk_menu_item_new_with_label("Add new trip above"); + g_signal_connect(menuitem, "activate", G_CALLBACK(insert_trip_before_cb), path); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } + if (DIVE_IN_TRIP(dive)) { + menuitem = gtk_menu_item_new_with_label("Remove 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); @@ -1199,14 +1577,14 @@ static void popup_divelist_menu(GtkTreeView *tree_view, GtkTreeModel *model, int static void popup_menu_cb(GtkTreeView *tree_view, gpointer userdata) { - popup_divelist_menu(tree_view, GTK_TREE_MODEL(dive_list.model), 0); + popup_divelist_menu(tree_view, GTK_TREE_MODEL(dive_list.model), 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), GTK_TREE_MODEL(dive_list.model), 3); + popup_divelist_menu(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(dive_list.model), 3, event); return TRUE; } return FALSE; @@ -415,6 +415,24 @@ static void save_dive_info_changes(struct dive *dive, struct dive *master, struc } } +static void dive_trip_widget(GtkWidget *box, struct dive *trip, struct dive_info *info) +{ + GtkWidget *hbox, *label; + char buffer[80] = "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); +} + static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info *info, gboolean multi) { GtkWidget *hbox, *label, *frame, *equipment; @@ -489,7 +507,49 @@ void update_equipment_data(struct dive *dive, struct dive *master) memcpy(dive->weightsystem, master->weightsystem, WS_BYTES); } -/* A negative index means "all selected" */ +gboolean edit_trip(struct dive *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); + 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 = 1; + } + if (info.notes) { + old_text = trip->notes; + trip->notes = get_text(info.notes); + if (text_changed(old_text, trip->notes)) + changed = 1; + if (old_text) + g_free(old_text); + } + if (changed) { + mark_divelist_changed(TRUE); + flush_divelist(trip); + } + } + gtk_widget_destroy(dialog); + return changed; +} + int edit_multi_dive_info(struct dive *single_dive) { int success; |