GnuCash  2.6.17
Modules | Files | Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
Import_Export

Modules

 AqBanking
 

Files

 
file  import-backend.h
 Generic importer backend interface.
 
file  import-commodity-matcher.h
 A Generic commodity matcher/picker.
 
file  import-main-matcher.h
 Transaction matcher main window.
 
file  import-match-map.h
 Generic import mapper service, maps strings->accounts.
 
file  import-match-picker.h
 The transaction match picker dialog interface.
 
file  import-pending-matches.h
 Tracking container for pending match status.
 
file  import-settings.h
 Import preference handling. User preference interface for transaction matching (for both the gui and the backend)
 
file  import-utilities.h
 Utility functions for writing import modules.
 

Data Structures

struct  AccountPickerDialog
 
struct  GNCImportSelectedMatchInfo
 
struct  GNCImportTransInfo
 
struct  GNCImportMatchInfo
 
struct  GNCImportMainMatcher
 
struct  GncImportMatchMap
 
struct  account_token_count
 
struct  token_accounts_info
 
struct  account_probability
 
struct  account_info
 
struct  GNCImportMatchPicker
 
struct  GNCPendingMatches
 
struct  GNCImportSettings
 
struct  split_record
 

Macros

#define STATE_SECTION   "dialogs/import/generic_matcher/account_matcher"
 
#define GNC_PREFS_GROUP   "dialogs.import.generic.transaction-list"
 
#define COLOR_RED   "brown1"
 
#define COLOR_YELLOW   "gold"
 
#define COLOR_GREEN   "DarkSeaGreen1"
 
#define IMAP_FRAME   "import-map"
 
#define IMAP_FRAME_BAYES   "import-map-bayes"
 
#define PROBABILITY_FACTOR   100000
 
#define threshold   (.90 * PROBABILITY_FACTOR) /* 90% */
 
#define GNC_PREFS_GROUP   "dialogs.import.generic.match-picker"
 
#define GNC_PREF_DISPLAY_RECONCILED   "display-reconciled"
 
#define GNC_PREFS_GROUP_IMPORT   "dialogs.import.generic"
 
#define GNC_PREF_ENABLE_SKIP   "enable-skip"
 
#define GNC_PREF_ENABLE_UPDATE   "enable-update"
 
#define GNC_PREF_USE_BAYES   "use-bayes"
 
#define GNC_PREF_ATM_FEE_THRESHOLD   "atm-fee-threshold"
 
#define GNC_PREF_AUTO_CLEAR_THRESHOLD   "auto-clear-threshold"
 
#define GNC_PREF_AUTO_ADD_THRESHOLD   "auto-add-threshold"
 
#define GNC_PREF_MATCH_THRESHOLD   "match-threshold"
 
#define GNC_PREFS_GROUP   "dialogs.log-replay"
 
#define STRING_FIELD_SIZE   256
 
#define GNC_PREFS_GROUP   "dialogs.import.ofx"
 
#define GNC_PREF_AUTO_COMMODITY   "auto-create-commodity"
 

Typedefs

typedef void(* GNCTransactionProcessedCB) (GNCImportTransInfo *trans_info, gboolean imported, gpointer user_data)
 
typedef GHashTable GNCImportPendingMatches
 

Enumerations

enum  GNCImportAction {
  GNCImport_SKIP, GNCImport_ADD, GNCImport_CLEAR, GNCImport_UPDATE,
  GNCImport_LAST_ACTION, GNCImport_INVALID_ACTION
}
 
enum  downloaded_cols {
  DOWNLOADED_COL_DATE = 0, DOWNLOADED_COL_ACCOUNT, DOWNLOADED_COL_AMOUNT, DOWNLOADED_COL_DESCRIPTION,
  DOWNLOADED_COL_MEMO, DOWNLOADED_COL_ACTION_ADD, DOWNLOADED_COL_ACTION_CLEAR, DOWNLOADED_COL_ACTION_UPDATE,
  DOWNLOADED_COL_ACTION_INFO, DOWNLOADED_COL_ACTION_PIXBUF, DOWNLOADED_COL_DATA, DOWNLOADED_COL_COLOR,
  NUM_DOWNLOADED_COLS, DOWNLOADED_COL_ACCOUNT = 0, DOWNLOADED_COL_DATE, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_MEMO, DOWNLOADED_COL_BALANCED, DOWNLOADED_COL_INFO_PTR,
  NUM_DOWNLOADED_COLS
}
 
enum  downloaded_cols {
  DOWNLOADED_COL_DATE = 0, DOWNLOADED_COL_ACCOUNT, DOWNLOADED_COL_AMOUNT, DOWNLOADED_COL_DESCRIPTION,
  DOWNLOADED_COL_MEMO, DOWNLOADED_COL_ACTION_ADD, DOWNLOADED_COL_ACTION_CLEAR, DOWNLOADED_COL_ACTION_UPDATE,
  DOWNLOADED_COL_ACTION_INFO, DOWNLOADED_COL_ACTION_PIXBUF, DOWNLOADED_COL_DATA, DOWNLOADED_COL_COLOR,
  NUM_DOWNLOADED_COLS, DOWNLOADED_COL_ACCOUNT = 0, DOWNLOADED_COL_DATE, DOWNLOADED_COL_AMOUNT,
  DOWNLOADED_COL_DESCRIPTION, DOWNLOADED_COL_MEMO, DOWNLOADED_COL_BALANCED, DOWNLOADED_COL_INFO_PTR,
  NUM_DOWNLOADED_COLS
}
 
enum  matcher_cols {
  MATCHER_COL_CONFIDENCE = 0, MATCHER_COL_CONFIDENCE_PIXBUF, MATCHER_COL_DATE, MATCHER_COL_AMOUNT,
  MATCHER_COL_DESCRIPTION, MATCHER_COL_MEMO, MATCHER_COL_RECONCILED, MATCHER_COL_PENDING,
  MATCHER_COL_INFO_PTR, NUM_MATCHER_COLS
}
 
enum  GNCImportPendingMatchType { GNCImportPending_NONE, GNCImportPending_AUTO, GNCImportPending_MANUAL }
 

Functions

char * libgncmod_csv_export_gnc_module_path (void)
 
char * libgncmod_csv_export_gnc_module_description (void)
 
int libgncmod_csv_export_gnc_module_init (int refcount)
 
int libgncmod_csv_export_gnc_module_end (int refcount)
 
char * libgncmod_csv_import_gnc_module_path (void)
 
char * libgncmod_csv_import_gnc_module_description (void)
 
int libgncmod_csv_import_gnc_module_init (int refcount)
 
int libgncmod_csv_import_gnc_module_end (int refcount)
 
Accountgnc_import_select_account (GtkWidget *parent, const gchar *account_online_id_value, gboolean auto_create, const gchar *account_human_description, const gnc_commodity *new_account_default_commodity, GNCAccountType new_account_default_type, Account *default_selection, gboolean *ok_pressed)
 
AccountPickerDialoggnc_import_account_assist_setup (GtkWidget *parent)
 
Accountgnc_import_account_assist_update (AccountPickerDialog *picker)
 
gnc_commodity * gnc_import_select_commodity (const char *cusip, gboolean ask_on_unknown, const char *default_fullname, const char *default_mnemonic)
 
void on_matcher_ok_clicked (GtkButton *button, GNCImportMainMatcher *info)
 
void on_matcher_cancel_clicked (GtkButton *button, gpointer user_data)
 
void on_matcher_help_clicked (GtkButton *button, gpointer user_data)
 
void on_matcher_help_close_clicked (GtkButton *button, gpointer user_data)
 
void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
 
GNCImportMainMatcher * gnc_gen_trans_list_new (GtkWidget *parent, const gchar *heading, gboolean all_from_same_account, gint match_date_hardlimit)
 
GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent, const gchar *heading, gboolean all_from_same_account, gint match_date_hardlimit)
 
void gnc_gen_trans_assist_start (GNCImportMainMatcher *info)
 
void gnc_gen_trans_list_add_tp_cb (GNCImportMainMatcher *info, GNCTransactionProcessedCB trans_processed_cb, gpointer user_data)
 
gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info)
 
void gnc_gen_trans_list_add_trans (GNCImportMainMatcher *gui, Transaction *trans)
 
void gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)
 
GtkWidget * gnc_gen_trans_list_widget (GNCImportMainMatcher *info)
 
void gnc_imap_destroy (GncImportMatchMap *imap)
 
void gnc_imap_clear (GncImportMatchMap *imap)
 
Accountgnc_imap_find_account (GncImportMatchMap *imap, const char *category, const char *key)
 
void gnc_imap_add_account (GncImportMatchMap *imap, const char *category, const char *key, Account *acc)
 
Accountgnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
 
void gnc_imap_add_account_bayes (GncImportMatchMap *imap, GList *tokens, Account *acc)
 
void gnc_import_match_picker_run_and_close (GNCImportTransInfo *transaction_info, GNCImportPendingMatches *pending_matches)
 
GNCImportPendingMatches * gnc_import_PendingMatches_new (void)
 
void gnc_import_PendingMatches_delete (GNCImportPendingMatches *map)
 
void gnc_import_PendingMatches_add_match (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info, gboolean selected_manually)
 
void gnc_import_PendingMatches_remove_match (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info, gboolean selected_manually)
 
GNCImportPendingMatchType gnc_import_PendingMatches_get_match_type (GNCImportPendingMatches *map, GNCImportMatchInfo *match_info)
 
const char * gnc_import_PendingMatches_get_type_str (GNCImportPendingMatchType type)
 
GNCImportSettings * gnc_import_Settings_new (void)
 
void gnc_import_Settings_delete (GNCImportSettings *settings)
 
gboolean gnc_import_trans_has_online_id (Transaction *transaction)
 
gboolean gnc_import_split_has_online_id (Split *split)
 
void gnc_file_log_replay (void)
 
char * libgncmod_log_replay_gnc_module_path (void)
 
char * libgncmod_log_replay_gnc_module_description (void)
 
int libgncmod_log_replay_gnc_module_init (int refcount)
 
int libgncmod_log_replay_gnc_module_end (int refcount)
 
int ofx_proc_security_cb (const struct OfxSecurityData data, void *security_user_data)
 
int ofx_proc_transaction_cb (struct OfxTransactionData data, void *transaction_user_data)
 
int ofx_proc_account_cb (struct OfxAccountData data, void *account_user_data)
 
void gnc_file_ofx_import (void)
 
char * libgncmod_ofx_gnc_module_path (void)
 
char * libgncmod_ofx_gnc_module_description (void)
 
int libgncmod_ofx_gnc_module_init (int refcount)
 
int libgncmod_ofx_gnc_module_end (int refcount)
 

Variables

int libgncmod_csv_export_gnc_module_system_interface = 0
 
int libgncmod_csv_export_gnc_module_current = 0
 
int libgncmod_csv_export_gnc_module_revision = 0
 
int libgncmod_csv_export_gnc_module_age = 0
 
int libgncmod_csv_import_gnc_module_system_interface = 0
 
int libgncmod_csv_import_gnc_module_current = 0
 
int libgncmod_csv_import_gnc_module_revision = 0
 
int libgncmod_csv_import_gnc_module_age = 0
 
gint GNCPendingMatches::num_manual_matches
 
gint GNCPendingMatches::num_auto_matches
 
int libgncmod_log_replay_gnc_module_system_interface = 0
 
int libgncmod_log_replay_gnc_module_current = 0
 
int libgncmod_log_replay_gnc_module_revision = 0
 
int libgncmod_log_replay_gnc_module_age = 0
 
GNCImportMainMatcher * gnc_ofx_importer_gui = NULL
 
GList * ofx_created_commodites = NULL
 
int libgncmod_ofx_gnc_module_system_interface = 0
 
int libgncmod_ofx_gnc_module_current = 0
 
int libgncmod_ofx_gnc_module_revision = 0
 
int libgncmod_ofx_gnc_module_age = 0
 

Non-GUI Functions

GdkPixbuf * gen_probability_pixbuf (gint score_original, GNCImportSettings *settings, GtkWidget *widget)
 
void gnc_import_find_split_matches (GNCImportTransInfo *trans_info, gint process_threshold, double fuzzy_amount_difference, gint match_date_hardlimit)
 
gboolean gnc_import_process_trans_item (GncImportMatchMap *matchmap, GNCImportTransInfo *trans_info)
 
gboolean gnc_import_exists_online_id (Transaction *trans)
 
void gnc_import_TransInfo_init_matches (GNCImportTransInfo *trans_info, GNCImportSettings *settings)
 

Getters/Setters for GNCImportTransInfo

GList * gnc_import_TransInfo_get_match_list (const GNCImportTransInfo *info)
 
Transaction * gnc_import_TransInfo_get_trans (const GNCImportTransInfo *info)
 
gboolean gnc_import_TransInfo_is_balanced (const GNCImportTransInfo *info)
 
Split * gnc_import_TransInfo_get_fsplit (const GNCImportTransInfo *info)
 
GNCImportMatchInfognc_import_TransInfo_get_selected_match (const GNCImportTransInfo *info)
 
