*** empty log message ***

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2083 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-03-16 07:12:49 +00:00
parent fc7be297c9
commit ff62166bfa
42 changed files with 6746 additions and 103 deletions

View File

@ -291,6 +291,10 @@
<dd>for leap-year fix</dd>
<dt> <a href="mailto:grib@billgribble.com"> Bill Gribble</a></dt>
<dd>qif importation code</dd>
<dt> <a href="mailto:otto@bug.redhat.com"> Otto
Hammersmith</a></dt>

455
Docs/C/xacc-qif-import.html Normal file
View File

@ -0,0 +1,455 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Importing Quicken Data Into GnuCash</title>
<meta name="description" content=
"Importing Quicken data into GnuCash isn't the simplest thing in the world, but if you pay attention and have some patience you can get a very close approximation of what you want.">
<meta name="keywords" content=
"QIF, Quicken, importing">
</head>
<body bgcolor="#eeeeee">
<h1>Importing Quicken data into GnuCash</h1>
<h3>Bill Gribble &ltgrib@billgribble.com&gt</h3>
<a name="toc"><h2>Table of Contents</h2></a>
<ul>
<li> <a href="#overview">Overview
<li> <a href="#intro">Introduction to the QIF file</a>
<li> <a href="#how-to">How to use the Import QIF dialog</a>
<li> <a href="#dialog-files">The "Files" tab</a>
<li> <a href="#dialog-accounts">The "Accounts" and "Categories" tabs</a>
<li> <a href="#dialog-picker">The Account Picker dialog</a>
<li> <a href="#ok-button">The "OK" button
<li> <a href="#hints">Hints</a>
<ul><li> <a href="#opening-balance">Opening balances</a>
<li> <a href="#empty-category">Empty category</a>
<li> <a href="#dividend-category">Dividend category</a>
<li> <a href="#fund-families">Fund families</a>
<li> <a href="#brokerage-accounts">Brokerage accounts</a>
</ul>
</ul>
<a name="overview"><h2>Overview</h2></a>
<p>Quicken is one of the best-selling programs in the history of
the Universe. Pretty much everyone that has owned a PC or Mac since
the late 80's has had a copy of it lying around somewhere, and lots of
people actually use it to keep track of their finances. Why? Because
it works pretty well and Intuit has (to their credit) done a good job
of keeping up with what people want the program to do.
<p>They've done such a good job, in fact, that lots of Linux folks
keep a Windows partition on their machine just so they can run Quicken
and the latest shoot-em-up games. So of course we want to give you a
way to suck all your Quicken data into GnuCash and remove one more
barrier to putting a nice ext2 filesystem on that Windows partition.
<p>The problem is that GnuCash is a real double-entry accounting
system and Quicken has a pretty simplistic view about what an account
is, what a transaction is, and what to save in data files. In short,
QIF files just don't contain enough information to completely and
accurately reconstruct your Quicken account hierarchy in the GnuCash
double entry system without some guessing by the import code and some
handholding by you. QIF files omit small things that can be easily
guessed (for instance, are numbers in decimal-radix [1,000.00 == 1000]
form or European comma-radix form [1.000,00 == 1000]? Are dates m/d/y
or y/m/d?) and big things that can't be easily guessed, like, for
example, what currency the file is denominated in, or what account the
file describes.
<p>For the most part, GnuCash's QIF importer does a good job of
figuring this stuff out, but you do have to keep an eye on it. The
system is designed so that you can correct problems BEFORE you make
changes to your GnuCash accounts; nothing is done to your GnuCash
accounts until you click the final "OK" button.
<p>In the next section, I'll give an overview of the QIF file and
its "features". This may seem unnecessarily technical, but if you
will at least glance through it you will be much better able to
understand what's going on if you are having to jump through hoops to
make things work right, and how you might be able to jump right in and
edit the QIF file to fix really tough problems.
<p>There are two major "paths" for using the GnuCash QIF importer.
One is the "I am a Quicken user just migrating to GnuCash" path; the
other is the "I am downloading some updates from my bank as a QIF
file" path. This document mainly focuses on the former case, since
new users are likely to need the most help and you can't get started
using GnuCash until you can get your old records in.
<p><a href="#toc">Table of Contents</a>
<a name="intro"><h2>Introduction to the QIF file</h2></a>
<p>QIF files are plain text files formatted as "tag-value" pairs.
At the beginning of each line there is a single character "tag"
followed immedately by the "value", which extends to the end of the
line. Don't be afraid to pop up a QIF file in "less" or the text
editor of your choice if you are having problems getting some Quicken
data imported correctly; chances are a simple search-and-replace will
fix just about any problem you might have with a QIF file. And a
regexp search-and-replace will get the rest.
<p>Collections of tag-value pairs form records of various types.
There are records to store the names and descriptions of your accounts
and of expense and income categories that you have defined in Quicken.
There are records to define Quicken "classes" (sort of like
sub-accounts, sort of like categories, but not exactly like either).
And there are records to describe transactions.
<p>Here's a typical Quicken transaction record:
<pre>
!Type:Bank
D6/20/97
T-500
N1012
C*
M
P
L[Visa]
^
</pre>
<p>The ! tag denotes the start of a section of records of a
certain type. In this case, Bank transactions. Type:Cat means
a section of Category descriptions, Account means account
descriptions, and so on.
<p>The D tag denotes the date. Note y2k compliance "issue".
Here's a lovely "feature" of some version of Quicken and dates in
2000:
<pre>
D1/ 1' 0
T-640.00
CX
N511
PJoe Bob
LRent:Apartment
^
</pre>
<p>Ouch! Fortunately the GnuCash QIF importer can handle all of
the wacky date formats that the gnucash-devel list can find.
<p>The T field is the "Total" amount of the transaction. If there
are splits, the sum of all the split amounts is in a T field. Money
going out of the account is negative.
<p>The N field is a "Number", which is usually a check number or
some other identifying number for the transaction.
<p>The C field represents the clearing/reconciliation state of the
transaction. An x or X in this field means the transaction is
"Cleared", a * means the transaction is Reconciled.
<p>The M field is the transaction memo.
<p>The P field is the Payee.
<p>The L field is the Category/Account line. If the value in this
field is enclosed in square brackets, like [Visa], this transaction is
a transfer to the Quicken account named Visa. If there are no square
brackets, the transaction is in the named Category (like
Rent:Apartment).
<p>The ^ tag means End of Record.
<p>Quicken users taking advantage of Classes will see a slash (/)
character followed by the class name appended on the Category line
(like [Visa]/Project)
<p>If a transaction has "splits", meaning that it is a single
transaction with "this" account but is "split" into multiple
source/destination accounts, the splits are described with S fields
for the category/account/class of each split, an $ field for the
amount of the split, and an E field for a per-split memo. The total
of all the $ fields in a transaction record should equal the T field.
<p>Note that nowhere in the transaction record, nor anywhere
else in the file, does Quicken store the name of the account that the
file describes. Don't ask me, I don't know why either. Microsoft
Money (which also can save QIF files) started doing a "trick" to get
the information in the file. If the very first Bank transaction in
the file has a payee of "Opening Balance", the L line contains the
name of the account that the file describes:
<pre>
!Type:Bank
D12/03/95
T4,706.57
CX
POpening Balance
L[New Bank]
^
</pre>
<p>Opening Balance records are handled specially, since they don't
mean what they appear to mean (if you interpret the record literally,
as a transfer of $4706.57 from [New Bank] to [New Bank], your new
balance is a whopping $0.00). In the
<a href="#dialog-accounts">Accounts Tab</a> section there's a discussion
of what we do with them.
<p><a href="#toc">Table of Contents</a>
<a name="how-to"><h2>How to use the QIF Import dialog</h2></a>
<p>QIF files describe only one account, and try to be "complete"
in representing all the transactions involving that account. This is
fine if you only have one account, but if you have multiple Quicken
accounts and transfers between them, transactions will show up in
multiple files. This means that if you aren't smart about catching
duplicate transactions you will end up with wrong balances in GnuCash.
Definitely a bad thing.
<p>In order to get the best possible replication of your Quicken
account tree, export everything you can from Quicken and then import
it all in one session. The importer's
<a href="#dialog-files">Files tab</a> will allow you to load
as many QIF files as you want, and to make sure that the currency,
Quicken account name, and so on are right for each one. Then the
importer can do a really good job of catching cross-references and
marking them.
<p>The importer is written mostly in Guile, and it can be a little
slow on large QIF files. Load File takes 5-6 seconds for a QIF file
with 1000 or so transactions on my machine.
<p>Once you have loaded all the files into the importer, go to the
<a href="#dialog-accounts">Accounts tab</a>, and then to the
<a href="#dialog-categories">Categories tab</a>, and check that the
importer is going to put your Quicken transactions in the right place.
You can click to pop up a dialog and change the GnuCash destination
account name/type for any QIF account. Don't be afraid to change
these destination accounts; they are only guesses by the importer
based on the name and type of the QIF account. Mappings of Quicken
account to GnuCash account are written to a preferences file when you
click "OK", so if you import other Quicken files describing these same
accounts you won't have to correct the importer again.
<p>Make sure (especially in the Accounts tab) that the QIF account
names and transaction counts make sense to you. If you see that one
QIF account is mentioned by two different names, make sure that the
"QIF Account" for every file in the Files tab is what you meant it to
be. If the QIF Account for a file is wrong, the importer won't be
able to match up transfers correctly and your balances will be wrong.
If a QIF Account for a file is wrong, select the file in the Files tab,
unmark the "Auto" checkbox, and edit the text box to contain the right
name, then click "Load File" again. You will be asked to confirm a
reload of the file and then it will be done. Flip back to the
Accounts tab, see if that fixed the problem, repeat as necessary.
<p>When you are happy with the account mappings (double check
them, and make sure to save your GnuCash session first just to be
sure), then and only then click OK. If you click Cancel at any time,
your accounts will not be touched.
<p>Again, the importer is written mostly in Guile, and it can be a
little slow on large QIF files. It takes 3-4 seconds to stuff 1000
transactions into GnuCash on a Celeron 433, proportionately longer on
slower CPUs. You only have to do a large import like that a few
times, fortunately, so I'm not too worried about it.
<p><a href="#toc">Table of Contents</a>
<a name=dialog-files><h2>The "Files" Tab</h2>
<p>The first thing to do is load all your files. Click "Select
File", pick your file, then set the account, currency, radix, and date
fields, then click "Load File". The Currency field defaults to the
GnuCash default currency (set in the International tab of the
Preferences dialog). Try autodetecting radix, date format, and
account name first. The radix and date formats will stay on
"Autodetect" if the autodetector is not 100 percent sure of the right
answer; in that case, you will have to make a manual selection. You
probably know what the correct radix format is; if you're in the US or
the UK, it's definitely "decimal". Almost every QIF file I have seen
in the US is m/d/y for the date format, so try that if autodetect
doesn't work.
<p>To go back to a file that you have previously loaded, select
its name in the file list on the left. If you change settings for a
previously-loaded file, click "Load File" again to reload it with new
settings. Don't forget to turn off "Auto" on the QIF Account entry if
you manually enter it.
<p>If there's no Opening Balance record in the file, the account
name is guessed from the file name: any .qif extension is removed, and
all dashes and underscores are changed to spaces. If you want to save
yourself manually re-entering the name, save the file with a name that
will get guessed correctly (i.e. save the account "My Bank Account" as
My-Bank-Account.qif or My_Bank_Account.qif).
<p>GnuCash makes a hearty effort to interpret any QIF file that
you throw at it, but you need to make sure that it's a normal DOS or
Unix text file before trying to import. The Mac version of Quicken
saves files with Macintosh newline conventions, which really confuses
the Guile reader. Macintoshes use the carriage-return only (which
usually prints as ^M), and the Unix convention requires a line feed
(usually prints as ^J). You can use "tr" to fix this problem, or a
search and replace in your favorite text editor. With tr,
the command might look like
<pre>
cat macfile | tr 015 012 > unixfile
</pre>
<p><a href="#toc">Table of Contents</a>
<a name=dialog-accounts><h2>The "Accounts" and "Categories" Tabs</h2>
<p>Each line in the Accounts tab display represents a mapping from
a Quicken account to a GnuCash account. Similarly, the Categories tab
display shows mappings from Quicken categories to GnuCash
accounts. Only QIF accounts referenced by one or more transaction
records are displayed. The name of the GnuCash account is displayed
in "full name" format, including the names of all parent accounts
separated by your default separator character (generally ":").
<p>The first thing to check is the column of Quicken account
names. Make sure there are no duplicates with slightly-different
names. If a QIF transaction makes a transfer to [My Checking], and
you imported a file called my-checking.qif, you might have one account
entry for "my checking" and one for "My Checking". If these are the
same account, you need to go back to the Files tab and reload
my-checking.qif with the correct Quicken account name, My Checking.
<p>Once you have all the Quicken accounts making sense, check the
GnuCash account column. The default GnuCash account for a given
Quicken account is determined by a fallback procedure which makes the
best guess it can given the available information. The guesses that
are tried are (in order of preference):
<ul>
<li>Saved mappings from previous import sessions. Each time you
click "OK" in the import dialog, the mappings that you have selected
are saved for the next time you import files. At the moment, the file
is always called ~/.gnucash/qif-accounts-map. If you get some weird
default mappings (for instance, if you change an account name and the
importer wants to keep creating a new account with the old name) just
delete this file. It's on my wishlist to make this work a little
more smoothly.
<li>Similar accounts from your existing GnuCash account tree.
"Similar" means that the account types are compatible and the names
could reasonably be assumed to refer to the same thing. Full-path
exact name matches are preferred most, followed by case-insensitive
matches, followed by matches with prepended account parents (i.e.
QIF account Visa matches GnuCash account Credit Cards:Visa), followed
by various substring matches. If you think of a good heuristic
for this, let me know.
<li>New account. The name of the new account is currently just
the same as the name of the Quicken account; again, if you think of a
good heuristic to make this better let me know. I've thought about
making it look for subtrees to insert into (if all existing credit
card accounts are children of an account, make the new account a child
of that account, etc). On the wishlist.
</ul>
<p>Check both the name of the GnuCash account for each QIF account
and the type. If you are unhappy with either, click on the row in the
display containing the offensive mapping. You will see the
<a href="#dialog-picker">Account Picker</a> dialog which will allow you
to change it.
<p><a href="#toc">Table of Contents</a>
<a name=dialog-picker><h2>The Account Picker</h2>
<p>This account picker is sort of broken. The idea is that you
can select an existing account from the tree display, or enter
information for a new account in the boxes below. However, right now
it's possible to do Very Bad things like specify a subaccount of an
existing account with a type that's not compatible with the parent.
As soon as I figure out how I want this dialog to work I'll fix it. I
have tested out the worst things that you can do and nothing terrible
happens, except your account tree might be in a state that you could
never have created through the GUI (a Credit Card account as a child
of a Bank account, for example). Don't do that. I'll fix it Real
Soon.
<p><a href="#toc">Table of Contents</a>
<a name=ok-button><h2>The "OK" Button</h2></a>
<p>Everything really happens when you hit the "OK" button, so it
gets a section to itself.
<ul>
<li>First we do a "mark and sweep" to eliminate the duplicated
halves of transfers in the loaded Quicken transactions.
<li>A GnuCash account tree is created which mirrors
your existing tree and includes any new accounts added by your
Accounts and Categories mappings.
<li>All the QIF transactions are converted into GnuCash splits and
stuffed into the new account tree.
<li>Finally, the GnuCash engine is asked to merge the old account
tree with the new account tree.
</ul>
<p><a href="#toc">Table of Contents</a>
<a name="hints"><h2>A few hints</h2></a>
<a name="opening-balance"><h3>Opening Balance</h3></a>
<p>If your Quicken files have "Opening Balance" records, you will
see an account called "Opening Balance" in the Accounts tab.
Accounting for the source of opening balances is sort of a hassle,
when you think about it, because they come from accounts that are
outside the scope of the GnuCash universe. The suggestion I've seen
on the gnucash-devel list is to make Opening Balances point to a
GnuCash account called "Retained Earnings", of type Equity. I don't
exactly understand this but it seems reasonable, and it's the default
for accounts called "Opening Balance".
<a name="empty-category"><h3>Empty category</h3></a>
<p>In the Categories display, you may notice a blank QIF Category
entry. Quicken transactions are not required to have a Category, but
GnuCash transactions are required to have a source and a destination.
The blank category lets you select which GnuCash account all
uncategorized transactions go to. This will generally be
miscellaneous checks you have written, cash withdrawals, and so on, so
you probably want to put these in a "Misc Expenses" account or
something similar. It may make sense to put this in an equity
account; let me know if there's a good explanation for how it should
be.
<a name="dividend-category"><h3>Dividend category</h3></a>
<p>Quicken stock transactions have a recognizable pattern for
dividend payments. If the importer can definitely tell that a
transaction is a transfer from dividends then it will default to
creating a "Dividend" income account. This category is usually not
present in the Quicken file, so it's being manufactured out of
nowhere.
<a name="fund-families"><h3>Fund families</h3></a>
<p>Quicken has the abstraction of a single account representing a
"fund family" for the purpose of allowing smooth transfers between the
various accounts administered within the family. The GnuCash Importer
will ALWAYS get this wrong the first time, because Quicken explicitly
puts the wrong information in the file. The "blanket" account
representing the fund family as a whole should probably be a Bank
account, since the transfers to and from it in the Quicken file are
denominated in currency, not shares. The balance of such an account
is supposed to always be 0 since you just use it as an intermediary
between two accounts in the family. Hopefully I'll fix this at some
point if someone tells me how it's supposed to work.
<a name="brokerage-accounts"><h3>Brokerage accounts</h3></a>
<p>Brokerage accounts are really confusing to me. Basically, my
thinking is that the brokerage account itself should probably be a
Bank account. The only wierdness is in stuff like dividends paid from
securities to the brokerage account. If you're using a Dividend
account, you can lose the information about where the dividend came
from. The importer tries to save this information by putting the
security name in the Payee slot (which shows up in the GnuCash
Description field for the transaction). If you have a better idea,
let me know.
</body>
</html>

1
README
View File

@ -549,6 +549,7 @@ Bob Drzyzgula <bob@mostly.com> for budgeting design notes
Jan-Uwe Finck <ju_finck@mail.netwave.de> for German message translation
Ron Forrester <rjf@aracnet.com> for gnome patches
Dave Freese <DFreese@osc.uscg.mil> for leap-year fix
Bill Gribble <grib@billgribble.com> qif importation code
Otto Hammersmith <otto@bug.redhat.com> for RedHat RPM version
Alexandru Harsanyi <haral@codec.ro> for core dumps, lockups, gtk work.
Jon K}re Hellan <jk@isdn-a33.itea.ntnu.no> misc core dump fixes

110
po/fr.po
View File

