X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=equipment.c;h=4f5a703c96b25b035ed9aad511801a5df110023b;hb=2d02ac402ac8086d946f8a815104b30142ec83e5;hp=ca8c99651efbfb8f62a9f1fe9cf00248c85b5ebf;hpb=9afcee3b17059fbe7947ec55fb9ed413848b0186;p=ext%2Fsubsurface.git diff --git a/equipment.c b/equipment.c index ca8c996..4f5a703 100644 --- a/equipment.c +++ b/equipment.c @@ -22,7 +22,6 @@ GtkListStore *cylinder_model; enum { - CYL_INDEX, CYL_DESC, CYL_SIZE, CYL_WORKP, @@ -34,6 +33,7 @@ enum { }; static struct { + int max_index; GtkListStore *model; GtkWidget *tree_view; GtkWidget *edit, *add, *del; @@ -45,12 +45,10 @@ struct cylinder_widget { const char *name; GtkWidget *hbox; GtkComboBox *description; - GtkSpinButton *size, *pressure; + GtkSpinButton *size, *pressure, *start, *end; GtkWidget *o2, *gasmix_button; }; -static struct cylinder_widget gtk_cylinder[MAX_CYLINDERS]; - static int convert_pressure(int mbar, double *p) { int decimals = 1; @@ -89,20 +87,25 @@ static int convert_volume_pressure(int ml, int mbar, double *v, double *p) return decimals; } -static void set_cylinder_spinbuttons(struct cylinder_widget *cylinder, int ml, int mbar) +static void set_cylinder_spinbuttons(struct cylinder_widget *cylinder, int ml, int mbar, int start, int end) { double volume, pressure; convert_volume_pressure(ml, mbar, &volume, &pressure); gtk_spin_button_set_value(cylinder->size, volume); gtk_spin_button_set_value(cylinder->pressure, pressure); + + convert_pressure(start, &pressure); + gtk_spin_button_set_value(cylinder->start, pressure); + convert_pressure(end, &pressure); + gtk_spin_button_set_value(cylinder->end, pressure); } static void cylinder_cb(GtkComboBox *combo_box, gpointer data) { GtkTreeIter iter; GtkTreeModel *model = gtk_combo_box_get_model(combo_box); - GValue value1 = {0, }, value2 = {0,}; + int ml, mbar, start, end; struct cylinder_widget *cylinder = data; cylinder_t *cyl = current_dive->cylinder + cylinder->index; @@ -128,10 +131,14 @@ static void cylinder_cb(GtkComboBox *combo_box, gpointer data) } cylinder->changed = 1; - gtk_tree_model_get_value(model, &iter, 1, &value1); - gtk_tree_model_get_value(model, &iter, 2, &value2); + gtk_tree_model_get(model, &iter, + CYL_SIZE, &ml, + CYL_WORKP, &mbar, + CYL_STARTP, &start, + CYL_ENDP, &end, + -1); - set_cylinder_spinbuttons(cylinder, g_value_get_int(&value1), g_value_get_int(&value2)); + set_cylinder_spinbuttons(cylinder, ml, mbar, start, end); } /* @@ -198,7 +205,9 @@ static void show_cylinder(cylinder_t *cyl, struct cylinder_widget *cylinder) mbar = cyl->type.workingpressure.mbar; add_cylinder(cylinder, desc, ml, mbar); - set_cylinder_spinbuttons(cylinder, cyl->type.size.mliter, cyl->type.workingpressure.mbar); + set_cylinder_spinbuttons(cylinder, + cyl->type.size.mliter, cyl->type.workingpressure.mbar, + cyl->start.mbar, cyl->end.mbar); o2 = cyl->gasmix.o2.permille / 10.0; gtk_widget_set_sensitive(cylinder->o2, !!o2); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button), !!o2); @@ -218,6 +227,19 @@ static int cyl_nothing(cylinder_t *cyl) !cyl->end.mbar; } +static void set_one_cylinder(int index, cylinder_t *cyl, GtkListStore *model, GtkTreeIter *iter) +{ + gtk_list_store_set(model, iter, + CYL_DESC, cyl->type.description ? : "", + CYL_SIZE, cyl->type.size.mliter, + CYL_WORKP, cyl->type.workingpressure.mbar, + CYL_STARTP, cyl->start.mbar, + CYL_ENDP, cyl->end.mbar, + CYL_O2, cyl->gasmix.o2.permille, + CYL_HE, cyl->gasmix.he.permille, + -1); +} + void show_dive_equipment(struct dive *dive) { int i, max; @@ -234,20 +256,17 @@ void show_dive_equipment(struct dive *dive) break; } while (--max); + cylinder_list.max_index = max; + + gtk_widget_set_sensitive(cylinder_list.edit, 0); + gtk_widget_set_sensitive(cylinder_list.del, 0); + gtk_widget_set_sensitive(cylinder_list.add, max < MAX_CYLINDERS); + for (i = 0; i < max; i++) { cylinder_t *cyl = dive->cylinder+i; gtk_list_store_append(model, &iter); - gtk_list_store_set(model, &iter, - CYL_INDEX, i, - CYL_DESC, cyl->type.description ? : "", - CYL_SIZE, cyl->type.size.mliter, - CYL_WORKP, cyl->type.workingpressure.mbar, - CYL_STARTP, cyl->start.mbar, - CYL_ENDP, cyl->end.mbar, - CYL_O2, cyl->gasmix.o2.permille, - CYL_HE, cyl->gasmix.he.permille, - -1); + set_one_cylinder(i, cyl, model, &iter); } } @@ -256,25 +275,29 @@ static GtkWidget *create_spinbutton(GtkWidget *vbox, const char *name, double mi GtkWidget *frame, *hbox, *button; frame = gtk_frame_new(name); - gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(frame), hbox); button = gtk_spin_button_new_with_range(min, max, incr); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID); return button; } -static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl, const char *desc, double volume, double pressure, int o2) +static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl, const char *desc, + double volume, double pressure, double start, double end, int o2) { int mbar, ml; - if (output_units.pressure == PSI) + if (output_units.pressure == PSI) { pressure /= 14.5037738; + start /= 14.5037738; + end /= 14.5037738; + } if (pressure && output_units.volume == CUFT) { volume *= 28.3168466; /* CUFT to liter */ @@ -289,6 +312,8 @@ static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl cyl->type.description = desc; cyl->type.size.mliter = ml; cyl->type.workingpressure.mbar = mbar; + cyl->start.mbar = start * 1000 + 0.5; + cyl->end.mbar = end * 1000 + 0.5; cyl->gasmix.o2.permille = o2; /* @@ -301,7 +326,7 @@ static void record_cylinder_changes(cylinder_t *cyl, struct cylinder_widget *cyl { const gchar *desc; GtkComboBox *box; - double volume, pressure; + double volume, pressure, start, end; int o2; /* Ignore uninitialized cylinder widgets */ @@ -312,10 +337,12 @@ static void record_cylinder_changes(cylinder_t *cyl, struct cylinder_widget *cyl desc = gtk_combo_box_get_active_text(box); volume = gtk_spin_button_get_value(cylinder->size); pressure = gtk_spin_button_get_value(cylinder->pressure); + start = gtk_spin_button_get_value(cylinder->start); + end = gtk_spin_button_get_value(cylinder->end); o2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->o2))*10 + 0.5; if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button))) o2 = 0; - fill_cylinder_info(cylinder, cyl, desc, volume, pressure, o2); + fill_cylinder_info(cylinder, cyl, desc, volume, pressure, start, end, o2); } void flush_dive_equipment_changes(struct dive *dive) @@ -323,30 +350,6 @@ void flush_dive_equipment_changes(struct dive *dive) /* We do nothing: we require the "Ok" button press */ } -static void apply_cb(GtkButton *button, gpointer data) -{ - int i; - struct dive *dive = current_dive; - - if (!dive) - return; - - for (i = 0; i < MAX_CYLINDERS; i++) - record_cylinder_changes(dive->cylinder+i, gtk_cylinder+i); - mark_divelist_changed(TRUE); - flush_divelist(dive); -} - -static void cancel_cb(GtkButton *button, gpointer data) -{ - struct dive *dive = current_dive; - - if (!dive) - return; - - show_dive_equipment(current_dive); -} - /* * We hardcode the most common standard cylinders, * we should pick up any other names from the dive @@ -427,38 +430,54 @@ static void nitrox_cb(GtkToggleButton *button, gpointer data) gtk_widget_set_sensitive(cylinder->o2, state); } -static void cylinder_widget(int nr, GtkListStore *model) +static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, GtkListStore *model) { - struct cylinder_widget *cylinder; - GtkWidget *frame, *hbox, *hbox2; + GtkWidget *frame, *hbox; GtkWidget *widget; - char buffer[80]; - cylinder = gtk_cylinder + nr; - cylinder->index = nr; + /* + * Cylinder type: description, size and + * working pressure + */ + frame = gtk_frame_new("Cylinder"); hbox = gtk_hbox_new(FALSE, 3); - cylinder->hbox = hbox; - - snprintf(buffer, sizeof(buffer), "Cylinder %d", nr+1); - frame = gtk_frame_new(buffer); - gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 0); - - hbox2 = gtk_hbox_new(FALSE, 3); - gtk_container_add(GTK_CONTAINER(frame), hbox2); + gtk_container_add(GTK_CONTAINER(frame), hbox); widget = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(model), 0); - gtk_box_pack_start(GTK_BOX(hbox2), widget, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0); cylinder->description = GTK_COMBO_BOX(widget); g_signal_connect(widget, "changed", G_CALLBACK(cylinder_cb), cylinder); + hbox = gtk_hbox_new(FALSE, 3); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, TRUE, 0); + widget = create_spinbutton(hbox, "Size", 0, 300, 0.1); cylinder->size = GTK_SPIN_BUTTON(widget); widget = create_spinbutton(hbox, "Pressure", 0, 5000, 1); cylinder->pressure = GTK_SPIN_BUTTON(widget); + /* + * Cylinder start/end pressures + */ + hbox = gtk_hbox_new(FALSE, 3); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + + widget = create_spinbutton(hbox, "Start Pressure", 0, 5000, 1); + cylinder->start = GTK_SPIN_BUTTON(widget); + + widget = create_spinbutton(hbox, "End Pressure", 0, 5000, 1); + cylinder->end = GTK_SPIN_BUTTON(widget); + + /* + * Cylinder gas mix: Air, Nitrox or Trimix + */ + hbox = gtk_hbox_new(FALSE, 3); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + widget = create_spinbutton(hbox, "Nitrox", 21, 100, 0.1); cylinder->o2 = widget; cylinder->gasmix_button = gtk_check_button_new(); @@ -469,16 +488,136 @@ static void cylinder_widget(int nr, GtkListStore *model) gtk_spin_button_set_range(GTK_SPIN_BUTTON(cylinder->o2), 21.0, 100.0); } +static int edit_cylinder_dialog(int index, cylinder_t *cyl) +{ + int success; + GtkWidget *dialog, *vbox; + struct cylinder_widget cylinder; + struct dive *dive; + + cylinder.index = index; + cylinder.changed = 0; + + dive = current_dive; + if (!dive) + return 0; + *cyl = dive->cylinder[index]; + + dialog = gtk_dialog_new_with_buttons("Cylinder", + 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)); + cylinder_widget(vbox, &cylinder, cylinder_model); + + show_cylinder(cyl, &cylinder); + + gtk_widget_show_all(dialog); + success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT; + if (success) { + record_cylinder_changes(cyl, &cylinder); + dive->cylinder[index] = *cyl; + mark_divelist_changed(TRUE); + flush_divelist(dive); + } + + gtk_widget_destroy(dialog); + + return success; +} + +static int get_model_index(GtkListStore *model, GtkTreeIter *iter) +{ + int *p, index; + GtkTreePath *path; + + path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), iter); + p = gtk_tree_path_get_indices(path); + index = p ? *p : 0; + gtk_tree_path_free(path); + return index; +} + static void edit_cb(GtkButton *button, gpointer data) { + int index; + GtkTreeIter iter; + GtkListStore *model = cylinder_list.model; + GtkTreeSelection *selection; + cylinder_t cyl; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cylinder_list.tree_view)); + + /* Nothing selected? This shouldn't happen, since the button should be inactive */ + if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) + return; + + index = get_model_index(model, &iter); + if (!edit_cylinder_dialog(index, &cyl)) + return; + + set_one_cylinder(index, &cyl, model, &iter); } static void add_cb(GtkButton *button, gpointer data) { + int index = cylinder_list.max_index; + GtkTreeIter iter; + GtkListStore *model = cylinder_list.model; + GtkTreeSelection *selection; + cylinder_t cyl; + + if (!edit_cylinder_dialog(index, &cyl)) + return; + + gtk_list_store_append(model, &iter); + set_one_cylinder(index, &cyl, model, &iter); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cylinder_list.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); } static void del_cb(GtkButton *button, gpointer data) { + int index, nr; + GtkTreeIter iter; + GtkListStore *model = cylinder_list.model; + GtkTreeSelection *selection; + struct dive *dive; + cylinder_t *cyl; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cylinder_list.tree_view)); + + /* Nothing selected? This shouldn't happen, since the button should be inactive */ + if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) + return; + + index = get_model_index(model, &iter); + + dive = current_dive; + if (!dive) + return; + cyl = dive->cylinder + index; + nr = cylinder_list.max_index - index - 1; + + gtk_list_store_remove(model, &iter); + + cylinder_list.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); } static GtkListStore *create_tank_size_model(void) @@ -552,13 +691,31 @@ static void percentage_data_func(GtkTreeViewColumn *col, g_object_set(renderer, "text", buffer, NULL); } +static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model) +{ + GtkTreeIter iter; + int selected; + + selected = gtk_tree_selection_get_selected(selection, NULL, &iter); + gtk_widget_set_sensitive(cylinder_list.edit, selected); + gtk_widget_set_sensitive(cylinder_list.del, selected); +} + +static void row_activated_cb(GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + GtkTreeModel *model) +{ + edit_cb(NULL, NULL); +} + static GtkWidget *cylinder_list_create(void) { GtkWidget *tree_view; + GtkTreeSelection *selection; GtkListStore *model; model = gtk_list_store_new(CYL_COLUMNS, - G_TYPE_INT, /* CYL_INDEX */ G_TYPE_STRING, /* CYL_DESC: utf8 */ G_TYPE_INT, /* CYL_SIZE: mliter */ G_TYPE_INT, /* CYL_WORKP: mbar */ @@ -569,6 +726,16 @@ static GtkWidget *cylinder_list_create(void) ); cylinder_list.model = model; tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); + g_signal_connect(tree_view, "row-activated", G_CALLBACK(row_activated_cb), model); + + 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), model); + + g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE, + "enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, + NULL); + cylinder_list.desc = tree_view_column(tree_view, CYL_DESC, "Type", NULL, PANGO_ALIGN_LEFT, TRUE); cylinder_list.size = tree_view_column(tree_view, CYL_SIZE, "Size", size_data_func, PANGO_ALIGN_RIGHT, TRUE); cylinder_list.workp = tree_view_column(tree_view, CYL_WORKP, "MaxPress", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE);