struct gopt_int {
struct gopt gopt;
+ unsigned int lastval;
+ unsigned int in_change;
GtkWidget *spin;
};
gtk_box_pack_start(GTK_BOX(s->gopt.box), s->entry, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(s->gopt.box), label, FALSE, FALSE, 0);
+ o->gui_data = s;
return &s->gopt;
}
gtk_box_pack_start(GTK_BOX(c->gopt.box), c->combo, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(c->gopt.box), label, FALSE, FALSE, 0);
+ o->gui_data = c;
return c;
}
{
struct gopt_int *i = (struct gopt_int *) data;
struct fio_option *o = &fio_options[i->gopt.opt_index];
-
- printf("int %s changed\n", o->name);
+ GtkAdjustment *adj;
+ int value, delta;
+
+ adj = gtk_spin_button_get_adjustment(spin);
+ value = gtk_adjustment_get_value(adj);
+ delta = value - i->lastval;
+ i->lastval = value;
+
+ if (o->inv_opt) {
+ struct gopt_int *i_inv = o->inv_opt->gui_data;
+ int cur_val;
+
+ /*
+ * Don't recourse into notify changes. Is there a better
+ * way than this? We essentially want to block the update
+ * signal while we perform the below set_value().
+ */
+ if (i_inv->in_change)
+ return;
+
+ i->in_change = 1;
+ cur_val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(i_inv->spin));
+ cur_val -= delta;
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(i_inv->spin), cur_val);
+ i->in_change = 0;
+ }
}
static struct gopt_int *__gopt_new_int(struct fio_option *o, unsigned long long *p,
gopt_mark_index(&i->gopt, idx);
gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(i->spin), GTK_UPDATE_IF_VALID);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(i->spin), defval);
+ i->lastval = defval;
g_signal_connect(G_OBJECT(i->spin), "value-changed", G_CALLBACK(gopt_int_changed), i);
gtk_box_pack_start(GTK_BOX(i->gopt.box), i->spin, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(i->gopt.box), label, FALSE, FALSE, 0);
+ o->gui_data = i;
return i;
}
gtk_box_pack_start(GTK_BOX(b->gopt.box), b->check, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(b->gopt.box), label, FALSE, FALSE, 0);
+ o->gui_data = b;
return &b->gopt;
}
}
gtk_box_pack_start(GTK_BOX(r->gopt.box), label, FALSE, FALSE, 0);
+ o->gui_data = r;
return &r->gopt;
}
GtkWidget *hbox = NULL;
int i;
+ /*
+ * First add all options
+ */
for (i = 0; fio_options[i].name; i++) {
struct fio_option *o = &fio_options[i];
unsigned int mask = o->category;
.help = "Percentage of mixed workload that is reads",
.def = "50",
.interval = 5,
+ .inverse = "rwmixwrite",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RWMIX,
},
.help = "Percentage of mixed workload that is writes",
.def = "50",
.interval = 5,
+ .inverse = "rwmixread",
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RWMIX,
},
return 1;
}
- if (!handle_option(*o, post, data)) {
+ if (!handle_option(*o, post, data))
return 0;
- }
log_err("fio: failed parsing %s\n", input);
return 1;
dprint(FD_PARSE, "init options\n");
- for (o = &options[0]; o->name; o++)
+ for (o = &options[0]; o->name; o++) {
option_init(o);
+ if (o->inverse)
+ o->inv_opt = find_option(options, o->inverse);
+ }
}
void options_free(struct fio_option *options, void *data)
struct value_pair posval[PARSE_MAX_VP];/* possible values */
const char *parent; /* parent option */
int hide; /* hide if parent isn't set */
+ const char *inverse; /* if set, apply opposite action to this option */
+ struct fio_option *inv_opt; /* cached lookup */
int (*verify)(struct fio_option *, void *);
const char *prof_name; /* only valid for specific profile */
unsigned int category; /* what type of option */
unsigned int group; /* who to group with */
+ void *gui_data;
};
typedef int (str_cb_fn)(void *, char *);