@ -4,9 +4,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: gnucash 1.2.0\n"
"Project-Id-Version: gnucash 1.3.0\n"
"POT-Creation-Date: 2000-03-15 03:12-0800\n"
"PO-Revision-Date: 2000-03-06 23:47+0200\n"
"PO-Revision-Date: 2000-03-15 23:47+0200\n"
"Last-Translator: Yannick LE NY <y-le-ny@ifrance.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@ -27,7 +27,7 @@ msgstr "Fonds communs(SICAV / FCP)"
#: ../po/guile_strings.txt:4
msgid "Status"
msgstr ""
msgstr "Etats"
#: ../po/guile_strings.txt:5 messages-i18n.c:259
msgid "Date"
@ -35,7 +35,7 @@ msgstr "Date"
#: ../po/guile_strings.txt:6 messages-i18n.c:274
msgid "Equity"
msgstr "Capitaux propres(Actif)"
msgstr "Capitaux propres"
#: ../po/guile_strings.txt:7
msgid "Account Separator"
@ -46,7 +46,7 @@ msgid ""
"The default background color for splits in multi-line mode and the auto modes"
msgstr ""
"La couleur de l'arrière-plan par défaut pour les répartitions en mode lignes "
"multiet les modes auto"
"multi et les modes auto"
#: ../po/guile_strings.txt:9
msgid "Auto-Raise Lists"
@ -71,7 +71,7 @@ msgstr "Le bon"
#: ../po/guile_strings.txt:14
#, c-format
msgid "The current time is %s."
msgstr ""
msgstr "L'heure actuelle est %s."
#: ../po/guile_strings.txt:15 messages-i18n.c:170
msgid "Double Line"
@ -88,14 +88,13 @@ msgstr "Revenus:Salaire:Imposable"
#: ../po/guile_strings.txt:18
msgid "Type of budget report"
msgstr ""
msgstr "Type de rapport de budget"
#: ../po/guile_strings.txt:19
msgid "reg_win_width"
msgstr ""
#: ../po/guile_strings.txt:20
#, fuzzy
msgid "Balancing"
msgstr "Solde"
@ -136,12 +135,11 @@ msgid "_Account Transactions"
msgstr "Transactions du compte"
#: ../po/guile_strings.txt:29
#, fuzzy, c-format
#, c-format
msgid "The date option is %s."
msgstr "C'est une option de date"
msgstr "L'option de date est %s."
#: ../po/guile_strings.txt:30
#, fuzzy
msgid "Account Transactions"
msgstr "Transactions du compte"
@ -199,7 +197,7 @@ msgstr "Ligne multiple"
#: ../po/guile_strings.txt:44
msgid "View"
msgstr ""
msgstr "Vue"
#: ../po/guile_strings.txt:45
msgid "The default background color for odd rows in double mode"
@ -208,14 +206,12 @@ msgstr ""
"double"
#: ../po/guile_strings.txt:46
#, fuzzy
msgid "UK-style dd/mm/yyyy"
msgstr "Style-UK: jj/mm/aaaa"
#: ../po/guile_strings.txt:47
#, fuzzy
msgid "Show all columns"
msgstr "Montre toutes les transactions"
msgstr "Montre toutes les colonnes"
#: ../po/guile_strings.txt:48 messages-i18n.c:229
msgid "Account"
@ -272,14 +268,12 @@ msgid "Income/Salary/Taxable"
msgstr "Revenus/Salaire/Imposable"
#: ../po/guile_strings.txt:61
#, fuzzy
msgid "There are no selected accounts in the account list option."
msgstr "Ouvrir le compte sélectionné et tous ses sous-comptes."
msgstr "Il n'y a aucun comptes selectionnés dans la liste d'options du compte."
#: ../po/guile_strings.txt:62
#, fuzzy
msgid "_Budget"
msgstr "Acheté"
msgstr "Budget"
#: ../po/guile_strings.txt:63
msgid "Continental Europe: dd.mm.yyyy"
@ -310,9 +304,9 @@ msgid "Register Colors"
msgstr "Couleurs du registre"
#: ../po/guile_strings.txt:70
#, fuzzy, c-format
#, c-format
msgid "The boolean option is %s."
msgstr "C'est une option booléenne"
msgstr "L'option boléenne est %s."
#: ../po/guile_strings.txt:71
msgid "Multi mode default transaction background"
@ -323,8 +317,8 @@ msgid ""
"Double clicking on an account with children expands the account instead of "
"opening a register."
msgstr ""
"Double cliquez sur un compte avec des enfants développe le compte à la "
"placede l'ouverture d'un registre."
"Double cliquer sur un compte avec des enfants développe le compte à la "
"place de l'ouverture d'un registre."
#: ../po/guile_strings.txt:73
msgid "The background color for the active transaction in single mode"
@ -383,9 +377,8 @@ msgid "Average"
msgstr "Moyenne"
#: ../po/guile_strings.txt:86
#, fuzzy
msgid "The items selected in the list option are:"
msgstr "C'est une option de liste de compte"
msgstr "Les éléments sélectionnés dans la liste d'options sont:"
#: ../po/guile_strings.txt:87
msgid "A_ccount Balance Tracker"
@ -405,7 +398,7 @@ msgstr ""
#: ../po/guile_strings.txt:91
msgid "Full"
msgstr ""
msgstr "Plein"
#: ../po/guile_strings.txt:92
msgid "Multi mode default split background"
@ -445,7 +438,7 @@ msgstr ""
#: ../po/guile_strings.txt:101
msgid "A report useful for balancing the budget"
msgstr ""
msgstr "Un rapport utile pour équilibrer le budget"
#: ../po/guile_strings.txt:102
msgid "Date Format Display"
@ -464,7 +457,6 @@ msgid "Account fields to display"
msgstr "Champs du compte à afficher"
#: ../po/guile_strings.txt:106
#, fuzzy
msgid "Account Balance Tracker"
msgstr "Suivi du solde du compte"
@ -511,7 +503,7 @@ msgid ""
"The default background color for transactions in multi-line mode and the "
"auto modes"
msgstr ""
"La couleur de l'arrière-plan par défaut pour les transactionsen mode ligne "
"La couleur de l'arrière-plan par défaut pour les transactions en mode ligne "
"multi et les modes auto"
#: ../po/guile_strings.txt:117
@ -528,7 +520,7 @@ msgstr "Option laide"
#: ../po/guile_strings.txt:120
msgid "How are you doing on your budget?"
msgstr ""
msgstr "Comment aller vous faire votre budget?"
#: ../po/guile_strings.txt:121
msgid "Save Translatable Strings"
@ -560,7 +552,7 @@ msgstr "Format de date"
#: ../po/guile_strings.txt:128
msgid "A list option"
msgstr "Une option de liste"
msgstr "Une liste d'option"
#: ../po/guile_strings.txt:129
msgid "ISO Standard: yyyy-mm-dd"
@ -583,9 +575,9 @@ msgid "Double mode default even row background"
msgstr "Arrière-plan des lignes paires en mode double par défaut"
#: ../po/guile_strings.txt:134
#, fuzzy, c-format
#, c-format
msgid "The multi-choice option is %s."
msgstr "C'est une option à choix multiple"
msgstr "L'option à choix multiple est %s."
#: ../po/guile_strings.txt:135
msgid "Double mode colors alternate with transactions"
@ -610,7 +602,7 @@ msgstr "Sous-comptes"
#: ../po/guile_strings.txt:140
#, c-format
msgid "The date and time option is %s."
msgstr ""
msgstr "L'option de date et d'heure est %s."
#: ../po/guile_strings.txt:141 messages-i18n.c:290
msgid "Liability"
@ -658,9 +650,9 @@ msgid "Notes"
msgstr "Notes"
#: ../po/guile_strings.txt:152
#, fuzzy, c-format
#, c-format
msgid "The string option is %s."
msgstr "C'est une option de chaine"
msgstr "L'option de chaine est %s."
#: ../po/guile_strings.txt:153
msgid "_Reports"
@ -712,7 +704,7 @@ msgstr "Deux semaines"
#: ../po/guile_strings.txt:165
msgid "Save Window Geometry"
msgstr "Sauvegarger la géométrie de la fenêtre"
msgstr "Sauvegarder la géométrie de la fenêtre"
#: ../po/guile_strings.txt:166
msgid "Income\\Salary\\Taxable"
@ -723,7 +715,6 @@ msgid "Code"
msgstr "Code"
#: ../po/guile_strings.txt:168
#, fuzzy
msgid "Balance sheet"
msgstr "Feuille du solde/bilan"
@ -749,7 +740,7 @@ msgstr "Trier par ce second crit
#: ../po/guile_strings.txt:174
msgid "true"
msgstr ""
msgstr "vrai"
#: ../po/guile_strings.txt:175
msgid "Income.Salary.Taxable"
@ -792,9 +783,8 @@ msgid "Just a Date Option"
msgstr "Uniquement une option de date"
#: ../po/guile_strings.txt:185
#, fuzzy
msgid "The accounts selected in the account list option are:"
msgstr "C'est une option de liste de compte"
msgstr "Les comptes sélectionnés dans la liste d'options du compte sont:"
#: ../po/guile_strings.txt:186
#, c-format
@ -802,6 +792,8 @@ msgid ""
"This is a sample GnuCash report. See the guile (scheme) source code in %s "
"for details on writing your own reports, or extending existing reports."
msgstr ""
"C'est un exemple de rapport de Gnucash. Regardez le code source de Guile (scheme) dans %s"
"pour les détails sur l'écriture de vos propres rapports, ou étendez les rapports existants."
#: ../po/guile_strings.txt:187
msgid "The default background color for even rows in single mode"
@ -814,7 +806,6 @@ msgstr ""
"La couleur de l'arrière-plan par défaut pour les lignes paires en mode double"
#: ../po/guile_strings.txt:189
#, fuzzy
msgid "Display the Budget report."
msgstr "Affiche le rapport de la feuille du solde/bilan"
@ -851,9 +842,8 @@ msgid "Plot Type"
msgstr "Type de graphique"
#: ../po/guile_strings.txt:197
#, fuzzy
msgid "Budget"
msgstr "Acheté"
msgstr "Budget"
#: ../po/guile_strings.txt:198
msgid "Choose whether to display icons, text, or both for toolbar buttons"
@ -911,9 +901,8 @@ msgid "Default number of register rows to display."
msgstr "Nombre de lignes du registre par défaut à afficher"
#: ../po/guile_strings.txt:211
#, fuzzy
msgid "Report end date"
msgstr "Trier par date"
msgstr "Date de fin du rapport"
#: ../po/guile_strings.txt:212
msgid "None"
@ -948,9 +937,8 @@ msgid "__gui"
msgstr ""
#: ../po/guile_strings.txt:220
#, fuzzy
msgid "Report start date"
msgstr "Eléments de rapports depuis cette date"
msgstr "Date de départ du rapport"
#: ../po/guile_strings.txt:221 messages-i18n.c:334
msgid "To"
@ -1022,12 +1010,11 @@ msgstr "Rien"
#: ../po/guile_strings.txt:238
msgid "You have selected no values in the list option."
msgstr ""
msgstr "Vous n'avez sélectionné aucune valeurs dans la liste d'option."
#: ../po/guile_strings.txt:239
#, fuzzy
msgid "false"
msgstr "Fermer"
msgstr "faux"
#: ../po/guile_strings.txt:240 messages-i18n.c:276
msgid "Expense"
@ -1067,7 +1054,7 @@ msgstr "Affiche le rapport des transactions du compte."
#: ../po/guile_strings.txt:249
msgid "Have a nice day!"
msgstr ""
msgstr "Ayez une bonne journée!"
#: ../po/guile_strings.txt:250
msgid "This is a list option"
@ -1096,14 +1083,17 @@ msgid ""
"report, consult the mailing list %s. For details on subscribing to that "
"list, see %s."
msgstr ""
"Pour l'aide sur l'écriture de rapports,ou pour contribuer à notre flambant neuf,"
"totallement cool rapport, consultez la liste de courriers %s. Pour les détails "
"sur l'inscription à cette liste, regardez %s."
#: ../po/guile_strings.txt:256
msgid ""
"The background color for an active transaction in multi-line mode and the "
"auto modes"
msgstr ""
"L'arrière-plan en couleur pour une répartition active en mode multiet modes "
"auto"
"L'arrière-plan en couleur pour une répartition active en mode multi lignes"
"et en modes auto"
#: ../po/guile_strings.txt:257
msgid "This is a multi choice option."
@ -1114,7 +1104,6 @@ msgid "Income & Expense"
msgstr "Revenus et dépenses"
#: ../po/guile_strings.txt:259
#, fuzzy
msgid "Hello, World"
msgstr "Bonjour, tout le monde!"
@ -1560,9 +1549,8 @@ msgid "Delete the current transaction"
msgstr "Supprimer la transaction en cours"
#: messages-i18n.c:74
#, fuzzy
msgid "Make a copy of the current transaction"
msgstr "Enregistrer la transaction en cours"
msgstr "Faire une copie de la transaction actuelle"
#: messages-i18n.c:75
msgid "Edit the selected account"
@ -1795,9 +1783,8 @@ msgid "_Delete"
msgstr "Supprimer"
#: messages-i18n.c:132
#, fuzzy
msgid "D_uplicate"
msgstr "Date"
msgstr "Dupliquer"
#: messages-i18n.c:133
msgid "_Edit"
@ -2281,7 +2268,7 @@ msgstr "Diff
#: messages-i18n.c:269
msgid "Direct Debit"
msgstr ""
msgstr "Débit direct"
#: messages-i18n.c:270
msgid "Dist"
@ -2292,9 +2279,8 @@ msgid "Div"
msgstr "Div"
#: messages-i18n.c:272
#, fuzzy
msgid "Duplicate"
msgstr "Date"
msgstr "Dupliquer"
#: messages-i18n.c:273
msgid "Edit"

View File

@ -299,41 +299,8 @@ gncFileOpenFile (const char * newfile)
void
gncFileQIFImport (void)
{
char * newfile;
char buf[BUFSIZE];
int io_error, uh_oh = 0;
AccountGroup *newgrp;
newfile = fileBox(IMPORT_QIF_STR, "*.qif");
if (!newfile) return;
gnc_set_busy_cursor(NULL);
/* load the accounts from the file the user specified */
newgrp = xaccReadQIFAccountGroup (newfile);
gnc_unset_busy_cursor(NULL);
/* check for i/o error, put up appropriate error message */
io_error = xaccGetQIFIOError();
SHOW_IO_ERR_MSG(io_error);
if (uh_oh) return;
if( NULL == topgroup ) {
/* no topgroup exists */
topgroup = xaccMallocAccountGroup();
}
gnc_set_busy_cursor(NULL);
/* since quicken will not export all accounts
* into one file, we must merge them in one by one */
xaccConcatGroups (topgroup, newgrp);
xaccMergeAccounts (topgroup);
xaccConsolidateGrpTransactions (topgroup);
gnc_unset_busy_cursor(NULL);
/* pop up the QIF File Import dialog box */
gnc_ui_qif_import_dialog_make(NULL);
}
/* ======================================================== */

View File

@ -2,3 +2,4 @@ Makefile
tmp
obj
*.diff
backup.glade

View File

@ -34,7 +34,7 @@ INCLPATH := -I.. \
-I@top_srcdir@/lib/g-wrap-install/include \
-I@top_srcdir@/src/g-wrap \
-I${includedir} \
-I@top_srcdir@/src/register/gnome
-I@top_srcdir@/src/register/gnome
# All the other GNOME CFLAGS are handled in Makefile.common now
CFLAGS = @CFLAGS@ ${INCLPATH}
@ -69,7 +69,9 @@ GNOME_SRCS := top-level.c window-main.c window-register.c window-adjust.c \
dialog-options.c dialog-filebox.c dialog-transfer.c \
dialog-add.c dialog-edit.c dialog-utils.c \
extensions.c query-user.c reconcile-list.c \
window-report.c global-options.c
window-report.c global-options.c \
dialog-qif-import.c glade-qif-import.c \
dialog-account-picker.c glade-account-picker.c
######################################################################
all: gnome
@ -85,3 +87,6 @@ gnome: @top_srcdir@/gnucash.gnome
gnome.static: @top_srcdir@/gnucash.gnome.static
@top_srcdir@/gnucash.gnome.static: ${GNOME_OBJS} ${OTHER_OBJS}
$(CC) -static $(LDFLAGS) -o $@ $^ $(LIBS)

View File

@ -4,6 +4,7 @@
* GnuCash. *
* Copyright (C) 1998,1999 Jeremy Collins *
* Copyright (C) 1998,1999 Linas Vepstas *
* Copyright (C) 2000 Dave Peticolas <peticola@cs.ucdavis.edu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *

View File

@ -1,6 +1,7 @@
/*******************************************************************\
* account-tree.h -- GNOME account tree functions *
* Copyright (C) 1998,1999 Linas Vepstas *
* Copyright (C) 2000 Dave Peticolas <peticola@cs.ucdavis.edu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *

View File

@ -1,6 +1,7 @@
/********************************************************************\
* account-treeP.h -- private GNOME account tree functions *
* Copyright (C) 1998,1999 Linas Vepstas *
* Copyright (C) 2000 Dave Peticolas <peticola@cs.ucdavis.edu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *

View File

@ -0,0 +1,271 @@
/********************************************************************\
* dialog-account-picker.c -- window for picking a Gnucash account *
* (GnuCash) *
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
\********************************************************************/
#include "top-level.h"
#include <gnome.h>
#include <stdio.h>
#include "glade-account-picker.h"
#include "glade-cb-account-picker.h"
#include <guile/gh.h>
#include "FileDialog.h"
#include "Group.h"
#include "Account.h"
#include "dialog-utils.h"
#include "query-user.h"
#include "util.h"
static void
build_acct_tree(AccountGroup * group, GtkWidget * tree, GtkWidget * picker) {
Account ** accts;
AccountGroup * children;
GtkWidget * tree_item;
GtkWidget * sub_tree;
int num_accts;
int i;
accts = xaccGetAccounts(group);
num_accts = xaccGetNumAccounts(group);
for(i = 0; i < num_accts; i++) {
if(group == xaccAccountGetParent(accts[i])) {
tree_item =
gtk_tree_item_new_with_label(xaccAccountGetName(accts[i]));
gtk_object_set_data(GTK_OBJECT(tree_item),
"acct_name",
xaccAccountGetFullName(accts[i], ':'));
gtk_tree_append(GTK_TREE(tree), tree_item);
children = xaccAccountGetChildren(accts[i]);
if(children && (xaccGetNumAccounts(children) > 0)) {
sub_tree = gtk_tree_new();
gtk_signal_connect(GTK_OBJECT(sub_tree), "select_child",
GTK_SIGNAL_FUNC(gnc_ui_account_picker_select_cb),
picker);
build_acct_tree(children, sub_tree, picker);
gtk_tree_item_set_subtree(GTK_TREE_ITEM(tree_item),
sub_tree);
}
gtk_widget_show(tree_item);
}
}
}
/****************************************************************\
* accountPickerBox
* select an account from the ones that the engine knows about.
* this is sort of like fileBox... it returns a string for the
* account name or NULL on cancel. It's modal.
\****************************************************************/
SCM
accountPickerBox(char * initial_selection, int initial_type) {
AccountGroup * topgroup;
Account * selected;
int i;
GtkWidget * picker = create_GNUcash_Account_Picker();
GtkWidget * treeview = gtk_object_get_data(GTK_OBJECT(picker),
"account_tree");
GtkWidget * entry = gtk_object_get_data(GTK_OBJECT(picker),
"acct_entry");
GtkWidget * descript = gtk_object_get_data(GTK_OBJECT(picker),
"acct_description_entry");
GtkWidget * type_pick = gtk_object_get_data(GTK_OBJECT(picker),
"acct_type_picker");
GtkWidget * treeitem = gtk_tree_item_new_with_label("All Accounts");
GtkWidget * subtree = gtk_tree_new();
char * selected_account = NULL;
SCM infolist;
GtkWidget * active, * menu;
gtk_object_set_data(GTK_OBJECT(picker), "string_return",
&selected_account);
gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
GTK_SIGNAL_FUNC(gnc_ui_account_picker_select_cb),
picker);
/* do some setup */
topgroup = gncGetCurrentGroup();
gtk_tree_append(GTK_TREE(treeview), treeitem);
gtk_widget_show(treeitem);
build_acct_tree(topgroup, subtree, picker);
gtk_tree_item_set_subtree(GTK_TREE_ITEM(treeitem), subtree);
gtk_tree_set_view_lines(GTK_TREE(treeview), TRUE);
gtk_tree_item_expand(GTK_TREE_ITEM(treeitem));
/* this is a pain in the butt but there's no other way to easily
* find out the index of the optionmeny selection */
menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(type_pick));
for(i = 0; i < 11; i++) {
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick), i);
active = gtk_menu_get_active(GTK_MENU(menu));
gtk_object_set_data(GTK_OBJECT(active),
"option_index",
(gpointer)(i));
}
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick), 0);
if(initial_selection) {
printf("setting up initial selection..\n");
selected = xaccGetAccountFromFullName(topgroup, initial_selection, ':');
gtk_entry_set_text(GTK_ENTRY(entry), initial_selection);
if(selected) {
if(xaccAccountGetDescription(selected)) {
gtk_entry_set_text(GTK_ENTRY(descript),
xaccAccountGetDescription(selected));
}
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick),
xaccAccountGetType(selected));
infolist = SCM_LIST3(gh_str02scm(selected_account),
gh_int2scm(xaccAccountGetType(selected)),
gh_str02scm(xaccAccountGetDescription(selected)));
}
else {
gtk_entry_set_text(GTK_ENTRY(descript), "");
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick),
initial_type);
infolist = SCM_LIST3(gh_str02scm(selected_account),
gh_int2scm(initial_type),
gh_str02scm(""));
}
scm_protect_object(infolist);
gtk_object_set_data(GTK_OBJECT(picker),
"scm_acct_info", (gpointer)infolist);
}
/* make sure the window is modal, then wait on it */
gtk_window_set_modal(GTK_WINDOW(picker), TRUE);
gtk_widget_show(GTK_WIDGET(treeview));
gtk_widget_show(GTK_WIDGET(picker));
gtk_main();
infolist = (SCM)gtk_object_get_data(GTK_OBJECT(picker),
"scm_acct_info");
/* murder it */
gtk_widget_destroy(picker);
return infolist;
}
void
gnc_ui_account_picker_select_cb(GtkTree * tree,
GtkWidget * widget,
gpointer user_data) {
AccountGroup * topgroup = gncGetCurrentGroup();
Account * gnc_acct;
GtkWidget * acct_entry = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_entry");
GtkWidget * descript = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_description_entry");
GtkWidget * type_pick = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_type_picker");
char * selected_acct;
char * description;
int acct_type;
SCM infolist;
printf("in select cb\n");
selected_acct = gtk_object_get_data(GTK_OBJECT(widget), "acct_name");
gnc_acct = xaccGetAccountFromFullName(topgroup, selected_acct,
':');
gtk_entry_set_text(GTK_ENTRY(acct_entry), selected_acct);
description = xaccAccountGetDescription(gnc_acct);
acct_type = xaccAccountGetType(gnc_acct);
gtk_entry_set_text(GTK_ENTRY(descript),
description);
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick),
acct_type);
infolist = SCM_LIST3(gh_str02scm(selected_acct),
gh_int2scm(acct_type),
gh_str02scm(description));
scm_protect_object(infolist);
gtk_object_set_data(GTK_OBJECT(user_data),
"scm_acct_info", (gpointer)infolist);
printf("leaving select cb\n");
}
void
gnc_ui_account_picker_ok_cb(GtkButton *button,
gpointer user_data) {
GtkWidget * acct_entry = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_entry");
GtkWidget * descript = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_description_entry");
GtkWidget * type_pick = gtk_object_get_data(GTK_OBJECT(user_data),
"acct_type_picker");
GtkWidget * type_menu;
GtkWidget * menuitem;
char * selected_acct;
char * description;
int acct_type;
SCM infolist;
selected_acct = gtk_entry_get_text(GTK_ENTRY(acct_entry));
description = gtk_entry_get_text(GTK_ENTRY(descript));
type_menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(type_pick));
menuitem = gtk_menu_get_active(GTK_MENU(type_menu));
acct_type = (int)(gtk_object_get_data(GTK_OBJECT(menuitem),
"option_index"));
gtk_entry_set_text(GTK_ENTRY(descript),
description);
gtk_option_menu_set_history(GTK_OPTION_MENU(type_pick),
acct_type);
infolist = SCM_LIST3(gh_str02scm(selected_acct),
gh_int2scm(acct_type),
gh_str02scm(description));
scm_protect_object(infolist);
gtk_object_set_data(GTK_OBJECT(user_data),
"scm_acct_info", (gpointer)infolist);
gtk_main_quit();
}
void
gnc_ui_account_picker_cancel_cb(GtkButton * button,
gpointer user_data) {
gtk_object_set_data(GTK_OBJECT(user_data),
"scm_acct_info",
(gpointer)SCM_BOOL_F);
gtk_main_quit();
}

View File

@ -0,0 +1,313 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>GNUCash Account Picker</name>
<program_name>gnucash</program_name>
<directory></directory>
<source_directory></source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<use_widget_names>False</use_widget_names>
<output_main_file>False</output_main_file>
<output_support_files>True</output_support_files>
<output_build_files>False</output_build_files>
<backup_source_files>False</backup_source_files>
<main_source_file>glade-account-picker.c</main_source_file>
<main_header_file>glade-account-picker.h</main_header_file>
<handler_source_file>glade-cb-account-picker.c</handler_source_file>
<handler_header_file>glade-cb-account-picker.h</handler_header_file>
<support_source_file>glade-support-account-picker.c</support_source_file>
<support_header_file>glade-support-account-picker.h</support_header_file>
<translatable_strings_file></translatable_strings_file>
</project>
<widget>
<class>GnomeDialog</class>
<name>GNUcash Account Picker</name>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>True</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>1</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkVBox</class>
<name>vbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkFrame</class>
<name>frame1</name>
<label>Accounts</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow1</name>
<width>250</width>
<height>200</height>
<hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkViewport</class>
<name>viewport1</name>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkTree</class>
<name>account_tree</name>
<signal>
<name>select_child</name>
<handler>gnc_ui_account_picker_select_cb</handler>
<data>GNUcash_Account_Picker</data>
<last_modification_time>Thu, 02 Mar 2000 21:32:14 GMT</last_modification_time>
</signal>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<view_mode>GTK_TREE_VIEW_LINE</view_mode>
<view_line>True</view_line>
</widget>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>6</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label1</name>
<width>90</width>
<label>Selected account</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>8</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>acct_entry</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox3</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label2</name>
<width>90</width>
<label>Description</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>8</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>acct_description_entry</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox4</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label3</name>
<width>90</width>
<label>Account type</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>8</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>acct_type_picker</name>
<width>150</width>
<height>30</height>
<can_focus>True</can_focus>
<items>Bank
Cash
Asset
Credit
Liability
Stock
Mutual
Currency
Income
Expense
Equity
</items>
<initial_choice>0</initial_choice>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>hbuttonbox1</name>
<layout_style>GTK_BUTTONBOX_SPREAD</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button1</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_account_picker_ok_cb</handler>
<data>GNUcash_Account_Picker</data>
<last_modification_time>Thu, 02 Mar 2000 23:02:59 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button2</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_account_picker_cancel_cb</handler>
<data>GNUcash_Account_Picker</data>
<last_modification_time>Thu, 02 Mar 2000 23:03:18 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@ -0,0 +1,29 @@
/********************************************************************\
* dialog-account-picker.h -- window for picking a GNUcash account *
* (GnuCash) *
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
\********************************************************************/
#ifndef __DIALOG_ACCOUNT_PICKER_H_
#define __DIALOG_ACCOUNT_PICKER_H_
#include "glade-account-picker.h"
#include "glade-cb-account-picker.h"
SCM accountPickerBox(char *initial_pick, int initial_type);
#endif

View File