void gnc_import_TransInfo_set_selected_match_info (GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
 
gboolean gnc_import_TransInfo_get_match_selected_manually (const GNCImportTransInfo *info)
 
GNCImportAction gnc_import_TransInfo_get_action (const GNCImportTransInfo *info)
 
void gnc_import_TransInfo_set_action (GNCImportTransInfo *info, GNCImportAction action)
 
Accountgnc_import_TransInfo_get_destacc (const GNCImportTransInfo *info)
 
void gnc_import_TransInfo_set_destacc (GNCImportTransInfo *info, Account *acc, gboolean selected_manually)
 
gboolean gnc_import_TransInfo_get_destacc_selected_manually (const GNCImportTransInfo *info)
 
guint32 gnc_import_TransInfo_get_ref_id (const GNCImportTransInfo *info)
 
void gnc_import_TransInfo_set_ref_id (GNCImportTransInfo *info, guint32 ref_id)
 
void gnc_import_TransInfo_delete (GNCImportTransInfo *info)
 
GNCImportTransInfo * gnc_import_TransInfo_new (Transaction *trans, GncImportMatchMap *matchmap)
 
gboolean gnc_import_TransInfo_refresh_destacc (GNCImportTransInfo *transaction_info, GncImportMatchMap *matchmap)
 

Getters/Setters for GNCImportMatchInfo

Split * gnc_import_MatchInfo_get_split (const GNCImportMatchInfo *info)
 
gint gnc_import_MatchInfo_get_probability (const GNCImportMatchInfo *info)
 
GncImportMatchMap * gnc_imap_create_from_account (Account *acc)
 
GncImportMatchMap * gnc_imap_create_from_book (QofBook *book)
 

Some well-known categories

NOTE: You DO NOT have to use these values in your importer – these are just "well known" values, not "mandatory" values. You are free to use these if they apply, map your own fields to these labels, or create your own category strings.

#define GNCIMPORT_DESC   "desc"
 
#define GNCIMPORT_MEMO   "memo"
 
#define GNCIMPORT_PAYEE   "payee"
 

Getters/Setters for GNCImportSettings

double gnc_import_Settings_get_fuzzy_amount (GNCImportSettings *settings)
 
gboolean gnc_import_Settings_get_action_skip_enabled (GNCImportSettings *settings)
 
gboolean gnc_import_Settings_get_action_add_enabled (GNCImportSettings *settings)
 
gboolean gnc_import_Settings_get_action_update_enabled (GNCImportSettings *settings)
 
gboolean gnc_import_Settings_get_action_clear_enabled (GNCImportSettings *settings)
 
gint gnc_import_Settings_get_clear_threshold (GNCImportSettings *settings)
 
gint gnc_import_Settings_get_add_threshold (GNCImportSettings *settings)
 
gint gnc_import_Settings_get_display_threshold (GNCImportSettings *settings)
 
void gnc_import_Settings_set_match_date_hardlimit (GNCImportSettings *s, gint m)
 
gint gnc_import_Settings_get_match_date_hardlimit (const GNCImportSettings *s)
 

Setter-getters

Setter and getter functions for the online_id kvp_frame for Splits.

const gchar * gnc_import_get_acc_online_id (Account *account)
 
void gnc_import_set_acc_online_id (Account *account, const gchar *string_value)
 
const gchar * gnc_import_get_trans_online_id (Transaction *transaction)
 
void gnc_import_set_trans_online_id (Transaction *transaction, const gchar *string_value)
 
const gchar * gnc_import_get_split_online_id (Split *split)
 
void gnc_import_set_split_online_id (Split *split, const gchar *string_value)
 

Detailed Description

Macro Definition Documentation

◆ GNC_PREFS_GROUP_IMPORT

#define GNC_PREFS_GROUP_IMPORT   "dialogs.import.generic"

The preferences used by the importer

Definition at line 30 of file import-utilities.h.

◆ PROBABILITY_FACTOR

#define PROBABILITY_FACTOR   100000

convert a hash table of account names and (struct account_probability*) into a hash table of 100000x the percentage match value, ie. 10% would be 0.10 * 100000 = 10000

Definition at line 229 of file import-match-map.c.

Function Documentation

◆ gen_probability_pixbuf()

GdkPixbuf * gen_probability_pixbuf ( gint  score,
GNCImportSettings *  settings,
GtkWidget *  widget 
)

This function generates a new pixmap representing a match score. It is a series of vertical bars of different colors. -Below or at the add_threshold the bars are red -Above or at the clear_threshold the bars are green -Between the two threshold the bars are yellow

Parameters
scoreThe score for which to generate a pixmap.
settingsThe user settings from which to get the threshold
widgetThe parent widget in which the pixmap will eventually be added. Will be used to generate the colormap.

Definition at line 275 of file import-backend.c.

276 {
277  GdkPixbuf* retval = NULL;
278  gint i, j;
279  gint score;
280  const gint height = 15;
281  const gint width_each_bar = 7;
282  gchar * green_bar = ("bggggb ");
283  gchar * yellow_bar = ("byyyyb ");
284  gchar * red_bar = ("brrrrb ");
285  gchar * black_bar = ("bbbbbb ");
286  const gint width_first_bar = 1;
287  gchar * black_first_bar = ("b");
288  const gint num_colors = 5;
289  gchar * size_str;
290  gchar * none_color_str = g_strdup_printf(" c None");
291  gchar * green_color_str = g_strdup_printf("g c green");
292  gchar * yellow_color_str = g_strdup_printf("y c yellow");
293  gchar * red_color_str = g_strdup_printf("r c red");
294  gchar * black_color_str = g_strdup_printf("b c black");
295  gchar * xpm[2+num_colors+height];
296  gint add_threshold, clear_threshold;
297 
298  g_assert(settings);
299  g_assert(widget);
300  if (score_original < 0)
301  {
302  score = 0;
303  }
304  else
305  {
306  score = score_original;
307  }
308  size_str = g_strdup_printf("%d%s%d%s%d%s", (width_each_bar * score) + width_first_bar/*width*/, " ", height, " ", num_colors, " 1"/*characters per pixel*/);
309 
310  /*DEBUG("Begin");*/
311  xpm[0] = size_str;
312  xpm[1] = none_color_str;
313  xpm[2] = green_color_str;
314  xpm[3] = yellow_color_str;
315  xpm[4] = red_color_str;
316  xpm[5] = black_color_str;
317  add_threshold = gnc_import_Settings_get_add_threshold(settings);
318  clear_threshold = gnc_import_Settings_get_clear_threshold(settings);
319 
320  for (i = 0; i < height; i++)
321  {
322  xpm[num_colors+1+i] = g_new0(char, (width_each_bar * score) + width_first_bar + 1);
323  for (j = 0; j <= score; j++)
324  {
325  if (i == 0 || i == height - 1)
326  {
327  if (j == 0)
328  {
329  strcat(xpm[num_colors+1+i], black_first_bar);
330  }
331  else
332  {
333  strcat(xpm[num_colors+1+i], black_bar);
334  }
335  }
336  else
337  {
338  if (j == 0)
339  {
340  strcat(xpm[num_colors+1+i], black_first_bar);
341  }
342  else if (j <= add_threshold)
343  {
344  strcat(xpm[num_colors+1+i], red_bar);
345  }
346  else if (j >= clear_threshold)
347  {
348  strcat(xpm[num_colors+1+i], green_bar);
349  }
350  else
351  {
352  strcat(xpm[num_colors+1+i], yellow_bar);
353  }
354  }
355  }
356  }
357 
358  retval = gdk_pixbuf_new_from_xpm_data((const gchar **)xpm);
359  for (i = 0; i <= num_colors + height; i++)
360  {
361  /*DEBUG("free_loop i=%d%s%s",i,": ",xpm[i]);*/
362  g_free(xpm[i]);
363  }
364 
365  return retval;
366 }
gint gnc_import_Settings_get_clear_threshold(GNCImportSettings *settings)
gint gnc_import_Settings_get_add_threshold(GNCImportSettings *settings)

◆ gnc_file_log_replay()

void gnc_file_log_replay ( void  )

The gnc_file_log_replay() routine will pop up a standard file selection dialogue asking the user to pick a log file to replay. If one is selected the the .log file is opened and read. It's contents are then silently merged in the current log file.

Definition at line 540 of file gnc-log-replay.c.

541 {
542  char *selected_filename;
543  char *default_dir;
544  char read_buf[256];
545  char *read_retval;
546  GtkFileFilter *filter;
547  FILE *log_file;
548  char * record_start_str = "===== START";
549  /* NOTE: This string must match src/engine/TransLog.c (sans newline) */
550  char * expected_header_orig = "mod\ttrans_guid\tsplit_guid\ttime_now\t"
551  "date_entered\tdate_posted\tacc_guid\tacc_name\tnum\tdescription\t"
552  "notes\tmemo\taction\treconciled\tamount\tvalue\tdate_reconciled";
553  static char *expected_header = NULL;
554 
555  /* Use g_strdup_printf so we don't get accidental tab -> space conversion */
556  if (!expected_header)
557  expected_header = g_strdup(expected_header_orig);
558 
559  qof_log_set_level(GNC_MOD_IMPORT, QOF_LOG_DEBUG);
560  ENTER(" ");
561 
562  /* Don't log the log replay. This would only result in redundant logs */
563  xaccLogDisable();
564 
565  default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
566 
567  filter = gtk_file_filter_new();
568  gtk_file_filter_set_name(filter, "*.log");
569  gtk_file_filter_add_pattern(filter, "*.[Ll][Oo][Gg]");
570  selected_filename = gnc_file_dialog(_("Select a .log file to replay"),
571  g_list_prepend(NULL, filter),
572  default_dir,
573  GNC_FILE_DIALOG_OPEN);
574  g_free(default_dir);
575 
576  if (selected_filename != NULL)
577  {
578  /* Remember the directory as the default. */
579  default_dir = g_path_get_dirname(selected_filename);
580  gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
581  g_free(default_dir);
582 
583  /*strncpy(file,selected_filename, 255);*/
584  DEBUG("Filename found: %s", selected_filename);
585  if (xaccFileIsCurrentLog(selected_filename))
586  {
587  g_warning("Cannot open the current log file: %s", selected_filename);
588  gnc_error_dialog(NULL,
589  /* Translators: %s is the file name. */
590  _("Cannot open the current log file: %s"),
591  selected_filename);
592  }
593  else
594  {
595  DEBUG("Opening selected file");
596  log_file = g_fopen(selected_filename, "r");
597  if (!log_file || ferror(log_file) != 0)
598  {
599  int err = errno;
600  perror("File open failed");
601  gnc_error_dialog(NULL,
602  /* Translation note:
603  * First argument is the filename,
604  * second argument is the error.
605  */
606  _("Failed to open log file: %s: %s"),
607  selected_filename,
608  strerror(err));
609  }
610  else
611  {
612  if ((read_retval = fgets(read_buf, sizeof(read_buf), log_file)) == NULL)
613  {
614  DEBUG("Read error or EOF");
615  gnc_info_dialog(NULL, "%s",
616  _("The log file you selected was empty."));
617  }
618  else
619  {
620  if (strncmp(expected_header, read_buf, strlen(expected_header)) != 0)
621  {
622  PERR("File header not recognised:\n%s", read_buf);
623  PERR("Expected:\n%s", expected_header);
624  gnc_error_dialog(NULL, "%s",
625  _("The log file you selected cannot be read. "
626  "The file header was not recognized."));
627  }
628  else
629  {
630  do
631  {
632  read_retval = fgets(read_buf, sizeof(read_buf), log_file);
633  /*DEBUG("Chunk read: %s",read_retval);*/
634  if (strncmp(record_start_str, read_buf, strlen(record_start_str)) == 0) /* If a record started */
635  {
636  process_trans_record(log_file);
637  }
638  }
639  while (feof(log_file) == 0);
640  }
641  }
642  fclose(log_file);
643  }
644  }
645  g_free(selected_filename);
646  }
647  /* Start logging again */
648  xaccLogEnable();
649 
650  LEAVE("");
651 }
void qof_log_set_level(QofLogModule log_module, QofLogLevel level)
Definition: qoflog.c:226
void xaccLogDisable(void)
Definition: TransLog.c:93
#define DEBUG(format, args...)
Definition: qoflog.h:250
#define PERR(format, args...)
Definition: qoflog.h:232
#define ENTER(format, args...)
Definition: qoflog.h:256
#define LEAVE(format, args...)
Definition: qoflog.h:266
gboolean xaccFileIsCurrentLog(const gchar *name)
Definition: TransLog.c:139
void xaccLogEnable(void)
Definition: TransLog.c:97

◆ gnc_file_ofx_import()

void gnc_file_ofx_import ( void  )

The gnc_file_ofx_import() routine will pop up a standard file selection dialogue asking the user to pick a OFX/QFX file. If one is selected the the OFX file is opened and read. It's contents are merged into the existing session (if any). The current session continues to remain open for editing.

Definition at line 968 of file gnc-ofx-import.c.

969 {
970  extern int ofx_PARSER_msg;
971  extern int ofx_DEBUG_msg;
972  extern int ofx_WARNING_msg;
973  extern int ofx_ERROR_msg;
974  extern int ofx_INFO_msg;
975  extern int ofx_STATUS_msg;
976  char *selected_filename;
977  char *default_dir;
978  LibofxContextPtr libofx_context = libofx_get_new_context();
979 
980  ofx_PARSER_msg = false;
981  ofx_DEBUG_msg = false;
982  ofx_WARNING_msg = true;
983  ofx_ERROR_msg = true;
984  ofx_INFO_msg = true;
985  ofx_STATUS_msg = false;
986 
987  DEBUG("gnc_file_ofx_import(): Begin...\n");
988 
989  default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
990  selected_filename = gnc_file_dialog(_("Select an OFX/QFX file to process"),
991  NULL,
992  default_dir,
993  GNC_FILE_DIALOG_IMPORT);
994  g_free(default_dir);
995 
996  if (selected_filename != NULL)
997  {
998 #ifdef G_OS_WIN32
999  gchar *conv_name;
1000 #endif
1001 
1002  /* Remember the directory as the default. */
1003  default_dir = g_path_get_dirname(selected_filename);
1004  gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
1005  g_free(default_dir);
1006 
1007  /*strncpy(file,selected_filename, 255);*/
1008  DEBUG("Filename found: %s", selected_filename);
1009 
1010  /* Create the Generic transaction importer GUI. */
1011  gnc_ofx_importer_gui = gnc_gen_trans_list_new(NULL, NULL, FALSE, 42);
1012 
1013  /* Look up the needed preferences */
1014  auto_create_commodity =
1015  gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_AUTO_COMMODITY);
1016 
1017  /* Initialize libofx */
1018 
1019  /*ofx_set_statement_cb(libofx_context, ofx_proc_statement_cb, 0);*/
1020  ofx_set_account_cb(libofx_context, ofx_proc_account_cb, 0);
1021  ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
1022  ofx_set_security_cb(libofx_context, ofx_proc_security_cb, 0);
1023  /*ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0);*/
1024 
1025 #ifdef G_OS_WIN32
1026  conv_name = g_win32_locale_filename_from_utf8(selected_filename);
1027  g_free(selected_filename);
1028  selected_filename = conv_name;
1029 #endif
1030 
1031  DEBUG("Opening selected file");
1032  libofx_proc_file(libofx_context, selected_filename, AUTODETECT);
1033  g_free(selected_filename);
1034  }
1035 
1036  if (ofx_created_commodites)
1037  {
1038  /* FIXME: Present some result window about the newly created
1039  * commodities */
1040  g_warning("Created %d new commodities during import", g_list_length(ofx_created_commodites));
1041  g_list_free(ofx_created_commodites);
1042  ofx_created_commodites = NULL;
1043  }
1044  else
1045  {
1046  //g_warning("No new commodities created");
1047  }
1048 }
#define DEBUG(format, args...)
Definition: qoflog.h:250
#define GNC_PREFS_GROUP_IMPORT
GNCImportMainMatcher * gnc_gen_trans_list_new(GtkWidget *parent, const gchar *heading, gboolean all_from_same_account, gint match_date_hardlimit)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196

