GnuCash  5.6-150-g038405b370+
assistant-csv-export.c
Go to the documentation of this file.
1 /*******************************************************************\
2  * assistant-csv-export.c -- An assistant for exporting Accounts *
3  * and Transactions to a file *
4  * *
5  * Copyright (C) 2012 Robert Fewell *
6  * *
7  * This program is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU General Public License as *
9  * published by the Free Software Foundation; either version 2 of *
10  * the License, or (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License*
18  * along with this program; if not, contact: *
19  * *
20  * Free Software Foundation Voice: +1-617-542-5942 *
21  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22  * Boston, MA 02110-1301, USA gnu@gnu.org *
23 \********************************************************************/
28 #include <config.h>
29 
30 #include <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 
33 #include "gnc-ui.h"
34 #include "gnc-uri-utils.h"
35 #include "gnc-component-manager.h"
36 #include "gnc-date-edit.h"
37 #include "gnc-prefs.h"
38 #include "gnc-tree-view-account.h"
39 #include "dialog-utils.h"
40 #include "Query.h"
41 #include "Transaction.h"
42 
43 #include "assistant-csv-export.h"
44 #include "csv-tree-export.h"
46 
47 #define GNC_PREFS_GROUP "dialogs.export.csv"
48 #define GNC_PREF_PANED_POS "paned-position"
49 #define ASSISTANT_CSV_EXPORT_CM_CLASS "assistant-csv-export"
50 
51 /* This static indicates the debugging module that this .o belongs to. */
52 static QofLogModule log_module = GNC_MOD_ASSISTANT;
53 
54 /*************************************************************************/
55 
56 void csv_export_assistant_prepare (GtkAssistant *assistant, GtkWidget *page, gpointer user_data);
57 void csv_export_assistant_finish (GtkAssistant *gtkassistant, gpointer user_data);
58 void csv_export_assistant_cancel (GtkAssistant *gtkassistant, gpointer user_data);
59 void csv_export_assistant_close (GtkAssistant *gtkassistant, gpointer user_data);
60 
61 void csv_export_assistant_start_page_prepare (GtkAssistant *assistant, gpointer user_data);
62 void csv_export_assistant_account_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
63 void csv_export_assistant_file_page_prepare (GtkAssistant *assistant, gpointer user_data);
64 void csv_export_assistant_finish_page_prepare (GtkAssistant *assistant, gpointer user_data);
65 void csv_export_assistant_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
66 
67 void csv_export_quote_cb (GtkToggleButton *button, gpointer user_data);
68 void csv_export_simple_cb (GtkToggleButton *button, gpointer user_data);
69 void csv_export_sep_cb (GtkWidget *radio, gpointer user_data);
70 void csv_export_custom_entry_cb (GtkWidget *widget, gpointer user_data);
71 
72 void csv_export_show_range_cb (GtkRadioButton *button, gpointer user_data);
73 void csv_export_start_date_cb (GtkWidget *radio, gpointer user_data);
74 void csv_export_end_date_cb (GtkWidget *radio, gpointer user_data);
75 
76 void csv_export_file_chooser_file_activated_cb (GtkFileChooser *chooser, CsvExportInfo *info);
77 void csv_export_file_chooser_selection_changed_cb (GtkFileChooser *chooser, CsvExportInfo *info);
78 
79 static const gchar *start_tree_string = N_(
80  "This assistant will help you export the Account Tree to a file "
81  "with the separator specified below.\n\n"
82  "Select the settings you require for the file and then click \"Next\" "
83  "to proceed or \"Cancel\" to abort the export.\n");
84 
85 static const gchar *start_trans_common_string = N_(
86  /* Translators: %s is one of the following paragraphs about rows/transaction. */
87  "This assistant will help you export the Transactions to a file "
88  "with the separator specified below.\n\n"
89  "%s\n\n"
90  "While a transaction may have splits in several of the selected accounts "
91  "it will only be exported once. It will appear under the first processed "
92  "account it has a split in.\n\n"
93  "The Price/Rate output format is controlled by the preference\n"
94  "\"Numbers, Date, Time\"->\"Force Prices to display as decimals\".\n\n"
95  "Select the settings you require for the file and then click \"Next\" "
96  "to proceed or \"Cancel\" to abort the export.\n");
97 
98 static const gchar *start_trans_multi_string = N_(
99  "There will be multiple rows for each transaction with each row "
100  "representing one split.");
101 
102 static const gchar *start_trans_simple_string = N_(
103  "There will be one row for each transaction, equivalent to a single row "
104  "in a register in 'Basic Ledger' mode. As such some transfer detail "
105  "could be lost.");
106 
107 static const gchar *finish_tree_string = N_(
108  /* Translators: %s is the file name. */
109  "The account tree will be exported to the file '%s' when you click \"Apply\".\n\n"
110  "You can also verify your selections by clicking on \"Back\" or \"Cancel\" to abort the export.\n");
111 
112 static const gchar *finish_trans_string = N_(
113  /* Translators: %s is the file name and %u the number of accounts. */
114  "When you click \"Apply\", the transactions will be exported to the file '%s' "
115  "and the number of accounts exported will be %u.\n\n"
116  "You can also verify your selections by clicking on \"Back\" or \"Cancel\" to abort the export.\n");
117 
118 static const gchar *finish_trans_search_gl_string = N_(
119  /* Translators: %s is the file name. */
120  "When you click \"Apply\", the transactions will be exported to the file '%s'.\n\n"
121  "You can also verify your selections by clicking on \"Back\" or \"Cancel\" to abort the export.\n");
122 
123 
124 /**************************************************
125  * csv_export_assistant_check_filename
126  *
127  * check for a valid filename for GtkFileChooser callbacks
128  **************************************************/
129 static gboolean
130 csv_export_assistant_check_filename (GtkFileChooser *chooser,
131  CsvExportInfo *info)
132 {
133  gchar *file_name = gtk_file_chooser_get_filename (chooser);
134 
135  /* Test for a valid filename and not a directory */
136  if (file_name && !g_file_test (file_name, G_FILE_TEST_IS_DIR))
137  {
138  gchar *filepath = gnc_uri_get_path (file_name);
139  gchar *filedir = g_path_get_dirname (filepath);
140 
141  g_free (info->file_name);
142  info->file_name = g_strdup (file_name);
143 
144  g_free (info->starting_dir);
145  info->starting_dir = g_strdup (filedir);
146 
147  g_free (filedir);
148  g_free (filepath);
149  g_free (file_name);
150 
151  DEBUG("file_name selected is %s", info->file_name);
152  DEBUG("starting directory is %s", info->starting_dir);
153  return TRUE;
154  }
155  g_free (file_name);
156  return FALSE;
157 }
158 
159 
160 /**************************************************
161  * csv_export_file_chooser_file_activated_cb
162  *
163  * call back for GtkFileChooser file-activated signal
164  **************************************************/
165 void
166 csv_export_file_chooser_file_activated_cb (GtkFileChooser *chooser,
167  CsvExportInfo *info)
168 {
169  GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
170  gtk_assistant_set_page_complete (assistant, info->file_page, FALSE);
171 
172  /* Test for a valid filename and not a directory */
173  if (csv_export_assistant_check_filename (chooser, info))
174  {
175  gtk_assistant_set_page_complete (assistant, info->file_page, TRUE);
176  gtk_assistant_next_page (assistant);
177  }
178 }
179 
180 
181 /**************************************************
182  * csv_export_file_chooser_selection_changed_cb
183  *
184  * call back for GtkFileChooser widget
185  **************************************************/
186 void
187 csv_export_file_chooser_selection_changed_cb (GtkFileChooser *chooser,
188  CsvExportInfo *info)
189 {
190  GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
191 
192  /* Enable the "Next" button based on a valid filename */
193  gtk_assistant_set_page_complete (assistant, info->file_page,
194  csv_export_assistant_check_filename (chooser, info));
195 }
196 
197 
198 /*******************************************************
199  * csv_export_sep_cb
200  *
201  * call back for type of separator required
202  *******************************************************/
203 void
204 csv_export_sep_cb (GtkWidget *radio, gpointer user_data)
205 {
206  CsvExportInfo *info = user_data;
207  GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
208  const gchar *name;
209 
210  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(radio)))
211  {
212  LEAVE("1st callback of pair. Defer to 2nd callback.");
213  return;
214  }
215 
216  name = gtk_buildable_get_name (GTK_BUILDABLE(radio));
217 
218  gtk_widget_set_sensitive (info->custom_entry, FALSE);
219  info->use_custom = FALSE;
220  gtk_assistant_set_page_complete (assistant, info->start_page, TRUE);
221 
222  if (g_strcmp0 (name, "comma_radio") == 0)
223  info->separator_str = ",";
224  if (g_strcmp0 (name, "colon_radio") == 0)
225  info->separator_str = ":";
226  if (g_strcmp0 (name, "semicolon_radio") == 0)
227  info->separator_str = ";";
228 
229  if (g_strcmp0 (name, "custom_radio") == 0)
230  {
231  gtk_widget_set_sensitive (info->custom_entry, TRUE);
232  info->use_custom = TRUE;
233  if (gtk_entry_get_text_length (GTK_ENTRY(info->custom_entry)) == 0)
234  gtk_assistant_set_page_complete (assistant, info->start_page, FALSE);
235  }
236 }
237 
238 
239 /*******************************************************
240  * csv_export_quote_cb
241  *
242  * call back for use of quotes
243  *******************************************************/
244 void
245 csv_export_quote_cb (GtkToggleButton *button, gpointer user_data)
246 {
247  CsvExportInfo *info = user_data;
248 
249  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button)))
250  info->use_quotes = TRUE;
251  else
252  info->use_quotes = FALSE;
253 }
254 
255 /*******************************************************
256  * csv_export_simple_cb
257  *
258  * call back for use of simple_layout
259  *******************************************************/
260 void
261 csv_export_simple_cb (GtkToggleButton *button, gpointer user_data)
262 {
263  CsvExportInfo *info = user_data;
264 
265  info->simple_layout = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button));
266 
267  gchar *msg = NULL;
268  if (info->simple_layout)
269  msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_simple_string));
270  else
271  msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_multi_string));
272 
273  gtk_label_set_text (GTK_LABEL(info->start_label), msg);
274  g_free (msg);
275 }
276 
277 /*******************************************************
278  * csv_export_custom_entry_cb
279  *
280  * call back for custom separator
281  *******************************************************/
282 void
283 csv_export_custom_entry_cb (GtkWidget *widget, gpointer user_data)
284 {
285  CsvExportInfo *info = user_data;
286  GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
287  const gchar *custom_str;
288 
289  custom_str = gtk_entry_get_text (GTK_ENTRY(info->custom_entry));
290  info->separator_str = strdup (custom_str);
291 
292  if (info->use_custom == TRUE && gtk_entry_get_text_length (GTK_ENTRY(info->custom_entry)) == 0)
293  gtk_assistant_set_page_complete (assistant, info->start_page, FALSE);
294  else
295  gtk_assistant_set_page_complete (assistant, info->start_page, TRUE);
296 }
297 
298 
299 /*******************************************************
300  * load_settings
301  *
302  * load the default settings for the assistant
303  *******************************************************/
304 static void
305 load_settings (CsvExportInfo *info)
306 {
307  info->use_quotes = FALSE;
308  info->simple_layout = FALSE;
309  info->separator_str = ",";
310  info->file_name = NULL;
311  info->starting_dir = NULL;
312 
313  /* The default directory for the user to select files. */
314  info->starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
315 }
316 
317 /* =============================================================== */
318 
319 /*******************************************************
320  * csv_export_cursor_changed_cb
321  *
322  * call back for cursor selection in account tree
323  *******************************************************/
324 static void
325 csv_export_cursor_changed_cb (GtkWidget *widget, gpointer user_data)
326 {
327  CsvExportInfo *info = user_data;
328  GncTreeViewAccount *account_tree;
329  Account *account;
330  gint num_children;
331 
332  account_tree = GNC_TREE_VIEW_ACCOUNT (info->csva.account_treeview);
333  account = gnc_tree_view_account_get_cursor_account (account_tree);
334  if (!account)
335  {
336  gtk_widget_set_sensitive (info->csva.select_button, FALSE);
337  return;
338  }
339  num_children = gnc_tree_view_account_count_children (account_tree, account);
340  gtk_widget_set_sensitive (info->csva.select_button, num_children > 0);
341 }
342 
343 
344 /*******************************************************
345  * show_acct_type_accounts
346  *
347  * show required accounts in account tree
348  *******************************************************/
349 static void
350 show_acct_type_accounts (CsvExportInfo *info)
351 {
352  GncTreeViewAccount *tree;
353  AccountViewInfo Viewinfo;
354  GNCAccountType type;
355 
356  tree = GNC_TREE_VIEW_ACCOUNT (info->csva.account_treeview);
357 
358  gnc_tree_view_account_get_view_info (tree, &Viewinfo);
359 
360  for (type = 0; type < NUM_ACCOUNT_TYPES; type++) /* from Account.h */
361  {
362  Viewinfo.include_type[type] = ((type == ACCT_TYPE_BANK) ||
363  (type == ACCT_TYPE_CASH) ||
364  (type == ACCT_TYPE_CREDIT) ||
365  (type == ACCT_TYPE_ASSET) ||
366  (type == ACCT_TYPE_LIABILITY) ||
367  (type == ACCT_TYPE_STOCK) ||
368  (type == ACCT_TYPE_MUTUAL) ||
369  (type == ACCT_TYPE_INCOME) ||
370  (type == ACCT_TYPE_EXPENSE) ||
371  (type == ACCT_TYPE_EQUITY) ||
372  (type == ACCT_TYPE_RECEIVABLE)||
373  (type == ACCT_TYPE_PAYABLE) ||
374  (type == ACCT_TYPE_ROOT) ||
375  (type == ACCT_TYPE_TRADING));
376  }
377  gnc_tree_view_account_set_view_info (tree, &Viewinfo);
378  csv_export_cursor_changed_cb (GTK_WIDGET(tree), info);
379 }
380 
381 
382 /*******************************************************
383  * update_accounts_tree
384  *
385  * update the account tree
386  *******************************************************/
387 static void
388 update_accounts_tree (CsvExportInfo *info)
389 {
390  GncTreeViewAccount *tree;
391  GtkTreeSelection* selection;
392  GtkWidget *label;
393  int num_accounts;
394  char *string;
395 
396  tree = GNC_TREE_VIEW_ACCOUNT(info->csva.account_treeview);
397  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
398  num_accounts = gtk_tree_selection_count_selected_rows (selection);
399 
400  label = info->csva.num_acct_label;
401  string = g_strdup_printf (_("Accounts Selected: %d"), num_accounts);
402  gtk_label_set_text (GTK_LABEL (label), string);
403  g_free (string);
404 }
405 
406 
407 /*******************************************************
408  * csv_export_account_changed_cb
409  *
410  * update account list after selection changed
411  *******************************************************/
412 static void
413 csv_export_account_changed_cb (GtkTreeSelection *selection,
414  gpointer user_data)
415 {
416 
417  g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
418 
419  CsvExportInfo *info = user_data;
420 
421  GncTreeViewAccount *view = GNC_TREE_VIEW_ACCOUNT(info->csva.account_treeview);
422  info->csva.account_list = gnc_tree_view_account_get_selected_accounts (view);
423 
424  /* Enable the "Next" Assistant Button if we have accounts */
425  GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
426  if (g_list_length (info->csva.account_list) > 0)
427  gtk_assistant_set_page_complete (assistant, info->account_page, TRUE);
428  else
429  gtk_assistant_set_page_complete (assistant, info->account_page, FALSE);
430 
431  update_accounts_tree (info);
432 }
433 
434 
435 /*******************************************************
436  * csv_export_select_all_clicked_cb
437  *
438  * select all the accounts
439  *******************************************************/
440 static void
441 csv_export_select_all_clicked_cb (GtkWidget *widget, gpointer user_data)
442 {
443  CsvExportInfo *info = user_data;
444  GtkTreeSelection *selection = gtk_tree_view_get_selection
445  (GTK_TREE_VIEW (info->csva.account_treeview));
446 
447  gtk_tree_view_expand_all (GTK_TREE_VIEW (info->csva.account_treeview));
448  gtk_tree_selection_select_all (selection);
449 
450  gtk_widget_grab_focus (info->csva.account_treeview);
451 }
452 
453 
454 /*******************************************************
455  * csv_export_select_subaccounts_clicked_cb
456  *
457  * select all the sub accounts
458  *******************************************************/
459 static void
460 csv_export_select_subaccounts_clicked_cb (GtkWidget *widget, gpointer user_data)
461 {
462  CsvExportInfo *info = user_data;
463  GncTreeViewAccount *account_tree;
464  Account *account;
465 
466  account_tree = GNC_TREE_VIEW_ACCOUNT (info->csva.account_treeview);
467  account = gnc_tree_view_account_get_cursor_account (account_tree);
468  if (!account)
469  return;
470 
471  gnc_tree_view_account_select_subaccounts (account_tree, account);
472 
473  gtk_widget_grab_focus (info->csva.account_treeview);
474 }
475 
476 /* =============================================================== */
477 
478 /*******************************************************
479  * get_filter_times
480  *
481  * get the start and end times from the dialog
482  *******************************************************/
483 static void
484 get_filter_times (CsvExportInfo *info)
485 {
486  time64 time_val;
487 
488  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csvd.start_date_choose)))
489  {
490  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT(info->csvd.start_date));
491  time_val = gnc_time64_get_day_start (time_val);
492  info->csvd.start_time = time_val;
493  }
494  else
495  {
496  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csvd.start_date_today)))
497  info->csvd.start_time = gnc_time64_get_today_start();
498  else
499  info->csvd.start_time = info->csvd.earliest_time;
500  }
501 
502  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csvd.end_date_choose)))
503  {
504  time_val = gnc_date_edit_get_date (GNC_DATE_EDIT(info->csvd.end_date));
505  time_val = gnc_time64_get_day_end (time_val);
506  info->csvd.end_time = time_val;
507  }
508  else
509  {
510  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csvd.end_date_today)))
511  info->csvd.end_time = gnc_time64_get_today_end();
512  else
513  info->csvd.end_time = info->csvd.latest_time;
514  }
515 }
516 
517 
518 /*******************************************************
519  * csv_export_show_range_cb
520  *
521  * call back for show range button
522  *******************************************************/
523 void
524 csv_export_show_range_cb (GtkRadioButton *button, gpointer user_data)
525 {
526  CsvExportInfo *info = user_data;
527  gboolean active;
528 
529  g_return_if_fail (GTK_IS_RADIO_BUTTON(button));
530 
531  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button));
532 
533  if (!active)
534  {
535  info->csvd.start_time = info->csvd.earliest_time;
536  info->csvd.end_time = info->csvd.latest_time;
537  }
538  else
539  get_filter_times (info);
540 
541  gtk_widget_set_sensitive (info->csvd.table, active);
542 }
543 
544 
545 /*******************************************************
546  * csv_export_date_changed_cb
547  *
548  * call back for when a date changes
549  *******************************************************/
550 static void
551 csv_export_date_changed_cb (GtkWidget *w, gpointer user_data)
552 {
553  CsvExportInfo *info = user_data;
554 
555  get_filter_times (info);
556 }
557 
558 
559 /*******************************************************
560  * csv_export_start_date_cb
561  *
562  * call back for when the start date changes
563  *******************************************************/
564 void
565 csv_export_start_date_cb (GtkWidget *radio, gpointer user_data)
566 {
567  CsvExportInfo *info = user_data;
568  const gchar *name;
569  gboolean active;
570 
571  g_return_if_fail (GTK_IS_RADIO_BUTTON(radio));
572 
573  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(radio)))
574  {
575  LEAVE("1st callback of pair. Defer to 2nd callback.");
576  return;
577  }
578 
579  name = gtk_buildable_get_name (GTK_BUILDABLE(radio));
580  active = (g_strcmp0 (name, "start_date_choose") == 0 ? 1 : 0 );
581  gtk_widget_set_sensitive (info->csvd.start_date, active);
582  get_filter_times (info);
583 }
584 
585 
586 /*******************************************************
587  * csv_export_end_date_cb
588  *
589  * call back for when the end date changes
590  *******************************************************/
591 void
592 csv_export_end_date_cb (GtkWidget *radio, gpointer user_data)
593 {
594  CsvExportInfo *info = user_data;
595  const gchar *name;
596  gboolean active;
597 
598  g_return_if_fail (GTK_IS_RADIO_BUTTON(radio));
599 
600  if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(radio)))
601  {
602  LEAVE("1st callback of pair. Defer to 2nd callback.");
603  return;
604  }
605 
606  name = gtk_buildable_get_name (GTK_BUILDABLE(radio));
607  active = (g_strcmp0 (name, "end_date_choose") == 0 ? 1 : 0 );
608  gtk_widget_set_sensitive (info->csvd.end_date, active);
609  get_filter_times (info);
610 }
611 
612 
613 /*******************************************************************
614  * get_earliest_and_latest_in_book
615  *
616  * Find the earliest and latest dates occurring in the book.
617  *******************************************************************/
618 static void
619 get_earliest_and_latest_in_book (CsvExportInfo *info, QofBook *book)
620 {
621  QofQuery *q;
622  GSList *p1, *p2;
623  GList *res;
624  time64 etime, ltime;
625 
626  q = qof_query_create_for (GNC_ID_SPLIT);
627  qof_query_set_book (q, book);
628 
629  /* Sort by transaction date */
630  p1 = g_slist_prepend (NULL, TRANS_DATE_POSTED);
631  p1 = g_slist_prepend (p1, SPLIT_TRANS);
632  p2 = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
633  qof_query_set_sort_order (q, p1, p2, NULL);
634 
635  /* Run the query, find the earliest and latest transaction dates */
636  res = qof_query_run (q);
637 
638  if (res)
639  {
640  etime = xaccQueryGetEarliestDateFound (q);
641  ltime = xaccQueryGetLatestDateFound (q);
642  }
643  else
644  {
645  /* If no results, we don't want to bomb totally */
646  etime = gnc_time (0);
647  ltime = gnc_time (NULL);
648  }
649  info->csvd.earliest_time = gnc_time64_get_day_start (etime);
650  info->csvd.latest_time = gnc_time64_get_day_end (ltime);
651 
652  qof_query_destroy (q);
653 }
654 
655 
656 /* =============================================================== */
657 
658 
659 /*******************************************************
660  * Assistant page prepare functions
661  *******************************************************/
662 void
663 csv_export_assistant_start_page_prepare (GtkAssistant *assistant,
664  gpointer user_data)
665 {
666  CsvExportInfo *info = user_data;
667  gchar *msg = NULL;
668 
669  if (info->export_type == XML_EXPORT_TREE)
670  msg = g_strdup (_(start_tree_string));
671  else
672  msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_multi_string));
673 
674  gtk_label_set_text (GTK_LABEL(info->start_label), msg);
675  g_free (msg);
676 
677  /* Enable the Assistant Buttons */
678  gtk_assistant_set_page_complete (assistant, info->start_page, TRUE);
679 }
680 
681 
682 void
683 csv_export_assistant_account_page_prepare (GtkAssistant *assistant,
684  gpointer user_data)
685 {
686  CsvExportInfo *info = user_data;
687 
688  /* Enable the "Next" Assistant Button if we have accounts */
689  if (g_list_length(info->csva.account_list) > 0)
690  gtk_assistant_set_page_complete (assistant, info->account_page, TRUE);
691  else
692  gtk_assistant_set_page_complete (assistant, info->account_page, FALSE);
693 }
694 
695 
696 void
697 csv_export_assistant_file_page_prepare (GtkAssistant *assistant,
698  gpointer user_data)
699 {
700  CsvExportInfo *info = user_data;
701 
702  /* Set the default directory */
703  if (info->starting_dir)
704  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(info->file_chooser), info->starting_dir);
705  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(info->file_chooser), "");
706 
707  /* Disable the "Next" Assistant Button */
708  gtk_assistant_set_page_complete (assistant, info->file_page, FALSE);
709 }
710 
711 
712 void
713 csv_export_assistant_finish_page_prepare (GtkAssistant *assistant,
714  gpointer user_data)
715 {
716  CsvExportInfo *info = user_data;
717  gchar *text;
718 
719  /* Set Finish page text */
720  if (info->export_type == XML_EXPORT_TREE)
721  text = g_strdup_printf (gettext (finish_tree_string), info->file_name);
722  else
723  {
724  if ((info->export_type == XML_EXPORT_REGISTER) &&
725  (g_list_length (info->csva.account_list) == 0))
726  text = g_strdup_printf (gettext (finish_trans_search_gl_string), info->file_name);
727  else
728  text = g_strdup_printf (gettext (finish_trans_string),
729  info->file_name,
730  g_list_length (info->csva.account_list));
731  }
732  gtk_label_set_text (GTK_LABEL(info->finish_label), text);
733  g_free (text);
734 
735  /* Test if the filename exists */
736  if (g_file_test (info->file_name, G_FILE_TEST_EXISTS))
737  {
738  const char *format = _("The file %s already exists. "
739  "Are you sure you want to overwrite it?");
740 
741  /* if user says cancel, we should go back a page */
742  if (!gnc_verify_dialog (GTK_WINDOW (assistant), FALSE, format, info->file_name))
743  gtk_assistant_previous_page (assistant);
744  }
745  /* Enable the Assistant Buttons */
746  gtk_assistant_set_page_complete (assistant, info->finish_label, TRUE);
747 }
748 
749 
750 void
751 csv_export_assistant_summary_page_prepare (GtkAssistant *assistant,
752  gpointer user_data)
753 {
754  CsvExportInfo *info = user_data;
755  gchar *text, *mtext;
756  gnc_set_default_directory (GNC_PREFS_GROUP, info->starting_dir);
757 
758  if (info->failed)
759  text = _("There was a problem with the export, this could be due to lack of space, "
760  "permissions or unable to access folder. Check the trace file for further logging!\n"
761  "You may need to enable debugging.\n");
762  else
763  text = _("File exported successfully!\n");
764 
765  mtext = g_strdup_printf ("<span size=\"medium\"><b>%s</b></span>", text);
766 
767  gtk_label_set_markup (GTK_LABEL(info->summary_label), mtext);
768 
769  g_free (mtext);
770 }
771 
772 
773 void
774 csv_export_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
775  gpointer user_data)
776 {
777  CsvExportInfo *info = user_data;
778 
779  if (page == info->start_page)
780  csv_export_assistant_start_page_prepare (assistant, user_data);
781  else if (page == info->account_page)
782  csv_export_assistant_account_page_prepare (assistant, user_data);
783  else if (page == info->file_page)
784  csv_export_assistant_file_page_prepare (assistant, user_data);
785  else if (page == info->finish_label)
786  csv_export_assistant_finish_page_prepare (assistant, user_data);
787  else if (page == info->summary_label)
788  csv_export_assistant_summary_page_prepare (assistant, user_data);
789  else
790  g_assert_not_reached();
791 }
792 
793 
794 /*******************************************************
795  * Assistant call back functions
796  *******************************************************/
797 static void
798 csv_export_assistant_destroy_cb (GtkWidget *object, gpointer user_data)
799 {
800  CsvExportInfo *info = user_data;
801  gnc_unregister_gui_component_by_data (ASSISTANT_CSV_EXPORT_CM_CLASS, info);
802  g_list_free (info->csva.account_list);
803  g_free (info);
804 }
805 
806 void
807 csv_export_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
808 {
809  CsvExportInfo *info = user_data;
810  gnc_close_gui_component_by_data (ASSISTANT_CSV_EXPORT_CM_CLASS, info);
811 }
812 
813 void
814 csv_export_assistant_close (GtkAssistant *assistant, gpointer user_data)
815 {
816  CsvExportInfo *info = user_data;
817  gnc_close_gui_component_by_data (ASSISTANT_CSV_EXPORT_CM_CLASS, info);
818 }
819 
820 void
821 csv_export_assistant_finish (GtkAssistant *assistant, gpointer user_data)
822 {
823  CsvExportInfo *info = user_data;
824 
825  if (info->export_type == XML_EXPORT_TREE)
826  csv_tree_export (info);
827  else
829 }
830 
831 static void
832 csv_export_close_handler (gpointer user_data)
833 {
834  CsvExportInfo *info = user_data;
835 
836  g_free (info->file_name);
837  g_free (info->starting_dir);
838  if (info->mid_sep)
839  g_free (info->mid_sep);
840 
841  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->assistant));
842  gtk_widget_destroy (info->assistant);
843 }
844 
845 /*******************************************************
846  * Create the Assistant
847  *******************************************************/
848 static GtkWidget *
849 csv_export_assistant_create (CsvExportInfo *info)
850 {
851  GtkBuilder *builder;
852  GtkWidget *button;
853  GtkWidget *table, *hbox;
854 
855  builder = gtk_builder_new();
856  gnc_builder_add_from_file (builder , "assistant-csv-export.glade", "csv_export_assistant");
857  info->assistant = GTK_WIDGET(gtk_builder_get_object (builder, "csv_export_assistant"));
858 
859  // Set the name for this assistant so it can be easily manipulated with css
860  gtk_widget_set_name (GTK_WIDGET(info->assistant), "gnc-id-assistant-csv-export");
861  gnc_widget_style_context_add_class (GTK_WIDGET(info->assistant), "gnc-class-exports");
862 
863  /* Load default settings */
864  load_settings (info);
865 
866  /* Start Page */
867  info->start_page = GTK_WIDGET(gtk_builder_get_object(builder, "start_page"));
868  info->start_label = GTK_WIDGET(gtk_builder_get_object(builder, "start_label"));
869  info->custom_entry = GTK_WIDGET(gtk_builder_get_object(builder, "custom_entry"));
870  gtk_widget_set_sensitive (info->custom_entry, FALSE);
871 
872  /* Account Page */
873  info->account_page = GTK_WIDGET(gtk_builder_get_object(builder, "account_page"));
874 
875  if ((info->export_type == XML_EXPORT_TREE) || (info->export_type == XML_EXPORT_REGISTER))
876  {
877  GtkWidget *chkbox = GTK_WIDGET(gtk_builder_get_object(builder, "simple_layout"));
878 
879  // Don't provide simple export layout for search registers and General Journal
880  if ((info->export_type == XML_EXPORT_TREE) ||
881  (g_list_length (info->csva.account_list) == 0))
882  gtk_widget_destroy (chkbox);
883  gtk_assistant_remove_page (GTK_ASSISTANT(info->assistant), 1); //remove accounts page
884  }
885  else
886  {
887  GtkTreeView *tree_view;
888  GtkTreeSelection *selection;
889  GtkWidget *box, *label;
890 
891  info->csva.acct_info = GTK_WIDGET(gtk_builder_get_object (builder, "acct_info_vbox"));
892  info->csva.num_acct_label = GTK_WIDGET(gtk_builder_get_object (builder, "num_accounts_label"));
893 
894  tree_view = gnc_tree_view_account_new (FALSE);
895  info->csva.account_treeview = GTK_WIDGET(tree_view);
896 
897  selection = gtk_tree_view_get_selection (tree_view);
898  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
899  g_signal_connect (G_OBJECT(selection), "changed",
900  G_CALLBACK(csv_export_account_changed_cb), info);
901 
902  gtk_widget_show (info->csva.account_treeview);
903  box = GTK_WIDGET(gtk_builder_get_object (builder, "account_scroll"));
904  gtk_container_add (GTK_CONTAINER(box), info->csva.account_treeview);
905 
906  label = GTK_WIDGET(gtk_builder_get_object (builder, "accounts_label"));
907  gtk_label_set_mnemonic_widget (GTK_LABEL(label), GTK_WIDGET(tree_view));
908 
909  /* select subaccounts button */
910  button = GTK_WIDGET(gtk_builder_get_object (builder, "select_subaccounts_button"));
911  info->csva.select_button = button;
912  g_signal_connect (G_OBJECT(button), "clicked",
913  G_CALLBACK(csv_export_select_subaccounts_clicked_cb), info);
914 
915  button = GTK_WIDGET(gtk_builder_get_object (builder, "select_all_button"));
916  info->csva.select_button = button;
917  g_signal_connect (G_OBJECT(button), "clicked",
918  G_CALLBACK(csv_export_select_all_clicked_cb), info);
919 
920  g_signal_connect (G_OBJECT(info->csva.account_treeview), "cursor_changed",
921  G_CALLBACK(csv_export_cursor_changed_cb), info);
922 
923  /* Set the date info */
924  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_range"));
925 
926  /* Get the Earliest and Latest dates in Book */
927  get_earliest_and_latest_in_book (info, gnc_get_current_book());
928 
929  info->csvd.start_time = info->csvd.earliest_time;
930  info->csvd.end_time = info->csvd.latest_time;
931  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), FALSE);
932 
933  table = GTK_WIDGET(gtk_builder_get_object (builder, "select_range_table"));
934  info->csvd.table = table;
935  gtk_widget_set_sensitive (GTK_WIDGET(table), FALSE);
936 
937  info->csvd.start_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_choose"));
938  info->csvd.start_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_today"));
939  info->csvd.end_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_choose"));
940  info->csvd.end_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_today"));
941 
942  /* Start date info */
943  info->csvd.start_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
944  gtk_widget_set_sensitive (info->csvd.start_date, FALSE);
945  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_hbox"));
946  gtk_box_pack_start (GTK_BOX(hbox), info->csvd.start_date, TRUE, TRUE, 0);
947  gtk_widget_show (info->csvd.start_date);
948  gnc_date_edit_set_time (GNC_DATE_EDIT(info->csvd.start_date), info->csvd.start_time);
949  g_signal_connect (G_OBJECT(info->csvd.start_date), "date-changed",
950  G_CALLBACK(csv_export_date_changed_cb), info);
951 
952  /* End date info */
953  info->csvd.end_date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
954  gtk_widget_set_sensitive (info->csvd.end_date, FALSE);
955  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_hbox"));
956  gtk_box_pack_start (GTK_BOX(hbox), info->csvd.end_date, TRUE, TRUE, 0);
957  gtk_widget_show (info->csvd.end_date);
958  gnc_date_edit_set_time (GNC_DATE_EDIT(info->csvd.end_date), info->csvd.end_time);
959  g_signal_connect (G_OBJECT (info->csvd.end_date), "date-changed",
960  G_CALLBACK (csv_export_date_changed_cb), info);
961 
962  /* Load Accounts */
963  show_acct_type_accounts (info);
964  update_accounts_tree (info);
965  }
966 
967  /* File chooser Page */
968  info->file_page = GTK_WIDGET(gtk_builder_get_object(builder, "file_page"));
969  info->file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_SAVE);
970 
971  g_signal_connect (G_OBJECT(info->file_chooser), "selection-changed",
972  G_CALLBACK(csv_export_file_chooser_selection_changed_cb), info);
973 
974  g_signal_connect (G_OBJECT(info->file_chooser), "file-activated",
975  G_CALLBACK(csv_export_file_chooser_file_activated_cb), info);
976 
977  gtk_box_pack_start (GTK_BOX (info->file_page), info->file_chooser, TRUE, TRUE, 6);
978  gtk_widget_show (info->file_chooser);
979 
980  /* Finish Page */
981  info->finish_label = GTK_WIDGET(gtk_builder_get_object (builder, "end_page"));
982 
983  /* Summary Page */
984  info->summary_label = GTK_WIDGET(gtk_builder_get_object (builder, "summary_page"));
985 
986  g_signal_connect (G_OBJECT(info->assistant), "destroy",
987  G_CALLBACK(csv_export_assistant_destroy_cb), info);
988 
989  gnc_restore_window_size (GNC_PREFS_GROUP,
990  GTK_WINDOW(info->assistant), gnc_ui_get_main_window(NULL));
991  if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY))
992  {
993  GObject *object = gtk_builder_get_object (builder, "paned");
994  gnc_prefs_bind (GNC_PREFS_GROUP, GNC_PREF_PANED_POS, object, "position");
995  }
996 
997  gtk_builder_connect_signals (builder, info);
998  g_object_unref (G_OBJECT(builder));
999  return info->assistant;
1000 }
1001 
1002 static void
1003 gnc_file_csv_export_internal (CsvExportType export_type, Query *q, Account *acc)
1004 {
1005  CsvExportInfo *info;
1006 
1007  info = g_new0 (CsvExportInfo, 1);
1008  info->export_type = export_type;
1009 
1010  if (q)
1011  info->query = q;
1012  if (acc)
1013  info->csva.account_list = g_list_prepend(info->csva.account_list, acc);
1014 
1015  csv_export_assistant_create (info);
1016  gnc_register_gui_component (ASSISTANT_CSV_EXPORT_CM_CLASS,
1017  NULL, csv_export_close_handler,
1018  info);
1019  gtk_widget_show_all (info->assistant);
1020  gnc_window_adjust_for_screen (GTK_WINDOW(info->assistant));
1021 }
1022 
1023 
1024 /********************************************************************\
1025  * gnc_file_csv_export *
1026  * opens up a assistant to export accounts or transactions based on *
1027  * the type. *
1028  * Args: export_type *
1029  * Return: nothing *
1030 \********************************************************************/
1031 void
1032 gnc_file_csv_export (CsvExportType export_type)
1033 {
1034  gnc_file_csv_export_internal (export_type, NULL, NULL);
1035 }
1036 
1037 
1038 /********************************************************************\
1039  * gnc_file_csv_export_register *
1040  * opens up a assistant to export register transactions based. *
1041  * Args: export_type *
1042  * Args: Query *
1043  * Args: Account *
1044  * Return: nothing *
1045 \********************************************************************/
1046 void
1047 gnc_file_csv_export_register (CsvExportType export_type, Query *q, Account *acc)
1048 {
1049  gnc_file_csv_export_internal (export_type, q, acc);
1050 }
void gnc_tree_view_account_get_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will copy the current con...
GList * gnc_tree_view_account_get_selected_accounts(GncTreeViewAccount *view)
This function returns a list of the accounts associated with the selected items in the account tree v...
Account * gnc_tree_view_account_get_cursor_account(GncTreeViewAccount *view)
This function returns the account in the account tree view at the current location of the cursor...
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
Expense accounts are used to denote expenses.
Definition: Account.h:143
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *params1, QofQueryParamList *params2, QofQueryParamList *params3)
When a query is run, the results are sorted before being returned.
Definition: qofquery.cpp:1249
CSV Export Account Tree.
STRUCTS.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
Mutual Fund accounts will typically be shown in registers which show three columns: price...
Definition: Account.h:125
gchar * gnc_uri_get_path(const gchar *uri)
Extracts the path part from a uri.
stop here; the following types just aren&#39;t ready for prime time
Definition: Account.h:161
void gnc_tree_view_account_set_view_info(GncTreeViewAccount *view, AccountViewInfo *avi)
Given pointers to an account tree and old style filter block, this function will applies the settings...
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
Definition: Account.h:110
Account used to record multiple commodity transactions.
Definition: Account.h:155
CSV Export Assistant.
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
Definition: Account.h:122
void gnc_tree_view_account_select_subaccounts(GncTreeViewAccount *view, Account *account)
This function selects all sub-accounts of an account in the account tree view.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
void gnc_prefs_bind(const gchar *group, const gchar *pref_name, gpointer object, const gchar *property)
Bind a setting to a g_object property.
Definition: gnc-prefs.c:181
GtkTreeView implementation for gnucash account tree.
Income accounts are used to denote income.
Definition: Account.h:140
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
time64 gnc_time64_get_day_start(time64 time_val)
The gnc_time64_get_day_start() routine will take the given time in seconds and adjust it to the first...
Definition: gnc-date.cpp:1296
The bank account type denotes a savings or checking account held at a bank.
Definition: Account.h:107
void csv_tree_export(CsvExportInfo *info)
The csv_tree_export() will let the user export the account tree to a delimited file.
time64 gnc_time64_get_today_start(void)
The gnc_time64_get_today_start() routine returns a time64 value corresponding to the first second of ...
Definition: gnc-date.cpp:1347
void gnc_file_csv_export_register(CsvExportType export_type, Query *q, Account *acc)
The gnc_file_csv_export_register() will let the user export the active register transactions to a del...
A/P account type.
Definition: Account.h:151
void gnc_file_csv_export(CsvExportType export_type)
The gnc_file_csv_export() will let the user export the account tree or transactions to a delimited fi...
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
Definition: Account.h:116
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:101
CSV Export Transactions.
Generic api to store and retrieve preferences.
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
liability (and asset) accounts indicate generic, generalized accounts that are none of the above...
Definition: Account.h:119
gint gnc_tree_view_account_count_children(GncTreeViewAccount *view, Account *account)
This function determines if an account in the account tree view has any visible children.
time64 gnc_time64_get_today_end(void)
The gnc_time64_get_today_end() routine returns a time64 value corresponding to the last second of tod...
Definition: gnc-date.cpp:1356
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
A/R account type.
Definition: Account.h:149
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
#define QUERY_DEFAULT_SORT
Default sort object type.
Definition: qofquery.h:105
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
void csv_transactions_export(CsvExportInfo *info)
The csv_transactions_export() will let the user export the transactions to a delimited file...
Utility functions for convert uri in separate components and back.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
time64 gnc_time64_get_day_end(time64 time_val)
The gnc_time64_get_day_end() routine will take the given time in seconds and adjust it to the last se...
Definition: gnc-date.cpp:1316
Equity account is used to balance the balance sheet.
Definition: Account.h:146
API for Transactions and Splits (journal entries)
A Query.
Definition: qofquery.cpp:74
The hidden root account of an account tree.
Definition: Account.h:153
The Credit card account is used to denote credit (e.g.
Definition: Account.h:113