@ -0,0 +1,919 @@
/********************************************************************\
* dialog-qif-import.c -- window for importing QIF files *
* (GnuCash) *
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
\********************************************************************/
#define _GNU_SOURCE
#include "top-level.h"
#include <gnome.h>
#include <stdio.h>
#include <guile/gh.h>
#include "dialog-qif-import.h"
#include "dialog-account-picker.h"
#include "window-help.h"
#include "messages.h"
#include "gnome-top-level.h"
#include "Account.h"
#include "AccInfo.h"
#include "FileDialog.h"
#include "FileBox.h"
#include "dialog-utils.h"
#include "query-user.h"
#include "util.h"
static void update_file_info(QIFImportWindow * win, SCM qiffile);
static void update_file_page(QIFImportWindow * win);
static void update_accounts_page(QIFImportWindow * win);
static void update_categories_page(QIFImportWindow * win);
/********************************************************************\
* gnc_ui_qif_import_dialog_make(GtkWidget * parent) * build the
* dialog. For now, there can be only one (obhighlanderref)
\********************************************************************/
QIFImportWindow *
gnc_ui_qif_import_dialog_make(GtkWidget * parent)
{
QIFImportWindow * retval;
GtkWidget * optionmenu;
GtkWidget * menu;
GtkWidget * active;
GtkWidget * currency_entry;
int i;
SCM load_map_prefs;
SCM mapping_info;
SCM lookup_option;
SCM lookup_value;
SCM default_currency;
int scm_strlen;
retval = (QIFImportWindow *) malloc(sizeof(QIFImportWindow));
retval->parent = parent;
retval->dialog = create_QIF_File_Import_Dialog();
retval->imported_files =
SCM_EOL;
retval->selected_file = SCM_BOOL_F;
gtk_object_set_data(GTK_OBJECT(retval->dialog),
"qif_window_struct", retval);
/* load the saved-state of the mappings from Quicken accounts and
* categories to gnucash accounts */
load_map_prefs = gh_eval_str("qif-import:load-map-prefs");
lookup_option = gh_eval_str("gnc:lookup-global-option");
lookup_value = gh_eval_str("gnc:option-value");
mapping_info = gh_call0(load_map_prefs);
retval->mapping_info = mapping_info;
default_currency = gh_call1(lookup_value,
gh_call2(lookup_option,
gh_str02scm("International"),
gh_str02scm("Default Currency")));
scm_protect_object(retval->imported_files);
scm_protect_object(retval->mapping_info);
/* set the currency entry to the GNC default currency */
currency_entry = gtk_object_get_data(GTK_OBJECT(retval->dialog),
"qif_currency_entry");
gtk_entry_set_text(GTK_ENTRY(currency_entry),
gh_scm2newstr(default_currency, &scm_strlen));
/* repair the option menus to associate "option_index" with the
* index number for each menu item */
optionmenu = gtk_object_get_data(GTK_OBJECT(retval->dialog),
"qif_radix_picker");
menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optionmenu));
for(i = 0; i < 3; i++) {
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), i);
active = gtk_menu_get_active(GTK_MENU(menu));
gtk_object_set_data(GTK_OBJECT(active),
"option_index",
(gpointer)(i));
}
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0);
optionmenu = gtk_object_get_data(GTK_OBJECT(retval->dialog),
"qif_date_picker");
menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optionmenu));
for(i = 0; i < 5; i++) {
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), i);
active = gtk_menu_get_active(GTK_MENU(menu));
gtk_object_set_data(GTK_OBJECT(active),
"option_index",
(gpointer)(i));
}
gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0);
gtk_widget_show(retval->dialog);
if (retval->dialog->window == NULL) {
free(retval);
return NULL;
}
gdk_window_raise(retval->dialog->window);
return retval;
}
/********************************************************************\
* gnc_ui_qif_import_dialog_destroy
* close the QIF Import dialog window
\********************************************************************/
void
gnc_ui_qif_import_dialog_destroy (QIFImportWindow * window)
{
if(window) {
gnome_dialog_close(GNOME_DIALOG(window->dialog));
}
}
/********************************************************************\
* gnc_ui_qif_import_select_file_cb
* invoked when the "select file" button is clicked
* this is just to pick a file name and reset-to-defaults all the
* fields describing how to parse the file.
\********************************************************************/
void
gnc_ui_qif_import_select_file_cb(GtkButton * button,
gpointer user_data) {
GtkWidget * dialog = GTK_WIDGET(user_data);
QIFImportWindow * wind =
gtk_object_get_data(GTK_OBJECT(dialog), "qif_window_struct");
GtkWidget * qif_filename_entry =
gtk_object_get_data(GTK_OBJECT(wind->dialog), "qif_filename_entry");
GtkWidget * acct_auto_button =
gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_account_auto_check");
GtkWidget * qif_acct_entry =
gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_account_entry");
GtkWidget * qif_radix_picker =
gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_radix_picker");
GtkWidget * qif_date_picker =
gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_date_picker");
char * new_file_name;
new_file_name = (char *)fileBox("Select QIF File", "*.qif");
if(new_file_name) {
/* set the filename entry for what was selected */
if(qif_filename_entry) {
gtk_entry_set_text(GTK_ENTRY(qif_filename_entry),
new_file_name);
}
/* the account should be auto-determined by default
* if the "opening balance" trick doesn't work "auto" will
* use the file name as a guess */
if(acct_auto_button) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(acct_auto_button),
TRUE);
}
if(qif_acct_entry) {
gtk_entry_set_text(GTK_ENTRY(qif_acct_entry),
"");
}
/* radix and date formats are auto-determined by default */
if(qif_date_picker) {
gtk_option_menu_set_history(GTK_OPTION_MENU(qif_date_picker),
0);
}
if(qif_radix_picker) {
gtk_option_menu_set_history(GTK_OPTION_MENU(qif_radix_picker),
0);
}
}
}
/********************************************************************\
* gnc_ui_qif_import_load_file_cb
*
* Invoked when the "load file" button is clicked on the first page of
* the QIF Import notebook. Filename, currency, radix format, and
* date format are read from the UI and passed to the Scheme side.
\********************************************************************/
void
gnc_ui_qif_import_load_file_cb (GtkButton *button,
gpointer user_data) {
GtkWidget * dialog = GTK_WIDGET(user_data);
QIFImportWindow * wind =
gtk_object_get_data(GTK_OBJECT(dialog), "qif_window_struct");
char * path_to_load;
char * qif_account;
char * currency;
int radix_format;
int date_format;
GtkWidget * filename_box = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_filename_entry");
GtkWidget * currency_box = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_currency_entry");
GtkWidget * radix_picker = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_radix_picker");
GtkWidget * date_picker = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_date_picker");
GtkWidget * account_entry = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_account_entry");
GtkWidget * account_auto = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"qif_account_auto_check");
GtkWidget * menuitem;
SCM make_qif_file, qif_file_load, qif_file_loaded, unload_qif_file;
SCM scm_filename, scm_currency, scm_radix, scm_date, scm_qif_account;
SCM scm_qiffile;
SCM imported_files = SCM_EOL;
char * radix_symbols [] = { "unknown", "decimal", "comma" };
char * date_symbols [] = { "unknown", "m-d-y", "d-m-y",
"y-m-d", "y-d-m" };
/* get the UI elements */
path_to_load = gtk_entry_get_text(GTK_ENTRY(filename_box));
currency = gtk_entry_get_text(GTK_ENTRY(currency_box));
qif_account = gtk_entry_get_text(GTK_ENTRY(account_entry));
radix_picker = gtk_option_menu_get_menu(GTK_OPTION_MENU(radix_picker));
menuitem = gtk_menu_get_active(GTK_MENU(radix_picker));
radix_format = (int)(gtk_object_get_data(GTK_OBJECT(menuitem),
"option_index"));
date_picker = gtk_option_menu_get_menu(GTK_OPTION_MENU(date_picker));
menuitem = gtk_menu_get_active(GTK_MENU(date_picker));
date_format = (int)(gtk_object_get_data(GTK_OBJECT(menuitem),
"option_index"));
if(strlen(path_to_load) == 0) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"You must specify a file to load.");
}
else if(strlen(currency) == 0) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"You must specify a currency.");
}
else {
/* find the make and load functions. */
make_qif_file = gh_eval_str("make-qif-file");
qif_file_load = gh_eval_str("qif-file:read-file");
qif_file_loaded = gh_eval_str("qif-dialog:qif-file-loaded?");
unload_qif_file = gh_eval_str("qif-dialog:unload-qif-file");
if((!gh_procedure_p(make_qif_file)) ||
(!gh_procedure_p(qif_file_load)) ||
(!gh_procedure_p(qif_file_loaded))) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"QIF File scheme code not loaded properly.");
}
else {
/* convert args */
scm_filename = gh_str02scm(path_to_load);
scm_currency = gh_str02scm(currency);
scm_radix = gh_symbol2scm(radix_symbols[radix_format]);
scm_date = gh_symbol2scm(date_symbols[date_format]);
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(account_auto))) {
scm_qif_account = gh_symbol2scm("unknown");
}
else {
scm_qif_account = gh_str02scm(qif_account);
}
imported_files = wind->imported_files;
if(gh_call2(qif_file_loaded, scm_filename, wind->imported_files)
== SCM_BOOL_T) {
if(gnc_verify_dialog_parented(GTK_WINDOW(wind->dialog),
"QIF File already loaded. Reload "
"with current settings?", TRUE)) {
imported_files =
gh_call2(unload_qif_file, scm_filename, wind->imported_files);
}
else {
return;
}
}
/* create the <qif-file> object */
scm_qiffile = gh_apply(make_qif_file,
SCM_LIST4(scm_qif_account, scm_radix,
scm_date, scm_currency));
imported_files =
gh_cons(scm_qiffile, imported_files);
wind->selected_file = scm_qiffile;
/* I think I have to do this since it's a global but not in
* guile-space */
scm_protect_object(wind->selected_file);
/* import the file into it */
if(gh_call2(qif_file_load,
gh_car(imported_files),
scm_filename) != SCM_BOOL_T) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"Failed to load QIF file. Are you "
"sure it's a QIF file?");
imported_files =
gh_call2(unload_qif_file, scm_filename, imported_files);
}
wind->imported_files = imported_files;
scm_protect_object(wind->imported_files);
/* now update the Accounts and Categories pages in the notebook */
update_file_page(wind);
update_accounts_page(wind);
update_categories_page(wind);
}
}
}
void
gnc_ui_qif_import_select_loaded_file_cb(GtkList * list,
GtkWidget * widget,
gpointer user_data) {
GtkWidget * dialog = GTK_WIDGET(user_data);
QIFImportWindow * wind =
gtk_object_get_data(GTK_OBJECT(dialog), "qif_window_struct");
SCM scm_qiffile;
scm_qiffile = (SCM)gtk_object_get_data(GTK_OBJECT(widget), "scm-object");
wind->selected_file = scm_qiffile;
scm_protect_object(wind->selected_file);
update_file_info(wind, scm_qiffile);
}
/****************************************************************\
* qif_import_ok_cb
* do the work of actually translating QIF xtns to GNC xtns.
\****************************************************************/
void
gnc_ui_qif_import_ok_cb(GtkButton * button, gpointer user_data) {
SCM save_map_prefs;
SCM qif_to_gnc;
SCM hash_set;
SCM hash_data;
char * qif_acct_name;
char * qif_cat_name;
int row;
GtkWidget * dialog = GTK_WIDGET(user_data);
QIFImportWindow * wind =
gtk_object_get_data(GTK_OBJECT(dialog), "qif_window_struct");
GtkWidget * acc_list = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"account_page_list");
GtkWidget * cat_list = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"category_page_list");
save_map_prefs = gh_eval_str("qif-import:save-map-prefs");
qif_to_gnc = gh_eval_str("qif-import:qif-to-gnc");
hash_set = gh_eval_str("hash-set!");
/* transfer the info from the account / category pickers to
* the mapping info hash tables */
for(row=0; row < GTK_CLIST(acc_list)->rows; row++) {
gtk_clist_get_text(GTK_CLIST(acc_list), row, 0, &qif_acct_name);
hash_data = (SCM)gtk_clist_get_row_data(GTK_CLIST(acc_list), row);
gh_call3(hash_set, gh_cadr(wind->mapping_info),
gh_str02scm(qif_acct_name),
hash_data);
}
for(row=0; row < GTK_CLIST(cat_list)->rows; row++) {
gtk_clist_get_text(GTK_CLIST(cat_list), row, 0, &qif_cat_name);
hash_data = (SCM)gtk_clist_get_row_data(GTK_CLIST(cat_list), row);
gh_call3(hash_set, gh_caddr(wind->mapping_info),
gh_str02scm(qif_cat_name),
hash_data);
}
/* call a scheme function to do the work */
gh_call2(qif_to_gnc, wind->imported_files,
wind->mapping_info);
/* write out mapping info before destroying the window */
gh_call1(save_map_prefs, wind->mapping_info);
gnc_ui_qif_import_dialog_destroy(wind);
wind = NULL;
}
void
gnc_ui_qif_import_cancel_cb (GtkButton * button, gpointer user_data) {
GtkWidget * dialog = GTK_WIDGET(user_data);
QIFImportWindow * wind =
gtk_object_get_data(GTK_OBJECT(dialog), "qif_window_struct");
gnc_ui_qif_import_dialog_destroy(wind);
}
void
gnc_ui_qif_import_help_cb (GtkButton * button, gpointer user_data) {
helpWindow(NULL, HELP_STR, HH_QIFIMPORT);
}
void
gnc_ui_qif_import_account_line_select_cb(GtkCList * clist, gint row,
gint column, GdkEvent * event,
gpointer user_data) {
char * initial_string;
int initial_type;
SCM scm_acct;
SCM old_info;
SCM munge_func = gh_eval_str("qif-dialog:munge-account-mapping");
old_info = (SCM)gtk_clist_get_row_data(GTK_CLIST(clist), row);
gtk_clist_get_text(GTK_CLIST(clist), row, 2, &initial_string);
initial_type = gh_scm2int(gh_list_ref(old_info, gh_int2scm(2)));
scm_acct = accountPickerBox(initial_string, initial_type);
if(gh_list_p(scm_acct)) {
gh_call2(munge_func, old_info, scm_acct);
gtk_clist_set_text(GTK_CLIST(clist), row, 2,
gh_scm2newstr(gh_car(scm_acct), NULL));
gtk_clist_set_text(GTK_CLIST(clist), row, 3,
xaccAccountTypeEnumAsString
(gh_scm2int(gh_cadr(scm_acct))));
}
}
void
gnc_ui_qif_import_category_line_select_cb(GtkCList * clist, gint row,
gint column, GdkEvent * event,
gpointer user_data) {
char * initial_string;
int initial_type;
SCM scm_acct;
SCM old_info;
SCM munge_func = gh_eval_str("qif-dialog:munge-account-mapping");
old_info = (SCM)gtk_clist_get_row_data(GTK_CLIST(clist), row);
gtk_clist_get_text(GTK_CLIST(clist), row, 2, &initial_string);
initial_type = gh_scm2int(gh_list_ref(old_info, gh_int2scm(2)));
scm_acct = accountPickerBox(initial_string, initial_type);
if(gh_list_p(scm_acct)) {
gh_call2(munge_func, old_info, scm_acct);
gtk_clist_set_text(GTK_CLIST(clist), row, 2,
gh_scm2newstr(gh_car(scm_acct), NULL));
gtk_clist_set_text(GTK_CLIST(clist), row, 3,
xaccAccountTypeEnumAsString
(gh_scm2int(gh_cadr(scm_acct))));
}
}
/********************************************************************\
* update_file_page
* update the left-side list and the right-side info.
\********************************************************************/
static void
update_file_page(QIFImportWindow * wind) {
GtkWidget * new_list_item;
GList * new_loaded_file;
SCM loaded_file_list = wind->imported_files;
SCM scm_qiffile;
SCM qif_file_path;
int path_strlen;
/* find the list of loaded files */
GtkWidget * loaded_files = gtk_object_get_data(GTK_OBJECT(wind->dialog),
"selected_file_list");
/* clear the list */
gtk_list_remove_items(GTK_LIST(loaded_files),
gtk_container_children(GTK_CONTAINER(loaded_files)));
qif_file_path = gh_eval_str("qif-file:path");
/* iterate over all the imported files */
while(!gh_null_p(loaded_file_list)) {
scm_qiffile = gh_car(loaded_file_list);
/* make a list item with the SCM object attached as data */
new_list_item =
gtk_list_item_new_with_label(gh_scm2newstr(gh_call1(qif_file_path,
scm_qiffile),
&path_strlen));
gtk_object_set_data(GTK_OBJECT(new_list_item),
"scm-object", (gpointer)scm_qiffile);
scm_protect_object(scm_qiffile);
/* tack it on to the displayed list */
new_loaded_file = g_list_alloc();
new_loaded_file->next = NULL;
new_loaded_file->prev = NULL;
gtk_widget_show(new_list_item);
new_loaded_file->data = new_list_item;
/* now add the file to the loaded-files list */
gtk_list_append_items(GTK_LIST(loaded_files), new_loaded_file);
/* select_child will update the file info */
if(scm_qiffile == wind->selected_file) {
gtk_list_select_child(GTK_LIST(loaded_files), new_list_item);
}
loaded_file_list = gh_cdr(loaded_file_list);
}
}
/********************************************************************\
* update_file_info
*
* Invoked when a file is loaded or the name of a loaded file is
* clicked in the loaded files list. This causes the pickers and text
* boxes on the right side to be updated to reflect the actual values
* used or detected in loading the files.
\********************************************************************/
static void
update_file_info(QIFImportWindow * win, SCM qif_file) {
SCM qif_file_radix_format;
SCM qif_file_date_format;
SCM qif_file_currency;
SCM qif_file_path;
SCM qif_file_account;
SCM scm_radix_format;
SCM scm_date_format;
SCM scm_currency;
SCM scm_qif_account;
SCM scm_qif_path;
GtkWidget * path_entry;
GtkWidget * currency_entry;
GtkWidget * radix_optionmenu;
GtkWidget * date_optionmenu;
GtkWidget * account_entry;
GtkWidget * account_auto;
int scm_strlen;
/* look up the <qif-file> methods */
qif_file_radix_format = gh_eval_str("qif-file:radix-format");
qif_file_date_format = gh_eval_str("qif-file:date-format");
qif_file_currency = gh_eval_str("qif-file:currency");
qif_file_path = gh_eval_str("qif-file:path");
qif_file_account = gh_eval_str("qif-file:account");
/* make sure the methods are loaded */
if((!gh_procedure_p(qif_file_radix_format)) ||
(!gh_procedure_p(qif_file_date_format)) ||
(!gh_procedure_p(qif_file_currency)) ||
(!gh_procedure_p(qif_file_account)) ||
(!gh_procedure_p(qif_file_path))) {
gnc_error_dialog_parented(GTK_WINDOW(win->dialog),
"QIF File scheme code not loaded properly.");
return;
}
else {
/* find the relevant widgets */
path_entry = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_filename_entry");
currency_entry = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_currency_entry");
radix_optionmenu = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_radix_picker");
date_optionmenu = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_date_picker");
account_entry = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_account_entry");
account_auto = gtk_object_get_data(GTK_OBJECT(win->dialog),
"qif_account_auto_check");
/* stick the currently-selected qiffile scm in the window data */
gtk_object_set_data(GTK_OBJECT(win->dialog),
"current_qif_file", (gpointer)qif_file);
scm_protect_object(qif_file);
/* get the radix/date formats, currency etc from the Scheme side */
scm_radix_format = gh_call1(qif_file_radix_format,
qif_file);
scm_date_format = gh_call1(qif_file_date_format,
qif_file);
scm_currency = gh_call1(qif_file_currency,
qif_file);
scm_qif_path = gh_call1(qif_file_path,
qif_file);
scm_qif_account = gh_call1(qif_file_account,
qif_file);
/* put the data in the info fields */
gtk_entry_set_text(GTK_ENTRY(path_entry),
gh_scm2newstr(scm_qif_path, &scm_strlen));
gtk_entry_set_text(GTK_ENTRY(currency_entry),
gh_scm2newstr(scm_currency, &scm_strlen));
/* account is weird. after loading, either we know it or we don't
* but in either case the auto should be off. */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(account_auto), FALSE);
gtk_entry_set_text(GTK_ENTRY(account_entry),
gh_scm2newstr(scm_qif_account, &scm_strlen));
/* set the option menu selections */
if(!strcmp(gh_symbol2newstr(scm_radix_format, &scm_strlen),
"unknown")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(radix_optionmenu), 0);
}
else if(!strcmp(gh_symbol2newstr(scm_radix_format, &scm_strlen),
"decimal")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(radix_optionmenu), 1);
}
else if(!strcmp(gh_symbol2newstr(scm_radix_format, &scm_strlen),
"comma")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(radix_optionmenu), 2);
}
if(!strcmp(gh_symbol2newstr(scm_date_format, &scm_strlen),
"unknown")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(date_optionmenu), 0);
}
else if(!strcmp(gh_symbol2newstr(scm_date_format, &scm_strlen),
"m-d-y")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(date_optionmenu), 1);
}
else if(!strcmp(gh_symbol2newstr(scm_date_format, &scm_strlen),
"d-m-y")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(date_optionmenu), 2);
}
else if(!strcmp(gh_symbol2newstr(scm_date_format, &scm_strlen),
"y-m-d")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(date_optionmenu), 3);
}
else if(!strcmp(gh_symbol2newstr(scm_date_format, &scm_strlen),
"y-d-m")) {
gtk_option_menu_set_history(GTK_OPTION_MENU(date_optionmenu), 4);
}
}
}
/****************************************************************\
* update_accounts_page
* Ask the Scheme side to guess some account translations , then
* show the filename, account name, and suggested translation in
* the Accounts page clist.
\****************************************************************/
static void
update_accounts_page(QIFImportWindow * wind) {
SCM make_account_display;
SCM strings_left;
SCM display_info;
SCM hash_data;
SCM hash_set;
int xtn_count;
char * xtn_count_string;
char * qif_acct_name;
GtkWidget * account_list;
int row;
int scheme_strlen;
char * row_text[4];
make_account_display = gh_eval_str("qif-dialog:make-account-display");
hash_set = gh_eval_str("hash-set!");
/* make sure we found the procedure */
if(!gh_procedure_p(make_account_display)) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"QIF File scheme code not loaded properly.");
return;
}
account_list = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(wind->dialog),
"account_page_list");
/* transfer the existing info from the account picker to
* the mapping info hash table */
for(row=0; row < GTK_CLIST(account_list)->rows; row++) {
gtk_clist_get_text(GTK_CLIST(account_list), row, 0, &qif_acct_name);
hash_data = (SCM)gtk_clist_get_row_data(GTK_CLIST(account_list), row);
gh_call3(hash_set, gh_cadr(wind->mapping_info),
gh_str02scm(qif_acct_name),
hash_data);
}
/* now get the list of strings to display in the clist widget */
/* gnc_unprotect_object(wind->acct_display_info); */
display_info = gh_call2(make_account_display,
wind->imported_files,
wind->mapping_info);
wind->acct_display_info = display_info;
scm_protect_object(wind->acct_display_info);
strings_left = wind->acct_display_info;
if(!gh_list_p(strings_left)) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"Something is very wrong with QIF Importing.");
return;
}
/* clear the list */
gtk_clist_clear(GTK_CLIST(account_list));
/* update the text in the boxes */
gtk_clist_freeze(GTK_CLIST(account_list));
gtk_clist_set_column_justification(GTK_CLIST(account_list),
0,
GTK_JUSTIFY_RIGHT);
row = 0;
while(!gh_null_p(strings_left)) {
row_text[0] = gh_scm2newstr(gh_caar(strings_left), &scheme_strlen);
xtn_count = gh_scm2int(gh_list_ref(gh_car(strings_left),
gh_int2scm(4)));
asprintf(&xtn_count_string, "%d", xtn_count);
row_text[1] = xtn_count_string;
row_text[2] = gh_scm2newstr(gh_cadr(gh_car(strings_left)),
&scheme_strlen);
row_text[3] =
xaccAccountTypeEnumAsString(gh_scm2int
(gh_caddr(gh_car(strings_left))));
gtk_clist_append(GTK_CLIST(account_list), row_text);
gtk_clist_set_row_data(GTK_CLIST(account_list), row,
(gpointer)(gh_car(strings_left)));
scm_protect_object(gh_car(strings_left));
strings_left = gh_cdr(strings_left);
row++;
}
gtk_clist_thaw(GTK_CLIST(account_list));
}
/****************************************************************\
* update_categories_page
* Ask the Scheme side to guess some account translations , then
* show the filename, account name, and suggested translation in
* the Accounts page clist.
\****************************************************************/
static void
update_categories_page(QIFImportWindow * wind) {
SCM make_category_display;
SCM strings_left;
SCM display_info;
SCM hash_data;
SCM hash_set;
int xtn_count;
char * xtn_count_string;
char * qif_cat_name;
GtkWidget * category_list;
int row;
int scheme_strlen;
char * row_text[4];
make_category_display = gh_eval_str("qif-dialog:make-category-display");
hash_set = gh_eval_str("hash-set!");
/* make sure we found the procedure */
if(!gh_procedure_p(make_category_display)) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"QIF File scheme code not loaded properly.");
return;
}
category_list = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(wind->dialog),
"category_page_list");
/* get the existing mappings from the display */
for(row=0; row < GTK_CLIST(category_list)->rows; row++) {
gtk_clist_get_text(GTK_CLIST(category_list), row, 0, &qif_cat_name);
hash_data = (SCM)gtk_clist_get_row_data(GTK_CLIST(category_list), row);
gh_call3(hash_set, gh_caddr(wind->mapping_info),
gh_str02scm(qif_cat_name),
hash_data);
}
/* now get the list of strings to display in the clist widget */
/* gnc_unprotect_object(wind->cat_display_info); */
display_info = gh_call2(make_category_display,
wind->imported_files,
wind->mapping_info);
wind->cat_display_info = display_info;
scm_protect_object(wind->cat_display_info);
strings_left = wind->cat_display_info;
if(!gh_list_p(strings_left)) {
gnc_error_dialog_parented(GTK_WINDOW(wind->dialog),
"Something is very wrong with QIF Importing.");
return;
}
/* clear the list */
gtk_clist_clear(GTK_CLIST(category_list));
/* update the text in the boxes */
gtk_clist_freeze(GTK_CLIST(category_list));
gtk_clist_set_column_justification(GTK_CLIST(category_list),
0,
GTK_JUSTIFY_RIGHT);
row = 0;
while(!gh_null_p(strings_left)) {
row_text[0] = gh_scm2newstr(gh_caar(strings_left), &scheme_strlen);
xtn_count = gh_scm2int(gh_list_ref(gh_car(strings_left),
gh_int2scm(4)));
asprintf(&xtn_count_string, "%d", xtn_count);
row_text[1] = xtn_count_string;
row_text[2] = gh_scm2newstr(gh_cadr(gh_car(strings_left)),
&scheme_strlen);
row_text[3] = xaccAccountTypeEnumAsString(gh_scm2int
(gh_caddr(gh_car(strings_left))));
gtk_clist_append(GTK_CLIST(category_list), row_text);
gtk_clist_set_row_data(GTK_CLIST(category_list), row,
(gpointer)gh_car(strings_left));
scm_protect_object(gh_car(strings_left));
strings_left = gh_cdr(strings_left);
row++;
}
gtk_clist_thaw(GTK_CLIST(category_list));
}