◆ gnc_gen_trans_assist_new()

GNCImportMainMatcher * gnc_gen_trans_assist_new ( GtkWidget *  parent,
const gchar *  heading,
gboolean  all_from_same_account,
gint  match_date_hardlimit 
)

Add the Transaction matcher to an existing page of an assistant. Must be called with the parent widget, ie. a vbox that the transaction matcher will be packed into. The data structure GNCImportMainMatcher is returned.

Parameters
parentThe parent widget. This is the place the transaction matcher will be packed into.
headingThe heading label in the Importer window. May be NULL.
all_from_same_accountSet this to TRUE if ALL the transaction that will be added with gnc_gen_trans_list_add_trans are from the same source account. This will cause the account column to be hidden.
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.
Returns
A pointer to the GNCImportMainMatcher which has been setup.

Definition at line 578 of file import-main-matcher.c.

582 {
583  GNCImportMainMatcher *info;
584  GtkBuilder *builder;
585  GtkWidget *heading_label;
586  GtkWidget *box;
587  gboolean show_update;
588 
589  info = g_new0 (GNCImportMainMatcher, 1);
590  info->pending_matches = gnc_import_PendingMatches_new();
591 
592  /* Initialize user Settings. */
593  info->user_settings = gnc_import_Settings_new ();
594  gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
595 
596  /* load the interface */
597  builder = gtk_builder_new();
598  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
599  if (builder == NULL)
600  {
601  PERR("Error opening the glade builder interface");
602  }
603  /* Pack content into Assistant page widget */
604  box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
605  gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
606 
607  /* Get the view */
608  info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
609  g_assert (info->view != NULL);
610 
611  show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
612  gnc_gen_trans_init_view(info, all_from_same_account, show_update);
613  heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
614  g_assert (heading_label != NULL);
615 
616  /*Initialise the colors */
617  gdk_color_parse(COLOR_RED, &info->color_back_red);
618  gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
619  gdk_color_parse(COLOR_GREEN, &info->color_back_green);
620 
621  if (heading)
622  gtk_label_set_text (GTK_LABEL (heading_label), heading);
623 
624  info->transaction_processed_cb = NULL;
625 
626  /* Connect the signals */
627  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
628 
629  g_object_unref(G_OBJECT(builder));
630 
631  return info;
632 }
GNCImportSettings * gnc_import_Settings_new(void)
#define PERR(format, args...)
Definition: qoflog.h:232
void gnc_import_Settings_set_match_date_hardlimit(GNCImportSettings *s, gint m)
gboolean gnc_import_Settings_get_action_update_enabled(GNCImportSettings *settings)

◆ gnc_gen_trans_assist_start()

void gnc_gen_trans_assist_start ( GNCImportMainMatcher *  info)

This starts the import process for transaction from an assistant. assistant button callback.

Parameters
info.A pointer to a the GNCImportMainMatcher structure.

Definition at line 634 of file import-main-matcher.c.

635 {
636  on_matcher_ok_clicked (NULL, info);
637 }

◆ gnc_gen_trans_list_add_tp_cb()

void gnc_gen_trans_list_add_tp_cb ( GNCImportMainMatcher *  info,
GNCTransactionProcessedCB  trans_processed_cb,
gpointer  user_data 
)

Add transaction processed callback to the transaction importer.

Parameters
infoThe Transaction Importer to use.
trans_processed_cbThe callback function.

Definition at line 643 of file import-main-matcher.c.

646 {
647  info->user_data = user_data;
648  info->transaction_processed_cb = trans_processed_cb;
649 }

◆ gnc_gen_trans_list_add_trans()

void gnc_gen_trans_list_add_trans ( GNCImportMainMatcher *  gui,
Transaction *  trans 
)

Add a newly imported Transaction to the Transaction Importer. The Importer takes over ownership of the passed transaction.

Parameters
guiThe Transaction Importer to use.
transThe Transaction to add. The must contain at least one split, and this split must have been associated with an account Only the first split will be used for matching. The transaction must NOT be committed. The Importer takes over ownership of the passed transaction.

Definition at line 878 of file import-main-matcher.c.

879 {
881  return;
882 }/* end gnc_import_add_trans() */
void gnc_gen_trans_list_add_trans_with_ref_id(GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)

◆ gnc_gen_trans_list_add_trans_with_ref_id()

void gnc_gen_trans_list_add_trans_with_ref_id ( GNCImportMainMatcher *  gui,
Transaction *  trans,
guint32  ref_id 
)

Add a newly imported Transaction to the Transaction Importer and provide an external reference id for it. The Importer takes over ownership of the passed transaction.

Parameters
guiThe Transaction Importer to use.
transThe Transaction to add. The must contain at least one split, and this split must have been associated with an account Only the first split will be used for matching. The transaction must NOT be committed. The Importer takes over ownership of the passed transaction.
ref_idReference id which links an external object to the transaction.

Definition at line 884 of file import-main-matcher.c.

885 {
886  GNCImportTransInfo * transaction_info = NULL;
887  GtkTreeModel *model;
888  GtkTreeIter iter;
889  GNCImportMatchInfo *selected_match;
890  GncGUID *pending_match_guid;
891  gboolean match_selected_manually;
892  g_assert (gui);
893  g_assert (trans);
894 
895 
896  if (gnc_import_exists_online_id (trans))
897  return;
898  else
899  {
900  transaction_info = gnc_import_TransInfo_new(trans, NULL);
901  gnc_import_TransInfo_set_ref_id(transaction_info, ref_id);
902 
903  gnc_import_TransInfo_init_matches(transaction_info,
904  gui->user_settings);
905 
906  selected_match =
907  gnc_import_TransInfo_get_selected_match(transaction_info);
908  match_selected_manually =
910 
911  if (selected_match)
912  gnc_import_PendingMatches_add_match(gui->pending_matches,
913  selected_match,
914  match_selected_manually);
915 
916  model = gtk_tree_view_get_model(gui->view);
917  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
918  refresh_model_row (gui, model, &iter, transaction_info);
919  }
920  return;
921 }/* end gnc_import_add_trans_with_ref_id() */
GNCImportTransInfo * gnc_import_TransInfo_new(Transaction *trans, GncImportMatchMap *matchmap)
void gnc_import_TransInfo_set_ref_id(GNCImportTransInfo *info, guint32 ref_id)
Definition: guid.h:54
void gnc_import_TransInfo_init_matches(GNCImportTransInfo *trans_info, GNCImportSettings *settings)
gboolean gnc_import_exists_online_id(Transaction *trans)
gboolean gnc_import_TransInfo_get_match_selected_manually(const GNCImportTransInfo *info)
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)

◆ gnc_gen_trans_list_delete()

void gnc_gen_trans_list_delete ( GNCImportMainMatcher *  info)

Deletes the given object.

Definition at line 105 of file import-main-matcher.c.

106 {
107  GtkTreeModel *model;
108  GtkTreeIter iter;
109  GNCImportTransInfo *trans_info;
110 
111  if (info == NULL)
112  return;
113 
114  model = gtk_tree_view_get_model(info->view);
115  if (gtk_tree_model_get_iter_first(model, &iter))
116  {
117  do
118  {
119  gtk_tree_model_get(model, &iter,
120  DOWNLOADED_COL_DATA, &trans_info,
121  -1);
122 
123  if (info->transaction_processed_cb)
124  {
125  info->transaction_processed_cb(trans_info,
126  FALSE,
127  info->user_data);
128  }
129 
130  gnc_import_TransInfo_delete(trans_info);
131  }
132  while (gtk_tree_model_iter_next (model, &iter));
133  }
134 
135 
136  if (!(info->dialog == NULL))
137  {
138  gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(info->dialog));
139  gnc_import_Settings_delete (info->user_settings);
140  gtk_widget_destroy (GTK_WIDGET (info->dialog));
141  }
142  else
143  gnc_import_Settings_delete (info->user_settings);
144  g_free (info);
145 }
void gnc_import_TransInfo_delete(GNCImportTransInfo *info)
void gnc_import_Settings_delete(GNCImportSettings *settings)

◆ gnc_gen_trans_list_new()

GNCImportMainMatcher * gnc_gen_trans_list_new ( GtkWidget *  parent,
const gchar *  heading,
gboolean  all_from_same_account,
gint  match_date_hardlimit 
)

Create a new generic transaction dialog window and return it.

Parameters
parentThe parent GtkWidget. May be NULL.
headingThe heading label in the Importer window. May be NULL.
all_from_same_accountSet this to TRUE if ALL the transaction that will be added with gnc_gen_trans_list_add_trans are from the same source account. This will cause the account column to be hidden.
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.
Returns
A pointer to the GNCImportMainMatcher which has been setup.

Definition at line 510 of file import-main-matcher.c.

514 {
515  GNCImportMainMatcher *info;
516  GtkBuilder *builder;
517  GtkWidget *heading_label;
518  GtkWidget *box, *pbox;
519  gboolean show_update;
520 
521  info = g_new0 (GNCImportMainMatcher, 1);
522  info->pending_matches = gnc_import_PendingMatches_new();
523 
524  /* Initialize user Settings. */
525  info->user_settings = gnc_import_Settings_new ();
526  gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
527 
528  /* Initialize the GtkDialog. */
529  builder = gtk_builder_new();
530  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher");
531  gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
532  info->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher"));
533  g_assert (info->dialog != NULL);
534 
535  /* Pack the content into the dialog vbox */
536  pbox = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_vbox"));
537  box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
538  gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE, 0);
539 
540  /* Get the view */
541  info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
542  g_assert (info->view != NULL);
543 
544  show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
545  gnc_gen_trans_init_view(info, all_from_same_account, show_update);
546  heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
547  g_assert (heading_label != NULL);
548 
549  /* if (parent)
550  gtk_window_set_transient_for (GTK_WINDOW (info->dialog),
551  GTK_WINDOW (parent));*/
552 
553  /*Initialise the colors */
554  gdk_color_parse(COLOR_RED, &info->color_back_red);
555  gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
556  gdk_color_parse(COLOR_GREEN, &info->color_back_green);
557 
558  if (heading)
559  gtk_label_set_text (GTK_LABEL (heading_label), heading);
560 
561  gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(info->dialog));
562  gtk_widget_show_all (GTK_WIDGET (info->dialog));
563 
564  info->transaction_processed_cb = NULL;
565 
566  /* Connect the signals */
567  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
568 
569  g_object_unref(G_OBJECT(builder));
570 
571  return info;
572 }
GNCImportSettings * gnc_import_Settings_new(void)
void gnc_import_Settings_set_match_date_hardlimit(GNCImportSettings *s, gint m)
gboolean gnc_import_Settings_get_action_update_enabled(GNCImportSettings *settings)

◆ gnc_gen_trans_list_run()

gboolean gnc_gen_trans_list_run ( GNCImportMainMatcher *  info)

Run this dialog and return only after the user pressed Ok, Cancel, or closed the window. This means that all actual importing will have been finished upon returning.

Definition at line 651 of file import-main-matcher.c.

652 {
653  gboolean result;
654 
655  /* DEBUG("Begin"); */
656  result = gtk_dialog_run (GTK_DIALOG (info->dialog));
657  /* DEBUG("Result was %d", result); */
658 
659  /* No destroying here since the dialog was already destroyed through
660  the ok_clicked handlers. */
661 
662  return result;
663 }

◆ gnc_gen_trans_list_widget()

GtkWidget * gnc_gen_trans_list_widget ( GNCImportMainMatcher *  info)

Returns the widget of this dialog.

Definition at line 923 of file import-main-matcher.c.

924 {
925  g_assert(info);
926  return info->dialog;
927 }

◆ gnc_imap_add_account()

void gnc_imap_add_account ( GncImportMatchMap *  imap,
const char *  category,
const char *  key,
Account acc 
)

Store an Account in the map

Store an Account in the map. This mapping is immediatly stored in the underlying kvp frame, regardless of whether the MatchMap is destroyed later or not.

Definition at line 142 of file import-match-map.c.

144 {
145  kvp_value *value;
146 
147  if (!imap || !key || !acc || (strlen (key) == 0)) return;
148  if (!category)
149  {
150  category = key;
151  key = NULL;
152  }
153  g_return_if_fail (acc != NULL);
154 
155  value = kvp_value_new_guid (xaccAccountGetGUID (acc));
156  g_return_if_fail (value != NULL);
157  xaccAccountBeginEdit (imap->acc);
158  kvp_frame_set_slot_path (imap->frame, value, IMAP_FRAME, category, key, NULL);
159  qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
160  xaccAccountCommitEdit (imap->acc);
161  kvp_value_delete (value);
162 
163  /* XXX Mark the account (or book) as dirty! */
164 }
#define kvp_value
Definition: kvp_frame.h:108
void kvp_frame_set_slot_path(KvpFrame *frame, const KvpValue *value, const gchar *first_key,...)
void qof_instance_set_dirty(QofInstance *inst)
Set the dirty flag.
Definition: qofinstance.c:723
#define xaccAccountGetGUID(X)
Definition: Account.h:239
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1143
void kvp_value_delete(KvpValue *value)
Definition: kvp_frame.c:1064
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1184

◆ gnc_imap_add_account_bayes()

void gnc_imap_add_account_bayes ( GncImportMatchMap *  imap,
GList *  tokens,
Account acc 
)

Updates the imap for a given account using a list of tokens

Store an Account in the map. This mapping is immediatly stored in the underlying kvp frame, regardless of whether the MatchMap is destroyed later or not.

Definition at line 481 of file import-match-map.c.

