2011-09-20 19:40:34 +00:00
|
|
|
/* equipment.c */
|
|
|
|
/* creates the UI for the equipment page -
|
|
|
|
* controlled through the following interfaces:
|
2011-10-02 20:13:27 +00:00
|
|
|
*
|
2012-08-15 22:21:34 +00:00
|
|
|
* void show_dive_equipment(struct dive *dive, int w_idx)
|
2011-09-20 19:40:34 +00:00
|
|
|
*
|
|
|
|
* called from gtk-ui:
|
2012-08-15 22:21:34 +00:00
|
|
|
* GtkWidget *equipment_widget(int w_idx)
|
2011-09-20 19:40:34 +00:00
|
|
|
*/
|
2011-09-09 15:38:48 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <time.h>
|
2012-10-11 00:42:59 +00:00
|
|
|
#include <glib/gi18n.h>
|
2011-09-09 15:38:48 +00:00
|
|
|
|
|
|
|
#include "dive.h"
|
|
|
|
#include "display.h"
|
2013-05-03 18:04:51 +00:00
|
|
|
#if USE_GTK_UI
|
2011-09-20 19:40:34 +00:00
|
|
|
#include "display-gtk.h"
|
2013-05-03 18:04:51 +00:00
|
|
|
#endif
|
2011-09-09 15:38:48 +00:00
|
|
|
#include "divelist.h"
|
2013-04-13 13:17:59 +00:00
|
|
|
#include "conversions.h"
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2013-05-03 18:04:51 +00:00
|
|
|
#if USE_GTK_UI
|
|
|
|
#include "display-gtk.h"
|
2011-12-24 03:41:16 +00:00
|
|
|
static GtkListStore *cylinder_model, *weightsystem_model;
|
2011-10-02 20:13:27 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
CYL_DESC,
|
|
|
|
CYL_SIZE,
|
|
|
|
CYL_WORKP,
|
|
|
|
CYL_STARTP,
|
|
|
|
CYL_ENDP,
|
|
|
|
CYL_O2,
|
|
|
|
CYL_HE,
|
|
|
|
CYL_COLUMNS
|
|
|
|
};
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
enum {
|
|
|
|
WS_DESC,
|
|
|
|
WS_WEIGHT,
|
|
|
|
WS_COLUMNS
|
|
|
|
};
|
|
|
|
|
|
|
|
struct equipment_list {
|
2011-10-02 20:42:51 +00:00
|
|
|
int max_index;
|
2011-10-02 20:13:27 +00:00
|
|
|
GtkListStore *model;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkTreeView *tree_view;
|
2011-10-02 20:13:27 +00:00
|
|
|
GtkWidget *edit, *add, *del;
|
2011-12-24 03:41:16 +00:00
|
|
|
};
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
static struct equipment_list cylinder_list[2], weightsystem_list[2];
|
2011-12-24 03:41:16 +00:00
|
|
|
|
2012-09-11 20:37:06 +00:00
|
|
|
struct dive edit_dive;
|
2011-10-02 20:13:27 +00:00
|
|
|
|
2011-09-13 19:58:53 +00:00
|
|
|
struct cylinder_widget {
|
2011-09-13 20:15:31 +00:00
|
|
|
int index, changed;
|
|
|
|
const char *name;
|
2011-09-13 20:50:03 +00:00
|
|
|
GtkWidget *hbox;
|
2011-09-13 19:58:53 +00:00
|
|
|
GtkComboBox *description;
|
2011-11-09 16:37:49 +00:00
|
|
|
GtkSpinButton *size, *pressure;
|
2011-11-09 16:51:20 +00:00
|
|
|
GtkWidget *start, *end, *pressure_button;
|
2011-12-11 19:09:37 +00:00
|
|
|
GtkWidget *o2, *he, *gasmix_button;
|
2012-09-14 03:41:21 +00:00
|
|
|
int w_idx;
|
2011-09-13 19:58:53 +00:00
|
|
|
};
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
struct ws_widget {
|
|
|
|
int index, changed;
|
|
|
|
const char *name;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkComboBox *description;
|
|
|
|
GtkSpinButton *weight;
|
2012-09-14 03:41:21 +00:00
|
|
|
int w_idx;
|
2011-12-24 03:41:16 +00:00
|
|
|
};
|
2013-05-03 18:04:51 +00:00
|
|
|
#endif /* USE_GTK_UI */
|
2011-12-24 03:41:16 +00:00
|
|
|
|
2011-11-02 04:00:46 +00:00
|
|
|
/* we want bar - so let's not use our unit functions */
|
2013-04-13 13:17:59 +00:00
|
|
|
int convert_pressure(int mbar, double *p)
|
2011-09-10 22:27:23 +00:00
|
|
|
{
|
2011-10-02 20:13:27 +00:00
|
|
|
int decimals = 1;
|
|
|
|
double pressure;
|
|
|
|
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.pressure == PSI) {
|
2011-11-02 04:00:46 +00:00
|
|
|
pressure = mbar_to_PSI(mbar);
|
|
|
|
decimals = 0;
|
|
|
|
} else {
|
|
|
|
pressure = mbar / 1000.0;
|
2011-10-02 20:13:27 +00:00
|
|
|
}
|
2011-11-02 04:00:46 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
*p = pressure;
|
|
|
|
return decimals;
|
|
|
|
}
|
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
void convert_volume_pressure(int ml, int mbar, double *v, double *p)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2011-09-10 22:27:23 +00:00
|
|
|
double volume, pressure;
|
|
|
|
|
2011-11-09 15:56:07 +00:00
|
|
|
volume = ml / 1000.0;
|
2011-09-10 22:27:23 +00:00
|
|
|
if (mbar) {
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.volume == CUFT) {
|
2011-11-02 04:00:46 +00:00
|
|
|
volume = ml_to_cuft(ml);
|
|
|
|
volume *= bar_to_atm(mbar / 1000.0);
|
2011-11-09 15:56:07 +00:00
|
|
|
}
|
2011-11-02 04:00:46 +00:00
|
|
|
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.pressure == PSI)
|
2011-11-02 04:00:46 +00:00
|
|
|
pressure = mbar_to_PSI(mbar);
|
2012-09-18 23:51:48 +00:00
|
|
|
else
|
2011-11-02 04:00:46 +00:00
|
|
|
pressure = mbar / 1000.0;
|
2012-09-18 23:51:48 +00:00
|
|
|
*p = pressure;
|
2013-05-16 05:24:26 +00:00
|
|
|
} else {
|
|
|
|
*p = 0;
|
2011-09-10 22:27:23 +00:00
|
|
|
}
|
2011-10-02 20:13:27 +00:00
|
|
|
*v = volume;
|
|
|
|
}
|
2011-09-10 22:27:23 +00:00
|
|
|
|
2013-05-03 21:16:09 +00:00
|
|
|
int convert_weight(int grams, double *m)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
int decimals = 1; /* not sure - do people do less than whole lbs/kg ? */
|
|
|
|
double weight;
|
|
|
|
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.weight == LBS)
|
2011-12-24 03:41:16 +00:00
|
|
|
weight = grams_to_lbs(grams);
|
|
|
|
else
|
|
|
|
weight = grams / 1000.0;
|
|
|
|
*m = weight;
|
|
|
|
return decimals;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:04:51 +00:00
|
|
|
#if USE_GTK_UI
|
2013-01-28 00:40:01 +00:00
|
|
|
static void set_cylinder_description(struct cylinder_widget *cylinder, const char *desc)
|
|
|
|
{
|
|
|
|
set_active_text(cylinder->description, desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-22 14:18:58 +00:00
|
|
|
static void set_cylinder_type_spinbuttons(struct cylinder_widget *cylinder, int ml, int mbar)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
|
|
|
double volume, pressure;
|
|
|
|
|
|
|
|
convert_volume_pressure(ml, mbar, &volume, &pressure);
|
2011-09-13 20:15:31 +00:00
|
|
|
gtk_spin_button_set_value(cylinder->size, volume);
|
|
|
|
gtk_spin_button_set_value(cylinder->pressure, pressure);
|
2011-10-22 14:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-11-09 16:33:13 +00:00
|
|
|
static void set_cylinder_pressure_spinbuttons(struct cylinder_widget *cylinder, cylinder_t *cyl)
|
2011-10-22 14:18:58 +00:00
|
|
|
{
|
2011-11-09 16:51:20 +00:00
|
|
|
int set;
|
|
|
|
unsigned int start, end;
|
2011-10-22 14:18:58 +00:00
|
|
|
double pressure;
|
2011-10-17 18:12:11 +00:00
|
|
|
|
2011-11-09 16:51:20 +00:00
|
|
|
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);
|
2011-11-09 16:37:49 +00:00
|
|
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->start), pressure);
|
2011-11-09 16:51:20 +00:00
|
|
|
convert_pressure(end, &pressure);
|
2011-11-09 16:37:49 +00:00
|
|
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->end), pressure);
|
2011-09-10 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
static void set_weight_description(struct ws_widget *ws_widget, const char *desc)
|
|
|
|
{
|
|
|
|
set_active_text(ws_widget->description, desc);
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void set_weight_weight_spinbutton(struct ws_widget *ws_widget, int grams)
|
|
|
|
{
|
|
|
|
double weight;
|
|
|
|
|
|
|
|
convert_weight(grams, &weight);
|
|
|
|
gtk_spin_button_set_value(ws_widget->weight, weight);
|
|
|
|
}
|
|
|
|
|
2011-10-23 06:45:35 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static gboolean match_desc(GtkTreeModel *model, GtkTreePath *path,
|
|
|
|
GtkTreeIter *iter, gpointer data)
|
2011-10-23 06:45:35 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static int get_active_item(GtkComboBox *combo_box, GtkTreeIter *iter, GtkListStore *model)
|
2011-10-23 06:45:35 +00:00
|
|
|
{
|
2013-01-28 00:40:01 +00:00
|
|
|
const char *desc;
|
2011-10-23 06:45:35 +00:00
|
|
|
|
|
|
|
if (gtk_combo_box_get_active_iter(combo_box, iter))
|
|
|
|
return TRUE;
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
desc = get_active_text(combo_box);
|
2011-10-23 06:45:35 +00:00
|
|
|
|
|
|
|
found_match = NULL;
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_tree_model_foreach(GTK_TREE_MODEL(model), match_desc, (void *)desc);
|
2011-10-23 06:45:35 +00:00
|
|
|
|
|
|
|
if (!found_match)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*iter = *found_match;
|
|
|
|
gtk_combo_box_set_active_iter(combo_box, iter);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-09-10 04:39:54 +00:00
|
|
|
static void cylinder_cb(GtkComboBox *combo_box, gpointer data)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreeModel *model = gtk_combo_box_get_model(combo_box);
|
2011-10-22 14:18:58 +00:00
|
|
|
int ml, mbar;
|
2011-09-13 20:15:31 +00:00
|
|
|
struct cylinder_widget *cylinder = data;
|
2012-09-14 03:41:21 +00:00
|
|
|
struct dive *dive;
|
|
|
|
cylinder_t *cyl;
|
|
|
|
|
|
|
|
if (cylinder->w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
|
|
|
cyl = dive->cylinder + cylinder->index;
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2011-09-10 18:09:39 +00:00
|
|
|
/* Did the user set it to some non-standard value? */
|
2011-12-24 03:41:16 +00:00
|
|
|
if (!get_active_item(combo_box, &iter, cylinder_model)) {
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->changed = 1;
|
2011-09-10 04:39:54 +00:00
|
|
|
return;
|
2011-09-10 18:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We get "change" signal callbacks just because we set
|
|
|
|
* the description by hand. Whatever. So ignore them if
|
|
|
|
* they are no-ops.
|
|
|
|
*/
|
2011-09-13 20:15:31 +00:00
|
|
|
if (!cylinder->changed && cyl->type.description) {
|
2011-09-10 18:09:39 +00:00
|
|
|
int same;
|
2013-01-28 00:40:01 +00:00
|
|
|
const char *desc = get_active_text(combo_box);
|
2011-09-10 18:09:39 +00:00
|
|
|
|
|
|
|
same = !strcmp(desc, cyl->type.description);
|
|
|
|
if (same)
|
|
|
|
return;
|
|
|
|
}
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->changed = 1;
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2011-10-17 18:12:11 +00:00
|
|
|
gtk_tree_model_get(model, &iter,
|
|
|
|
CYL_SIZE, &ml,
|
|
|
|
CYL_WORKP, &mbar,
|
|
|
|
-1);
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2011-10-22 14:18:58 +00:00
|
|
|
set_cylinder_type_spinbuttons(cylinder, ml, mbar);
|
2011-09-10 04:39:54 +00:00
|
|
|
}
|
2011-09-10 02:46:53 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void weight_cb(GtkComboBox *combo_box, gpointer data)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreeModel *model = gtk_combo_box_get_model(combo_box);
|
|
|
|
int weight;
|
|
|
|
struct ws_widget *ws_widget = data;
|
2012-09-14 03:41:21 +00:00
|
|
|
struct dive *dive;
|
|
|
|
weightsystem_t *ws;
|
|
|
|
if (ws_widget->w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
|
|
|
ws = dive->weightsystem + ws_widget->index;
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
/* Did the user set it to some non-standard value? */
|
|
|
|
if (!get_active_item(combo_box, &iter, weightsystem_model)) {
|
|
|
|
ws_widget->changed = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We get "change" signal callbacks just because we set
|
|
|
|
* the description by hand. Whatever. So ignore them if
|
|
|
|
* they are no-ops.
|
|
|
|
*/
|
|
|
|
if (!ws_widget->changed && ws->description) {
|
|
|
|
int same;
|
2013-01-28 00:40:01 +00:00
|
|
|
const char *desc = get_active_text(combo_box);
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
same = !strcmp(desc, ws->description);
|
|
|
|
if (same)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ws_widget->changed = 1;
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, &iter,
|
|
|
|
WS_WEIGHT, &weight,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
set_weight_weight_spinbutton(ws_widget, weight);
|
|
|
|
}
|
|
|
|
|
2011-10-22 15:12:30 +00:00
|
|
|
static GtkTreeIter *add_cylinder_type(const char *desc, int ml, int mbar, GtkTreeIter *iter)
|
2011-09-11 00:14:07 +00:00
|
|
|
{
|
|
|
|
GtkTreeModel *model;
|
|
|
|
|
2011-10-22 15:12:30 +00:00
|
|
|
/* Don't even bother adding stuff without a size */
|
|
|
|
if (!ml)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
found_match = NULL;
|
|
|
|
model = GTK_TREE_MODEL(cylinder_model);
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_tree_model_foreach(model, match_desc, (void *)desc);
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
if (!found_match) {
|
|
|
|
GtkListStore *store = GTK_LIST_STORE(model);
|
|
|
|
|
2011-10-22 15:12:30 +00:00
|
|
|
gtk_list_store_append(store, iter);
|
|
|
|
gtk_list_store_set(store, iter,
|
2011-09-11 00:14:07 +00:00
|
|
|
0, desc,
|
|
|
|
1, ml,
|
|
|
|
2, mbar,
|
|
|
|
-1);
|
2011-10-22 15:12:30 +00:00
|
|
|
return iter;
|
2011-09-11 00:14:07 +00:00
|
|
|
}
|
2011-10-22 15:12:30 +00:00
|
|
|
return found_match;
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static GtkTreeIter *add_weightsystem_type(const char *desc, int weight, GtkTreeIter *iter)
|
|
|
|
{
|
|
|
|
GtkTreeModel *model;
|
|
|
|
|
|
|
|
found_match = NULL;
|
|
|
|
model = GTK_TREE_MODEL(weightsystem_model);
|
|
|
|
gtk_tree_model_foreach(model, match_desc, (void *)desc);
|
|
|
|
|
2012-08-06 19:55:55 +00:00
|
|
|
if (found_match) {
|
|
|
|
gtk_list_store_set(GTK_LIST_STORE(model), found_match,
|
|
|
|
WS_WEIGHT, weight,
|
|
|
|
-1);
|
2012-08-06 20:56:46 +00:00
|
|
|
} else if (desc && desc[0]) {
|
2012-08-06 19:55:55 +00:00
|
|
|
gtk_list_store_append(GTK_LIST_STORE(model), iter);
|
|
|
|
gtk_list_store_set(GTK_LIST_STORE(model), iter,
|
|
|
|
WS_DESC, desc,
|
|
|
|
WS_WEIGHT, weight,
|
2011-12-24 03:41:16 +00:00
|
|
|
-1);
|
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
return found_match;
|
|
|
|
}
|
|
|
|
|
2011-10-22 15:12:30 +00:00
|
|
|
/*
|
|
|
|
* When adding a dive, we'll add all the pre-existing cylinder
|
|
|
|
* information from that dive to our cylinder model.
|
|
|
|
*/
|
|
|
|
void add_cylinder_description(cylinder_type_t *type)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
const char *desc;
|
|
|
|
unsigned int size, workp;
|
|
|
|
|
|
|
|
desc = type->description;
|
|
|
|
if (!desc)
|
|
|
|
return;
|
|
|
|
size = type->size.mliter;
|
|
|
|
workp = type->workingpressure.mbar;
|
|
|
|
add_cylinder_type(desc, size, workp, &iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_cylinder(struct cylinder_widget *cylinder, const char *desc, int ml, int mbar)
|
|
|
|
{
|
2013-01-28 00:40:01 +00:00
|
|
|
GtkTreeIter iter;
|
2011-10-22 15:12:30 +00:00
|
|
|
|
|
|
|
cylinder->name = desc;
|
2013-01-28 00:40:01 +00:00
|
|
|
add_cylinder_type(desc, ml, mbar, &iter);
|
2011-09-11 00:14:07 +00:00
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
void add_weightsystem_description(weightsystem_t *weightsystem)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
const char *desc;
|
|
|
|
unsigned int weight;
|
|
|
|
|
|
|
|
desc = weightsystem->description;
|
|
|
|
if (!desc)
|
|
|
|
return;
|
|
|
|
weight = weightsystem->weight.grams;
|
|
|
|
add_weightsystem_type(desc, weight, &iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_weightsystem(struct ws_widget *ws_widget, const char *desc, int weight)
|
|
|
|
{
|
2013-01-28 00:40:01 +00:00
|
|
|
GtkTreeIter iter;
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
ws_widget->name = desc;
|
2013-01-28 00:40:01 +00:00
|
|
|
add_weightsystem_type(desc, weight, &iter);
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
|
|
|
|
2011-09-13 20:25:06 +00:00
|
|
|
static void show_cylinder(cylinder_t *cyl, struct cylinder_widget *cylinder)
|
2011-09-10 00:10:17 +00:00
|
|
|
{
|
2011-09-13 20:25:06 +00:00
|
|
|
const char *desc;
|
2011-09-11 00:14:07 +00:00
|
|
|
int ml, mbar;
|
2011-12-11 19:09:37 +00:00
|
|
|
int gasmix;
|
|
|
|
double o2, he;
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2011-09-13 20:25:06 +00:00
|
|
|
/* Don't show uninitialized cylinder widgets */
|
|
|
|
if (!cylinder->description)
|
|
|
|
return;
|
|
|
|
|
|
|
|
desc = cyl->type.description;
|
2011-09-10 23:27:19 +00:00
|
|
|
if (!desc)
|
|
|
|
desc = "";
|
2011-09-11 00:14:07 +00:00
|
|
|
ml = cyl->type.size.mliter;
|
|
|
|
mbar = cyl->type.workingpressure.mbar;
|
2011-09-13 20:15:31 +00:00
|
|
|
add_cylinder(cylinder, desc, ml, mbar);
|
2011-09-10 22:27:23 +00:00
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
set_cylinder_description(cylinder, desc);
|
2011-10-22 14:18:58 +00:00
|
|
|
set_cylinder_type_spinbuttons(cylinder,
|
|
|
|
cyl->type.size.mliter, cyl->type.workingpressure.mbar);
|
2011-11-09 16:33:13 +00:00
|
|
|
set_cylinder_pressure_spinbuttons(cylinder, cyl);
|
2011-12-11 19:09:37 +00:00
|
|
|
|
|
|
|
gasmix = cyl->gasmix.o2.permille || cyl->gasmix.he.permille;
|
|
|
|
gtk_widget_set_sensitive(cylinder->o2, gasmix);
|
|
|
|
gtk_widget_set_sensitive(cylinder->he, gasmix);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button), gasmix);
|
|
|
|
|
2011-09-10 18:09:39 +00:00
|
|
|
o2 = cyl->gasmix.o2.permille / 10.0;
|
2011-12-11 19:09:37 +00:00
|
|
|
he = cyl->gasmix.he.permille / 10.0;
|
2011-09-10 18:09:39 +00:00
|
|
|
if (!o2)
|
2013-01-14 22:53:38 +00:00
|
|
|
o2 = O2_IN_AIR / 10.0;
|
2011-09-13 20:15:31 +00:00
|
|
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->o2), o2);
|
2011-12-11 19:09:37 +00:00
|
|
|
gtk_spin_button_set_value(GTK_SPIN_BUTTON(cylinder->he), he);
|
2011-09-10 02:46:53 +00:00
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void show_weightsystem(weightsystem_t *ws, struct ws_widget *weightsystem_widget)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2011-12-24 03:41:16 +00:00
|
|
|
const char *desc;
|
|
|
|
int grams;
|
|
|
|
|
|
|
|
/* Don't show uninitialized widgets */
|
|
|
|
if (!weightsystem_widget->description)
|
|
|
|
return;
|
|
|
|
|
|
|
|
desc = ws->description;
|
|
|
|
if (!desc)
|
|
|
|
desc = "";
|
|
|
|
grams = ws->weight.grams;
|
|
|
|
add_weightsystem(weightsystem_widget, desc, grams);
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
set_weight_description(weightsystem_widget, desc);
|
2011-12-24 03:41:16 +00:00
|
|
|
set_weight_weight_spinbutton(weightsystem_widget, ws->weight.grams);
|
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
#else
|
|
|
|
/* placeholders for a few functions that we need to redesign for the Qt UI */
|
|
|
|
void add_cylinder_description(cylinder_type_t *type)
|
|
|
|
{
|
|
|
|
const char *desc;
|
|
|
|
|
|
|
|
desc = type->description;
|
|
|
|
if (!desc)
|
|
|
|
return;
|
|
|
|
/* now do something with it... */
|
|
|
|
}
|
|
|
|
void add_weightsystem_description(weightsystem_t *weightsystem)
|
|
|
|
{
|
|
|
|
const char *desc;
|
2013-09-10 18:42:26 +00:00
|
|
|
int i;
|
2013-05-03 18:04:51 +00:00
|
|
|
|
|
|
|
desc = weightsystem->description;
|
|
|
|
if (!desc)
|
|
|
|
return;
|
2013-09-10 18:42:26 +00:00
|
|
|
for (i = 0; i < 100 && ws_info[i].name != NULL; i++) {
|
|
|
|
if (strcmp(ws_info[i].name, desc) == 0) {
|
|
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < 100) {
|
|
|
|
ws_info[i].name = desc;
|
|
|
|
ws_info[i].grams = weightsystem->weight.grams;
|
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* USE_GTK_UI */
|
2011-12-24 03:41:16 +00:00
|
|
|
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
gboolean cylinder_nodata(cylinder_t *cyl)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
2011-10-02 20:13:27 +00:00
|
|
|
return !cyl->type.size.mliter &&
|
|
|
|
!cyl->type.workingpressure.mbar &&
|
|
|
|
!cyl->type.description &&
|
|
|
|
!cyl->gasmix.o2.permille &&
|
|
|
|
!cyl->gasmix.he.permille &&
|
|
|
|
!cyl->start.mbar &&
|
|
|
|
!cyl->end.mbar;
|
|
|
|
}
|
|
|
|
|
2013-01-29 21:10:46 +00:00
|
|
|
static gboolean cylinder_nosamples(cylinder_t *cyl)
|
Fix missing save of (almost empty) cylinder information
If we have no explicit cylinder info at all (it's normal air, no size or
working pressure information, and no beginning/end pressure information),
we don't save the cylinders in question because that would be redundant.
Such non-saved cylinders may still show up in the equipment list because
there may be implicit mention of them elsewhere, notably due to sample
data, so not saving them is the right thing to do - there is nothing to
save.
However, we missed one case: if there were other cylinders that *did* have
explicit information in it following such an uninteresting cylinder, we do
need to save the cylinder information for the useless case - if only in
order to be able to save the non-useless information for subsequent
cylinders.
This patch does that. Now, if you had an air-filled cylinder with no
information as your first cylinder, and a 51% nitrox as your second one,
it will save that information as
<cylinder />
<cylinder o2='51.0%' />
rather than dropping the cylinder information entirely.
This bug has been there for a long time, and was hidden by the fact that
normally you'd fill in cylinder descriptions etc after importing new
dives. It also used to be that we saved the cylinder beginning/end
pressure even if that was generated from the sample data, so if you
imported from a air-integrated computer and had samples for that cylinder,
we used to save it even though it was technically redundant.
We stopped saving redundant air sample information in commit 0089dd8819b7
("Don't save cylinder start/end pressures unless set by hand").
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Removed start and end in save_cylinder_info(). These two variables are no
longer used.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-09-21 21:06:57 +00:00
|
|
|
{
|
|
|
|
return !cyl->sample_start.mbar &&
|
|
|
|
!cyl->sample_end.mbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean cylinder_none(void *_data)
|
|
|
|
{
|
|
|
|
cylinder_t *cyl = _data;
|
|
|
|
return cylinder_nodata(cyl) && cylinder_nosamples(cyl);
|
|
|
|
}
|
|
|
|
|
2012-08-18 15:28:52 +00:00
|
|
|
/* descriptions are equal if they are both NULL or both non-NULL
|
|
|
|
and the same text */
|
2013-01-29 21:10:46 +00:00
|
|
|
static gboolean description_equal(const char *desc1, const char *desc2)
|
2012-08-18 15:28:52 +00:00
|
|
|
{
|
|
|
|
return ((! desc1 && ! desc2) ||
|
|
|
|
(desc1 && desc2 && strcmp(desc1, desc2) == 0));
|
|
|
|
}
|
|
|
|
|
2013-05-21 18:29:21 +00:00
|
|
|
gboolean weightsystem_none(void *_data)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
weightsystem_t *ws = _data;
|
|
|
|
return !ws->weight.grams && !ws->description;
|
|
|
|
}
|
|
|
|
|
2012-08-18 15:28:52 +00:00
|
|
|
gboolean no_weightsystems(weightsystem_t *ws)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_WEIGHTSYSTEMS; i++)
|
|
|
|
if (!weightsystem_none(ws + i))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean one_weightsystem_equal(weightsystem_t *ws1, weightsystem_t *ws2)
|
|
|
|
{
|
|
|
|
return ws1->weight.grams == ws2->weight.grams &&
|
|
|
|
description_equal(ws1->description, ws2->description);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean weightsystems_equal(weightsystem_t *ws1, weightsystem_t *ws2)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_WEIGHTSYSTEMS; i++)
|
|
|
|
if (!one_weightsystem_equal(ws1 + i, ws2 + i))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:04:51 +00:00
|
|
|
#if USE_GTK_UI
|
2012-03-24 04:07:53 +00:00
|
|
|
static void set_one_cylinder(void *_data, GtkListStore *model, GtkTreeIter *iter)
|
2011-10-02 23:41:17 +00:00
|
|
|
{
|
2011-12-24 03:41:16 +00:00
|
|
|
cylinder_t *cyl = _data;
|
2011-11-09 16:21:48 +00:00
|
|
|
unsigned int start, end;
|
|
|
|
|
|
|
|
start = cyl->start.mbar ? : cyl->sample_start.mbar;
|
|
|
|
end = cyl->end.mbar ? : cyl->sample_end.mbar;
|
2011-10-02 23:41:17 +00:00
|
|
|
gtk_list_store_set(model, iter,
|
|
|
|
CYL_DESC, cyl->type.description ? : "",
|
|
|
|
CYL_SIZE, cyl->type.size.mliter,
|
|
|
|
CYL_WORKP, cyl->type.workingpressure.mbar,
|
2011-11-09 16:21:48 +00:00
|
|
|
CYL_STARTP, start,
|
|
|
|
CYL_ENDP, end,
|
2011-10-02 23:41:17 +00:00
|
|
|
CYL_O2, cyl->gasmix.o2.permille,
|
|
|
|
CYL_HE, cyl->gasmix.he.permille,
|
|
|
|
-1);
|
|
|
|
}
|
|
|
|
|
2012-03-24 04:07:53 +00:00
|
|
|
static void set_one_weightsystem(void *_data, GtkListStore *model, GtkTreeIter *iter)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
weightsystem_t *ws = _data;
|
|
|
|
|
|
|
|
gtk_list_store_set(model, iter,
|
2012-10-11 00:42:59 +00:00
|
|
|
WS_DESC, ws->description ? : _("unspecified"),
|
2011-12-24 03:41:16 +00:00
|
|
|
WS_WEIGHT, ws->weight.grams,
|
|
|
|
-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *cyl_ptr(struct dive *dive, int idx)
|
|
|
|
{
|
|
|
|
if (idx < 0 || idx >= MAX_CYLINDERS)
|
|
|
|
return NULL;
|
|
|
|
return &dive->cylinder[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *ws_ptr(struct dive *dive, int idx)
|
2011-09-13 20:25:06 +00:00
|
|
|
{
|
2011-12-24 03:41:16 +00:00
|
|
|
if (idx < 0 || idx >= MAX_WEIGHTSYSTEMS)
|
|
|
|
return NULL;
|
|
|
|
return &dive->weightsystem[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_equipment(struct dive *dive, int max,
|
|
|
|
struct equipment_list *equipment_list,
|
|
|
|
void*(*ptr_function)(struct dive*, int),
|
2012-08-18 15:28:52 +00:00
|
|
|
gboolean(*none_function)(void *),
|
2012-03-24 04:07:53 +00:00
|
|
|
void(*set_one_function)(void*, GtkListStore*, GtkTreeIter *))
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
int i, used;
|
|
|
|
void *data;
|
2011-10-02 20:13:27 +00:00
|
|
|
GtkTreeIter iter;
|
2011-12-24 03:41:16 +00:00
|
|
|
GtkListStore *model = equipment_list->model;
|
2011-09-13 20:25:06 +00:00
|
|
|
|
2012-10-19 03:45:26 +00:00
|
|
|
if (! model)
|
|
|
|
return;
|
|
|
|
if (! dive) {
|
|
|
|
gtk_widget_set_sensitive(equipment_list->edit, 0);
|
|
|
|
gtk_widget_set_sensitive(equipment_list->del, 0);
|
|
|
|
gtk_widget_set_sensitive(equipment_list->add, 0);
|
2013-02-19 00:56:28 +00:00
|
|
|
clear_equipment_widgets();
|
2012-10-19 03:45:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-10-02 20:13:27 +00:00
|
|
|
gtk_list_store_clear(model);
|
2011-12-24 03:41:16 +00:00
|
|
|
used = max;
|
2011-10-02 20:13:27 +00:00
|
|
|
do {
|
2011-12-24 03:41:16 +00:00
|
|
|
data = ptr_function(dive, used-1);
|
|
|
|
if (!none_function(data))
|
2011-10-02 20:13:27 +00:00
|
|
|
break;
|
2011-12-24 03:41:16 +00:00
|
|
|
} while (--used);
|
2011-10-02 20:13:27 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
equipment_list->max_index = used;
|
2011-10-02 20:42:51 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_widget_set_sensitive(equipment_list->edit, 0);
|
|
|
|
gtk_widget_set_sensitive(equipment_list->del, 0);
|
|
|
|
gtk_widget_set_sensitive(equipment_list->add, used < max);
|
2011-10-02 20:13:27 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
for (i = 0; i < used; i++) {
|
|
|
|
data = ptr_function(dive, i);
|
2011-10-02 20:13:27 +00:00
|
|
|
gtk_list_store_append(model, &iter);
|
2012-03-24 04:07:53 +00:00
|
|
|
set_one_function(data, model, &iter);
|
2011-10-02 20:13:27 +00:00
|
|
|
}
|
2011-09-13 20:25:06 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
void show_dive_equipment(struct dive *dive, int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
2012-08-15 22:21:34 +00:00
|
|
|
show_equipment(dive, MAX_CYLINDERS, &cylinder_list[w_idx],
|
2011-12-24 03:41:16 +00:00
|
|
|
&cyl_ptr, &cylinder_none, &set_one_cylinder);
|
2012-08-15 22:21:34 +00:00
|
|
|
show_equipment(dive, MAX_WEIGHTSYSTEMS, &weightsystem_list[w_idx],
|
2011-12-24 03:41:16 +00:00
|
|
|
&ws_ptr, &weightsystem_none, &set_one_weightsystem);
|
|
|
|
}
|
|
|
|
|
2013-03-18 01:07:59 +00:00
|
|
|
int select_cylinder(struct dive *dive, int when)
|
|
|
|
{
|
|
|
|
GtkWidget *dialog, *vbox, *label;
|
|
|
|
GtkWidget *buttons[MAX_CYLINDERS] = { NULL, };
|
|
|
|
GSList *group = NULL;
|
|
|
|
int i, success, nr, selected = -1;
|
|
|
|
char buffer[256];
|
|
|
|
|
|
|
|
nr = MAX_CYLINDERS - 1;
|
|
|
|
while (nr >= 0 && cylinder_nodata(cyl_ptr(dive, nr)))
|
|
|
|
nr--;
|
|
|
|
|
|
|
|
if (nr == -1) {
|
|
|
|
dialog = gtk_dialog_new_with_buttons(_("Cannot add gas change"),
|
|
|
|
GTK_WINDOW(main_window),
|
|
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
|
|
|
NULL);
|
|
|
|
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
|
|
|
label = gtk_label_new(_("No cylinders listed for this dive."));
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show_all(dialog);
|
|
|
|
success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
snprintf(buffer, sizeof(buffer), _("Add gaschange event at %d:%02u"), FRACTION(when, 60));
|
|
|
|
dialog = gtk_dialog_new_with_buttons(buffer,
|
|
|
|
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));
|
|
|
|
label = gtk_label_new(_("Available gases"));
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
|
|
|
|
for (i = 0; i <= nr; i++) {
|
|
|
|
char gas_buf[80];
|
|
|
|
cylinder_t *cyl = cyl_ptr(dive, i);
|
|
|
|
get_gas_string(cyl->gasmix.o2.permille, cyl->gasmix.he.permille, gas_buf, sizeof(gas_buf));
|
|
|
|
snprintf(buffer, sizeof(buffer), "%s: %s",
|
|
|
|
dive->cylinder[i].type.description ?: _("unknown"), gas_buf);
|
|
|
|
buttons[i] = gtk_radio_button_new_with_label(group, buffer);
|
|
|
|
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(buttons[i]));
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), buttons[i], FALSE, FALSE, 0);
|
|
|
|
}
|
|
|
|
gtk_widget_show_all(dialog);
|
|
|
|
success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
|
|
|
|
if (success) {
|
|
|
|
for (i = 0; i <= nr; i++)
|
|
|
|
if (buttons[i] && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i])))
|
|
|
|
selected = i;
|
|
|
|
}
|
|
|
|
for (i = 0; i <= nr; i++)
|
|
|
|
if (buttons[i])
|
|
|
|
gtk_widget_destroy(buttons[i]);
|
|
|
|
bail:
|
|
|
|
gtk_widget_destroy(dialog);
|
|
|
|
|
|
|
|
return selected;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-09-10 18:09:39 +00:00
|
|
|
static GtkWidget *create_spinbutton(GtkWidget *vbox, const char *name, double min, double max, double incr)
|
2011-09-10 02:46:53 +00:00
|
|
|
{
|
2011-09-11 22:37:56 +00:00
|
|
|
GtkWidget *frame, *hbox, *button;
|
2011-09-10 02:46:53 +00:00
|
|
|
|
|
|
|
frame = gtk_frame_new(name);
|
2011-10-17 18:12:11 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, FALSE, 0);
|
2011-09-11 22:37:56 +00:00
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
2011-09-10 02:46:53 +00:00
|
|
|
|
2011-09-10 18:09:39 +00:00
|
|
|
button = gtk_spin_button_new_with_range(min, max, incr);
|
2011-10-17 18:12:11 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0);
|
2011-09-10 02:46:53 +00:00
|
|
|
|
2011-09-10 18:09:39 +00:00
|
|
|
gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(button), GTK_UPDATE_IF_VALID);
|
|
|
|
|
2011-09-10 02:46:53 +00:00
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:12:11 +00:00
|
|
|
static void fill_cylinder_info(struct cylinder_widget *cylinder, cylinder_t *cyl, const char *desc,
|
2011-12-11 19:09:37 +00:00
|
|
|
double volume, double pressure, double start, double end, int o2, int he)
|
2011-09-10 02:46:53 +00:00
|
|
|
{
|
2011-09-10 22:27:23 +00:00
|
|
|
int mbar, ml;
|
|
|
|
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.pressure == PSI) {
|
2011-11-02 04:00:46 +00:00
|
|
|
pressure = psi_to_bar(pressure);
|
|
|
|
start = psi_to_bar(start);
|
|
|
|
end = psi_to_bar(end);
|
2011-10-17 18:12:11 +00:00
|
|
|
}
|
2011-09-10 22:27:23 +00:00
|
|
|
|
gtk spinbuttons are crazy - fix possible divide-by-zero
When we fill the cylinder information in an imperial unit world, a
working pressure of zero is a special case, and forces us to use the
actual physical size of the cylinder in liter, despite the fact that
we normally would use cuft.
However, we compare that value against zero in a 'double', and in
between going through the gtk spinbutton logic, the zero we have
filled in then gets read out as some very tiny epsilon value from the
gtk spinbuttons (typically in the 10**-317 range). This causes us to
think that the zero isn't actually a zero, because gtk has done odd
things with it.
Fix this by calculating the millibar value (as an integer) first, and
check that *integer* against zero. Any crazy epsilon values will have
been rounded away, and our logic works again.
There's a good reason why subsurface does everything using integers
(ie the afore-mentioned "convert to integer millibar" etc) and doesn't
use floating point for any core data structures, only for conversion.
FP rounding and inexact behavior can be really subtle.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2012-11-10 14:12:58 +00:00
|
|
|
mbar = pressure * 1000 + 0.5;
|
2013-01-11 01:26:10 +00:00
|
|
|
if (mbar && prefs.units.volume == CUFT) {
|
2011-11-02 04:12:21 +00:00
|
|
|
volume = cuft_to_l(volume);
|
2011-11-02 04:00:46 +00:00
|
|
|
volume /= bar_to_atm(pressure);
|
2011-09-10 22:27:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ml = volume * 1000 + 0.5;
|
|
|
|
|
2011-12-11 19:09:37 +00:00
|
|
|
/* Ignore obviously crazy He values */
|
|
|
|
if (o2 + he > 1000)
|
|
|
|
he = 0;
|
|
|
|
|
|
|
|
/* We have a rule that normal air is all zeroes */
|
|
|
|
if (!he && o2 > 208 && o2 < 211)
|
2011-09-10 18:09:39 +00:00
|
|
|
o2 = 0;
|
2011-12-11 19:09:37 +00:00
|
|
|
|
2011-09-10 02:46:53 +00:00
|
|
|
cyl->type.description = desc;
|
2011-09-10 22:27:23 +00:00
|
|
|
cyl->type.size.mliter = ml;
|
2011-09-10 02:46:53 +00:00
|
|
|
cyl->type.workingpressure.mbar = mbar;
|
2011-10-17 18:12:11 +00:00
|
|
|
cyl->start.mbar = start * 1000 + 0.5;
|
|
|
|
cyl->end.mbar = end * 1000 + 0.5;
|
2011-09-10 18:09:39 +00:00
|
|
|
cyl->gasmix.o2.permille = o2;
|
2011-12-11 19:09:37 +00:00
|
|
|
cyl->gasmix.he.permille = he;
|
2011-09-10 23:27:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Also, insert it into the model if it doesn't already exist
|
|
|
|
*/
|
2013-04-13 13:17:59 +00:00
|
|
|
// WARNING: GTK-Specific Code.
|
2011-09-13 20:15:31 +00:00
|
|
|
add_cylinder(cylinder, desc, ml, mbar);
|
2011-09-10 00:10:17 +00:00
|
|
|
}
|
|
|
|
|
2011-09-13 20:25:06 +00:00
|
|
|
static void record_cylinder_changes(cylinder_t *cyl, struct cylinder_widget *cylinder)
|
2011-09-10 00:10:17 +00:00
|
|
|
{
|
2011-09-10 02:46:53 +00:00
|
|
|
const gchar *desc;
|
2011-09-13 20:25:06 +00:00
|
|
|
GtkComboBox *box;
|
2011-10-17 18:12:11 +00:00
|
|
|
double volume, pressure, start, end;
|
2011-12-11 19:09:37 +00:00
|
|
|
int o2, he;
|
2011-09-10 02:46:53 +00:00
|
|
|
|
2011-09-13 20:25:06 +00:00
|
|
|
/* Ignore uninitialized cylinder widgets */
|
|
|
|
box = cylinder->description;
|
|
|
|
if (!box)
|
|
|
|
return;
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
desc = strdup(get_active_text(box));
|
2011-09-13 20:15:31 +00:00
|
|
|
volume = gtk_spin_button_get_value(cylinder->size);
|
|
|
|
pressure = gtk_spin_button_get_value(cylinder->pressure);
|
2011-11-13 17:29:07 +00:00
|
|
|
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));
|
2011-11-13 17:51:34 +00:00
|
|
|
} else {
|
2011-11-09 16:51:20 +00:00
|
|
|
start = end = 0;
|
2011-11-13 17:51:34 +00:00
|
|
|
}
|
2011-12-11 19:09:37 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder->gasmix_button))) {
|
2011-11-13 17:29:07 +00:00
|
|
|
o2 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->o2))*10 + 0.5;
|
2011-12-11 19:09:37 +00:00
|
|
|
he = gtk_spin_button_get_value(GTK_SPIN_BUTTON(cylinder->he))*10 + 0.5;
|
|
|
|
} else {
|
2011-09-13 18:47:20 +00:00
|
|
|
o2 = 0;
|
2011-12-11 19:09:37 +00:00
|
|
|
he = 0;
|
|
|
|
}
|
|
|
|
fill_cylinder_info(cylinder, cyl, desc, volume, pressure, start, end, o2, he);
|
2011-09-10 04:39:54 +00:00
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void record_weightsystem_changes(weightsystem_t *ws, struct ws_widget *weightsystem_widget)
|
|
|
|
{
|
|
|
|
const gchar *desc;
|
|
|
|
GtkComboBox *box;
|
|
|
|
int grams;
|
|
|
|
double value;
|
2012-08-06 19:55:55 +00:00
|
|
|
GtkTreeIter iter;
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
/* Ignore uninitialized cylinder widgets */
|
|
|
|
box = weightsystem_widget->description;
|
|
|
|
if (!box)
|
|
|
|
return;
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
desc = strdup(get_active_text(box));
|
2011-12-24 03:41:16 +00:00
|
|
|
value = gtk_spin_button_get_value(weightsystem_widget->weight);
|
|
|
|
|
2013-01-11 01:26:10 +00:00
|
|
|
if (prefs.units.weight == LBS)
|
2011-12-24 03:41:16 +00:00
|
|
|
grams = lbs_to_grams(value);
|
|
|
|
else
|
|
|
|
grams = value * 1000;
|
|
|
|
ws->weight.grams = grams;
|
|
|
|
ws->description = desc;
|
2012-08-06 19:55:55 +00:00
|
|
|
add_weightsystem_type(desc, grams, &iter);
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
#endif /* USE_GTK_UI */
|
2011-09-11 00:14:07 +00:00
|
|
|
/*
|
|
|
|
* We hardcode the most common standard cylinders,
|
|
|
|
* we should pick up any other names from the dive
|
|
|
|
* logs directly.
|
|
|
|
*/
|
2013-04-15 18:04:35 +00:00
|
|
|
struct tank_info tank_info[100] = {
|
2011-09-11 00:14:07 +00:00
|
|
|
/* Need an empty entry for the no-cylinder case */
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
{ "", },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
/* Size-only metric cylinders */
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
{ "10.0 l", .ml = 10000 },
|
|
|
|
{ "11.1 l", .ml = 11100 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
/* Most common AL cylinders */
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
{ "AL50", .cuft = 50, .psi = 3000 },
|
|
|
|
{ "AL63", .cuft = 63, .psi = 3000 },
|
|
|
|
{ "AL72", .cuft = 72, .psi = 3000 },
|
|
|
|
{ "AL80", .cuft = 80, .psi = 3000 },
|
|
|
|
{ "AL100", .cuft = 100, .psi = 3300 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
/* Somewhat common LP steel cylinders */
|
2012-04-01 22:38:52 +00:00
|
|
|
{ "LP85", .cuft = 85, .psi = 2640 },
|
|
|
|
{ "LP95", .cuft = 95, .psi = 2640 },
|
|
|
|
{ "LP108", .cuft = 108, .psi = 2640 },
|
|
|
|
{ "LP121", .cuft = 121, .psi = 2640 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
|
|
|
/* Somewhat common HP steel cylinders */
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
{ "HP65", .cuft = 65, .psi = 3442 },
|
|
|
|
{ "HP80", .cuft = 80, .psi = 3442 },
|
|
|
|
{ "HP100", .cuft = 100, .psi = 3442 },
|
|
|
|
{ "HP119", .cuft = 119, .psi = 3442 },
|
|
|
|
{ "HP130", .cuft = 130, .psi = 3442 },
|
2011-09-11 00:14:07 +00:00
|
|
|
|
2011-12-11 20:03:55 +00:00
|
|
|
/* Common European steel cylinders */
|
|
|
|
{ "10L 300 bar", .ml = 10000, .bar = 300 },
|
|
|
|
{ "12L 200 bar", .ml = 12000, .bar = 200 },
|
|
|
|
{ "12L 232 bar", .ml = 12000, .bar = 232 },
|
|
|
|
{ "12L 300 bar", .ml = 12000, .bar = 300 },
|
|
|
|
{ "15L 200 bar", .ml = 15000, .bar = 200 },
|
|
|
|
{ "15L 232 bar", .ml = 15000, .bar = 232 },
|
|
|
|
{ "D7 300 bar", .ml = 14000, .bar = 300 },
|
|
|
|
{ "D8.5 232 bar", .ml = 17000, .bar = 232 },
|
|
|
|
{ "D12 232 bar", .ml = 24000, .bar = 232 },
|
|
|
|
|
2011-09-11 00:14:07 +00:00
|
|
|
/* We'll fill in more from the dive log dynamically */
|
2011-09-09 15:38:48 +00:00
|
|
|
{ NULL, }
|
|
|
|
};
|
|
|
|
|
2013-05-03 18:04:51 +00:00
|
|
|
#if USE_GTK_UI
|
2011-09-09 15:38:48 +00:00
|
|
|
static void fill_tank_list(GtkListStore *store)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
struct tank_info *info = tank_info;
|
|
|
|
|
2012-04-01 22:38:52 +00:00
|
|
|
for (info = tank_info ; info->name; info++) {
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
int ml = info->ml;
|
|
|
|
int cuft = info->cuft;
|
2011-09-09 15:38:48 +00:00
|
|
|
int psi = info->psi;
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
int mbar;
|
|
|
|
double bar = info->bar;
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2012-04-01 22:38:52 +00:00
|
|
|
if (psi && bar)
|
|
|
|
goto bad_tank_info;
|
|
|
|
if (ml && cuft)
|
|
|
|
goto bad_tank_info;
|
|
|
|
if (cuft && !psi)
|
|
|
|
goto bad_tank_info;
|
|
|
|
|
2011-09-09 15:38:48 +00:00
|
|
|
/* Is it in cuft and psi? */
|
2012-04-01 22:38:52 +00:00
|
|
|
if (psi)
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
bar = psi_to_bar(psi);
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2012-04-01 22:38:52 +00:00
|
|
|
if (cuft) {
|
|
|
|
double airvolume = cuft_to_l(cuft) * 1000.0;
|
|
|
|
double atm = bar_to_atm(bar);
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
|
2012-04-01 22:38:52 +00:00
|
|
|
ml = airvolume / atm + 0.5;
|
2011-09-09 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
Clean up reference tank information table
This makes the reference tanks ("struct tank_info") use a saner format
which specifies explicitly whether the size is in ml or cubic feet, and
whether the pressure is in psi or bar.
So instead of having magic rules ("size is in cuft if < 1000, otherwise
mliter"), just set the size explicitly:
{ "11.1 l", .ml = 11100 },
{ "AL80", .cuft = 80, .psi = 3000 },
and then the code can just convert to standard measurements without any
odd rules, and the initialization table becomes self-explanatory too.
This is in preparation for doing the metric tanks with pressure: Henrik
Aronsen sent a really ugly patch using the previous setup, I just
couldn't stand the additional hackery.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-12-11 19:54:17 +00:00
|
|
|
mbar = bar * 1000 + 0.5;
|
|
|
|
|
2011-09-09 15:38:48 +00:00
|
|
|
gtk_list_store_append(store, &iter);
|
|
|
|
gtk_list_store_set(store, &iter,
|
|
|
|
0, info->name,
|
|
|
|
1, ml,
|
|
|
|
2, mbar,
|
|
|
|
-1);
|
2012-04-01 22:38:52 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
bad_tank_info:
|
|
|
|
fprintf(stderr, "Bad tank info for '%s'\n", info->name);
|
2011-09-09 15:38:48 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-24 01:38:45 +00:00
|
|
|
#endif /* USE_GTK_UI */
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
/*
|
|
|
|
* We hardcode the most common weight system types
|
|
|
|
* This is a bit odd as the weight system types don't usually encode weight
|
|
|
|
*/
|
2013-05-24 01:38:45 +00:00
|
|
|
struct ws_info ws_info[100] = {
|
2012-10-11 00:42:59 +00:00
|
|
|
{ N_("integrated"), 0 },
|
|
|
|
{ N_("belt"), 0 },
|
|
|
|
{ N_("ankle"), 0 },
|
2012-10-19 02:45:16 +00:00
|
|
|
{ N_("backplate weight"), 0 },
|
2012-10-11 00:42:59 +00:00
|
|
|
{ N_("clip-on"), 0 },
|
2011-12-24 03:41:16 +00:00
|
|
|
};
|
|
|
|
|
2013-05-24 01:38:45 +00:00
|
|
|
#if USE_GTK_UI
|
2011-12-24 03:41:16 +00:00
|
|
|
static void fill_ws_list(GtkListStore *store)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
struct ws_info *info = ws_info;
|
|
|
|
|
|
|
|
while (info->name) {
|
|
|
|
gtk_list_store_append(store, &iter);
|
|
|
|
gtk_list_store_set(store, &iter,
|
2012-10-11 00:42:59 +00:00
|
|
|
0, _(info->name),
|
2011-12-24 03:41:16 +00:00
|
|
|
1, info->grams,
|
|
|
|
-1);
|
|
|
|
info++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-11 19:09:37 +00:00
|
|
|
static void gasmix_cb(GtkToggleButton *button, gpointer data)
|
2011-09-13 18:47:20 +00:00
|
|
|
{
|
2011-09-13 20:15:31 +00:00
|
|
|
struct cylinder_widget *cylinder = data;
|
2011-09-13 18:47:20 +00:00
|
|
|
int state;
|
|
|
|
|
|
|
|
state = gtk_toggle_button_get_active(button);
|
2011-09-13 20:15:31 +00:00
|
|
|
gtk_widget_set_sensitive(cylinder->o2, state);
|
2011-12-11 19:09:37 +00:00
|
|
|
gtk_widget_set_sensitive(cylinder->he, state);
|
2011-09-13 18:47:20 +00:00
|
|
|
}
|
|
|
|
|
2011-11-09 16:51:20 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-10-23 06:45:35 +00:00
|
|
|
static void cylinder_activate_cb(GtkComboBox *combo_box, gpointer data)
|
|
|
|
{
|
|
|
|
struct cylinder_widget *cylinder = data;
|
|
|
|
cylinder_cb(cylinder->description, data);
|
|
|
|
}
|
|
|
|
|
2011-12-11 19:09:37 +00:00
|
|
|
/* Return a frame containing a hbox inside a hbox */
|
|
|
|
static GtkWidget *frame_box(const char *title, GtkWidget *vbox)
|
|
|
|
{
|
|
|
|
GtkWidget *hbox, *frame;
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 10);
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, FALSE, 0);
|
|
|
|
|
|
|
|
frame = gtk_frame_new(title);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, FALSE, 0);
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 10);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
|
|
|
|
|
|
|
return hbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkWidget *labeled_spinbutton(GtkWidget *box, const char *name, double min, double max, double incr)
|
|
|
|
{
|
|
|
|
GtkWidget *hbox, *label, *button;
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, FALSE, 0);
|
|
|
|
|
|
|
|
label = gtk_label_new(name);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
|
|
|
|
|
|
|
|
button = gtk_spin_button_new_with_range(min, max, incr);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-10-02 23:16:08 +00:00
|
|
|
static void cylinder_widget(GtkWidget *vbox, struct cylinder_widget *cylinder, GtkListStore *model)
|
2011-09-09 15:38:48 +00:00
|
|
|
{
|
2011-10-02 23:16:08 +00:00
|
|
|
GtkWidget *frame, *hbox;
|
2011-09-10 18:09:39 +00:00
|
|
|
GtkWidget *widget;
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2011-10-17 18:12:11 +00:00
|
|
|
/*
|
|
|
|
* Cylinder type: description, size and
|
|
|
|
* working pressure
|
|
|
|
*/
|
2012-10-11 00:42:59 +00:00
|
|
|
frame = gtk_frame_new(_("Cylinder"));
|
2011-09-13 20:15:31 +00:00
|
|
|
|
2011-09-11 22:37:56 +00:00
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
2011-10-02 23:16:08 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
widget = combo_box_with_model_and_entry(model);
|
2011-10-02 23:16:08 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
|
2011-09-10 18:09:39 +00:00
|
|
|
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->description = GTK_COMBO_BOX(widget);
|
|
|
|
g_signal_connect(widget, "changed", G_CALLBACK(cylinder_cb), cylinder);
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
g_signal_connect(get_entry(GTK_COMBO_BOX(widget)), "activate", G_CALLBACK(cylinder_activate_cb), cylinder);
|
2011-10-22 16:39:03 +00:00
|
|
|
|
2011-10-02 23:16:08 +00:00
|
|
|
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);
|
|
|
|
|
2012-10-15 03:43:32 +00:00
|
|
|
widget = create_spinbutton(hbox, _("Size"), 0, 300, 0.1);
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->size = GTK_SPIN_BUTTON(widget);
|
2011-09-10 04:39:54 +00:00
|
|
|
|
2012-10-15 03:43:32 +00:00
|
|
|
widget = create_spinbutton(hbox, _("Pressure"), 0, 5000, 1);
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->pressure = GTK_SPIN_BUTTON(widget);
|
2011-09-10 02:46:53 +00:00
|
|
|
|
2011-10-17 18:12:11 +00:00
|
|
|
/*
|
|
|
|
* Cylinder start/end pressures
|
|
|
|
*/
|
2012-10-11 00:42:59 +00:00
|
|
|
hbox = frame_box(_("Pressure"), vbox);
|
2011-10-17 18:12:11 +00:00
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
widget = labeled_spinbutton(hbox, _("Start"), 0, 5000, 1);
|
2011-11-09 16:37:49 +00:00
|
|
|
cylinder->start = widget;
|
2011-10-17 18:12:11 +00:00
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
widget = labeled_spinbutton(hbox, _("End"), 0, 5000, 1);
|
2011-11-09 16:37:49 +00:00
|
|
|
cylinder->end = widget;
|
2011-10-17 18:12:11 +00:00
|
|
|
|
2011-12-11 19:09:37 +00:00
|
|
|
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);
|
|
|
|
|
2011-10-17 18:12:11 +00:00
|
|
|
/*
|
|
|
|
* Cylinder gas mix: Air, Nitrox or Trimix
|
|
|
|
*/
|
2012-10-11 00:42:59 +00:00
|
|
|
hbox = frame_box(_("Gasmix"), vbox);
|
2011-10-17 18:12:11 +00:00
|
|
|
|
2011-12-11 19:09:37 +00:00
|
|
|
widget = labeled_spinbutton(hbox, "O"UTF8_SUBSCRIPT_2 "%", 1, 100, 0.1);
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->o2 = widget;
|
2011-12-11 19:09:37 +00:00
|
|
|
widget = labeled_spinbutton(hbox, "He%", 0, 100, 0.1);
|
|
|
|
cylinder->he = widget;
|
2011-09-13 20:15:31 +00:00
|
|
|
cylinder->gasmix_button = gtk_check_button_new();
|
2011-12-11 19:09:37 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), cylinder->gasmix_button, FALSE, FALSE, 3);
|
|
|
|
g_signal_connect(cylinder->gasmix_button, "toggled", G_CALLBACK(gasmix_cb), cylinder);
|
2011-09-09 15:38:48 +00:00
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void weight_activate_cb(GtkComboBox *combo_box, gpointer data)
|
|
|
|
{
|
|
|
|
struct ws_widget *ws_widget = data;
|
|
|
|
weight_cb(ws_widget->description, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ws_widget(GtkWidget *vbox, struct ws_widget *ws_widget, GtkListStore *model)
|
|
|
|
{
|
|
|
|
GtkWidget *frame, *hbox;
|
|
|
|
GtkWidget *widget;
|
|
|
|
GtkEntry *entry;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* weight_system: description and weight
|
|
|
|
*/
|
2012-10-11 00:42:59 +00:00
|
|
|
frame = gtk_frame_new(_("Weight"));
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
widget = combo_box_with_model_and_entry(model);
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
|
|
|
|
|
|
|
|
ws_widget->description = GTK_COMBO_BOX(widget);
|
|
|
|
g_signal_connect(widget, "changed", G_CALLBACK(weight_cb), ws_widget);
|
|
|
|
|
2013-01-28 00:40:01 +00:00
|
|
|
entry = get_entry(GTK_COMBO_BOX(widget));
|
2011-12-24 03:41:16 +00:00
|
|
|
g_signal_connect(entry, "activate", G_CALLBACK(weight_activate_cb), ws_widget);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2013-01-29 21:10:46 +00:00
|
|
|
if (prefs.units.weight == KG)
|
2012-10-18 21:45:36 +00:00
|
|
|
widget = create_spinbutton(hbox, _("kg"), 0, 50, 0.5);
|
2011-12-24 03:41:16 +00:00
|
|
|
else
|
2012-10-18 21:45:36 +00:00
|
|
|
widget = create_spinbutton(hbox, _("lbs"), 0, 110, 1);
|
2011-12-24 03:41:16 +00:00
|
|
|
ws_widget->weight = GTK_SPIN_BUTTON(widget);
|
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static int edit_cylinder_dialog(GtkWidget *w, int index, cylinder_t *cyl, int w_idx)
|
2011-10-02 20:42:51 +00:00
|
|
|
{
|
2011-10-03 00:16:50 +00:00
|
|
|
int success;
|
2012-09-29 18:13:05 +00:00
|
|
|
GtkWidget *dialog, *vbox, *parent;
|
2011-10-03 00:16:50 +00:00
|
|
|
struct cylinder_widget cylinder;
|
2011-10-02 23:41:17 +00:00
|
|
|
struct dive *dive;
|
|
|
|
|
|
|
|
cylinder.index = index;
|
2012-09-14 03:41:21 +00:00
|
|
|
cylinder.w_idx = w_idx;
|
2011-10-02 23:41:17 +00:00
|
|
|
cylinder.changed = 0;
|
2011-10-02 23:16:08 +00:00
|
|
|
|
2012-09-11 20:37:06 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
2011-10-03 00:16:50 +00:00
|
|
|
if (!dive)
|
|
|
|
return 0;
|
|
|
|
*cyl = dive->cylinder[index];
|
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
dialog = gtk_dialog_new_with_buttons(_("Cylinder"),
|
2011-10-02 23:16:08 +00:00
|
|
|
GTK_WINDOW(main_window),
|
|
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
|
|
|
|
NULL);
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
parent = gtk_widget_get_ancestor(w, GTK_TYPE_DIALOG);
|
|
|
|
if (parent) {
|
|
|
|
gtk_widget_set_sensitive(parent, FALSE);
|
|
|
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
|
|
|
|
}
|
|
|
|
|
2011-10-02 23:16:08 +00:00
|
|
|
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
2011-10-02 23:41:17 +00:00
|
|
|
cylinder_widget(vbox, &cylinder, cylinder_model);
|
|
|
|
|
|
|
|
show_cylinder(cyl, &cylinder);
|
2011-10-02 23:16:08 +00:00
|
|
|
|
|
|
|
gtk_widget_show_all(dialog);
|
2011-10-03 00:16:50 +00:00
|
|
|
success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
|
|
|
|
if (success) {
|
2011-10-02 23:41:17 +00:00
|
|
|
record_cylinder_changes(cyl, &cylinder);
|
2011-10-03 00:16:50 +00:00
|
|
|
dive->cylinder[index] = *cyl;
|
2012-09-11 20:37:06 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY) {
|
|
|
|
mark_divelist_changed(TRUE);
|
|
|
|
update_cylinder_related_info(dive);
|
|
|
|
flush_divelist(dive);
|
|
|
|
}
|
2011-10-02 23:16:08 +00:00
|
|
|
}
|
2011-10-03 00:16:50 +00:00
|
|
|
|
2011-10-02 23:16:08 +00:00
|
|
|
gtk_widget_destroy(dialog);
|
2012-09-29 18:13:05 +00:00
|
|
|
if (parent)
|
|
|
|
gtk_widget_set_sensitive(parent, TRUE);
|
2011-10-03 00:16:50 +00:00
|
|
|
return success;
|
2011-10-02 20:42:51 +00:00
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static int edit_weightsystem_dialog(GtkWidget *w, int index, weightsystem_t *ws, int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
int success;
|
2012-09-29 18:13:05 +00:00
|
|
|
GtkWidget *dialog, *vbox, *parent;
|
2011-12-24 03:41:16 +00:00
|
|
|
struct ws_widget weightsystem_widget;
|
|
|
|
struct dive *dive;
|
|
|
|
|
|
|
|
weightsystem_widget.index = index;
|
2012-09-14 03:41:21 +00:00
|
|
|
weightsystem_widget.w_idx = w_idx;
|
2011-12-24 03:41:16 +00:00
|
|
|
weightsystem_widget.changed = 0;
|
|
|
|
|
2012-09-11 20:37:06 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
2011-12-24 03:41:16 +00:00
|
|
|
if (!dive)
|
|
|
|
return 0;
|
|
|
|
*ws = dive->weightsystem[index];
|
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
dialog = gtk_dialog_new_with_buttons(_("Weight System"),
|
2011-12-24 03:41:16 +00:00
|
|
|
GTK_WINDOW(main_window),
|
|
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
|
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
|
|
|
|
NULL);
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
parent = gtk_widget_get_ancestor(w, GTK_TYPE_DIALOG);
|
|
|
|
if (parent) {
|
|
|
|
gtk_widget_set_sensitive(parent, FALSE);
|
|
|
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
|
|
|
ws_widget(vbox, &weightsystem_widget, weightsystem_model);
|
|
|
|
|
|
|
|
show_weightsystem(ws, &weightsystem_widget);
|
|
|
|
|
|
|
|
gtk_widget_show_all(dialog);
|
|
|
|
success = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT;
|
|
|
|
if (success) {
|
|
|
|
record_weightsystem_changes(ws, &weightsystem_widget);
|
|
|
|
dive->weightsystem[index] = *ws;
|
2012-09-11 20:37:06 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY) {
|
|
|
|
mark_divelist_changed(TRUE);
|
|
|
|
flush_divelist(dive);
|
|
|
|
}
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy(dialog);
|
2012-09-29 18:13:05 +00:00
|
|
|
if (parent)
|
|
|
|
gtk_widget_set_sensitive(parent, TRUE);
|
2011-12-24 03:41:16 +00:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2011-10-03 02:14:00 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static void edit_cb(GtkWidget *w, int w_idx)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2011-10-02 20:42:51 +00:00
|
|
|
int index;
|
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = cylinder_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
|
2011-10-02 20:42:51 +00:00
|
|
|
GtkTreeSelection *selection;
|
2011-10-03 00:16:50 +00:00
|
|
|
cylinder_t cyl;
|
2011-10-02 20:42:51 +00:00
|
|
|
|
2011-11-19 19:47:04 +00:00
|
|
|
selection = gtk_tree_view_get_selection(tree_view);
|
2011-10-02 20:42:51 +00:00
|
|
|
|
|
|
|
/* Nothing selected? This shouldn't happen, since the button should be inactive */
|
|
|
|
if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
|
|
|
|
return;
|
|
|
|
|
2011-10-03 02:14:00 +00:00
|
|
|
index = get_model_index(model, &iter);
|
2012-09-29 18:13:05 +00:00
|
|
|
if (!edit_cylinder_dialog(w, index, &cyl, w_idx))
|
2011-10-03 00:16:50 +00:00
|
|
|
return;
|
|
|
|
|
2012-01-05 16:12:57 +00:00
|
|
|
set_one_cylinder(&cyl, model, &iter);
|
2011-10-21 13:14:45 +00:00
|
|
|
repaint_dive();
|
2011-10-02 20:13:27 +00:00
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static void add_cb(GtkWidget *w, int w_idx)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2012-08-15 22:21:34 +00:00
|
|
|
int index = cylinder_list[w_idx].max_index;
|
2011-10-02 20:42:51 +00:00
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = cylinder_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
|
2011-10-02 23:16:08 +00:00
|
|
|
GtkTreeSelection *selection;
|
2011-10-03 00:16:50 +00:00
|
|
|
cylinder_t cyl;
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
if (!edit_cylinder_dialog(w, index, &cyl, w_idx))
|
2011-10-03 00:16:50 +00:00
|
|
|
return;
|
2011-10-02 20:42:51 +00:00
|
|
|
|
|
|
|
gtk_list_store_append(model, &iter);
|
2012-01-05 16:12:57 +00:00
|
|
|
set_one_cylinder(&cyl, model, &iter);
|
2011-10-02 23:16:08 +00:00
|
|
|
|
2011-11-19 19:47:04 +00:00
|
|
|
selection = gtk_tree_view_get_selection(tree_view);
|
2011-10-02 23:16:08 +00:00
|
|
|
gtk_tree_selection_select_iter(selection, &iter);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
cylinder_list[w_idx].max_index++;
|
|
|
|
gtk_widget_set_sensitive(cylinder_list[w_idx].add, cylinder_list[w_idx].max_index < MAX_CYLINDERS);
|
2011-10-02 20:13:27 +00:00
|
|
|
}
|
2013-05-22 17:02:28 +00:00
|
|
|
#endif /* USE_GTK_UI */
|
2011-10-02 20:13:27 +00:00
|
|
|
|
2013-05-22 17:02:28 +00:00
|
|
|
void remove_cylinder(struct dive *dive, int idx)
|
|
|
|
{
|
|
|
|
cylinder_t *cyl = dive->cylinder + idx;
|
|
|
|
int nr = MAX_CYLINDERS - idx - 1;
|
|
|
|
memmove(cyl, cyl + 1, nr * sizeof(*cyl));
|
|
|
|
memset(cyl + nr, 0, sizeof(*cyl));
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove_weightsystem(struct dive *dive, int idx)
|
|
|
|
{
|
|
|
|
weightsystem_t *ws = dive->weightsystem + idx;
|
|
|
|
int nr = MAX_WEIGHTSYSTEMS - idx - 1;
|
|
|
|
memmove(ws, ws + 1, nr * sizeof(*ws));
|
|
|
|
memset(ws + nr, 0, sizeof(*ws));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if USE_GTK_UI
|
2012-08-15 22:21:34 +00:00
|
|
|
static void del_cb(GtkButton *button, int w_idx)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2011-10-02 23:58:53 +00:00
|
|
|
int index, nr;
|
2011-10-02 23:16:08 +00:00
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = cylinder_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = cylinder_list[w_idx].tree_view;
|
2011-10-02 23:16:08 +00:00
|
|
|
GtkTreeSelection *selection;
|
2011-10-02 23:58:53 +00:00
|
|
|
struct dive *dive;
|
|
|
|
cylinder_t *cyl;
|
2011-10-02 23:16:08 +00:00
|
|
|
|
2011-11-19 19:47:04 +00:00
|
|
|
selection = gtk_tree_view_get_selection(tree_view);
|
2011-10-02 23:16:08 +00:00
|
|
|
|
|
|
|
/* Nothing selected? This shouldn't happen, since the button should be inactive */
|
|
|
|
if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
|
|
|
|
return;
|
|
|
|
|
2011-10-03 02:14:00 +00:00
|
|
|
index = get_model_index(model, &iter);
|
2011-10-02 23:58:53 +00:00
|
|
|
|
2012-09-14 03:41:21 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
2011-10-02 23:58:53 +00:00
|
|
|
if (!dive)
|
|
|
|
return;
|
|
|
|
cyl = dive->cylinder + index;
|
2012-08-15 22:21:34 +00:00
|
|
|
nr = cylinder_list[w_idx].max_index - index - 1;
|
2011-10-02 23:58:53 +00:00
|
|
|
|
2011-10-03 02:14:00 +00:00
|
|
|
gtk_list_store_remove(model, &iter);
|
2011-10-02 23:16:08 +00:00
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
cylinder_list[w_idx].max_index--;
|
2011-10-02 23:58:53 +00:00
|
|
|
memmove(cyl, cyl+1, nr*sizeof(*cyl));
|
|
|
|
memset(cyl+nr, 0, sizeof(*cyl));
|
|
|
|
|
|
|
|
mark_divelist_changed(TRUE);
|
|
|
|
flush_divelist(dive);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
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);
|
2011-10-02 20:13:27 +00:00
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static void ws_edit_cb(GtkWidget *w, int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
int index;
|
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = weightsystem_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
|
2011-12-24 03:41:16 +00:00
|
|
|
GtkTreeSelection *selection;
|
|
|
|
weightsystem_t ws;
|
|
|
|
|
|
|
|
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))
|
|
|
|
return;
|
|
|
|
|
|
|
|
index = get_model_index(model, &iter);
|
2012-09-29 18:13:05 +00:00
|
|
|
if (!edit_weightsystem_dialog(w, index, &ws, w_idx))
|
2011-12-24 03:41:16 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-24 04:07:53 +00:00
|
|
|
set_one_weightsystem(&ws, model, &iter);
|
2011-12-24 03:41:16 +00:00
|
|
|
repaint_dive();
|
|
|
|
}
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
static void ws_add_cb(GtkWidget *w, int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
2012-08-15 22:21:34 +00:00
|
|
|
int index = weightsystem_list[w_idx].max_index;
|
2011-12-24 03:41:16 +00:00
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = weightsystem_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
|
2011-12-24 03:41:16 +00:00
|
|
|
GtkTreeSelection *selection;
|
|
|
|
weightsystem_t ws;
|
|
|
|
|
2012-09-29 18:13:05 +00:00
|
|
|
if (!edit_weightsystem_dialog(w, index, &ws, w_idx))
|
2011-12-24 03:41:16 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_list_store_append(model, &iter);
|
2012-03-24 04:07:53 +00:00
|
|
|
set_one_weightsystem(&ws, model, &iter);
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
selection = gtk_tree_view_get_selection(tree_view);
|
|
|
|
gtk_tree_selection_select_iter(selection, &iter);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
weightsystem_list[w_idx].max_index++;
|
|
|
|
gtk_widget_set_sensitive(weightsystem_list[w_idx].add, weightsystem_list[w_idx].max_index < MAX_WEIGHTSYSTEMS);
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
static void ws_del_cb(GtkButton *button, int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
int index, nr;
|
|
|
|
GtkTreeIter iter;
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = weightsystem_list[w_idx].model;
|
|
|
|
GtkTreeView *tree_view = weightsystem_list[w_idx].tree_view;
|
2011-12-24 03:41:16 +00:00
|
|
|
GtkTreeSelection *selection;
|
|
|
|
struct dive *dive;
|
|
|
|
weightsystem_t *ws;
|
|
|
|
|
|
|
|
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))
|
|
|
|
return;
|
|
|
|
|
|
|
|
index = get_model_index(model, &iter);
|
|
|
|
|
2012-09-14 03:41:21 +00:00
|
|
|
if (w_idx == W_IDX_PRIMARY)
|
|
|
|
dive = current_dive;
|
|
|
|
else
|
|
|
|
dive = &edit_dive;
|
2011-12-24 03:41:16 +00:00
|
|
|
if (!dive)
|
|
|
|
return;
|
|
|
|
ws = dive->weightsystem + index;
|
2012-08-15 22:21:34 +00:00
|
|
|
nr = weightsystem_list[w_idx].max_index - index - 1;
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
gtk_list_store_remove(model, &iter);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
weightsystem_list[w_idx].max_index--;
|
2011-12-24 03:41:16 +00:00
|
|
|
memmove(ws, ws+1, nr*sizeof(*ws));
|
|
|
|
memset(ws+nr, 0, sizeof(*ws));
|
|
|
|
|
|
|
|
mark_divelist_changed(TRUE);
|
|
|
|
flush_divelist(dive);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
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);
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
|
|
|
|
2011-09-09 15:38:48 +00:00
|
|
|
static GtkListStore *create_tank_size_model(void)
|
|
|
|
{
|
|
|
|
GtkListStore *model;
|
|
|
|
|
|
|
|
model = gtk_list_store_new(3,
|
|
|
|
G_TYPE_STRING, /* Tank name */
|
|
|
|
G_TYPE_INT, /* Tank size in mliter */
|
|
|
|
G_TYPE_INT, /* Tank working pressure in mbar */
|
|
|
|
-1);
|
|
|
|
|
|
|
|
fill_tank_list(model);
|
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static GtkListStore *create_weightsystem_model(void)
|
|
|
|
{
|
|
|
|
GtkListStore *model;
|
|
|
|
|
|
|
|
model = gtk_list_store_new(2,
|
|
|
|
G_TYPE_STRING, /* Weightsystem description */
|
|
|
|
G_TYPE_INT, /* Weight in grams */
|
|
|
|
-1);
|
|
|
|
|
|
|
|
fill_ws_list(model);
|
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
static void size_data_func(GtkTreeViewColumn *col,
|
|
|
|
GtkCellRenderer *renderer,
|
|
|
|
GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
gpointer data)
|
2011-09-09 15:38:48 +00:00
|
|
|
{
|
2011-10-02 20:13:27 +00:00
|
|
|
int ml, mbar;
|
|
|
|
double size, pressure;
|
2013-03-03 22:12:10 +00:00
|
|
|
char buffer[64];
|
2011-10-02 20:13:27 +00:00
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, CYL_SIZE, &ml, CYL_WORKP, &mbar, -1);
|
|
|
|
convert_volume_pressure(ml, mbar, &size, &pressure);
|
|
|
|
if (size)
|
|
|
|
snprintf(buffer, sizeof(buffer), "%.1f", size);
|
|
|
|
else
|
2012-10-11 00:42:59 +00:00
|
|
|
strcpy(buffer, _("unkn"));
|
2011-10-02 20:13:27 +00:00
|
|
|
g_object_set(renderer, "text", buffer, NULL);
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void weight_data_func(GtkTreeViewColumn *col,
|
|
|
|
GtkCellRenderer *renderer,
|
|
|
|
GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
int idx = (long)data;
|
|
|
|
int grams, decimals;
|
|
|
|
double value;
|
2013-03-04 01:53:43 +00:00
|
|
|
char buffer[64];
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, idx, &grams, -1);
|
|
|
|
decimals = convert_weight(grams, &value);
|
|
|
|
if (grams)
|
|
|
|
snprintf(buffer, sizeof(buffer), "%.*f", decimals, value);
|
|
|
|
else
|
2012-10-11 00:42:59 +00:00
|
|
|
strcpy(buffer, _("unkn"));
|
2011-12-24 03:41:16 +00:00
|
|
|
g_object_set(renderer, "text", buffer, NULL);
|
|
|
|
}
|
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
static void pressure_data_func(GtkTreeViewColumn *col,
|
|
|
|
GtkCellRenderer *renderer,
|
|
|
|
GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
int index = (long)data;
|
|
|
|
int mbar, decimals;
|
|
|
|
double pressure;
|
|
|
|
char buffer[10];
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, index, &mbar, -1);
|
|
|
|
decimals = convert_pressure(mbar, &pressure);
|
|
|
|
if (mbar)
|
|
|
|
snprintf(buffer, sizeof(buffer), "%.*f", decimals, pressure);
|
|
|
|
else
|
|
|
|
*buffer = 0;
|
|
|
|
g_object_set(renderer, "text", buffer, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void percentage_data_func(GtkTreeViewColumn *col,
|
|
|
|
GtkCellRenderer *renderer,
|
|
|
|
GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
int index = (long)data;
|
|
|
|
int permille;
|
|
|
|
char buffer[10];
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, index, &permille, -1);
|
|
|
|
if (permille)
|
|
|
|
snprintf(buffer, sizeof(buffer), "%.1f%%", permille / 10.0);
|
|
|
|
else
|
|
|
|
*buffer = 0;
|
|
|
|
g_object_set(renderer, "text", buffer, NULL);
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
static void selection_cb(GtkTreeSelection *selection, struct equipment_list *list)
|
2011-10-02 20:27:03 +00:00
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
|
|
|
int selected;
|
|
|
|
|
|
|
|
selected = gtk_tree_selection_get_selected(selection, NULL, &iter);
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_widget_set_sensitive(list->edit, selected);
|
|
|
|
gtk_widget_set_sensitive(list->del, selected);
|
2011-10-02 20:27:03 +00:00
|
|
|
}
|
|
|
|
|
2011-10-03 02:03:46 +00:00
|
|
|
static void row_activated_cb(GtkTreeView *tree_view,
|
|
|
|
GtkTreePath *path,
|
|
|
|
GtkTreeViewColumn *column,
|
2012-08-15 22:21:34 +00:00
|
|
|
int w_idx)
|
2011-10-03 02:03:46 +00:00
|
|
|
{
|
2012-09-29 18:13:05 +00:00
|
|
|
edit_cb(GTK_WIDGET(tree_view), w_idx);
|
2011-10-03 02:03:46 +00:00
|
|
|
}
|
|
|
|
|
2012-04-24 02:54:11 +00:00
|
|
|
static void ws_row_activated_cb(GtkTreeView *tree_view,
|
|
|
|
GtkTreePath *path,
|
|
|
|
GtkTreeViewColumn *column,
|
2012-08-15 22:21:34 +00:00
|
|
|
int w_idx)
|
2012-04-24 02:54:11 +00:00
|
|
|
{
|
2012-09-29 18:13:05 +00:00
|
|
|
ws_edit_cb(GTK_WIDGET(tree_view), w_idx);
|
2012-04-24 02:54:11 +00:00
|
|
|
}
|
|
|
|
|
2013-01-29 21:10:46 +00:00
|
|
|
static GtkWidget *cylinder_list_widget(int w_idx)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = cylinder_list[w_idx].model;
|
2011-10-02 20:13:27 +00:00
|
|
|
GtkWidget *tree_view;
|
2011-10-02 20:27:03 +00:00
|
|
|
GtkTreeSelection *selection;
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
|
2011-11-18 13:13:02 +00:00
|
|
|
gtk_widget_set_can_focus(tree_view, FALSE);
|
2011-11-19 19:47:04 +00:00
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
g_signal_connect(tree_view, "row-activated", G_CALLBACK(row_activated_cb), GINT_TO_POINTER(w_idx));
|
2011-10-02 20:27:03 +00:00
|
|
|
|
|
|
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
|
|
|
|
gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
|
2012-08-15 22:21:34 +00:00
|
|
|
g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &cylinder_list[w_idx]);
|
2011-10-02 20:27:03 +00:00
|
|
|
|
2011-10-03 02:03:46 +00:00
|
|
|
g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
|
|
|
|
"enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH,
|
|
|
|
NULL);
|
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
tree_view_column(tree_view, CYL_DESC, _("Type"), NULL, ALIGN_LEFT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, CYL_SIZE, _("Size"), size_data_func, ALIGN_RIGHT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, CYL_WORKP, _("MaxPress"), pressure_data_func, ALIGN_RIGHT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, CYL_STARTP, _("Start"), pressure_data_func, ALIGN_RIGHT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, CYL_ENDP, _("End"), pressure_data_func, ALIGN_RIGHT | UNSORTABLE);
|
2011-12-11 19:40:17 +00:00
|
|
|
tree_view_column(tree_view, CYL_O2, "O" UTF8_SUBSCRIPT_2 "%", percentage_data_func, ALIGN_RIGHT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, CYL_HE, "He%", percentage_data_func, ALIGN_RIGHT | UNSORTABLE);
|
2011-10-02 20:13:27 +00:00
|
|
|
return tree_view;
|
|
|
|
}
|
|
|
|
|
2013-01-29 21:10:46 +00:00
|
|
|
static GtkWidget *weightsystem_list_widget(int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkListStore *model = weightsystem_list[w_idx].model;
|
2011-12-24 03:41:16 +00:00
|
|
|
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);
|
2012-08-18 13:24:49 +00:00
|
|
|
g_signal_connect(tree_view, "row-activated", G_CALLBACK(ws_row_activated_cb), GINT_TO_POINTER(w_idx));
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
|
|
|
|
gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
|
2012-08-15 22:21:34 +00:00
|
|
|
g_signal_connect(selection, "changed", G_CALLBACK(selection_cb), &weightsystem_list[w_idx]);
|
2011-12-24 03:41:16 +00:00
|
|
|
|
|
|
|
g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
|
|
|
|
"enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH,
|
|
|
|
NULL);
|
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
tree_view_column(tree_view, WS_DESC, _("Type"), NULL, ALIGN_LEFT | UNSORTABLE);
|
|
|
|
tree_view_column(tree_view, WS_WEIGHT, _("weight"),
|
2011-12-24 03:41:16 +00:00
|
|
|
weight_data_func, ALIGN_RIGHT | UNSORTABLE);
|
|
|
|
|
|
|
|
return tree_view;
|
|
|
|
}
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
static GtkWidget *cylinder_list_create(int w_idx)
|
2011-11-19 19:47:04 +00:00
|
|
|
{
|
|
|
|
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 */
|
|
|
|
);
|
2012-08-15 22:21:34 +00:00
|
|
|
cylinder_list[w_idx].model = model;
|
|
|
|
return cylinder_list_widget(w_idx);
|
2011-11-19 19:47:04 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
static GtkWidget *weightsystem_list_create(int w_idx)
|
2011-12-24 03:41:16 +00:00
|
|
|
{
|
|
|
|
GtkListStore *model;
|
|
|
|
|
|
|
|
model = gtk_list_store_new(WS_COLUMNS,
|
|
|
|
G_TYPE_STRING, /* WS_DESC: utf8 */
|
|
|
|
G_TYPE_INT /* WS_WEIGHT: grams */
|
|
|
|
);
|
2012-08-15 22:21:34 +00:00
|
|
|
weightsystem_list[w_idx].model = model;
|
|
|
|
return weightsystem_list_widget(w_idx);
|
2011-12-24 03:41:16 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
GtkWidget *equipment_widget(int w_idx)
|
2011-10-02 20:13:27 +00:00
|
|
|
{
|
2011-11-19 19:47:04 +00:00
|
|
|
GtkWidget *vbox, *hbox, *frame, *framebox, *tree_view;
|
2011-10-02 20:13:27 +00:00
|
|
|
GtkWidget *add, *del, *edit;
|
|
|
|
|
2011-09-10 02:46:53 +00:00
|
|
|
vbox = gtk_vbox_new(FALSE, 3);
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
/*
|
2012-08-15 22:21:34 +00:00
|
|
|
* 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.
|
2011-10-02 20:13:27 +00:00
|
|
|
*/
|
2012-08-15 22:21:34 +00:00
|
|
|
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);
|
2011-09-13 20:50:03 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
|
2011-09-13 20:50:03 +00:00
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
frame = gtk_frame_new(_("Cylinders"));
|
2011-10-02 20:13:27 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, FALSE, 3);
|
2011-09-09 15:38:48 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
framebox = gtk_vbox_new(FALSE, 3);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), framebox);
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
|
2011-09-20 16:53:45 +00:00
|
|
|
|
2011-11-19 19:47:04 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), tree_view, TRUE, FALSE, 3);
|
2011-09-20 16:53:45 +00:00
|
|
|
|
2011-10-02 20:13:27 +00:00
|
|
|
hbox = gtk_hbox_new(TRUE, 3);
|
|
|
|
gtk_box_pack_start(GTK_BOX(framebox), hbox, TRUE, FALSE, 3);
|
|
|
|
|
|
|
|
edit = gtk_button_new_from_stock(GTK_STOCK_EDIT);
|
|
|
|
add = gtk_button_new_from_stock(GTK_STOCK_ADD);
|
|
|
|
del = gtk_button_new_from_stock(GTK_STOCK_DELETE);
|
2012-10-19 03:45:26 +00:00
|
|
|
gtk_widget_set_sensitive(edit, FALSE);
|
|
|
|
gtk_widget_set_sensitive(add, FALSE);
|
|
|
|
gtk_widget_set_sensitive(del, FALSE);
|
2011-10-02 20:13:27 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), add, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), del, FALSE, FALSE, 0);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
cylinder_list[w_idx].edit = edit;
|
|
|
|
cylinder_list[w_idx].add = add;
|
|
|
|
cylinder_list[w_idx].del = del;
|
2011-10-02 20:13:27 +00:00
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
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));
|
2011-09-20 16:53:45 +00:00
|
|
|
|
2011-12-24 03:41:16 +00:00
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 3);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
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);
|
2011-12-24 03:41:16 +00:00
|
|
|
|
2012-10-11 00:42:59 +00:00
|
|
|
frame = gtk_frame_new(_("Weight"));
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, FALSE, 3);
|
|
|
|
|
|
|
|
framebox = gtk_vbox_new(FALSE, 3);
|
|
|
|
gtk_container_add(GTK_CONTAINER(frame), framebox);
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE, 3);
|
|
|
|
gtk_box_pack_start(GTK_BOX(framebox), hbox, 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);
|
|
|
|
|
|
|
|
edit = gtk_button_new_from_stock(GTK_STOCK_EDIT);
|
|
|
|
add = gtk_button_new_from_stock(GTK_STOCK_ADD);
|
|
|
|
del = gtk_button_new_from_stock(GTK_STOCK_DELETE);
|
2012-10-19 03:45:26 +00:00
|
|
|
gtk_widget_set_sensitive(edit, FALSE);
|
|
|
|
gtk_widget_set_sensitive(add, FALSE);
|
|
|
|
gtk_widget_set_sensitive(del, FALSE);
|
2011-12-24 03:41:16 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), add, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start(GTK_BOX(hbox), del, FALSE, FALSE, 0);
|
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
weightsystem_list[w_idx].edit = edit;
|
|
|
|
weightsystem_list[w_idx].add = add;
|
|
|
|
weightsystem_list[w_idx].del = del;
|
2011-12-24 03:41:16 +00:00
|
|
|
|
2012-08-15 22:21:34 +00:00
|
|
|
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));
|
2011-12-24 03:41:16 +00:00
|
|
|
|
2011-09-09 15:38:48 +00:00
|
|
|
return vbox;
|
|
|
|
}
|
2012-09-10 21:32:55 +00:00
|
|
|
|
|
|
|
void clear_equipment_widgets()
|
|
|
|
{
|
|
|
|
gtk_list_store_clear(cylinder_list[W_IDX_PRIMARY].model);
|
|
|
|
gtk_list_store_clear(weightsystem_list[W_IDX_PRIMARY].model);
|
|
|
|
}
|
2013-05-03 18:04:51 +00:00
|
|
|
#endif /* USE_GTK_UI */
|