View File

@ -0,0 +1,694 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>dialog-qif-import</name>
<program_name>dialog-qif-import</program_name>
<directory></directory>
<source_directory></source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<use_widget_names>False</use_widget_names>
<output_main_file>False</output_main_file>
<output_support_files>True</output_support_files>
<output_build_files>False</output_build_files>
<backup_source_files>False</backup_source_files>
<main_source_file>glade-qif-import.c</main_source_file>
<main_header_file>glade-qif-import.h</main_header_file>
<handler_source_file>glade-cb-qif-import.c</handler_source_file>
<handler_header_file>glade-cb-qif-import.h</handler_header_file>
<support_source_file>glade-support-qif-import.c</support_source_file>
<support_header_file>glade-support-qif-import.h</support_header_file>
<translatable_strings_file></translatable_strings_file>
</project>
<widget>
<class>GnomeDialog</class>
<name>QIF File Import Dialog</name>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>True</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox2</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkNotebook</class>
<name>notebook1</name>
<can_focus>True</can_focus>
<show_tabs>True</show_tabs>
<show_border>True</show_border>
<tab_pos>GTK_POS_TOP</tab_pos>
<scrollable>False</scrollable>
<tab_hborder>2</tab_hborder>
<tab_vborder>2</tab_vborder>
<popup_enable>False</popup_enable>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkFrame</class>
<name>frame2</name>
<width>200</width>
<label>Loaded Files</label>
<label_xalign>0.05</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow1</name>
<height>150</height>
<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkViewport</class>
<name>viewport1</name>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkList</class>
<name>selected_file_list</name>
<signal>
<name>select_child</name>
<handler>gnc_ui_qif_import_select_loaded_file_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:17:01 GMT</last_modification_time>
</signal>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame1</name>
<width>325</width>
<label>File Info</label>
<label_xalign>0.01</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkVBox</class>
<name>vbox1</name>
<homogeneous>True</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkHBox</class>
<name>hbox5</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label1</name>
<width>70</width>
<label>QIF Filename</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>qif_filename_entry</name>
<can_default>True</can_default>
<has_default>True</has_default>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>5</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox8</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label679</name>
<width>70</width>
<label>QIF Account</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>qif_account_auto_check</name>
<width>45</width>
<height>16</height>
<can_focus>True</can_focus>
<label>Auto</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>2</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>qif_account_entry</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>5</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>currency_label</name>
<width>70</width>
<label>Currency</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>qif_currency_entry</name>
<width>75</width>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox3</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>radix_format_label</name>
<width>70</width>
<label>Radix format</label>
<justify>GTK_JUSTIFY_RIGHT</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>qif_radix_picker</name>
<width>140</width>
<can_focus>True</can_focus>
<items>Autodetect
Decimal (1,000.00)
Comma (1.000,00)
</items>
<initial_choice>0</initial_choice>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox4</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>date_format_label</name>
<width>70</width>
<label>Date format</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkOptionMenu</class>
<name>qif_date_picker</name>
<width>140</width>
<can_focus>True</can_focus>
<items>Autodetect
MM/DD/YYYY
DD/MM/YYYY
YYYY/MM/DD
YYYY/DD/MM
</items>
<initial_choice>0</initial_choice>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox6</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>5</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>file_select_btn</name>
<width>125</width>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_qif_import_select_file_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:42:40 GMT</last_modification_time>
</signal>
<label>Select file</label>
<child>
<padding>3</padding>
<expand>True</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>add_file_button</name>
<width>125</width>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_qif_import_load_file_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:14:48 GMT</last_modification_time>
</signal>
<label>Load file</label>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label69</name>
<label>Files</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow2</name>
<hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkCList</class>
<name>account_page_list</name>
<can_focus>True</can_focus>
<signal>
<name>select_row</name>
<handler>gnc_ui_qif_import_account_line_select_cb</handler>
<last_modification_time>Tue, 14 Mar 2000 14:58:13 GMT</last_modification_time>
</signal>
<columns>4</columns>
<column_widths>116,80,204,80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>True</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label682</name>
<label>QIF Account</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label683</name>
<label>Transactions</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label684</name>
<label>GNUCash Account Name</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label685</name>
<label>Type</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label2</name>
<label>Accounts</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow3</name>
<hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkCList</class>
<name>category_page_list</name>
<can_focus>True</can_focus>
<signal>
<name>select_row</name>
<handler>gnc_ui_qif_import_category_line_select_cb</handler>
<last_modification_time>Tue, 14 Mar 2000 14:59:18 GMT</last_modification_time>
</signal>
<columns>4</columns>
<column_widths>117,80,204,80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>True</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label686</name>
<label>QIF Category</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label687</name>
<label>Transactions</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label688</name>
<label>GNUCash Account Name</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label689</name>
<label>Type</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>foo6868</name>
<label>Categories</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area2</name>
<layout_style>GTK_BUTTONBOX_SPREAD</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button2</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_qif_import_ok_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:08:23 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button3</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_qif_import_cancel_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:08:04 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button4</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_qif_import_help_cb</handler>
<data>QIF_File_Import_Dialog</data>
<last_modification_time>Tue, 14 Mar 2000 15:08:59 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_HELP</stock_button>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@ -0,0 +1,46 @@
/********************************************************************\
* dialog-qif-import.h -- window for controlling import of QIF data *
* (GnuCash) *
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
\********************************************************************/
#ifndef __DIALOG_QIF_IMPORT_H_
#define __DIALOG_QIF_IMPORT_H_
#include <guile/gh.h>
#include "glade-qif-import.h"
#include "glade-cb-qif-import.h"
typedef struct _qifimportwindow
{
GtkWidget * parent;
GtkWidget * dialog;
SCM imported_files;
SCM selected_file;
SCM mapping_info;
SCM cat_display_info;
SCM acct_display_info;
} QIFImportWindow;
QIFImportWindow * gnc_ui_qif_import_dialog_make(GtkWidget * parent);
void gnc_ui_qif_import_dialog_destroy(QIFImportWindow * window);
#endif

View File

@ -0,0 +1,236 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <gnome.h>
#include "glade-cb-account-picker.h"
#include "glade-account-picker.h"
#include "glade-support-account-picker.h"
GtkWidget*
create_GNUcash_Account_Picker (void)
{
GtkWidget *GNUcash_Account_Picker;
GtkWidget *vbox1;
GtkWidget *vbox2;
GtkWidget *hbox1;
GtkWidget *frame1;
GtkWidget *scrolledwindow1;
GtkWidget *viewport1;
GtkWidget *account_tree;
GtkWidget *hbox2;
GtkWidget *label1;
GtkWidget *acct_entry;
GtkWidget *hbox3;
GtkWidget *label2;
GtkWidget *acct_description_entry;
GtkWidget *hbox4;
GtkWidget *label3;
GtkWidget *acct_type_picker;
GtkWidget *acct_type_picker_menu;
GtkWidget *glade_menuitem;
GtkWidget *hbuttonbox1;
GtkWidget *button1;
GtkWidget *button2;
GNUcash_Account_Picker = gnome_dialog_new (NULL, NULL);
gtk_object_set_data (GTK_OBJECT (GNUcash_Account_Picker), "GNUcash_Account_Picker", GNUcash_Account_Picker);
gtk_window_set_policy (GTK_WINDOW (GNUcash_Account_Picker), TRUE, TRUE, FALSE);
vbox1 = GNOME_DIALOG (GNUcash_Account_Picker)->vbox;
gtk_object_set_data (GTK_OBJECT (GNUcash_Account_Picker), "vbox1", vbox1);
gtk_widget_show (vbox1);
vbox2 = gtk_vbox_new (FALSE, 0);
gtk_widget_ref (vbox2);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "vbox2", vbox2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (vbox2);
gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);
hbox1 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "hbox1", hbox1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox1);
gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0);
frame1 = gtk_frame_new (_("Accounts"));
gtk_widget_ref (frame1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "frame1", frame1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (frame1);
gtk_box_pack_start (GTK_BOX (hbox1), frame1, TRUE, TRUE, 0);
scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_ref (scrolledwindow1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "scrolledwindow1", scrolledwindow1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (scrolledwindow1);
gtk_container_add (GTK_CONTAINER (frame1), scrolledwindow1);
gtk_widget_set_usize (scrolledwindow1, 250, 200);
viewport1 = gtk_viewport_new (NULL, NULL);
gtk_widget_ref (viewport1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "viewport1", viewport1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (viewport1);
gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1);
account_tree = gtk_tree_new ();
gtk_widget_ref (account_tree);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "account_tree", account_tree,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (account_tree);
gtk_container_add (GTK_CONTAINER (viewport1), account_tree);
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox2);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "hbox2", hbox2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox2);
gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 6);
label1 = gtk_label_new (_("Selected account"));
gtk_widget_ref (label1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "label1", label1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label1);
gtk_box_pack_start (GTK_BOX (hbox2), label1, FALSE, FALSE, 8);
gtk_widget_set_usize (label1, 90, -2);
gtk_misc_set_alignment (GTK_MISC (label1), 1, 0.5);
acct_entry = gtk_entry_new ();
gtk_widget_ref (acct_entry);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "acct_entry", acct_entry,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (acct_entry);
gtk_box_pack_start (GTK_BOX (hbox2), acct_entry, TRUE, TRUE, 0);
hbox3 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox3);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "hbox3", hbox3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox3);
gtk_box_pack_start (GTK_BOX (vbox1), hbox3, FALSE, FALSE, 0);
label2 = gtk_label_new (_("Description"));
gtk_widget_ref (label2);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "label2", label2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label2);
gtk_box_pack_start (GTK_BOX (hbox3), label2, FALSE, FALSE, 8);
gtk_widget_set_usize (label2, 90, -2);
gtk_misc_set_alignment (GTK_MISC (label2), 1, 0.5);
acct_description_entry = gtk_entry_new ();
gtk_widget_ref (acct_description_entry);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "acct_description_entry", acct_description_entry,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (acct_description_entry);
gtk_box_pack_start (GTK_BOX (hbox3), acct_description_entry, TRUE, TRUE, 0);
hbox4 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox4);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "hbox4", hbox4,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox4);
gtk_box_pack_start (GTK_BOX (vbox1), hbox4, FALSE, FALSE, 0);
label3 = gtk_label_new (_("Account type"));
gtk_widget_ref (label3);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "label3", label3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label3);
gtk_box_pack_start (GTK_BOX (hbox4), label3, FALSE, FALSE, 8);
gtk_widget_set_usize (label3, 90, -2);
gtk_misc_set_alignment (GTK_MISC (label3), 1, 0.5);
acct_type_picker = gtk_option_menu_new ();
gtk_widget_ref (acct_type_picker);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "acct_type_picker", acct_type_picker,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (acct_type_picker);
gtk_box_pack_start (GTK_BOX (hbox4), acct_type_picker, FALSE, FALSE, 0);
gtk_widget_set_usize (acct_type_picker, 150, 30);
acct_type_picker_menu = gtk_menu_new ();
glade_menuitem = gtk_menu_item_new_with_label (_("Bank"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Cash"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Asset"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Credit"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Liability"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Stock"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Mutual"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Currency"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Income"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Expense"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Equity"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (acct_type_picker_menu), glade_menuitem);
gtk_option_menu_set_menu (GTK_OPTION_MENU (acct_type_picker), acct_type_picker_menu);
hbuttonbox1 = GNOME_DIALOG (GNUcash_Account_Picker)->action_area;
gtk_object_set_data (GTK_OBJECT (GNUcash_Account_Picker), "hbuttonbox1", hbuttonbox1);
gtk_widget_show (hbuttonbox1);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox1), 8);
gnome_dialog_append_button (GNOME_DIALOG (GNUcash_Account_Picker), GNOME_STOCK_BUTTON_OK);
button1 = g_list_last (GNOME_DIALOG (GNUcash_Account_Picker)->buttons)->data;
gtk_widget_ref (button1);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "button1", button1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button1);
GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
gnome_dialog_append_button (GNOME_DIALOG (GNUcash_Account_Picker), GNOME_STOCK_BUTTON_CANCEL);
button2 = g_list_last (GNOME_DIALOG (GNUcash_Account_Picker)->buttons)->data;
gtk_widget_ref (button2);
gtk_object_set_data_full (GTK_OBJECT (GNUcash_Account_Picker), "button2", button2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button2);
GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (account_tree), "select_child",
GTK_SIGNAL_FUNC (gnc_ui_account_picker_select_cb),
GNUcash_Account_Picker);
gtk_signal_connect (GTK_OBJECT (button1), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_account_picker_ok_cb),
GNUcash_Account_Picker);
gtk_signal_connect (GTK_OBJECT (button2), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_account_picker_cancel_cb),
GNUcash_Account_Picker);
return GNUcash_Account_Picker;
}

View File

@ -0,0 +1,5 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
GtkWidget* create_GNUcash_Account_Picker (void);

View File

@ -0,0 +1,35 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include "glade-cb-account-picker.h"
#include "glade-account-picker.h"
#include "glade-support-account-picker.h"
void
gnc_ui_account_picker_select_cb (GtkTree *tree,
GtkWidget *widget,
gpointer user_data)
{
}
void
gnc_ui_account_picker_ok_cb (GtkButton *button,
gpointer user_data)
{
}
void
gnc_ui_account_picker_cancel_cb (GtkButton *button,
gpointer user_data)
{
}

View File

@ -0,0 +1,15 @@
#include <gnome.h>
void
gnc_ui_account_picker_select_cb (GtkTree *tree,
GtkWidget *widget,
gpointer user_data);
void
gnc_ui_account_picker_ok_cb (GtkButton *button,
gpointer user_data);
void
gnc_ui_account_picker_cancel_cb (GtkButton *button,
gpointer user_data);

View File

@ -0,0 +1,84 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gnome.h>
#include "glade-cb-qif-import.h"
#include "glade-qif-import.h"
#include "glade-support-qif-import.h"
void
gnc_ui_qif_import_select_loaded_file_cb
(GtkList *list,
GtkWidget *widget,
gpointer user_data)
{
}
void
gnc_ui_qif_import_select_file_cb (GtkButton *button,
gpointer user_data)
{
}
void
gnc_ui_qif_import_load_file_cb (GtkButton *button,
gpointer user_data)
{
}
void
gnc_ui_qif_import_account_line_select_cb
(GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data)
{
}
void
gnc_ui_qif_import_category_line_select_cb
(GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data)
{
}
void
gnc_ui_qif_import_ok_cb (GtkButton *button,
gpointer user_data)
{
}
void
gnc_ui_qif_import_cancel_cb (GtkButton *button,
gpointer user_data)
{
}
void
gnc_ui_qif_import_help_cb (GtkButton *button,
gpointer user_data)
{
}

View File

@ -0,0 +1,44 @@
#include <gnome.h>
void
gnc_ui_qif_import_select_loaded_file_cb
(GtkList *list,
GtkWidget *widget,
gpointer user_data);
void
gnc_ui_qif_import_select_file_cb (GtkButton *button,
gpointer user_data);
void
gnc_ui_qif_import_load_file_cb (GtkButton *button,
gpointer user_data);
void
gnc_ui_qif_import_account_line_select_cb
(GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data);
void
gnc_ui_qif_import_category_line_select_cb
(GtkCList *clist,
gint row,
gint column,
GdkEvent *event,
gpointer user_data);
void
gnc_ui_qif_import_ok_cb (GtkButton *button,
gpointer user_data);
void
gnc_ui_qif_import_cancel_cb (GtkButton *button,
gpointer user_data);
void
gnc_ui_qif_import_help_cb (GtkButton *button,
gpointer user_data);

View File