482 {
483  GList *current_token;
484  kvp_value *value;
485  gint64 token_count;
486  char* account_fullname;
487  kvp_value *new_value; /* the value that will be added back into the kvp tree */
488  const gchar *guid_string;
489  gboolean use_fullname = TRUE;
490 
491  ENTER(" ");
492 
493  /* if imap is null return */
494  if (!imap)
495  {
496  LEAVE(" ");
497  return;
498  }
499 
500  g_return_if_fail (acc != NULL);
501  account_fullname = gnc_account_get_full_name(acc);
502  xaccAccountBeginEdit (imap->acc);
503 
504  PINFO("account name: '%s'\n", account_fullname);
505 
506  guid_string = guid_to_string (xaccAccountGetGUID (acc));
507 
508  /* process each token in the list */
509  for (current_token = g_list_first(tokens); current_token;
510  current_token = current_token->next)
511  {
512  /* Jump to next iteration if the pointer is not valid or if the
513  string is empty. In HBCI import we almost always get an empty
514  string, which doesn't work in the kvp loopkup later. So we
515  skip this case here. */
516  if (!current_token->data || (*((char*)current_token->data) == '\0'))
517  continue;
518 
519  /* start off with no tokens for this account */
520  token_count = 0;
521 
522  PINFO("adding token '%s'\n", (char*)current_token->data);
523 
524  /* is this token/account_name already in the kvp tree under fullname? */
525  value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
526  (char*)current_token->data, account_fullname,
527  NULL);
528 
529  if (!value) // we have not found entry under the fullname, maybe guid
530  {
531  value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
532  (char*)current_token->data, guid_string,
533  NULL);
534  if (value)
535  use_fullname = FALSE;
536  }
537 
538  /* if the token/account is already in the tree, read the current
539  * value from the tree and use this for the basis of the value we
540  * are putting back
541  */
542  if (value)
543  {
544  PINFO("found existing value of '%ld'\n",
545  (long)kvp_value_get_gint64(value));
546 
547  /* convert this value back into an integer */
548  token_count += kvp_value_get_gint64(value);
549  }
550 
551  /* increment the token count */
552  token_count++;
553 
554  /* create a new value */
555  new_value = kvp_value_new_gint64(token_count);
556 
557  /* insert the value into the kvp tree at
558  * /imap->frame/IMAP_FRAME/token_string/account_fullname or guid
559  */
560  if (use_fullname == TRUE)
561  {
562  KvpFrame *book_frame = qof_book_get_slots (imap->book);
563  const gchar *book_path = "changed-bayesian-to-guid";
564 
565  kvp_frame_set_slot_path(imap->frame, new_value, IMAP_FRAME_BAYES,
566  (char*)current_token->data, account_fullname, NULL);
567 
568  /* Reset the run once kvp flag for versions 2.7.0 and later */
569  if (kvp_frame_get_string(book_frame, book_path) != NULL)
570  kvp_frame_set_string(book_frame, book_path, "false");
571  }
572  else
573  kvp_frame_set_slot_path(imap->frame, new_value, IMAP_FRAME_BAYES,
574  (char*)current_token->data, guid_string, NULL);
575  /* kvp_frame_set_slot_path() copied the value so we
576  * need to delete this one ;-) */
577  kvp_value_delete(new_value);
578  }
579 
580  /* free up the account fullname string */
581  qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
582  xaccAccountCommitEdit (imap->acc);
583  g_free(account_fullname);
584 
585  LEAVE(" ");
586 }
#define kvp_value
Definition: kvp_frame.h:108
#define PINFO(format, args...)
Definition: qoflog.h:244
void kvp_frame_set_slot_path(KvpFrame *frame, const KvpValue *value, const gchar *first_key,...)
void qof_instance_set_dirty(QofInstance *inst)
Set the dirty flag.
Definition: qofinstance.c:723
#define ENTER(format, args...)
Definition: qoflog.h:256
gint64 kvp_value_get_gint64(const KvpValue *value)
Definition: kvp_frame.c:1104
#define xaccAccountGetGUID(X)
Definition: Account.h:239
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:2913
const char * guid_to_string(const GncGUID *guid)
Definition: guid.c:656
KvpValue * kvp_frame_get_slot_path(KvpFrame *frame, const gchar *first_key,...)
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1143
#define LEAVE(format, args...)
Definition: qoflog.h:266
void kvp_value_delete(KvpValue *value)
Definition: kvp_frame.c:1064
KvpFrame * qof_book_get_slots(const QofBook *book)
Definition: qofbook.c:257
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1184
void kvp_frame_set_string(KvpFrame *frame, const gchar *path, const gchar *str)
Store a copy of the string at the indicated path.

◆ gnc_imap_clear()

void gnc_imap_clear ( GncImportMatchMap *  imap)

Clear an import map – this removes ALL entries in the map

Definition at line 107 of file import-match-map.c.

108 {
109  if (!imap) return;
110  xaccAccountBeginEdit (imap->acc);
111  /* Clear the IMAP_FRAME kvp */
112  kvp_frame_set_slot_path (imap->frame, NULL, IMAP_FRAME);
113 
114  /* Clear the bayes kvp, IMAP_FRAME_BAYES */
115  kvp_frame_set_slot_path (imap->frame, NULL, IMAP_FRAME_BAYES);
116  qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
117  xaccAccountCommitEdit (imap->acc);
118 }
void kvp_frame_set_slot_path(KvpFrame *frame, const KvpValue *value, const gchar *first_key,...)
void qof_instance_set_dirty(QofInstance *inst)
Set the dirty flag.
Definition: qofinstance.c:723
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1143
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1184

◆ gnc_imap_create_from_account()

GncImportMatchMap * gnc_imap_create_from_account ( Account acc)

Obtain an ImportMatchMap object from an Account or a Book

Definition at line 77 of file import-match-map.c.

78 {
79  kvp_frame * frame;
80 
81  if (!acc) return NULL;
82  frame = xaccAccountGetSlots (acc);
83  g_return_val_if_fail (frame != NULL, NULL);
84 
85  return gnc_imap_create_from_frame (frame, acc, NULL);
86 }
#define kvp_frame
Definition: kvp_frame.h:106

◆ gnc_imap_destroy()

void gnc_imap_destroy ( GncImportMatchMap *  imap)

Destroy an import map

Destroy an import map. But all stored entries will still continue to exist in the underlying kvp frame of the account or book.

Definition at line 100 of file import-match-map.c.

101 {
102  if (!imap) return;
103  g_free (imap);
104 }

◆ gnc_imap_find_account()

Account * gnc_imap_find_account ( GncImportMatchMap *  imap,
const char *  category,
const char *  key 
)

Look up an Account in the map

Definition at line 121 of file import-match-map.c.

123 {
124  kvp_value *value;
125  GncGUID * guid;
126 
127  if (!imap || !key) return NULL;
128  if (!category)
129  {
130  category = key;
131  key = NULL;
132  }
133 
134  value = kvp_frame_get_slot_path (imap->frame, IMAP_FRAME, category, key, NULL);
135  if (!value) return NULL;
136 
137  guid = kvp_value_get_guid (value);
138  return xaccAccountLookup (guid, imap->book);
139 }
#define kvp_value
Definition: kvp_frame.h:108
Definition: guid.h:54
GncGUID * kvp_value_get_guid(const KvpValue *value)
Definition: kvp_frame.c:1160
KvpValue * kvp_frame_get_slot_path(KvpFrame *frame, const gchar *first_key,...)
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1690

◆ gnc_imap_find_account_bayes()

Account * gnc_imap_find_account_bayes ( GncImportMatchMap *  imap,
GList *  tokens 
)

Look up an Account in the map

Look up an Account in the map from a GList* of pointers to strings(tokens) from the current transaction

< holds the accounts and total token count for a single token

    < pointer to the current token from the

input GList *tokens

    < pointer to the struct

account_token_count

< an account name and the number of times a token has appeared for the account

< intermediate storage of values to compute the bayes probability of an account

Definition at line 290 of file import-match-map.c.

291 {
292  struct token_accounts_info tokenInfo;
294  GList *current_token;
296  GList *current_account_token;
298  struct account_token_count *account_c;
301  struct account_probability *account_p;
304  GHashTable *running_probabilities = g_hash_table_new(g_str_hash, g_str_equal);
305  GHashTable *final_probabilities = g_hash_table_new(g_str_hash, g_str_equal);
306  struct account_info account_i;
307  kvp_value* value;
308  kvp_frame* token_frame;
309 
310  ENTER(" ");
311 
312  /* check to see if the imap is NULL */
313  if (!imap)
314  {
315  PINFO("imap is null, returning null");
316  LEAVE(" ");
317  return NULL;
318  }
319 
320  /* find the probability for each account that contains any of the tokens
321  * in the input tokens list
322  */
323  for (current_token = tokens; current_token; current_token = current_token->next)
324  {
325  /* zero out the token_accounts_info structure */
326  memset(&tokenInfo, 0, sizeof(struct token_accounts_info));
327 
328  PINFO("token: '%s'", (char*)current_token->data);
329 
330  /* find the slot for the given token off of the source account
331  * for these tokens, search off of the IMAP_FRAME_BAYES path so
332  * we aren't looking from the parent of the entire kvp tree
333  */
334  value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
335  (char*)current_token->data, NULL);
336 
337  /* if value is null we should skip over this token */
338  if (!value)
339  continue;
340 
341  /* convert the slot(value) into a the frame that contains the
342  * list of accounts
343  */
344  token_frame = kvp_value_get_frame(value);
345 
346  /* token_frame should NEVER be null */
347  if (!token_frame)
348  {
349  PERR("token '%s' has no accounts", (char*)current_token->data);
350  continue; /* skip over this token */
351  }
352 
353  /* process the accounts for this token, adding the account if it
354  * doesn't already exist or adding to the existing accounts token
355  * count if it does
356  */
357  kvp_frame_for_each_slot(token_frame, buildTokenInfo, &tokenInfo);
358 
359  /* for each account we have just found, see if the account already exists
360  * in the list of account probabilities, if not add it
361  */
362  for (current_account_token = tokenInfo.accounts; current_account_token;
363  current_account_token = current_account_token->next)
364  {
365  /* get the account name and corresponding token count */
366  account_c = (struct account_token_count*)current_account_token->data;
367 
368  PINFO("account_c->account_name('%s'), "
369  "account_c->token_count('%ld')/total_count('%ld')",
370  account_c->account_name, (long)account_c->token_count,
371  (long)tokenInfo.total_count);
372 
373  account_p = g_hash_table_lookup(running_probabilities,
374  account_c->account_name);
375 
376  /* if the account exists in the list then continue
377  * the running probablities
378  */
379  if (account_p)
380  {
381  account_p->product =
382  ((double)account_c->token_count / (double)tokenInfo.total_count)
383  * account_p->product;
384  account_p->product_difference =
385  ((double)1 - ((double)account_c->token_count /
386  (double)tokenInfo.total_count))
387  * account_p->product_difference;
388  PINFO("product == %f, product_difference == %f",
389  account_p->product, account_p->product_difference);
390  }
391  else
392  {
393  /* add a new entry */
394  PINFO("adding a new entry for this account");
395  account_p = (struct account_probability*)
396  g_new0(struct account_probability, 1);
397 
398  /* set the product and product difference values */
399  account_p->product = ((double)account_c->token_count /
400  (double)tokenInfo.total_count);
401  account_p->product_difference =
402  (double)1 - ((double)account_c->token_count /
403  (double)tokenInfo.total_count);
404 
405  PINFO("product == %f, product_difference == %f",
406  account_p->product, account_p->product_difference);
407 
408  /* add the account name and (struct account_probability*)
409  * to the hash table */
410  g_hash_table_insert(running_probabilities,
411  account_c->account_name, account_p);
412  }
413  } /* for all accounts in tokenInfo */
414 
415  /* free the data in tokenInfo */
416  for (current_account_token = tokenInfo.accounts; current_account_token;
417  current_account_token = current_account_token->next)
418  {
419  /* free up each struct account_token_count we allocated */
420  g_free((struct account_token_count*)current_account_token->data);
421  }
422 
423  g_list_free(tokenInfo.accounts); /* free the accounts GList */
424  }
425 
426  /* build a hash table of account names and their final probabilities
427  * from each entry in the running_probabilties hash table
428  */
429  g_hash_table_foreach(running_probabilities, buildProbabilities,
430  final_probabilities);
431 
432  /* find the highest probabilty and the corresponding account */
433  memset(&account_i, 0, sizeof(struct account_info));
434  g_hash_table_foreach(final_probabilities, highestProbability, &account_i);
435 
436  /* free each element of the running_probabilities hash */
437  g_hash_table_foreach(running_probabilities, freeProbabilities, NULL);
438 
439  /* free the hash tables */
440  g_hash_table_destroy(running_probabilities);
441  g_hash_table_destroy(final_probabilities);
442 
443  PINFO("highest P('%s') = '%d'",
444  account_i.account_name ? account_i.account_name : "(null)",
445  account_i.probability);
446 
447  /* has this probability met our threshold? */
448  if (account_i.probability >= threshold)
449  {
450  Account *account = NULL;
451  PINFO("Probability has met threshold");
452 
453  account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(imap->book),
454  account_i.account_name);
455 
456  if (account == NULL) // Possibly we have a Guid or account not found
457  {
458  GncGUID *guid = g_new (GncGUID, 1);
459 
460  if (string_to_guid (account_i.account_name, guid))
461  account = xaccAccountLookup (guid, imap->book);
462 
463  g_free (guid);
464  }
465 
466  if (account != NULL)
467  LEAVE("Return account is '%s'", xaccAccountGetName (account));
468  else
469  LEAVE("Return NULL, account for string '%s' can not be found", account_i.account_name);
470 
471  return account;
472  }
473  PINFO("Probability has not met threshold");
474  LEAVE("Return NULL");
475 
476  return NULL; /* we didn't meet our threshold, return NULL for an account */
477 }
#define kvp_value
Definition: kvp_frame.h:108
#define PINFO(format, args...)
Definition: qoflog.h:244
gboolean string_to_guid(const gchar *string, GncGUID *guid)
Definition: guid.h:54
#define PERR(format, args...)
Definition: qoflog.h:232
#define ENTER(format, args...)
Definition: qoflog.h:256
#define kvp_frame
Definition: kvp_frame.h:106
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
Definition: Account.c:2790
KvpValue * kvp_frame_get_slot_path(KvpFrame *frame, const gchar *first_key,...)
void kvp_frame_for_each_slot(KvpFrame *f, void(*proc)(const gchar *key, KvpValue *value, gpointer data), gpointer data)
#define LEAVE(format, args...)
Definition: qoflog.h:266
KvpFrame * kvp_value_get_frame(const KvpValue *value)
Definition: kvp_frame.c:1237
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:2906
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1690

◆ gnc_import_account_assist_setup()

