diff --git a/ChangeLog b/ChangeLog index 118a36af24..8c1d022dea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2001-02-14 Bill Gribble + + * src/scm/qif-import/*.scm: fuzzify account type rules a bit to + make imports more likely to match up with existing accounts. Fix + broken "New" detection. + + * src/gnome/druid-qif-import.c: add default acct based on file + name + + * src/gnome/dialog-account-picker.c: make sure picker gets + scrolled to initial selection. + 2001-02-14 Christian Stimming * src/scm/html-utilities.scm (gnc:html-build-acct-table): Add diff --git a/src/gnome/dialog-account-picker.c b/src/gnome/dialog-account-picker.c index 63a6d4d250..3db71fc062 100644 --- a/src/gnome/dialog-account-picker.c +++ b/src/gnome/dialog-account-picker.c @@ -118,7 +118,6 @@ build_acct_tree(QIFAccountPickerDialog * picker, QIFImportWindow * import) { int row = 0; gtk_clist_clear(GTK_CLIST(picker->treeview)); - gtk_clist_set_column_justification (GTK_CLIST(picker->treeview), 1, GTK_JUSTIFY_CENTER); @@ -217,8 +216,22 @@ gnc_ui_qif_account_picker_unselect_cb(GtkCTree * tree, wind->selected_name = NULL; } + +static int +gnc_ui_qif_account_picker_map_cb(GtkWidget * w, gpointer user_data) { + QIFAccountPickerDialog * wind = + gtk_object_get_data(GTK_OBJECT(user_data), + "account_picker_struct"); + + /* update the tree display with all the existing accounts plus all + * the ones the QIF importer thinks it will be creating. this will + * also select the map_entry line. */ + build_acct_tree(wind, wind->qif_wind); + return FALSE; +} + /**************************************************************** - * accountPickerBox + * qif_account_picker_dialog * select an account from the ones that the engine knows about, plus * the ones that will be created newly by the QIF import. this is * sort of like fileBox... it returns a string for the account name or @@ -259,11 +272,14 @@ qif_account_picker_dialog(QIFImportWindow * qif_wind, SCM map_entry) { GTK_SIGNAL_FUNC(gnc_ui_qif_account_picker_unselect_cb), wind->dialog); - /* update the tree display with all the existing accounts plus all - * the ones the QIF importer thinks it will be creating. this will - * also select the map_entry line. */ - build_acct_tree(wind, qif_wind); + gtk_signal_connect_after(GTK_OBJECT(wind->dialog), "map", + GTK_SIGNAL_FUNC(gnc_ui_qif_account_picker_map_cb), + wind->dialog); + /* this is to get the checkmarks set up right.. it will get called + * again after the window is mapped. */ + build_acct_tree(wind, wind->qif_wind); + retval = gnome_dialog_run_and_close(GNOME_DIALOG(wind->dialog)); scm_unprotect_object(wind->map_entry); @@ -277,3 +293,4 @@ qif_account_picker_dialog(QIFImportWindow * qif_wind, SCM map_entry) { return saved_entry; } } + diff --git a/src/gnome/druid-qif-import.c b/src/gnome/druid-qif-import.c index a206b80c64..931c51b5f6 100644 --- a/src/gnome/druid-qif-import.c +++ b/src/gnome/druid-qif-import.c @@ -489,7 +489,8 @@ gnc_ui_qif_import_load_file_next_cb(GnomeDruidPage * page, char * path_to_load; char * error_string = NULL; - + char * default_acctname = NULL; + GList * format_strings; GList * listit; @@ -499,6 +500,7 @@ gnc_ui_qif_import_load_file_next_cb(GnomeDruidPage * page, SCM qif_file_loaded = gh_eval_str("qif-dialog:qif-file-loaded?"); SCM unload_qif_file = gh_eval_str("qif-dialog:unload-qif-file"); SCM check_from_acct = gh_eval_str("qif-file:check-from-acct"); + SCM default_acct = gh_eval_str("qif-file:path-to-accountname"); SCM date_formats; SCM scm_filename; SCM scm_qiffile; @@ -660,6 +662,13 @@ gnc_ui_qif_import_load_file_next_cb(GnomeDruidPage * page, } else if(gh_call1(check_from_acct, gh_car(imported_files)) != SCM_BOOL_T) { /* skip to the "ask account name" page */ + default_acctname = gh_scm2newstr(gh_call1(default_acct, + gh_car(imported_files)), + NULL); + gtk_entry_set_text(GTK_ENTRY(wind->acct_entry), default_acctname); + + if(default_acctname) free(default_acctname); + gnome_druid_set_page(GNOME_DRUID(wind->druid), get_named_page(wind, "account_name_page")); return TRUE; @@ -864,7 +873,6 @@ gnc_ui_qif_import_default_acct_next_cb(GnomeDruidPage * page, else { scm_name = gh_str02scm(acct_name); gh_call2(fix_default, wind->selected_file, scm_name); - gtk_entry_set_text(GTK_ENTRY(wind->acct_entry), ""); return FALSE; } } @@ -1535,6 +1543,7 @@ gnc_ui_qif_import_comm_check_cb(GnomeDruidPage * page, gnome_druid_set_page(GNOME_DRUID(wind->druid), get_named_page(wind, "end_page")); } + return TRUE; } else { return FALSE; diff --git a/src/gnome/glade-gnc-dialogs.c b/src/gnome/glade-gnc-dialogs.c index 2152886d2d..0b67110681 100644 --- a/src/gnome/glade-gnc-dialogs.c +++ b/src/gnome/glade-gnc-dialogs.c @@ -3848,7 +3848,6 @@ create_QIF_Import_Druid (void) GdkColor memo_match_page_logo_bg_color = { 0, 65535, 65535, 65535 }; GdkColor memo_match_page_title_color = { 0, 65535, 65535, 65535 }; GtkWidget *druid_vbox40; - GtkWidget *label847713; GtkWidget *scrolledwindow25; GtkWidget *memo_page_list; GtkWidget *label847708; @@ -4376,13 +4375,6 @@ create_QIF_Import_Druid (void) gtk_widget_show (druid_vbox40); gtk_container_set_border_width (GTK_CONTAINER (druid_vbox40), 25); - label847713 = gtk_label_new (_("This doesn't actually affect the QIF import yet. \nGive it a couple more days :)")); - gtk_widget_ref (label847713); - gtk_object_set_data_full (GTK_OBJECT (QIF_Import_Druid), "label847713", label847713, - (GtkDestroyNotify) gtk_widget_unref); - gtk_widget_show (label847713); - gtk_box_pack_start (GTK_BOX (druid_vbox40), label847713, FALSE, FALSE, 0); - scrolledwindow25 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_ref (scrolledwindow25); gtk_object_set_data_full (GTK_OBJECT (QIF_Import_Druid), "scrolledwindow25", scrolledwindow25, diff --git a/src/gnome/gnc-dialogs.glade b/src/gnome/gnc-dialogs.glade index ce9be5da2f..8779ac04e5 100644 --- a/src/gnome/gnc-dialogs.glade +++ b/src/gnome/gnc-dialogs.glade @@ -6483,24 +6483,6 @@ files. True - - GtkLabel - label847713 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - - 0 - False - False - - - GtkScrolledWindow scrolledwindow25 diff --git a/src/scm/qif-import/qif-dialog-utils.scm b/src/scm/qif-import/qif-dialog-utils.scm index 6e9446e160..6d76511561 100644 --- a/src/scm/qif-import/qif-dialog-utils.scm +++ b/src/scm/qif-import/qif-dialog-utils.scm @@ -64,7 +64,7 @@ (for-each (lambda (acct) (if (string=? (qif-map-entry:gnc-name map-entry) - (car acct)) + (cadr acct)) (set! retval #t))) acct-list) retval)) @@ -78,18 +78,12 @@ (define (qif-dialog:make-account-display qif-files acct-hash gnc-acct-info) ;; first, clear the "display" flags in the acct-hash and set up the ;; new-file? flags. If there's nothing to show any more, don't. - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (qif-map-entry:set-display?! (cdr elt) #f) - (qif-map-entry:set-new-acct?! - (cdr elt) - (if (qif-import:gnc-account-exists (cdr elt) gnc-acct-info) - #f #t))) - bin)) - (vector->list acct-hash)) - + (hash-fold + (lambda (k v p) + (qif-map-entry:set-display?! v #f) + #f) + #f acct-hash) + (let ((retval '())) ;; we want to make two passes here. The first pass picks the ;; explicit Account descriptions out of each file. These are the @@ -99,12 +93,6 @@ ;; we'll have most of the accounts already located by that point. ;; Otherwise, we have to guess them. - ;; guess-acct returns a list that's - ;; (qif-name gnc-name gnc-type new-acct?) - ;; acct-hash hashes QIF account name to a list that's composed of - ;; (qif-acct-name gnc-acct-name gnc-acct-type gnc-acct-new? - ;; num-qif-xtns qif-object) so we can find the properties later. - ;; acct-hash hashes the qif name to a object. ;; guess-acct returns one. (for-each @@ -116,7 +104,7 @@ (if (not entry) (set! entry (qif-import:guess-acct (qif-acct:name acct) - (list (qif-acct:type acct)) + (qif-acct:type acct) gnc-acct-info))) (qif-map-entry:set-description! entry (qif-acct:description acct)) (hash-set! acct-hash (qif-acct:name acct) entry))) @@ -155,15 +143,15 @@ (set! qif-account (default-stock-acct from-acct stock-acct)) (set! qif-account-types (list GNC-STOCK-TYPE - GNC-MUTUAL-TYPE - GNC-ASSET-TYPE))) + GNC-MUTUAL-TYPE))) ((div cgshort cgmid cglong intinc miscinc miscexp margint rtrncap xin xout) (set! qif-account from-acct) (set! qif-account-types (list GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE))) ((divx cgshortx cgmidx cglongx intincx margintx rtrncapx) (set! qif-account @@ -172,7 +160,8 @@ (set! qif-account-types (list GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE))) ((miscincx miscexpx) (set! qif-account (qif-split:miscx-category @@ -180,7 +169,8 @@ (set! qif-account-types (list GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE)))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE)))) ;; now reference the near-end account (if qif-account @@ -198,7 +188,7 @@ ;; the far end will be the brokerage for buy, sell, ;; etc, or the "L"-referenced account for buyx, ;; sellx, etc, or an equity account for ShrsIn/ShrsOut - + ;; miscintx and miscexpx are very, very "special" ;; cases ... I'm not sure this is right. ;; the L line looks like : @@ -206,7 +196,7 @@ ;; so I assume near-acct is Account and far acct ;; is Category. This matches the intincx/divx ;; behavior. - + (set! qif-account #f) (case action ((buy sell) @@ -214,7 +204,8 @@ (set! qif-account-types (list GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE))) ((buyx sellx xin xout) (set! qif-account (qif-split:category @@ -222,19 +213,21 @@ (set! qif-account-types (list GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE))) ((stksplit) (set! qif-account (default-stock-acct from-acct stock-acct)) (set! qif-account-types (list GNC-STOCK-TYPE GNC-MUTUAL-TYPE - GNC-ASSET-TYPE))) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE))) ((cgshort cgshortx reinvsg reinvsh) (set! qif-account (default-cgshort-acct from-acct stock-acct)) (set! qif-account-types (list GNC-INCOME-TYPE))) - + ((cgmid cgmidx reinvmd) (set! qif-account (default-cgmid-acct from-acct stock-acct)) @@ -254,7 +247,7 @@ (set! qif-account (default-dividend-acct from-acct stock-acct)) (set! qif-account-types (list GNC-INCOME-TYPE))) - + ((rtrncap rtrncapx) (set! qif-account (default-capital-return-acct from-acct)) @@ -300,7 +293,7 @@ (list GNC-EXPENSE-TYPE) gnc-acct-info))) (qif-map-entry:set-display?! entry #t) - (hash-set! acct-hash qif-account entry)))) + (hash-set! acct-hash qif-account entry)))) ;; non-stock transactions. these are a bit easier. ;; the near-end account (from) is always in the @@ -314,7 +307,8 @@ GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE) gnc-acct-info))) (qif-map-entry:set-display?! entry #t) (hash-set! acct-hash from-acct entry) @@ -337,7 +331,8 @@ GNC-BANK-TYPE GNC-CCARD-TYPE GNC-CASH-TYPE - GNC-ASSET-TYPE) + GNC-ASSET-TYPE + GNC-LIABILITY-TYPE) gnc-acct-info))) (qif-map-entry:set-display?! entry #t) (hash-set! acct-hash xtn-acct entry))))) @@ -346,15 +341,15 @@ qif-files) ;; now that the hash table is filled, make the display list - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (if (qif-map-entry:display? (cdr elt)) - (set! retval - (cons (cdr elt) retval)))) - bin)) - (vector->list acct-hash)) + (hash-fold + (lambda (k v p) + (if (qif-map-entry:display? v) + (begin + (qif-map-entry:set-new-acct?! + v (not (qif-import:gnc-account-exists v gnc-acct-info))) + (set! retval (cons v retval)))) + #f) + #f acct-hash) ;; sort by number of transactions with that account so the ;; most important are at the top @@ -372,18 +367,12 @@ (define (qif-dialog:make-category-display qif-files cat-hash gnc-acct-info) ;; first, clear the "display" flags in the cat-hash. If there's ;; nothing to show any more, don't. - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (qif-map-entry:set-display?! (cdr elt) #f) - (qif-map-entry:set-new-acct?! - (cdr elt) - (if (qif-import:gnc-account-exists (cdr elt) gnc-acct-info) - #f #t))) - bin)) - (vector->list cat-hash)) - + (hash-fold + (lambda (k v p) + (qif-map-entry:set-display?! v #f) + #f) + #f cat-hash) + (let ((retval '()) (entry #f)) ;; get the Cat entries from each file @@ -437,15 +426,16 @@ qif-files) ;; now that the hash table is filled, make the display list - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (if (qif-map-entry:display? (cdr elt)) - (set! retval (cons (cdr elt) retval)))) - bin)) - (vector->list cat-hash)) - + (hash-fold + (lambda (k v p) + (if (qif-map-entry:display? v) + (begin + (qif-map-entry:set-new-acct?! + v (not (qif-import:gnc-account-exists v gnc-acct-info))) + (set! retval (cons v retval)))) + #f) + #f cat-hash) + ;; sort by qif account name (set! retval (sort retval (lambda (a b) @@ -453,24 +443,17 @@ (qif-map-entry:qif-name b))))) retval)) -;; UNFINISHED (and currently not connected to anything) ;; this one's like the other display builders, it just looks at the ;; payee and memo too. (define (qif-dialog:make-memo-display qif-files memo-hash gnc-acct-info) (let ((retval '())) ;; clear the display flags for existing items - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (qif-map-entry:set-new-acct?! - (cdr elt) - (if (qif-import:gnc-account-exists (cdr elt) gnc-acct-info) - #f #t)) - (qif-map-entry:set-display?! (cdr elt) #f)) - bin)) - (vector->list memo-hash)) + (hash-fold + (lambda (k v p) + (qif-map-entry:set-display?! v #f) + #f) + #f memo-hash) ;; iterate over every imported transaction. If there's no ;; category in the transaction, look at the payee to get a clue. @@ -506,14 +489,11 @@ (qif-map-entry:set-qif-name! entry key-string) (qif-map-entry:set-gnc-name! entry (default-unspec-acct)) - (qif-map-entry:set-new-acct?! - entry (if (qif-import:gnc-account-exists - entry gnc-acct-info) - #f #t)) (qif-map-entry:set-allowed-types! - entry (if (> (qif-split:amount split) 0) - (list GNC-INCOME-TYPE) - (list GNC-EXPENSE-TYPE))))) + entry + (if (> (qif-split:amount split) 0) + (list GNC-INCOME-TYPE GNC-EXPENSE-TYPE) + (list GNC-EXPENSE-TYPE GNC-INCOME-TYPE))))) (qif-map-entry:set-display?! entry #t) (hash-set! memo-hash key-string entry))))) splits))) @@ -521,14 +501,15 @@ qif-files) ;; build display list - (for-each - (lambda (bin) - (for-each - (lambda (elt) - (if (qif-map-entry:display? (cdr elt)) - (set! retval (cons (cdr elt) retval)))) - bin)) - (vector->list memo-hash)) + (hash-fold + (lambda (k v p) + (if (qif-map-entry:display? v) + (begin + (qif-map-entry:set-new-acct?! + v (not (qif-import:gnc-account-exists v gnc-acct-info))) + (set! retval (cons v retval)))) + #f) + #f memo-hash) ;; sort by qif memo/payee name (set! retval (sort retval @@ -546,7 +527,7 @@ (if (memq #t status) #t #f))) - + (define (qif-dialog:unload-qif-file oldfile list-of-files) (delq oldfile list-of-files)) @@ -629,7 +610,7 @@ (begin (display "stock-name #f.. name ==") (display name)(newline))) - + (if (not (hash-ref newhash stock-name)) (begin (set! names (cons stock-name names)) @@ -684,7 +665,7 @@ (set! newtree (cons (cvt-to-tree path new?) newtree)))))) (sort newtree (lambda (a b) (string 'qif-name)) diff --git a/src/scm/qif-import/qif-parse.scm b/src/scm/qif-import/qif-parse.scm index 4cf617f251..534318df4e 100644 --- a/src/scm/qif-import/qif-parse.scm +++ b/src/scm/qif-import/qif-parse.scm @@ -144,40 +144,27 @@ (string-remove-leading-space read-value))))) (cond ((string=? mangled-string "bank") - GNC-BANK-TYPE) + (list GNC-BANK-TYPE)) ((string=? mangled-string "port") - GNC-BANK-TYPE) + (list GNC-BANK-TYPE)) ((string=? mangled-string "cash") - GNC-CASH-TYPE) + (list GNC-CASH-TYPE)) ((string=? mangled-string "ccard") - GNC-CCARD-TYPE) + (list GNC-CCARD-TYPE)) ((string=? mangled-string "invst") ;; these are brokerage accounts. - GNC-BANK-TYPE) + (list GNC-BANK-TYPE)) ((string=? mangled-string "oth a") - GNC-ASSET-TYPE) + (list GNC-ASSET-TYPE GNC-BANK-TYPE GNC-CASH-TYPE GNC-STOCK-TYPE + GNC-MUTUAL-TYPE)) ((string=? mangled-string "oth l") - GNC-LIABILITY-TYPE) + (list GNC-LIABILITY-TYPE GNC-CCARD-TYPE)) ((string=? mangled-string "mutual") - GNC-MUTUAL-TYPE) + (list GNC-MUTUAL-TYPE GNC-STOCK-TYPE)) (#t (display "qif-parse:parse-acct-type : unhandled account type ") (display read-value) (display "... substituting Bank.") - GNC-BANK-TYPE)))) - -(define (qif-parse:state-to-account-type qstate) - (cond ((eq? qstate 'type:bank) - GNC-BANK-TYPE) - ((eq? qstate 'type:cash) - GNC-CASH-TYPE) - ((eq? qstate 'type:ccard) - GNC-CCARD-TYPE) - ((eq? qstate 'type:invst) ;; these are brokerage accounts in quicken - GNC-BANK-TYPE) - ((eq? qstate '#{type:oth\ a}#) - GNC-ASSET-TYPE) - ((eq? qstate '#{type:oth\ l}#) - GNC-LIABILITY-TYPE))) + (list GNC-BANK-TYPE))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; parse-bang-field : the bang fields switch the parse context for diff --git a/src/scm/qif-import/qif-to-gnc.scm b/src/scm/qif-import/qif-to-gnc.scm index 69fc6778ad..f1aabbcfee 100644 --- a/src/scm/qif-import/qif-to-gnc.scm +++ b/src/scm/qif-import/qif-to-gnc.scm @@ -29,7 +29,7 @@ (qif-map-entry:allowed-types acct-info)) (make-new-acct #f) (incompatible-acct #f)) - + (define (make-unique-name-variant long-name short-name) (if (gnc:get-account-from-full-name old-group long-name separator) (let loop ((count 2)) @@ -38,9 +38,9 @@ (if (gnc:get-account-from-full-name old-group test-name separator) (loop (+ 1 count)) - test-name))) + (string-append short-name (sprintf #f " %a" count))))) short-name)) - + ;; just because we found an account doesn't mean we can use it. ;; if the name is in use but the currency, security, or type are ;; incompatible, we need to create a new account with a modified @@ -52,7 +52,7 @@ (gnc:commodity-equiv? security (gnc:account-get-security same-gnc-account))) (list? allowed-types) - (memq (gnc:account-get-type same-gnc-account) + (memv (gnc:account-get-type same-gnc-account) allowed-types)) (begin ;; everything is ok, so we can just use the same @@ -83,7 +83,7 @@ (set! last-colon (string-rindex gnc-name separator)) (gnc:account-begin-edit new-acct) - + ;; if this is a copy of an existing gnc account, copy the ;; account properties. For incompatible existing accts, ;; we'll do something different later. @@ -114,7 +114,7 @@ (qif-map-entry:set-qif-name! pinfo parent-name) (qif-map-entry:set-gnc-name! pinfo parent-name) (qif-map-entry:set-allowed-types! - pinfo (qif-map-entry:allowed-types acct-info)) + pinfo (qif-map-entry:allowed-parent-types acct-info)) (set! parent-acct (qif-import:find-or-make-acct pinfo currency security @@ -244,7 +244,7 @@ (qif-import:get-account-name (qif-map-entry:qif-name acctinfo))))) (ok-types (qif-map-entry:allowed-types acctinfo)) - (equity? (memq GNC-EQUITY-TYPE ok-types))) + (equity? (memv GNC-EQUITY-TYPE ok-types))) (cond ((and equity? security) ;; a "retained holdings" acct (qif-import:find-or-make-acct acctinfo