@ -0,0 +1,499 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <gnome.h>
#include "glade-cb-qif-import.h"
#include "glade-qif-import.h"
#include "glade-support-qif-import.h"
GtkWidget*
create_QIF_File_Import_Dialog (void)
{
GtkWidget *QIF_File_Import_Dialog;
GtkWidget *dialog_vbox2;
GtkWidget *notebook1;
GtkWidget *hbox1;
GtkWidget *frame2;
GtkWidget *scrolledwindow1;
GtkWidget *viewport1;
GtkWidget *selected_file_list;
GtkWidget *frame1;
GtkWidget *vbox1;
GtkWidget *hbox5;
GtkWidget *label1;
GtkWidget *qif_filename_entry;
GtkWidget *hbox8;
GtkWidget *label679;
GtkWidget *qif_account_auto_check;
GtkWidget *qif_account_entry;
GtkWidget *hbox2;
GtkWidget *currency_label;
GtkWidget *qif_currency_entry;
GtkWidget *hbox3;
GtkWidget *radix_format_label;
GtkWidget *qif_radix_picker;
GtkWidget *qif_radix_picker_menu;
GtkWidget *glade_menuitem;
GtkWidget *hbox4;
GtkWidget *date_format_label;
GtkWidget *qif_date_picker;
GtkWidget *qif_date_picker_menu;
GtkWidget *hbox6;
GtkWidget *file_select_btn;
GtkWidget *add_file_button;
GtkWidget *label69;
GtkWidget *scrolledwindow2;
GtkWidget *account_page_list;
GtkWidget *label682;
GtkWidget *label683;
GtkWidget *label684;
GtkWidget *label685;
GtkWidget *label2;
GtkWidget *scrolledwindow3;
GtkWidget *category_page_list;
GtkWidget *label686;
GtkWidget *label687;
GtkWidget *label688;
GtkWidget *label689;
GtkWidget *foo6868;
GtkWidget *dialog_action_area2;
GtkWidget *button2;
GtkWidget *button3;
GtkWidget *button4;
QIF_File_Import_Dialog = gnome_dialog_new (NULL, NULL);
gtk_object_set_data (GTK_OBJECT (QIF_File_Import_Dialog), "QIF_File_Import_Dialog", QIF_File_Import_Dialog);
gtk_window_set_policy (GTK_WINDOW (QIF_File_Import_Dialog), TRUE, TRUE, FALSE);
dialog_vbox2 = GNOME_DIALOG (QIF_File_Import_Dialog)->vbox;
gtk_object_set_data (GTK_OBJECT (QIF_File_Import_Dialog), "dialog_vbox2", dialog_vbox2);
gtk_widget_show (dialog_vbox2);
notebook1 = gtk_notebook_new ();
gtk_widget_ref (notebook1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "notebook1", notebook1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (notebook1);
gtk_box_pack_start (GTK_BOX (dialog_vbox2), notebook1, TRUE, TRUE, 0);
hbox1 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox1", hbox1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox1);
gtk_container_add (GTK_CONTAINER (notebook1), hbox1);
frame2 = gtk_frame_new (_("Loaded Files"));
gtk_widget_ref (frame2);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "frame2", frame2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (frame2);
gtk_box_pack_start (GTK_BOX (hbox1), frame2, TRUE, TRUE, 0);
gtk_widget_set_usize (frame2, 200, -2);
gtk_frame_set_label_align (GTK_FRAME (frame2), 0.05, 0.5);
scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_ref (scrolledwindow1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "scrolledwindow1", scrolledwindow1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (scrolledwindow1);
gtk_container_add (GTK_CONTAINER (frame2), scrolledwindow1);
gtk_widget_set_usize (scrolledwindow1, -2, 150);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
viewport1 = gtk_viewport_new (NULL, NULL);
gtk_widget_ref (viewport1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "viewport1", viewport1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (viewport1);
gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1);
selected_file_list = gtk_list_new ();
gtk_widget_ref (selected_file_list);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "selected_file_list", selected_file_list,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (selected_file_list);
gtk_container_add (GTK_CONTAINER (viewport1), selected_file_list);
frame1 = gtk_frame_new (_("File Info"));
gtk_widget_ref (frame1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "frame1", frame1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (frame1);
gtk_box_pack_start (GTK_BOX (hbox1), frame1, FALSE, FALSE, 0);
gtk_widget_set_usize (frame1, 325, -2);
gtk_frame_set_label_align (GTK_FRAME (frame1), 0.01, 0.5);
vbox1 = gtk_vbox_new (TRUE, 0);
gtk_widget_ref (vbox1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "vbox1", vbox1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (frame1), vbox1);
hbox5 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox5);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox5", hbox5,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox5);
gtk_box_pack_start (GTK_BOX (vbox1), hbox5, FALSE, FALSE, 0);
label1 = gtk_label_new (_("QIF Filename"));
gtk_widget_ref (label1);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label1", label1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label1);
gtk_box_pack_start (GTK_BOX (hbox5), label1, FALSE, FALSE, 10);
gtk_widget_set_usize (label1, 70, -2);
gtk_misc_set_alignment (GTK_MISC (label1), 1, 0.5);
qif_filename_entry = gtk_entry_new ();
gtk_widget_ref (qif_filename_entry);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_filename_entry", qif_filename_entry,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_filename_entry);
gtk_box_pack_start (GTK_BOX (hbox5), qif_filename_entry, TRUE, TRUE, 5);
GTK_WIDGET_SET_FLAGS (qif_filename_entry, GTK_CAN_DEFAULT);
hbox8 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox8);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox8", hbox8,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox8);
gtk_box_pack_start (GTK_BOX (vbox1), hbox8, TRUE, TRUE, 0);
label679 = gtk_label_new (_("QIF Account"));
gtk_widget_ref (label679);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label679", label679,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label679);
gtk_box_pack_start (GTK_BOX (hbox8), label679, FALSE, FALSE, 10);
gtk_widget_set_usize (label679, 70, -2);
gtk_misc_set_alignment (GTK_MISC (label679), 1, 0.5);
qif_account_auto_check = gtk_check_button_new_with_label (_("Auto"));
gtk_widget_ref (qif_account_auto_check);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_account_auto_check", qif_account_auto_check,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_account_auto_check);
gtk_box_pack_start (GTK_BOX (hbox8), qif_account_auto_check, FALSE, FALSE, 2);
gtk_widget_set_usize (qif_account_auto_check, 45, 16);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (qif_account_auto_check), TRUE);
qif_account_entry = gtk_entry_new ();
gtk_widget_ref (qif_account_entry);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_account_entry", qif_account_entry,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_account_entry);
gtk_box_pack_start (GTK_BOX (hbox8), qif_account_entry, TRUE, TRUE, 5);
hbox2 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox2);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox2", hbox2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox2);
gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, FALSE, 0);
currency_label = gtk_label_new (_("Currency"));
gtk_widget_ref (currency_label);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "currency_label", currency_label,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (currency_label);
gtk_box_pack_start (GTK_BOX (hbox2), currency_label, FALSE, FALSE, 10);
gtk_widget_set_usize (currency_label, 70, -2);
gtk_label_set_justify (GTK_LABEL (currency_label), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (currency_label), 1, 0.5);
qif_currency_entry = gtk_entry_new ();
gtk_widget_ref (qif_currency_entry);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_currency_entry", qif_currency_entry,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_currency_entry);
gtk_box_pack_start (GTK_BOX (hbox2), qif_currency_entry, FALSE, FALSE, 5);
gtk_widget_set_usize (qif_currency_entry, 75, -2);
hbox3 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox3);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox3", hbox3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox3);
gtk_box_pack_start (GTK_BOX (vbox1), hbox3, FALSE, FALSE, 0);
radix_format_label = gtk_label_new (_("Radix format"));
gtk_widget_ref (radix_format_label);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "radix_format_label", radix_format_label,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (radix_format_label);
gtk_box_pack_start (GTK_BOX (hbox3), radix_format_label, FALSE, FALSE, 10);
gtk_widget_set_usize (radix_format_label, 70, -2);
gtk_label_set_justify (GTK_LABEL (radix_format_label), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (radix_format_label), 1, 0.5);
qif_radix_picker = gtk_option_menu_new ();
gtk_widget_ref (qif_radix_picker);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_radix_picker", qif_radix_picker,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_radix_picker);
gtk_box_pack_start (GTK_BOX (hbox3), qif_radix_picker, FALSE, FALSE, 5);
gtk_widget_set_usize (qif_radix_picker, 140, -2);
qif_radix_picker_menu = gtk_menu_new ();
glade_menuitem = gtk_menu_item_new_with_label (_("Autodetect"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_radix_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Decimal (1,000.00)"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_radix_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("Comma (1.000,00)"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_radix_picker_menu), glade_menuitem);
gtk_option_menu_set_menu (GTK_OPTION_MENU (qif_radix_picker), qif_radix_picker_menu);
hbox4 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox4);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox4", hbox4,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox4);
gtk_box_pack_start (GTK_BOX (vbox1), hbox4, FALSE, FALSE, 0);
date_format_label = gtk_label_new (_("Date format"));
gtk_widget_ref (date_format_label);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "date_format_label", date_format_label,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (date_format_label);
gtk_box_pack_start (GTK_BOX (hbox4), date_format_label, FALSE, FALSE, 10);
gtk_widget_set_usize (date_format_label, 70, -2);
gtk_misc_set_alignment (GTK_MISC (date_format_label), 1, 0.5);
qif_date_picker = gtk_option_menu_new ();
gtk_widget_ref (qif_date_picker);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "qif_date_picker", qif_date_picker,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (qif_date_picker);
gtk_box_pack_start (GTK_BOX (hbox4), qif_date_picker, FALSE, FALSE, 5);
gtk_widget_set_usize (qif_date_picker, 140, -2);
qif_date_picker_menu = gtk_menu_new ();
glade_menuitem = gtk_menu_item_new_with_label (_("Autodetect "));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_date_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("MM/DD/YYYY"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_date_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("DD/MM/YYYY"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_date_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("YYYY/MM/DD"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_date_picker_menu), glade_menuitem);
glade_menuitem = gtk_menu_item_new_with_label (_("YYYY/DD/MM"));
gtk_widget_show (glade_menuitem);
gtk_menu_append (GTK_MENU (qif_date_picker_menu), glade_menuitem);
gtk_option_menu_set_menu (GTK_OPTION_MENU (qif_date_picker), qif_date_picker_menu);
hbox6 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox6);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "hbox6", hbox6,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox6);
gtk_box_pack_start (GTK_BOX (vbox1), hbox6, TRUE, TRUE, 5);
file_select_btn = gtk_button_new_with_label (_("Select file"));
gtk_widget_ref (file_select_btn);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "file_select_btn", file_select_btn,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (file_select_btn);
gtk_box_pack_start (GTK_BOX (hbox6), file_select_btn, TRUE, FALSE, 3);
gtk_widget_set_usize (file_select_btn, 125, -2);
add_file_button = gtk_button_new_with_label (_("Load file"));
gtk_widget_ref (add_file_button);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "add_file_button", add_file_button,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (add_file_button);
gtk_box_pack_start (GTK_BOX (hbox6), add_file_button, TRUE, FALSE, 0);
gtk_widget_set_usize (add_file_button, 125, -2);
label69 = gtk_label_new (_("Files"));
gtk_widget_ref (label69);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label69", label69,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label69);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label69);
scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_ref (scrolledwindow2);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "scrolledwindow2", scrolledwindow2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (scrolledwindow2);
gtk_container_add (GTK_CONTAINER (notebook1), scrolledwindow2);
account_page_list = gtk_clist_new (4);
gtk_widget_ref (account_page_list);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "account_page_list", account_page_list,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (account_page_list);
gtk_container_add (GTK_CONTAINER (scrolledwindow2), account_page_list);
gtk_clist_set_column_width (GTK_CLIST (account_page_list), 0, 116);
gtk_clist_set_column_width (GTK_CLIST (account_page_list), 1, 80);
gtk_clist_set_column_width (GTK_CLIST (account_page_list), 2, 204);
gtk_clist_set_column_width (GTK_CLIST (account_page_list), 3, 80);
gtk_clist_column_titles_show (GTK_CLIST (account_page_list));
label682 = gtk_label_new (_("QIF Account"));
gtk_widget_ref (label682);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label682", label682,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label682);
gtk_clist_set_column_widget (GTK_CLIST (account_page_list), 0, label682);
label683 = gtk_label_new (_("Transactions"));
gtk_widget_ref (label683);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label683", label683,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label683);
gtk_clist_set_column_widget (GTK_CLIST (account_page_list), 1, label683);
label684 = gtk_label_new (_("GNUCash Account Name"));
gtk_widget_ref (label684);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label684", label684,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label684);
gtk_clist_set_column_widget (GTK_CLIST (account_page_list), 2, label684);
label685 = gtk_label_new (_("Type"));
gtk_widget_ref (label685);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label685", label685,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label685);
gtk_clist_set_column_widget (GTK_CLIST (account_page_list), 3, label685);
label2 = gtk_label_new (_("Accounts"));
gtk_widget_ref (label2);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label2", label2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label2);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label2);
scrolledwindow3 = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_ref (scrolledwindow3);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "scrolledwindow3", scrolledwindow3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (scrolledwindow3);
gtk_container_add (GTK_CONTAINER (notebook1), scrolledwindow3);
category_page_list = gtk_clist_new (4);
gtk_widget_ref (category_page_list);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "category_page_list", category_page_list,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (category_page_list);
gtk_container_add (GTK_CONTAINER (scrolledwindow3), category_page_list);
gtk_clist_set_column_width (GTK_CLIST (category_page_list), 0, 117);
gtk_clist_set_column_width (GTK_CLIST (category_page_list), 1, 80);
gtk_clist_set_column_width (GTK_CLIST (category_page_list), 2, 204);
gtk_clist_set_column_width (GTK_CLIST (category_page_list), 3, 80);
gtk_clist_column_titles_show (GTK_CLIST (category_page_list));
label686 = gtk_label_new (_("QIF Category"));
gtk_widget_ref (label686);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label686", label686,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label686);
gtk_clist_set_column_widget (GTK_CLIST (category_page_list), 0, label686);
label687 = gtk_label_new (_("Transactions"));
gtk_widget_ref (label687);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label687", label687,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label687);
gtk_clist_set_column_widget (GTK_CLIST (category_page_list), 1, label687);
label688 = gtk_label_new (_("GNUCash Account Name"));
gtk_widget_ref (label688);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label688", label688,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label688);
gtk_clist_set_column_widget (GTK_CLIST (category_page_list), 2, label688);
label689 = gtk_label_new (_("Type"));
gtk_widget_ref (label689);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "label689", label689,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label689);
gtk_clist_set_column_widget (GTK_CLIST (category_page_list), 3, label689);
foo6868 = gtk_label_new (_("Categories"));
gtk_widget_ref (foo6868);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "foo6868", foo6868,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (foo6868);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 2), foo6868);
dialog_action_area2 = GNOME_DIALOG (QIF_File_Import_Dialog)->action_area;
gtk_object_set_data (GTK_OBJECT (QIF_File_Import_Dialog), "dialog_action_area2", dialog_action_area2);
gtk_widget_show (dialog_action_area2);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area2), GTK_BUTTONBOX_SPREAD);
gtk_button_box_set_spacing (GTK_BUTTON_BOX (dialog_action_area2), 8);
gnome_dialog_append_button (GNOME_DIALOG (QIF_File_Import_Dialog), GNOME_STOCK_BUTTON_OK);
button2 = g_list_last (GNOME_DIALOG (QIF_File_Import_Dialog)->buttons)->data;
gtk_widget_ref (button2);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "button2", button2,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button2);
GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
gnome_dialog_append_button (GNOME_DIALOG (QIF_File_Import_Dialog), GNOME_STOCK_BUTTON_CANCEL);
button3 = g_list_last (GNOME_DIALOG (QIF_File_Import_Dialog)->buttons)->data;
gtk_widget_ref (button3);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "button3", button3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button3);
GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);
gnome_dialog_append_button (GNOME_DIALOG (QIF_File_Import_Dialog), GNOME_STOCK_BUTTON_HELP);
button4 = g_list_last (GNOME_DIALOG (QIF_File_Import_Dialog)->buttons)->data;
gtk_widget_ref (button4);
gtk_object_set_data_full (GTK_OBJECT (QIF_File_Import_Dialog), "button4", button4,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button4);
GTK_WIDGET_SET_FLAGS (button4, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (selected_file_list), "select_child",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_select_loaded_file_cb),
QIF_File_Import_Dialog);
gtk_signal_connect (GTK_OBJECT (file_select_btn), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_select_file_cb),
QIF_File_Import_Dialog);
gtk_signal_connect (GTK_OBJECT (add_file_button), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_load_file_cb),
QIF_File_Import_Dialog);
gtk_signal_connect (GTK_OBJECT (account_page_list), "select_row",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_account_line_select_cb),
NULL);
gtk_signal_connect (GTK_OBJECT (category_page_list), "select_row",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_category_line_select_cb),
NULL);
gtk_signal_connect (GTK_OBJECT (button2), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_ok_cb),
QIF_File_Import_Dialog);
gtk_signal_connect (GTK_OBJECT (button3), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_cancel_cb),
QIF_File_Import_Dialog);
gtk_signal_connect (GTK_OBJECT (button4), "clicked",
GTK_SIGNAL_FUNC (gnc_ui_qif_import_help_cb),
QIF_File_Import_Dialog);
gtk_widget_grab_default (qif_filename_entry);
return QIF_File_Import_Dialog;
}

View File

@ -0,0 +1,5 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
GtkWidget* create_QIF_File_Import_Dialog (void);

View File

@ -0,0 +1,143 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <gnome.h>
#include "glade-support-account-picker.h"
/* This is an internally used function to create pixmaps. */
static GtkWidget* create_dummy_pixmap (GtkWidget *widget,
gboolean gnome_pixmap);
GtkWidget*
lookup_widget (GtkWidget *widget,
const gchar *widget_name)
{
GtkWidget *parent, *found_widget;
for (;;)
{
if (GTK_IS_MENU (widget))
parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
else
parent = widget->parent;
if (parent == NULL)
break;
widget = parent;
}
found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
widget_name);
if (!found_widget)
g_warning ("Widget not found: %s", widget_name);
return found_widget;
}
/* This is a dummy pixmap we use when a pixmap can't be found. */
static char *dummy_pixmap_xpm[] = {
/* columns rows colors chars-per-pixel */
"1 1 1 1",
" c None",
/* pixels */
" ",
" "
};
/* This is an internally used function to create pixmaps. */
static GtkWidget*
create_dummy_pixmap (GtkWidget *widget,
gboolean gnome_pixmap)
{
GdkColormap *colormap;
GdkPixmap *gdkpixmap;
GdkBitmap *mask;
GtkWidget *pixmap;
if (gnome_pixmap)
{
return gnome_pixmap_new_from_xpm_d (dummy_pixmap_xpm);
}
colormap = gtk_widget_get_colormap (widget);
gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
NULL, dummy_pixmap_xpm);
if (gdkpixmap == NULL)
g_error ("Couldn't create replacement pixmap.");
pixmap = gtk_pixmap_new (gdkpixmap, mask);
gdk_pixmap_unref (gdkpixmap);
gdk_bitmap_unref (mask);
return pixmap;
}
/* This is an internally used function to create pixmaps. */
GtkWidget*
create_pixmap (GtkWidget *widget,
const gchar *filename,
gboolean gnome_pixmap)
{
GtkWidget *pixmap;
GdkColormap *colormap;
GdkPixmap *gdkpixmap;
GdkBitmap *mask;
gchar *pathname;
pathname = gnome_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return create_dummy_pixmap (widget, gnome_pixmap);
}
if (gnome_pixmap)
{
pixmap = gnome_pixmap_new_from_file (pathname);
g_free (pathname);
return pixmap;
}
colormap = gtk_widget_get_colormap (widget);
gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
NULL, pathname);
if (gdkpixmap == NULL)
{
g_warning (_("Couldn't create pixmap from file: %s"), pathname);
g_free (pathname);
return create_dummy_pixmap (widget, gnome_pixmap);
}
g_free (pathname);
pixmap = gtk_pixmap_new (gdkpixmap, mask);
gdk_pixmap_unref (gdkpixmap);
gdk_bitmap_unref (mask);
return pixmap;
}
/* This is an internally used function to create imlib images. */
GdkImlibImage*
create_image (const gchar *filename)
{
GdkImlibImage *image;
gchar *pathname;
pathname = gnome_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
image = gdk_imlib_load_image (pathname);
g_free (pathname);
return image;
}

View File

@ -0,0 +1,34 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#include <gnome.h>
/*
* Public Functions.
*/
/*
* This function returns a widget in a component created by Glade.
* Call it with the toplevel widget in the component (i.e. a window/dialog),
* or alternatively any widget in the component, and the name of the widget
* you want returned.
*/
GtkWidget* lookup_widget (GtkWidget *widget,
const gchar *widget_name);
/* get_widget() is deprecated. Use lookup_widget instead. */
#define get_widget lookup_widget
/*
* Private Functions.
*/
/* This is used to create the pixmaps in the interface. */
GtkWidget* create_pixmap (GtkWidget *widget,
const gchar *filename,
gboolean gnome_pixmap);
GdkImlibImage* create_image (const gchar *filename);

View File

@ -0,0 +1,143 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <gnome.h>
#include "glade-support-qif-import.h"
/* This is an internally used function to create pixmaps. */
static GtkWidget* create_dummy_pixmap (GtkWidget *widget,
gboolean gnome_pixmap);
GtkWidget*
lookup_widget (GtkWidget *widget,
const gchar *widget_name)
{
GtkWidget *parent, *found_widget;
for (;;)
{
if (GTK_IS_MENU (widget))
parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
else
parent = widget->parent;
if (parent == NULL)
break;
widget = parent;
}
found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
widget_name);
if (!found_widget)
g_warning ("Widget not found: %s", widget_name);
return found_widget;
}
/* This is a dummy pixmap we use when a pixmap can't be found. */
static char *dummy_pixmap_xpm[] = {
/* columns rows colors chars-per-pixel */
"1 1 1 1",
" c None",
/* pixels */
" ",
" "
};
/* This is an internally used function to create pixmaps. */
static GtkWidget*
create_dummy_pixmap (GtkWidget *widget,
gboolean gnome_pixmap)
{
GdkColormap *colormap;
GdkPixmap *gdkpixmap;
GdkBitmap *mask;
GtkWidget *pixmap;
if (gnome_pixmap)
{
return gnome_pixmap_new_from_xpm_d (dummy_pixmap_xpm);
}
colormap = gtk_widget_get_colormap (widget);
gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
NULL, dummy_pixmap_xpm);
if (gdkpixmap == NULL)
g_error ("Couldn't create replacement pixmap.");
pixmap = gtk_pixmap_new (gdkpixmap, mask);
gdk_pixmap_unref (gdkpixmap);
gdk_bitmap_unref (mask);
return pixmap;
}
/* This is an internally used function to create pixmaps. */
GtkWidget*
create_pixmap (GtkWidget *widget,
const gchar *filename,
gboolean gnome_pixmap)
{
GtkWidget *pixmap;
GdkColormap *colormap;
GdkPixmap *gdkpixmap;
GdkBitmap *mask;
gchar *pathname;
pathname = gnome_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return create_dummy_pixmap (widget, gnome_pixmap);
}
if (gnome_pixmap)
{
pixmap = gnome_pixmap_new_from_file (pathname);
g_free (pathname);
return pixmap;
}
colormap = gtk_widget_get_colormap (widget);
gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
NULL, pathname);
if (gdkpixmap == NULL)
{
g_warning (_("Couldn't create pixmap from file: %s"), pathname);
g_free (pathname);
return create_dummy_pixmap (widget, gnome_pixmap);
}
g_free (pathname);
pixmap = gtk_pixmap_new (gdkpixmap, mask);
gdk_pixmap_unref (gdkpixmap);
gdk_bitmap_unref (mask);
return pixmap;
}
/* This is an internally used function to create imlib images. */
GdkImlibImage*
create_image (const gchar *filename)
{
GdkImlibImage *image;
gchar *pathname;
pathname = gnome_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
image = gdk_imlib_load_image (pathname);
g_free (pathname);
return image;
}

View File

@ -0,0 +1,34 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#include <gnome.h>
/*
* Public Functions.
*/
/*
* This function returns a widget in a component created by Glade.
* Call it with the toplevel widget in the component (i.e. a window/dialog),
* or alternatively any widget in the component, and the name of the widget
* you want returned.
*/
GtkWidget* lookup_widget (GtkWidget *widget,
const gchar *widget_name);
/* get_widget() is deprecated. Use lookup_widget instead. */
#define get_widget lookup_widget
/*
* Private Functions.
*/
/* This is used to create the pixmaps in the interface. */
GtkWidget* create_pixmap (GtkWidget *widget,
const gchar *filename,
gboolean gnome_pixmap);
GdkImlibImage* create_image (const gchar *filename);

View File