AccountPickerDialog * gnc_import_account_assist_setup ( GtkWidget *  parent)

Must be called with the parent widget, ie. a vbox that the account picker dialog will be packed into. The data structure AccountPickerDialog is initialised and default values populated.

Parameters
parentThe parent widget. This is the place the account picker dialog will be packed into.
Returns
A pointer to the AccountPickerDialog which has been setup.

Definition at line 411 of file import-account-matcher.c.

412 {
413  AccountPickerDialog * picker;
414  GtkBuilder *builder;
415  GtkWidget *button, *box, *h_box;
416 
417  /* Init the account picker structure */
418  picker = gnc_import_new_account_picker();
419 
420  /* load the interface */
421  builder = gtk_builder_new();
422  gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker_content");
423  /* connect the signals in the interface */
424  if (builder == NULL)
425  {
426  PERR("Error opening the glade builder interface");
427  }
428 
429  picker->assistant = gtk_widget_get_parent(parent);
430  /* Pack content into Assistant page widget */
431  box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
432  gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
433 
434  picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
435  picker->account_online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
436 
437  /* Add the New Account Button */
438  button = gtk_button_new_with_mnemonic ("_New Account");
439  h_box = gtk_hbox_new(TRUE, 0);
440  gtk_box_pack_start(GTK_BOX(h_box), button, FALSE, FALSE, 0);
441  gtk_box_pack_start( GTK_BOX(box), h_box, FALSE, FALSE, 6);
442  gtk_button_set_use_stock (GTK_BUTTON(button), TRUE);
443  gtk_widget_show (button);
444  g_signal_connect(button, "clicked",
445  G_CALLBACK(gnc_import_add_account), picker);
446 
447  build_acct_tree(picker);
448 
449  g_signal_connect(picker->account_tree, "row-activated",
450  G_CALLBACK(account_tree_row_activated_cb), picker);
451 
452  g_object_unref(G_OBJECT(builder));
453  return picker;
454 }
#define PERR(format, args...)
Definition: qoflog.h:232

◆ gnc_import_account_assist_update()

Account * gnc_import_account_assist_update ( AccountPickerDialog picker)

Must be called with an AccountPickerDialog structure allready setup. If an account with a matching online_id kvp_frame is found, which is allready present in the dialog structure, the function returns with a pointer to that account or NULL if not found.

Parameters
Accountpicker Dialog structure, AccountPickerDialog
Returns
A pointer to the found account, or NULL if account not found.

Definition at line 462 of file import-account-matcher.c.

463 {
464 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255
465 
466  const gchar *retval_name = NULL;
467  gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
468 
469  ENTER("Default commodity received: %s", gnc_commodity_get_fullname( picker->new_account_default_commodity));
470  DEBUG("Default account type received: %s", xaccAccountGetTypeStr( picker->new_account_default_type));
471 
472  /*DEBUG("Looking for account with online_id: %s", picker->account_online_id_value);*/
473  if (picker->account_online_id_value != NULL)
474  {
475  picker->retAccount =
476  gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
477  test_acct_online_id_match,
478  /* This argument will only be used as a "const char*" */
479  (void*)picker->account_online_id_value);
480  }
481 
482  if (picker->account_human_description != NULL)
483  {
484  strncat(account_description_text, picker->account_human_description,
485  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
486  strncat(account_description_text, "\n",
487  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
488  }
489  if (picker->account_online_id_value != NULL)
490  {
491  strncat(account_description_text, _("(Full account ID: "),
492  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
493  strncat(account_description_text, picker->account_online_id_value,
494  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
495  strncat(account_description_text, ")",
496  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
497  }
498  gtk_label_set_text(GTK_LABEL( picker->account_online_id_label), account_description_text);
499 
500  if (picker->default_account == NULL)
501  gnc_tree_view_account_set_selected_account(picker->account_tree, picker->retAccount);
502  else
503  gnc_tree_view_account_set_selected_account(picker->account_tree, picker->default_account);
504 
505  /*FIXME: DEBUG("WRITEME: Here we should check if an account type is compatible, currency matches, etc.\n"); */
506 
507  /*DEBUG("Return value: %p%s%s%s",picker->retAccount,", account name:",xaccAccountGetName(picker->retAccount),"\n");*/
508  retval_name = picker->retAccount ? xaccAccountGetName(picker->retAccount) : NULL;
509  LEAVE("Selected account %p, %s", picker->retAccount, retval_name ? retval_name : "(null)");
510  return picker->retAccount;
511 }
#define DEBUG(format, args...)
Definition: qoflog.h:250
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
Definition: Account.c:2854
#define ENTER(format, args...)
Definition: qoflog.h:256
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
#define LEAVE(format, args...)
Definition: qoflog.h:266
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:2906
const char * xaccAccountGetTypeStr(GNCAccountType type)
Definition: Account.c:4023

◆ gnc_import_exists_online_id()

gboolean gnc_import_exists_online_id ( Transaction *  trans)

Checks whether the given transaction's online_id already exists in its parent account.

Checks whether the given transaction's online_id already exists in its parent account. The given transaction has to be open for editing. If a matching online_id exists, the transaction is destroyed (!) and TRUE is returned, otherwise FALSE is returned.

Parameters
transThe transaction for which to check for an existing online_id.

Definition at line 1114 of file import-backend.c.

1115 {
1116  gboolean online_id_exists = FALSE;
1117  Account *dest_acct;
1118  Split *source_split;
1119 
1120  /* Look for an online_id in the first split */
1121  source_split = xaccTransGetSplit(trans, 0);
1122  g_assert(source_split);
1123 
1124  /* DEBUG("%s%d%s","Checking split ",i," for duplicates"); */
1125  dest_acct = xaccSplitGetAccount(source_split);
1126  online_id_exists = xaccAccountForEachTransaction(dest_acct,
1127  check_trans_online_id,
1128  source_split);
1129 
1130  /* If it does, abort the process for this transaction, since it is
1131  already in the system. */
1132  if (online_id_exists == TRUE)
1133  {
1134  DEBUG("%s", "Transaction with same online ID exists, destroying current transaction");
1135  xaccTransDestroy(trans);
1136  xaccTransCommitEdit(trans);
1137  }
1138  return online_id_exists;
1139 }
gint xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, void *data)
Definition: Account.c:4848
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2126
#define DEBUG(format, args...)
Definition: qoflog.h:250
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1378
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1555
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:732

◆ gnc_import_find_split_matches()

void gnc_import_find_split_matches ( GNCImportTransInfo *  trans_info,
gint  process_threshold,
double  fuzzy_amount_difference,
gint  match_date_hardlimit 
)

/brief Iterate through all splits of the originating account of the given transaction, and find all matching splits there.

Iterate through all splits of the originating account of the given transaction, find all matching splits there, and store them in the GNCImportTransInfo structure.

Parameters
trans_infoThe TransInfo for which the corresponding matching existing transactions should be found.
process_thresholdEach match whose heuristics are smaller than this value is totally ignored.
fuzzy_amount_differenceFor fuzzy amount matching, a certain fuzzyness in the matching amount is allowed up to this value. May be e.g. 3.00 dollars for ATM fees, or 0.0 if you only want to allow exact matches.
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.

Definition at line 795 of file import-backend.c.

799 {
800  GList * list_element;
801  Query *query = qof_query_create_for(GNC_ID_SPLIT);
802  g_assert (trans_info);
803 
804  /* Get list of splits of the originating account. */
805  {
806  /* We used to traverse *all* splits of the account by using
807  xaccAccountGetSplitList, which is a bad idea because 90% of these
808  splits are outside the date range that is interesting. We should
809  rather use a query according to the date region, which is
810  implemented here.
811  */
812  Account *importaccount =
814  time64 download_time = xaccTransGetDate (gnc_import_TransInfo_get_trans (trans_info));
815 
816  qof_query_set_book (query, gnc_get_current_book());
817  xaccQueryAddSingleAccountMatch (query, importaccount,
818  QOF_QUERY_AND);
819  xaccQueryAddDateMatchTT (query,
820  TRUE, download_time - match_date_hardlimit * 86400,
821  TRUE, download_time + match_date_hardlimit * 86400,
822  QOF_QUERY_AND);
823  list_element = qof_query_run (query);
824  /* Sigh. Doesn't help too much. We still create and run one query
825  for each imported transaction. Maybe it would improve
826  performance further if there is one single (master-)query at
827  the beginning, matching the full date range and all accounts in
828  question. However, this doesn't quite work because this function
829  here is called from each gnc_gen_trans_list_add_trans(), which
830  is called one at a time. Therefore the whole importer would
831  have to change its behaviour: Accept the imported txns via
832  gnc_gen_trans_list_add_trans(), and only when
833  gnc_gen_trans_list_run() is called, then calculate all the
834  different match candidates. That's too much work for now.
835  */
836  }
837 
838  /* Traverse that list, calling split_find_match on each one. Note
839  that xaccAccountForEachSplit is declared in Account.h but
840  implemented nowhere :-( */
841  while (list_element != NULL)
842  {
843  split_find_match (trans_info, list_element->data,
844  process_threshold, fuzzy_amount_difference);
845  list_element = g_list_next (list_element);
846  }
847 
848  qof_query_destroy (query);
849 }
time64 xaccTransGetDate(const Transaction *trans)
Definition: Transaction.c:2219
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
void qof_query_destroy(QofQuery *q)
Definition: qofquery.c:975
void qof_query_set_book(QofQuery *q, QofBook *book)
Definition: qofquery.c:1291
GList * qof_query_run(QofQuery *q)
Definition: qofquery.c:833
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:732
gint64 time64
Definition: gnc-date.h:79

◆ gnc_import_match_picker_run_and_close()

void gnc_import_match_picker_run_and_close ( GNCImportTransInfo *  transaction_info,
GNCImportPendingMatches *  pending_matches 
)

Run a match_picker dialog so that the selected-MatchInfo in the given trans_info is updated accordingly. This functions will only return after the user clicked Ok, Cancel, or Window-Close.

Run a match_picker dialog where the user should pick the best match for 'one' given transaction, so that the selected-MatchInfo in the given trans_info is updated accordingly. This functions will only return after the user clicked Ok, Cancel, or Window-Close.

The dialog uses the same functionality as the one created through gnc_import_add_trans(), except that its two listviews are shown above one another, and the listview of downloaded transactions shows only one transaction, namely, the given trans_info.

This function is used from the gnc-gen-transaction code.

Parameters
transaction_infoThe TransInfo for which the user is supposed to pick a matching transaction.

Definition at line 507 of file import-match-picker.c.

509 {
510  GNCImportMatchPicker *matcher;
511  gint response;
512  GNCImportMatchInfo *old;
513  gboolean old_selected_manually;
514  g_assert (transaction_info);
515 
516  /* Create a new match_picker, even though it's stored in a
517  transmatcher struct :-) */
518  matcher = g_new0(GNCImportMatchPicker, 1);
519 
520  matcher->pending_matches = pending_matches;
521 
522  /* DEBUG("Init match_picker"); */
523  init_match_picker_gui(matcher);
524 
525  /* Append this single transaction to the view and select it */
526  downloaded_transaction_append(matcher, transaction_info);
527 
528  old = gnc_import_TransInfo_get_selected_match (transaction_info);
529  old_selected_manually =
531 
532  /* Let this dialog run and close. */
533  /*DEBUG("Right before run and close");*/
534  gtk_window_set_modal(GTK_WINDOW(matcher->transaction_matcher), TRUE);
535  response = gtk_dialog_run (GTK_DIALOG (matcher->transaction_matcher));
536 
537  gnc_save_window_size(GNC_PREFS_GROUP,
538  GTK_WINDOW (matcher->transaction_matcher));
539  gtk_widget_destroy (matcher->transaction_matcher);
540  /*DEBUG("Right after run and close");*/
541  /* DEBUG("Response was %d.", response); */
542  if (response == GTK_RESPONSE_OK && matcher->selected_match_info != old)
543  {
544  /* OK was pressed */
546  matcher->selected_match_info,
547  TRUE);
548 
549  gnc_import_PendingMatches_remove_match (pending_matches,
550  old,
551  old_selected_manually);
552  gnc_import_PendingMatches_add_match (pending_matches,
553  matcher->selected_match_info,
554  TRUE);
555  }
556 }
void gnc_import_TransInfo_set_selected_match_info(GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
gboolean gnc_import_TransInfo_get_match_selected_manually(const GNCImportTransInfo *info)
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)

◆ gnc_import_MatchInfo_get_probability()

gint gnc_import_MatchInfo_get_probability ( const GNCImportMatchInfo info)

Get the probability (confidence level) of this MatchInfo.

Parameters
infoCan be NULL, in which case the function returns 0

Definition at line 239 of file import-backend.c.

240 {
241  if (info)
242  {
243  return info->probability;
244  }
245  else
246  {
247  return 0;
248  }
249 }

◆ gnc_import_MatchInfo_get_split()

Split * gnc_import_MatchInfo_get_split ( const GNCImportMatchInfo info)

Get the split ('this-side split') of this MatchInfo.

Definition at line 232 of file import-backend.c.

233 {
234  g_assert (info);
235  return info->split;
236 }

◆ gnc_import_process_trans_item()

gboolean gnc_import_process_trans_item ( GncImportMatchMap *  matchmap,
GNCImportTransInfo *  trans_info 
)

/brief – Processes one match according to its selected action.

This function is intended to be called when the importer dialog is finished. It should be called once for each imported transaction and processes each ImportTransInfo according to its selected action: For GNCImport_ADD, the transaction is added etc. etc.

Each successful match is also stored in the given ImportMatchMap, or, if that argument is NULL, in the ImportMatchMap of each originating account.

Parameters
matchmapThe ImportMatchMap where each match should be stored. May be NULL, in which case the ImportMatchMap of each account will be used.
trans_infoThe ImportTransInfo item to process.
Returns
TRUE if the item has been processed.

Definition at line 858 of file import-backend.c.

860 {
861  Split * other_split;
862  gnc_numeric imbalance_value;
863 
864  /* DEBUG("Begin"); */
865 
866  g_assert (trans_info);
867  /*DEBUG("Iteration %d, action %d, split %s", i,
868  trans_info->action,
869  xaccTransGetDescription (gnc_import_TransInfo_get_trans
870  (trans_info)))*/
871  switch (gnc_import_TransInfo_get_action (trans_info))
872  {
873  case GNCImport_SKIP:
874  return FALSE;
875  case GNCImport_ADD:
876  /* Transaction gets imported. */
877 
878  /* Is the transaction not balanced and there is a non-NULL destination account? */
879  if (gnc_import_TransInfo_is_balanced(trans_info) == FALSE
880  && gnc_import_TransInfo_get_destacc(trans_info) != NULL)
881  {
882  /* Create the 'other' split. */
883  Split *split =
885  (gnc_account_get_book
886  (gnc_import_TransInfo_get_destacc (trans_info)));
888  (gnc_import_TransInfo_get_trans (trans_info), split);
890  (gnc_import_TransInfo_get_destacc (trans_info), split);
891  /*xaccSplitSetBaseValue
892  (split,
893  gnc_numeric_neg(xaccTransGetImbalance
894  (gnc_import_TransInfo_get_trans (trans_info))),
895  xaccTransGetCurrency
896  (gnc_import_TransInfo_get_trans (trans_info)));*/
897  {
898  /* This is a quick workaround for the bug described in
899  http://gnucash.org/pipermail/gnucash-devel/2003-August/009982.html
900  Assume that importers won't create transactions involving two or more
901  currencies so we can use xaccTransGetImbalanceValue. */
902  imbalance_value =
904  (gnc_import_TransInfo_get_trans (trans_info)));
905  xaccSplitSetValue (split, imbalance_value);
906  xaccSplitSetAmount (split, imbalance_value);
907  }
908  /*xaccSplitSetMemo (split, _("Auto-Balance split"));
909  -- disabled due to popular request */
910  }
911 
913  /*Set reconcile date to today*/
915  gnc_time (NULL));
916  /* Done editing. */
918  return TRUE;
919  case GNCImport_UPDATE:
920  {
921  GNCImportMatchInfo *selected_match =
923 
924  /* If there is no selection, ignore this transaction. */
925  if (!selected_match)
926  {
927  PWARN("No matching translaction to be cleared was chosen. Imported transaction will be ignored.");
928  break;
929  }
930 
931  /* Transaction gets not imported but the matching one gets
932  updated and reconciled. */
933  if (gnc_import_MatchInfo_get_split(selected_match) == NULL)
934  {
935  PERR("The split I am trying to update and reconcile is NULL, shouldn't happen!");
936  }
937  else
938  {
939  /* Update and reconcile the matching transaction */
940  /*DEBUG("BeginEdit selected_match")*/
941  xaccTransBeginEdit(selected_match->trans);
942 
943  xaccTransSetDatePostedSecsNormalized(selected_match->trans,
945  gnc_import_TransInfo_get_fsplit(trans_info))));
946 
947  xaccSplitSetAmount(selected_match->split,
949  gnc_import_TransInfo_get_fsplit(trans_info)));
950  xaccSplitSetValue(selected_match->split,
952  gnc_import_TransInfo_get_fsplit(trans_info)));
953 
954  imbalance_value = xaccTransGetImbalanceValue(
955  gnc_import_TransInfo_get_trans(trans_info));
956  other_split = xaccSplitGetOtherSplit(selected_match->split);
957  if (!gnc_numeric_zero_p(imbalance_value) && other_split)
958  {
959  if (xaccSplitGetReconcile(other_split) == NREC)
960  {
961  imbalance_value = gnc_numeric_neg(imbalance_value);
962  xaccSplitSetValue(other_split, imbalance_value);
963  xaccSplitSetAmount(other_split, imbalance_value);
964  }
965  /* else GC will automatically insert a split to equity
966  to balance the transaction */
967  }
968 
969  xaccTransSetDescription(selected_match->trans,
971  gnc_import_TransInfo_get_trans(trans_info)));
972 
973  if (xaccSplitGetReconcile(selected_match->split) == NREC)
974  {
975  xaccSplitSetReconcile(selected_match->split, CREC);
976  }
977 
978  /* Set reconcile date to today */
979  xaccSplitSetDateReconciledSecs(selected_match->split, gnc_time (NULL));
980 
981  /* Copy the online id to the reconciled transaction, so
982  the match will be remembered */
983  if (gnc_import_split_has_online_id(trans_info->first_split))
984  {
985  gnc_import_set_split_online_id(selected_match->split,
986  gnc_import_get_split_online_id(trans_info->first_split));
987  }
988 
989  /* Done editing. */
990  /*DEBUG("CommitEdit selected_match")*/
991  xaccTransCommitEdit(selected_match->trans);
992 
993  /* Store the mapping to the other account in the MatchMap. */
994  matchmap_store_destination(matchmap, trans_info, TRUE);
995 
996  /* Erase the downloaded transaction */
997  xaccTransDestroy(trans_info->trans);
998  /*DEBUG("CommitEdit trans")*/
999  xaccTransCommitEdit(trans_info->trans);
1000  /* Very important: Make sure the freed transaction is not freed again! */
1001  trans_info->trans = NULL;
1002  }
1003  }
1004  return TRUE;
1005  case GNCImport_CLEAR:
1006  {
1007  GNCImportMatchInfo *selected_match =
1009 
1010  /* If there is no selection, ignore this transaction. */
1011  if (!selected_match)
1012  {
1013  PWARN("No matching translaction to be cleared was chosen. Imported transaction will be ignored.");
1014  break;
1015  }
1016 
1017  /* Transaction gets not imported but the matching one gets
1018  reconciled. */
1019  if (gnc_import_MatchInfo_get_split (selected_match) == NULL)
1020  {
1021  PERR("The split I am trying to reconcile is NULL, shouldn't happen!");
1022  }
1023  else
1024  {
1025  /* Reconcile the matching transaction */
1026  /*DEBUG("BeginEdit selected_match")*/
1027  xaccTransBeginEdit(selected_match->trans);
1028 
1030  (selected_match->split) == NREC)
1032  (selected_match->split, CREC);
1033  /* Set reconcile date to today */
1035  (selected_match->split, gnc_time (NULL));
1036 
1037  /* Copy the online id to the reconciled transaction, so
1038  the match will be remembered */
1039  if (gnc_import_split_has_online_id(trans_info->first_split))
1040  gnc_import_set_split_online_id
1041  (selected_match->split,
1042  gnc_import_get_split_online_id(trans_info->first_split));
1043 
1044  /* Done editing. */
1045  /*DEBUG("CommitEdit selected_match")*/
1047  (selected_match->trans);
1048 
1049  /* Store the mapping to the other account in the MatchMap. */
1050  matchmap_store_destination (matchmap, trans_info, TRUE);
1051 
1052  /* Erase the downloaded transaction */
1053  xaccTransDestroy(trans_info->trans);
1054  /*DEBUG("CommitEdit trans")*/
1055  xaccTransCommitEdit(trans_info->trans);
1056  /* Very important: Make sure the freed transaction is not freed again! */
1057  trans_info->trans = NULL;
1058  }
1059  }
1060  return TRUE;
1061  default:
1062  DEBUG("Invalid GNCImportAction for this imported transaction.");
1063  break;
1064  }
1065  /*DEBUG("End");*/
1066  return FALSE;
1067 }
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1074
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:351
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
Definition: Transaction.c:1896
time64 xaccTransGetDate(const Transaction *trans)
Definition: Transaction.c:2219
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Definition: gnc-numeric.c:745
#define DEBUG(format, args...)
Definition: qoflog.h:250
char xaccSplitGetReconcile(const Split *split)
Definition: Split.c:1735
Split * gnc_import_TransInfo_get_fsplit(const GNCImportTransInfo *info)
void xaccTransSetDescription(Transaction *trans, const char *desc)
Definition: Transaction.c:2067
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
gboolean gnc_numeric_zero_p(gnc_numeric a)
Definition: gnc-numeric.c:173
void xaccSplitSetReconcile(Split *split, char recn)
Definition: Split.c:1581
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1658
#define PERR(format, args...)
Definition: qoflog.h:232
GNCImportAction gnc_import_TransInfo_get_action(const GNCImportTransInfo *info)
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1378
#define PWARN(format, args...)
Definition: qoflog.h:238
Split * gnc_import_MatchInfo_get_split(const GNCImportMatchInfo *info)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Definition: Split.c:1042
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
Definition: Transaction.c:956
const char * xaccTransGetDescription(const Transaction *trans)
Definition: Transaction.c:2188
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1555
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1356
#define CREC
Definition: Split.h:67
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:349
void xaccSplitSetDateReconciledSecs(Split *split, time64 secs)
Definition: Split.c:1607
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1748
#define xaccAccountInsertSplit(acc, s)
Definition: Account.h:972
Split * xaccSplitGetOtherSplit(const Split *split)
Definition: Split.c:1841
Account * gnc_import_TransInfo_get_destacc(const GNCImportTransInfo *info)
time64 gnc_time(time64 *tbuf)
get the current local time
Definition: gnc-date.c:410
GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match(const GNCImportTransInfo *info)
gboolean gnc_import_TransInfo_is_balanced(const GNCImportTransInfo *info)
#define NREC
Definition: Split.h:70
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1742

