+static struct flist_head gopt_list[FIO_MAX_OPTS];
+
+static void __gopt_set_children_visible(unsigned int idx, gboolean visible)
+{
+ struct flist_head *entry;
+ struct gopt_widget *gw;
+
+ flist_for_each(entry, &gopt_list[idx]) {
+ gw = flist_entry(entry, struct gopt_widget, list);
+ gtk_widget_set_sensitive(gw->widget, visible);
+ }
+}
+
+/*
+ * Mark children as invisible, if needed.
+ */
+static void gopt_set_children_visible(struct fio_option *parent, gboolean visible)
+{
+ struct fio_option *o;
+ int i;
+
+ /*
+ * This isn't super fast, but it should not be an issue. If it is, we
+ * can speed it up by caching the lookup at least. Or we can do it
+ * once, at init time.
+ */
+ for (i = 0; fio_options[i].name; i++) {
+ o = &fio_options[i];
+ if (!o->parent || !o->hide)
+ continue;
+
+ if (strcmp(parent->name, o->parent))
+ continue;
+
+ __gopt_set_children_visible(i, visible);
+ }
+}
+
+static void gopt_str_changed(GtkEntry *entry, gpointer data)
+{
+ struct gopt_str *s = (struct gopt_str *) data;
+ struct fio_option *o = &fio_options[s->gopt.opt_index];
+ const gchar *text;
+ int set;
+
+ text = gtk_entry_get_text(GTK_ENTRY(s->entry));
+ set = strcmp(text, "") != 0;
+ gopt_set_children_visible(o, set);
+}
+
+static void gopt_mark_index(struct gopt *gopt, unsigned int idx)
+{
+ struct gopt_widget *gw;
+
+ gopt->opt_index = idx;
+
+ gw = malloc(sizeof(*gw));
+ gw->widget = gopt->box;
+ flist_add_tail(&gw->list, &gopt_list[idx]);
+}
+
+static struct gopt *gopt_new_str_store(struct fio_option *o, const char *text, unsigned int idx)