@ -1,6 +1,9 @@
/********************************************************************\
* window-html -- an html window for gnucash. *
* Copyright (C) 1997 Robin D. Clark *
* Copyright (C) 1998 Linas Vepstas *
* Copyright (C) 1999 Jeremy Collins ( gtk-xmhtml port ) *
* Copyright (C) 2000 Linas Vepstas *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *

View File

@ -45,6 +45,7 @@
#include "account-tree.h"
#include "dialog-transfer.h"
#include "dialog-edit.h"
#include "dialog-qif-import.h"
#include "Scrub.h"
#include "util.h"
#include "gnc.h"

View File

@ -45,15 +45,14 @@
(define (gnc:extensions-menu-setup win)
(define menu (gnc:make-menu "Extensions" (list "_Settings")))
(define export-item
(gnc:make-menu-item "Export data as text (Danger: Unfinished)"
"Export data as text."
(list "Extensions" "")
(lambda () (gnc:main-win-export-data-as-text win))))
(define qif-item
(gnc:make-menu-item "QIF File Import (Danger: Unfinished)"
"Import QIF File - Scripted in Guile."
@ -83,6 +82,7 @@
(gnc:hook-add-dangler gnc:*main-window-opened-hook*
gnc:extensions-menu-setup))
;; Automatically pick accelerators for menu names
(define (gnc:new-menu-namer)

View File

@ -17,10 +17,17 @@
(gnc:depend "doc.scm")
(gnc:depend "extensions.scm")
(gnc:depend "text-export.scm")
(gnc:depend "importqif.scm")
; (gnc:depend "importqif.scm")
(gnc:depend "report.scm")
(gnc:depend "report/report-list.scm")
(gnc:config-var-value-set! gnc:*load-path* #f
(cons (string-append gnc:_share-dir-default_
"/scm/qif-import")
(gnc:config-var-value-get gnc:*load-path*)))
(gnc:depend "qif-import.scm")
;; Load the system configs
(if (not (gnc:load-system-config-if-needed))
(gnc:shutdown 1))

View File

@ -0,0 +1,264 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-dialog-utils.scm
;;; build qif->gnc account maps and put them in a displayable
;;; form.
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "qif-dialog-utils.scm")
(define (qif-dialog:munge-account-mapping old-map new-info)
(let ((new-name (car new-info))
(new-type (cadr new-info))
(new-descript (caddr new-info)))
(list-set! old-map 1 new-name)
(list-set! old-map 2 new-type)
(cond ((qif-cat? (list-ref old-map 5))
(qif-cat:set-description! (list-ref old-map 5) new-descript))
((qif-acct? (list-ref old-map 5))
(qif-acct:set-description! (list-ref old-map 5) new-descript))
(#t
(list-set! old-map 5 new-descript)))))
;; the account-display is a 3-columned list of accounts in the QIF
;; import dialog (the "Account" page of the notebook). Column 1 is
;; the account name in the QIF file, column 2 is the number of QIF
;; xtns with that account name, and column 3 is the guess for the
;; translation. Sorted on # transactions, then alpha.
(define (qif-dialog:make-account-display qif-files gnc-acct-info)
(let ((acct-hash (make-hash-table 20))
(retval '()))
;; we want to make two passes here. The first pass picks the
;; explicit Account descriptions and implicit "this" description
;; out of each file. These are the best sources of info because
;; we will have types and so on for them. The second pass picks
;; out account-style L fields and investment security names from
;; the transactions. Hopefully 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.
(for-each
(lambda (file)
;; first, get the explicit account references.
(for-each
(lambda (acct)
(if (not (hash-ref acct-hash (qif-acct:name acct)))
(hash-set!
acct-hash (qif-acct:name acct)
(append
(qif-import:guess-acct (qif-acct:name acct)
(list (qif-acct:type acct))
gnc-acct-info)
(list 0 acct)))))
(qif-file:accounts file))
;; then make an implicit account entry for the file
(if (and (qif-file:account file)
(qif-file:account-type file))
; (not (eq? (qif-file:account-type file) GNC-STOCK-TYPE)))
(let ((entry (hash-ref acct-hash (qif-file:account file))))
(if entry
;; increment the xtn count in place
(list-set! entry 4
(+ (list-ref entry 4)
(length (qif-file:xtns file))))
;; make a new hash table entry for the account
;; make it a Bank account by default.
(hash-set!
acct-hash (qif-file:account file)
(append (qif-import:guess-acct
(qif-file:account file)
(list GNC-BANK-TYPE
GNC-CCARD-TYPE)
gnc-acct-info)
(list
(length (qif-file:xtns file))
#f)))))))
qif-files)
;; now make the second pass through the files, looking at the
;; transactions. Hopefully the accounts are all there already.
;; stock accounts can have both a category/account and another
;; account ref from the security name.
(for-each
(lambda (file)
(for-each
(lambda (xtn)
(let ((bank-xtn? (qif-xtn:bank-xtn? xtn))
(stock-acct (qif-xtn:security-name xtn))
(entry #f))
(if (not bank-xtn?)
(begin
(set! entry (hash-ref acct-hash stock-acct))
(if entry
(list-set! entry 4
(+ 1 (list-ref entry 4)))
(hash-set! acct-hash stock-acct
(append (qif-import:guess-acct
stock-acct
(list GNC-STOCK-TYPE
GNC-MUTUAL-TYPE)
gnc-acct-info)
(list 1 xtn)))))))
;; iterate over the splits doing the same thing.
(for-each
(lambda (split)
(let ((xtn-is-acct (qif-split:category-is-account? split))
(xtn-acct #f)
(entry #f))
(if xtn-is-acct
(begin
(set! xtn-acct (qif-split:category split))
(set! entry (hash-ref acct-hash xtn-acct))
(if entry
(list-set! entry 4
(+ 1 (list-ref entry 4)))
(hash-set! acct-hash xtn-acct
(append (qif-import:guess-acct
xtn-acct
(list
GNC-BANK-TYPE
GNC-CCARD-TYPE
GNC-STOCK-TYPE)
gnc-acct-info)
(list 1 #f))))))))
(qif-xtn:splits xtn)))
(qif-file:xtns file)))
qif-files)
;; now that the hash table is filled, make the display list
(for-each
(lambda (bin)
(for-each
(lambda (elt)
(if (> (list-ref (cdr elt) 4) 0)
(set! retval
(cons (cdr elt) retval))))
bin))
(vector->list acct-hash))
(list-set! gnc-acct-info 1 acct-hash)
;; sort by number of transactions with that account so the
;; most important are at the top
; (set! retval (sort-list retval
; (lambda (a b)
; (or
; (> (list-ref a 4) (list-ref b 4))
; (and
; (eq? (list-ref a 4) (list-ref b 4))
; (string<? (car a) (car b)))))))
retval))
;; the category display is similar to the Account display.
;; QIF category name, xtn count, then GNUcash account.
(define (qif-dialog:make-category-display qif-files gnc-acct-info)
(let ((cat-hash (make-hash-table 20))
(retval '()))
;; get the Cat entries from each file
(for-each
(lambda (file)
(for-each
(lambda (cat)
(if (not (hash-ref cat-hash (qif-cat:name cat)))
(begin
(hash-set! cat-hash
(qif-cat:name cat)
(append
(qif-import:guess-acct
(qif-cat:name cat)
(if (qif-cat:expense-cat cat)
(list GNC-EXPENSE-TYPE)
(list GNC-INCOME-TYPE))
gnc-acct-info)
(list 0 cat))))))
(qif-file:cats file)))
qif-files)
;; now look at every transaction and increment the count
;; in the account slot if the string matches, or make a
;; new hash reference if not.
(for-each
(lambda (qif-file)
(for-each
(lambda (xtn)
;; iterate over the splits
(for-each
(lambda (split)
(let ((xtn-is-acct (qif-split:category-is-account? split))
(xtn-cat #f)
(entry #f))
(if (not xtn-is-acct)
(begin
(set! xtn-cat (qif-split:category split))
(set! entry (hash-ref cat-hash xtn-cat))
(if entry
(list-set! entry 4
(+ 1 (list-ref entry 4)))
(hash-set! cat-hash xtn-cat
(append (qif-import:guess-acct
xtn-cat
(if (> (qif-split:amount split) 0)
(list GNC-INCOME-TYPE)
(list GNC-EXPENSE-TYPE))
gnc-acct-info)
(list 1 #f))))))))
(qif-xtn:splits xtn)))
(qif-file:xtns qif-file)))
qif-files)
;; now that the hash table is filled, make the display list
(for-each
(lambda (bin)
(for-each
(lambda (elt)
(if (> (list-ref (cdr elt) 4) 0)
(set! retval (cons (cdr elt) retval))))
bin))
(vector->list cat-hash))
(list-set! gnc-acct-info 2 cat-hash)
;; sort by number of transactions with that account so the
;; most important are at the top
; (set! retval (sort-list retval
; (lambda (a b)
; (or
; (> (list-ref a 4) (list-ref b 4))
; (and
; (eq? (list-ref a 4) (list-ref b 4))
; (string<? (car a) (car b)))))))
retval))
(define (qif-dialog:qif-file-loaded? filename list-of-files)
(let ((status (map
(lambda (file)
(string=? filename (qif-file:path file)))
list-of-files)))
(if (memq #t status)
#t
#f)))
(define (qif-dialog:unload-qif-file filename list-of-files)
(delq #f
(map
(lambda (file)
(if (string=? filename (qif-file:path file))
#f
file))
list-of-files)))

View File

@ -0,0 +1,434 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-file.scm
;;; read a QIF file into a <qif-file> object
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:depend "qif-objects.scm")
(gnc:depend "qif-parse.scm")
(gnc:depend "qif-utils.scm")
(gnc:support "qif-file.scm")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-file:read-file self path
;; suck in all the transactions; if necessary, determine [guess]
;; radix format first.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:read-file self path)
(qif-file:set-path! self path)
(let ((qstate-type #f)
(current-xtn #f)
(current-split #f)
(default-split #f)
(first-xtn #f)
(line #f)
(tag #f)
(value #f)
(heinous-error #f))
(with-input-from-file path
(lambda ()
;; loop over lines
(let line-loop ()
(set! line (read-line))
(if (and
(not (eof-object? line))
(>= (string-length line) 1))
(begin
;; pick the 1-char tag off from the remainder of the line
(set! tag (string-ref line 0))
(set! value (substring line 1 (string-length line)))
;; now do something with the line
(cond
;; the type switcher.
((eq? tag #\!)
(set! qstate-type (qif-file:parse-bang-field self value))
(cond ((or (eq? qstate-type 'type:bank)
(eq? qstate-type 'type:cash)
(eq? qstate-type 'type:ccard)
(eq? qstate-type 'type:invst)
(eq? qstate-type '#{type:oth\ a}#)
(eq? qstate-type '#{type:oth\ l}#))
(set! current-xtn (make-qif-xtn))
(set! default-split (make-qif-split))
(qif-split:set-category! default-split "")
(qif-file:set-account-type!
self (qif-file:state-to-account-type
self qstate-type))
(set! first-xtn #t))
((eq? qstate-type 'type:class)
(set! current-xtn (make-qif-class)))
((eq? qstate-type 'type:cat)
(set! current-xtn (make-qif-cat)))
((eq? qstate-type 'account)
(set! current-xtn (make-qif-acct)))
(#t
(display "qif-file:read-file can't handle ")
(write qstate-type)
(display " transactions yet.")
(newline))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; account transactions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((or (eq? qstate-type 'type:bank)
(eq? qstate-type 'type:cash)
(eq? qstate-type 'type:ccard)
(eq? qstate-type 'type:invst)
(eq? qstate-type '#{type:oth\ a}#)
(eq? qstate-type '#{type:oth\ l}#))
(cond
;; D : transaction date
((eq? tag #\D)
(qif-xtn:set-date! current-xtn
(qif-file:parse-date self value)))
;; T : total amount
((eq? tag #\T)
(qif-split:set-amount! default-split
(qif-file:parse-value self value)))
;; P : payee
((eq? tag #\P)
(qif-xtn:set-payee! current-xtn
(qif-file:parse-string self value)))
;; A : address
;; multiple "A" lines are appended together with
;; newlines; some Quicken files have a lot of
;; A lines.
((eq? tag #\A)
(qif-xtn:set-address!
current-xtn
(let ((current (qif-xtn:address current-xtn)))
(if (not (string? current))
(set! current ""))
(string-append
current "\n"
(qif-file:parse-string self value)))))
;; N : check number / transaction number /xtn direction
;; this could be a number or a string; no point in
;; keeping it numeric just yet.
((eq? tag #\N)
(qif-xtn:set-number!
current-xtn (qif-file:parse-string self value)))
;; C : cleared flag
((eq? tag #\C)
(qif-xtn:set-cleared!
current-xtn (qif-file:parse-cleared-field self value)))
;; M : memo
((eq? tag #\M)
(qif-split:set-memo! default-split
(qif-file:parse-string self value)))
;; I : share price (stock transactions)
((eq? tag #\I)
(qif-xtn:set-share-price!
current-xtn (qif-file:parse-value self value)))
;; Q : share price (stock transactions)
((eq? tag #\Q)
(qif-xtn:set-num-shares!
current-xtn (qif-file:parse-value self value))
(qif-xtn:set-bank-xtn?! current-xtn #f))
;; Y : name of security (stock transactions)
((eq? tag #\Y)
(qif-xtn:set-security-name!
current-xtn (qif-file:parse-string self value)))
;; O : adjustment (stock transactions)
((eq? tag #\O)
(qif-xtn:set-adjustment!
current-xtn (qif-file:parse-value self value)))
;; L : category
((eq? tag #\L)
(qif-split:set-category!
default-split (qif-file:parse-string self value)))
;; S : split category
((eq? tag #\S)
(set! current-split (make-qif-split))
(qif-split:set-category!
current-split (qif-file:parse-string self value))
(qif-xtn:set-splits!
current-xtn
(cons current-split (qif-xtn:splits current-xtn))))
;; E : split memo (?)
((eq? tag #\E)
(qif-split:set-memo!
current-split (qif-file:parse-string self value)))
;; $ : split amount (if there are splits)
((eq? tag #\$)
;; if this is 'Type:Invst, I can't figure out
;; what the $ signifies. I'll do it later.
(if (eq? qstate-type 'type:bank)
(qif-split:set-amount!
current-split (qif-file:parse-value self value))))
;; ^ : end-of-record
((eq? tag #\^)
(if (and (qif-xtn:date current-xtn)
(qif-split:amount default-split))
(begin
(if (null? (qif-xtn:splits current-xtn))
(qif-xtn:set-splits! current-xtn
(list default-split)))
(qif-file:add-xtn! self current-xtn))
(begin
(display "qif-file:read-file : discarding xtn")
(newline)
(qif-xtn:print current-xtn)))
(if (and first-xtn
(string? (qif-xtn:payee current-xtn))
(string=? (qif-xtn:payee current-xtn)
"Opening Balance")
(eq? (length (qif-xtn:splits current-xtn)) 1)
(qif-split:category-is-account?
(car (qif-xtn:splits current-xtn))))
(begin
(qif-file:set-account!
self (qif-split:category
(car (qif-xtn:splits current-xtn))))
(qif-split:set-category!
(car (qif-xtn:splits current-xtn))
"Opening Balance")))
;; some special love for stock transactions
(if (and (qif-xtn:security-name current-xtn)
(string? (qif-xtn:number current-xtn)))
(begin
(cond
((and
(or (string=? (qif-xtn:number current-xtn)
"ReinvDiv")
(string=? (qif-xtn:number current-xtn)
"ReinvLg")
(string=? (qif-xtn:number current-xtn)
"ReinvSh")
(string=? (qif-xtn:number current-xtn)
"Div"))
(string=?
"" (qif-split:category
(car
(qif-xtn:splits current-xtn)))))
(qif-split:set-category!
(car (qif-xtn:splits current-xtn))
"Dividend")
;; KLUDGE! for brokerage accounts
;; where Dividend pays into the
;; brokerage account.
(if (and (qif-xtn:bank-xtn? current-xtn)
(string?
(qif-xtn:security-name
current-xtn)))
(qif-xtn:set-payee!
current-xtn (qif-xtn:security-name
current-xtn))))
((or (string=? (qif-xtn:number current-xtn)
"SellX")
(string=? (qif-xtn:number current-xtn)
"Sell"))
(qif-xtn:set-num-shares!
current-xtn
(string-append
"-" (qif-xtn:num-shares current-xtn)))))))
(set! first-xtn #f)
(set! current-xtn (make-qif-xtn))
(set! default-split (make-qif-split)))
(#t
(display "qif-file:read-file : unknown Bank slot ")
(display tag) (newline))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Class transactions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((eq? qstate-type 'type:class)
(cond
;; N : name
((eq? tag #\N)
(qif-class:set-name! current-xtn
(qif-file:parse-string self value)))
;; D : description
((eq? tag #\D)
(qif-class:set-description!
current-xtn (qif-file:parse-string self value)))
;; end-of-record
((eq? tag #\^)
(qif-file:add-class! self current-xtn)
; (qif-class:print current-xtn)
(set! current-xtn (make-qif-class)))
(#t
(display "qif-file:read-file : unknown Class slot ")
(display tag) (newline))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Account definitions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((eq? qstate-type 'account)
(cond
((eq? tag #\N)
(qif-acct:set-name! current-xtn
(qif-file:parse-string self value)))
((eq? tag #\D)
(qif-acct:set-description!
current-xtn (qif-file:parse-string self value)))
((eq? tag #\T)
(qif-acct:set-type!
current-xtn (qif-file:parse-acct-type self value)))
((eq? tag #\L)
(qif-acct:set-limit!
current-xtn (qif-file:parse-value self value)))
((eq? tag #\^)
(qif-file:add-account! self current-xtn)
; (qif-acct:print current-xtn)
(set! current-xtn (make-qif-acct)))
(#t
(display "qif-file:read-file : unknown Account slot ")
(display tag) (newline))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Category (Cat) transactions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
((eq? qstate-type 'type:cat)
(cond
;; N : category name
((eq? tag #\N)
(qif-cat:set-name! current-xtn
(qif-file:parse-string self value)))
;; D : category description
((eq? tag #\D)
(qif-cat:set-description! current-xtn
(qif-file:parse-string
self value)))
;; E : is this a taxable category?
((eq? tag #\T)
(qif-cat:set-taxable! current-xtn #t))
;; E : is this an expense category?
((eq? tag #\E)
(qif-cat:set-expense-cat! current-xtn #t))
;; I : is this an income category?
((eq? tag #\I)
(qif-cat:set-income-cat! current-xtn #t))
;; R : what is the tax rate (from some table?
;; seems to be an integer)
((eq? tag #\R)
(qif-cat:set-tax-rate!
current-xtn (qif-file:parse-value self value)))
;; B : budget amount. not really supported.
((eq? tag #\B)
(qif-cat:set-budget-amt!
current-xtn (qif-file:parse-value self value)))
;; end-of-record
((eq? tag #\^)
(qif-file:add-cat! self current-xtn)
; (qif-cat:print current-xtn)
(set! current-xtn (make-qif-cat)))
(#t
(display "qif-file:read-file : unknown Cat slot ")
(display tag) (newline))))
;; trying to sneak on by, eh?
(#t
(if (not qstate-type)
(begin
(display "line = ") (display line) (newline)
(display "qif-file:read-file : ")
(display "file does not appear to be a QIF file.")
(newline)
(set! heinous-error #t)))))
;; this is if we read a normal (non-null, non-eof) line...
(if (not heinous-error)
(line-loop)))
;; and this is if we read a null or eof line
(if (and (not heinous-error)
(not (eof-object? line)))
(line-loop))))))
(if (not heinous-error)
(begin
;; now that the file is read in, figure out if either
;; the date or radix format has made itself clear from the
;; values.
(if (and
(eq? (qif-file:radix-format self) 'unknown)
(not (eq? (qif-file:guessed-radix-format self) 'unknown))
(not (eq? (qif-file:guessed-radix-format self) 'inconsistent)))
(qif-file:set-radix-format!
self
(qif-file:guessed-radix-format self)))
(if (and
(eq? (qif-file:date-format self) 'unknown)
(not (eq? (qif-file:guessed-date-format self) 'unknown))
(not (eq? (qif-file:guessed-date-format self) 'inconsistent)))
(qif-file:set-date-format! self
(qif-file:guessed-date-format self)))
;; if the account hasn't been found from an Opening Balance line,
;; just set it to the filename and force the user to specify it.
(if (eq? 'unknown (qif-file:account self))
(qif-file:set-account!
self (qif-file:path-to-accountname self)))
;; reparse values and dates if we figured out the format.
(for-each
(lambda (xtn)
(qif-xtn:reparse xtn self))
(qif-file:xtns self))
(for-each
(lambda (cat)
(qif-cat:reparse cat self))
(qif-file:cats self))
(for-each
(lambda (acct)
(qif-acct:reparse acct self))
(qif-file:accounts self))
#t)
(begin
(display "There was a heinous error. Failed to read file.")
(newline)
#f))))

View File

@ -0,0 +1,281 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-guess-map.scm
;;; guess (or load from prefs) mappings from QIF cats/accts to gnc
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "qif-guess-map.scm")
(define GNC-BANK-TYPE 0)
(define GNC-CASH-TYPE 1)
(define GNC-ASSET-TYPE 2)
(define GNC-LIABILITY-TYPE 4)
(define GNC-CCARD-TYPE 3)
(define GNC-STOCK-TYPE 5)
(define GNC-MUTUAL-TYPE 6)
(define GNC-INCOME-TYPE 8)
(define GNC-EXPENSE-TYPE 9)
(define GNC-EQUITY-TYPE 10)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:load-map-prefs
;; load the saved mappings file, and make a table of all the
;; accounts with their full names and pointers for later
;; guessing of a mapping.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:load-map-prefs)
(define (extract-all-account-info agroup root-name)
(if (pointer-token-null? agroup)
'()
(let ((children (gnc:get-accounts agroup))
(children-list '())
(names '()))
;; convert an array object to a list
;; seems that equal? works as a predicate on pointer
;; equality.... that bugs me. the test is to weed out
;; all but immediate children.
(let loop ((count (pointer-array-length children)))
(if (> count 0)
(let ((acct (pointer-array-ref children (- count 1))))
(if (equal? agroup (gnc:account-get-parent acct))
(set! children-list
(cons acct
children-list)))
(loop (- count 1)))))
;; now descend the tree of child accounts.
(for-each
(lambda (child-acct)
(let* ((name (gnc:account-get-name child-acct))
(fullname
(if (string? root-name)
(string-append root-name ":" name)
name)))
(set! names
(append (cons (list name fullname child-acct)
(extract-all-account-info
(gnc:account-get-children child-acct)
fullname))
names))))
children-list)
names)))
;; we'll be returning a list of 3 elements:
;; - a list of all the known gnucash accounts in
;; (shortname fullname account) format.
;; - a hash of QIF account name to gnucash account info
;; - a hash of QIF category to gnucash account info
(let ((pref-filename (build-path (getenv "HOME")
".gnucash" "qif-accounts-map"))
(results '()))
;; first, read the account map and category map from the
;; user's qif-accounts-map file.
(if (access? pref-filename R_OK)
(with-input-from-file pref-filename
(lambda ()
(let ((qif-account-hash #f)
(qif-cat-hash #f))
(set! qif-account-hash (read))
(if (not (vector? qif-account-hash))
(set! qif-account-hash (make-hash-table 20)))
(set! qif-cat-hash (read))
(if (not (vector? qif-cat-hash))
(set! qif-cat-hash (make-hash-table 20)))
(set! results (list qif-account-hash qif-cat-hash)))))
(begin
(set! results (list (make-hash-table 20)
(make-hash-table 20)))))
;; now build the list of all known account names
(let* ((all-accounts (gnc:get-current-group))
(all-account-info (extract-all-account-info all-accounts #f)))
(set! results (cons all-account-info results)))
; (display " ** load prefs **")(newline)
; (write results)(newline)
results))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; dump the mapping hash tables to a file. The hash tables are
;; updated when the user clicks the big "OK" button on the dialog,
;; so your selections get lost if you do Cancel.
;; we initialize the number of transactions to 0 here so
;; bogus accounts don't get created if you have funny stuff
;; in your map.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:save-map-prefs prefs)
(let ((pref-filename (build-path (getenv "HOME")
".gnucash" "qif-accounts-map"))
(acct-map (cadr prefs))
(cat-map (caddr prefs)))
(for-each
(lambda (bin)
(for-each
(lambda (hashpair)
(list-set! (cdr hashpair) 4 0))
bin))
(vector->list acct-map))
(for-each
(lambda (bin)
(for-each
(lambda (hashpair)
(list-set! (cdr hashpair) 4 0))
bin))
(vector->list cat-map))
(with-output-to-file pref-filename
(lambda ()
(display ";;; qif-accounts-map") (newline)
(display ";;; automatically generated by GNUcash. DO NOT EDIT")
(newline)
(display ";;; map from QIF accounts to GNC accounts") (newline)
(write acct-map) (newline)
(display ";;; map from QIF categories to GNC accounts") (newline)
(write cat-map) (newline)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; here's where we do all the guessing. We really want to find the
;; match in the hash table, but failing that we guess intelligently
;; and then (failing that) not so intelligently. called in the
;; dialog routines to rebuild the category and account map pages.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; guess-acct
;; find an existing gnc acct of the right type and name, or
;; specify a type and name for a new one.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:guess-acct acct-name allowed-types gnc-map-info)
;; see if there's a saved mapping in the hash table or an
;; existing gnucash account with a name that could reasonably
;; be said to be the same name (i.e. ABC Bank == abc bank)
(let* ((mapped-gnc-acct
(or
;; best alternative: an entry in the map.
(hash-ref (cadr gnc-map-info) acct-name)
;; second choice: a "similar" account (close name,
;; same type, etc)
(qif-import:find-similar-acct acct-name allowed-types
gnc-map-info))))
(if mapped-gnc-acct
;; ok, we've found an existing account that
;; seems to work OK name-wise.
(begin
; (write mapped-gnc-acct) (newline)
(list acct-name
(list-ref mapped-gnc-acct 1)
(list-ref mapped-gnc-acct 2) #f))
;; we haven't found a match, so by default just create a new
;; one. Try to put the new account in a similar place in
;; the hierarchy if there is one.
(let ((new-acct-info
(qif-import:find-new-acct acct-name allowed-types
gnc-map-info)))
(list acct-name
(car new-acct-info)
(cadr new-acct-info) #t)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:find-similar-acct
;; guess a translation from QIF info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:find-similar-acct qif-acct-name allowed-types gnc-map-info)
(let* ((same-type-accts '())
(matching-name-accts '())
(retval #f))
(for-each
(lambda (gnc-acct)
;; check against allowed-types
(let ((acct-matches? #f))
(for-each
(lambda (type)
(if (eq? type (gnc:account-get-type (caddr gnc-acct)))
(set! acct-matches? #t)))
allowed-types)
(if acct-matches?
(set! same-type-accts (cons gnc-acct same-type-accts)))))
(car gnc-map-info))
;; now find one in the same-type-list with a similar name.
(for-each
(lambda (gnc-acct)
(if (qif-import:possibly-matching-name?
qif-acct-name gnc-acct)
(set! matching-name-accts
(cons gnc-acct matching-name-accts))))
same-type-accts)
;; now we have either nothing, something, or too much :)
;; return the full-name of the first name-matching account
(if (not (null? matching-name-accts))
(set! retval (list qif-acct-name
(cadr (car matching-name-accts))
(gnc:account-get-type
(caddr (car matching-name-accts)))))
#f)
retval))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:possibly-matching-name? qif-acct gnc-acct
;; try various normalizations and permutations of the names
;; to see if they could be the same.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:possibly-matching-name? qif-acct-name gnc-acct)
(or
;; the QIF acct is the same name as the short name of the
;; gnc acct [ignoring case] (likely)
(string=? (string-downcase qif-acct-name)
(string-downcase (car gnc-acct)))
;; the QIF acct is the same name as the long name of the
;; gnc acct [ignoring case] (not so likely)
(string=? (string-downcase qif-acct-name)
(string-downcase (cadr gnc-acct)))
;; the QIF name is a substring of the gnc full name.
;; this happens if you have the same tree but a different
;; top-level structure. (i.e. expenses:tax vs. QIF tax)
(string-match (string-downcase qif-acct-name)
(string-downcase (cadr gnc-acct)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:find-new-acct
;; Come up with a logical name for a new account based on
;; the Quicken name and type of the account
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:find-new-acct qif-acct allowed-types gnc-map-info)
(cond ((and (string? qif-acct)
(string=? qif-acct "Opening Balance"))
(let ((existing-equity
(qif-import:find-similar-acct "Retained Earnings"
(list GNC-EQUITY-TYPE)
gnc-map-info)))
(if existing-equity
(cdr existing-equity)
(list "Retained Earnings" GNC-EQUITY-TYPE))))
((and (string? qif-acct)
(not (string=? qif-acct "")))
(list qif-acct (car allowed-types)))
(#t
(list "Unspecified" (car allowed-types)))))

View File

@ -0,0 +1,19 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-import.scm
;;; virtual loader for QIF import facility
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:depend "simple-obj.scm")
(gnc:depend "qif-objects.scm") ;; class definitions
(gnc:depend "qif-parse.scm") ;; string-to-value, date parsing
(gnc:depend "qif-utils.scm")
(gnc:depend "qif-file.scm") ;; actual file reading
(gnc:depend "qif-dialog-utils.scm") ;; build displays for dialog
(gnc:depend "qif-guess-map.scm") ;; build QIF->gnc acct mappings
(gnc:depend "qif-to-gnc.scm") ;; conv QIF xtns/acct to GNC xtns/acct
(gnc:support "qif-import.scm")

View File

@ -0,0 +1,542 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-objects.scm
;;; representations for parts of an imported Quicken file.
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:depend "simple-obj.scm")
(gnc:support "qif-objects.scm")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-file class
;; radix-format : one of 'decimal 'comma or 'unspecified
;; date-format : one of 'd-m-y, 'm-d-y, 'y-m-d, 'y-d-m, 'unspecified
;; currency : a string representing the file's currency unit
;; xtns : list of <qif-xtn>
;; accounts : list of <qif-acct>
;; cats : list of <qif-cat>
;; classes : list of <qif-class>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-file>
(make-simple-class
'qif-file
'(path ;; where file was loaded
account ;; guessed or specified
account-type ;; either GNC-BANK-TYPE or GNC-STOCK-TYPE
radix-format
guessed-radix-format
date-format
guessed-date-format
y2k-threshold
currency ;; this is a string.. no checking
xtns ;;
accounts
cats
classes)))
(define (qif-file? self)
(eq? (simple-obj-type self) 'qif-file))
(define (qif-file:path self)
(simple-obj-getter self <qif-file> 'path))
(define (qif-file:account self)
(simple-obj-getter self <qif-file> 'account))
(define (qif-file:set-account! self value)
(simple-obj-setter self <qif-file> 'account value))
(define (qif-file:account-type self)
(simple-obj-getter self <qif-file> 'account-type))
(define (qif-file:set-account-type! self value)
(simple-obj-setter self <qif-file> 'account-type value))
(define (qif-file:set-path! self value)
(simple-obj-setter self <qif-file> 'path value))
(define (qif-file:radix-format self)
(simple-obj-getter self <qif-file> 'radix-format))
(define (qif-file:set-radix-format! self value)
(simple-obj-setter self <qif-file> 'radix-format value))
(define (qif-file:guessed-radix-format self)
(simple-obj-getter self <qif-file> 'guessed-radix-format))
(define (qif-file:set-guessed-radix-format! self value)
(simple-obj-setter self <qif-file> 'guessed-radix-format value))
(define (qif-file:date-format self)
(simple-obj-getter self <qif-file> 'date-format))
(define (qif-file:set-date-format! self value)
(simple-obj-setter self <qif-file> 'date-format value))
(define (qif-file:guessed-date-format self)
(simple-obj-getter self <qif-file> 'guessed-date-format))
(define (qif-file:set-guessed-date-format! self value)
(simple-obj-setter self <qif-file> 'guessed-date-format value))
(define (qif-file:y2k-threshold self)
(simple-obj-getter self <qif-file> 'y2k-threshold))
(define (qif-file:set-y2k-threshold! self value)
(simple-obj-setter self <qif-file> 'y2k-threshold value))
(define (qif-file:currency self)
(simple-obj-getter self <qif-file> 'currency))
(define (qif-file:set-currency! self value)
(simple-obj-setter self <qif-file> 'currency value))
(define (qif-file:cats self)
(simple-obj-getter self <qif-file> 'cats))
(define (qif-file:set-cats! self value)
(simple-obj-setter self <qif-file> 'cats value))
(define (qif-file:classes self)
(simple-obj-getter self <qif-file> 'classes))
(define (qif-file:set-classes! self value)
(simple-obj-setter self <qif-file> 'classes value))
(define (qif-file:xtns self)
(simple-obj-getter self <qif-file> 'xtns))
(define (qif-file:set-xtns! self value)
(simple-obj-setter self <qif-file> 'xtns value))
(define (qif-file:accounts self)
(simple-obj-getter self <qif-file> 'accounts))
(define (qif-file:set-accounts! self value)
(simple-obj-setter self <qif-file> 'accounts value))
(define (make-qif-file account radix-format date-format currency)
(let ((self (make-simple-obj <qif-file>)))
(qif-file:set-account! self account)
(qif-file:set-radix-format! self radix-format)
(qif-file:set-guessed-radix-format! self radix-format)
(qif-file:set-date-format! self date-format)
(qif-file:set-guessed-date-format! self date-format)
(qif-file:set-currency! self currency)
(qif-file:set-y2k-threshold! self 50)
(qif-file:set-xtns! self '())
(qif-file:set-accounts! self '())
(qif-file:set-cats! self '())
(qif-file:set-classes! self '())
self))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-split class
;; this is for bank/ccard accounts only.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-split>
(make-simple-class
'qif-split
'(category class memo amount category-is-account? mark)))
(define (qif-split:category self)
(simple-obj-getter self <qif-split> 'category))
(define (qif-split:set-category! self value)
(let* ((cat-info
(qif-split:parse-category self value))
(cat-name (list-ref cat-info 0))
(is-account? (list-ref cat-info 1))
(class-name (list-ref cat-info 2)))
(simple-obj-setter self <qif-split> 'category cat-name)
(simple-obj-setter self <qif-split> 'class class-name)
(simple-obj-setter self <qif-split> 'category-is-account? is-account?)))
; (if (not is-account?)
; (simple-obj-setter self <qif-split> 'mark #t))))
(define (qif-split:class self)
(simple-obj-getter self <qif-split> 'class))
(define (qif-split:set-class! self value)
(simple-obj-setter self <qif-split> 'class value))
(define (qif-split:memo self)
(simple-obj-getter self <qif-split> 'memo))
(define (qif-split:set-memo! self value)
(simple-obj-setter self <qif-split> 'memo value))
(define (qif-split:amount self)
(simple-obj-getter self <qif-split> 'amount))
(define (qif-split:set-amount! self value)
(simple-obj-setter self <qif-split> 'amount value))
(define (qif-split:mark self)
(simple-obj-getter self <qif-split> 'mark))
(define (qif-split:set-mark! self value)
(simple-obj-setter self <qif-split> 'mark value))
(define (qif-split:category-is-account? self)
(simple-obj-getter self <qif-split> 'category-is-account?))
(define (qif-split:set-category-is-account?! self value)
(simple-obj-setter self <qif-split> 'category-is-account? value))
(define (make-qif-split)
(let ((self (make-simple-obj <qif-split>)))
(qif-split:set-category! self "")
self))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-xtn class
;; [D] date : parsed.
;; [P] payee : string
;; [N] number (check number, sell, or buy)
;; [C] cleared : parsed (x/X/*) ;
;; [T] amount : parsed, units are currency from <qif-file>.
;; [M] memo : string
;; [I] share price : parsed
;; [Q] number of shares
;; [Y] name of security
;; [O] adjustment (parsed)
;; [L] category : string
;; [S]/[E]/[$] splits : a list of <qif-split>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-xtn>
(make-simple-class
'qif-xtn
'(date payee address number cleared memo
share-price num-shares security-name adjustment
splits bank-xtn? mark)))
(define (qif-xtn? self)
(eq? (simple-obj-type self) 'qif-xtn))
(define (qif-xtn:date self)
(simple-obj-getter self <qif-xtn> 'date))
(define (qif-xtn:set-date! self value)
(simple-obj-setter self <qif-xtn> 'date value))
(define (qif-xtn:payee self)
(simple-obj-getter self <qif-xtn> 'payee))
(define (qif-xtn:set-payee! self value)
(simple-obj-setter self <qif-xtn> 'payee value))
(define (qif-xtn:address self)
(simple-obj-getter self <qif-xtn> 'address))
(define (qif-xtn:set-address! self value)
(simple-obj-setter self <qif-xtn> 'address value))
(define (qif-xtn:number self)
(simple-obj-getter self <qif-xtn> 'number))
(define (qif-xtn:set-number! self value)
(simple-obj-setter self <qif-xtn> 'number value))
(define (qif-xtn:cleared self)
(simple-obj-getter self <qif-xtn> 'cleared))
(define (qif-xtn:set-cleared! self value)
(simple-obj-setter self <qif-xtn> 'cleared value))
(define (qif-xtn:share-price self)
(simple-obj-getter self <qif-xtn> 'share-price))
(define (qif-xtn:set-share-price! self value)
(simple-obj-setter self <qif-xtn> 'share-price value))
(define (qif-xtn:num-shares self)
(simple-obj-getter self <qif-xtn> 'num-shares))
(define (qif-xtn:set-num-shares! self value)
(simple-obj-setter self <qif-xtn> 'num-shares value))
(define (qif-xtn:security-name self)
(simple-obj-getter self <qif-xtn> 'security-name))
(define (qif-xtn:set-security-name! self value)
(simple-obj-setter self <qif-xtn> 'security-name value))
(define (qif-xtn:adjustment self)
(simple-obj-getter self <qif-xtn> 'adjustment))
(define (qif-xtn:set-adjustment! self value)
(simple-obj-setter self <qif-xtn> 'adjustment value))
(define (qif-xtn:splits self)
(simple-obj-getter self <qif-xtn> 'splits))
(define (qif-xtn:set-splits! self value)
(simple-obj-setter self <qif-xtn> 'splits value))
(define (qif-xtn:mark self)
(simple-obj-getter self <qif-xtn> 'mark))
(define (qif-xtn:set-mark! self value)
(simple-obj-setter self <qif-xtn> 'mark value))
(define (qif-xtn:bank-xtn? self)
(simple-obj-getter self <qif-xtn> 'bank-xtn?))
(define (qif-xtn:set-bank-xtn?! self value)
(simple-obj-setter self <qif-xtn> 'bank-xtn? value))
(define (make-qif-xtn)
(let ((self (make-simple-obj <qif-xtn>)))
(qif-xtn:set-bank-xtn?! self #t)
(qif-xtn:set-mark! self #f)
(qif-xtn:set-splits! self '())
self))
(define (qif-xtn:reparse self qif-file)
;; share price
(if (string? (qif-xtn:share-price self))
(qif-xtn:set-share-price!
self
(qif-file:parse-value qif-file (qif-xtn:share-price self))))
;; number of shares
(if (string? (qif-xtn:num-shares self))
(qif-xtn:set-num-shares!
self
(qif-file:parse-value qif-file (qif-xtn:num-shares self))))
;; adjustment
(if (string? (qif-xtn:adjustment self))
(qif-xtn:set-adjustment!
self
(qif-file:parse-value qif-file (qif-xtn:adjustment self))))
;; reparse the amount of each split
(for-each
(lambda (split)
(if (string? (qif-split:amount split))
(qif-split:set-amount!
split
(qif-file:parse-value qif-file (qif-split:amount split)))))
(qif-xtn:splits self))
;; reparse the date
(if (string? (qif-xtn:date self))
(qif-xtn:set-date! self
(qif-file:parse-date qif-file
(qif-xtn:date self)))))
(define (qif-xtn:print self)
(simple-obj-print self <qif-xtn>))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; <qif-acct>
;; [N] name : string
;; [T] type : string
;; [D] description : string
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-acct>
(make-simple-class
'qif-acct
'(name type description limit)))
(define (qif-acct:name self)
(simple-obj-getter self <qif-acct> 'name))
(define (qif-acct:set-name! self value)
(simple-obj-setter self <qif-acct> 'name value))
(define (qif-acct:type self)
(simple-obj-getter self <qif-acct> 'type))
(define (qif-acct:set-type! self value)
(simple-obj-setter self <qif-acct> 'type value))
(define (qif-acct:description self)
(simple-obj-getter self <qif-acct> 'description))
(define (qif-acct:set-description! self value)
(simple-obj-setter self <qif-acct> 'description value))
(define (qif-acct:limit self)
(simple-obj-getter self <qif-acct> 'limit))
(define (qif-acct:set-limit! self value)
(simple-obj-setter self <qif-acct> 'limit value))
(define (make-qif-acct)
(make-simple-obj <qif-acct>))
(define (qif-acct? self)
(eq? (simple-obj-type self) 'qif-acct))
(define (qif-acct:print self)
(simple-obj-print self <qif-acct>))
(define (qif-acct:reparse self file)
(if (string? (qif-acct:limit self))
(qif-acct:set-limit!
self (qif-file:parse-value file (qif-acct:limit self)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; <qif-class>
;; [N] name : string
;; [D] description : string
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-class>
(make-simple-class
'qif-class
'(name description)))
(define (qif-class:name self)
(simple-obj-getter self <qif-class> 'name))
(define (qif-class:set-name! self value)
(simple-obj-setter self <qif-class> 'name value))
(define (qif-class:description self)
(simple-obj-getter self <qif-class> 'description))
(define (qif-class:set-description! self value)
(simple-obj-setter self <qif-class> 'description value))
(define (qif-class:print self)
(simple-obj-print self <qif-class>))
(define (make-qif-class)
(make-simple-obj <qif-class>))
(define (qif-class? self)
(eq? (simple-obj-type self) 'qif-class))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; <qif-cat> : a "Cat" or category transaction
;; [N] name : string
;; [D] description : string
;; [T] taxable : boolean
;; [E] expense? : boolean
;; [I] income? : boolean
;; [R] tax rate : number
;; [B] budget amt : number
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define <qif-cat>
(make-simple-class
'qif-cat
'(name description taxable expense-cat income-cat tax-rate budget-amt)))
(define (qif-cat:name self)
(simple-obj-getter self <qif-cat> 'name))
(define (qif-cat:set-name! self value)
(simple-obj-setter self <qif-cat> 'name value))
(define (qif-cat:description self)
(simple-obj-getter self <qif-cat> 'description))
(define (qif-cat:set-description! self value)
(simple-obj-setter self <qif-cat> 'description value))
(define (qif-cat:taxable self)
(simple-obj-getter self <qif-cat> 'taxable))
(define (qif-cat:set-taxable! self value)
(simple-obj-setter self <qif-cat> 'taxable value))
(define (qif-cat:expense-cat self)
(simple-obj-getter self <qif-cat> 'expense-cat))
(define (qif-cat:set-expense-cat! self value)
(simple-obj-setter self <qif-cat> 'expense-cat value))
(define (qif-cat:income-cat self)
(simple-obj-getter self <qif-cat> 'income-cat))
(define (qif-cat:set-income-cat! self value)
(simple-obj-setter self <qif-cat> 'income-cat value))
(define (qif-cat:tax-rate self)
(simple-obj-getter self <qif-cat> 'tax-rate))
(define (qif-cat:set-tax-rate! self value)
(simple-obj-setter self <qif-cat> 'tax-rate value))
(define (qif-cat:budget-amt self)
(simple-obj-getter self <qif-cat> 'budget-amt))
(define (qif-cat:set-budget-amt! self value)
(simple-obj-setter self <qif-cat> 'budget-amt value))
(define (make-qif-cat)
(make-simple-obj <qif-cat>))
(define (qif-cat? obj)
(eq? (simple-obj-type obj) 'qif-cat))
(define (qif-cat:print self)
(simple-obj-print self <qif-cat>))
(define (qif-cat:reparse self file)
(if (string? (qif-cat:tax-rate self))
(qif-cat:set-tax-rate!
self (qif-file:parse-value file (qif-cat:tax-rate self))))
(if (string? (qif-cat:budget-amt self))
(qif-cat:set-budget-amt!
self (qif-file:parse-value file (qif-cat:budget-amt self)))))
(define (qif-file:add-xtn! self xtn)
(qif-file:set-xtns! self
(cons xtn (qif-file:xtns self))))
(define (qif-file:add-cat! self cat)
(qif-file:set-cats! self
(cons cat (qif-file:cats self))))
(define (qif-file:add-class! self class)
(qif-file:set-classes! self
(cons class (qif-file:classes self))))
(define (qif-file:add-account! self account)
(qif-file:set-accounts! self
(cons account (qif-file:accounts self))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; munge the QIF filename to create a simple default account name
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:path-to-accountname self)
(let ((namestring (qif-file:path self)))
(if (and (string? namestring)
(> (string-length namestring) 0))
(begin
(set! namestring
(substring namestring
(let ((last-slash (string-rindex namestring #\/)))
(if last-slash
(+ 1 last-slash)
0))
(let ((last-dot (string-rindex namestring #\.)))
(if last-dot
last-dot
(string-length namestring)))))
(set! namestring (string-replace-char! namestring #\- #\space))
(set! namestring (string-replace-char! namestring #\_ #\space))
namestring)
"QIF Import")))

View File

@ -0,0 +1,475 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-parse.scm
;;; routines to parse values and dates in QIF files.
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "qif-parse.scm")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-split:parse-category
;; this one just gets nastier and nastier.
;; ATM we return a list of 3 elements: parsed category name
;; (without [] if it was an account name), bool stating if it
;; was an account name, and string representing the class name
;; (or #f if no class).
;; gosh, I love regular expressions.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define qif-category-compiled-rexp
(make-regexp "(\\[)?([^]/]*)(]?)(/?)(.*)"))
(define (qif-split:parse-category self value)
(let ((match (regexp-exec qif-category-compiled-rexp value)))
(if match
(begin
(list (match:substring match 2)
(if (and (match:substring match 1)
(match:substring match 3))
#t #f)
(if (match:substring match 4)
(match:substring match 5)
#f)))
(begin
(display "qif-split:parse-category : can't parse ")
(display value) (newline)
(list "" #f #f)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-file:fix-year
;; this is where we handle y2k fixes etc. input is a string
;; containing the year ("00", "2000", and "19100" all mean the same
;; thing). output is an integer representing the year in the C.E.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:fix-year self year-string)
(let ((fixed-string #f)
(post-read-value #f)
(y2k-fixed-value #f))
;; quicken prints 2000 as "' 0" for at least some versions.
;; thanks dave p for reporting this.
(if (eq? (string-ref year-string 0) #\')
(begin
(display "qif-file:fix-year : found a weird QIF Y2K year : |")
(display year-string)
(display "|") (newline)
(set! fixed-string
(substring year-string 2 (string-length year-string))))
(set! fixed-string year-string))
;; now the string should just have a number in it plus some
;; optional trailing space.
(set! post-read-value
(with-input-from-string fixed-string
(lambda () (read))))
(cond
;; 2-digit numbers less than the window size are interpreted to
;; be post-2000.
((and (integer? post-read-value)
(< post-read-value (qif-file:y2k-threshold self)))
(set! y2k-fixed-value (+ 2000 post-read-value)))
;; there's a common bug in printing post-2000 dates that
;; prints 2000 as 19100 etc.
((and (integer? post-read-value)
(> post-read-value 19000))
(set! y2k-fixed-value (+ 1900 (- post-read-value 19000))))
;; normal dates represented in unix years (i.e. year-1900, so
;; 2000 => 100.) We also want to allow full year specifications,
;; (i.e. 1999, 2001, etc) and there's a point at which you can't
;; determine which is which. this should eventually be another
;; field in the qif-file struct but not yet. mktime in scheme
;; doesn't deal with dates before December 14, 1901, at least for
;; now, so let's give ourselves until at least 3802 before this
;; does the wrong thing.
((and (integer? post-read-value)
(< post-read-value 1902))
(set! y2k-fixed-value (+ 1900 post-read-value)))
;; this is a normal, 4-digit year spec (1999, 2000, etc).
((integer? post-read-value)
(set! y2k-fixed-value post-read-value))
;; No idea what the string represents. Maybe a new bug in Quicken!
(#t
(display "qif-file:fix-year : ay caramba! What is this? |")
(display year-string)
(display "|") (newline)))
y2k-fixed-value))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; parse-acct-type : set the type of the account, using gnucash
;; conventions.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:parse-acct-type self read-value)
(let ((mangled-string
(string-downcase! (string-remove-trailing-space
(string-remove-leading-space read-value)))))
(cond
((string=? mangled-string "bank")
GNC-BANK-TYPE)
((string=? mangled-string "cash")
GNC-CASH-TYPE)
((string=? mangled-string "ccard")
GNC-CCARD-TYPE)
((string=? mangled-string "invst")
GNC-STOCK-TYPE)
((string=? mangled-string "oth a")
GNC-ASSET-TYPE)
((string=? mangled-string "oth l")
GNC-LIABILITY-TYPE)
(#t read-value))))
(define (qif-file:state-to-account-type self 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)
GNC-STOCK-TYPE)
((eq? qstate '#{type:oth\ a}#)
GNC-ASSET-TYPE)
((eq? qstate '#{type:oth\ l}#)
GNC-LIABILITY-TYPE)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; parse-bang-field : the bang fields switch the parse context for
;; the qif file.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:parse-bang-field self read-value)
(string->symbol (string-downcase!
(string-remove-trailing-space read-value))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; parse-cleared-field : in a C (cleared) field in a QIF transaction,
;; * means cleared, x or X means reconciled, and ! or ? mean some
;; budget related stuff I don't understand.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:parse-cleared-field self read-value)
(if (and (string? read-value)
(> (string-length read-value) 0))
(let ((secondchar (string-ref read-value 0)))
(cond ((eq? secondchar #\*)
'cleared)
((or (eq? secondchar #\x)
(eq? secondchar #\X))
'reconciled)
((or (eq? secondchar #\?)
(eq? secondchar #\!))
'budgeted)
(#t
#f)))
#f))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-file:parse-date
;;
;; If the date format is specified, use that; otherwise, try to guess
;; the format. When the format is being guessed, I don't actually do
;; any translation to a numeric format; that's saved for a second
;; pass (calling qif-bank-xtn:reparse on every transaction)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-file:parse-date self date-string)
(if (or (not (string? date-string))
(not (> (string-length date-string) 0)))
(begin
(display "qif-import: very bogus QIF date in transaction.") (newline)
(display "qif-import: Substituting 1/1/2999 for date.") (newline)
(set! date-string "1/1/2999")))
(let ((date-parts '())
(numeric-date-parts '())
(retval date-string)
(match
(string-match "([0-9]+) *[-/.'] *([0-9]+) *[-/.'] *([0-9]+)"
date-string)))
(if match
(set! date-parts (list (match:substring match 1)
(match:substring match 2)
(match:substring match 3))))
;; get the strings into numbers (but keep the strings around)
(set! numeric-date-parts
(map (lambda (elt)
(with-input-from-string elt
(lambda () (read))))
date-parts))
(cond
;; if the date parts list doesn't have 3 parts, we're in
;; trouble
((not (eq? 3 (length date-parts)))
(begin
(display "qif-file:parse-date : can't interpret date ")
(display date-string) (newline)))
;; if the format is unknown, don't try to fully interpret the
;; number, just look for a good guess or an inconsistency with
;; the current guess.
((and (eq? (qif-file:date-format self) 'unknown)
(not (eq? (qif-file:guessed-date-format self)
'inconsistent)))
(cond
;; we currently think the date format is m/d/y
((eq? (qif-file:guessed-date-format self) 'm-d-y)
(let ((m (car numeric-date-parts))
(d (cadr numeric-date-parts)))
(if (or (not (number? m)) (not (number? d)) (> m 12) (> d 31))
(qif-file:set-guessed-date-format! self 'inconsistent))))
;; current guess is d/m/y
((eq? (qif-file:guessed-date-format self) 'd-m-y)
(let ((d (car numeric-date-parts))
(m (cadr numeric-date-parts)))
(if (or (not (number? m)) (not (number? d)) (> m 12) (> d 31))
(qif-file:set-guessed-date-format! self 'inconsistent))))
;; current guess is y/m/d
((eq? (qif-file:guessed-date-format self) 'y-m-d)
(let ((m (cadr numeric-date-parts))
(d (caddr numeric-date-parts)))
(if (or (not (number? m)) (not (number? d)) (> m 12) (> d 31))
(qif-file:set-guessed-date-format! self 'inconsistent))))
;; current guess is y/d/m (is this really possible?)
((eq? (qif-file:guessed-date-format self) 'y-m-d)
(let ((d (cadr numeric-date-parts))
(m (caddr numeric-date-parts)))
(if (or (not (number? m)) (not (number? d)) (> m 12) (> d 31))
(qif-file:set-guessed-date-format! self 'inconsistent))))
;; no guess currently. See if we can find a smoking gun in
;; the date format. For dates like 11-9-11 just don't try to
;; guess.
((eq? (qif-file:guessed-date-format self) 'unknown)
(let ((possibilities '(m-d-y d-m-y y-m-d y-d-m))
(n1 (car numeric-date-parts))
(n2 (cadr numeric-date-parts))
(n3 (caddr numeric-date-parts)))
;; filter the possibilities to eliminate (hopefully)
;; all but one
(if (or (not (number? n1)) (> n1 12))
(set! possibilities (delq 'm-d-y possibilities)))
(if (or (not (number? n1)) (> n1 31))
(set! possibilities (delq 'd-m-y possibilities)))
(if (or (not (number? n2)) (> n2 12))
(begin
(set! possibilities (delq 'd-m-y possibilities))
(set! possibilities (delq 'y-m-d possibilities))))
(if (or (not (number? n2)) (> n2 31))
(begin
(set! possibilities (delq 'm-d-y possibilities))
(set! possibilities (delq 'y-d-m possibilities))))
(if (or (not (number? n3)) (> n3 12))
(set! possibilities (delq 'y-d-m possibilities)))
(if (or (not (number? n3)) (> n3 31))
(set! possibilities (delq 'y-m-d possibilities)))
;; if there's exactly one possibility left, we've got a good
;; guess. if there are no possibilities left, the date
;; is somehow inconsistent. More than one, do nothing.
(cond ((eq? (length possibilities) 1)
(qif-file:set-guessed-date-format! self (car possibilities)))
((eq? (length possibilities) 0)
(display "qif-file:parse-date : can't interpret date ")
(display date-string)
(newline)
(qif-file:set-guessed-date-format! self 'inconsistent)))))))
;; we think we know the date format. Make sure the data is
;; consistent with that.
((eq? (qif-file:date-format self) 'd-m-y)
(let ((d (car numeric-date-parts))
(m (cadr numeric-date-parts))
(y (qif-file:fix-year self (caddr date-parts))))
(if (and (integer? d) (integer? m) (integer? y)
(<= m 12) (<= d 31))
(set! retval (list d m y))
(begin
(display "qif-file:parse-date : format is d/m/y, but date is ")
(display date-string) (newline)))))
((eq? (qif-file:date-format self) 'm-d-y)
(let ((m (car numeric-date-parts))
(d (cadr numeric-date-parts))
(y (qif-file:fix-year self (caddr date-parts))))
(if (and (integer? d) (integer? m) (integer? y)
(<= m 12) (<= d 31))
(set! retval (list d m y))
(begin
(display "qif-file:parse-date : format is m/d/y, but date is ")
(display date-string) (newline)))))
((eq? (qif-file:date-format self) 'y-m-d)
(let ((y (qif-file:fix-year self (car date-parts)))
(m (cadr numeric-date-parts))
(d (caddr numeric-date-parts))))
(if (and (integer? d) (integer? m) (integer? y)
(<= m 12) (<= d 31))
(set! retval (list d m y))
(begin
(display "qif-file:parse-date : format is y/m/d, but date is ")
(display date-string) (newline))))
((eq? (qif-file:date-format self) 'y-d-m)
(let ((y (qif-file:fix-year self (car date-parts)))
(d (cadr numeric-date-parts))
(m (caddr numeric-date-parts))))
(if (and (integer? d) (integer? m) (integer? y)
(<= m 12) (<= d 31))
(set! retval (list d m y))
(begin
(display "qif-file:parse-date : format is y/m/d, but date is ")
(display date-string) (newline)))))
retval))
(define (qif-file:parse-string self str)
(if (or (not (string? str))
(not (> (string-length str) 0)))
(set! str " "))
(string-remove-leading-space (string-remove-trailing-space str)))
(define (qif-file:parse-value self value-string)
(if (or (not (string? value-string))
(not (> (string-length value-string) 0)))
(set! value-string "0"))
(let ((comma-index (string-rindex value-string #\,))
(decimal-index (string-rindex value-string #\.))
(comma-count (string-char-count value-string #\,))
(decimal-count (string-char-count value-string #\.)))
;; if we don't know the radix format, it might be appropriate to
;; guess. guessed radix format doesn't affect parsing at all
;; until you set the radix-format from the guessed-radix-format
;; and call reparse-values on all the values.
(if (and (eq? (qif-file:radix-format self) 'unknown)
(not (eq? (qif-file:guessed-radix-format self) 'inconsistent)))
(cond
;; already think it's decimal
((eq? (qif-file:guessed-radix-format self) 'decimal)
(if (or (> decimal-count 1)
(and decimal-index comma-index
(> comma-index decimal-index)))
(begin
(qif-file:set-guessed-radix-format! self 'inconsistent)
(display "this QIF file has inconsistent radix notation!")
(newline))))
;; already think it's comma
((eq? (qif-file:guessed-radix-format self) 'comma)
(if (or (> comma-count 1)
(and decimal-index comma-index
(> decimal-index comma-index)))
(begin
(qif-file:set-guessed-radix-format! self 'inconsistent)
(display "this QIF file has inconsistent radix notation!")
(newline))))
;; don't know : look for numbers that are giveaways.
((eq? (qif-file:guessed-radix-format self) 'unknown)
;; case 1: there's a decimal and a comma, and the
;; decimal is to the right of the comma, and there's
;; only one decimal : it's a decimal number.
(if (and decimal-index comma-index
(> decimal-index comma-index)
(eq? decimal-count 1))
(qif-file:set-guessed-radix-format! self 'decimal))
;; case 2: the opposite.
(if (and decimal-index comma-index
(> comma-index decimal-index)
(eq? comma-count 1))
(qif-file:set-guessed-radix-format! self 'comma))
;; case 3: there's no decimal and more than one comma:
;; it's a decimal number. I wish I had more transactions
;; like this!
(if (and (eq? decimal-count 0)
(> comma-count 1))
(qif-file:set-guessed-radix-format! self 'decimal))
;; case 4: the opposite (no comma, multiple decimals)
(if (and (eq? comma-count 0)
(> decimal-count 1))
(qif-file:set-guessed-radix-format! self 'comma))
;; case 5: one decimal, no commas, and not-3 digits
;; after it --> decimal.
(if (and (eq? comma-count 0)
(eq? decimal-count 1)
(not (eq? (- (string-length value-string)
decimal-index)
4)))
(qif-file:set-guessed-radix-format! self 'decimal))
;; case 6: the opposite --> comma
(if (and (eq? comma-count 1)
(eq? decimal-count 0)
(not (eq? (- (string-length value-string)
comma-index)
4)))
(begin
(display "hey!") (display comma-count)
(display comma-index) (display (string-length value-string))
(newline)
(qif-file:set-guessed-radix-format! self 'comma))))))
(cond
;; decimal radix (US format)
;; number can't have more than one ., and the rightmost
;; . must be to the right of the rightmost ,
;; , are ignored otherwise
((eq? 'decimal (qif-file:radix-format self))
(if (or (and decimal-count
(> decimal-count 1))
(and decimal-index comma-index
(> comma-index decimal-index)))
(error "badly-formed decimal-radix number" value-string)
(+ 0.0
(with-input-from-string (string-remove-char value-string #\,)
(lambda () (read))))))
;; comma radix (German format)
;; number can't have more than one , and the rightmost
;; , must be to the right of the rightmost .
;; . are ignored otherwise. Substitute . for , before
;; parsing.
((eq? 'comma (qif-file:radix-format self))
(if (or (and comma-count
(> comma-count 1))
(and decimal-index comma-index
(> decimal-index comma-index)))
(error "badly formed comma-radix number" value-string)
(+ 0.0
(with-input-from-string (string-replace-char!
(string-remove-char value-string #\.)
#\, #\.)
(lambda () (read))))))
;; unknown radix - store the string and we can process it
;; later.
(#t
value-string))))

View File

@ -0,0 +1,479 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-to-gnc.scm
;;; this is where QIF transactions are transformed into a
;;; Gnucash account tree.
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "qif-to-gnc.scm")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; find-or-make-acct:
;; given a colon-separated account path, return an Account* to
;; an existing or new account.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:find-or-make-acct gnc-name gnc-acct-hash
gnc-type qif-info acct-group)
(let ((existing-account (hash-ref gnc-acct-hash gnc-name))
(same-gnc-account (gnc:get-account-from-full-name acct-group
gnc-name
#\:))
(check-full-name #f)
(make-new-acct #f))
(if (or (pointer-token-null? same-gnc-account)
(and (not (pointer-token-null? same-gnc-account))
(not (string=?
(gnc:account-get-full-name same-gnc-account)
gnc-name))))
(set! make-new-acct #t))
(if (and make-new-acct
(not (pointer-token-null? same-gnc-account)))
(begin (display " BUG IN get-account-from-full-name !!")(newline)))
(if existing-account
existing-account
(let ((new-acct (gnc:malloc-account))
(parent-acct #f)
(parent-name #f)
(acct-name #f)
(last-colon #f))
(set! last-colon (string-rindex gnc-name #\:))
(gnc:init-account new-acct)
(gnc:account-begin-edit new-acct 1)
;; if this is a copy of an existing gnc account,
;; copy the account properties
(if (not make-new-acct)
(begin
(gnc:account-set-name
new-acct (gnc:account-get-name same-gnc-account))
(gnc:account-set-description
new-acct (gnc:account-get-description same-gnc-account))
(gnc:account-set-type
new-acct (gnc:account-get-type same-gnc-account))
(gnc:account-set-currency
new-acct (gnc:account-get-currency same-gnc-account))
(gnc:account-set-notes
new-acct (gnc:account-get-notes same-gnc-account))
(gnc:account-set-code
new-acct (gnc:account-get-code same-gnc-account))
(gnc:account-set-security
new-acct (gnc:account-get-security same-gnc-account))))
;; make sure that if this is a nested account foo:bar:baz,
;; foo:bar and foo exist also.
(if last-colon
(begin
(set! parent-name (substring gnc-name 0 last-colon))
(set! acct-name (substring gnc-name (+ 1 last-colon)
(string-length gnc-name)))
(set! parent-acct (qif-import:find-or-make-acct
parent-name gnc-acct-hash
gnc-type qif-info
acct-group))
;; if this is a new account, use the
;; parameters passed in
(if make-new-acct
(begin
(gnc:account-set-name new-acct acct-name)
(if gnc-type (gnc:account-set-type new-acct gnc-type))
(cond ((and (qif-acct? qif-info)
(qif-acct:description qif-info))
(gnc:account-set-description
new-acct (qif-acct:description qif-info)))
((and (qif-cat? qif-info)
(qif-cat:description qif-info))
(gnc:account-set-description
new-acct (qif-cat:description qif-info)))
((and (qif-xtn? qif-info)
(not (qif-xtn:bank-xtn? qif-info)))
(gnc:account-set-security
(qif-xtn:security-name qif-info)))
((string? qif-info)
(gnc:account-set-description
new-acct qif-info)))))
(gnc:account-commit-edit new-acct)
(gnc:insert-subaccount parent-acct new-acct))
(begin
(if make-new-acct
(begin
(gnc:account-set-name new-acct gnc-name)
(cond ((and (qif-acct? qif-info)
(qif-acct:description qif-info))
(gnc:account-set-description
new-acct (qif-acct:description qif-info)))
((and (qif-cat? qif-info)
(qif-cat:description qif-info))
(gnc:account-set-description
new-acct (qif-cat:description qif-info)))
((string? qif-info)
(gnc:account-set-description
new-acct qif-info)))
(if gnc-type (gnc:account-set-type new-acct gnc-type))))
(gnc:account-commit-edit new-acct)
(gnc:group-insert-account acct-group new-acct)))
(hash-set! gnc-acct-hash gnc-name new-acct)
new-acct))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:qif-to-gnc
;; this is the top-level of the back end conversion from
;; QIF to GNC. all the account mappings and so on should be
;; done before this is called.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:qif-to-gnc qif-files-list mapping-data)
(let* ((existing-gnc-accts (car mapping-data))
(qif-acct-map (cadr mapping-data))
(qif-cat-map (caddr mapping-data))
(account-group (gnc:get-current-group))
(gnc-acct-hash (make-hash-table 20))
(existing-gnc-accounts #f)
(sorted-qif-files-list
(sort qif-files-list
(lambda (a b)
(> (length (qif-file:xtns a))
(length (qif-file:xtns b)))))))
;; first, build a local account tree that mirrors the gnucash
;; accounts in the mapping data. we need to iterate over the
;; cat-map and the acct-map, building the gnc-acct-hash as we go.
(for-each
(lambda (bin)
(for-each
(lambda (hashpair)
(let* ((acctinfo (cdr hashpair))
(qif-name (list-ref acctinfo 0))
(gnc-name (list-ref acctinfo 1))
(gnc-type (list-ref acctinfo 2))
(gnc-new (list-ref acctinfo 3))
(gnc-xtns (list-ref acctinfo 4))
(qif-info (list-ref acctinfo 5)))
(if (> gnc-xtns 0)
(qif-import:find-or-make-acct gnc-name gnc-acct-hash
gnc-type qif-info
account-group))))
bin))
(vector->list qif-acct-map))
(for-each
(lambda (bin)
(for-each
(lambda (hashpair)
(let* ((acctinfo (cdr hashpair))
(qif-name (list-ref acctinfo 0))
(gnc-name (list-ref acctinfo 1))
(gnc-type (list-ref acctinfo 2))
(gnc-new (list-ref acctinfo 3))
(gnc-xtns (list-ref acctinfo 4))
(qif-info (list-ref acctinfo 5)))
(if (> gnc-xtns 0)
(qif-import:find-or-make-acct gnc-name gnc-acct-hash
gnc-type qif-info
account-group))))
bin))
(vector->list qif-cat-map))
;; iterate over files. Going in the sort order by number of
;; transactions should give us a small speed advantage.
(for-each
(lambda (qif-file)
;; within the file, iterate over transactions. key things to
;; remember: if the L line in the transaction is a category,
;; it's a single-entry xtn and no need to look for the other
;; end. if it's an account, search for a QIF file with that
;; account name and find the xtn to mark.
(for-each
(lambda (xtn)
(if (not (qif-xtn:mark xtn))
(begin
;; mark the transaction and find any other QIF
;; xtns that refer to the same xtn
(qif-xtn:set-mark! xtn #t)
(qif-import:mark-matching-xtns xtn qif-file qif-files-list)
;; create and fill in the GNC transaction
(let ((gnc-xtn (gnc:transaction-create)))
(gnc:transaction-init gnc-xtn)
(gnc:transaction-begin-edit gnc-xtn 1)
;; destroy any automagic splits in the transaction
(let ((numsplits (gnc:transaction-get-split-count gnc-xtn)))
(if (not (eqv? 0 numsplits))
(let splitloop ((ind (- numsplits 1)))
(gnc:split-destroy
(gnc:transaction-get-split gnc-xtn ind))
(if (> ind 0)
(loop (- ind 1))))))
;; build the transaction
(qif-import:qif-xtn-to-gnc-xtn
xtn qif-file gnc-xtn gnc-acct-hash mapping-data)
;; rebalance and commit everything
(gnc:transaction-commit-edit gnc-xtn)))))
(qif-file:xtns qif-file)))
sorted-qif-files-list)
;; now take the new account tree and merge it in with the
;; existing gnucash account tree.
(gnc:merge-accounts account-group)
(gnc:refresh-main-window)
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:qif-xtn-to-gnc-xtn
;; translate a single transaction to a set of gnucash splits and
;; a gnucash transaction structure.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:qif-xtn-to-gnc-xtn qif-xtn qif-file gnc-xtn
gnc-acct-hash mapping-data)
(let ((splits (qif-xtn:splits qif-xtn))
(qif-cat-map (caddr mapping-data))
(qif-acct-map (cadr mapping-data))
(near-acct-info #f)
(near-acct-name #f)
(near-acct #f))
;; set properties of the whole transaction
(apply gnc:transaction-set-date gnc-xtn (qif-xtn:date qif-xtn))
(if (qif-xtn:payee qif-xtn)
(gnc:transaction-set-description gnc-xtn (qif-xtn:payee qif-xtn)))
(if (qif-xtn:number qif-xtn)
(gnc:transaction-set-xnum gnc-xtn (qif-xtn:number qif-xtn)))
;; find the GNC account for the near end of the transaction
;; (all splits have the same near end)
(if (qif-xtn:bank-xtn? qif-xtn)
(begin
(set! near-acct-info
(hash-ref qif-acct-map
(qif-file:account qif-file)))
(set! near-acct-name
(list-ref near-acct-info 1))
(set! near-acct (hash-ref gnc-acct-hash near-acct-name)))
(begin
(set! near-acct-info
(hash-ref qif-acct-map
(qif-xtn:security-name qif-xtn)))
(set! near-acct-name
(list-ref near-acct-info 1))
(set! near-acct (hash-ref gnc-acct-hash near-acct-name))))
;; iterate over QIF splits
(for-each
(lambda (qif-split)
(let ((gnc-near-split (gnc:split-create))
(gnc-far-split (gnc:split-create))
(far-acct-info #f)
(far-acct-name #f)
(far-acct-type #f)
(far-acct #f))
;; fill the splits in (near first). This handles files in
;; multiple currencies by pulling the currency value from the
;; file import.
(gnc:split-set-base-value gnc-near-split
(qif-split:amount qif-split)
(qif-file:currency qif-file))
(gnc:split-set-base-value gnc-far-split
(- (qif-split:amount qif-split))
(qif-file:currency qif-file))
(if (qif-split:memo qif-split)
(begin
(gnc:split-set-memo gnc-near-split (qif-split:memo qif-split))
(gnc:split-set-memo gnc-far-split (qif-split:memo qif-split))))
;; my guess is that you can't have Quicken splits
;; on stock transactions. This will break if you can.
(if (qif-xtn:share-price qif-xtn)
(begin
(if (> (length splits) 1)
(begin
(display "qif-import:qif-xtn-to-gnc-xtn : ")
(display "splits in stock transaction!") (newline)))
(gnc:split-set-share-price gnc-near-split
(qif-xtn:share-price qif-xtn))
(gnc:split-set-share-price gnc-far-split
(qif-xtn:share-price qif-xtn)))
(begin
(gnc:split-set-share-price gnc-near-split 1.0)
(gnc:split-set-share-price gnc-far-split 1.0)))
(if (qif-xtn:num-shares qif-xtn)
(begin
(if (> (length splits) 1)
(begin
(display "qif-import:qif-xtn-to-gnc-xtn : ")
(display "splits in stock transaction!") (newline)))
(gnc:split-set-share-amount gnc-near-split
(qif-xtn:num-shares qif-xtn))
(gnc:split-set-share-amount gnc-far-split
(- (qif-xtn:num-shares qif-xtn)))))
;; find the GNC account on the far end of the split
(cond
;; this is a stock xtn with no specified category, which
;; generally means this account is a brokerage account
;; description.
((and (not (qif-xtn:bank-xtn? qif-xtn))
(string=? (qif-split:category qif-split) ""))
(set! far-acct-info
(hash-ref qif-acct-map
(qif-file:account qif-file)))
(set! far-acct-name
(list-ref far-acct-info 1))
(set! far-acct (hash-ref gnc-acct-hash far-acct-name)))
;; this is a normal stock or bank transfer to another
;; account
((qif-split:category-is-account? qif-split)
(set! far-acct-info
(hash-ref qif-acct-map
(qif-split:category qif-split)))
(set! far-acct-name
(list-ref far-acct-info 1))
(set! far-acct (hash-ref gnc-acct-hash far-acct-name)))
;; otherwise the category is a category and won't have a
;; matching split in the QIF world.
(#t
(set! far-acct-info
(hash-ref qif-cat-map
(qif-split:category qif-split)))
(set! far-acct-name
(list-ref far-acct-info 1))
(set! far-acct (hash-ref gnc-acct-hash far-acct-name))))
;; finally, plug the splits into the accounts
(gnc:transaction-append-split gnc-xtn gnc-near-split)
(gnc:transaction-append-split gnc-xtn gnc-far-split)
(gnc:account-insert-split near-acct gnc-near-split)
(gnc:account-insert-split far-acct gnc-far-split)))
splits)
;; return the modified transaction (though it's ignored).
gnc-xtn))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-import:mark-matching-xtns
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-import:mark-matching-xtns xtn qif-file qif-files)
(for-each
(lambda (split)
(if (not (qif-split:mark split))
(if (qif-split:category-is-account? split)
(begin
(qif-split:set-mark! split #t)
(qif-import:mark-matching-split split xtn qif-file qif-files))
(qif-split:set-mark! split #t))))
(qif-xtn:splits xtn))
(qif-xtn:set-mark! xtn #t))
(define (qif-import:mark-matching-split split xtn qif-file qif-files)
(let ((near-acct-name #f)
(far-acct-name (qif-split:category split))
(date (qif-xtn:date xtn))
(amount (- (qif-split:amount split)))
(memo (qif-split:memo split))
(bank-xtn? (qif-xtn:bank-xtn? xtn))
(done #f))
(if bank-xtn?
(set! near-acct-name (qif-file:account qif-file))
(set! near-acct-name (qif-xtn:security-name xtn)))
;; (display "mark-matching-split : near-acct = ")
;; (write near-acct-name)
;; (display " far-acct = ")
;; (write far-acct-name)
;; (display " date = ")
;; (write date)
;; (newline)
;; this is the grind loop. Go over every unmarked split of every
;; unmarked transaction of every file that's not this one.
(let file-loop ((files qif-files))
(if (and (not (eq? qif-file (car files)))
(or (not bank-xtn?)
(string=? far-acct-name
(qif-file:account (car files)))))
(let xtn-loop ((xtns (qif-file:xtns (car files))))
(if (not (qif-xtn:mark (car xtns)))
(let split-loop ((splits (qif-xtn:splits (car xtns))))
(if (qif-split:split-matches?
(car splits) (car xtns)
near-acct-name date amount memo)
(begin
;; (display "found ")(write (car splits))(newline)
(qif-split:set-mark! (car splits) #t)
(set! done #t)
(let ((all-marked #t))
(for-each
(lambda (s) (if (not (qif-split:mark s))
(set! all-marked #f)))
(qif-xtn:splits (car xtns)))
(if all-marked (qif-xtn:set-mark!
(car xtns) #t)))))
(if (and (not done)
(not (null? (cdr splits))))
(split-loop (cdr splits)))))
(if (and (not done)
(not (null? (cdr xtns))))
(xtn-loop (cdr xtns)))))
(if (and (not done)
(not (null? (cdr files))))
(file-loop (cdr files))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; qif-split:split-matches?
;; check if a split matches date, amount, and other criteria
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (qif-split:split-matches? split xtn acct-name date amount memo)
(and
;; account name matches
(string=? acct-name (qif-split:category split))
;; is the amount right?
(eqv? amount (qif-split:amount split))
;; is the date the same?
(let ((self-date (qif-xtn:date xtn)))
(and (pair? self-date)
(pair? date)
(eq? (length self-date) 3)
(eq? (length date) 3)
(eqv? (car self-date) (car date))
(eqv? (cadr self-date) (cadr date))
(eqv? (caddr self-date) (caddr date))))
;; is the memo the same? (is this true?)
;; ignore it for now
))

View File

@ -0,0 +1,65 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; qif-utils.scm
;;; string munging and other utility routines
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "qif-utils.scm")
(define (simple-filter pred list)
(let ((retval '()))
(map (lambda (elt)
(if (pred elt)
(set! retval (cons elt retval))))
list)
(reverse retval)))
(define remove-trailing-space-rexp
(make-regexp "^(.*[^ ]+) *$"))
(define remove-leading-space-rexp
(make-regexp "^ *([^ ].*)$"))
(define (string-remove-trailing-space str)
(if (eq? (string-ref str (- (string-length str) 1)) #\cr)
(string-set! str (- (string-length str) 1) #\space))
(let ((match (regexp-exec remove-trailing-space-rexp str)))
(if match
(string-copy (match:substring match 1))
"")))
(define (string-remove-leading-space str)
(let ((match (regexp-exec remove-leading-space-rexp str)))
(if match
(string-copy (match:substring match 1))
"")))
(define (string-remove-char str char)
(let ((rexpstr (make-string 1 char)))
(regexp-substitute/global #f rexpstr str 'pre 'post)))
(define (string-char-count str char)
(length (simple-filter (lambda (elt) (eq? elt char))
(string->list str))))
(define (string-replace-char! str old new)
(let ((rexpstr (make-string 1 old))
(newstr (make-string 1 new)))
(regexp-substitute/global #f rexpstr str 'pre newstr 'post)))
(define (string-split-on str char)
(let ((parts '())
(first-char #f))
(let loop ((last-char (string-length str)))
(set! first-char (string-rindex str char 0 last-char))
(if first-char
(begin
(set! parts (cons (substring str (+ 1 first-char) last-char)
parts))
(loop first-char))
(set! parts (cons (substring str 0 last-char) parts))))
parts))

View File

@ -0,0 +1,101 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; simple-obj.scm
;;; rudimentary "class" system for straight Scheme
;;;
;;; Bill Gribble <grib@billgribble.com> 20 Feb 2000
;;; $Id$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gnc:support "simple-obj.scm")
;; this is an extremely rudimentary object system. Each object is a
;; cons cell, where the car is a symbol with the class name and the
;; cdr is a vector of the slots.
;;
;; the "class object" is an instance of simple-class which just has
;; the name of the class and an alist of slot names to vector indices
;; as its slots.
;;
;; by convention, I name class objects (defined with make-simple-class)
;; <class-name> with class-smybol 'class-name. For example,
;;
;; (define <test-class> (make-simple-class 'test-class '(slot-1 slot-2)))
;; (define t (make-simple-obj <test-class>))
;; t ==> (test-class . #(#f #f))
;; the 'simple-class' class.
(define (make-simple-class class-symbol slot-names)
(let ((slots (make-vector 3))
(slot-hash (make-hash-table 11))
(slot-counter 0))
(vector-set! slots 0 class-symbol)
(vector-set! slots 1 slot-hash)
(vector-set! slots 2 slot-names)
(for-each
(lambda (elt)
(hash-set! slot-hash elt slot-counter)
(set! slot-counter (+ 1 slot-counter)))
slot-names)
(cons 'simple-class slots)))
(define (simple-class? self)
(and (pair? self) (eq? (car self) 'simple-class)))
(define (simple-obj-getter obj class slot)
(let ((slot-num (hash-ref (vector-ref (cdr class) 1) slot)))
(vector-ref (cdr obj) slot-num)))
;; (if (and (pair? obj)
;; (simple-class? class))
;; (if (eq? (vector-ref (cdr class) 0) (car obj))
;; (let ((slot-num-pair (assq slot (vector-ref (cdr class) 1))))
;; (if slot-num-pair
;; (if (vector? (cdr obj))
;; (vector-ref (cdr obj) (cdr slot-num-pair))
;; (error "simple-obj-getter: data field not a vector??"))
;; (error "simple-obj-getter: no slot " slot " in class "
;; class)))
;; (error "simple-obj-getter: object " obj " is not of class "
;; class))
;; (error "simple-obj-getter: bad object/class " obj class)))
(define (simple-obj-setter obj class slot value)
(let ((slot-num (hash-ref (vector-ref (cdr class) 1) slot)))
(vector-set! (cdr obj) slot-num value)))
;; (if (and (pair? obj)
;; (simple-class? class))
;; (if (eq? (vector-ref (cdr class) 0) (car obj))
;; (let ((slot-num-pair (assq slot (vector-ref (cdr class) 1))))
;; (if slot-num-pair
;; (if (vector? (cdr obj))
;; (vector-set! (cdr obj) (cdr slot-num-pair) value)
;; (error "simple-obj-setter: data field not a vector??"))
;; (error "simple-obj-setter: no slot " slot " in class "
;; class)))
;; (error "simple-obj-setter: object " obj " is not of class "
;; class))
;; (error "simple-obj-setter: bad object/class " obj class)))
(define (simple-obj-print obj class)
(display ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;") (newline)
(for-each
(lambda (slot)
(display " ")
(display slot)
(display " : ")
(display (simple-obj-getter obj class slot))
(newline))
(vector-ref (cdr class) 2)))
(define (simple-obj-type obj)
(if (pair? obj)
(car obj)
#f))
(define (make-simple-obj class)
(if (simple-class? class)
(cons (vector-ref (cdr class) 0)
(make-vector (length (vector-ref (cdr class) 2)) #f))))

View File

@ -40,6 +40,7 @@
#define HH_GPL "xacc-gpl.html"
#define HH_GLOBPREFS "xacc-globalprefs.html"
#define HH_ACCEDIT "xacc-accountedit.html"
#define HH_QIFIMPORT "xacc-qif-import.html"
/** STRUCTS *********************************************************/