◆ gnc_import_select_account()

Account * gnc_import_select_account ( GtkWidget *  parent,
const gchar *  account_online_id_value,
gboolean  auto_create,
const gchar *  account_human_description,
const gnc_commodity *  new_account_default_commodity,
GNCAccountType  new_account_default_type,
Account default_selection,
gboolean *  ok_pressed 
)

Must be called with a string containing a unique identifier for the account. If an account with a matching online_id kvp_frame is found, the function immediately returns with a pointer to that account. Otherwise, the user is prompted to select a GnuCash account or create a new one (in both cases, the unique identifier is written to the account's kvp_frame, so the user won't be prompted again). If the user refuses to select or create an account, NULL is returned.

Parameters
parentThe parent widget. Can be NULL.
account_online_id_valueThe string containing your unique account_id coming from some string of your module. This is the normal mode of operation. Can be NULL.

If account_online_id_value==NULL, you basically end up with an account selector that allows you to select an account whose GncGUID will be remembered elsewhere. You would fill account_human_description to tell the user what he is looking for. In this mode, the online_id kvp_frame of the found account will not be touched. To use this mode, auto_create must NOT be set to 0.

Parameters
account_human_descriptionA human-readable description of the account. Can be NULL. If it is not NULL, it will be shown before the id in the account matching dialog. It will also be used as the default account name if a new account is created.
new_account_default_commodityDefault commodity of the new account. Can be NULL. If not NULL, it will be the account's commodity if a new account is created. Also, if not NULL, the function will also warn the user if the found or created account's commodity doesn't match.
new_account_default_typeDefault account type of a new account. Can be NULL. If not ACCT_TYPE_NONE, it will be the account's type if a new account is created. If not ACCT_TYPE_NONE, the function will also warn the user if the found or created account's commodity doesn't match.
auto_createOnly active if no account with the account_online_id_value could be found in gnucash, or if online-id was NULL. In that case, if auto_create is TRUE (nonzero), the user will be asked to create a new account. If auto_create is FALSE (zero), this function will simply return NULL but will neither select nor create any account.
default_selectionIf not NULL, that account will be pre-selected by default.
ok_pressedA pointer to gboolean. If non-NULL, whether or not the picker dialog was closed by the user pressing ok will be stored in the parameter. If no dialog was created by the gnc_import_select_account() call, TRUE is always returned.
Returns
A pointer to the found or created Account, or NULL if no account was found or created.

Definition at line 224 of file import-account-matcher.c.

