26#include <glib/gi18n.h>
30#include "dialog-utils.h"
31#include "assistant-xml-encoding.h"
33#include "gnc-component-manager.h"
40#include "gnc-gui-query.h"
43#include "gnc-splash.h"
45#include "gnc-ui-balances.h"
52#include "ScrubBudget.h"
54#include "gnc-session.h"
56#include "gnc-autosave.h"
62static QofLogModule log_module = GNC_MOD_GUI;
64static GNCShutdownCB shutdown_cb = NULL;
65static gint save_in_progress = 0;
67typedef bool (*CharToBool)(
const char*);
69static bool datafile_filter (
const GtkFileFilterInfo* info, CharToBool checker)
71 return info && info->filename && checker (info->filename);
75gnc_file_chooser_get_datafile_filters ()
79 const char* datafiles = N_(
"Datafiles only (*.gnucash, *.xac)");
80 const char* backups = N_(
"Backups only (*.gnucash.*.gnucash, *.xac.*.xac)");
83 GtkFileFilter *filter = gtk_file_filter_new ();
84 gtk_file_filter_set_name (filter,
_(datafiles));
85 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME,
86 (GtkFileFilterFunc)datafile_filter,
87 gnc_filename_is_datafile, NULL);
88 rv = g_list_prepend (rv, filter);
90 filter = gtk_file_filter_new ();
91 gtk_file_filter_set_name (filter,
_(backups));
92 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME,
93 (GtkFileFilterFunc)datafile_filter,
94 gnc_filename_is_backup, NULL);
95 rv = g_list_prepend (rv, filter);
97 return g_list_reverse (rv);
101gnc_file_chooser_add_filters (GtkFileChooser* file_box, GList *filters)
103 g_return_if_fail (GTK_IS_WIDGET (file_box));
104 if (filters == NULL)
return;
106 for (GList* node = filters; node; node = node->next)
107 gtk_file_chooser_add_filter (file_box, GTK_FILE_FILTER (node->data));
109 GtkFileFilter* all_filter = gtk_file_filter_new();
110 gtk_file_filter_set_name (all_filter,
_(
"All files"));
111 gtk_file_filter_add_pattern (all_filter,
"*");
112 gtk_file_chooser_add_filter (file_box, all_filter);
115 gtk_file_chooser_set_filter (file_box, filters->data);
116 g_list_free (filters);
121gnc_file_dialog_int (GtkWindow *parent,
124 const char * starting_dir,
125 GNCFileDialogType type,
130 char *file_name = NULL;
131 gchar * okbutton = NULL;
132 const gchar *ok_icon = NULL;
133 GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
135 GSList* file_name_list = NULL;
141 case GNC_FILE_DIALOG_OPEN:
142 action = GTK_FILE_CHOOSER_ACTION_OPEN;
143 okbutton =
_(
"_Open");
147 case GNC_FILE_DIALOG_IMPORT:
148 action = GTK_FILE_CHOOSER_ACTION_OPEN;
149 okbutton =
_(
"_Import");
153 case GNC_FILE_DIALOG_SAVE:
154 action = GTK_FILE_CHOOSER_ACTION_SAVE;
155 okbutton =
_(
"_Save");
159 case GNC_FILE_DIALOG_EXPORT:
160 action = GTK_FILE_CHOOSER_ACTION_SAVE;
161 okbutton =
_(
"_Export");
169 file_box = gtk_file_chooser_dialog_new(
173 _(
"_Cancel"), GTK_RESPONSE_CANCEL,
176 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_box), TRUE);
179 gnc_gtk_dialog_add_button(file_box, okbutton, ok_icon, GTK_RESPONSE_ACCEPT);
181 gtk_dialog_add_button(GTK_DIALOG(file_box),
182 okbutton, GTK_RESPONSE_ACCEPT);
185 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_box),
188 gtk_window_set_modal(GTK_WINDOW(file_box), TRUE);
191 gnc_file_chooser_add_filters (GTK_FILE_CHOOSER (file_box), filters);
193 response = gtk_dialog_run(GTK_DIALOG(file_box));
196 gtk_widget_set_name (GTK_WIDGET(file_box),
"gnc-id-file");
198 if (response == GTK_RESPONSE_ACCEPT)
202 file_name_list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (file_box));
207 file_name = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER (file_box));
208 if (file_name != NULL)
210 if (strstr (file_name,
"file://") == file_name)
214 file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_box));
216 file_name_list = g_slist_append (file_name_list, file_name);
220 gtk_widget_destroy(GTK_WIDGET(file_box));
221 LEAVE(
"%s", file_name ? file_name :
"(null)");
222 return file_name_list;
240gnc_file_dialog (GtkWindow *parent,
243 const char * starting_dir,
244 GNCFileDialogType type
247 gchar* file_name = NULL;
248 GSList* ret = gnc_file_dialog_int (parent, title, filters, starting_dir, type, FALSE);
250 file_name = g_strdup (ret->data);
251 g_slist_free_full (ret, g_free);
270gnc_file_dialog_multi (GtkWindow *parent,
273 const char * starting_dir,
274 GNCFileDialogType type
277 return gnc_file_dialog_int (parent, title, filters, starting_dir, type, TRUE);
281show_session_error (GtkWindow *parent,
284 GNCFileDialogType type)
287 gboolean uh_oh = TRUE;
288 const char *fmt, *label;
294 displayname = g_strdup(
_(
"(null)"));
308 case ERR_BACKEND_NO_ERR:
313 fmt =
_(
"No suitable backend was found for %s.");
314 gnc_error_dialog(parent, fmt, displayname);
318 fmt =
_(
"The URL %s is not supported by this version of GnuCash.");
319 gnc_error_dialog (parent, fmt, displayname);
323 fmt =
_(
"Can't parse the URL %s.");
324 gnc_error_dialog (parent, fmt, displayname);
328 fmt =
_(
"Can't connect to %s. "
329 "The host, username or password were incorrect.");
330 gnc_error_dialog (parent, fmt, displayname);
334 fmt =
_(
"Can't connect to %s. "
335 "Connection was lost, unable to send data.");
336 gnc_error_dialog (parent, fmt, displayname);
340 fmt =
_(
"This file/URL appears to be from a newer version "
341 "of GnuCash. You must upgrade your version of GnuCash "
342 "to work with this data.");
343 gnc_error_dialog (parent,
"%s", fmt);
347 fmt =
_(
"The database %s doesn't seem to exist. "
348 "Do you want to create it?");
349 if (gnc_verify_dialog (parent, TRUE, fmt, displayname))
358 case GNC_FILE_DIALOG_OPEN:
361 fmt =
_(
"GnuCash could not obtain the lock for %s. "
362 "That database may be in use by another user, "
363 "in which case you should not open the database. "
364 "Do you want to proceed with opening the database?");
367 case GNC_FILE_DIALOG_IMPORT:
369 fmt =
_(
"GnuCash could not obtain the lock for %s. "
370 "That database may be in use by another user, "
371 "in which case you should not import the database. "
372 "Do you want to proceed with importing the database?");
375 case GNC_FILE_DIALOG_SAVE:
377 fmt =
_(
"GnuCash could not obtain the lock for %s. "
378 "That database may be in use by another user, "
379 "in which case you should not save the database. "
380 "Do you want to proceed with saving the database?");
383 case GNC_FILE_DIALOG_EXPORT:
385 fmt =
_(
"GnuCash could not obtain the lock for %s. "
386 "That database may be in use by another user, "
387 "in which case you should not export the database. "
388 "Do you want to proceed with exporting the database?");
392 dialog = gtk_message_dialog_new(parent,
393 GTK_DIALOG_DESTROY_WITH_PARENT,
394 GTK_MESSAGE_QUESTION,
398 gtk_dialog_add_buttons(GTK_DIALOG(dialog),
399 _(
"_Cancel"), GTK_RESPONSE_CANCEL,
400 label, GTK_RESPONSE_YES,
403 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
404 response = gtk_dialog_run(GTK_DIALOG(dialog));
405 gtk_widget_destroy(dialog);
406 uh_oh = (response != GTK_RESPONSE_YES);
410 fmt =
_(
"GnuCash could not write to %s. "
411 "That database may be on a read-only file system, "
412 "you may not have write permission for the directory "
413 "or your anti-virus software is preventing this action.");
414 gnc_error_dialog (parent, fmt, displayname);
418 fmt =
_(
"The file/URL %s "
419 "does not contain GnuCash data or the data is corrupt.");
420 gnc_error_dialog (parent, fmt, displayname);
424 fmt =
_(
"The server at URL %s "
425 "experienced an error or encountered bad or corrupt data.");
426 gnc_error_dialog (parent, fmt, displayname);
430 fmt =
_(
"You do not have permission to access %s.");
431 gnc_error_dialog (parent, fmt, displayname);
435 fmt =
_(
"An error occurred while processing %s.");
436 gnc_error_dialog (parent, fmt, displayname);
440 fmt =
_(
"There was an error reading the file. "
441 "Do you want to continue?");
442 if (gnc_verify_dialog (parent, TRUE,
"%s", fmt))
449 fmt =
_(
"There was an error parsing the file %s.");
450 gnc_error_dialog (parent, fmt, displayname);
454 fmt =
_(
"The file %s is empty.");
455 gnc_error_dialog (parent, fmt, displayname);
459 if (type == GNC_FILE_DIALOG_SAVE)
467 fmt =
_(
"The file/URI %s could not be found.\n\nThe file is in the history list, do you want to remove it?");
468 if (gnc_verify_dialog (parent, FALSE, fmt, displayname))
473 fmt =
_(
"The file/URI %s could not be found.");
474 gnc_error_dialog (parent, fmt, displayname);
480 fmt =
_(
"This file is from an older version of GnuCash. "
481 "Do you want to continue?");
482 if (gnc_verify_dialog (parent, TRUE,
"%s", fmt))
489 fmt =
_(
"The file type of file %s is unknown.");
490 gnc_error_dialog(parent, fmt, displayname);
494 fmt =
_(
"Could not make a backup of the file %s");
495 gnc_error_dialog(parent, fmt, displayname);
499 fmt =
_(
"Could not write to file %s. Check that you have "
500 "permission to write to this file and that "
501 "there is sufficient space to create it.");
502 gnc_error_dialog(parent, fmt, displayname);
506 fmt =
_(
"No read permission to read from file %s.");
507 gnc_error_dialog (parent, fmt, displayname);
513 fmt =
_(
"You attempted to save in\n%s\nor a subdirectory thereof. "
514 "This is not allowed as %s reserves that directory for internal use.\n\n"
515 "Please try again in a different directory.");
516 gnc_error_dialog (parent, fmt, gnc_userdata_dir(), PACKAGE_NAME);
520 fmt =
_(
"This database is from an older version of GnuCash. "
521 "Select OK to upgrade it to the current version, Cancel "
522 "to mark it read-only.");
524 response = gnc_ok_cancel_dialog(parent, GTK_RESPONSE_CANCEL,
"%s", fmt);
525 uh_oh = (response == GTK_RESPONSE_CANCEL);
529 fmt =
_(
"This database is from a newer version of GnuCash. "
530 "This version can read it, but cannot safely save to it. "
531 "It will be marked read-only until you do File->Save As, "
532 "but data may be lost in writing to the old version.");
533 gnc_warning_dialog (parent,
"%s", fmt);
538 fmt =
_(
"The SQL database is in use by other users, "
539 "and the upgrade cannot be performed until they logoff. "
540 "If there are currently no other users, consult the "
541 "documentation to learn how to clear out dangling login "
543 gnc_error_dialog (parent,
"%s", fmt);
548 fmt =
_(
"The library \"libdbi\" installed on your system doesn't correctly "
549 "store large numbers. This means GnuCash cannot use SQL databases "
550 "correctly. Gnucash will not open or save to SQL databases until this is "
551 "fixed by installing a different version of \"libdbi\". Please see "
552 "https://bugs.gnucash.org/show_bug.cgi?id=611936 for more "
555 gnc_error_dialog (parent,
"%s", fmt);
560 fmt =
_(
"GnuCash could not complete a critical test for the presence of "
561 "a bug in the \"libdbi\" library. This may be caused by a "
562 "permissions misconfiguration of your SQL database. Please see "
563 "https://bugs.gnucash.org/show_bug.cgi?id=645216 for more "
566 gnc_error_dialog (parent,
"%s", fmt);
570 fmt =
_(
"This file is from an older version of GnuCash and will be "
571 "upgraded when saved by this version. You will not be able "
572 "to read the saved file from the older version of Gnucash "
573 "(it will report an \"error parsing the file\"). If you wish "
574 "to preserve the old version, exit without saving.");
575 gnc_warning_dialog (parent,
"%s", fmt);
580 PERR(
"FIXME: Unhandled error %d", io_error);
581 fmt =
_(
"An unknown I/O error (%d) occurred.");
582 gnc_error_dialog (parent, fmt, io_error);
586 g_free (displayname);
591gnc_add_history (QofSession * session)
596 if (!session)
return;
598 url = qof_session_get_url ( session );
612gnc_book_opened (
void)
614 gnc_hook_run(HOOK_BOOK_OPENED, gnc_get_current_session());
618gnc_file_new (GtkWindow *parent)
624 if (!gnc_file_query_save (parent, TRUE))
627 if (gnc_current_session_exist())
629 session = gnc_get_current_session ();
635 gnc_hook_run(HOOK_BOOK_CLOSED, session);
637 gnc_close_gui_component_by_session (session);
639 gnc_clear_current_session();
644 gnc_get_current_session ();
646 gnc_hook_run(HOOK_NEW_BOOK, NULL);
648 gnc_gui_refresh_all ();
655gnc_file_query_save (GtkWindow *parent, gboolean can_cancel)
659 if (!gnc_current_session_exist())
664 gnc_autosave_remove_timer(current_book);
676 const char *title =
_(
"Save changes to the file?");
681 dialog = gtk_message_dialog_new(parent,
682 GTK_DIALOG_DESTROY_WITH_PARENT,
683 GTK_MESSAGE_QUESTION,
687 minutes = (
gnc_time (NULL) - oldest_change) / 60 + 1;
688 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
689 ngettext(
"If you don't save, changes from the past %d minute will be discarded.",
690 "If you don't save, changes from the past %d minutes will be discarded.",
692 gtk_dialog_add_button(GTK_DIALOG(dialog),
693 _(
"Continue _Without Saving"), GTK_RESPONSE_OK);
696 gtk_dialog_add_button(GTK_DIALOG(dialog),
697 _(
"_Cancel"), GTK_RESPONSE_CANCEL);
698 gtk_dialog_add_button(GTK_DIALOG(dialog),
699 _(
"_Save"), GTK_RESPONSE_YES);
701 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
703 response = gtk_dialog_run(GTK_DIALOG(dialog));
704 gtk_widget_destroy(dialog);
708 case GTK_RESPONSE_YES:
709 gnc_file_save (parent);
713 case GTK_RESPONSE_CANCEL:
720 case GTK_RESPONSE_OK:
731get_account_sep_warning (
QofBook *book)
735 if (!violation_accts)
739 g_list_free_full (violation_accts, g_free);
745#define RESPONSE_NEW 1
746#define RESPONSE_OPEN 2
747#define RESPONSE_QUIT 3
748#define RESPONSE_READONLY 4
749#define RESPONSE_FILE 5
754run_post_load_scrubs (GtkWindow *parent,
QofBook *book)
756 const char *budget_warning =
757 _(
"This book has budgets. The internal representation of "
758 "budget amounts no longer depends on the Reverse Balanced "
759 "Accounts preference. Please review the budgets and amend "
760 "signs if necessary.");
768 if (gnc_maybe_scrub_all_budget_signs (book))
769 infos = g_list_prepend (infos, g_strdup (budget_warning));
776 char *sep_warning = get_account_sep_warning (book);
778 infos = g_list_prepend (infos, sep_warning);
785 const char *header = N_(
"The following are noted in this file:");
786 infos = g_list_reverse (infos);
787 infos = g_list_prepend (infos, g_strdup (
_(header)));
789 gnc_info_dialog (parent,
"%s",
final);
792 g_list_free_full (infos, g_free);
796gnc_post_file_open (GtkWindow *parent,
const char * filename, gboolean is_readonly)
798 QofSession *new_session;
799 gboolean uh_oh = FALSE;
803 gchar *scheme = NULL;
804 gchar *hostname = NULL;
805 gchar *username = NULL;
806 gchar *password = NULL;
811 ENTER(
"filename %s", filename);
813 if (!filename || (*filename ==
'\0'))
return FALSE;
820 show_session_error (parent,
821 ERR_FILEIO_FILE_NOT_FOUND, filename,
822 GNC_FILE_DIALOG_OPEN);
827 &port, &username, &password, &path);
839 gboolean have_valid_pw = FALSE;
841 path, &username, &password );
848 username, password, path);
854 gchar *default_dir = g_path_get_dirname(path);
855 gnc_set_default_directory (GNC_PREFS_GROUP_OPEN_SAVE, default_dir);
865 gnc_set_busy_cursor (NULL, TRUE);
869 if (gnc_current_session_exist())
871 QofSession *current_session = gnc_get_current_session();
872 gnc_hook_run(HOOK_BOOK_CLOSED, current_session);
873 gnc_close_gui_component_by_session (current_session);
875 gnc_clear_current_session();
890 show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_OPEN);
891 if (g_file_test (filename, G_FILE_TEST_IS_DIR))
892 directory = g_strdup (filename);
894 directory = gnc_get_default_directory (GNC_PREFS_GROUP_OPEN_SAVE);
896 filename = gnc_file_dialog (parent, NULL, NULL, directory,
897 GNC_FILE_DIALOG_OPEN);
900 qof_session_destroy (new_session);
909 gchar *displayname = NULL;
911 char *fmt1 =
_(
"GnuCash could not obtain the lock for %s.");
913 _(
"That database may be in use by another user, "
914 "in which case you should not open the database. "
915 "What would you like to do?") :
916 _(
"That database may be on a read-only file system, "
917 "you may not have write permission for the directory, "
918 "or your anti-virus software is preventing this action. "
919 "If you proceed you may not be able to save any changes. "
920 "What would you like to do?")
930 dialog = gtk_message_dialog_new(parent,
935 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
937 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
939 gnc_gtk_dialog_add_button(dialog,
_(
"Open _Read-Only"),
940 "emblem-readonly", RESPONSE_READONLY);
942 gnc_gtk_dialog_add_button(dialog,
_(
"Create _New File"),
943 "document-new-symbolic", RESPONSE_NEW);
945 gnc_gtk_dialog_add_button(dialog,
_(
"Open _Anyway"),
946 "document-open-symbolic", RESPONSE_OPEN);
948 gnc_gtk_dialog_add_button(dialog,
_(
"Open _Folder"),
949 "folder-open-symbolic", RESPONSE_FILE);
953 gtk_dialog_add_button(GTK_DIALOG(dialog),
954 _(
"_Quit"), RESPONSE_QUIT);
955 gtk_dialog_set_default_response (GTK_DIALOG(dialog), RESPONSE_QUIT);
958 gtk_dialog_set_default_response (GTK_DIALOG(dialog), RESPONSE_FILE);
960 rc = gtk_dialog_run(GTK_DIALOG(dialog));
961 gtk_widget_destroy(dialog);
962 g_free (displayname);
964 if (rc == GTK_RESPONSE_DELETE_EVENT)
966 rc = shutdown_cb ? RESPONSE_QUIT : RESPONSE_FILE;
975 case RESPONSE_READONLY:
989 gnc_file_new (parent);
996 gnc_file_open (parent);
1003 if (!show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_OPEN))
1016 if ((ERR_BACKEND_LOCKED == io_err) ||
1025 uh_oh = show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_OPEN);
1037 path, username, password );
1040 gnc_window_show_progress(
_(
"Loading user dataā¦"), 0.0);
1041 qof_session_load (new_session, gnc_window_show_progress);
1042 gnc_window_show_progress(NULL, -1.0);
1057 if (gnc_xml_convert_single_file (newfile))
1060 gnc_window_show_progress(
_(
"Loading user dataā¦"), 0.0);
1061 qof_session_load (new_session, gnc_window_show_progress);
1062 gnc_window_show_progress(NULL, -1.0);
1072 uh_oh = show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_OPEN);
1076 gnc_window_show_progress(
_(
"Re-saving user dataā¦"), 0.0);
1079 uh_oh = show_session_error(parent, io_err, newfile, GNC_FILE_DIALOG_SAVE);
1092 if (uh_oh) new_root = NULL;
1096 if (!uh_oh && !new_root)
1099 GNC_FILE_DIALOG_OPEN);
1114 gnc_error_dialog (parent, msg,
"");
1117 if (template_root != NULL)
1119 GList *child = NULL;
1122 for (child = children; child; child = g_list_next (child))
1124 Account *acc = GNC_ACCOUNT (child->data);
1126 g_list_foreach (splits,
1127 (GFunc)gnc_sx_scrub_split_numerics, NULL);
1128 g_list_free (splits);
1130 g_list_free (children);
1141 gnc_unset_busy_cursor (NULL);
1147 qof_session_destroy (new_session);
1156 gnc_get_current_session ();
1161 gnc_gui_refresh_all ();
1168 gnc_set_current_session(new_session);
1173 gnc_add_history (new_session);
1178 gnc_gui_refresh_all ();
1183 run_post_load_scrubs (parent, gnc_get_current_book ());
1195gnc_file_open (GtkWindow *parent)
1197 const gchar * newfile;
1199 gchar *default_dir = NULL;
1202 if (!gnc_file_query_save (parent, TRUE))
1208 default_dir = g_path_get_dirname( filepath );
1209 g_free ( filepath );
1212 default_dir = gnc_get_default_directory(GNC_PREFS_GROUP_OPEN_SAVE);
1214 newfile = gnc_file_dialog (parent,
_(
"Open"),
1215 gnc_file_chooser_get_datafile_filters(),
1216 default_dir, GNC_FILE_DIALOG_OPEN);
1218 g_free ( default_dir );
1220 result = gnc_post_file_open (parent, newfile, FALSE );
1226 gnc_get_current_session ();
1232gnc_file_open_file (GtkWindow *parent,
const char * newfile, gboolean open_readonly)
1234 if (!newfile)
return FALSE;
1236 if (!gnc_file_query_save (parent, TRUE))
1243 return gnc_post_file_open (parent, newfile, open_readonly);
1251gnc_file_export (GtkWindow *parent)
1253 const char *filename;
1254 char *default_dir = NULL;
1263 default_dir = g_path_get_dirname( filepath );
1264 g_free ( filepath );
1267 default_dir = gnc_get_default_directory(GNC_PREFS_GROUP_EXPORT);
1269 filename = gnc_file_dialog (parent,
_(
"Save"),
1270 gnc_file_chooser_get_datafile_filters(),
1271 default_dir, GNC_FILE_DIALOG_SAVE);
1273 g_free ( default_dir );
1274 if (!filename)
return;
1276 gnc_file_do_export (parent, filename);
1285check_file_path (
const char *path)
1288 gchar *dir = g_path_get_dirname(path);
1289 const gchar *dotgnucash = gnc_userdata_dir();
1290 char *dirpath = dir;
1295 while (strcmp(dir = g_path_get_dirname(dirpath), dirpath) != 0)
1297 if (strcmp(dirpath, dotgnucash) == 0)
1313gnc_file_do_export(GtkWindow *parent,
const char * filename)
1315 QofSession *current_session, *new_session;
1320 const gchar *oldfile;
1322 gchar *scheme = NULL;
1323 gchar *hostname = NULL;
1324 gchar *username = NULL;
1325 gchar *password = NULL;
1336 show_session_error (parent, ERR_FILEIO_FILE_NOT_FOUND, filename,
1337 GNC_FILE_DIALOG_EXPORT);
1344 &port, &username, &password, &path);
1349 if (g_strcmp0 (scheme,
"file") == 0)
1352 scheme = g_strdup (
"xml");
1354 username, password, path);
1356 newfile = norm_file;
1364 if (check_file_path (path))
1367 GNC_FILE_DIALOG_SAVE);
1370 gnc_set_default_directory (GNC_PREFS_GROUP_OPEN_SAVE,
1371 g_path_get_dirname(path));
1375 current_session = gnc_get_current_session ();
1376 oldfile = qof_session_get_url(current_session);
1377 if (strlen (oldfile) && (strcmp(oldfile, newfile) == 0))
1381 GNC_FILE_DIALOG_EXPORT);
1389 new_session = qof_session_new (NULL);
1396 const char *format =
_(
"The file %s already exists. "
1397 "Are you sure you want to overwrite it?");
1405 if (!gnc_verify_dialog (parent, FALSE, format, name))
1414 if (!show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_EXPORT))
1424 gnc_set_busy_cursor (NULL, TRUE);
1425 gnc_window_show_progress(
_(
"Exporting fileā¦"), 0.0);
1426 ok = qof_session_export (new_session, current_session,
1427 gnc_window_show_progress);
1428 gnc_window_show_progress(NULL, -1.0);
1429 gnc_unset_busy_cursor (NULL);
1431 qof_session_destroy (new_session);
1438 const char *format =
_(
"There was an error saving the file.\n\n%s");
1440 gnc_error_dialog (parent, format, strerror(errno));
1445static gboolean been_here_before = FALSE;
1448gnc_file_save (GtkWindow *parent)
1451 const char * newfile;
1452 QofSession *session;
1455 if (!gnc_current_session_exist ())
1461 session = gnc_get_current_session ();
1463 if (!strlen (qof_session_get_url (session)))
1465 gnc_file_save_as (parent);
1471 gint response = gnc_ok_cancel_dialog(parent,
1472 GTK_RESPONSE_CANCEL,
1473 _(
"The database was opened read-only. "
1474 "Do you want to save it to a different place?"));
1475 if (response == GTK_RESPONSE_OK)
1477 gnc_file_save_as (parent);
1484 gnc_set_busy_cursor (NULL, TRUE);
1485 gnc_window_show_progress(
_(
"Writing fileā¦"), 0.0);
1487 gnc_window_show_progress(NULL, -1.0);
1488 gnc_unset_busy_cursor (NULL);
1494 if (ERR_BACKEND_NO_ERR != io_err)
1496 newfile = qof_session_get_url(session);
1497 show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_SAVE);
1499 if (been_here_before)
return;
1500 been_here_before = TRUE;
1501 gnc_file_save_as (parent);
1502 been_here_before = FALSE;
1507 gnc_add_history (session);
1508 gnc_hook_run(HOOK_BOOK_SAVED, session);
1517gnc_file_save_as (GtkWindow *parent)
1519 const gchar *filename;
1520 gchar *default_dir = NULL;
1525 if (!gnc_current_session_exist ())
1527 LEAVE(
"No Session.");
1535 default_dir = g_path_get_dirname( filepath );
1536 g_free ( filepath );
1539 default_dir = gnc_get_default_directory(GNC_PREFS_GROUP_OPEN_SAVE);
1541 filename = gnc_file_dialog (parent,
_(
"Save"),
1542 gnc_file_chooser_get_datafile_filters(),
1543 default_dir, GNC_FILE_DIALOG_SAVE);
1545 g_free ( default_dir );
1546 if (!filename)
return;
1548 gnc_file_do_save_as (parent, filename);
1554gnc_file_do_save_as (GtkWindow *parent,
const char* filename)
1556 QofSession *new_session;
1557 QofSession *session;
1560 const gchar *oldfile;
1562 gchar *scheme = NULL;
1563 gchar *hostname = NULL;
1564 gchar *username = NULL;
1565 gchar *password = NULL;
1579 show_session_error (parent, ERR_FILEIO_FILE_NOT_FOUND, filename,
1580 GNC_FILE_DIALOG_SAVE);
1587 &port, &username, &password, &path);
1592 if (g_strcmp0 (scheme,
"file") == 0)
1595 scheme = g_strdup (
"xml");
1597 username, password, path);
1599 newfile = norm_file;
1607 if (check_file_path (path))
1610 GNC_FILE_DIALOG_SAVE);
1613 gnc_set_default_directory (GNC_PREFS_GROUP_OPEN_SAVE,
1614 g_path_get_dirname (path));
1619 session = gnc_get_current_session ();
1620 oldfile = qof_session_get_url(session);
1621 if (strlen (oldfile) && (strcmp(oldfile, newfile) == 0))
1624 gnc_file_save (parent);
1630 gnc_suspend_gui_refresh ();
1632 gnc_resume_gui_refresh ();
1639 new_session = qof_session_new (NULL);
1647 const char *format =
_(
"The file %s already exists. "
1648 "Are you sure you want to overwrite it?");
1657 if (!gnc_verify_dialog (parent, FALSE, format, name ))
1660 qof_session_destroy (new_session);
1671 if (!show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_SAVE))
1679 else if ((ERR_FILEIO_FILE_NOT_FOUND == io_err) ||
1683 if (!show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_SAVE))
1695 if (ERR_BACKEND_NO_ERR != io_err)
1697 show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_SAVE);
1699 qof_session_destroy (new_session);
1711 path, username, password );
1727 gnc_set_busy_cursor (NULL, TRUE);
1728 gnc_window_show_progress(
_(
"Writing fileā¦"), 0.0);
1730 gnc_window_show_progress(NULL, -1.0);
1731 gnc_unset_busy_cursor (NULL);
1734 if ( ERR_BACKEND_NO_ERR != io_err )
1739 show_session_error (parent, io_err, newfile, GNC_FILE_DIALOG_SAVE);
1742 qof_session_destroy( new_session );
1750 gnc_gui_component_reset_session (session, new_session);
1751 gnc_clear_current_session();
1752 gnc_set_current_session( new_session );
1757 gnc_add_history (new_session);
1758 gnc_hook_run(HOOK_BOOK_SAVED, new_session);
1769gnc_file_revert (GtkWindow *parent)
1771 QofSession *session;
1772 const gchar *fileurl, *filename, *tmp;
1773 const gchar *title =
_(
"Reverting will discard all unsaved changes to %s. Are you sure you want to proceed?");
1778 session = gnc_get_current_session();
1779 fileurl = qof_session_get_url(session);
1780 if (!strlen (fileurl))
1781 fileurl =
_(
"<unknown>");
1782 if ((tmp = strrchr(fileurl,
'/')) != NULL)
1787 if (!gnc_verify_dialog (parent, FALSE, title, filename))
1796 QofSession *session;
1798 if (!gnc_current_session_exist ())
1800 gnc_set_busy_cursor (NULL, TRUE);
1801 session = gnc_get_current_session ();
1807 gnc_hook_run(HOOK_BOOK_CLOSED, session);
1808 gnc_close_gui_component_by_session (session);
1810 gnc_clear_current_session();
1813 gnc_unset_busy_cursor (NULL);
1817gnc_file_set_shutdown_callback (GNCShutdownCB cb)
1823gnc_file_save_in_progress (
void)
1825 if (gnc_current_session_exist())
1827 QofSession *session = gnc_get_current_session();
Account handling public routines.
Anchor Scheduled Transaction info in a book.
convert single-entry accounts to clean double-entry
API for the transaction logger.
Commodity handling public routines.
All type declarations for the whole Gnucash engine.
Utility functions for file access.
File path resolution utility functions.
Functions to save and retrieve passwords.
Functions providing the file history menu.
Functions to load, save and get gui state.
utility functions for the GnuCash UI
Utility functions for convert uri in separate components and back.
Functions that are supported by all types of windows.
GList * gnc_account_list_name_violations(QofBook *book, const gchar *separator)
Runs through all the accounts and returns a list of account names that contain the provided separator...
gchar * gnc_account_name_violations_errmsg(const gchar *separator, GList *invalid_account_names)
Composes a translatable error message showing which account names clash with the current account sepa...
const gchar * gnc_get_account_separator_string(void)
Returns the account separation character chosen by the user.
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
QofBackendError qof_session_pop_error(QofSession *session)
The qof_session_pop_error() routine can be used to obtain the reason for any failure.
void qof_session_swap_data(QofSession *session_1, QofSession *session_2)
The qof_session_swap_data () method swaps the book of the two given sessions.
void qof_session_save(QofSession *session, QofPercentageFunc percentage_func)
The qof_session_save() method will commit all changes that have been made to the session.
QofBackendError
The errors that can be reported to the GUI & other front-end users.
gboolean qof_session_save_in_progress(const QofSession *session)
The qof_session_not_saved() subroutine will return TRUE if any data in the session hasn't been saved ...
QofBackendError qof_session_get_error(QofSession *session)
The qof_session_get_error() routine can be used to obtain the reason for any failure.
void qof_session_begin(QofSession *session, const char *uri, SessionOpenMode mode)
Begins a new session.
void qof_session_safe_save(QofSession *session, QofPercentageFunc percentage_func)
A special version of save used in the sql backend which moves the existing tables aside,...
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
@ ERR_FILEIO_FILE_EACCES
No read access permission for the given file.
@ ERR_SQL_DB_BUSY
database is busy, cannot upgrade version
@ ERR_BACKEND_NO_SUCH_DB
the named database doesn't exist
@ ERR_BACKEND_BAD_URL
Can't parse url.
@ ERR_BACKEND_STORE_EXISTS
File exists, data would be destroyed.
@ ERR_BACKEND_NO_HANDLER
no backend handler found for this access method (ENOSYS)
@ ERR_BACKEND_LOCKED
in use by another user (ETXTBSY)
@ ERR_FILEIO_WRITE_ERROR
couldn't write to the file
@ ERR_BACKEND_SERVER_ERR
error in response from server
@ ERR_FILEIO_FILE_EMPTY
file exists, is readable, but is empty
@ ERR_BACKEND_NO_BACKEND
Backend * pointer was unexpectedly null.
@ ERR_FILEIO_NO_ENCODING
file does not specify encoding
@ ERR_BACKEND_DATA_CORRUPT
data in db is corrupt
@ ERR_SQL_DB_TOO_OLD
database is old and needs upgrading
@ ERR_SQL_DB_TOO_NEW
database is newer, we can't write to it
@ ERR_BACKEND_CANT_CONNECT
bad dbname/login/passwd or network failure
@ ERR_FILEIO_FILE_BAD_READ
read failed or file prematurely truncated
@ ERR_FILEIO_FILE_UPGRADE
file will be upgraded and not be able to be read by prior versions - warn users
@ ERR_FILEIO_UNKNOWN_FILE_TYPE
didn't recognize the file type
@ ERR_SQL_DBI_UNTESTABLE
could not complete test for LibDBI bug
@ ERR_BACKEND_MISC
undetermined error
@ ERR_FILEIO_BACKUP_ERROR
couldn't make a backup of the file
@ ERR_BACKEND_TOO_NEW
file/db version newer than what we can read
@ ERR_FILEIO_RESERVED_WRITE
User attempt to write to a directory reserved for internal use by GnuCash.
@ ERR_FILEIO_PARSE_ERROR
couldn't parse the data in the file
@ ERR_BACKEND_PERM
user login successful, but no permissions to access the desired object
@ ERR_FILEIO_FILE_NOT_FOUND
not found / no such file
@ ERR_BACKEND_READONLY
cannot write to file/directory
@ ERR_FILEIO_FILE_TOO_OLD
file version so old we can't read it
@ ERR_BACKEND_CONN_LOST
Lost connection to server.
@ ERR_SQL_BAD_DBI
LibDBI has numeric errors.
@ SESSION_READ_ONLY
Create a new store at the URI even if a store already exists there.
@ SESSION_NEW_STORE
Open will fail if the URI doesn't exist or is locked.
@ SESSION_BREAK_LOCK
Open the session read-only, ignoring any existing lock and not creating one if the URI isn't locked.
@ SESSION_NEW_OVERWRITE
Create a new store at the URI.
void qof_book_mark_readonly(QofBook *book)
Mark the book as read only.
void qof_book_mark_session_dirty(QofBook *book)
The qof_book_mark_dirty() routine marks the book as having been modified.
gboolean qof_book_session_not_saved(const QofBook *book)
qof_book_not_saved() returns the value of the session_dirty flag, set when changes to any object in t...
QofBook * qof_book_new(void)
Allocate, initialise and return a new QofBook.
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
void qof_book_mark_session_saved(QofBook *book)
The qof_book_mark_saved() routine marks the book as having been saved (to a file, to a database).
time64 qof_book_get_session_dirty_time(const QofBook *book)
Retrieve the earliest modification time on the book.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
time64 gnc_time(time64 *tbuf)
get the current time
void gnc_account_reset_convert_bayes_to_flat(void)
Reset the flag that indicates the function imap_convert_bayes_to_flat has been run.
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account.
void qof_event_resume(void)
Resume engine event generation.
void qof_event_suspend(void)
Suspend all engine events.
void gnc_keyring_set_password(const gchar *access_method, const gchar *server, guint32 port, const gchar *service, const gchar *user, const gchar *password)
Attempt to store a password in some trusted keystore.
gboolean gnc_keyring_get_password(GtkWidget *parent, const gchar *access_method, const gchar *server, guint32 port, const gchar *service, gchar **user, gchar **password)
Attempt to retrieve a password to connect to a remote service.
gboolean gnc_main_window_all_finish_pending(void)
Tell all pages in all windows to finish any outstanding activities.
void gnc_state_save(const QofSession *session)
Save the state to a state file on disk for the given session.
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
#define LEAVE(format, args...)
Print a function exit debugging message.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
void gnc_history_add_file(const char *newfile)
Add a file name to the front of the file "history list".
void gnc_history_remove_file(const char *oldfile)
Remove all occurrences of a file name from the history list.
gboolean gnc_history_test_for_file(const char *oldfile)
Test for a file name existing in the history list.
char * gnc_history_get_last(void)
Retrieve the name of the file most recently accessed.
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
void xaccAccountScrubColorNotSet(QofBook *book)
Remove color slots that have a "Not Set" value, since 2.4.0, fixed in 3.4 This should only be run onc...
void xaccLogEnable(void)
document me
void xaccLogDisable(void)
document me
gchar * gnc_features_test_unknown(QofBook *book)
Test if the current book relies on features only introduced in a more recent version of GnuCash.
gchar * gnc_uri_get_path(const gchar *uri)
Extracts the path part from a uri.
gboolean gnc_uri_targets_local_fs(const gchar *uri)
Checks if the given uri is either a valid file uri or a local filesystem path.
gboolean gnc_uri_is_file_scheme(const gchar *scheme)
Checks if the given scheme is used to refer to a file (as opposed to a network service like a databas...
gboolean gnc_uri_is_file_uri(const gchar *uri)
Checks if the given uri defines a file (as opposed to a network service like a database or web url)
gchar * gnc_uri_add_extension(const gchar *uri, const gchar *extension)
Adds an extension to the uri if:
gchar * gnc_uri_normalize_uri(const gchar *uri, gboolean allow_password)
Composes a normalized uri starting from any uri (filename, db spec,...).
gchar * gnc_uri_create_uri(const gchar *scheme, const gchar *hostname, gint32 port, const gchar *username, const gchar *password, const gchar *path)
Composes a normalized uri starting from its separate components.
void gnc_uri_get_components(const gchar *uri, gchar **scheme, gchar **hostname, gint32 *port, gchar **username, gchar **password, gchar **path)
Converts a uri in separate components.
void qof_session_ensure_all_data_loaded(QofSession *session)
Ensure all of the data is loaded from the session.