X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=equipment.c;h=2b278934d559cba41c5ccd8eca9293fc18671423;hb=192713680eb02afe6453a0a404e0eabb59758791;hp=d7ccbc3ab33ea58b24f3ea8724b5779da1294f15;hpb=0b4814a95d822ff99258f465cb123cd3f821eec2;p=ext%2Fsubsurface.git diff --git a/equipment.c b/equipment.c index d7ccbc3..2b27893 100644 --- a/equipment.c +++ b/equipment.c @@ -3,7 +3,6 @@ * controlled through the following interfaces: * * void show_dive_equipment(struct dive *dive) - * void flush_dive_equipment_changes(struct dive *dive) * * called from gtk-ui: * GtkWidget *equipment_widget(void) @@ -35,9 +34,7 @@ enum { static struct { int max_index; GtkListStore *model; - GtkWidget *tree_view; GtkWidget *edit, *add, *del; - GtkTreeViewColumn *desc, *size, *workp, *startp, *endp, *o2, *he; } cylinder_list; struct cylinder_widget { @@ -45,22 +42,24 @@ struct cylinder_widget { const char *name; GtkWidget *hbox; GtkComboBox *description; - GtkSpinButton *size, *pressure, *start, *end; + GtkSpinButton *size, *pressure; + GtkWidget *start, *end, *pressure_button; GtkWidget *o2, *gasmix_button; }; +/* we want bar - so let's not use our unit functions */ static int convert_pressure(int mbar, double *p) { int decimals = 1; double pressure; - pressure = mbar / 1000.0; - if (mbar) { - if (output_units.pressure == PSI) { - pressure *= 14.5037738; /* Bar to PSI */ - decimals = 0; - } + if (output_units.pressure == PSI) { + pressure = mbar_to_PSI(mbar); + decimals = 0; + } else { + pressure = mbar / 1000.0; } + *p = pressure; return decimals; } @@ -71,16 +70,17 @@ static int convert_volume_pressure(int ml, int mbar, double *v, double *p) double volume, pressure; volume = ml / 1000.0; - pressure = mbar / 1000.0; if (mbar) { if (output_units.volume == CUFT) { - volume /= 28.3168466; /* Liters to cuft */ - volume *= pressure / 1.01325; + volume = ml_to_cuft(ml); + volume *= bar_to_atm(mbar / 1000.0); } + if (output_units.pressure == PSI) { - pressure *= 14.5037738; /* Bar to PSI */ + pressure = mbar_to_PSI(mbar); decimals = 0; - } + } else + pressure = mbar / 1000.0; } *v = volume; *p = pressure; @@ -96,14 +96,74 @@ static void set_cylinder_type_spinbuttons(struct cylinder_widget *cylinder, int gtk_spin_button_set_value(cylinder->pressure, pressure); } -static void set_cylinder_pressure_spinbuttons(struct cylinder_widget *cylinder, int start, int end) +static void set_cylinder_pressure_spinbuttons(struct cylinder_widget *cylinder, cylinder_t *cyl) { + int set; + unsigned int start, end; double pressure; + start = cyl->start.mbar; + end = cyl->end.mbar; + set = start || end; + if (!set) { + start = cyl->sample_start.mbar; + end = cyl->sample_end.mbar; + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cylinder->pressure_button), set); + gtk_widget_set_sensitive(cylinder->start, set); + gtk_widget_set_sensitive(cylinder->end, set); + convert_pressure(start, &pressure); - gtk_spin_button_set_value(cylinder->start, pressure); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->start), pressure); convert_pressure(end, &pressure); - gtk_spin_button_set_value(cylinder->end, pressure); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->end), pressure); +} + +/* + * The gtk_tree_model_foreach() interface is bad. It could have + * returned whether the callback ever returned true + */ +static GtkTreeIter *found_match = NULL; +static GtkTreeIter match_iter; + +static gboolean match_cylinder(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + int match; + gchar *name; + const char *desc = data; + + gtk_tree_model_get(model, iter, 0, &name, -1); + match = !strcmp(desc, name); + g_free(name); + if (match) { + match_iter = *iter; + found_match = &match_iter; + } + return match; +} + +static int get_active_cylinder(GtkComboBox *combo_box, GtkTreeIter *iter) +{ + char *desc; + + if (gtk_combo_box_get_active_iter(combo_box, iter)) + return TRUE; + + desc = gtk_combo_box_get_active_text(combo_box); + + found_match = NULL; + gtk_tree_model_foreach(GTK_TREE_MODEL(cylinder_model), match_cylinder, (void *)desc); + + g_free(desc); + if (!found_match) + return FALSE; + + *iter = *found_match; + gtk_combo_box_set_active_iter(combo_box, iter); + return TRUE; } static void cylinder_cb(GtkComboBox *combo_box, gpointer data) @@ -115,7 +175,7 @@ static void cylinder_cb(GtkComboBox *combo_box, gpointer data) cylinder_t *cyl = current_dive->cylinder + cylinder->index; /* Did the user set it to some non-standard value? */ - if (!gtk_combo_box_get_active_iter(combo_box, &iter)) { + if (!get_active_cylinder(combo_box, &iter)) { cylinder->changed = 1; return; } @@ -144,31 +204,6 @@ static void cylinder_cb(GtkComboBox *combo_box, gpointer data) set_cylinder_type_spinbuttons(cylinder, ml, mbar); } -/* - * The gtk_tree_model_foreach() interface is bad. It could have - * returned whether the callback ever returned true - */ -static GtkTreeIter *found_match = NULL; -static GtkTreeIter match_iter; - -static gboolean match_cylinder(GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - const char *name; - const char *desc = data; - GValue value = {0, }; - - gtk_tree_model_get_value(model, iter, 0, &value); - name = g_value_get_string(&value); - if (strcmp(desc, name)) - return FALSE; - match_iter = *iter; - found_match = &match_iter; - return TRUE; -} - static GtkTreeIter *add_cylinder_type(const char *desc, int ml, int mbar, GtkTreeIter *iter) { GtkTreeModel *model; @@ -242,8 +277,7 @@ static void show_cylinder(cylinder_t *cyl, struct cylinder_widget *cylinder) set_cylinder_type_spinbuttons(cylinder, cyl->type.size.mliter, cyl->type.workingpressure.mbar); - set_cylinder_pressure_spinbuttons(cylinder, - cyl->start.mbar, cyl->end.mbar); + set_cylinder_pressure_spinbuttons(cylinder, cyl); 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); @@ -259,18 +293,24 @@ static int cyl_nothing(cylinder_t *cyl) !cyl->type.description && !cyl->gasmix.o2.permille && !cyl->gasmix.he.permille && + !cyl->sample_start.mbar && + !cyl->sample_end.mbar && !cyl->start.mbar && !cyl->end.mbar; } static void set_one_cylinder(int index, cylinder_t *cyl, GtkListStore *model, GtkTreeIter *iter) { + unsigned int start, end; + + start = cyl->start.mbar ? : cyl->sample_start.mbar; + end = cyl->end.mbar ? : cyl->sample_end.mbar; 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_STARTP, start, + CYL_ENDP, end, CYL_O2, cyl->gasmix.o2.permille, CYL_HE, cyl->gasmix.he.permille, -1); @@ -330,14 +370,14 @@ static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl int mbar, ml; if (output_units.pressure == PSI) { - pressure /= 14.5037738; - start /= 14.5037738; - end /= 14.5037738; + pressure = psi_to_bar(pressure); + start = psi_to_bar(start); + end = psi_to_bar(end); } if (pressure && output_units.volume == CUFT) { - volume *= 28.3168466; /* CUFT to liter */ - volume /= pressure / 1.01325; + volume = cuft_to_l(volume); + volume /= bar_to_atm(pressure); } ml = volume * 1000 + 0.5; @@ -373,19 +413,19 @@ 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))) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->pressure_button))) { + start = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->start)); + end = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->end)); + } else { + start = end = 0; + } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button))) + o2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->o2))*10 + 0.5; + else o2 = 0; fill_cylinder_info(cylinder, cyl, desc, volume, pressure, start, end, o2); } -void flush_dive_equipment_changes(struct dive *dive) -{ - /* We do nothing: we require the "Ok" button press */ -} - /* * We hardcode the most common standard cylinders, * we should pick up any other names from the dive @@ -439,9 +479,9 @@ static void fill_tank_list(GtkListStore *store) /* Is it in cuft and psi? */ if (psi) { - double bar = 0.0689475729 * psi; - double airvolume = 28316.8466 * size; - double atm = bar / 1.01325; + double bar = psi_to_bar(psi); + double airvolume = cuft_to_l(size) * 1000.0; + double atm = bar_to_atm(bar); ml = airvolume / atm + 0.5; mbar = bar*1000 + 0.5; @@ -466,6 +506,16 @@ static void nitrox_cb(GtkToggleButton *button, gpointer data) gtk_widget_set_sensitive(cylinder->o2, state); } +static void pressure_cb(GtkToggleButton *button, gpointer data) +{ + struct cylinder_widget *cylinder = data; + int state; + + state = gtk_toggle_button_get_active(button); + gtk_widget_set_sensitive(cylinder->start, state); + gtk_widget_set_sensitive(cylinder->end, state); +} + static gboolean completion_cb(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, struct cylinder_widget *cylinder) { const char *desc; @@ -476,6 +526,12 @@ static gboolean completion_cb(GtkEntryCompletion *widget, GtkTreeModel *model, G return TRUE; } +static void cylinder_activate_cb(GtkComboBox *combo_box, gpointer data) +{ + struct cylinder_widget *cylinder = data; + cylinder_cb(cylinder->description, data); +} + static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, GtkListStore *model) { GtkWidget *frame, *hbox; @@ -499,6 +555,8 @@ static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, G g_signal_connect(widget, "changed", G_CALLBACK(cylinder_cb), cylinder); entry = GTK_ENTRY(GTK_BIN(widget)->child); + g_signal_connect(entry, "activate", G_CALLBACK(cylinder_activate_cb), cylinder); + completion = gtk_entry_completion_new(); gtk_entry_completion_set_text_column(completion, 0); gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(model)); @@ -521,11 +579,15 @@ static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, G hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + cylinder->pressure_button = gtk_check_button_new(); + gtk_box_pack_start(GTK_BOX(hbox), cylinder->pressure_button, FALSE, FALSE, 3); + g_signal_connect(cylinder->pressure_button, "toggled", G_CALLBACK(pressure_cb), cylinder); + widget = create_spinbutton(hbox, "Start Pressure", 0, 5000, 1); - cylinder->start = GTK_SPIN_BUTTON(widget); + cylinder->start = widget; widget = create_spinbutton(hbox, "End Pressure", 0, 5000, 1); - cylinder->end = GTK_SPIN_BUTTON(widget); + cylinder->end = widget; /* * Cylinder gas mix: Air, Nitrox or Trimix @@ -576,6 +638,7 @@ static int edit_cylinder_dialog(int index, cylinder_t *cyl) record_cylinder_changes(cyl, &cylinder); dive->cylinder[index] = *cyl; mark_divelist_changed(TRUE); + update_cylinder_related_info(dive); flush_divelist(dive); } @@ -596,7 +659,7 @@ static int get_model_index(GtkListStore *model, GtkTreeIter *iter) return index; } -static void edit_cb(GtkButton *button, gpointer data) +static void edit_cb(GtkButton *button, GtkTreeView *tree_view) { int index; GtkTreeIter iter; @@ -604,7 +667,7 @@ static void edit_cb(GtkButton *button, gpointer data) GtkTreeSelection *selection; cylinder_t cyl; - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cylinder_list.tree_view)); + selection = gtk_tree_view_get_selection(tree_view); /* Nothing selected? This shouldn't happen, since the button should be inactive */ if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) @@ -618,7 +681,7 @@ static void edit_cb(GtkButton *button, gpointer data) repaint_dive(); } -static void add_cb(GtkButton *button, gpointer data) +static void add_cb(GtkButton *button, GtkTreeView *tree_view) { int index = cylinder_list.max_index; GtkTreeIter iter; @@ -632,14 +695,14 @@ static void add_cb(GtkButton *button, gpointer data) 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)); + 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); } -static void del_cb(GtkButton *button, gpointer data) +static void del_cb(GtkButton *button, GtkTreeView *tree_view) { int index, nr; GtkTreeIter iter; @@ -648,7 +711,7 @@ static void del_cb(GtkButton *button, gpointer data) struct dive *dive; cylinder_t *cyl; - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cylinder_list.tree_view)); + selection = gtk_tree_view_get_selection(tree_view); /* Nothing selected? This shouldn't happen, since the button should be inactive */ if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) @@ -762,26 +825,18 @@ static void row_activated_cb(GtkTreeView *tree_view, GtkTreeViewColumn *column, GtkTreeModel *model) { - edit_cb(NULL, NULL); + edit_cb(NULL, tree_view); } -static GtkWidget *cylinder_list_create(void) +GtkWidget *cylinder_list_widget(void) { + GtkListStore *model = cylinder_list.model; GtkWidget *tree_view; GtkTreeSelection *selection; - GtkListStore *model; - model = gtk_list_store_new(CYL_COLUMNS, - G_TYPE_STRING, /* CYL_DESC: utf8 */ - G_TYPE_INT, /* CYL_SIZE: mliter */ - G_TYPE_INT, /* CYL_WORKP: mbar */ - G_TYPE_INT, /* CYL_STARTP: mbar */ - G_TYPE_INT, /* CYL_ENDP: mbar */ - G_TYPE_INT, /* CYL_O2: permille */ - G_TYPE_INT /* CYL_HE: permille */ - ); - cylinder_list.model = model; 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); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)); @@ -792,19 +847,36 @@ static GtkWidget *cylinder_list_create(void) "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); - cylinder_list.startp = tree_view_column(tree_view, CYL_STARTP, "Start", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE); - cylinder_list.endp = tree_view_column(tree_view, CYL_ENDP, "End", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE); - cylinder_list.o2 = tree_view_column(tree_view, CYL_O2, "O" UTF8_SUBSCRIPT_2 "%", percentage_data_func, PANGO_ALIGN_RIGHT, TRUE); - cylinder_list.he = tree_view_column(tree_view, CYL_HE, "He%", percentage_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_DESC, "Type", NULL, PANGO_ALIGN_LEFT, TRUE); + tree_view_column(tree_view, CYL_SIZE, "Size", size_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_WORKP, "MaxPress", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_STARTP, "Start", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_ENDP, "End", pressure_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_O2, "O" UTF8_SUBSCRIPT_2 "%", percentage_data_func, PANGO_ALIGN_RIGHT, TRUE); + tree_view_column(tree_view, CYL_HE, "He%", percentage_data_func, PANGO_ALIGN_RIGHT, TRUE); return tree_view; } +static GtkWidget *cylinder_list_create(void) +{ + GtkListStore *model; + + model = gtk_list_store_new(CYL_COLUMNS, + G_TYPE_STRING, /* CYL_DESC: utf8 */ + G_TYPE_INT, /* CYL_SIZE: mliter */ + G_TYPE_INT, /* CYL_WORKP: mbar */ + G_TYPE_INT, /* CYL_STARTP: mbar */ + G_TYPE_INT, /* CYL_ENDP: mbar */ + G_TYPE_INT, /* CYL_O2: permille */ + G_TYPE_INT /* CYL_HE: permille */ + ); + cylinder_list.model = model; + return cylinder_list_widget(); +} + GtkWidget *equipment_widget(void) { - GtkWidget *vbox, *hbox, *frame, *framebox; + GtkWidget *vbox, *hbox, *frame, *framebox, *tree_view; GtkWidget *add, *del, *edit; vbox = gtk_vbox_new(FALSE, 3); @@ -818,7 +890,7 @@ GtkWidget *equipment_widget(void) */ cylinder_model = create_tank_size_model(); - cylinder_list.tree_view = cylinder_list_create(); + tree_view = cylinder_list_create(); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3); @@ -832,7 +904,7 @@ GtkWidget *equipment_widget(void) hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3); - gtk_box_pack_start(GTK_BOX(hbox), cylinder_list.tree_view, TRUE, FALSE, 3); + gtk_box_pack_start(GTK_BOX(hbox), tree_view, TRUE, FALSE, 3); hbox = gtk_hbox_new(TRUE, 3); gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3); @@ -848,9 +920,9 @@ GtkWidget *equipment_widget(void) cylinder_list.add = add; cylinder_list.del = del; - g_signal_connect(edit, "clicked", G_CALLBACK(edit_cb), NULL); - g_signal_connect(add, "clicked", G_CALLBACK(add_cb), NULL); - g_signal_connect(del, "clicked", G_CALLBACK(del_cb), NULL); + 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); return vbox; }