232 {
233 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255
234  AccountPickerDialog * picker;
235  gint response;
236  Account * retval = NULL;
237  const gchar *retval_name = NULL;
238  GtkBuilder *builder;
239  GtkWidget * online_id_label, *button, *box, *pbox;
240  gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
241  gboolean ok_pressed_retval = FALSE;
242 
243  ENTER("Default commodity received: %s", gnc_commodity_get_fullname( new_account_default_commodity));
244  DEBUG("Default account type received: %s", xaccAccountGetTypeStr( new_account_default_type));
245  picker = g_new0(AccountPickerDialog, 1);
246 
247  picker->account_online_id_value = account_online_id_value;
248  picker->account_human_description = account_human_description;
249  picker->new_account_default_commodity = new_account_default_commodity;
250  picker->new_account_default_type = new_account_default_type;
251 
252  /*DEBUG("Looking for account with online_id: \"%s\"", account_online_id_value);*/
253  if (account_online_id_value != NULL)
254  {
255  retval =
256  gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
257  test_acct_online_id_match,
258  /* This argument will only be used as a "const char*" */
259  (void*)account_online_id_value);
260 
261  /* BEGIN: try again without extra space at the end */
262  /*
263  * libofx, used for file import, generates online_id as
264  * ACCTID + space + ACCTKEY which differs from the online_id
265  * generated by aqbanking for online ofx transfer as ACCTID.
266  *
267  * If a gnucash account has been associated with an online_id
268  * via aqbanking data, it is not possible to construct an OFX
269  * file for gnucash import that matches the same online_id
270  * because even with no ACCTKEY in the file, there will be a
271  * trailing space.
272  *
273  * This is a hack to overcome that problem.
274  */
275  if ((retval == NULL) && g_str_has_suffix(account_online_id_value, " "))
276  {
277  gchar *trimmed = g_strndup(account_online_id_value, strlen(account_online_id_value) - 1);
278  if (trimmed)
279  {
281  gnc_get_current_root_account (),
282  test_acct_online_id_match,
283  (void *)trimmed);
284  }
285  g_free(trimmed);
286  }
287  /* END: try again without extra space at the end */
288  }
289  if (retval == NULL && auto_create != 0)
290  {
291  /* load the interface */
292  builder = gtk_builder_new();
293  gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker");
294  gnc_builder_add_from_file (builder, "dialog-import.glade", "account_picker_content");
295  /* connect the signals in the interface */
296  if (builder == NULL)
297  {
298  PERR("Error opening the glade builder interface");
299  }
300  picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker"));
301  if (parent)
302  gtk_window_set_transient_for (GTK_WINDOW (picker->dialog),
303  GTK_WINDOW (parent));
304 
305  /* Pack the content into the dialog vbox */
306  pbox = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_vbox"));
307  box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
308  gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE, 0);
309 
310  picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
311  online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
312  button = GTK_WIDGET(gtk_builder_get_object (builder, "newbutton"));
313  gtk_button_set_use_stock (GTK_BUTTON(button), TRUE);
314 
315  //printf("gnc_import_select_account(): Fin get widget\n");
316 
317  if (account_human_description != NULL)
318  {
319  strncat(account_description_text, account_human_description,
320  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
321  strncat(account_description_text, "\n",
322  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
323  }
324  if (account_online_id_value != NULL)
325  {
326  strncat(account_description_text, _("(Full account ID: "),
327  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
328  strncat(account_description_text, account_online_id_value,
329  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
330  strncat(account_description_text, ")",
331  ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
332  }
333  gtk_label_set_text((GtkLabel*)online_id_label, account_description_text);
334  build_acct_tree(picker);
335  gnc_tree_view_account_set_selected_account(picker->account_tree, default_selection);
336 
337  gtk_window_set_modal(GTK_WINDOW(picker->dialog), TRUE);
338  g_signal_connect(picker->account_tree, "row-activated",
339  G_CALLBACK(account_tree_row_activated_cb), picker);
340  do
341  {
342  response = gtk_dialog_run(GTK_DIALOG(picker->dialog));
343  switch (response)
344  {
345  case GTK_RESPONSE_OK:
346  retval = gnc_tree_view_account_get_selected_account(picker->account_tree);
347  if (retval)
348  retval_name = xaccAccountGetName(retval);
349  if (!retval_name)
350  retval_name = "(null)";
351  DEBUG("Selected account %p, %s", retval, retval_name);
352 
353  /* See if the selected account is a placeholder. */
354  if (retval && xaccAccountGetPlaceholder (retval))
355  {
356  gnc_error_dialog
357  (picker->dialog,
358  _("The account %s is a placeholder account and does not allow "
359  "transactions. Please choose a different account."),
360  retval_name);
361  response = GNC_RESPONSE_NEW;
362  break;
363  }
364 
365  if ( account_online_id_value != NULL)
366  {
367  gnc_import_set_acc_online_id(retval, account_online_id_value);
368  }
369  ok_pressed_retval = TRUE;
370  break;
371  case GNC_RESPONSE_NEW:
372  gnc_import_add_account(NULL, picker);
373  ok_pressed_retval = TRUE;
374  break;
375  default:
376  ok_pressed_retval = FALSE;
377  break;
378  }
379  }
380  while (response == GNC_RESPONSE_NEW);
381 
382  g_object_unref(G_OBJECT(builder));
383  gtk_widget_destroy(picker->dialog);
384  }
385  else
386  {
387  retval_name = retval ? xaccAccountGetName(retval) : NULL;
388  ok_pressed_retval = TRUE; /* There was no dialog involved, so the computer "pressed" ok */
389  }
390  /*FIXME: DEBUG("WRITEME: gnc_import_select_account() Here we should check if account type is compatible, currency matches, etc.\n"); */
391  g_free(picker);
392  /*DEBUG("Return value: %p%s%s%s",retval,", account name:",xaccAccountGetName(retval),"\n");*/
393  if (ok_pressed != NULL)
394  {
395  *ok_pressed = ok_pressed_retval;
396  }
397  LEAVE("Selected account %p, %s", retval, retval_name ? retval_name : "(null)");
398  return retval;
399 }
#define DEBUG(format, args...)
Definition: qoflog.h:250
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
Definition: Account.c:2854
#define PERR(format, args...)
Definition: qoflog.h:232
#define ENTER(format, args...)
Definition: qoflog.h:256
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
void gnc_tree_view_account_set_selected_account(GncTreeViewAccount *view, Account *account)
gboolean xaccAccountGetPlaceholder(const Account *acc)
Definition: Account.c:3798
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
#define LEAVE(format, args...)
Definition: qoflog.h:266
const char * xaccAccountGetName(const Account *acc)
Definition: Account.c:2906
const char * xaccAccountGetTypeStr(GNCAccountType type)
Definition: Account.c:4023

◆ gnc_import_select_commodity()

gnc_commodity * gnc_import_select_commodity ( const char *  cusip,
gboolean  ask_on_unknown,
const char *  default_fullname,
const char *  default_mnemonic 
)

Must be called with a string containing a unique identifier for the commodity. If an commodity with a matching cusip is found, the function immediately returns with a pointer to that commodity. Otherwise, the user may be prompted to select a GnuCash commodity or create a new one (in both cases, the cusip is written to the commodity's cusip field, overwriting anything that was there before.

Parameters
cusipThe string containing the code for which you want a matching commodity. A CUISP code or similar UNIQUE code. The stock ticker is NOT appropriate, unless you have no other option. Must be non-NULL.
ask_on_unknownIf the cusip value is unknown and this parameter is false (zero), the function returns NULL. Otherwise the user will be asked to select an existing or create a new commodity.
default_fullnameA human-readable description of the commodity, such as the stock name. Can be NULL. If it is not NULL, it will be shown to the user when selecting a commodity. It will also be used as the default if a new commodity is created.
default_mnemonicUsually the stock ticker or similar. Can be NULL. If it is not NULL, it will be shown to the user when selecting a commodity. It will also be used as the default if a new commodity is created.
Returns
A pointer to the found or created commodity, or NULL if no commodity was found or created.

Definition at line 53 of file import-commodity-matcher.c.

57 {
58  const gnc_commodity_table * commodity_table = gnc_get_current_commodities ();
59  gnc_commodity * retval = NULL;
60  gnc_commodity * tmp_commodity = NULL;
61  char * tmp_namespace = NULL;
62  GList * commodity_list = NULL;
63  GList * namespace_list = NULL;
64  DEBUG("Default fullname received: %s",
65  default_fullname ? default_fullname : "(null)");
66  DEBUG("Default mnemonic received: %s",
67  default_mnemonic ? default_mnemonic : "(null)");
68 
69  g_return_val_if_fail(cusip, NULL);
70  DEBUG("Looking for commodity with exchange_code: %s", cusip);
71 
72  g_assert(commodity_table);
73  namespace_list = gnc_commodity_table_get_namespaces(commodity_table);
74 
75 
76  namespace_list = g_list_first(namespace_list);
77  while ( namespace_list != NULL && retval == NULL)
78  {
79  tmp_namespace = namespace_list->data;
80  DEBUG("Looking at namespace %s", tmp_namespace);
81  commodity_list = gnc_commodity_table_get_commodities(commodity_table,
82  tmp_namespace);
83  commodity_list = g_list_first(commodity_list);
84  while ( commodity_list != NULL && retval == NULL)
85  {
86  const char* tmp_cusip = NULL;
87  tmp_commodity = commodity_list->data;
88  DEBUG("Looking at commodity %s",
89  gnc_commodity_get_fullname(tmp_commodity));
90  tmp_cusip = gnc_commodity_get_cusip(tmp_commodity);
91  if (tmp_cusip != NULL && cusip != NULL)
92  {
93  int len = strlen(cusip) > strlen(tmp_cusip) ? strlen(cusip) :
94  strlen(tmp_cusip);
95  if (strncmp(tmp_cusip, cusip, len) == 0)
96  {
97  retval = tmp_commodity;
98  DEBUG("Commodity %s%s",
99  gnc_commodity_get_fullname(retval), " matches.");
100  }
101  }
102  commodity_list = g_list_next(commodity_list);
103  }
104  namespace_list = g_list_next(namespace_list);
105  }
106 
107  g_list_free(commodity_list);
108  g_list_free(namespace_list);
109 
110  if (retval == NULL && ask_on_unknown != 0)
111  {
112  const gchar *message =
113  _("Please select a commodity to match the following exchange "
114  "specific code. Please note that the exchange code of the "
115  "commodity you select will be overwritten.");
117  NULL,
119  message,
120  cusip,
121  default_fullname,
122  default_mnemonic);
123 
124  }
125  /* There seems to be a problem here - if the matched commodity does not
126  have a cusip defined (gnc_commodity_get_cusip returns NULL) then
127  it does not get overwritten - which is not consistent with the
128  message - so Im adding it to do this. Looks like this is all
129  that was needed to fix the cash value used as stock units problem
130  for pre-defined commodities which didnt have the cusip defined! */
131  if (retval != NULL &&
132  gnc_commodity_get_cusip(retval) != NULL &&
133  cusip != NULL &&
134  (strncmp(gnc_commodity_get_cusip(retval), cusip, strlen(cusip)) != 0))
135  {
136  gnc_commodity_set_cusip(retval, cusip);
137  }
138  else if (gnc_commodity_get_cusip(retval) == NULL && cusip != NULL)
139  {
140  gnc_commodity_set_cusip(retval, cusip);
141  }
142  return retval;
143 };
const char * gnc_commodity_get_cusip(const gnc_commodity *cm)
#define DEBUG(format, args...)
Definition: qoflog.h:250
GList * gnc_commodity_table_get_namespaces(const gnc_commodity_table *table)
void gnc_commodity_set_cusip(gnc_commodity *cm, const char *cusip)
gnc_commodity * gnc_ui_select_commodity_modal_full(gnc_commodity *orig_sel, GtkWidget *parent, dialog_commodity_mode mode, const char *user_message, const char *cusip, const char *fullname, const char *mnemonic)
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
CommodityList * gnc_commodity_table_get_commodities(const gnc_commodity_table *table, const char *name_space)

◆ gnc_import_Settings_delete()

void gnc_import_Settings_delete ( GNCImportSettings *  settings)

Destructor

Definition at line 106 of file import-settings.c.

107 {
108  if (settings)
109  {
110  g_free(settings);
111  }
112 }

◆ gnc_import_Settings_get_action_add_enabled()

gboolean gnc_import_Settings_get_action_add_enabled ( GNCImportSettings *  settings)

Return the selected action is enable state.

Definition at line 127 of file import-settings.c.

128 {
129  g_assert (settings);
130  return settings->action_add_enabled;
131 };

◆ gnc_import_Settings_get_action_clear_enabled()

gboolean gnc_import_Settings_get_action_clear_enabled ( GNCImportSettings *  settings)

Return the selected action is enable state.

Definition at line 139 of file import-settings.c.

140 {
141  g_assert (settings);
142  return settings->action_clear_enabled;
143 };

◆ gnc_import_Settings_get_action_skip_enabled()

gboolean gnc_import_Settings_get_action_skip_enabled ( GNCImportSettings *  settings)

Return the selected action is enable state.

Definition at line 121 of file import-settings.c.

122 {
123  g_assert (settings);
124  return settings->action_skip_enabled;
125 };

◆ gnc_import_Settings_get_action_update_enabled()

gboolean gnc_import_Settings_get_action_update_enabled ( GNCImportSettings *  settings)

Return the selected action is enable state.

Definition at line 133 of file import-settings.c.

134 {
135  g_assert (settings);
136  return settings->action_update_enabled;
137 };

◆ gnc_import_Settings_get_add_threshold()

gint gnc_import_Settings_get_add_threshold ( GNCImportSettings *  settings)

Return the selected threshold.

Definition at line 151 of file import-settings.c.

152 {
153  g_assert (settings);
154  return settings->add_threshold;
155 };

◆ gnc_import_Settings_get_clear_threshold()

gint gnc_import_Settings_get_clear_threshold ( GNCImportSettings *  settings)

Return the selected threshold.

Definition at line 145 of file import-settings.c.

146 {
147  g_assert (settings);
148  return settings->clear_threshold;
149 };

◆ gnc_import_Settings_get_display_threshold()

gint gnc_import_Settings_get_display_threshold ( GNCImportSettings *  settings)

Return the selected threshold.

Definition at line 157 of file import-settings.c.

158 {
159  g_assert (settings);
160  return settings->display_threshold;
161 };

◆ gnc_import_Settings_get_fuzzy_amount()

double gnc_import_Settings_get_fuzzy_amount ( GNCImportSettings *  settings)

Return the allowed amount range for fuzzy amount matching.

Returns
The allowed amount range for fuzzy amount matching, in the users default commodity.

Definition at line 115 of file import-settings.c.

116 {
117  g_assert (settings);
118  return settings->fuzzy_amount;
119 };

◆ gnc_import_Settings_get_match_date_hardlimit()

gint gnc_import_Settings_get_match_date_hardlimit ( const GNCImportSettings *  settings)

Returns the hard-limiting number of days that a matching split may differ.

Definition at line 168 of file import-settings.c.

169 {
170  g_assert(s);
171  return s->match_date_hardlimit;
172 }

◆ gnc_import_Settings_new()

GNCImportSettings * gnc_import_Settings_new ( void  )

Allocates a new GNCImportSettings object, and initialize it with the appropriate user prefs.

Definition at line 78 of file import-settings.c.

79 {
80  GNCImportSettings * settings;
81 
82  settings = g_new0 ( GNCImportSettings, 1);
83 
84 
85  settings->action_skip_enabled =
86  gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_ENABLE_SKIP);
87  settings->action_update_enabled =
88  gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_ENABLE_UPDATE);
89  settings->action_add_enabled = DEFAULT_ACTION_ADD_ENABLED;
90  settings->action_clear_enabled = DEFAULT_ACTION_CLEAR_ENABLED;
91  settings->clear_threshold =
92  (int)gnc_prefs_get_float (GNC_PREFS_GROUP_IMPORT, GNC_PREF_AUTO_CLEAR_THRESHOLD);
93  settings->add_threshold =
94  (int)gnc_prefs_get_float (GNC_PREFS_GROUP_IMPORT, GNC_PREF_AUTO_ADD_THRESHOLD);
95  settings->display_threshold =
96  (int)gnc_prefs_get_float (GNC_PREFS_GROUP_IMPORT, GNC_PREF_MATCH_THRESHOLD);
97 
98  settings->fuzzy_amount =
99  gnc_prefs_get_float (GNC_PREFS_GROUP_IMPORT, GNC_PREF_ATM_FEE_THRESHOLD);
100 
101  settings->match_date_hardlimit = 42; /* 6 weeks */
102  return settings;
103 }
#define GNC_PREFS_GROUP_IMPORT
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196
gdouble gnc_prefs_get_float(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:227

◆ gnc_import_Settings_set_match_date_hardlimit()

void gnc_import_Settings_set_match_date_hardlimit ( GNCImportSettings *  settings,
gint  match_date_hardlimit 
)
Parameters
match_date_hardlimitThe number of days that a matching split may differ from the given transaction before it is discarded immediately. In other words, any split that is more distant from the given transaction than this match_date_hardlimit days will be ignored altogether. For use cases without paper checks (e.g. HBCI), values like 14 (days) might be appropriate, whereas for use cases with paper checks (e.g. OFX, QIF), values like 42 (days) seem more appropriate.

Definition at line 163 of file import-settings.c.

164 {
165  g_assert(s);
166  s->match_date_hardlimit = m;
167 }

◆ gnc_import_TransInfo_delete()

void gnc_import_TransInfo_delete ( GNCImportTransInfo *  info)

Destructor

Definition at line 251 of file import-backend.c.

252 {
253  if (info)
254  {
255  g_list_free (info->match_list);
256  /*If the transaction exists and is still open, it must be destroyed*/
257  if (info->trans && xaccTransIsOpen(info->trans))
258  {
259  xaccTransDestroy(info->trans);
260  xaccTransCommitEdit(info->trans);
261  }
262  if (info->match_tokens)
263  {
264  GList *node;
265 
266  for (node = info->match_tokens; node; node = node->next)
267  g_free (node->data);
268 
269  g_list_free (info->match_tokens);
270  }
271  g_free(info);
272  }
273 }
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1795
void xaccTransDestroy(Transaction *trans)
Definition: Transaction.c:1378
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1555

◆ gnc_import_TransInfo_get_action()

GNCImportAction gnc_import_TransInfo_get_action ( const GNCImportTransInfo *  info)

Returns the currently selected action for this TransInfo.

Definition at line 169 of file import-backend.c.

170 {
171  g_assert (info);
172  return info->action;
173 }

◆ gnc_import_TransInfo_get_destacc()

Account * gnc_import_TransInfo_get_destacc ( const GNCImportTransInfo *  info)

Returns the 'other account' of this transaction. May return NULL.

Definition at line 188 of file import-backend.c.

189 {
190  g_assert (info);
191  return info->dest_acc;
192 }

◆ gnc_import_TransInfo_get_destacc_selected_manually()

gboolean gnc_import_TransInfo_get_destacc_selected_manually ( const GNCImportTransInfo *  info)

Returns if the currently selected destination account for auto-matching was selected by the user.

Definition at line 209 of file import-backend.c.

210 {
211  g_assert (info);
212  return info->dest_acc_selected_manually;
213 }

◆ gnc_import_TransInfo_get_fsplit()

Split * gnc_import_TransInfo_get_fsplit ( const GNCImportTransInfo *  info)

Returns the first split of the transaction of this TransInfo.

Definition at line 138 of file import-backend.c.

139 {
140  g_assert (info);
141  return info->first_split;
142 }

◆ gnc_import_TransInfo_get_match_list()

GList * gnc_import_TransInfo_get_match_list ( const GNCImportTransInfo *  info)

Returns the stored list of possible matches.

Definition at line 107 of file import-backend.c.

108 {
109  g_assert (info);
110  return info->match_list;
111 }

◆ gnc_import_TransInfo_get_match_selected_manually()

gboolean gnc_import_TransInfo_get_match_selected_manually ( const GNCImportTransInfo *  info)

Returns if the currently selected match was selected by the user.

Definition at line 162 of file import-backend.c.

163 {
164  g_assert (info);
165  return info->selected_match_info.selected_manually;
166 }

◆ gnc_import_TransInfo_get_ref_id()

guint32 gnc_import_TransInfo_get_ref_id ( const GNCImportTransInfo *  info)

Returns the reference id for this TransInfo.

Definition at line 216 of file import-backend.c.

217 {
218  g_assert (info);
219  return info->ref_id;
220 }

◆ gnc_import_TransInfo_get_selected_match()

GNCImportMatchInfo * gnc_import_TransInfo_get_selected_match ( const GNCImportTransInfo *  info)

Returns the currently selected match in this TransInfo.

Definition at line 145 of file import-backend.c.

146 {
147  g_assert (info);
148  return info->selected_match_info.selected_match;
149 }

◆ gnc_import_TransInfo_get_trans()

Transaction * gnc_import_TransInfo_get_trans ( const GNCImportTransInfo *  info)

Returns the transaction of this TransInfo.

Definition at line 114 of file import-backend.c.

115 {
116  g_assert (info);
117  return info->trans;
118 }

◆ gnc_import_TransInfo_init_matches()

void gnc_import_TransInfo_init_matches ( GNCImportTransInfo *  trans_info,
GNCImportSettings *  settings 
)

Iterates through all splits of the originating account of trans_info. Sorts the resulting list and sets the selected_match and action fields in the trans_info.

Iterates through all splits of the originating account of trans_info. Sorts the resulting list and sets the selected_match and action fields in the trans_info.

Parameters
trans_infoThe TransInfo for which the matches should be found, sorted, and selected.
settingsThe structure that holds all the user preferences.

Definition at line 1183 of file import-backend.c.

1185 {
1186  GNCImportMatchInfo * best_match = NULL;
1187  g_assert (trans_info);
1188 
1189 
1190  /* Find all split matches in originating account. */
1191  gnc_import_find_split_matches(trans_info,
1195 
1196  if (trans_info->match_list != NULL)
1197  {
1198  trans_info->match_list = g_list_sort(trans_info->match_list,
1199  compare_probability);
1200  best_match = g_list_nth_data(trans_info->match_list, 0);
1202  best_match,
1203  FALSE);
1204  if (best_match != NULL &&
1205  best_match->probability >= gnc_import_Settings_get_clear_threshold(settings))
1206  {
1207  trans_info->action = GNCImport_CLEAR;
1208  }
1209  else if (best_match == NULL ||
1210  best_match->probability <= gnc_import_Settings_get_add_threshold(settings))
1211  {
1212  trans_info->action = GNCImport_ADD;
1213  }
1215  {
1216  trans_info->action = GNCImport_SKIP;
1217  }
1219  {
1220  trans_info->action = GNCImport_UPDATE;
1221  }
1222  else
1223  {
1224  trans_info->action = GNCImport_ADD;
1225  }
1226  }
1227  else
1228  {
1229  trans_info->action = GNCImport_ADD;
1230  }
1231  if (best_match &&
1232  trans_info->action == GNCImport_CLEAR &&
1234  {
1235  if (best_match->update_proposed)
1236  {
1237  trans_info->action = GNCImport_UPDATE;
1238  }
1239  }
1240 
1241  trans_info->previous_action = trans_info->action;
1242 }
gint gnc_import_Settings_get_match_date_hardlimit(const GNCImportSettings *s)
gint gnc_import_Settings_get_clear_threshold(GNCImportSettings *settings)
void gnc_import_TransInfo_set_selected_match_info(GNCImportTransInfo *info, GNCImportMatchInfo *match, gboolean selected_manually)
gint gnc_import_Settings_get_display_threshold(GNCImportSettings *settings)
double gnc_import_Settings_get_fuzzy_amount(GNCImportSettings *settings)
void gnc_import_find_split_matches(GNCImportTransInfo *trans_info, gint process_threshold, double fuzzy_amount_difference, gint match_date_hardlimit)
gboolean gnc_import_Settings_get_action_update_enabled(GNCImportSettings *settings)
gboolean gnc_import_Settings_get_action_skip_enabled(GNCImportSettings *settings)
gint gnc_import_Settings_get_add_threshold(GNCImportSettings *settings)

◆ gnc_import_TransInfo_is_balanced()

gboolean gnc_import_TransInfo_is_balanced ( const GNCImportTransInfo *  info)

Returns if the transaction stored in the TransInfo is currently balanced.

Definition at line 121 of file import-backend.c.

122 {
123  g_assert (info);
124  /* Assume that the importer won't create a transaction that involves two or more
125  currencies and no non-currency commodity. In that case can use the simpler
126  value imbalance check. */
128  {
129  return TRUE;
130  }
131  else
132  {
133  return FALSE;
134  }
135 }
Transaction * gnc_import_TransInfo_get_trans(const GNCImportTransInfo *info)
gboolean gnc_numeric_zero_p(gnc_numeric a)
Definition: gnc-numeric.c:173
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
Definition: Transaction.c:956

◆ gnc_import_TransInfo_new()

GNCImportTransInfo * gnc_import_TransInfo_new ( Transaction *  trans,
GncImportMatchMap *  matchmap 
)

Create a new object of GNCImportTransInfo here.

Allocates a new TransInfo object, with the Transaction 'trans' already stored in there. Also, this already checks the ImportMatchMap for automated destination account matching. The given MatchMap may be NULL, in which case the ImportMatchMap of the originating account will be used.

Parameters
transThe transaction that this TransInfo should work with.
matchmapMatchMap used for automated destination account choosing. This may be NULL, in which case the MatchMap of the originating account will be used.

Definition at line 1147 of file import-backend.c.

1148 {
1149  GNCImportTransInfo *transaction_info;
1150  Split *split;
1151  g_assert (trans);
1152 
1153  transaction_info = g_new0(GNCImportTransInfo, 1);
1154 
1155  transaction_info->trans = trans;
1156  /* Only use first split, the source split */
1157  split = xaccTransGetSplit(trans, 0);
1158  g_assert(split);
1159  transaction_info->first_split = split;
1160 
1161  /* Try to find a previously selected destination account
1162  string match for the ADD action */
1163  gnc_import_TransInfo_set_destacc (transaction_info,
1164  matchmap_find_destination (matchmap, transaction_info),
1165  FALSE);
1166  return transaction_info;
1167 }
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2126
void gnc_import_TransInfo_set_destacc(GNCImportTransInfo *info, Account *acc, gboolean selected_manually)

◆ gnc_import_TransInfo_refresh_destacc()

gboolean gnc_import_TransInfo_refresh_destacc ( GNCImportTransInfo *  transaction_info,
GncImportMatchMap *  matchmap 
)

Try to automatch a given transaction to a destination account

Definition at line 1248 of file import-backend.c.

1250 {
1251  Account *orig_destacc;
1252  Account *new_destacc = NULL;
1253  g_assert(transaction_info);
1254 
1255  orig_destacc = gnc_import_TransInfo_get_destacc(transaction_info);
1256 
1257  /* if we haven't manually selected a destination account for this transaction */
1258  if (gnc_import_TransInfo_get_destacc_selected_manually(transaction_info) == FALSE)
1259  {
1260  /* Try to find the destination account for this transaction based on prior ones */
1261  new_destacc = matchmap_find_destination(matchmap, transaction_info);
1262  gnc_import_TransInfo_set_destacc(transaction_info, new_destacc, FALSE);
1263  }
1264  else
1265  {
1266  new_destacc = orig_destacc;
1267  }
1268 
1269  /* account has changed */
1270  if (new_destacc != orig_destacc)
1271  {
1272  return TRUE;
1273  }
1274  else /* account is the same */
1275  {
1276  return FALSE;
1277  }
1278 }
void gnc_import_TransInfo_set_destacc(GNCImportTransInfo *info, Account *acc, gboolean selected_manually)
Account * gnc_import_TransInfo_get_destacc(const GNCImportTransInfo *info)
gboolean gnc_import_TransInfo_get_destacc_selected_manually(const GNCImportTransInfo *info)

◆ gnc_import_TransInfo_set_action()

void gnc_import_TransInfo_set_action ( GNCImportTransInfo *  info,
GNCImportAction  action 
)

Set the action for this TransInfo. Also sets the previous action.

Definition at line 176 of file import-backend.c.

178 {
179  g_assert (info);
180  if (action != info->action)
181  {
182  info->previous_action = info->action;
183  info->action = action;
184  }
185 }

◆ gnc_import_TransInfo_set_destacc()

void gnc_import_TransInfo_set_destacc ( GNCImportTransInfo *  info,
Account acc,
gboolean  selected_manually 
)

Set the 'other account' of this transaction (used for auto-balance if needed). May be set to NULL.

Parameters
selected_manuallyTRUE or FALSE; Was this account set as a result of a selection by the user or by an algorithm?

Definition at line 193 of file import-backend.c.

196 {
197  g_assert (info);
198  info->dest_acc = acc;
199  info->dest_acc_selected_manually = selected_manually;
200 
201  /* Store the mapping to the other account in the MatchMap. */
202  if (selected_manually)
203  {
204  matchmap_store_destination (NULL, info, FALSE);
205  }
206 }

◆ gnc_import_TransInfo_set_ref_id()

void gnc_import_TransInfo_set_ref_id ( GNCImportTransInfo *  info,
guint32  ref_id 
)

Set the reference id for this TransInfo.

Definition at line 223 of file import-backend.c.

225 {
226  g_assert (info);
227  info->ref_id = ref_id;
228 }

◆ gnc_import_TransInfo_set_selected_match_info()

void gnc_import_TransInfo_set_selected_match_info ( GNCImportTransInfo *  info,
GNCImportMatchInfo match,
gboolean  selected_manually 
)

Sets the currently selected match in this TransInfo.

Parameters
selected_manuallyTRUE or FALSE; Was this match set as a result of a selection by the user or by an algorithm?

Definition at line 152 of file import-backend.c.

155 {
156  g_assert (info);
157  info->selected_match_info.selected_match = match;
158  info->selected_match_info.selected_manually = selected_manually;
159 }

◆ on_matcher_help_clicked()

void on_matcher_help_clicked ( GtkButton *  button,
gpointer  user_data 
)

This allows for the transaction help dialog to be started from the assistant button callback.

Parameters
button.The button widget clicked on in the call back.
user_data.A pointer to a structure.

Definition at line 208 of file import-main-matcher.c.

209 {
210  GNCImportMainMatcher *info = user_data;
211  GtkBuilder *builder;
212  GtkWidget *help_dialog, *box;
213 
214  builder = gtk_builder_new();
215  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer2");
216  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer3");
217  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer4");
218  gnc_builder_add_from_file (builder, "dialog-import.glade", "textbuffer5");
219  gnc_builder_add_from_file (builder, "dialog-import.glade", "matcher_help");
220 
221  box = GTK_WIDGET(gtk_builder_get_object (builder, "red"));
222  gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_red);
223  box = GTK_WIDGET(gtk_builder_get_object (builder, "yellow"));
224  gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_yellow);
225  box = GTK_WIDGET(gtk_builder_get_object (builder, "green"));
226  gtk_widget_modify_bg(box, GTK_STATE_NORMAL, &info->color_back_green);
227 
228  help_dialog = GTK_WIDGET(gtk_builder_get_object (builder, "matcher_help"));
229  gtk_window_set_transient_for(GTK_WINDOW(help_dialog),
230  GTK_WINDOW(info->dialog));
231 
232  /* Connect the signals */
233  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, help_dialog);
234 
235  g_object_unref(G_OBJECT(builder));
236 
237  gtk_widget_show(help_dialog);
238 }