static void gwy_resource_class_load_dir(const gchar *path, GwyResourceClass *klass, gboolean is_system) { GDir *dir; GwyResource *resource; GError *err = NULL; const gchar *name; gchar *filename, *text; if (!(dir = g_dir_open(path, 0, NULL))) return; while ((name = g_dir_read_name(dir))) { if (gwy_filename_ignore(name)) continue; if (gwy_inventory_get_item(klass->inventory, name)) { g_warning("Ignoring duplicite %s `%s'", klass->name, name); continue; } /* FIXME */ filename = g_build_filename(path, name, NULL); if (!g_file_get_contents(filename, &text, NULL, &err)) { g_warning("Cannot read `%s': %s", filename, err->message); g_clear_error(&err); g_free(filename); continue; } g_free(filename); resource = gwy_resource_parse_real(text, G_TYPE_FROM_CLASS(klass), is_system); if (resource) { g_string_assign(resource->name, name); resource->is_modified = FALSE; gwy_inventory_insert_item(klass->inventory, resource); g_object_unref(resource); } g_free(text); } g_dir_close(dir); }
static void threshold_changed(GFilterControls *controls, GtkAdjustment *adj) { GFilterArgs *args = controls->args; GwyInventory *inventory; GwyGrainValue *gvalue; GtkEntry *entry; const gchar *name; gboolean is_upper; guint id, i, k; gdouble *v; gdouble value; gchar *s; if (controls->in_init) return; id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(adj), "id")); is_upper = id & IS_UPPER; id &= ~IS_UPPER; k = gwy_adjustment_get_int(adj); inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[id].quantity); g_return_if_fail(gvalue); name = gwy_resource_get_name(GWY_RESOURCE(gvalue)); i = gwy_inventory_get_item_position(inventory, args->ranges[id].quantity); v = g_ptr_array_index(args->sortedvaluedata, i); value = v[k]; s = g_strdup_printf("%.*f", controls->vf[id]->precision, value/controls->vf[id]->magnitude); if (is_upper) entry = GTK_ENTRY(controls->upper_entry[id]); else entry = GTK_ENTRY(controls->lower_entry[id]); gtk_entry_set_text(entry, s); g_free(s); set_threshold_value(args, id, name, value, is_upper); gfilter_invalidate(controls); }
static void gfilter_sanitize_args(GFilterArgs *args) { GwyInventory *inventory; guint i; inventory = gwy_grain_values(); args->logical = MIN(args->logical, GRAIN_LOGICAL_NTYPES); for (i = 0; i < NQUANTITIES; i++) { RangeRecord *rr = args->ranges + i; GwyGrainValue *gvalue; if ((gvalue = gwy_inventory_get_item(inventory, rr->quantity))) rr->quantity = gwy_resource_get_name(GWY_RESOURCE(gvalue)); else rr->quantity = gfilter_defaults.ranges[i].quantity; /* The actual range is restored later from range_history. */ } args->update = !!args->update; }
static void threshold_activated(GFilterControls *controls, GtkEntry *entry) { GFilterArgs *args = controls->args; GwyInventory *inventory; GwyGrainValue *gvalue; GtkAdjustment *adj; guint id; gboolean is_upper; const gchar *s, *name; gdouble value; if (controls->in_init) return; id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(entry), "id")); is_upper = id & IS_UPPER; id &= ~IS_UPPER; inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[id].quantity); g_return_if_fail(gvalue); name = gwy_resource_get_name(GWY_RESOURCE(gvalue)); s = gtk_entry_get_text(entry); value = g_strtod(s, NULL) * controls->vf[id]->magnitude; if (is_upper) adj = GTK_ADJUSTMENT(controls->upper[id]); else adj = GTK_ADJUSTMENT(controls->lower[id]); controls->in_init = TRUE; set_adjustment_to_grain_value(controls, gvalue, adj, value); controls->in_init = FALSE; set_threshold_value(args, id, name, value, is_upper); gfilter_invalidate(controls); }
static void gfilter_dialog(GFilterArgs *args, GwyContainer *data, GwyDataField *dfield, GwyDataField *mfield, gint id, GQuark mquark) { GtkWidget *dialog, *table, *vbox, *hbox, *scwin, *hbox2, *label; GtkTreeView *treeview; GtkTreeSelection *selection; GFilterControls controls; gint response, row, i; GwySIUnit *siunit; GwyPixmapLayer *layer; controls.args = args; controls.mask = mfield; controls.in_init = TRUE; controls.computed = FALSE; siunit = gwy_si_unit_new(NULL); for (i = 0; i < NQUANTITIES; i++) { controls.vf[i] = gwy_si_unit_get_format_with_digits(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, 1.0, 4, NULL); } g_object_unref(siunit); dialog = gtk_dialog_new_with_buttons(_("Filter Grains"), NULL, 0, NULL); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Update"), GTK_STOCK_EXECUTE), RESPONSE_PREVIEW); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), RESPONSE_PREVIEW, !args->update); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.dialog = dialog; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 4); vbox = gtk_vbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); mfield = gwy_data_field_duplicate(mfield); gwy_container_set_object_by_name(controls.mydata, "/0/mask", mfield); g_object_unref(mfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_REAL_SQUARE, 0); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); layer = gwy_layer_mask_new(); gwy_pixmap_layer_set_data_key(layer, "/0/mask"); gwy_layer_mask_set_color_key(GWY_LAYER_MASK(layer), "/0/mask"); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); controls.update = gtk_check_button_new_with_mnemonic(_("I_nstant updates")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.update), args->update); gtk_box_pack_start(GTK_BOX(vbox), controls.update, FALSE, FALSE, 0); g_signal_connect_swapped(controls.update, "toggled", G_CALLBACK(update_changed), &controls); hbox2 = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic(_("_Mask color:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.color_button = gwy_color_button_new(); gwy_color_button_set_use_alpha(GWY_COLOR_BUTTON(controls.color_button), TRUE); load_mask_color(controls.color_button, gwy_data_view_get_data(GWY_DATA_VIEW(controls.view))); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.color_button); gtk_box_pack_start(GTK_BOX(hbox2), controls.color_button, FALSE, FALSE, 0); g_signal_connect(controls.color_button, "clicked", G_CALLBACK(mask_color_changed), &controls); table = gtk_table_new(10, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 4); controls.table = table; row = 0; scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_table_attach(GTK_TABLE(table), scwin, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); controls.values = gwy_grain_value_tree_view_new(FALSE, "name", "symbol_markup", NULL); treeview = GTK_TREE_VIEW(controls.values); gtk_widget_set_size_request(scwin, -1, 120); gtk_tree_view_set_headers_visible(treeview, FALSE); selection = gtk_tree_view_get_selection(treeview); gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); gwy_grain_value_tree_view_set_same_units(treeview, args->units_equal); gwy_grain_value_tree_view_set_expanded_groups(treeview, args->expanded); gtk_container_add(GTK_CONTAINER(scwin), controls.values); row++; hbox2 = gtk_hbox_new(FALSE, 0); for (i = 0; i < NQUANTITIES; i++) { gchar buf[2]; buf[0] = 'A' + i; buf[1] = '\0'; controls.set_as[i] = gtk_button_new_with_label(buf); gtk_box_pack_start(GTK_BOX(hbox2), controls.set_as[i], FALSE, FALSE, 0); g_object_set_data(G_OBJECT(controls.set_as[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.set_as[i], "clicked", G_CALLBACK(set_as_clicked), &controls); } gwy_table_attach_hscale(table, row++, _("Set selected as:"), NULL, GTK_OBJECT(hbox2), GWY_HSCALE_WIDGET_NO_EXPAND); controls.logical_op = gwy_enum_combo_box_newl(G_CALLBACK(logical_op_changed), &controls, args->logical, "A", GRAIN_LOGICAL_A, "A ∧ B", GRAIN_LOGICAL_A_AND_B, "A ∨ B", GRAIN_LOGICAL_A_OR_B, "A ∧ B ∧ C", GRAIN_LOGICAL_A_AND_B_AND_C, "A ∨ B ∨ C", GRAIN_LOGICAL_A_OR_B_OR_C, "(A ∧ B) ∨ C", GRAIN_LOGICAL_A_AND_B_OR_C, "(A ∨ B) ∧ C", GRAIN_LOGICAL_A_OR_B_AND_C, NULL); gwy_table_attach_hscale(table, row++, _("Keep grains satisfying:"), NULL, GTK_OBJECT(controls.logical_op), GWY_HSCALE_WIDGET); for (i = 0; i < NQUANTITIES; i++) { gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); controls.header[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.header[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.header[i], 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; /* The values are set properly later. */ controls.lower_label[i] = gtk_label_new(_("Lower threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.lower_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.lower[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.lower[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.lower_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.lower[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.lower_scale[i]), FALSE); gtk_widget_set_size_request(controls.lower_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.lower_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.lower_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.lower_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.lower_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.lower_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.lower_entry[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.lower_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.lower_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.upper_label[i] = gtk_label_new(_("Upper threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.upper_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.upper[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.upper[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.upper_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.upper[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.upper_scale[i]), FALSE); gtk_widget_set_size_request(controls.upper_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.upper_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.upper_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.upper_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.upper_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.upper_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.upper_entry[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.upper_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.upper_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; } for (i = 0; i < NQUANTITIES; i++) { GwyInventory *inventory; GwyGrainValue *gvalue; inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[i].quantity); set_up_quantity(&controls, gvalue, i); } logical_op_changed(GTK_COMBO_BOX(controls.logical_op), &controls); /* finished initializing, allow instant updates */ controls.in_init = FALSE; gfilter_invalidate(&controls); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: g_object_unref(controls.mydata); gfilter_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_PREVIEW: preview(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); gfilter_save_args(gwy_app_settings_get(), args); if (controls.computed) { mfield = gwy_container_get_object_by_name(controls.mydata, "/0/mask"); gwy_app_undo_qcheckpointv(data, 1, &mquark); gwy_container_set_object(data, mquark, mfield); g_object_unref(controls.mydata); } else { g_object_unref(controls.mydata); run_noninteractive(args, data, controls.mask, mquark); } gwy_app_channel_log_add_proc(data, id, id); }
static void gfilter_load_args(GwyContainer *container, GFilterArgs *args) { GwyInventory *inventory; gchar *filename, *buffer; gsize size; guint i; inventory = gwy_grain_values(); *args = gfilter_defaults; gwy_container_gis_boolean_by_name(container, update_key, &args->update); gwy_container_gis_int32_by_name(container, expanded_key, &args->expanded); gwy_container_gis_enum_by_name(container, logical_key, &args->logical); for (i = 0; i < NQUANTITIES; i++) { RangeRecord *rr = args->ranges + i; gchar buf[sizeof(quantity_key) + 10]; g_snprintf(buf, sizeof(buf), "%s%u", quantity_key, i+1); gwy_container_gis_string_by_name(container, buf, (const guchar**)&rr->quantity); } args->ranges_history = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, range_record_free); filename = g_build_filename(gwy_get_user_dir(), "grain_filter", "ranges", NULL); if (g_file_get_contents(filename, &buffer, &size, NULL)) { gchar *p = buffer, *line; for (line = gwy_str_next_line(&p); line; line = gwy_str_next_line(&p)) { g_strstrip(line); if (*line) { GwyGrainValue *gvalue; RangeRecord *rr; gchar *s = line, *end; gdouble lower, upper; lower = g_ascii_strtod(s, &end); s = end; upper = g_ascii_strtod(s, &end); if (end == s) { g_warning("Invalid grain_filter range record: %s.", line); continue; } s = end; g_strstrip(s); if (!(gvalue = gwy_inventory_get_item(inventory, s))) { g_warning("Invalid grain_filter range record: %s.", line); continue; } rr = g_slice_new(RangeRecord); rr->lower = lower; rr->upper = upper; rr->quantity = gwy_resource_get_name(GWY_RESOURCE(gvalue)); g_hash_table_insert(args->ranges_history, (gpointer)rr->quantity, rr); } } g_free(buffer); } g_free(filename); gfilter_sanitize_args(args); }
static gboolean cnew_dialog(CNewArgs *args, GwyDataField *dfield) { GtkWidget *dialog, *table, *spin, *label; GwySIUnit *unit; gint row; CNewControls controls; gint response; controls.args = args; controls.in_update = TRUE; dialog = gtk_dialog_new_with_buttons(_("Simple Calibration Data"), NULL, 0, _("_Reset"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); table = gtk_table_new(4, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 4); /*x from*/ row = 0; label = gtk_label_new_with_mnemonic(_("_X from:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.xrange_from = gtk_adjustment_new(args->xrange_from/pow10(args->xyexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.xrange_from), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_xy(dfield); controls.xyexponent = gwy_combo_box_metric_unit_new(G_CALLBACK(xyexponent_changed_cb), &controls, -15, 6, unit, args->xyexponent); gtk_table_attach(GTK_TABLE(table), controls.xyexponent, 2, 3, row, row+2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0, 0); controls.xyunits = gtk_button_new_with_label(gwy_sgettext("verb|Change")); g_object_set_data(G_OBJECT(controls.xyunits), "id", (gpointer)"xy"); gtk_table_attach(GTK_TABLE(table), controls.xyunits, 3, 4, row, row+2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_X to:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.xrange_to = gtk_adjustment_new(args->xrange_to/pow10(args->xyexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.xrange_to), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Y from:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.yrange_from = gtk_adjustment_new(args->yrange_from/pow10(args->xyexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.yrange_from), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Y to:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.yrange_to = gtk_adjustment_new(args->yrange_to/pow10(args->xyexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.yrange_to), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Z from:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.zrange_from = gtk_adjustment_new(args->zrange_from/pow10(args->zexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.zrange_from), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_z(dfield); controls.zexponent = gwy_combo_box_metric_unit_new(G_CALLBACK(zexponent_changed_cb), &controls, -15, 6, unit, args->zexponent); gtk_table_attach(GTK_TABLE(table), controls.zexponent, 2, 3, row, row+2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0, 0); controls.zunits = gtk_button_new_with_label(gwy_sgettext("verb|Change")); g_object_set_data(G_OBJECT(controls.zunits), "id", (gpointer)"z"); gtk_table_attach(GTK_TABLE(table), controls.zunits, 3, 4, row, row+2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Z to:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.zrange_to = gtk_adjustment_new(args->zrange_to/pow10(args->zexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.zrange_to), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_X uncertainty:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.xunc = gtk_adjustment_new(args->xunc/pow10(args->xyuexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.xunc), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_xy(dfield); controls.xyuexponent = gwy_combo_box_metric_unit_new(G_CALLBACK(xyuexponent_changed_cb), &controls, -15, 6, unit, args->xyuexponent); gtk_table_attach(GTK_TABLE(table), controls.xyuexponent, 2, 3, row, row+2, GTK_EXPAND | GTK_FILL , 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Y uncertainty:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.yunc = gtk_adjustment_new(args->yunc/pow10(args->xyuexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.yunc), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Z uncertainty:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.zunc = gtk_adjustment_new(args->zunc/pow10(args->zuexponent), -10000, 10000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.zunc), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_z(dfield); controls.zuexponent = gwy_combo_box_metric_unit_new(G_CALLBACK(zuexponent_changed_cb), &controls, -15, 6, unit, args->zuexponent); gtk_table_attach(GTK_TABLE(table), controls.zuexponent, 2, 3, row, row+1, GTK_EXPAND | GTK_FILL , 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_X correction factor:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.xmult = gtk_adjustment_new(args->xmult, 0, 1000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.xmult), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Y correction factor:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.ymult = gtk_adjustment_new(args->ymult, 0, 1000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.ymult), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("_Z correction factor:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.zmult = gtk_adjustment_new(args->zmult, 0, 1000, 1, 10, 0); spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.zmult), 1, 2); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); gtk_table_attach(GTK_TABLE(table), spin, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new_with_mnemonic(_("Calibration name:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.name = GTK_ENTRY(gtk_entry_new()); gtk_entry_set_text(controls.name, args->name); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(controls.name), 1, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.xrange_from, "value-changed", G_CALLBACK(xfrom_changed_cb), &controls); g_signal_connect(controls.xrange_to, "value-changed", G_CALLBACK(xto_changed_cb), &controls); g_signal_connect(controls.yrange_from, "value-changed", G_CALLBACK(yfrom_changed_cb), &controls); g_signal_connect(controls.yrange_to, "value-changed", G_CALLBACK(yto_changed_cb), &controls); g_signal_connect(controls.zrange_from, "value-changed", G_CALLBACK(zfrom_changed_cb), &controls); g_signal_connect(controls.zrange_to, "value-changed", G_CALLBACK(zto_changed_cb), &controls); g_signal_connect(controls.xunc, "value-changed", G_CALLBACK(xunc_changed_cb), &controls); g_signal_connect(controls.yunc, "value-changed", G_CALLBACK(yunc_changed_cb), &controls); g_signal_connect(controls.zunc, "value-changed", G_CALLBACK(zunc_changed_cb), &controls); g_signal_connect(controls.xmult, "value-changed", G_CALLBACK(xmult_changed_cb), &controls); g_signal_connect(controls.ymult, "value-changed", G_CALLBACK(ymult_changed_cb), &controls); g_signal_connect(controls.zmult, "value-changed", G_CALLBACK(zmult_changed_cb), &controls); g_signal_connect(controls.xyunits, "clicked", G_CALLBACK(units_change_cb), &controls); g_signal_connect(controls.zunits, "clicked", G_CALLBACK(units_change_cb), &controls); controls.in_update = FALSE; gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: return FALSE; break; case GTK_RESPONSE_OK: /*check whether this resource already exists*/ args->name = g_strdup(gtk_entry_get_text(controls.name)); if (gwy_inventory_get_item(gwy_calibrations(), args->name)) response = ask_for_overwrite(GTK_WINDOW(dialog), args); else args->duplicate = DUPLICATE_NONE; break; case RESPONSE_RESET: *args = cnew_defaults; cnew_dialog_update(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); return TRUE; }
static void cnew(G_GNUC_UNUSED GwyContainer *data, GwyRunType run) { GwyDataField *dfield; CNewArgs args; gboolean ok; gint oldid, i, j, k, n; GwyCalibration *calibration; GwyCalData *caldata = NULL, *old; gchar *filename; gchar *contents; gsize len = 0; GError *err = NULL; gsize pos = 0; GString *str; gdouble *x, *y, *z, *xunc, *yunc, *zunc, *xerr, *yerr, *zerr; FILE *fh; g_return_if_fail(run & CNEW_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); cnew_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = cnew_dialog(&args, dfield); cnew_save_args(gwy_app_settings_get(), &args); if (!ok) return; } /*create the caldata*/ caldata = gwy_caldata_new(8); x = gwy_caldata_get_x(caldata); y = gwy_caldata_get_y(caldata); z = gwy_caldata_get_z(caldata); xerr = gwy_caldata_get_xerr(caldata); yerr = gwy_caldata_get_yerr(caldata); zerr = gwy_caldata_get_zerr(caldata); xunc = gwy_caldata_get_xunc(caldata); yunc = gwy_caldata_get_yunc(caldata); zunc = gwy_caldata_get_zunc(caldata); gwy_caldata_set_si_unit_x(caldata, gwy_data_field_get_si_unit_xy(dfield)); gwy_caldata_set_si_unit_y(caldata, gwy_data_field_get_si_unit_xy(dfield)); gwy_caldata_set_si_unit_z(caldata, gwy_data_field_get_si_unit_z(dfield)); n = 0; for (i=0; i<2; i++) { for (j=0; j<2; j++) { for (k=0; k<2; k++) { if (i) x[n] = args.xrange_from; else x[n] = args.xrange_to; if (j) y[n] = args.yrange_from; else y[n] = args.yrange_to; if (k) z[n] = args.zrange_from; else z[n] = args.zrange_to; if (i) xerr[n] = (args.xrange_to-args.xrange_from)*(args.xmult-1); else xerr[n] = 0; if (j) yerr[n] = (args.yrange_to-args.yrange_from)*(args.ymult-1); else yerr[n] = 0; if (k) zerr[n] = (args.zrange_to-args.zrange_from)*(args.zmult-1); else zerr[n] = 0; xunc[n] = args.xunc; yunc[n] = args.yunc; zunc[n] = args.zunc; n++; } } } if (args.duplicate == DUPLICATE_APPEND && (calibration = gwy_inventory_get_item(gwy_calibrations(), args.name))) { filename = g_build_filename(gwy_get_user_dir(), "caldata", calibration->filename, NULL); if (!g_file_get_contents(filename, &contents, &len, &err) || !len) { g_warning("Error loading file: %s", err->message); g_clear_error(&err); return; } else { if (len) old = GWY_CALDATA(gwy_serializable_deserialize(contents, len, &pos)); g_free(contents); } gwy_caldata_append(old, caldata); g_object_unref(caldata); caldata = old; } gwy_caldata_set_range(caldata, args.xrange_from, args.xrange_to, args.yrange_from, args.yrange_to, args.zrange_from, args.zrange_to); //printf("Saving %g %g %g %g\n", args.xrange_from, args.xrange_to, args.yrange_from, args.yrange_to); /*now create and save the resource*/ if ((calibration = GWY_CALIBRATION(gwy_inventory_get_item(gwy_calibrations(), args.name)))==NULL) { calibration = gwy_calibration_new(args.name, g_strconcat(args.name, ".dat", NULL)); gwy_inventory_insert_item(gwy_calibrations(), calibration); g_object_unref(calibration); } calibration->caldata = caldata; filename = gwy_resource_build_filename(GWY_RESOURCE(calibration)); if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { g_mkdir(g_build_filename(gwy_get_user_dir(), "calibrations", NULL), 0700); } fh = gwy_fopen(filename, "wb"); if (!fh) { g_warning(_("Cannot save preset: %s"), filename); g_free(filename); return; } g_free(filename); str = gwy_resource_dump(GWY_RESOURCE(calibration)); fwrite(str->str, 1, str->len, fh); fclose(fh); g_string_free(str, TRUE); gwy_resource_data_saved(GWY_RESOURCE(calibration)); gwy_resource_data_changed(GWY_RESOURCE(calibration)); /*now save the calibration data*/ //gwy_caldata_debug(caldata, "Saving: "); gwy_caldata_save_data(caldata, calibration->filename); }
static gboolean cload_dialog(CLoadArgs *args, GwyDataField *dfield) { GtkWidget *dialog, *dialog2, *table, *label; gint row = 0; CLoadControls controls; enum { RESPONSE_RESET = 1, RESPONSE_DUPLICATE_OVERWRITE = 2, RESPONSE_DUPLICATE_APPEND = 3 }; gint response; controls.args = args; dialog = gtk_dialog_new_with_buttons(_("Load calibration data"), NULL, 0, _("_Reset"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); controls.dialog = dialog; gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Load"), GTK_STOCK_OPEN), RESPONSE_LOAD); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); table = gtk_table_new(4, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 4); label = gtk_label_new_with_mnemonic(_("Calibration name:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); args->name = g_strdup("new"); //FIXME this should not be here controls.name = GTK_ENTRY(gtk_entry_new()); gtk_entry_set_text(controls.name, args->name); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(controls.name), 1, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.text = gtk_label_new(_("No data loaded")); gtk_misc_set_alignment(GTK_MISC(controls.text), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.text, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: return FALSE; break; case GTK_RESPONSE_OK: /*check whether this resource already exists*/ args->name = g_strdup(gtk_entry_get_text(controls.name)); if (gwy_inventory_get_item(gwy_calibrations(), args->name)) { dialog2 = gtk_message_dialog_new (GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_CANCEL, "Calibration '%s' alerady exists", args->name); gtk_dialog_add_button(GTK_DIALOG(dialog2), "Overwrite", RESPONSE_DUPLICATE_OVERWRITE); gtk_dialog_add_button(GTK_DIALOG(dialog2), "Append", RESPONSE_DUPLICATE_APPEND); response = gtk_dialog_run(GTK_DIALOG(dialog2)); if (response == RESPONSE_DUPLICATE_OVERWRITE) { args->duplicate = DUPLICATE_OVERWRITE; response = GTK_RESPONSE_OK; } else if (response == RESPONSE_DUPLICATE_APPEND) { args->duplicate = DUPLICATE_APPEND; response = GTK_RESPONSE_OK; } gtk_widget_destroy (dialog2); } else args->duplicate = DUPLICATE_NONE; break; case RESPONSE_LOAD: load_caldata(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); return TRUE; }
static void cload(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; CLoadArgs args; gboolean ok; gint oldid, i, n; GwyCalibration *calibration; GwyCalData *caldata = NULL; gchar *filename; gchar *contents; gsize len; GError *err = NULL; gsize pos = 0; GString *str; GByteArray *barray; FILE *fh; g_return_if_fail(run & CNEW_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); //cload_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = cload_dialog(&args, dfield); //cload_save_args(gwy_app_settings_get(), &args); if (!ok) return; } /*if append requested, copy newly created calibration into old one*/ if (args.duplicate == DUPLICATE_APPEND && (calibration = gwy_inventory_get_item(gwy_calibrations(), args.name))) { filename = g_build_filename(gwy_get_user_dir(), "caldata", calibration->filename, NULL); if (!g_file_get_contents(filename, &contents, &len, &err)) { g_warning("Error loading file: %s\n", err->message); g_clear_error(&err); return; } else { if (len) caldata = GWY_CALDATA(gwy_serializable_deserialize(contents, len, &pos)); g_free(contents); } n = caldata->ndata + args.caldata->ndata; //add to args->caldata args.caldata->x = g_realloc(args.caldata->x, n*sizeof(gdouble)); args.caldata->y = g_realloc(args.caldata->y, n*sizeof(gdouble)); args.caldata->z = g_realloc(args.caldata->z, n*sizeof(gdouble)); args.caldata->xerr = g_realloc(args.caldata->xerr, n*sizeof(gdouble)); args.caldata->yerr = g_realloc(args.caldata->yerr, n*sizeof(gdouble)); args.caldata->zerr = g_realloc(args.caldata->zerr, n*sizeof(gdouble)); args.caldata->xunc = g_realloc(args.caldata->xunc, n*sizeof(gdouble)); args.caldata->yunc = g_realloc(args.caldata->yunc, n*sizeof(gdouble)); args.caldata->zunc = g_realloc(args.caldata->zunc, n*sizeof(gdouble)); for (i=args.caldata->ndata; i<n; i++) { args.caldata->x[i] = caldata->x[i-caldata->ndata]; args.caldata->y[i] = caldata->y[i-caldata->ndata]; args.caldata->z[i] = caldata->z[i-caldata->ndata]; args.caldata->xerr[i] = caldata->xerr[i-caldata->ndata]; args.caldata->yerr[i] = caldata->yerr[i-caldata->ndata]; args.caldata->zerr[i] = caldata->zerr[i-caldata->ndata]; args.caldata->xunc[i] = caldata->xunc[i-caldata->ndata]; args.caldata->yunc[i] = caldata->yunc[i-caldata->ndata]; args.caldata->zunc[i] = caldata->zunc[i-caldata->ndata]; } args.caldata->ndata = n; } /*now create and save the resource*/ if ((calibration = GWY_CALIBRATION(gwy_inventory_get_item(gwy_calibrations(), args.name)))==NULL) { calibration = gwy_calibration_new(args.name, 8, g_strconcat(args.name, ".dat", NULL)); gwy_inventory_insert_item(gwy_calibrations(), calibration); g_object_unref(calibration); } filename = gwy_resource_build_filename(GWY_RESOURCE(calibration)); fh = g_fopen(filename, "w"); if (!fh) { g_warning("Cannot save preset: %s", filename); g_free(filename); return; } g_free(filename); str = gwy_resource_dump(GWY_RESOURCE(calibration)); fwrite(str->str, 1, str->len, fh); fclose(fh); g_string_free(str, TRUE); gwy_resource_data_saved(GWY_RESOURCE(calibration)); //debugcal(args.caldata); /*now save the calibration data*/ if (!g_file_test(g_build_filename(gwy_get_user_dir(), "caldata", NULL), G_FILE_TEST_EXISTS)) { g_mkdir(g_build_filename(gwy_get_user_dir(), "caldata", NULL), 0700); } fh = g_fopen(g_build_filename(gwy_get_user_dir(), "caldata", calibration->filename, NULL), "w"); if (!fh) { g_warning("Cannot save caldata\n"); return; } barray = gwy_serializable_serialize(G_OBJECT(args.caldata), NULL); //g_file_set_contents(fh, barray->data, sizeof(guint8)*barray->len, NULL); fwrite(barray->data, sizeof(guint8), barray->len, fh); fclose(fh); }