GKeyFile *gnc_state_load (const QofSession *session) { GKeyFile *keyfile = NULL; GError *error = NULL; /* Drop possible previous state_file first */ if (state_file) { g_key_file_free (state_file); state_file = NULL; } gnc_state_set_base (session); if (state_file_name_pre_241) state_file = gnc_key_file_load_from_file (state_file_name_pre_241, TRUE, TRUE, NULL); else if (state_file_name) state_file = gnc_key_file_load_from_file (state_file_name, TRUE, TRUE, NULL); return gnc_state_get_current (); }
/* Sort changed callback */ static void gnc_split_reg2_sort_changed_cb (GtkTreeSortable *sortable, gpointer user_data) { GNCSplitReg2 *gsr = user_data; GncTreeViewSplitReg *view; GncTreeModelSplitReg *model; GtkSortType type; gint sortcol; gint sort_depth; const gchar *state_section; GKeyFile *state_file = gnc_state_get_current(); gtk_tree_sortable_get_sort_column_id (sortable, &sortcol, &type); ENTER("sortcol is %d", sortcol); view = gnc_ledger_display2_get_split_view_register (gsr->ledger); model = gnc_ledger_display2_get_split_model_register (gsr->ledger); sort_depth = gnc_tree_view_reg_get_selected_row_depth (view); if (sort_depth != 0) model->sort_depth = sort_depth; model->sort_col = sortcol; model->sort_direction = type; /* Save the sort depth state */ state_section = gnc_tree_view_get_state_section (GNC_TREE_VIEW (view)); g_key_file_set_integer (state_file, state_section, "sort_depth", model->sort_depth); LEAVE("m_sort_col %d, m_sort_direction is %d m_sort_depth is %d", model->sort_col, model->sort_direction, model->sort_depth); if (sortcol != -1) gnc_ledger_display2_refresh (gsr->ledger); }
void CsvImportSettings::remove_common (void) { auto keyfile = gnc_state_get_current (); auto group = csv_group_prefix + m_settings_type + " - " + m_name; g_key_file_remove_group (keyfile, group.c_str(), nullptr); }
void CsvTransSettings::remove (void) { if (trans_preset_is_reserved_name (m_name)) return; auto keyfile = gnc_state_get_current (); auto group = csv_group_prefix + m_name; g_key_file_remove_group (keyfile, group.c_str(), nullptr); }
/************************************************** * save_common * * save settings to a key file **************************************************/ bool CsvImportSettings::save_common (void) { auto keyfile = gnc_state_get_current (); auto group = csv_group_prefix + m_settings_type + " - " + m_name; // Start Saving the Common settings g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str()); g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines); g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, m_skip_end_lines); g_key_file_set_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, m_skip_alt_lines); g_key_file_set_boolean (keyfile, group.c_str(), CSV_FORMAT, (m_file_format == GncImpFileFormat::CSV) ? true : false); g_key_file_set_string (keyfile, group.c_str(), CSV_SEP, m_separators.c_str()); g_key_file_set_integer (keyfile, group.c_str(), CSV_DATE, m_date_format); std::ostringstream cmt_ss; cmt_ss << "Supported date formats: "; int fmt_num = 0; std::for_each (GncDate::c_formats.cbegin(), GncDate::c_formats.cend(), [&cmt_ss, &fmt_num](const GncDateFormat& fmt) { cmt_ss << fmt_num++ << ": '" << fmt.m_fmt << "', "; }); auto cmt = cmt_ss.str().substr(0, static_cast<long>(cmt_ss.tellp()) - 2); g_key_file_set_comment (keyfile, group.c_str(), CSV_DATE, cmt.c_str(), nullptr); g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format); g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str()); if (!m_column_widths.empty()) g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS, (gint*)(m_column_widths.data()), m_column_widths.size()); // Do a test read of encoding GError *key_error = nullptr; bool error = false; auto enc_val = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error); auto enc_str = std::string{enc_val}; if (enc_val) g_free (enc_val); if ((key_error) || (enc_str != m_encoding.c_str())) { if (key_error) { g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_ENCODING, key_error->message); g_error_free (key_error); } else g_warning ("Error comparing group %s key %s: '%s' and '%s'", group.c_str(), CSV_ENCODING, enc_str.c_str(), group.c_str()); error = true; } return error; }
/** Save all persistent program state to disk. This function finds the * name of the "new" state file associated with a specific book guid. * It saves some top level data, then iterates through the list of * open windows calling a helper function to save each window. * * @note The name of the state file is based on the name of the data * file, not the path name of the data file. If there are multiple * data files with the same name, the state files will be suffixed * with a number. E.G. test_account, test_account_2, test_account_3, * etc. * * @param session The QofSession whose state should be saved. * * @param unused */ static void gnc_save_all_state (gpointer session, gpointer unused) { QofBook *book; gchar guid_string[GUID_ENCODING_LENGTH+1]; const GncGUID *guid; GKeyFile *keyfile = NULL; keyfile = gnc_state_get_current (); if (keyfile) { /* Remove existing Window and Page groups from the keyfile * They will be regenerated. */ gsize num_groups, curr; gchar **groups = g_key_file_get_groups (keyfile, &num_groups); for (curr=0; curr < num_groups; curr++) { if (g_str_has_prefix (groups[curr], "Window ") || g_str_has_prefix (groups[curr], "Page ")) { DEBUG ("Removing state group %s", groups[curr]); g_key_file_remove_group (keyfile, groups[curr], NULL); } } g_strfreev (groups); } /* Store the book's GncGUID in the top level group */ book = qof_session_get_book(session); guid = qof_entity_get_guid(QOF_INSTANCE(book)); guid_to_string_buff(guid, guid_string); g_key_file_set_string(keyfile, STATE_FILE_TOP, STATE_FILE_BOOK_GUID, guid_string); gnc_main_window_save_all_windows(keyfile); #ifdef DEBUG /* Debugging: dump a copy to the trace log */ { gchar *file_data; gsize file_length; file_data = g_key_file_to_data(keyfile, &file_length, NULL); DEBUG("=== File Data Written===\n%s\n=== File End ===\n", file_data); g_free(file_data); } #endif LEAVE(""); }
/************************************************** * find * * find all settings entries in the state key file **************************************************/ const preset_vec& get_trans_presets (void) { // Search all Groups in the state key file for ones starting with prefix auto preset_names = std::vector<std::string>(); auto keyfile = gnc_state_get_current (); gsize grouplength; gchar **groups = g_key_file_get_groups (keyfile, &grouplength); /* Start by building a sorted list of candidate presets as found in the state file */ for (gsize i=0; i < grouplength; i++) { auto group = std::string(groups[i]); auto pos = group.find(csv_group_prefix); if (pos == std::string::npos) continue; preset_names.push_back(group.substr(csv_group_prefix.size())); } // string array from the state file is no longer needed now. g_strfreev (groups); /* We want our settings to appear sorted alphabetically to the user */ std::sort(preset_names.begin(), preset_names.end()); /* Now add each preset to our global list */ presets.clear(); /* Start with the internally generated ones */ presets.push_back(create_int_no_preset()); presets.push_back(create_int_gnc_exp_preset()); /* Then add all the ones we found in the state file */ for (auto preset_name : preset_names) { auto preset = std::make_shared<CsvTransSettings>(); preset->m_name = preset_name; preset->load(); presets.push_back(preset); } return presets; }
/************************************************** * load_common * * load the settings from a state key file **************************************************/ bool CsvImportSettings::load_common (void) { GError *key_error = nullptr; m_load_error = false; auto group = csv_group_prefix + m_settings_type + " - " + m_name; auto keyfile = gnc_state_get_current (); m_skip_start_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error); m_load_error |= handle_load_error (&key_error, group); m_skip_end_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_END, &key_error); m_load_error |= handle_load_error (&key_error, group); m_skip_alt_lines = g_key_file_get_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, &key_error); m_load_error |= handle_load_error (&key_error, group); auto csv_format = g_key_file_get_boolean (keyfile, group.c_str(), CSV_FORMAT, &key_error); if (key_error) csv_format = true; // default to true, but above command will return false in case of error m_load_error |= handle_load_error (&key_error, group); if (csv_format) m_file_format = GncImpFileFormat::CSV; else m_file_format = GncImpFileFormat::FIXED_WIDTH; gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_SEP, &key_error); if (key_char && *key_char != '\0') m_separators = key_char; m_load_error |= handle_load_error (&key_error, group); if (key_char) g_free (key_char); m_date_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_DATE, &key_error); m_load_error |= handle_load_error (&key_error, group); m_currency_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_CURRENCY, &key_error); m_load_error |= handle_load_error (&key_error, group); key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error); if (key_char && *key_char != '\0') m_encoding = key_char; else m_encoding = "UTF-8"; m_load_error |= handle_load_error (&key_error, group); if (key_char) g_free (key_char); // Widths gsize list_len; m_column_widths.clear(); gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS, &list_len, &key_error); for (uint32_t i = 0; i < list_len; i++) { if (col_widths_int[i] > 0) m_column_widths.push_back(col_widths_int[i]); } m_load_error |= handle_load_error (&key_error, group); if (col_widths_int) g_free (col_widths_int); return m_load_error; }
/************************************************** * save * * save settings to a key file **************************************************/ bool CsvTransSettings::save (void) { if (trans_preset_is_reserved_name (m_name)) { PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str()); return true; } if ((m_name.find('[') != std::string::npos)) { PWARN ("Name '%s' contains invalid characters '[]'. Refusing to save", m_name.c_str()); return true; } auto keyfile = gnc_state_get_current (); auto group = csv_group_prefix + m_name; // Drop previous saved settings with this name g_key_file_remove_group (keyfile, group.c_str(), nullptr); // Start Saving the settings g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str()); g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split); g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines); g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, m_skip_end_lines); g_key_file_set_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, m_skip_alt_lines); g_key_file_set_boolean (keyfile, group.c_str(), CSV_FORMAT, (m_file_format == GncImpFileFormat::CSV) ? true : false); g_key_file_set_string (keyfile, group.c_str(), CSV_SEP, m_separators.c_str()); g_key_file_set_integer (keyfile, group.c_str(), CSV_DATE, m_date_format); std::ostringstream cmt_ss; cmt_ss << "Supported date formats: "; int fmt_num = 0; std::for_each (GncDate::c_formats.cbegin(), GncDate::c_formats.cend(), [&cmt_ss, &fmt_num](const GncDateFormat& fmt) { cmt_ss << fmt_num++ << ": '" << fmt.m_fmt << "', "; }); auto cmt = cmt_ss.str().substr(0, static_cast<long>(cmt_ss.tellp()) - 2); g_key_file_set_comment (keyfile, group.c_str(), CSV_DATE, cmt.c_str(), nullptr); g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format); g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str()); if (m_base_account) g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account)); std::vector<const char*> col_types_str; for (auto col_type : m_column_types) col_types_str.push_back(gnc_csv_col_type_strs[col_type]); if (!col_types_str.empty()) g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES, col_types_str.data(), col_types_str.size()); if (!m_column_widths.empty()) g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS, (gint*)(m_column_widths.data()), m_column_widths.size()); // Do a test read of encoding GError *key_error = nullptr; bool error = false; auto enc_val = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error); auto enc_str = std::string{enc_val}; if (enc_val) g_free (enc_val); if ((key_error) || (enc_str != m_encoding.c_str())) { if (key_error) { g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_COL_TYPES, key_error->message); g_error_free (key_error); } else g_warning ("Error comparing group %s key %s: '%s' and '%s'", group.c_str(), CSV_COL_TYPES, enc_str.c_str(), group.c_str()); error = true; } return error; }
/************************************************** * load * * load the settings from a state key file **************************************************/ bool CsvTransSettings::load (void) { if (trans_preset_is_reserved_name (m_name)) return true; GError *key_error = nullptr; m_load_error = false; auto group = csv_group_prefix + m_name; auto keyfile = gnc_state_get_current (); m_skip_start_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error); m_load_error |= handle_load_error (&key_error, group); m_skip_end_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_END, &key_error); m_load_error |= handle_load_error (&key_error, group); m_skip_alt_lines = g_key_file_get_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, &key_error); m_load_error |= handle_load_error (&key_error, group); m_multi_split = g_key_file_get_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, &key_error); m_load_error |= handle_load_error (&key_error, group); auto csv_format = g_key_file_get_boolean (keyfile, group.c_str(), CSV_FORMAT, &key_error); if (key_error) csv_format = true; // default to true, but above command will return false in case of error m_load_error |= handle_load_error (&key_error, group); if (csv_format) m_file_format = GncImpFileFormat::CSV; else m_file_format = GncImpFileFormat::FIXED_WIDTH; gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_SEP, &key_error); if (key_char && *key_char != '\0') m_separators = key_char; m_load_error |= handle_load_error (&key_error, group); if (key_char) g_free (key_char); m_date_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_DATE, &key_error); m_load_error |= handle_load_error (&key_error, group); m_currency_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_CURRENCY, &key_error); m_load_error |= handle_load_error (&key_error, group); key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error); if (key_char && *key_char != '\0') m_encoding = key_char; else m_encoding = "UTF-8"; m_load_error |= handle_load_error (&key_error, group); if (key_char) g_free (key_char); key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error); if (key_char && *key_char != '\0') m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char); m_load_error |= handle_load_error (&key_error, group); if (key_char) g_free (key_char); m_column_types.clear(); gsize list_len; gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES, &list_len, &key_error); for (uint32_t i = 0; i < list_len; i++) { auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(), gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i])); if (col_types_it != gnc_csv_col_type_strs.end()) { /* Found a valid column type. Now check whether it is allowed * in the selected mode (two-split vs multi-split) */ auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split); m_column_types.push_back(prop); if (prop != col_types_it->first) PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. " "Inserting column type 'NONE' instead'.", col_types_it->second, m_multi_split ? "enabled" : "disabled"); } else PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.", col_types_str[i]); } if (col_types_str) g_strfreev (col_types_str); m_column_widths.clear(); gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS, &list_len, &key_error); for (uint32_t i = 0; i < list_len; i++) { if (col_widths_int[i] > 0) m_column_widths.push_back(col_widths_int[i]); } m_load_error |= handle_load_error (&key_error, group); if (col_widths_int) g_free (col_widths_int); return m_load_error; }
static void gsr2_create_table (GNCSplitReg2 *gsr) { GncTreeViewSplitReg *view; GncTreeModelSplitReg *model; GtkTreeModel *s_model; GtkWidget *scrolled_window; GtkTreeViewColumn *col; GNCLedgerDisplay2Type ledger_type; GtkWidget *hbox; gdouble num_of_trans; gchar *state_section; GKeyFile *state_file = gnc_state_get_current(); const GncGUID * guid; Account * account; account = gnc_ledger_display2_leader (gsr->ledger); guid = xaccAccountGetGUID (account); ENTER("create table gsr=%p", gsr); gnc_ledger_display2_set_user_data (gsr->ledger, (gpointer)gsr); gnc_ledger_display2_set_handlers (gsr->ledger, gnc_split_reg2_ld_destroy, gnc_split_reg2_get_parent); model = gnc_ledger_display2_get_split_model_register (gsr->ledger); view = gnc_tree_view_split_reg_new_with_model (model); g_object_unref (G_OBJECT (model)); /* State_section is used to store per register state: column widths, sort order,... */ ledger_type = gnc_ledger_display2_type (gsr->ledger); if (ledger_type == LD2_GL && model->type == GENERAL_JOURNAL2) state_section = g_strdup (STATE_SECTION_GEN_JOURNAL); else if (ledger_type == LD2_SUBACCOUNT) { gchar guidstr[GUID_ENCODING_LENGTH+1]; guid_to_string_buff (guid, guidstr); state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, " w/subaccounts", NULL); } else { gchar guidstr[GUID_ENCODING_LENGTH+1]; guid_to_string_buff (guid, guidstr); state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr, NULL); } g_object_set (G_OBJECT (view), "state-section", state_section, "show-column-menu", FALSE, NULL); // Create a hbox for treeview and scrollbar. hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE); gtk_widget_show (hbox); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show (scrolled_window); gtk_box_pack_start (GTK_BOX (gsr), hbox, TRUE, TRUE, 0); num_of_trans = model->number_of_trans_in_full_tlist - 1; gsr->scroll_adj = GTK_ADJUSTMENT (gtk_adjustment_new (model->position_of_trans_in_full_tlist, 0.0, num_of_trans + 10, 1.0, 10.0, 10.0)); gsr->scroll_bar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (gsr->scroll_adj)); gtk_widget_show (gsr->scroll_bar); gtk_box_pack_start (GTK_BOX (hbox), gsr->scroll_bar, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (hbox), scrolled_window, TRUE, TRUE, 0); gnc_ledger_display2_set_split_view_register (gsr->ledger, view); /* Synchronize model state with view state * (needed to properly set up the internal query) */ /* Restore the sort depth from saved state */ model->sort_depth = g_key_file_get_integer (state_file, state_section, "sort_depth", NULL); g_free(state_section); s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); if (s_model) { gint sort_col; GtkSortType type; if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (s_model), &sort_col, &type)) { model->sort_col = sort_col; model->sort_direction = type; } } gnc_tree_view_configure_columns (GNC_TREE_VIEW (view)); if (ledger_type == LD2_GL && model->type == GENERAL_JOURNAL2) gnc_tree_view_set_show_column_menu (GNC_TREE_VIEW (view), TRUE); else gnc_tree_view_set_show_column_menu (GNC_TREE_VIEW (view), FALSE); /* This column gets all the free space */ gnc_tree_view_expand_columns (GNC_TREE_VIEW (view), "descnotes", NULL); /* This sets the status color column, 4 is the minimum */ col = gnc_tree_view_find_column_by_name (GNC_TREE_VIEW (view), "status"); if (col != NULL) g_object_set (G_OBJECT(col), "resizable", FALSE, "sizing", GTK_TREE_VIEW_COLUMN_FIXED, "fixed-width", 4, NULL); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), TRUE); gtk_widget_show (GTK_WIDGET (view)); gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (view)); gtk_widget_show (GTK_WIDGET (gsr)); /* Should this be read only */ gnc_tree_view_split_reg_set_read_only (view, gsr->read_only); /* This tells the ledger that we have a valid tree view */ gnc_ledger_display2_set_split_view_refresh (gsr->ledger, TRUE); /* This triggers the update of the summary bar */ g_signal_connect_after (model, "refresh_status_bar", G_CALLBACK (gsr2_redraw_all_cb), gsr); //this works // This will keep scrollbar in sync. g_signal_connect (model, "scroll_sync", G_CALLBACK (gsr2_scroll_sync_cb), gsr); /* This triggers the update of the help text */ g_signal_connect (view, "help_signal", G_CALLBACK (gsr2_emit_help_changed), gsr); // this works gsr2_scroll_value_changed_cb (GTK_ADJUSTMENT (gsr->scroll_adj), gsr); /* This triggers the tooltip to change when scrolling */ g_signal_connect (gsr->scroll_adj, "value-changed", G_CALLBACK (gsr2_scroll_value_changed_cb), gsr); // this works /* This triggers the model update when mouse button released */ g_signal_connect (gsr->scroll_bar, "button-release-event", G_CALLBACK (gsr2_scroll_button_event_cb), gsr); // Connect a call back to update the sort settings. g_signal_connect (GTK_TREE_SORTABLE (s_model), "sort-column-changed", G_CALLBACK (gnc_split_reg2_sort_changed_cb), gsr); LEAVE(" "); }
static void gnucash_register_configure (GnucashSheet *sheet, gchar * state_section) { GNCHeaderWidths widths; Table *table; GList *node; gchar *key; guint value; GKeyFile *state_file = gnc_state_get_current(); // Stuff for per-register settings load. g_return_if_fail (sheet != NULL); g_return_if_fail (GNUCASH_IS_SHEET (sheet)); PINFO("state_section=%s",state_section); ENTER("sheet=%p, data=%p", sheet, ""); table = sheet->table; gnc_table_init_gui (table); table->ui_data = sheet; g_object_ref (sheet); /* config the cell-block styles */ widths = gnc_header_widths_new (); if (state_section && gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY)) { node = gnc_table_layout_get_cells (table->layout); for (; node; node = node->next) { BasicCell *cell = node->data; if (cell->expandable) continue; /* Remember whether the column is visible */ key = g_strdup_printf("%s_width", cell->cell_name); value = g_key_file_get_integer (state_file, state_section, key, NULL); if (value != 0) gnc_header_widths_set_width (widths, cell->cell_name, value); g_free(key); } } gnucash_sheet_create_styles (sheet); gnucash_sheet_set_header_widths (sheet, widths); gnucash_sheet_compile_styles (sheet); gnucash_sheet_table_load (sheet, TRUE); gnucash_sheet_cursor_set_from_table (sheet, TRUE); gnucash_sheet_redraw_all (sheet); gnc_header_widths_destroy (widths); LEAVE(" "); }