Merge branch 'tree2' of git://git.hohndel.org/subsurface

Pull dive-trip grouping from Dirk Hohndel:
 "This turned into an updated pull request for the tree2 branch where I
  implemented the date based grouping - but is actually a very different
  topic: this adds the ability to edit multiple dives (and fixes some
  issues with the dive editing overall).  The reason for that is that it
  reuses some of the infrastructure that I implemented in the tree2
  branch for tracking the selected dives.  More details in the commit
  messages."

* 'tree2' of git://git.hohndel.org/subsurface:
  Switch from date based to dive trip based grouping
  Redo dive editing
  Fix selecting and unselecting summary items
  Apply sort functions to the correct model, don't select summary entries
  Maintain selected rows when switching between list model and tree model
  Create duplicate list model so sorting by columns works again
  Improve tree model implementation
  Allow date based grouping
This commit is contained in:
Linus Torvalds 2012-08-16 10:46:30 -07:00
commit 9b72217f79
8 changed files with 670 additions and 216 deletions

View 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 {
@ -521,11 +522,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);
}
@ -1063,11 +1064,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;
@ -1085,11 +1087,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;
@ -1102,15 +1105,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;
@ -1127,27 +1131,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;
@ -1165,11 +1170,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;
@ -1182,15 +1188,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;
@ -1207,20 +1214,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)
@ -1340,33 +1347,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,
@ -1382,9 +1389,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;
@ -1394,7 +1401,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,
@ -1407,7 +1414,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;
@ -1420,11 +1427,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;
@ -1432,11 +1439,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;
@ -1444,14 +1451,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);
@ -1477,19 +1487,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);
@ -1512,13 +1524,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;
}