From 7de7b944f8637e92dff24a328eec459259761e14 Mon Sep 17 00:00:00 2001 From: Joshua Sled Date: Tue, 16 Apr 2002 07:09:16 +0000 Subject: [PATCH] 2002-04-16 Joshua Sled * src/register/ledger-core/gnc-ledger-display.c: Some template-GL cleanup [debugging printf's removed]. Removed never-used LD_TEMPLATE type. * src/gnome/glade/sched-xact.glade: Removed unused start page. * src/gnome/dialog-sxsincelast.c: Added support for using the gnc-regWidget to display created transactions for review. Added 'Cancel' support. Didn't remove enough dead code, but started to. * src/gnome/dialog-scheduledxaction.c: Added support for using the gncRegWidget in the SX editor. Formatting changes. * src/register/ledger-core/gnc-regWidget.{h,c}: Added; a macro-widget roughly duplicating the src/gnome/window-register.c look-and-feel-and-behavior. * src/engine/SchedXaction.c: Added support for saving a "temporal snapshot" of a scheduled transaction. Rewrote "sequence state" manipulations in terms of temporal snapshots. * src/engine/Query.c: Add support for Querying the template AccountGroup. * src/doc/TODO-schedxactions: Updates. * src/engine/Makefile.am: Prepend-to instead of unconditionally setting GUILE_LOAD_PATH when creating iso-4217-currencies.c, for those of us that need to set it for whatever reason we need to do so. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6795 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 33 + po/POTFILES.in | 455 +-- src/doc/TODO-schedxactions | 218 +- src/engine/Makefile.am | 6 +- src/engine/Query.c | 22 +- src/engine/Query.h | 4 + src/engine/SchedXaction.c | 60 +- src/engine/SchedXaction.h | 22 +- src/gnome/dialog-scheduledxaction.c | 420 +-- src/gnome/dialog-sxsincelast.c | 686 ++--- src/gnome/glade/sched-xact.glade | 12 - src/register/ledger-core/Makefile.am | 7 +- src/register/ledger-core/gnc-ledger-display.c | 25 +- src/register/ledger-core/gnc-ledger-display.h | 1 - src/register/ledger-core/gnc-regwidget.c | 2544 +++++++++++++++++ src/register/ledger-core/gnc-regwidget.h | 104 + 16 files changed, 3592 insertions(+), 1027 deletions(-) create mode 100644 src/register/ledger-core/gnc-regwidget.c create mode 100644 src/register/ledger-core/gnc-regwidget.h diff --git a/ChangeLog b/ChangeLog index 5ec6658c06..f781535cd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2002-04-16 Joshua Sled + + * src/register/ledger-core/gnc-ledger-display.c: Some template-GL + cleanup [debugging printf's removed]. Removed never-used + LD_TEMPLATE type. + + * src/gnome/glade/sched-xact.glade: Removed unused start page. + + * src/gnome/dialog-sxsincelast.c: Added support for using the + gnc-regWidget to display created transactions for review. Added + 'Cancel' support. Didn't remove enough dead code, but started to. + + * src/gnome/dialog-scheduledxaction.c: Added support for using the + gncRegWidget in the SX editor. Formatting changes. + + * src/register/ledger-core/gnc-regWidget.{h,c}: Added; a + macro-widget roughly duplicating the src/gnome/window-register.c + look-and-feel-and-behavior. + + * src/engine/SchedXaction.c: Added support for saving a "temporal + snapshot" of a scheduled transaction. Rewrote "sequence state" + manipulations in terms of temporal snapshots. + + * src/engine/Query.c: Add support for Querying the template + AccountGroup. + + * src/doc/TODO-schedxactions: Updates. + + * src/engine/Makefile.am: Prepend-to instead of unconditionally + setting GUILE_LOAD_PATH when creating iso-4217-currencies.c, for + those of us that need to set it for whatever reason we need to do + so. + 2002-03-04 Derek Atkins * Plug-in Extensions for backends, so pluggable objects can diff --git a/po/POTFILES.in b/po/POTFILES.in index c742deeb53..f49e0388ef 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,26 +1,51 @@ # List of files which containing translatable strings. # This file was generated by ../make-gnucash-potfiles.in. +src/calculation/amort_opt.c +src/calculation/amort_prt.c +src/calculation/expression_parser.c +src/calculation/fin-interactive.c +src/calculation/fin-main.c +src/calculation/fin.c +src/calculation/numeric_ops.c +src/calculation/test/test-link.c +src/calculation/gncmod-calculation.c +src/app-utils/test/test-exp-parser.c +src/app-utils/test/test-link-module.c +src/app-utils/test/test-print-parse-amount.c +src/app-utils/gfec.c +src/app-utils/global-options.c +src/app-utils/gnc-component-manager.c +src/app-utils/gnc-euro.c +src/app-utils/gnc-exp-parser.c +src/app-utils/gnc-gettext-util.c +src/app-utils/gnc-helpers.c +src/app-utils/gnc-ui-util.c +src/app-utils/gncmod-app-utils.c +src/app-utils/guile-util.c +src/app-utils/option-util.c +src/app-utils/file-utils.c +src/backend/file/test/test-date-converting.c src/backend/file/test/test-dom-converters1.c src/backend/file/test/test-dom-parser1.c -src/backend/file/test/test-kvp-frames.c -src/backend/file/test/test-load-xml2.c -src/backend/file/test/test-string-converters.c src/backend/file/test/test-file-stuff.c +src/backend/file/test/test-kvp-frames.c +src/backend/file/test/test-load-example-account.c +src/backend/file/test/test-load-xml2.c +src/backend/file/test/test-save-in-lang.c +src/backend/file/test/test-string-converters.c src/backend/file/test/test-xml-account.c src/backend/file/test/test-xml-commodity.c -src/backend/file/test/test-xml2-is-file.c -src/backend/file/test/test-load-example-account.c -src/backend/file/test/test-save-in-lang.c -src/backend/file/test/test-date-converting.c -src/backend/file/test/test-xml-transaction.c src/backend/file/test/test-xml-pricedb.c +src/backend/file/test/test-xml-transaction.c +src/backend/file/test/test-xml2-is-file.c src/backend/file/gnc-account-xml-v2.c src/backend/file/gnc-backend-file.c src/backend/file/gnc-commodity-xml-v2.c src/backend/file/gnc-freqspec-xml-v2.c src/backend/file/gnc-schedxaction-xml-v2.c src/backend/file/gnc-transaction-xml-v2.c +src/backend/file/gncmod-backend-file.c src/backend/file/io-example-account.c src/backend/file/io-gncbin-r.c src/backend/file/io-gncxml-gen.c @@ -35,7 +60,6 @@ src/backend/file/sixtp-utils.c src/backend/file/sixtp.c src/backend/file/gnc-pricedb-xml-v2.c src/backend/file/gnc-book-xml-v2.c -src/backend/file/gncmod-backend-file.c src/backend/rpc/RpcBackend.c src/backend/rpc/RpcServer.c src/backend/rpc/RpcSock.c @@ -51,6 +75,7 @@ src/backend/rpc/xprt_thrd.c src/backend/postgres/test/test-db.c src/backend/postgres/test/test-escape.c src/backend/postgres/test/test-period.c +src/backend/postgres/PostgresBackend.c src/backend/postgres/account.c src/backend/postgres/builder.c src/backend/postgres/checkpoint.c @@ -64,163 +89,14 @@ src/backend/postgres/price.c src/backend/postgres/txn.c src/backend/postgres/txnmass.c src/backend/postgres/upgrade.c -src/backend/postgres/PostgresBackend.c src/backend/postgres/book.c src/backend/net/NetIO.c -src/app-utils/test/test-link-module.c -src/app-utils/test/test-exp-parser.c -src/app-utils/test/test-print-parse-amount.c -src/app-utils/gfec.c -src/app-utils/global-options.c -src/app-utils/gnc-component-manager.c -src/app-utils/gnc-gettext-util.c -src/app-utils/gnc-helpers.c -src/app-utils/gnc-ui-util.c -src/app-utils/guile-util.c -src/app-utils/option-util.c -src/app-utils/file-utils.c -src/app-utils/gnc-euro.c -src/app-utils/gncmod-app-utils.c -src/app-utils/gnc-exp-parser.c -src/tax/us/test/test-link-module.c -src/tax/us/gncmod-tax-us.c -src/business/business-core/test/test-address.c -src/business/business-core/test/test-business.c -src/business/business-core/test/test-customer.c -src/business/business-core/test/test-employee.c -src/business/business-core/test/test-job.c -src/business/business-core/test/test-vendor.c -src/business/business-core/test/test-load-module.c -src/business/business-core/businessmod-core.c -src/business/business-core/gncAddress.c -src/business/business-core/gncBusiness.c -src/business/business-core/gncCustomer.c -src/business/business-core/gncEmployee.c -src/business/business-core/gncJob.c -src/business/business-core/gncVendor.c -src/business/business-core/gncEntry.c -src/business/business-core/gncInvoice.c -src/business/business-core/gncOrder.c -src/business/business-core/gncOwner.c -src/business/business-gnome/businessmod-gnome.c -src/business/business-gnome/customer.glade -src/business/business-gnome/dialog-customer.c -src/business/business-gnome/dialog-employee.c -src/business/business-gnome/dialog-job-select.c -src/business/business-gnome/dialog-job.c -src/business/business-gnome/dialog-vendor.c -src/business/business-gnome/employee.glade -src/business/business-gnome/gnc-business-utils.c -src/business/business-gnome/job.glade -src/business/business-gnome/vendor.glade -src/business/business-gnome/dialog-order.c -src/business/business-gnome/dialog-invoice.c -src/business/business-gnome/order.glade -src/business/business-gnome/business-utils.c -src/business/business-gnome/date-close.glade -src/business/business-gnome/dialog-date-close.c -src/business/business-gnome/invoice.glade -src/business/business-ledger/gncEntryLedgerControl.c -src/business/business-ledger/gncEntryLedgerLayout.c -src/business/business-ledger/gncEntryLedgerModel.c -src/business/business-ledger/gncEntryLedgerLoad.c -src/business/business-ledger/gncEntryLedger.c -src/business/business-ledger/gncEntryLedgerDisplay.c -src/gnome-utils/dialog-utils.c -src/gnome-utils/druid-utils.c -src/gnome-utils/dialog-commodity.c -src/gnome-utils/test/test-link-module.c -src/gnome-utils/gnc-amount-edit.c -src/gnome-utils/gnc-account-tree.c -src/gnome-utils/gnc-commodity-edit.c -src/gnome-utils/cursors.c -src/gnome-utils/gnc-html.c -src/gnome-utils/commodity.glade -src/gnome-utils/gnc-menu-extensions.c -src/gnome-utils/gnc-currency-edit.c -src/gnome-utils/gnc-gui-query.c -src/gnome-utils/gnc-date-edit.c -src/gnome-utils/gnc-html-history.c -src/gnome-utils/gnc-html-guppi.c -src/gnome-utils/gnc-frequency.c -src/gnome-utils/gncmod-gnome-utils.c -src/gnome-utils/gnc-date-delta.c -src/gnome-utils/gnc-gnome-utils.c -src/gnome-utils/dialog-options.c -src/gnome-utils/window-help.c -src/gnome-utils/gnc-general-select.c -src/gnome-utils/gtkselect.c -src/gnome-utils/print-session.c -src/gnome-utils/gnc-mdi-utils.c -src/gnome-utils/argv-list-converters.c -src/network-utils/gnc-gpg.c -src/network-utils/gnc-http.c -src/network-utils/test/test-link-module.c -src/network-utils/gncmod-network-utils.c -src/calculation/amort_opt.c -src/calculation/amort_prt.c -src/calculation/expression_parser.c -src/calculation/fin-interactive.c -src/calculation/fin-main.c -src/calculation/fin.c -src/calculation/numeric_ops.c -src/calculation/gncmod-calculation.c -src/calculation/test/test-link.c -src/engine/Account.c -src/engine/Backend.c -src/engine/DateUtils.c -src/engine/FreqSpec.c -src/engine/GNCId.c -src/engine/Group.c -src/engine/Query.c -src/engine/SchedXaction.c -src/engine/Scrub.c -src/engine/TransLog.c -src/engine/Transaction.c -src/engine/date.c -src/engine/engine-helpers.c -src/engine/glib-helpers.c -src/engine/gnc-associate-account.c -src/engine/gnc-book.c -src/engine/gnc-commodity.c -src/engine/gnc-engine.c -src/engine/gnc-event.c -src/engine/gnc-numeric.c -src/engine/gnc-pricedb.c -src/engine/gncmod-engine.c -src/engine/guid.c -src/engine/kvp_frame.c -src/engine/md5.c -src/engine/test/test-load-engine.c -src/engine/test/test-commodities.c -src/engine/test/test-resolve-file-path.c -src/engine/test/test-split-vs-account.c -src/engine/test/test-freq-spec.c -src/engine/test/test-scm-query.c -src/engine/test/test-group-vs-book.c -src/engine/test/test-transaction-voiding.c -src/engine/test/test-query.c -src/engine/test/test-date.c -src/engine/test/test-period.c -src/engine/Period.c -src/engine/kvp-scm.c -src/engine/messages.c -src/engine/kvp-util.c -src/engine/gnc-session.c -src/engine/SX-ttinfo.c -src/engine/test-core/test-engine-stuff.c -src/engine/test-core/gncmod-test-engine.c -src/engine/gnc-engine-util.c +src/app-file/gnome/gnc-file-dialog.c +src/app-file/gnome/gnc-file-history.c +src/app-file/gnome/gw-app-file-gnome.c src/app-file/gnc-file.c src/app-file/gncmod-app-file.c src/app-file/test/test-link.c -src/app-file/gnome/gnc-file-history.c -src/app-file/gnome/gnc-file-dialog.c -src/experimental/cgi-bin/fastcgi-hello.c -src/experimental/cgi-bin/gnc-server.c -src/experimental/cgi-bin/hello.c -src/experimental/cgi-bin/hello2.c -src/experimental/cgi-bin/hello3.c src/gnc-module/test/misc-mods/agedver.c src/gnc-module/test/misc-mods/futuremodsys.c src/gnc-module/test/misc-mods/incompatdep.c @@ -236,22 +112,190 @@ src/gnc-module/test/mod-baz/gnc-mod-baz.c src/gnc-module/test/mod-foo/foo.c src/gnc-module/test/mod-foo/gnc-mod-foo.c src/gnc-module/gnc-module.c +src/import-export/binary-import/test/test-link-module.c +src/import-export/binary-import/binary-import.glade +src/import-export/binary-import/druid-commodity.c +src/import-export/binary-import/gncmod-binary-import.c +src/import-export/qif-import/test/test-link.c +src/import-export/qif-import/dialog-account-picker.c +src/import-export/qif-import/druid-qif-import.c +src/import-export/qif-import/gncmod-qif-import.c +src/import-export/qif-import/qif.glade +src/import-export/qif-io-core/gncmod-qifiocore.c +src/gnome-utils/test/test-link-module.c +src/gnome-utils/cursors.c +src/gnome-utils/dialog-commodity.c +src/gnome-utils/dialog-utils.c +src/gnome-utils/druid-utils.c +src/gnome-utils/gnc-account-tree.c +src/gnome-utils/gnc-amount-edit.c +src/gnome-utils/gnc-commodity-edit.c +src/gnome-utils/gnc-currency-edit.c +src/gnome-utils/gnc-date-delta.c +src/gnome-utils/gnc-date-edit.c +src/gnome-utils/gnc-frequency.c +src/gnome-utils/gnc-gui-query.c +src/gnome-utils/gnc-html-guppi.c +src/gnome-utils/gnc-html-history.c +src/gnome-utils/gnc-html.c +src/gnome-utils/gnc-mdi-utils.c +src/gnome-utils/gnc-menu-extensions.c +src/gnome-utils/gncmod-gnome-utils.c +src/gnome-utils/gtkselect.c +src/gnome-utils/print-session.c +src/gnome-utils/gnc-general-select.c +src/gnome-utils/commodity.glade +src/gnome-utils/dialog-options.c +src/gnome-utils/window-help.c +src/gnome-utils/argv-list-converters.c +src/gnome-utils/gnc-gnome-utils.c +src/report/locale-specific/us/test/test-link-module.c +src/report/locale-specific/us/gncmod-locale-reports-us.c +src/report/report-system/test/test-link-module.c +src/report/report-system/gncmod-report-system.c +src/report/report-system/gnc-report.c +src/report/standard-reports/gncmod-standard-reports.c +src/report/stylesheets/gncmod-stylesheets.c +src/report/utility-reports/gncmod-utility-reports.c +src/report/report-gnome/gncmod-report-gnome.c +src/report/report-gnome/window-report.c +src/report/report-gnome/test/test-link-module.c +src/report/report-gnome/dialog-column-view.c +src/report/report-gnome/dialog-style-sheet.c +src/report/report-gnome/report.glade +src/business/business-core/test/test-address.c +src/business/business-core/test/test-business.c +src/business/business-core/test/test-customer.c +src/business/business-core/test/test-employee.c +src/business/business-core/test/test-job.c +src/business/business-core/test/test-vendor.c +src/business/business-core/test/test-load-module.c +src/business/business-core/file/gnc-address-xml-v2.c +src/business/business-core/file/gnc-customer-xml-v2.c +src/business/business-core/file/gnc-employee-xml-v2.c +src/business/business-core/file/gnc-entry-xml-v2.c +src/business/business-core/file/gnc-invoice-xml-v2.c +src/business/business-core/file/gnc-job-xml-v2.c +src/business/business-core/file/gnc-order-xml-v2.c +src/business/business-core/file/gnc-owner-xml-v2.c +src/business/business-core/file/gnc-vendor-xml-v2.c +src/business/business-core/file/gncmod-business-backend-file.c +src/business/business-core/businessmod-core.c +src/business/business-core/gncAddress.c +src/business/business-core/gncBusiness.c +src/business/business-core/gncCustomer.c +src/business/business-core/gncEmployee.c +src/business/business-core/gncEntry.c +src/business/business-core/gncInvoice.c +src/business/business-core/gncJob.c +src/business/business-core/gncOrder.c +src/business/business-core/gncVendor.c +src/business/business-core/gncOwner.c +src/business/business-gnome/businessmod-gnome.c +src/business/business-gnome/customer.glade +src/business/business-gnome/dialog-customer.c +src/business/business-gnome/dialog-employee.c +src/business/business-gnome/dialog-job-select.c +src/business/business-gnome/dialog-job.c +src/business/business-gnome/dialog-vendor.c +src/business/business-gnome/employee.glade +src/business/business-gnome/gnc-business-utils.c +src/business/business-gnome/job.glade +src/business/business-gnome/vendor.glade +src/business/business-gnome/dialog-order.c +src/business/business-gnome/order.glade +src/business/business-gnome/business-utils.c +src/business/business-gnome/date-close.glade +src/business/business-gnome/dialog-date-close.c +src/business/business-gnome/dialog-invoice.c +src/business/business-gnome/invoice.glade +src/business/business-ledger/gncEntryLedger.c +src/business/business-ledger/gncEntryLedgerControl.c +src/business/business-ledger/gncEntryLedgerLayout.c +src/business/business-ledger/gncEntryLedgerModel.c +src/business/business-ledger/gncEntryLedgerLoad.c +src/business/business-ledger/gncEntryLedgerDisplay.c +src/tax/us/test/test-link-module.c +src/tax/us/gncmod-tax-us.c +src/engine/Account.c +src/engine/Backend.c +src/engine/DateUtils.c +src/engine/FreqSpec.c +src/engine/GNCId.c +src/engine/Group.c +src/engine/test/test-commodities.c +src/engine/test/test-freq-spec.c +src/engine/test/test-group-vs-book.c +src/engine/test/test-load-engine.c +src/engine/test/test-resolve-file-path.c +src/engine/test/test-scm-query.c +src/engine/test/test-split-vs-account.c +src/engine/test/test-transaction-voiding.c +src/engine/test/test-date.c +src/engine/test/test-query.c +src/engine/test/test-period.c +src/engine/test/test-object.c +src/engine/test/test-querynew.c +src/engine/Query.c +src/engine/SchedXaction.c +src/engine/Scrub.c +src/engine/TransLog.c +src/engine/Transaction.c +src/engine/date.c +src/engine/gnc-associate-account.c +src/engine/gnc-book.c +src/engine/gncmod-engine.c +src/engine/gnc-commodity.c +src/engine/gnc-engine-util.c +src/engine/gnc-engine.c +src/engine/gnc-event.c +src/engine/gnc-numeric.c +src/engine/gnc-pricedb.c +src/engine/kvp-scm.c +src/engine/test-core/gncmod-test-engine.c +src/engine/test-core/test-engine-stuff.c +src/engine/guid.c +src/engine/kvp_frame.c +src/engine/md5.c +src/engine/Period.c +src/engine/SX-ttinfo.c +src/engine/gnc-session.c +src/engine/engine-helpers.c +src/engine/glib-helpers.c +src/engine/messages.c +src/engine/QueryCore.c +src/engine/kvp-util.c +src/engine/QueryNew.c +src/engine/QueryObject.c +src/engine/gncObject.c +src/experimental/cgi-bin/fastcgi-hello.c +src/experimental/cgi-bin/gnc-server.c +src/experimental/cgi-bin/hello.c +src/experimental/cgi-bin/hello2.c +src/experimental/cgi-bin/hello3.c +src/network-utils/test/test-link-module.c +src/network-utils/gnc-gpg.c +src/network-utils/gnc-http.c +src/network-utils/gncmod-network-utils.c src/gnome/glade/account.glade -src/gnome/glade/commodities.glade +src/gnome/glade/sched-xact.glade src/gnome/glade/fincalc.glade +src/gnome/glade/sched-xact_strings.c src/gnome/glade/find.glade src/gnome/glade/help.glade src/gnome/glade/newuser.glade -src/gnome/glade/print.glade +src/gnome/glade/commodities.glade src/gnome/glade/price.glade +src/gnome/glade/print.glade src/gnome/glade/progress.glade src/gnome/glade/register.glade src/gnome/glade/stocks.glade -src/gnome/glade/sched-xact.glade src/gnome/glade/tax.glade src/gnome/glade/transfer.glade src/gnome/glade/userpass.glade +src/gnome/gnucash.desktop.in src/gnome/dialog-commodities.c +src/gnome/tip-of-the-day.c src/gnome/dialog-fincalc.c src/gnome/dialog-find-transactions.c src/gnome/dialog-new-user.c @@ -259,53 +303,42 @@ src/gnome/dialog-price-editor.c src/gnome/dialog-print-check.c src/gnome/dialog-progress.c src/gnome/dialog-scheduledxaction.c -src/gnome/dialog-sxsincelast.c src/gnome/dialog-tax-info.c src/gnome/dialog-totd.c src/gnome/dialog-transfer.c src/gnome/dialog-userpass.c -src/gnome/reconcile-list.c -src/gnome/window-main.c src/gnome/druid-hierarchy.c -src/gnome/top-level.c +src/gnome/dialog-sx-from-trans.c src/gnome/druid-stock-split.c -src/gnome/window-main-summarybar.c src/gnome/gnc-network.c src/gnome/gnc-splash.c src/gnome/gnucash.keys.in src/gnome/mainwindow-account-tree.c -src/gnome/window-reconcile.c +src/gnome/reconcile-list.c +src/gnome/top-level.c src/gnome/window-acct-tree.c +src/gnome/window-main-summarybar.c +src/gnome/window-main.c +src/gnome/window-reconcile.c +src/gnome/regwidget-window-register.c src/gnome/window-register.c -src/gnome/tip-of-the-day.c -src/gnome/dialog-sx-from-trans.c -src/gnome/gnucash.desktop.in -src/import-export/qif-import/dialog-account-picker.c -src/import-export/qif-import/druid-qif-import.c -src/import-export/qif-import/gncmod-qif-import.c -src/import-export/qif-import/qif.glade -src/import-export/qif-import/test/test-link.c -src/import-export/qif-io-core/gncmod-qifiocore.c -src/import-export/binary-import/druid-commodity.c -src/import-export/binary-import/gncmod-binary-import.c -src/import-export/binary-import/test/test-link-module.c -src/import-export/binary-import/binary-import.glade +src/gnome/dialog-sxsincelast.c +src/guile/gw-gnc.c +src/guile/gnucash.c src/optional/swig/gnucash-swig-defines.c src/optional/swig/helperfuncs.c -src/core-utils/core-utils.c -src/test-core/test-stuff.c -src/test-core/gncmod-test.c +src/register/ledger-core/test/test-link-module.c src/register/ledger-core/gnc-ledger-display.c src/register/ledger-core/gncmod-ledger-core.c -src/register/ledger-core/split-register-layout.c +src/register/ledger-core/split-register-control.c src/register/ledger-core/split-register-load.c src/register/ledger-core/split-register-model-save.c src/register/ledger-core/split-register-model.c src/register/ledger-core/split-register-util.c src/register/ledger-core/split-register.c -src/register/ledger-core/split-register-control.c +src/register/ledger-core/split-register-layout.c src/register/ledger-core/dialog-dup-trans.c -src/register/ledger-core/test/test-link-module.c +src/register/ledger-core/gnc-regwidget.c src/register/register-core/QuickFill.c src/register/register-core/basiccell.c src/register/register-core/cell-factory.c @@ -317,11 +350,11 @@ src/register/register-core/pricecell.c src/register/register-core/quickfillcell.c src/register/register-core/recncell.c src/register/register-core/register-common.c +src/register/register-core/test/test-link-module.c src/register/register-core/table-allgui.c src/register/register-core/table-control.c src/register/register-core/table-layout.c src/register/register-core/table-model.c -src/register/register-core/test/test-link-module.c src/register/register-gnome/combocell-gnome.c src/register/register-gnome/datecell-gnome.c src/register/register-gnome/gncmod-register-gnome.c @@ -329,29 +362,35 @@ src/register/register-gnome/gnucash-color.c src/register/register-gnome/gnucash-cursor.c src/register/register-gnome/gnucash-date-picker.c src/register/register-gnome/gnucash-grid.c -src/register/register-gnome/gnucash-header.c -src/register/register-gnome/gnucash-item-edit.c src/register/register-gnome/gnucash-item-list.c src/register/register-gnome/gnucash-scrolled-window.c -src/register/register-gnome/gnucash-sheet.c -src/register/register-gnome/gnucash-style.c +src/register/register-gnome/gnucash-item-edit.c src/register/register-gnome/pricecell-gnome.c src/register/register-gnome/quickfillcell-gnome.c src/register/register-gnome/table-gnome.c src/register/register-gnome/test/test-link-module.c +src/register/register-gnome/gnucash-sheet.c +src/register/register-gnome/gnucash-header.c +src/register/register-gnome/gnucash-style.c +src/scm/gnumeric/guile-strings.c +src/scm/guile-strings.c +src/scm/printing/guile-strings.c +src/scm/qif-import/guile-strings.c +src/scm/report/guile-strings.c +src/test-core/gncmod-test.c +src/test-core/test-stuff.c +src/core-utils/core-utils.c src/dialog-account/dialog-account.c -src/report/locale-specific/us/test/test-link-module.c -src/report/locale-specific/us/gncmod-locale-reports-us.c -src/report/report-system/test/test-link-module.c -src/report/report-system/gncmod-report-system.c -src/report/report-system/gnc-report.c -src/report/standard-reports/gncmod-standard-reports.c -src/report/stylesheets/gncmod-stylesheets.c -src/report/utility-reports/gncmod-utility-reports.c -src/report/report-gnome/window-report.c -src/report/report-gnome/gncmod-report-gnome.c -src/report/report-gnome/report.glade -src/report/report-gnome/test/test-link-module.c -src/report/report-gnome/dialog-column-view.c -src/report/report-gnome/dialog-style-sheet.c +src/gnome-search/dialog-search.c +src/gnome-search/gncmod-gnome-search.c +src/gnome-search/search-boolean.c +src/gnome-search/search-core-type.c +src/gnome-search/search-date.c +src/gnome-search/search-double.c +src/gnome-search/search-int64.c +src/gnome-search/search-numeric.c +src/gnome-search/search-param.c +src/gnome-search/search-string.c +src/gnome-search/search.glade +src/gnome-search/search-account.c intl-scm/guile-strings.c diff --git a/src/doc/TODO-schedxactions b/src/doc/TODO-schedxactions index 632cc8ab1e..40c0f59cb1 100644 --- a/src/doc/TODO-schedxactions +++ b/src/doc/TODO-schedxactions @@ -3,20 +3,6 @@ Author: jsled@asynchronous.org Main Scheduled Transaction todo list ------------------------------------ -################################################## -### Done -################################################## - -X add the ...GetFreqStr() code for the complex composite FreqSpecs -X fix the ...GetNextInstance() code -X XMLv2 I/O -X need policy for start-dates in GNCFrequency -X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs - X also needs to deal with >28-mday values WRT last-occur date + multipliers -X Engine ...Init() functions should be private. -X would like "don't even tell me you instantiated it, just fscking do - it!" option for non-manual-conf SXes - ################################################## ### To-Do ### @@ -24,6 +10,8 @@ X would like "don't even tell me you instantiated it, just fscking do ### ################################################## +. Meta + . fulfill everything on http://linas.org/linux/gnucash/projects.html#alerts . FreqSpec.c . xaccFreqSpecGetFreqStr [display] needs to go away [?] @@ -32,10 +20,11 @@ X create a template register X store account and amount data in kvp_frames. . find a way to list multiple registers for template transaction purposes. . this is a "normal" general ledger + a "stock" general ledger + . warlord's business stuff may extend this to more ledgers... . this is going to be: a tabbed notebook in which the tabs contain the number of transactions the GL they hold contain. -. register macro-widget +. register macro-widget [src/register/ledger-core/gnc-regWidget.{h,c}] . should support . toolbar . Close @@ -64,13 +53,21 @@ X create a template register . Blank . Jump . extended to support previously-menu-accessible options in embedded case - + . status bar . configurable UI elts [menu, toolbar, status] + . re-configurable UI elts + . menu: the register itself should provide a sub-menu for inclusion + into other menus [the window-register, for instance] + . toolbar: As seen above, certain toolbar elts are common, some are + appl.-specific. + . status: the status bar is sort-of a boolean option; applications + may wish to place the status bar in a more acceptable location. . default callbacks . override-able + . can "orverridable" mean "[gtk-style-]signal-based"? . bitmask of supported functionality - . !"Schedule..." for the embedded-in-SX-editor case, gray-out + . !"Schedule..." for the embedded-in-SX-editor case => gray-out . shouldn't [necessarily] support . date range [may be fixed/irrelevant by caller] . style changes [caller may enforce] @@ -79,15 +76,52 @@ X create a template register ? Hook into 'book data changed' save-on-exit decision +. GNCFrequency + . bugs + . transitioning to a new tab doesn't correctly setup the agreement + between the startdate and the page elements. + X why does the accounts window go crazy when we change the FreqSpec parameters? + X probably component-manager related... yup; FreqSpec Malloc/Free + generates events, which cause GUI refreshes. + X Example calendar month change isn't handled correctly/doesn't refresh the + marks. + X fixed by removing any ability to change the example calendar. + X "Inappropriate FreqSpec type" on new-SX editing. + X "new; weekly: click on day, click off day: GLib-CRITICAL **: file gdate.c: line 1236 (g_date_to_struct_tm): assertion `g_date_valid (d)' failed." + . no longer reproducable + . SX list . add a big calendar [gnome-pim? evo?] to SXaction List/overview . tab order . SX editor - X 'Cancel' button should auto-cancel ledger changes . tab order + . Can't click-out of the register + . 'ESC' while editing template register causes window to go away badly + . attempting to create a Weekly SX with no days selected causes a segfault. + . the user should be prevented from doing this. + X composite SX shouldn't segfault when asked to getFreqSpecStr for this + X should use regWidget + X Size/space issues [?] + X auto-shrink on window create [the register is too wide, leading to too + much whitespace on the two top panels -- sometimes]. + X Un-selecting "End Date" leaves calendar widget sensitive + X 'Cancel' button should auto-cancel ledger changes . make-from-transaction + . bugs + . you can delete a freshly-from-trans'd SX from the list with the + from-trans dlg still open, then 'ok' the dlg to get a segfault. + . creating a SX from trans with the SX list open does not update it. + . general: there's going to be all sorts of interaction issues like these + between these things [SX-from-trans, SX list, SX editor] that should be + handled. + . tab-order + . better frequency guess? + [related...] + . match existing transactions for long-time users + . based off template-transaction data, some big existing-transaction + scanning code. X credit/debit pull-over issues X need to remove '-' from printed credit value. X pull accounts over. @@ -95,15 +129,39 @@ X create a template register X need start-date on Make dialog X [initially starts as the next occurance after the created-from SX, which may not be the Right Thing] - . better frequency guess? - . non-trivial problem - [related...] - . match existing transactions for long-time users - . based off template-transaction data, some big existing-transaction - scanning code. - . tab-order . need "since-last-run" UI for instanatiation. + . need effective cancellation support + . need nifty visual style + . use color-setting code in src/gnome-utils/druid-utils.[ch] + . support sorting in clists + . tab-order + . variable-binding table: + . tab through variables -- if on last one: ( if something's unfilled, + tab back to there, else, tab back to clist:( if no more unfilled + entries, then tab down to back/next/cancel. )) + . Double-clicking on auto-create list should jump to transaction + . register of first split? + . Need some way to defer to-create SXes? + . need some configuration for constantly-running GnuCash users of when to + pop up the 'new scheduled transactions' dialog [option, time-of-day] + . fix first/last page issues. + . bugs + . correct "Back" button behavior in Druid paradigm + . tab-order on variable-entry window isn't always correct. + . created SXes are put in GL forever... :( + . inital "To-Create Transactions" varbinding table doesn't setup table correctly. + X twunder reports [2002.01.29] register growing a little bit at a time if + tab is hit to switch between register fields -- started with update on + 1/21. + X I _bet_ this is fixed with magic gnc-regWidget sizing fix -- 2002.04.15 + X "0" and "0.0" don't work for variable values? + X correct "Cancel" behavior in Druid + X reset SX state to before creation + X delete any created SXes. + X restore any obsolete-n-deleted SXes. + X variable expressions don't get re-eval'd [as formula]? + X need to do this only on tab-out of the field. X Change from dialogs to druid X/O create transactions X numeric @@ -111,6 +169,7 @@ X create a template register X need variable fill-in UI... X re-use gnome-sheet code for a variable-binding table? -- ended up using GtkTable [for now?] + X variables should default to '0', and '0' should be acceptable. X need way to expire/purge scheduled transactions which have no chance of being created [outside their end date; once-scheduled and past]. X infrequent enough that a dialog should suffice. @@ -118,33 +177,31 @@ X create a template register X Is it sufficient to look at the next instance of ea. transaction only? I think not... we probably want to look out until the transaction is outside the reminder range. - . support sorting in clists - . tab-order - . need some configuration for constantly-running GnuCash users of when to - pop up the 'new scheduled transactions' dialog [option, time-of-day] X Should deal with "nothing-to-do" better [not even show up in the worst [read: no auto-notify/to-create/reminders] case]. X don't load/init/create the GUI if we're not about to use it. X this is different between the auto-invoked since-last-run dialog [show nothing] and the menu-invoked since-last-run [show a dialog to the user stating there's nothing to do]. - . Double-clicking on auto-create list should jump to transaction - . register of first split? X double-clicking a reminder should [probably] move it up to the to-create list. X Easy UI way of moving through the SXes which need variable bindings. [This presently is: click "Ok" and the next clist row which needs bindings is selected.] - . Need some way to defer to-create SXes? + X any [horizontal] window size change height-grows the top/auto-create GL. + X always goes one date past the instantiation date. + X credit and debit seem reversed at instantiation time... + X this is fixed, but is the fix correct? -. register mods - . to see upcoming xactions, modifying future balance - . to note which are "recurring" - . the mozilla "reload" glyph is kinda neat... - . Differently-colored "not-yet-created" entries for a configurable - time window. - . Context menus/sensitive toolbar button/menu item for creation of - not-yet-created transactions. +. register mods? + . to see upcoming xactions, modifying future balance? + . to note which are "recurring" + . the mozilla "reload" glyph is kinda neat... + . prolly should use existing PIM "recurring" glyphs + . Differently-colored "not-yet-created" entries for a configurable + time window? + . Context menus/sensitive toolbar button/menu item for creation of + not-yet-created transactions? . The ability to turn a non-recurring transaction into a recurring one... X [see from-trans section] . inactive cells @@ -161,21 +218,38 @@ X create a template register . only a couple left; which ones? . backend support - . PostgreSQL + . SQL . others? +################################################## +### Done +### ... don't put stuff here ... just move it to the bottom of the +### appropriate list, above, and 'X' it -- jsled +################################################## + +X add the ...GetFreqStr() code for the complex composite FreqSpecs +X fix the ...GetNextInstance() code +X XMLv2 I/O +X need policy for start-dates in GNCFrequency +X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs + X also needs to deal with >28-mday values WRT last-occur date + multipliers +X Engine ...Init() functions should be private. +X would like "don't even tell me you instantiated it, just fscking do + it!" option for non-manual-conf SXes + --------------- +Random Notes . SX Creation... . Creation occurs due to a variety of circumstances: - X GnuCash starts and hasn't been run in some length of time; the - transactions which have "come due" since the last run are available for - creation. . A user opens a register with future transactions in it; they manually force the creation of the [perhaps not immediately next [though this seems a bit weird]] one. . A user is reminded of something which hasn't come due, but will w/in a configurable amount of time, and thus they pay/create it. + X GnuCash starts and hasn't been run in some length of time; the + transactions which have "come due" since the last run are available for + creation. . Configuration options... . Overall @@ -220,49 +294,10 @@ X General X Date l10n. . GNCFreqency - X why does the accounts window go crazy when we change the FreqSpec parameters? - X probably component-manager related... yup; FreqSpec Malloc/Free - generates events, which cause GUI refreshes. - . transitioning to a new tab doesn't correctly setup the agreement between - the startdate and the page elements. - X Example calendar month change isn't handled correctly/doesn't refresh the - marks. - X fixed by removing any ability to change the example calendar. - X "Inappropriate FreqSpec type" on new-SX editing. - X "new; weekly: click on day, click off day: GLib-CRITICAL **: file gdate.c: line 1236 (g_date_to_struct_tm): assertion `g_date_valid (d)' failed." - . no longer reproducable - -. Scheduled Transaction Editor - . Can't click-out of the register - . 'ESC' while editing template register causes window to go away [badly]. - . attempting to create a Weekly SX with no days selected causes a segfault. - . the user should be prevented from doing this. - X composite SX shouldn't segfault when asked to getFreqSpecStr for this - X Size/space issues [?] - X auto-shrink on window create [the register is too wide, leading to too - much whitespace on the two top panels -- sometimes]. - X Un-selecting "End Date" leaves calendar widget sensitive - -. Scheduled Transaction List . Since-last-run - . correct "Back" button behavior in new Druid paradigm - . correct "Cancel" behavior in Druid - . reset SX state to before creation - . delete any created SXes. - . restore any obsolete-n-deleted SXes. - . tab-order on variable-entry window isn't always correct. - X any [horizontal] window size change height-grows the top/auto-create GL. - X always goes one date past the instantiation date. - X credit and debit seem reversed at instantiation time... - X this is fixed, but is the fix correct? . SX-from-trans - . you can delete a freshly-from-trans'd SX from the list with the - from-trans dlg still open, then 'ok' the dlg to get a segfault. - . creating a SX from trans with the SX list open does not update it. - . general: there's going to be all sorts of interaction issues like these - between these things [SX-from-trans, SX list, SX editor] that should be handled. ################################################## ### Enhancements @@ -405,7 +440,7 @@ window-register notes: . RegWindow *regWindowSimple (Account *account) . RegWindow *regWindowAccGroup (Account *account) . functionality should remain, probably in reg mwidget - + . I now disagree; this should be the caller [for templates, especially] . void gnc_register_raise (RegWindow *regData) . probably should remain here; if the reg mwidget has knowledge of it's @@ -416,12 +451,13 @@ window-register notes: . should be part of mwidget . static void gnc_register_change_style (RegWindow *regData, SplitRegisterStyle style) -. static void gnc_register_style_(ledger|auto_ledger|journal|double_line_cb (GtkWidget *w, gpointer data) - . mwidget +. static void gnc_register_style_(ledger|auto_ledger|journal|double_line)_cb (GtkWidget *w, gpointer data) + . mwidget [no] . static void gnc_register_sort_(standard|date|date_entered|date_reconciled|num|amount|memo|desc)_cb(GtkWidget *w, gpointer data) . static void gnc_register_sort (RegWindow *regData, sort_type_t sort_code) - . mwidget + . mwidget? -- actually seems like container's responsibility. + . then, need some way to get the ledger->query for manip. . some of these may not make sense in embedded applications . static time_t gnc_register_(min|max)_day_time(time_t time_val) @@ -437,15 +473,19 @@ window-register notes: . static void gnc_register_show_date_window(RegWindow *regData) . static RegDateWindow *gnc_register_date_window (RegWindow *regData, gboolean show_all) . need DateWindow policy/decision. + . decision: caller's responsibility. . static GtkWidget *gnc_register_create_tool_bar (RegWindow *regData) . mwidget + . should use passed-in toolbar, with clear contract about how the caller + should add/manip the [modified] toolbar provided. . static void gnc_ui_find_transactions_cb (GtkWidget *widget, gpointer data) - . necessary for embedded applications? + . necessary for embedded applications? [nope] . static GtkWidget *add_summary_label (GtkWidget *summarybar, const char *label_str) . mwidget [option] + . eh? . static GtkWidget *gnc_register_create_summary_bar (RegWindow *regData) . static GtkWidget *gnc_register_create_status_bar (RegWindow *regData) @@ -480,7 +520,7 @@ window-register notes: . static gnc_numeric gnc_account_present_balance (Account *account) . static GNCPrice *account_latest_price (Account *account) - . mwidget? + . mwidget? [nope ... in fact, not even in window-register] . static void startRecnCB(GtkWidget * w, gpointer data) . recn: configurable behavior diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 6aece094be..d53ea4b6c2 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -162,9 +162,9 @@ gncmod-engine.c: gw-engine.h gnc-commodity.c: iso-4217-currencies.c -iso-4217-currencies.c: .scm-links iso-4217-currencies.scm iso-currencies-to-c - chmod u+x ${srcdir}/iso-currencies-to-c - GUILE_LOAD_PATH=${top_srcdir}/lib/ ${srcdir}/iso-currencies-to-c +iso-4217-currencies.c: iso-4217-currencies.scm iso-currencies-to-c + chmod u+x ./iso-currencies-to-c + GUILE_LOAD_PATH=${top_srcdir}/lib/:${GUILE_LOAD_PATH} ${srcdir}/iso-currencies-to-c gw-engine.scm gw-engine.c gw-engine.h: .scm-links gw-engine-spec.scm FLAVOR=gnome guile -c \ diff --git a/src/engine/Query.c b/src/engine/Query.c index 9888c013b8..7e37e1cbbd 100644 --- a/src/engine/Query.c +++ b/src/engine/Query.c @@ -72,6 +72,9 @@ struct query_s /* list of books that will be participating in the query */ BookList *books; + /* Flag to indicate if we're searching over template-transactions, too. */ + gboolean templates_too; + /* cache the results so we don't have to run the whole search * again until it's really necessary */ int changed; @@ -103,7 +106,6 @@ static int xaccValueMatchPredicate(Split * s, PredicateData * pd); /******************************************************************** ********************************************************************/ - void xaccQueryPrint(Query * q) { @@ -288,6 +290,14 @@ xaccQueryPrint(Query * q) } } +void +xaccQuerySearchTemplateGroup( Query *q, gboolean newState ) +{ + if (!q) + return; + q->templates_too = newState; +} + /******************************************************************** * xaccInitQuery @@ -328,6 +338,8 @@ xaccInitQuery(Query * q, QueryTerm * initial_term) q->primary_increasing = TRUE; q->secondary_increasing = TRUE; q->tertiary_increasing = TRUE; + + q->templates_too = FALSE; } @@ -646,6 +658,8 @@ xaccQueryCopy(Query *q) copy->changed = q->changed; copy->split_list = g_list_copy (q->split_list); copy->xtn_list = g_list_copy (q->xtn_list); + + copy->templates_too = q->templates_too; return copy; } @@ -1328,6 +1342,12 @@ xaccQueryGetSplits(Query * q) GNCBook *book = node->data; all_accts = g_list_concat (all_accts, xaccGroupGetSubAccounts (gnc_book_get_group(book))); + /* If we're searching template accounts, then add them. */ + if ( q->templates_too ) { + all_accts = + g_list_concat( all_accts, + xaccGroupGetSubAccounts( gnc_book_get_template_group(book) ) ); + } } for (node = all_accts; node; node = node->next) diff --git a/src/engine/Query.h b/src/engine/Query.h index 99013d5326..ceb30e38ba 100644 --- a/src/engine/Query.h +++ b/src/engine/Query.h @@ -229,6 +229,10 @@ gboolean xaccQueryEqual(Query *q1, Query *q2); /* handy for debugging */ void xaccQueryPrint(Query *q); +/* (Un-)set the Query's search to look at the template account group used by + * scheduled transactions, as well. */ +void xaccQuerySearchTemplateGroup( Query *, gboolean ); + /******************************************************************* * match-adding API *******************************************************************/ diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index 6f7f66a626..9881f7bf2c 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -43,10 +43,19 @@ static short module = MOD_SX; /** Local data defs *****/ -void sxprivtransactionListMapDelete( gpointer data, gpointer user_data ); + +/* Just the temporal bits from the SX structure. */ +typedef struct _temporalStateData { + GDate last_date; + GDate start_date; + GDate end_date; + gint num_occur_total; + gint num_occur_rem; +} temporalStateData; /** Local Prototypes *****/ +void sxprivtransactionListMapDelete( gpointer data, gpointer user_data ); static void xaccSchedXactionInit( SchedXaction *sx, GNCBook *book) @@ -635,8 +644,10 @@ xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list, void* xaccSchedXactionCreateSequenceState( SchedXaction *sx ) { - void *toRet = NULL; + //void *toRet = NULL; + return gnc_sx_create_temporal_state_snapshot( sx ); + /* if ( xaccSchedXactionHasOccurDef( sx ) ) { toRet = g_new0( gint, 1 ); *(gint*)toRet = xaccSchedXactionGetRemOccur( sx ); @@ -644,26 +655,65 @@ xaccSchedXactionCreateSequenceState( SchedXaction *sx ) } else { DEBUG( "Returning null state data" ); } - return toRet; + */ + //return toRet; } void xaccSchedXactionIncrSequenceState( SchedXaction *sx, void *stateData ) { + if ( xaccSchedXactionHasOccurDef( sx ) ) { + temporalStateData *tsd = (temporalStateData*)stateData; + tsd->num_occur_rem -= 1; + } +#if 0 /* change to temporal_state */ if ( xaccSchedXactionHasOccurDef( sx ) ) { gint *remaining; remaining = (gint*)stateData; *remaining = *remaining - 1; } +#endif /* 0 */ } void -xaccSchedXactionDestroySequenceState( SchedXaction *sx, - void *stateData ) +xaccSchedXactionDestroySequenceState( void *stateData ) { + gnc_sx_destroy_temporal_state_snapshot( stateData ); +#if 0 /* change to temporal_state */ if ( xaccSchedXactionHasOccurDef( sx ) ) { g_free( (gint*)stateData ); } +#endif /* 0 */ } +void +*gnc_sx_create_temporal_state_snapshot( SchedXaction *sx ) +{ + temporalStateData *toRet = g_new0( temporalStateData, 1 ); + toRet->last_date = sx->last_date; + toRet->start_date = sx->start_date; + toRet->end_date = sx->end_date; + toRet->num_occur_total = sx->num_occurances_total; + toRet->num_occur_rem = sx->num_occurances_remain; + return (void*)toRet; +} + +void +gnc_sx_revert_to_temporal_state_snapshot( SchedXaction *sx, void *stateData ) +{ + temporalStateData *tsd = (temporalStateData*)stateData; + sx->last_date = tsd->last_date; + sx->start_date = tsd->start_date; + sx->end_date = tsd->end_date; + sx->num_occurances_total = tsd->num_occur_total; + sx->num_occurances_remain = tsd->num_occur_rem; + + sx->dirty = TRUE; +} + +void +gnc_sx_destroy_temporal_state_snapshot( void *stateData ) +{ + g_free( (temporalStateData*)stateData ); +} diff --git a/src/engine/SchedXaction.h b/src/engine/SchedXaction.h index fe46215ea3..0f120cb21b 100644 --- a/src/engine/SchedXaction.h +++ b/src/engine/SchedXaction.h @@ -161,6 +161,7 @@ void xaccSchedXactionSetSlot( SchedXaction *sx, const GUID *xaccSchedXactionGetGUID( SchedXaction *sx ); void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g ); +///@{ /** * Next-Instance state data. * @@ -179,7 +180,26 @@ void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g ); **/ void *xaccSchedXactionCreateSequenceState( SchedXaction *sx ); void xaccSchedXactionIncrSequenceState( SchedXaction *sx, void *stateData ); -void xaccSchedXactionDestroySequenceState( SchedXaction *sx, void *stateData ); +void xaccSchedXactionDestroySequenceState( void *stateData ); +///@} + +///@{ +/** + * Temporal state data. + * + * These functions allow us to opaquely save the entire temporal state of + * ScheduledTransactions. This is used by the "since-last-run" dialog to + * store the initial state of SXes before modification ... if it later + * becomes necessary to revert an entire set of changes, we can 'revert' the + * SX without having to rollback all the individual state changes. + * + * NOTE that this is similar to the above SequenceState interface, and + * perhaps can be seen as entailing the above interface. + **/ +void *gnc_sx_create_temporal_state_snapshot( SchedXaction *sx ); +void gnc_sx_revert_to_temporal_state_snapshot( SchedXaction *sx, void *stateData ); +void gnc_sx_destroy_temporal_state_snapshot( void *stateData ); +///@} /** * Returns the next occurance of a scheduled transaction. If the diff --git a/src/gnome/dialog-scheduledxaction.c b/src/gnome/dialog-scheduledxaction.c index 97e9450a60..df08e34ab6 100644 --- a/src/gnome/dialog-scheduledxaction.c +++ b/src/gnome/dialog-scheduledxaction.c @@ -47,6 +47,8 @@ #include "window-help.h" #include "window-register.h" +#include "gnc-regwidget.h" + /* FIXME: temp until variable-related-stuff settled. */ #include "dialog-sxsincelast.h" @@ -72,6 +74,8 @@ static short module = MOD_SX; #define END_DATE_OPTION 1 #define NUM_OCCUR_OPTION 2 +#define NUM_LEDGER_LINES_DEFAULT 6 + /** Datatypes ***********************************************************/ /* FIXME: this is stolen from window-register.c */ @@ -98,18 +102,18 @@ struct _SchedXactionDialog struct _SchedXactionEditorDialog { - GladeXML *gxml; - GtkWidget *dialog; - SchedXactionDialog *sxd; - SchedXaction *sx; + GladeXML *gxml; + GtkWidget *dialog; + SchedXactionDialog *sxd; + SchedXaction *sx; int new; - GNCLedgerDisplay *ledger; - GnucashRegister *reg; + GNCLedgerDisplay *ledger; + GnucashRegister *reg; - GNCFrequency *gncfreq; + GNCFrequency *gncfreq; - char *sxGUIDstr; + char *sxGUIDstr; GtkWidget *toolbar; }; @@ -178,8 +182,8 @@ sxed_close_handler ( gpointer user_data ) gnc_sxed_reg_check_close( sxed ); - gnc_ledger_display_close( sxed->ledger ); - sxed->ledger = NULL; + /*gnc_ledger_display_close( sxed->ledger );*/ + /*sxed->ledger = NULL;*/ g_free (sxed->sxGUIDstr); sxed->sxGUIDstr = NULL; @@ -485,7 +489,7 @@ gnc_ui_scheduled_xaction_dialog_create(void) gnc_register_gui_component( DIALOG_SCHEDXACTION_CM_CLASS, NULL, /* no refresh handler */ - sxd_close_handler, + sxd_close_handler, sxd ); gtk_signal_connect( sxdo, "destroy", @@ -719,238 +723,6 @@ schedXact_editor_init( SchedXactionEditorDialog *sxed ) } - -static -GtkWidget * -schedXaction_editor_create_reg_popup( SchedXactionEditorDialog *sxed ) -{ - GtkWidget *popup; - - static GnomeUIInfo transaction_menu[] = - { - { - GNOME_APP_UI_ITEM, - N_("_Enter"), - N_("Record the current transaction"), - sxed_reg_recordCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("_Cancel"), - N_("Cancel the current transaction"), - sxed_reg_cancelCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("_Delete"), - N_("Delete the current transaction"), - sxed_reg_deleteCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, - { - GNOME_APP_UI_ITEM, - N_("D_uplicate"), - N_("Make a copy of the current transaction"), - sxed_reg_duplicateCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("_Schedule..."), - N_("Create a scheduled transaction using the current one as a template"), - NULL, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, - { - GNOME_APP_UI_TOGGLEITEM, - N_("_Split"), - N_("Show all splits in the current transaction"), - sxed_reg_expand_trans_checkCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("_Blank"), - N_("Move to the blank transaction at the " - "bottom of the register"), - sxed_reg_new_transCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("_Jump"), - N_("Jump to the corresponding transaction in " - "the other account"), - sxed_reg_jumpCB, NULL, NULL, - GNOME_APP_PIXMAP_NONE, NULL, - 0, 0, NULL - }, - GNOMEUIINFO_END - }; - - gnc_fill_menu_with_data( transaction_menu, sxed ); - - popup = gnome_popup_menu_new (transaction_menu); - - return popup; -} - -static GtkWidget * -schedXaction_editor_create_reg_tool_bar( SchedXactionEditorDialog *sxed ) -{ - /* RegWindow *regData */ - GtkWidget *toolbar; - - static GnomeUIInfo toolbar_info[] = - { -/* - { - GNOME_APP_UI_ITEM, - N_("Close"), - N_("Close this register window"), - sxed_close_handler, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CLOSE, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, -*/ - { - GNOME_APP_UI_ITEM, - N_("Enter"), - N_("Record the current transaction"), - sxed_reg_recordCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_ADD, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("Cancel"), - N_("Cancel the current transaction"), - sxed_reg_cancelCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_UNDELETE, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("Delete"), - N_("Delete the current transaction"), - sxed_reg_deleteCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_TRASH, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, - { - GNOME_APP_UI_ITEM, - N_("Duplicate"), - N_("Make a copy of the current transaction"), - sxed_reg_duplicateCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_COPY, - 0, 0, NULL - }, -/* - { - GNOME_APP_UI_ITEM, - N_("Schedule"), - N_("Create a scheduled transaction using the current one as a template"), - NULL, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_LINE_IN, - 0, 0, NULL - }, -*/ - GNOMEUIINFO_SEPARATOR, -/* - { - GNOME_APP_UI_TOGGLEITEM, - N_("Split"), - N_("Show all splits in the current transaction"), - expand_trans_cb, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_BOOK_OPEN, - 0, 0, NULL - }, -*/ - { - GNOME_APP_UI_ITEM, - N_("Blank"), - N_("Move to the blank transaction at the " - "bottom of the register"), - sxed_reg_new_transCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_NEW, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("Jump"), - N_("Jump to the corresponding transaction in " - "the other account"), - sxed_reg_jumpCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_JUMP_TO, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, - { - GNOME_APP_UI_ITEM, - N_("Transfer"), - N_("Transfer funds from one account to another"), - sxed_reg_xferCB, NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CONVERT, - 0, 0, NULL - }, - GNOMEUIINFO_SEPARATOR, - { - GNOME_APP_UI_ITEM, - N_("Find"), - N_("Find transactions with a search"), - /* FIXME:gnc_ui_find_transactions_cb */ NULL, - NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_SEARCH, - 0, 0, NULL - }, -/* - { - GNOME_APP_UI_ITEM, - N_("Report"), - N_("Open a report window for this register"), - reportCB, - NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_BOOK_GREEN, - 0, 0, NULL - }, - { - GNOME_APP_UI_ITEM, - N_("Print"), - N_("Print a report for this register"), - printReportCB, - NULL, NULL, - GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_PRINT, - 0, 0, NULL - }, -*/ - GNOMEUIINFO_END - }; - - toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH); - - gnome_app_fill_toolbar_with_data (GTK_TOOLBAR(toolbar), toolbar_info, - NULL, sxed); - - sxed->toolbar = toolbar; - - /* regData->split_button = toolbar_info[9].widget; */ - - return toolbar; -} - static void schedXact_editor_create_freq_sel( SchedXactionEditorDialog *sxed ) @@ -986,27 +758,61 @@ schedXact_editor_create_ledger( SchedXactionEditorDialog *sxed ) { GtkFrame *tempxaction_frame; SplitRegister *splitreg; - GtkWidget *regWidget, *vbox, *popup, *toolbar; -#define NUM_LEDGER_LINES_DEFAULT 6 + GtkWidget *regWidget, *vbox, *toolbar; int numLedgerLines = NUM_LEDGER_LINES_DEFAULT; tempxaction_frame = GTK_FRAME( glade_xml_get_widget( sxed->gxml, "tempxaction_frame" ) ); + vbox = glade_xml_get_widget( sxed->gxml, "register_vbox" ); + sxed->sxGUIDstr = guid_to_string( xaccSchedXactionGetGUID(sxed->sx) ); sxed->ledger = gnc_ledger_display_template_gl( sxed->sxGUIDstr ); - - gnc_ledger_display_set_handlers( sxed->ledger, - sxe_ledger_destroy, - sxe_ledger_get_parent ); - gnc_ledger_display_set_user_data( sxed->ledger, (gpointer)sxed ); - splitreg = gnc_ledger_display_get_split_register( sxed->ledger ); numLedgerLines = (int)gnc_lookup_number_option( SX_OPT_STR, "Template Register Lines", NUM_LEDGER_LINES_DEFAULT ); + gnucash_register_set_initial_rows(numLedgerLines); + + regWidget = gnc_regWidget_new( sxed->ledger, + GTK_WINDOW(sxed->dialog) ); + gtk_box_pack_start( GTK_BOX(vbox), + gnc_regWidget_get_toolbar( GNC_REGWIDGET(regWidget) ), + TRUE, TRUE, 2 ); + { + GtkWidget *popup, *tmpMenu, *tmpMI; + /* Fixup the popup menu with the menus that would normally be in the + * menu-bar of the window-register. */ + popup = gnc_regWidget_get_popup( GNC_REGWIDGET(regWidget) ); + gtk_menu_append( GTK_MENU(popup), gtk_menu_item_new() ); + + tmpMenu = gnc_regWidget_get_edit_menu( GNC_REGWIDGET(regWidget) ); + tmpMI = gtk_menu_item_new_with_label( N_("Edit") ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(tmpMI), tmpMenu ); + gtk_menu_append( GTK_MENU(popup), tmpMI ); + + tmpMenu = gnc_regWidget_get_style_menu( GNC_REGWIDGET(regWidget) ); + tmpMI = gtk_menu_item_new_with_label( N_("Style") ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(tmpMI), tmpMenu ); + gtk_menu_append( GTK_MENU(popup), tmpMI ); + + tmpMenu = gnc_regWidget_get_sort_menu( GNC_REGWIDGET(regWidget) ); + tmpMI = gtk_menu_item_new_with_label( N_("Sort") ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(tmpMI), tmpMenu ); + gtk_menu_append( GTK_MENU(popup), tmpMI ); + + gtk_widget_show_all( popup ); + } + gtk_box_pack_start( GTK_BOX(vbox), regWidget, TRUE, TRUE, 2 ); + +#if 0 + gnc_ledger_display_set_handlers( sxed->ledger, + sxe_ledger_destroy, + sxe_ledger_get_parent ); + gnc_ledger_display_set_user_data( sxed->ledger, (gpointer)sxed ); + /* Watch the order of operations, here... */ gnucash_register_set_initial_rows( numLedgerLines ); @@ -1015,8 +821,6 @@ schedXact_editor_create_ledger( SchedXactionEditorDialog *sxed ) sxed->reg = GNUCASH_REGISTER(regWidget); GNUCASH_SHEET(sxed->reg->sheet)->window = GTK_WIDGET(sxed->dialog); - vbox = glade_xml_get_widget( sxed->gxml, "register_vbox" ); - popup = schedXaction_editor_create_reg_popup( sxed ); gnucash_register_attach_popup( sxed->reg, popup, sxed ); @@ -1025,6 +829,7 @@ schedXact_editor_create_ledger( SchedXactionEditorDialog *sxed ) gtk_box_pack_start( GTK_BOX(vbox), toolbar, FALSE, FALSE, 2 ); gtk_box_pack_end( GTK_BOX(vbox), regWidget, TRUE, TRUE, 2 ); +#endif /* 0 */ #if 0 gtk_signal_connect( GTK_OBJECT(sxed->dialog), "activate_cursor", @@ -1569,115 +1374,6 @@ refactor_transaction_delete_query(GtkWindow *parent) return return_value; } -static -void -sxed_reg_deleteCB( GtkWidget *w, gpointer d ) -{ - /* FIXME: this is C&P from window-register.c. As it's the - identical code [modulo the SplitReg userdata-lookup], it - should be refactored. */ - SchedXactionEditorDialog *sxed = d; - SplitRegisterStyle style; - CursorClass cursor_class; - SplitRegister *reg; - Transaction *trans; - char *buf = NULL; - Split *split; - gint result; - - reg = gnc_ledger_display_get_split_register (sxed->ledger); - - /* get the current split based on cursor position */ - split = gnc_split_register_get_current_split (reg); - if (split == NULL) - { - gnc_split_register_cancel_cursor_split_changes (reg); - return; - } - - trans = xaccSplitGetParent(split); - style = reg->style; - cursor_class = gnc_split_register_get_current_cursor_class(reg); - - /* Deleting the blank split just cancels */ - { - Split *blank_split = gnc_split_register_get_blank_split (reg); - - if (split == blank_split) - { - gnc_split_register_cancel_cursor_trans_changes (reg); - return; - } - } - - if (cursor_class == CURSOR_CLASS_NONE) - return; - - /* On a split cursor, just delete the one split. */ - if (cursor_class == CURSOR_CLASS_SPLIT) - { - const char *format = _("Are you sure you want to delete\n %s\n" - "from the transaction\n %s ?"); - /* ask for user confirmation before performing permanent damage */ - buf = g_strdup_printf(format, xaccSplitGetMemo(split), - xaccTransGetDescription(trans)); - - /* result = gnc_verify_dialog_parented(sxed->dialog, buf, FALSE); */ - result = TRUE; - - g_free(buf); - - if (!result) - return; - - gnc_split_register_delete_current_split (reg); - return; - } - - g_return_if_fail (cursor_class == CURSOR_CLASS_TRANS); - - /* On a transaction cursor with 2 or fewer splits in single or double - * mode, we just delete the whole transaction, kerblooie */ - if ((xaccTransCountSplits(trans) <= 2) && (style == REG_STYLE_LEDGER)) - { - const char *message = _("Are you sure you want to delete the current " - "transaction?"); - - result = gnc_verify_dialog_parented(sxed->dialog, message, FALSE); - - if (!result) - return; - - gnc_split_register_delete_current_trans (reg); - return; - } - - /* At this point we are on a transaction cursor with more than 2 splits - * or we are on a transaction cursor in multi-line mode or an auto mode. - * We give the user two choices: delete the whole transaction or delete - * all the splits except the transaction split. */ - { - DeleteType del_type; - - del_type = refactor_transaction_delete_query(GTK_WINDOW(sxed->dialog)); - - if (del_type == DELETE_CANCEL) - return; - - if (del_type == DELETE_TRANS) - { - gnc_split_register_delete_current_trans (reg); - return; - } - - if (del_type == DELETE_SPLITS) - { - gnc_split_register_emtpy_current_trans (reg); - return; - } - } -} - static void sxed_reg_duplicateCB( GtkWidget *w, gpointer d ) diff --git a/src/gnome/dialog-sxsincelast.c b/src/gnome/dialog-sxsincelast.c index 9a52bcbfb7..6c90fed23d 100644 --- a/src/gnome/dialog-sxsincelast.c +++ b/src/gnome/dialog-sxsincelast.c @@ -32,7 +32,10 @@ * . Page 5: obsolete list * . backed by: sxsld->toRemoveList * . Page 6: finish - * . implement changes? + * . allow user last chance to revert/cancel changes. If we need to do + * this, we'll go through our created lists and destroy a bunch of + * things. In the future, we'd rather use this page to implement changes + * after approval. **/ #include "config.h" @@ -58,6 +61,7 @@ #include "split-register.h" #include "gnc-ledger-display.h" #include "gnucash-sheet.h" +#include "gnc-regwidget.h" #include "dialog-sxsincelast.h" @@ -91,12 +95,12 @@ #define CANCEL_BUTTON "cancel_button" #define VARIABLE_TABLE "variables_table" #define AUTO_CREATE_VBOX "ac_vbox" +#define CREATED_VBOX "created_vbox" #define TO_CREATE_CLIST_WIDTH 3 #define REMINDER_CLIST_WIDTH 3 #define SX_OBSOLETE_CLIST_WIDTH 3 - #define COERCE_VOID_TO_GBOOLEAN(x) ((gboolean)(*#x)) #ifdef HAVE_LANGINFO_D_FMT @@ -124,23 +128,34 @@ static short module = MOD_SX; * signal handler: e.g., a since-last dialog with only obsolete SXes would go * through the 'prep' methods of all it's pages to reach the Obsolete page. **/ - typedef struct _sxSinceLastData { GtkWidget *sincelast_window; GnomeDruid *sincelast_druid; GladeXML *gxml; + /* Multi-stage processing-related stuff... */ GList /* */ *autoCreateList; GList /* */ *toCreateList; GList /* */ *reminderList; GList /* */ *toRemoveList; + /********** "Cancel"-related stuff... **********/ + + /** A HashTable of SX mapped to initial temporal data. */ + GHashTable /* */ *sxInitStates; + /** The list of removed SXes, in case we need to revert/cancel. */ + GList /* */ *removedList; + /** The list of GUIDs of Txns we've created... */ + GList /* */ *createdTxnGUIDList; + gboolean autoCreatedSomething; + gboolean createdSomething; GNCLedgerDisplay *ac_ledger; - GnucashRegister *reg; + GNCRegWidget *ac_regWidget; - Query *autoCreateQuery; + GNCLedgerDisplay *created_ledger; + GNCRegWidget *created_regWidget; /** Next reminder clist row index to create. **/ gint rl_row; @@ -178,27 +193,21 @@ typedef struct creation_helper_userdata_ { /* the to-create tuple */ toCreateTuple *tct; /* a [pointer to a] GList to append the GUIDs of newly-created - * transactions to, or NULL */ + * Transactions to, or NULL */ GList **createdGUIDs; } createData; static void sxsincelast_init( sxSinceLastData *sxsld ); -static void create_autoCreate_gen_ledger( sxSinceLastData *sxsld ); +static void create_autoCreate_ledger( sxSinceLastData *sxsld ); +static void create_created_ledger( sxSinceLastData *sxsld ); static gncUIWidget sxsld_ledger_get_parent( GNCLedgerDisplay *ld ); static gboolean sxsincelast_populate( sxSinceLastData *sxsld ); static void sxsincelast_druid_cancelled( GnomeDruid *druid, gpointer ud ); static void sxsincelast_close_handler( gpointer ud ); -#if 0 -static void sxsincelast_ok_clicked( GtkButton *b, gpointer ud ); - -static void sxsincelast_cancel_clicked( GtkButton *b, gpointer ud ); -#endif static void sxsincelast_entry_changed( GtkEditable *e, gpointer ud ); - static void sxsincelast_destroy( GtkObject *o, gpointer ud ); - static void create_transactions_on( SchedXaction *sx, GDate *gd, toCreateTuple *tct, @@ -273,6 +282,7 @@ gnc_ui_sxsincelast_dialog_create() sxSinceLastData *sxsld = g_new0( sxSinceLastData, 1 ); sxsld->toCreateList = sxsld->reminderList = sxsld->toRemoveList = NULL; + sxsld->sxInitStates = g_hash_table_new( g_direct_hash, g_direct_equal ); if ( ! sxsincelast_populate( sxsld ) ) { g_free( sxsld ); @@ -287,7 +297,6 @@ gnc_ui_sxsincelast_dialog_create() sxsld->sincelast_druid = GNOME_DRUID( glade_xml_get_widget( sxsld->gxml, SXSLD_DRUID_GLADE_NAME ) ); - sxsincelast_init( sxsld ); return TRUE; } @@ -309,11 +318,11 @@ typedef struct { } widgetSignalHandlerTuple; typedef struct { - char *pageName; - void (*prepareHandlerFn)(); + char *pageName; + void (*prepareHandlerFn)(); gboolean (*backHandlerFn)(); gboolean (*nextHandlerFn)(); - void (*finishHandlerFn)(); + void (*finishHandlerFn)(); gboolean (*cancelHandlerFn)(); } druidSignalHandlerTuple; @@ -396,19 +405,17 @@ theres_no_turning_back_bang( GnomeDruidPage *druid_page, return TRUE; } -static void -reminders_prep( GnomeDruidPage *druid_page, - gpointer arg1, gpointer ud ) +static void +reminders_page_prep( gpointer ud ) { sxSinceLastData *sxsld = (sxSinceLastData*)ud; GtkWidget *w; - DEBUG( "begin" ); if ( g_list_length( sxsld->reminderList ) == 0 ) { - DEBUG( "reminders." ); w = glade_xml_get_widget( sxsld->gxml, AUTO_CREATE_NOTIFY_PG ); gnome_druid_set_page( sxsld->sincelast_druid, GNOME_DRUID_PAGE(w) ); + return; } w = glade_xml_get_widget( sxsld->gxml, REMINDER_CLIST ); @@ -416,7 +423,13 @@ reminders_prep( GnomeDruidPage *druid_page, gtk_clist_clear( GTK_CLIST(w) ); add_reminders_to_gui( sxsld->reminderList, sxsld ); gtk_clist_thaw( GTK_CLIST(w) ); - DEBUG( "done" ); +} + +static void +reminders_prep( GnomeDruidPage *druid_page, + gpointer arg1, gpointer ud ) +{ + reminders_page_prep( ud ); } static gboolean @@ -469,10 +482,10 @@ created_prep( GnomeDruidPage *druid_page, GtkWidget *w; sxSinceLastData *sxsld = (sxSinceLastData*)ud; - if ( /* FIXME: signal that we had to create a bunch of stuff from the - previous page. */ 1 ) { + if ( !sxsld->createdSomething ) { w = glade_xml_get_widget( sxsld->gxml, OBSOLETE_PG ); - gnome_druid_set_page( sxsld->sincelast_druid, GNOME_DRUID_PAGE(w) ); + gnome_druid_set_page( sxsld->sincelast_druid, + GNOME_DRUID_PAGE(w) ); return; } } @@ -485,7 +498,8 @@ obsolete_prep( GnomeDruidPage *druid_page, sxSinceLastData *sxsld = (sxSinceLastData*)ud; if ( g_list_length( sxsld->toRemoveList ) == 0 ) { w = glade_xml_get_widget( sxsld->gxml, FINISH_PG ); - gnome_druid_set_page( sxsld->sincelast_druid, GNOME_DRUID_PAGE(w) ); + gnome_druid_set_page( sxsld->sincelast_druid, + GNOME_DRUID_PAGE(w) ); return; } processRemoveList( sxsld->toRemoveList, sxsld ); @@ -495,7 +509,7 @@ static gboolean obsolete_next( GnomeDruidPage *druid_page, gpointer arg1, gpointer ud ) { - GList *sxList, *toDelPtr; + GList *sxList, *toDelPtr, *elt; GtkCList *cl; gint row; toDeleteTuple *tdt; @@ -510,15 +524,24 @@ obsolete_next( GnomeDruidPage *druid_page, toDelPtr; toDelPtr = toDelPtr->next ) { row = (gint)toDelPtr->data; + DEBUG( "getting row data for SX_OBSOLETE_CLIST row %d", + row ); tdt = (toDeleteTuple*)gtk_clist_get_row_data( cl, row ); - sxList = g_list_remove( sxList, tdt->sx ); - sxsld->toRemoveList = - g_list_remove( sxsld->toRemoveList, tdt->sx ); - - /* FIXME: we should really save this until the user is out of - * the woods RE:cancelleing the dialog. */ - xaccSchedXactionFree( tdt->sx ); - tdt->sx = NULL; + DEBUG( "got tdt with sx with name \"%s\"", + xaccSchedXactionGetName( tdt->sx ) ); + { + elt = g_list_find( sxList, tdt->sx ); + sxList = g_list_remove_link( sxList, elt ); + + sxsld->removedList = g_list_concat( sxsld->removedList, elt ); + } + { + elt = g_list_find( sxsld->toRemoveList, tdt ); + sxsld->toRemoveList = + g_list_remove_link( sxsld->toRemoveList, elt ); + g_list_free_1(elt); + } + g_date_free( tdt->endDate ); g_free( tdt ); } @@ -561,6 +584,7 @@ to_create_next( GnomeDruidPage *druid_page, GList *tcList; gboolean allVarsBound; toCreateTuple *tct; + Query *q, *oldQuery, *newQuery; sxsld = (sxSinceLastData*)ud; @@ -568,14 +592,13 @@ to_create_next( GnomeDruidPage *druid_page, /* First: check to make sure all TCTs are 'ready' [and return if not]. * Second: create the entries based on the variable bindings. */ - tcList = sxsld->toCreateList; if ( tcList == NULL ) { DEBUG( "No transactions to create..." ); - /* FIXME: sxsincelast_close_handler( sxsld ); */ return FALSE; } - do { + + for ( ; tcList ; tcList = tcList->next ) { tct = (toCreateTuple*)tcList->data; allVarsBound = TRUE; g_hash_table_foreach( tct->varBindings, @@ -590,20 +613,40 @@ to_create_next( GnomeDruidPage *druid_page, gtk_clist_select_row( cl, tct->clistRow, 0 ); return TRUE; } - } while ( (tcList = tcList->next) ); + } tcList = sxsld->toCreateList; /* At this point we can assume there are to-create transactions and all variables are bound. */ g_return_val_if_fail( tcList, TRUE ); + + q = xaccMallocQuery(); gnc_suspend_gui_refresh(); - do { + for ( ; tcList ; tcList = tcList->next ) { + GList *l = NULL; + GList *created = NULL; + tct = (toCreateTuple*)tcList->data; - create_transactions_on( tct->sx, tct->date, tct, NULL ); - } while ( (tcList = tcList->next) ); + create_transactions_on( tct->sx, tct->date, tct, &created ); + /* Add to the Query for that register. */ + for ( l = created; l; l = l->next ) { + xaccQueryAddGUIDMatch( q, + (GUID*)l->data, + GNC_ID_TRANS, + QUERY_OR ); + } + sxsld->createdTxnGUIDList = + g_list_concat( sxsld->createdTxnGUIDList, created ); + } gnc_resume_gui_refresh(); - /* FXME: place in GL for review */ + oldQuery = gnc_ledger_display_get_query( sxsld->created_ledger ); + newQuery = xaccQueryMerge( oldQuery, q, QUERY_AND ); + gnc_ledger_display_set_query( sxsld->created_ledger, newQuery ); + gnc_ledger_display_refresh( sxsld->created_ledger ); + xaccFreeQuery( q ); + + sxsld->createdSomething = TRUE; return FALSE; } @@ -616,28 +659,48 @@ finish_finish( GnomeDruidPage *druid_page, sxsincelast_close_handler( sxsld ); } +static void +restore_sx_temporal_state( gpointer key, + gpointer value, + gpointer user_data ) +{ + SchedXaction *sx; + sxSinceLastData *sxsld; + + sxsld = (sxSinceLastData*)user_data; + + sx = (SchedXaction*)key; + gnc_sx_revert_to_temporal_state_snapshot( sx, (void*)value ); + + gnc_sx_destroy_temporal_state_snapshot( (void*)value ); +} + static gboolean cancel_check( GnomeDruidPage *druid_page, gpointer arg1, gpointer ud ) { + GList *l; sxSinceLastData *sxsld = (sxSinceLastData*)ud; const char *lastrun_cancel_check_msg = _( "Cancelling the Since-Last-Run dialog " "will revert all changes.\n" "Are you sure you want to lose all " - "Scheduled Transaction changes?" - "\n\nNote that this doesn't presently work, " - "and nothing will be reverted..." ); + "Scheduled Transaction changes?" ); DEBUG( "cancel_check" ); + if ( g_list_length( sxsld->removedList ) == 0 + && g_list_length( sxsld->createdTxnGUIDList ) == 0 ) { + /* There's nothing to cancel, so just do so... */ + return FALSE; + } + if ( !gnc_verify_dialog_parented( sxsld->sincelast_window, lastrun_cancel_check_msg, TRUE ) ) { return TRUE; } DEBUG( "reverting SX changes...\n" ); - /* Cancel policy: * . deleted SXes * . reborn @@ -656,16 +719,61 @@ cancel_check( GnomeDruidPage *druid_page, * . last_occur_date */ + gnc_suspend_gui_refresh(); + /* rebirth deleted SXes */ + DEBUG( "There are %d SXes on the 'removedList' to re-birth", + g_list_length( sxsld->removedList ) ); + if ( g_list_length( sxsld->removedList ) > 0 ) { + GList *sxList = + gnc_book_get_schedxactions( gnc_get_current_book () ); + for ( l = sxsld->removedList; l; l = l->next ) { + DEBUG( "re-birthing SX \"%s\"", + xaccSchedXactionGetName( (SchedXaction*)l->data ) ); + sxList = g_list_append( sxList, + (SchedXaction*)l->data ); + } + gnc_book_set_schedxactions( gnc_get_current_book(), + sxList ); + } + /* delete created transactions */ + DEBUG( "length( sxsld->createdTxnGUIDList ): %d", + g_list_length( sxsld->createdTxnGUIDList ) ); + if ( g_list_length( sxsld->createdTxnGUIDList ) > 0 ) { + Transaction *t = NULL; + for ( l = sxsld->createdTxnGUIDList; l; l = l->next ) { + t = xaccTransLookup( (GUID*)l->data, + gnc_get_current_book() ); + if ( t == NULL ) { + char *guidStr; + guidStr = + guid_to_string( (GUID*)l->data ); + PERR( "We thought we created Transaction " + "\"%s\", but can't " + "xaccTransLookup(...) it now.", + guidStr ); + free(guidStr); + break; + } + xaccTransBeginEdit( t ); + xaccTransDestroy( t ); + xaccTransCommitEdit( t ); + t = NULL; + } + } + /* Restore the temporal state of all SXes. + * This is in sxInitStates [a bunch of opaque void *'s ... which + * should be freed when we're done to prevent a memory leak.] */ + g_hash_table_foreach( sxsld->sxInitStates, + restore_sx_temporal_state, + (gpointer)sxsld ); + g_hash_table_destroy( sxsld->sxInitStates ); + sxsld->sxInitStates = NULL; + + gnc_resume_gui_refresh(); return FALSE; } -static void -show_test( GtkWidget *w, gpointer ud ) -{ - DEBUG( "hmmm." ); -} - static void sxsincelast_init( sxSinceLastData *sxsld ) { @@ -683,7 +791,8 @@ sxsincelast_init( sxSinceLastData *sxsld ) sx_obsolete_select_all_clicked }, { UNSELECT_ALL_BUTTON, "clicked", sx_obsolete_unselect_all_clicked }, - { NULL, NULL, NULL } + + { NULL, NULL, NULL } }; static druidSignalHandlerTuple pages[] = { @@ -720,10 +829,12 @@ sxsincelast_init( sxSinceLastData *sxsld ) sxsincelast_close_handler, sxsld->sincelast_window ); +#if 0 /* FIXME: need to be fixed because 'show-test' removal, b0rk them all. */ gtk_signal_connect( GTK_OBJECT(sxsld->sincelast_window), "map", GTK_SIGNAL_FUNC( show_test ), sxsld ); gtk_signal_connect( GTK_OBJECT(sxsld->sincelast_window), "realize", GTK_SIGNAL_FUNC( show_test ), sxsld ); +#endif /* 0 */ gtk_signal_connect( GTK_OBJECT(sxsld->sincelast_window), "destroy", GTK_SIGNAL_FUNC( sxsincelast_destroy ), sxsld ); @@ -738,10 +849,13 @@ sxsincelast_init( sxSinceLastData *sxsld ) w = glade_xml_get_widget( sxsld->gxml, SX_OBSOLETE_CLIST ); clist_set_all_cols_autoresize(GTK_CLIST(w), SX_OBSOLETE_CLIST_WIDTH); - create_autoCreate_gen_ledger( sxsld ); + create_autoCreate_ledger( sxsld ); + create_created_ledger( sxsld ); process_auto_create_list( sxsld->autoCreateList, sxsld ); + reminders_page_prep( (gpointer)sxsld ); + gtk_widget_show_all( sxsld->sincelast_window ); } @@ -802,7 +916,7 @@ generate_instances( SchedXaction *sx, gd = xaccSchedXactionGetInstanceAfter( sx, &gd, seqStateData ); } } - xaccSchedXactionDestroySequenceState( sx, seqStateData ); + xaccSchedXactionDestroySequenceState( seqStateData ); seqStateData = NULL; } @@ -854,18 +968,12 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld ) GList *thisGUID; autoCreateTuple *act; gboolean autoCreateState, notifyState; + Query *q, *dlQuery, *newQuery; - /* get the "automagically created and notification requested" - * register, and create the entries in it. */ - if ( ! sxsld->autoCreateQuery ) { - sxsld->autoCreateQuery = xaccMallocQuery(); - xaccQuerySetBook( sxsld->autoCreateQuery, - gnc_get_current_book() ); - - } - + q = xaccMallocQuery(); gnc_suspend_gui_refresh(); for ( ; autoCreateList ; autoCreateList = autoCreateList->next ) { + thisGUID = createdGUIDs = NULL; act = (autoCreateTuple*)autoCreateList->data; xaccSchedXactionGetAutoCreate( act->sx, &autoCreateState, @@ -873,26 +981,31 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld ) create_transactions_on( act->sx, act->date, NULL, &createdGUIDs ); + DEBUG( "created %d Transaction GUIDs", + g_list_length( createdGUIDs ) ); sxsld->autoCreatedSomething = TRUE; if ( notifyState ) { - for ( thisGUID = createdGUIDs; thisGUID ; + for ( thisGUID = createdGUIDs; + thisGUID; (thisGUID = thisGUID->next) ) { - xaccQueryAddGUIDMatch( sxsld->autoCreateQuery, + xaccQueryAddGUIDMatch( q, (GUID*)thisGUID->data, GNC_ID_TRANS, QUERY_OR ); } - g_list_free( createdGUIDs ); - thisGUID = createdGUIDs = NULL; } - /* FIXME: We probably want to save these somewhere for - * deletion if the user selects cancel. */ - /* FIXME: we'll also want to delete the GUIDs... */ + /* Save these GUIDs in case we need to 'cancel' this + * operation [and thus delete these transactions]. */ + sxsld->createdTxnGUIDList = + g_list_concat( sxsld->createdTxnGUIDList, + createdGUIDs ); } - gnc_resume_gui_refresh(); + dlQuery = gnc_ledger_display_get_query( sxsld->ac_ledger ); + newQuery = xaccQueryMerge( dlQuery, q, QUERY_AND ); + gnc_ledger_display_set_query( sxsld->ac_ledger, newQuery ); + xaccFreeQuery( q ); - gnc_ledger_display_set_query( sxsld->ac_ledger, - sxsld->autoCreateQuery ); + gnc_resume_gui_refresh(); gnc_ledger_display_refresh( sxsld->ac_ledger ); } @@ -906,13 +1019,15 @@ add_to_create_list_to_gui( GList *toCreateList, sxSinceLastData *sxsld ) if ( toCreateList == NULL ) return; + DEBUG( "foobar" ); clist = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, TO_CREATE_CLIST ) ); - do { + for ( ; toCreateList ; toCreateList = toCreateList->next ) { tct = (toCreateTuple*)toCreateList->data; /* tct->{sx,date} are already filled in. */ tct->clistRow = sxsld->tcl_row; if ( ! tct->varBindings ) { - tct->varBindings = g_hash_table_new( g_str_hash, g_str_equal ); + tct->varBindings = g_hash_table_new( g_str_hash, + g_str_equal ); } /* add to clist [ahem... register... ahem] */ @@ -931,8 +1046,7 @@ add_to_create_list_to_gui( GList *toCreateList, sxSinceLastData *sxsld ) sxsld->tcl_row++; g_free( rowText[1] ); - - } while ( (toCreateList = toCreateList->next) ); + } if ( sxsld->tcl_row > 0 ) { gtk_clist_select_row( clist, 0, 0 ); @@ -991,7 +1105,8 @@ processRemoveList(GList *removeList, sxSinceLastData *sxsld) gtk_clist_freeze( cl ); gtk_clist_clear( cl ); - for(row = 0; removeList != NULL; row++, removeList = removeList->next) { + for ( row = 0; removeList; + row++, removeList = removeList->next ) { tdt = (toDeleteTuple*)removeList->data; rowtext[0] = xaccSchedXactionGetName( tdt->sx ); @@ -1008,7 +1123,7 @@ processRemoveList(GList *removeList, sxSinceLastData *sxsld) strcpy( rowtext[2], "obsolete" ); gtk_clist_insert( cl, row, rowtext ); - gtk_clist_set_row_data(cl, row, removeList->data ); + gtk_clist_set_row_data(cl, row, tdt ); } gtk_clist_thaw( cl ); @@ -1068,6 +1183,7 @@ sxsincelast_populate( sxSinceLastData *sxsld ) GList *sxList, *instanceList; SchedXaction *sx; + void *sx_state; GDate end, endPlusReminders; GDate *instDate; gint daysInAdvance; @@ -1087,8 +1203,22 @@ sxsincelast_populate( sxSinceLastData *sxsld ) return FALSE; } - do { + for ( ; sxList; + sxList = sxList->next ) { sx = (SchedXaction*)sxList->data; + + /* Store initial state of SX. */ + if ( g_hash_table_lookup( sxsld->sxInitStates, sx ) + != NULL ) { + PERR( "Why are we able to find a SX initial state " + "hash entry for something we're seeing for " + "the first time?" ); + return FALSE; + } + sx_state = gnc_sx_create_temporal_state_snapshot( sx ); + g_hash_table_insert( sxsld->sxInitStates, + sx, sx_state ); + g_date_set_time( &end, time(NULL) ); daysInAdvance = xaccSchedXactionGetAdvanceCreation( sx ); g_date_add_days( &end, daysInAdvance ); @@ -1131,8 +1261,7 @@ sxsincelast_populate( sxSinceLastData *sxsld ) * show. */ showIt |= (g_list_length( sxsld->autoCreateList ) > 0); showIt |= (g_list_length( sxsld->toCreateList ) > 0); - - } while ( (sxList = sxList->next) ); + } showIt |= (g_list_length( sxsld->reminderList ) > 0); showIt |= (g_list_length( sxsld->toRemoveList ) > 0); @@ -1175,35 +1304,6 @@ clean_sincelast_dlg( sxSinceLastData *sxsld ) sxsld->tcl_row = sxsld->rl_row = 0; } -/* - * FIXME: This is workable w/two dialogs, but not with three!! - */ -/** - * Close policy: - * . If reminders-dialog-open - * . clean up since-last and hide [reminders may need to re-populate and - * re-display it. - * . If !reminders-dialog-open && since-last-dialog-open - * . close/destroy reminders dialog - * . close/destroy since-last dialog. - * . If !reminders-dialog-open && !since-last-dialog-open - * . close/destroy reminders dialog. - * . close/destroy since-last dialog. - * - * Fragile code alert... :( - **/ -/* major problem... we don't know, here, whether we've been - * called because we've been asked to close, or because the - * remind_dialog close has called us. This is important, - * because it determines what we do at this point: - * - * 1. We were called... - * ...thus, we clean out and raise the reminder dlg, or - * create the obsolete dialog. - * - * 2. The remind-dialog-close was called, and then called us... - * ...thus, we wait around for our interaction to complete. - */ static void sxsincelast_close_handler( gpointer ud ) { @@ -1216,70 +1316,6 @@ sxsincelast_close_handler( gpointer ud ) clean_sincelast_data( sxsld ); } -#if 0 -static void -sxsincelast_ok_clicked( GtkButton *b, gpointer ud ) -{ - sxSinceLastData *sxsld; - GtkCList *cl; - toCreateTuple *tct; - - GList *tcList; - gboolean allVarsBound; - - sxsld = (sxSinceLastData*)ud; - - cl = GTK_CLIST(glade_xml_get_widget( sxsld->gxml, TO_CREATE_CLIST )); - - /* First: check to make sure all TCTs are 'ready' [and return if not]. - * Second: create the entries based on the variable bindings. */ - - tcList = sxsld->toCreateList; - if ( tcList == NULL ) { - DEBUG( "No transactions to create..." ); - sxsincelast_close_handler( sxsld ); - return; - } - do { - tct = (toCreateTuple*)tcList->data; - allVarsBound = TRUE; - g_hash_table_foreach( tct->varBindings, - andequal_numerics_set, - &allVarsBound ); - if ( !allVarsBound ) { - char tmpBuf[GNC_D_BUF_WIDTH]; - g_date_strftime( tmpBuf, GNC_D_WIDTH, GNC_D_FMT, tct->date ); - /* FIXME: this should be better-presented to the user. */ - DEBUG( "SX %s on date %s still has unbound variables.", - xaccSchedXactionGetName(tct->sx), tmpBuf ); - gtk_clist_select_row( cl, tct->clistRow, 0 ); - return; - } - } while ( (tcList = tcList->next) ); - - tcList = sxsld->toCreateList; - /* At this point we can assume there are to-create transactions and - all variables are bound. */ - g_return_if_fail( tcList ); - gnc_suspend_gui_refresh(); - do { - tct = (toCreateTuple*)tcList->data; - create_transactions_on( tct->sx, tct->date, tct, NULL ); - } while ( (tcList = tcList->next) ); - gnc_resume_gui_refresh(); - - /* FIXME: cleanup appropriately. */ - sxsincelast_close_handler( sxsld ); - -} - -static void -sxsincelast_cancel_clicked( GtkButton *o, gpointer ud ) -{ - sxsincelast_close_handler( ud ); -} -#endif - static void andequal_numerics_set( gpointer key, gpointer value, gpointer data ) { @@ -1300,9 +1336,8 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud ) sxsld = (sxSinceLastData*)ud; tct = (toCreateTuple*)gtk_object_get_data( GTK_OBJECT(e), "tct" ); varName = (gchar*)gtk_object_get_data( GTK_OBJECT(e), "varName" ); + num = (gnc_numeric*)gtk_object_get_data( GTK_OBJECT(e), "numeric" ); entryText = gtk_editable_get_chars( e, 0, -1 ); - num = g_new0( gnc_numeric, 1 ); - *num = gnc_numeric_create( 0, 1 ); dummyVarHash = g_hash_table_new( NULL, NULL ); /* FIXME: these debugs probably want to go into a staus bar... */ /* FIXME: Should be using xaccParseAmount instead of parser_parse_separate_vars? */ @@ -1321,11 +1356,9 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud ) "gnc_numeric-parseable", entryText ); g_free( num ); num = NULL; - } else if ( gnc_numeric_zero_p( *num ) ) { - DEBUG( "entry \"%s\" parses as '0'", - ( entryText ? entryText : "(null)" ) ); - g_free( num ); - num = NULL; + } else { + DEBUG( "\"%s\" parses as \"%f\"", entryText, + gnc_numeric_to_double( *num ) ); } g_hash_table_destroy( dummyVarHash ); @@ -1337,7 +1370,7 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud ) &maybeKey, &maybeValue ) ) { g_hash_table_remove( tct->varBindings, maybeKey ); g_free( maybeValue ); - /* Does the maybeKey need to be freed? */ + /* FIXME: Does the maybeKey need to be freed? */ } g_hash_table_insert( tct->varBindings, maybeKey, num ); } @@ -1365,6 +1398,9 @@ sxsincelast_destroy( GtkObject *o, gpointer ud ) gnc_ledger_display_close( sxsld->ac_ledger ); /* FIXME: need more freeing for ac_ledger? */ sxsld->ac_ledger = NULL; + gnc_ledger_display_close( sxsld->created_ledger ); + /* FIXME: need more freeing for created_ledger? */ + sxsld->created_ledger = NULL; g_free( sxsld ); } @@ -1740,6 +1776,47 @@ sxsl_get_sx_vars( SchedXaction *sx, GHashTable *varHash ) (gpointer)varHash ); } +static gboolean +tct_table_entry_key_handle( GtkWidget *widget, GdkEventKey *event, gpointer ud ) +{ + gnc_numeric *num; + //gchar *entryText; + GtkEntry *ent = NULL; + GString *str; + + if ( (event->keyval != GDK_Tab) + && (event->keyval != GDK_ISO_Left_Tab) ) { + return FALSE; + } + + /* First, deal with formulas in these cells, replacing their + * contents with the eval'd value. */ + ent = GTK_ENTRY(widget); + num = (gnc_numeric*)gtk_object_get_data( GTK_OBJECT(ent), "numeric" ); + str = g_string_new(""); + g_string_sprintf( str, "%0.2f", gnc_numeric_to_double( *num ) ); + gtk_entry_set_text( ent, str->str ); + g_string_free( str, TRUE ); + + /* Next, deal with tab-ordering in this page... */ + + // if ( entry isn't last in table ) + // return (normal)FALSE + // if ( unfilled entry in this table exists ) + // change focus to unfilled entry + // if ( no more unfilled clist-rows ) + // return (normal)FALSE + // clist-select next unfilled row + + // This doesn't deal with shift-tab very well ... + // And there's a question of if the user will allow us to futz with + // their tab-ordering... though it's already pretty screwed up for the + // dynamically-changing-table anyways, so they probably won't mind + // too much... -- jsled + + return FALSE; +} + static void sxsincelast_tc_row_sel( GtkCList *clist, gint row, @@ -1754,6 +1831,7 @@ sxsincelast_tc_row_sel( GtkCList *clist, int tableIdx; GtkWidget *label, *entry; GList *varList; + gint varHashSize; toCreateTuple *tct; sxSinceLastData *sxsld; @@ -1768,23 +1846,22 @@ sxsincelast_tc_row_sel( GtkCList *clist, return; } - varList = NULL; - hash_to_sorted_list( tct->varBindings, &varList ); - - if ( g_hash_table_size( tct->varBindings ) == 0 ) { + if ( (varHashSize = g_hash_table_size( tct->varBindings )) == 0 ) { PINFO( "No variables to deal with" ); return; } + varList = NULL; + hash_to_sorted_list( tct->varBindings, &varList ); varTable = GTK_TABLE( glade_xml_get_widget( sxsld->gxml, VARIABLE_TABLE ) ); - gtk_table_resize( varTable, 4, NUM_COLS ); + gtk_table_resize( varTable, varHashSize + 1, NUM_COLS ); tableIdx = 1; - do { + for ( ; varList ; varList = varList->next ) { GString *gstr; const gchar *numValueStr; - gnc_numeric *numValue; + gnc_numeric *numValue, *tmpNumValue; gstr = g_string_sized_new(16); g_string_sprintf( gstr, "%s: ", (gchar*)varList->data ); @@ -1793,8 +1870,20 @@ sxsincelast_tc_row_sel( GtkCList *clist, g_string_free( gstr, TRUE ); entry = gtk_entry_new(); - gtk_object_set_data( GTK_OBJECT(entry), "varName", varList->data ); + gtk_object_set_data( GTK_OBJECT(entry), "varName", + varList->data ); gtk_object_set_data( GTK_OBJECT(entry), "tct", tct ); + tmpNumValue = g_new0( gnc_numeric, 1 ); + *tmpNumValue = gnc_numeric_create( 0, 1 ); + gtk_object_set_data( GTK_OBJECT(entry), "numeric", + tmpNumValue ); + if ( tableIdx == varHashSize ) { + /* Set a flag so we can know if we're the last row of + * the table. */ + gtk_object_set_data( GTK_OBJECT(entry), "lastVisualElt", + (gpointer)1 ); + } + gtk_widget_set_usize( entry, 64, 0 ); numValue = (gnc_numeric*)g_hash_table_lookup( tct->varBindings, varList->data ); @@ -1805,6 +1894,10 @@ sxsincelast_tc_row_sel( GtkCList *clist, gtk_entry_set_text( GTK_ENTRY(entry), numValueStr ); } + /* fixme::2002.02.10 jsled testing */ + gtk_signal_connect( GTK_OBJECT(entry), "key-press-event", + GTK_SIGNAL_FUNC( tct_table_entry_key_handle ), + NULL ); gtk_signal_connect( GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC( sxsincelast_entry_changed ), sxsld ); @@ -1816,7 +1909,7 @@ sxsincelast_tc_row_sel( GtkCList *clist, 1, 2, tableIdx, tableIdx + 1, sopts, sopts, 0, 0 ); tableIdx += 1; - } while ( (varList = varList->next) ); + } gtk_widget_show_all( GTK_WIDGET(varTable) ); } @@ -2075,116 +2168,6 @@ inform_or_add( GList *reminders, return okFlag; } -#if 0 -static void -sx_obsolete_row_sel(GtkCList *clist, - gint row, - gint column, - GdkEventButton *event, - gpointer user_data) -{ - sxSinceLastData *sxsld; - - GList *row_sxlentry_data; - sxsld = (sxSinceLastData*) user_data; - - row_sxlentry_data = (GList *)gtk_clist_get_row_data(clist, row); - - if (g_list_position(sxsld->actual_to_remove, row_sxlentry_data) == -1) - { - sxsld->actual_to_remove = g_list_append(sxsld->actual_to_remove, row_sxlentry_data); - } - - return; -} - -static void -sx_obsolete_row_unsel(GtkCList *clist, - gint row, - gint column, - GdkEventButton *event, - gpointer user_data) -{ - GList *position; - GList *row_sxlentry_data = gtk_clist_get_row_data(clist, row); - sxSinceLastData *sxsld = user_data; - - - if((position = g_list_find(sxsld->actual_to_remove, row_sxlentry_data))) - { - sxsld->actual_to_remove = g_list_remove_link(sxsld->actual_to_remove, position); - g_list_free_1(position); - - } - - return; -} - -static void -sx_obsolete_ok_clicked(GtkButton *button, gpointer user_data) -{ - sxSinceLastData *sxsld = user_data; - SchedXaction *sx; - GList *actual_sx_list, *actual_sx_listref, *removelist_ref; - - GNCBook *book = gnc_get_current_book (); - - actual_sx_list = gnc_book_get_schedxactions(book); - for(removelist_ref = sxsld->actual_to_remove; - removelist_ref; removelist_ref = removelist_ref->next) - { - actual_sx_listref = removelist_ref->data; - - xaccSchedXactionFree( (SchedXaction *) (actual_sx_listref->data) ); - actual_sx_list = g_list_remove_link(actual_sx_list, - actual_sx_listref); - - g_list_free_1(actual_sx_listref); - } - - g_list_free(sxsld->actual_to_remove); - sxsld->actual_to_remove = NULL; - - gnc_book_set_schedxactions(book, actual_sx_list); - - printf( "c\n" ); - gnome_dialog_close(GNOME_DIALOG(sxsld->dlg_obsolete)); -} - - -static void -sx_obsolete_close_handler(gpointer user_data) -{ - sxSinceLastData *sxsld = user_data; - - if ( sxsld->toRemoveList ) { - /* FIXME: g_list_foreach( tdt_destroyer, ...->toRemoveList ) */ - g_list_free(sxsld->toRemoveList); - sxsld->toRemoveList = NULL; - } - - if ( sxsld->actual_to_remove ) { - g_list_free(sxsld->actual_to_remove); - sxsld->actual_to_remove = NULL; - } - sxsld->n_obsolete = 0; - - if ( sxsld->dlg_obsolete ) { - printf( "d\n" ); - gnome_dialog_close(GNOME_DIALOG(sxsld->dlg_obsolete)); - sxsld->dlg_obsolete = NULL; - sxsld->obsolete_displayed = FALSE; - } - sxsincelast_close_handler( sxsld ); -} - -static void -sx_obsolete_cancel_clicked(GtkButton *button, gpointer user_data) -{ - sx_obsolete_close_handler(user_data); -} -#endif /* 0 */ - static void sx_obsolete_select_all_clicked(GtkButton *button, gpointer user_data) { @@ -2206,35 +2189,34 @@ sx_obsolete_unselect_all_clicked(GtkButton *button, gpointer user_data) } static void -create_autoCreate_gen_ledger( sxSinceLastData *sxsld ) +create_autoCreate_ledger( sxSinceLastData *sxsld ) { SplitRegister *splitreg; - GtkWidget *vbox; - GtkWidget *toolbar; - GtkWidget *regWidget; - - sxsld->ac_ledger = gnc_ledger_display_gl(); + GtkWidget *vbox, *toolbar; + Query *q; + q = xaccMallocQuery(); + xaccQueryAddSingleBookMatch( q, gnc_get_current_book(), QUERY_AND ); + sxsld->ac_ledger = gnc_ledger_display_query( q, + GENERAL_LEDGER, + REG_STYLE_LEDGER ); gnc_ledger_display_set_handlers( sxsld->ac_ledger, NULL, sxsld_ledger_get_parent ); gnc_ledger_display_set_user_data( sxsld->ac_ledger, (gpointer)sxsld ); - splitreg = gnc_ledger_display_get_split_register( sxsld->ac_ledger ); /* FIXME: make configurable? */ gnucash_register_set_initial_rows( 4 ); - regWidget = gnucash_register_new( splitreg->table ); - gnc_table_init_gui( regWidget, splitreg ); - sxsld->reg = GNUCASH_REGISTER(regWidget); - GNUCASH_SHEET(sxsld->reg->sheet)->window = - GTK_WIDGET( sxsld->sincelast_druid ); - + sxsld->ac_regWidget = + gnc_regWidget_new( sxsld->ac_ledger, + GTK_WINDOW( sxsld->sincelast_window ) ); + vbox = glade_xml_get_widget( sxsld->gxml, AUTO_CREATE_VBOX ); - toolbar = gtk_label_new( "foo ... toolbar...uh... fooo" ); + toolbar = gnc_regWidget_get_toolbar( sxsld->ac_regWidget ); gtk_box_pack_start( GTK_BOX(vbox), toolbar, FALSE, FALSE, 2 ); - gtk_box_pack_end( GTK_BOX(vbox), regWidget, TRUE, TRUE, 2 ); + gtk_box_pack_end( GTK_BOX(vbox), GTK_WIDGET(sxsld->ac_regWidget), TRUE, TRUE, 2 ); #if 0 gtk_signal_connect( GTK_OBJECT(sxed->dialog), "activate_cursor", @@ -2246,10 +2228,6 @@ create_autoCreate_gen_ledger( sxSinceLastData *sxsld ) /* FIXME: we should do all the happy-fun register stuff... button bar * controls ... popups ... */ -#if 0 - popup = schedXaction_editor_create_reg_popup( sxsld ); - gnucash_register_attach_popup( sxsld->reg, popup, sxsld ); -#endif /* 0 */ /* configure... */ /* don't use double-line */ @@ -2265,6 +2243,61 @@ create_autoCreate_gen_ledger( sxSinceLastData *sxsld ) gnc_ledger_display_refresh( sxsld->ac_ledger ); } +static void +create_created_ledger( sxSinceLastData *sxsld ) +{ + SplitRegister *splitreg; + GtkWidget *vbox, *toolbar; + Query *q; + + q = xaccMallocQuery(); + xaccQueryAddSingleBookMatch( q, gnc_get_current_book(), QUERY_AND ); + sxsld->created_ledger = gnc_ledger_display_query( q, + GENERAL_LEDGER, + REG_STYLE_LEDGER ); + gnc_ledger_display_set_handlers( sxsld->created_ledger, + NULL, + sxsld_ledger_get_parent ); + gnc_ledger_display_set_user_data( sxsld->created_ledger, (gpointer)sxsld ); + splitreg = gnc_ledger_display_get_split_register( sxsld->created_ledger ); + /* FIXME: make configurable? */ + gnucash_register_set_initial_rows( 4 ); + + sxsld->created_regWidget = + gnc_regWidget_new( sxsld->created_ledger, + GTK_WINDOW( sxsld->sincelast_window ) ); + + vbox = glade_xml_get_widget( sxsld->gxml, CREATED_VBOX ); + toolbar = gnc_regWidget_get_toolbar( sxsld->created_regWidget ); + + gtk_box_pack_start( GTK_BOX(vbox), toolbar, FALSE, FALSE, 2 ); + gtk_box_pack_end( GTK_BOX(vbox), GTK_WIDGET(sxsld->created_regWidget), TRUE, TRUE, 2 ); + +#if 0 + gtk_signal_connect( GTK_OBJECT(sxed->dialog), "activate_cursor", + GTK_SIGNAL_FUNC(sxe_register_record_cb), sxed ); + gtk_signal_connect( GTK_OBJECT(sxed->dialog), "redraw_all", + GTK_SIGNAL_FUNC(sxe_register_redraw_all_cb), sxed ); + +#endif /* 0 */ + + /* FIXME: we should do all the happy-fun register stuff... button bar + * controls ... popups ... */ + + /* configure... */ + /* don't use double-line */ + /* FIXME */ + gnc_split_register_config(splitreg, + splitreg->type, splitreg->style, + FALSE); + + /* don't show present/future divider [by definition, not necessary] */ + gnc_split_register_show_present_divider( splitreg, FALSE ); + + /* force a refresh */ + gnc_ledger_display_refresh( sxsld->created_ledger ); +} + static gncUIWidget sxsld_ledger_get_parent( GNCLedgerDisplay *ld ) @@ -2272,7 +2305,8 @@ sxsld_ledger_get_parent( GNCLedgerDisplay *ld ) sxSinceLastData *sxsld; sxsld = (sxSinceLastData*)gnc_ledger_display_get_user_data( ld ); - return (gncUIWidget)sxsld->reg->sheet->window; + //return (gncUIWidget)sxsld->reg->sheet->window; + return (gncUIWidget)sxsld->sincelast_window; } static void diff --git a/src/gnome/glade/sched-xact.glade b/src/gnome/glade/sched-xact.glade index 668b4ca0fa..d187b72907 100644 --- a/src/gnome/glade/sched-xact.glade +++ b/src/gnome/glade/sched-xact.glade @@ -4613,18 +4613,6 @@ Anually GnomeDruid sincelast_druid - - GnomeDruidPageStart - druidpagestart1 - Start page - I don't know exactly what we do here, but this is just a test, anyways... - 255,255,255 - 0,0,0 - 25,25,112 - 255,255,255 - 255,255,255 - - GnomeDruidPageStandard reminders_page diff --git a/src/register/ledger-core/Makefile.am b/src/register/ledger-core/Makefile.am index b007d52058..d45bd951c4 100644 --- a/src/register/ledger-core/Makefile.am +++ b/src/register/ledger-core/Makefile.am @@ -12,7 +12,8 @@ libgncmod_ledger_core_la_SOURCES = \ split-register-load.c \ split-register-model.c \ split-register-model-save.c \ - split-register-util.c + split-register-util.c \ + gnc-regwidget.c noinst_HEADERS = \ gnc-ledger-display.h \ @@ -21,7 +22,8 @@ noinst_HEADERS = \ split-register-layout.h \ split-register-model.h \ split-register-model-save.h \ - split-register-p.h + split-register-p.h \ + gnc-regwidget.h libgncmod_ledger_core_la_LDFLAGS = -module libgncmod_ledger_core_la_LIBADD = \ @@ -38,6 +40,7 @@ AM_CFLAGS = \ -I${top_srcdir}/src/app-utils \ -I${top_srcdir}/src/gnome-utils \ -I${top_srcdir}/src/register/register-core \ + -I${top_srcdir}/src/register/register-gnome \ ${GUILE_INCS} \ ${GLADE_CFLAGS} \ ${GNOME_INCLUDEDIR} \ diff --git a/src/register/ledger-core/gnc-ledger-display.c b/src/register/ledger-core/gnc-ledger-display.c index 8a1f1186ce..93db783092 100644 --- a/src/register/ledger-core/gnc-ledger-display.c +++ b/src/register/ledger-core/gnc-ledger-display.c @@ -417,10 +417,7 @@ gnc_ledger_display_gl (void) /** * id is some identifier that can be: - * . used in a query to look for the transaction which belong to this - * template ledger - * . set in a specific key value for new transactions which belong to - * this template ledger. + * FIXME: what's the correct description of 'id'? **/ GNCLedgerDisplay * gnc_ledger_display_template_gl (char *id) @@ -440,22 +437,23 @@ gnc_ledger_display_template_gl (char *id) acct = xaccGetAccountFromName (ag, id); if (!acct) { - /* FIXME */ - printf( "can't get template account for id \"%s\"\n", id ); + /* FIXME: this should be a more serious error, somehow */ + PERR( "can't get template account for id \"%s\"\n", id ); } + xaccQueryAddSingleBookMatch( q, book, QUERY_AND ); xaccQueryAddSingleAccountMatch (q, acct, QUERY_AND); + xaccQuerySearchTemplateGroup( q, TRUE ); - PWARN ("cannot use queries in this way call to fix"); - DxaccQuerySetGroup (q, gnc_book_get_template_group(book)); + //PWARN ("cannot use queries in this way call to fix"); + //DxaccQuerySetGroup (q, gnc_book_get_template_group(book)); ld = gnc_ledger_display_internal (NULL, q, LD_GL, GENERAL_LEDGER, REG_STYLE_JOURNAL, - TRUE); /* template mode? TRUE. */ + TRUE); /* TRUE : template mode */ sr = gnc_ledger_display_get_split_register (ld); - gnc_split_register_set_template_account (sr, acct); return ld; @@ -577,7 +575,6 @@ gnc_ledger_display_make_query (GNCLedgerDisplay *ld, break; case LD_GL: - case LD_TEMPLATE: return; default: @@ -692,12 +689,6 @@ gnc_ledger_display_internal (Account *lead_account, Query *q, break; - case LD_TEMPLATE: - class = REGISTER_TEMPLATE_CM_CLASS; - /* FIXME: sanity checks? - Check for kvp-frame data? */ - break; - default: PERR ("bad ledger type: %d", ld_type); return NULL; diff --git a/src/register/ledger-core/gnc-ledger-display.h b/src/register/ledger-core/gnc-ledger-display.h index f823884c61..8a21552302 100644 --- a/src/register/ledger-core/gnc-ledger-display.h +++ b/src/register/ledger-core/gnc-ledger-display.h @@ -50,7 +50,6 @@ typedef enum LD_SINGLE, LD_SUBACCOUNT, LD_GL, - LD_TEMPLATE, } GNCLedgerDisplayType; diff --git a/src/register/ledger-core/gnc-regwidget.c b/src/register/ledger-core/gnc-regwidget.c new file mode 100644 index 0000000000..220b496c64 --- /dev/null +++ b/src/register/ledger-core/gnc-regwidget.c @@ -0,0 +1,2544 @@ +/********************************************************************\ + * gnc-regwidget.c -- A widget for the common register look-n-feel. * + * Copyright (C) 2002 Joshua Sled * + * * + * 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, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +#include "gnc-regwidget.h" +#include "gnc-engine-util.h" +#include "dialog-utils.h" + +static short module = MOD_SX; + +static void gnc_regWidget_class_init (GNCRegWidgetClass *); +static void gnc_regWidget_init (GNCRegWidget *); +static void gnc_regWidget_init2( GNCRegWidget *rw, GNCLedgerDisplay *ledger, GtkWindow *win ); +static void emit_cb( GNCRegWidget *rw, const char *signal_name, gpointer ud ); + +static void emit_enter_ent_cb( GtkWidget *widget, gpointer data ); +static void emit_cancel_ent_cb( GtkWidget *widget, gpointer data ); +static void emit_delete_ent_cb( GtkWidget *widget, gpointer data ); +static void emit_dup_ent_cb( GtkWidget *widget, gpointer data ); +static void emit_expand_ent_cb( GtkWidget *widget, gpointer data ); +static void emit_blank_cb( GtkWidget *widget, gpointer data ); +static void emit_jump_cb( GtkWidget *widget, gpointer data ); + +guint +gnc_regWidget_get_type () +{ + static guint gnc_regWidget_type = 0; + + if (!gnc_regWidget_type) + { + GtkTypeInfo gnc_regWidget_info = + { + "GNCRegWidget", + sizeof (GNCRegWidget), + sizeof (GNCRegWidgetClass), + (GtkClassInitFunc) gnc_regWidget_class_init, + (GtkObjectInitFunc) gnc_regWidget_init, + (GtkArgSetFunc) NULL, + (GtkArgGetFunc) NULL + }; + + gnc_regWidget_type = gtk_type_unique (GTK_TYPE_VBOX, &gnc_regWidget_info); + } + + return gnc_regWidget_type; +} + +/* SIGNALS */ +enum gnc_regWidget_signal_enum { + ENTER_ENT_SIGNAL, + CANCEL_ENT_SIGNAL, + DELETE_ENT_SIGNAL, + DUP_ENT_SIGNAL, + EXPAND_ENT_SIGNAL, + BLANK_SIGNAL, + JUMP_SIGNAL, +#if 0 + ACTIVATE_CURSOR_SIGNAL, + REDRAW_ALL_SIGNAL, + REDRAW_HELP_SIGNAL, +#endif /* 0 */ + LAST_SIGNAL +}; + +static gint gnc_regWidget_signals[LAST_SIGNAL] = { 0 }; + +static void +default_cancel( GNCRegWidget *rw, gpointer ud ) +{ + printf( "default_cancel\n" ); +} + +static void +gnc_regWidget_class_init (GNCRegWidgetClass *class) +{ + int i; + GtkObjectClass *object_class; + static struct similar_signal_info { + enum gnc_regWidget_signal_enum s; + const char *signal_name; + guint offset; + } signals[] = { + { ENTER_ENT_SIGNAL, "enter_ent", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, enter_ent_cb ) }, + { CANCEL_ENT_SIGNAL, "cancel_ent", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, cancel_ent_cb ) }, + { DELETE_ENT_SIGNAL, "delete_ent", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, delete_ent_cb ) }, + { DUP_ENT_SIGNAL, "dup_ent", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, dup_ent_cb ) }, + { EXPAND_ENT_SIGNAL, "expand_ent", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, expand_ent_cb ) }, + { BLANK_SIGNAL, "blank", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, blank_cb ) }, + { JUMP_SIGNAL, "jump", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, jump_cb ) }, +#if 0 + { ACTIVATE_CURSOR_SIGNAL, "activate_cursor", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, activate_cursor ) }, + { REDRAW_ALL_SIGNAL, "redraw_all", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, redraw_all ) }, + { REDRAW_HELP_SIGNAL, "redraw_help", GTK_SIGNAL_OFFSET( GNCRegWidgetClass, redraw_help ) }, +#endif /* 0 */ + { LAST_SIGNAL, NULL, 0 } + }; + + object_class = (GtkObjectClass*) class; + + for ( i=0; signals[i].signal_name != NULL; i++ ) { + gnc_regWidget_signals[ signals[i].s ] = + gtk_signal_new( signals[i].signal_name, + GTK_RUN_FIRST, + object_class->type, signals[i].offset, + gtk_signal_default_marshaller, GTK_TYPE_NONE, 0 ); + } + + gtk_object_class_add_signals (object_class, gnc_regWidget_signals, LAST_SIGNAL); + + /* FIXME: set all fn pointers to NULL */ + class->enter_ent_cb = NULL; + class->cancel_ent_cb = default_cancel; +} + +GtkWidget* +gnc_regWidget_new( GNCLedgerDisplay *ld, GtkWindow *win ) +{ + GNCRegWidget *rw; + rw = GNC_REGWIDGET( gtk_type_new( gnc_regWidget_get_type() ) ); + /* IMPORTANT: If we set this to anything other than GTK_RESIZE_QUEUE, we + * enter into a very bad back-and-forth between the sheet and the druid [in + * certain conditions and circumstances not detailed here], causing in + * either a single instance of the druid resizing or infinite instances of + * the druid resizing without bound. Contact jsled@asynchronous.org for + * details. -- 2002.04.15 + */ + gtk_container_set_resize_mode( GTK_CONTAINER( rw ), GTK_RESIZE_QUEUE ); + gnc_regWidget_init2( rw, ld, win ); + return GTK_WIDGET( rw ); +} + +/*******************************************************************\ + * window-register.c -- the register window for GnuCash * + * Copyright (C) 1997 Robin D. Clark * + * Copyright (C) 1997-1998 Linas Vepstas * + * Copyright (C) 1998 Rob Browning * + * Copyright (C) 1999-2000 Dave Peticolas * + * Copyright (C) 2001 Gnumatic, Inc. * + * * + * 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, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * + * * +\********************************************************************/ + +#define _GNU_SOURCE + +#include "config.h" + +#include +#include +#include + +#include "AccWindow.h" +#include "Scrub.h" +#include "global-options.h" +#include "gnc-component-manager.h" +#include "gnc-date-edit.h" +#include "gnc-engine-util.h" +#include "gnc-euro.h" +#include "gnc-gui-query.h" +#include "gnc-ledger-display.h" +#include "gnc-pricedb.h" +#include "gnc-ui-util.h" +#include "gnc-ui.h" +#include "gnucash-sheet.h" +#include "messages.h" +#include "table-allgui.h" + +static int last_width = 0; +static int last_stock_width = 0; + +/** PROTOTYPES ******************************************************/ +static void gnc_register_redraw_all_cb (GnucashRegister *g_reg, gpointer data); +static void gnc_register_redraw_help_cb (GnucashRegister *g_reg, + gpointer data); +static void gnc_reg_refresh_toolbar(GNCRegWidget *regData); +static void regDestroy(GNCLedgerDisplay *ledger); +static void gnc_register_check_close(GNCRegWidget *regData); + +static void editCB(GtkWidget *w, gpointer data) { } +static void helpCB(GtkWidget *w, gpointer data); +static void cutCB(GtkWidget *w, gpointer data); +static void copyCB(GtkWidget *w, gpointer data); +static void pasteCB(GtkWidget *w, gpointer data); +static void cutTransCB(GtkWidget *w, gpointer data); +static void copyTransCB(GtkWidget *w, gpointer data); +static void pasteTransCB(GtkWidget *w, gpointer data); + +static void deleteCB(GNCRegWidget *rw, gpointer data); +static void duplicateCB(GNCRegWidget *rw, gpointer data); +static void recordCB(GNCRegWidget *rw, gpointer data); +static void cancelCB(GNCRegWidget *rw, gpointer data); +static void expand_ent_cb(GNCRegWidget *rw, gpointer data); +static void new_trans_cb(GNCRegWidget *rw, gpointer data); +static void jump_cb(GNCRegWidget *rw, gpointer data ); + +static void startRecnCB(GtkWidget *w, gpointer data) { } +static void xferCB(GtkWidget *w, gpointer data) { } +static void stockSplitCB (GtkWidget * w, gpointer data) { } + +static void closeCB(GtkWidget *w, gpointer data) { } +static void reportCB(GtkWidget *w, gpointer data) { } +static void invoiceCB(GtkWidget *w, gpointer data) { } +static void invoiceTransCB(GtkWidget *w, gpointer data) { } +static void printReportCB(GtkWidget *w, gpointer data) { } +static void dateCB(GtkWidget *w, gpointer data) { } + +void gnc_register_raise (GNCRegWidget *rw); +void gnc_register_jump_to_split(GNCRegWidget *rw, Split *split); +void gnc_register_jump_to_split_amount(GNCRegWidget *rw, Split *split); +void gnc_register_jump_to_blank (GNCRegWidget *rw); + +/********************************************************************\ + * gnc_register_raise * + * raise an existing register window to the front * + * * + * Args: rw - the register widget data structure * + * Return: nothing * +\********************************************************************/ +void +gnc_register_raise (GNCRegWidget *rw) +{ + if (rw == NULL) + return; + + if (rw->window == NULL) + return; + + gtk_widget_show (rw->window); + + if (rw->window->window == NULL) + return; + + gdk_window_raise (rw->window->window); +} + +/********************************************************************\ + * gnc_register_jump_to_split * + * move the cursor to the split, if present in register * + * * + * Args: rw - the register widget data structure * + * split - the split to jump to * + * Return: nothing * +\********************************************************************/ +void +gnc_register_jump_to_split(GNCRegWidget *rw, Split *split) +{ + Transaction *trans; + VirtualCellLocation vcell_loc; + SplitRegister *reg; + + if (!rw) return; + + trans = xaccSplitGetParent(split); +#if 0 + if (trans != NULL) + /* jsled: If we don't know about dates, what do we do? */ + if (gnc_register_include_date(rw, xaccTransGetDate(trans))) + { + gnc_ledger_display_refresh (rw->ledger); + } +#endif /* 0 */ + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + if (gnc_split_register_get_split_virt_loc(reg, split, &vcell_loc)) + gnucash_register_goto_virt_cell(rw->reg, vcell_loc); +} + + +/********************************************************************\ + * gnc_register_jump_to_split_amount * + * move the cursor to the split in the non-blank amount column * + * * + * Args: regData - the register data structure * + * split - the split to jump to * + * Return: nothing * +\********************************************************************/ +void +gnc_register_jump_to_split_amount(GNCRegWidget *rw, Split *split) +{ + Transaction *trans; + VirtualLocation virt_loc; + SplitRegister *reg; + + if (!rw) return; + + trans = xaccSplitGetParent(split); +#if 0 + if (trans != NULL) + /* jsled: if no knowledge of date, what to do? */ + if (gnc_register_include_date(rw, xaccTransGetDate(trans))) + { + gnc_ledger_display_refresh (rw->ledger); + } +#endif /* 0 */ + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + if (gnc_split_register_get_split_amount_virt_loc (reg, split, &virt_loc)) + gnucash_register_goto_virt_loc (rw->reg, virt_loc); +} + +/* jsled: style changing. */ +static void +gnc_register_change_style (GNCRegWidget *rw, SplitRegisterStyle style) +{ + SplitRegister *reg = gnc_ledger_display_get_split_register (rw->ledger); + + if (style == reg->style) + return; + + gnc_split_register_config (reg, reg->type, style, reg->use_double_line); + + gnc_ledger_display_refresh (rw->ledger); +} + +static void +gnc_register_style_ledger_cb (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + if (!GTK_CHECK_MENU_ITEM (w)->active) + return; + + gnc_register_change_style (rw, REG_STYLE_LEDGER); +} + +static void +gnc_register_style_auto_ledger_cb (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + if (!GTK_CHECK_MENU_ITEM (w)->active) + return; + + gnc_register_change_style (rw, REG_STYLE_AUTO_LEDGER); +} + +static void +gnc_register_style_journal_cb (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + if (!GTK_CHECK_MENU_ITEM (w)->active) + return; + + gnc_register_change_style (rw, REG_STYLE_JOURNAL); +} + +/* jsled: relates to style */ +static void +gnc_register_double_line_cb (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + SplitRegister *reg = gnc_ledger_display_get_split_register (rw->ledger); + gboolean use_double_line; + + use_double_line = GTK_CHECK_MENU_ITEM(w)->active; + + if (use_double_line == reg->use_double_line) + return; + + gnc_split_register_config (reg, reg->type, reg->style, use_double_line); + + gnc_ledger_display_refresh (rw->ledger); +} + +static void +gnc_register_sort (GNCRegWidget *rw, sort_type_t sort_code) +{ + Query *query = gnc_ledger_display_get_query (rw->ledger); + gboolean show_present_divider = FALSE; + SplitRegister *reg; + + if (rw->sort_type == sort_code) + return; + + switch (sort_code) + { + case BY_STANDARD: + xaccQuerySetSortOrder(query, BY_STANDARD, BY_NONE, BY_NONE); + show_present_divider = TRUE; + break; + case BY_DATE: + xaccQuerySetSortOrder(query, BY_DATE, BY_STANDARD, BY_NONE); + show_present_divider = TRUE; + break; + case BY_DATE_ENTERED: + xaccQuerySetSortOrder(query, BY_DATE_ENTERED, BY_STANDARD, BY_NONE); + break; + case BY_DATE_RECONCILED: + xaccQuerySetSortOrder(query, BY_RECONCILE, BY_DATE_RECONCILED, + BY_STANDARD); + break; + case BY_NUM: + xaccQuerySetSortOrder(query, BY_NUM, BY_STANDARD, BY_NONE); + break; + case BY_AMOUNT: + xaccQuerySetSortOrder(query, BY_AMOUNT, BY_STANDARD, BY_NONE); + break; + case BY_MEMO: + xaccQuerySetSortOrder(query, BY_MEMO, BY_STANDARD, BY_NONE); + break; + case BY_DESC: + xaccQuerySetSortOrder(query, BY_DESC, BY_STANDARD, BY_NONE); + break; + default: + g_return_if_fail (FALSE); + } + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + gnc_split_register_show_present_divider (reg, show_present_divider); + + rw->sort_type = sort_code; + + gnc_ledger_display_refresh(rw->ledger); +} + +static void +gnc_register_sort_standard_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_STANDARD); +} + +static void +gnc_register_sort_date_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_DATE); +} + +static void +gnc_register_sort_date_entered_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_DATE_ENTERED); +} + +static void +gnc_register_sort_date_reconciled_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_DATE_RECONCILED); +} + +static void +gnc_register_sort_num_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_NUM); +} + +static void +gnc_register_sort_amount_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_AMOUNT); +} + +static void +gnc_register_sort_memo_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_MEMO); +} + +static void +gnc_register_sort_desc_cb(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_sort(rw, BY_DESC); +} + +static GtkWidget * +gnc_register_create_tool_bar ( GNCRegWidget *rw ) +{ + GtkWidget *toolbar; + + static GnomeUIInfo toolbar_info[] = + { + { + GNOME_APP_UI_ITEM, + N_("Enter"), + N_("Record the current FOO"), + emit_enter_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_ADD, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Cancel"), + N_("Cancel the current FOO"), + emit_cancel_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_UNDELETE, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Delete"), + N_("Delete the current FOO"), + emit_delete_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_TRASH, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_ITEM, + N_("Duplicate"), + N_("Make a copy of the current FOO for editing"), + emit_dup_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_COPY, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_TOGGLEITEM, + N_("Split"), + N_("Show all splits in the current FOO"), + emit_expand_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_BOOK_OPEN, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Blank"), + N_("Move to the blank FOO at the " + "bottom of the register"), + emit_blank_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_NEW, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Jump"), + N_("Jump to the corresponding FOO in " + "the other BAR"), + emit_jump_cb, NULL, NULL, + GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_JUMP_TO, + 0, 0, NULL + }, + GNOMEUIINFO_END + }; + + toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH); + + gnome_app_fill_toolbar_with_data (GTK_TOOLBAR(toolbar), toolbar_info, + NULL, rw); + + rw->split_button = toolbar_info[6].widget; + +#if 0 + /* FIXME_jsled: we want something like this, but it doesn't seem to exist... :( */ + gnome_app_install_appbar_toolbar_hints( GNOME_APPBAR(rw->statusbar), + toolbar_info ); +#endif /* 0 */ + + return toolbar; +} + +static GtkWidget * +gnc_regWidget_create_status_bar (GNCRegWidget *rw) +{ + GtkWidget *statusbar; + + statusbar = gnome_appbar_new (FALSE, /* no progress bar */ + TRUE, /* has status area */ + GNOME_PREFERENCES_USER); + rw->statusbar = statusbar; + + return statusbar; +} + +void +gnc_register_jump_to_blank (GNCRegWidget *rw) +{ + SplitRegister *reg = gnc_ledger_display_get_split_register (rw->ledger); + VirtualCellLocation vcell_loc; + Split *blank; + + blank = gnc_split_register_get_blank_split (reg); + if (blank == NULL) + return; + + if (gnc_split_register_get_split_virt_loc (reg, blank, &vcell_loc)) + gnucash_register_goto_virt_cell (rw->reg, vcell_loc); +} + + +static void +expand_trans_check_cb (GtkWidget *widget, gpointer data) +{ + GNCRegWidget *rw = data; + gboolean expand; + SplitRegister *reg; + + if (!rw) + return; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + expand = GTK_CHECK_MENU_ITEM (widget)->active; + + gnc_split_register_expand_current_trans (reg, expand); +} + +static void +expand_ent_cb (GNCRegWidget *rw, gpointer data) +{ + GtkWidget *widget = data; + gboolean expand; + SplitRegister *reg; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + +#if 0 + /* jsled: this isn't true. */ + expand = GTK_TOGGLE_BUTTON (widget)->active; +#else + expand = TRUE; +#endif /* 0 */ + + gnc_split_register_expand_current_trans (reg, expand); +} + +/* jsled: default handler */ +static void +new_trans_cb (GNCRegWidget *rw, gpointer data) +{ + SplitRegister *reg; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + if (gnc_split_register_save (reg, TRUE)) + gnc_split_register_redraw (reg); + + gnc_register_jump_to_blank (rw); +} + +static void +emit_enter_ent_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "enter_ent", widget ); +} + +static void +emit_cancel_ent_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "cancel_ent", widget ); +} + +static void +emit_delete_ent_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "delete_ent", widget ); +} + +static void +emit_dup_ent_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "dup_ent", widget ); +} + +static void +emit_expand_ent_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "expand_ent", widget ); +} + +static void +emit_blank_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "blank", widget ); +} + +static void +emit_jump_cb( GtkWidget *widget, gpointer data ) +{ + emit_cb( (GNCRegWidget*)data, "jump", widget ); +} + +static void +emit_cb( GNCRegWidget *rw, const char *signal_name, gpointer ud ) +{ + PINFO( "emitting signal: \"%s\"\n", signal_name ); + gtk_signal_emit_by_name( GTK_OBJECT(rw), signal_name, NULL ); +} + +static void +jump_cb(GNCRegWidget *rw, gpointer data) +{ + SplitRegister *reg; + Account *account; + Account *leader; + Split *split; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + split = gnc_split_register_get_current_split (reg); + if (split == NULL) + return; + + account = xaccSplitGetAccount(split); + if (account == NULL) + return; + + leader = gnc_ledger_display_leader (rw->ledger); + + if (account == leader) + { + split = xaccSplitGetOtherSplit(split); + if (split == NULL) + return; + + account = xaccSplitGetAccount(split); + if (account == NULL) + return; + if (account == leader) + return; + } + +#if 0 + /* jsled: what to do, here...? [window-knowledge issues] */ + regData = regWindowSimple(account); + if (regData == NULL) + return; + + gnc_register_raise (rw); + gnc_register_jump_to_split (rw, split); +#endif /* 0 */ +} + +static void +gnc_register_create_menus(GNCRegWidget *rw, GtkWidget *statusbar) +{ + GtkAccelGroup *accel_group; + gpointer user_data = (gpointer)rw; + + static GnomeUIInfo style_list[] = + { + GNOMEUIINFO_RADIOITEM_DATA(N_("Basic Ledger"), + N_("Show transactions on one or two lines"), + gnc_register_style_ledger_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Auto-Split Ledger"), + N_("Show transactions on one or two lines and " + "expand the current transaction"), + gnc_register_style_auto_ledger_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Transaction Journal"), + N_("Show expanded transactions with all " + "splits"), + gnc_register_style_journal_cb, NULL, NULL), + GNOMEUIINFO_END + }; + + static GnomeUIInfo style_menu[] = + { + GNOMEUIINFO_RADIOLIST(style_list), + GNOMEUIINFO_SEPARATOR, + GNOMEUIINFO_TOGGLEITEM(N_("_Double Line"), + N_("Show two lines of information for each " + "transaction"), + gnc_register_double_line_cb, NULL), + GNOMEUIINFO_END + }; + + static GnomeUIInfo sort_list[] = + { + GNOMEUIINFO_RADIOITEM_DATA(N_("Standard order"), + N_("Keep normal account order"), + gnc_register_sort_standard_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by Date"), + N_("Sort by Date"), + gnc_register_sort_date_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by date of entry"), + N_("Sort by the date of entry"), + gnc_register_sort_date_entered_cb, + NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by statement date"), + N_("Sort by the statement date " + "(unreconciled items last)"), + gnc_register_sort_date_reconciled_cb, + NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by Num"), + N_("Sort by Num"), + gnc_register_sort_num_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by Amount"), + N_("Sort by Amount"), + gnc_register_sort_amount_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by Memo"), + N_("Sort by Memo"), + gnc_register_sort_memo_cb, NULL, NULL), + GNOMEUIINFO_RADIOITEM_DATA(N_("Sort by Description"), + N_("Sort by Description"), + gnc_register_sort_desc_cb, NULL, NULL), + GNOMEUIINFO_END + }; + + static GnomeUIInfo sort_menu[] = + { + GNOMEUIINFO_RADIOLIST(sort_list), + GNOMEUIINFO_END + }; + + static GnomeUIInfo register_menu[] = + { + GNOMEUIINFO_SUBTREE(N_("_Style"), style_menu), + GNOMEUIINFO_SUBTREE(N_("Sort _Order"), sort_menu), + GNOMEUIINFO_END + }; + + static GnomeUIInfo edit_menu[] = + { + GNOMEUIINFO_MENU_CUT_ITEM(cutCB, NULL), + GNOMEUIINFO_MENU_COPY_ITEM(copyCB, NULL), + GNOMEUIINFO_MENU_PASTE_ITEM(pasteCB, NULL), + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_ITEM, + N_("Cut Transaction"), + N_("Cut the selected transaction"), + cutTransCB, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Copy Transaction"), + N_("Copy the selected transaction"), + copyTransCB, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Paste Transaction"), + N_("Paste the transaction clipboard"), + pasteTransCB, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_END + }; + + static GnomeUIInfo txn_menu[] = + { + { + GNOME_APP_UI_ITEM, + N_("_Enter"), + N_("Record the current transaction"), + emit_enter_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Cancel"), + N_("Cancel the current transaction"), + emit_cancel_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Delete"), + N_("Delete the current transaction"), + emit_delete_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_ITEM, + N_("D_uplicate"), + N_("Make a copy of the current transaction"), + emit_dup_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_TOGGLEITEM, + N_("_Split"), + N_("Show all splits in the current transaction"), + emit_expand_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Blank"), + N_("Move to the blank transaction at the " + "bottom of the register"), + emit_blank_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Jump"), + N_("Jump to the corresponding transaction in " + "the other account"), + emit_jump_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_END + }; + + accel_group = gtk_accel_group_new(); + gtk_accel_group_attach(accel_group, GTK_OBJECT(rw->window)); + + rw->style_menu = gtk_menu_new(); + gnc_fill_menu_with_data( style_menu, rw ); + gnome_app_fill_menu( GTK_MENU_SHELL(rw->style_menu), + style_menu, + accel_group, TRUE, 0); + gnome_app_install_appbar_menu_hints( GNOME_APPBAR(rw->statusbar), + style_menu ); + + rw->sort_menu = gtk_menu_new(); + gnc_fill_menu_with_data( sort_menu, rw ); + gnome_app_fill_menu( GTK_MENU_SHELL(rw->sort_menu), sort_menu, + accel_group, TRUE, 0 ); + gnome_app_install_appbar_menu_hints( GNOME_APPBAR(rw->statusbar), + sort_menu ); + + rw->edit_menu = gtk_menu_new(); + gnc_fill_menu_with_data( edit_menu, rw ); + gnome_app_fill_menu( GTK_MENU_SHELL(rw->edit_menu), edit_menu, + accel_group, TRUE, 0 ); + gnome_app_install_appbar_menu_hints( GNOME_APPBAR(rw->statusbar), + edit_menu ); + + rw->transaction_menu = gtk_menu_new(); + gnc_fill_menu_with_data( txn_menu, rw ); + gnome_app_fill_menu( GTK_MENU_SHELL(rw->transaction_menu), txn_menu, + accel_group, TRUE, 0 ); + gnome_app_install_appbar_menu_hints( GNOME_APPBAR(rw->statusbar), + txn_menu ); + + rw->double_line_check = style_menu[2].widget; + rw->split_menu_check = txn_menu[6].widget; + + /* Make sure the right style radio item is active */ + /* jsled: okP */ + { + SplitRegister *reg; + GtkWidget *widget; + int index; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + switch (reg->style) + { + default: + printf( "default\n" ); + case REG_STYLE_LEDGER: + index = 0; + break; + case REG_STYLE_AUTO_LEDGER: + index = 1; + break; + case REG_STYLE_JOURNAL: + index = 2; + break; + } + + /* registers with more than one account can only use journal mode */ + if (reg->type >= NUM_SINGLE_REGISTER_TYPES) + { + widget = style_list[0].widget; + gtk_widget_set_sensitive (widget, FALSE); + + widget = style_list[1].widget; + gtk_widget_set_sensitive (widget, FALSE); + } + + widget = style_list[index].widget; + gtk_signal_handler_block_by_data(GTK_OBJECT(widget), rw); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE); + gtk_signal_handler_unblock_by_data(GTK_OBJECT(widget), rw); + } +} + +static GtkWidget * +gnc_register_create_popup_menu (GNCRegWidget *rw) +{ + GtkWidget *popup; + + GnomeUIInfo transaction_menu[] = + { + { + GNOME_APP_UI_ITEM, + N_("_Enter"), + N_("Record the current FOO"), + emit_enter_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Cancel"), + N_("Cancel the current FOO"), + emit_cancel_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Delete"), + N_("Delete the current FOO"), + emit_delete_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_ITEM, + N_("D_uplicate"), + N_("Make a copy of the current FOO"), + emit_dup_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Schedule..."), + N_("Create a scheduled FOO using the current FOO as a template"), + emit_cb, "schedule", NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_TOGGLEITEM, + N_("_Split"), + N_("Show all SFOO in the current FOO"), + emit_expand_ent_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Blank"), + N_("Move to the blank FOO at the " + "bottom of the register"), + emit_blank_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("_Jump"), + N_("Jump to the corresponding FOO in " + "the other BAR"), + emit_jump_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_END + }; + + gnc_fill_menu_with_data (transaction_menu, rw); + + popup = gnome_popup_menu_new (transaction_menu); + + rw->split_popup_check = transaction_menu[7].widget; + + gnome_app_install_appbar_menu_hints( GNOME_APPBAR(rw->statusbar), + transaction_menu ); + + return popup; +} + +/* jsled: record helper */ +static void +gnc_register_record (GNCRegWidget *rw) +{ + SplitRegister *reg; + Transaction *trans; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + trans = gnc_split_register_get_current_trans (reg); + + if (!gnc_split_register_save (reg, TRUE)) + return; + +#if 0 + if (trans != NULL) + gnc_register_include_date (rw, xaccTransGetDate(trans)); +#endif /* 0 */ + + /*gnc_split_register_redraw (reg);*/ + gnc_ledger_display_refresh( rw->ledger ); +} + +static gboolean +gnc_register_match_trans_row (VirtualLocation virt_loc, + gpointer user_data) +{ + GNCRegWidget *rw = user_data; + CursorClass cursor_class; + SplitRegister *sr; + + sr = gnc_ledger_display_get_split_register (rw->ledger); + cursor_class = gnc_split_register_get_cursor_class (sr, virt_loc.vcell_loc); + + return (cursor_class == CURSOR_CLASS_TRANS); +} + +static void +gnc_register_goto_next_trans_row (GNCRegWidget *rw) +{ + gnucash_register_goto_next_matching_row (rw->reg, + gnc_register_match_trans_row, + rw); +} + +/* jsled: default 'enter' handler */ +static void +gnc_register_enter (GNCRegWidget *rw, gboolean next_transaction) +{ + SplitRegister *sr = gnc_ledger_display_get_split_register (rw->ledger); + gboolean goto_blank; + + goto_blank = gnc_lookup_boolean_option("Register", + "'Enter' moves to blank transaction", + FALSE); + + /* If we are in single or double line mode and we hit enter + * on the blank split, go to the blank split instead of the + * next row. This prevents the cursor from jumping around + * when you are entering transactions. */ + if (!goto_blank && !next_transaction) + { + SplitRegisterStyle style = sr->style; + + if (style == REG_STYLE_LEDGER) + { + Split *blank_split; + + blank_split = gnc_split_register_get_blank_split(sr); + if (blank_split != NULL) + { + Split *current_split; + + current_split = gnc_split_register_get_current_split(sr); + + if (blank_split == current_split) + goto_blank = TRUE; + } + } + } + + /* First record the transaction. This will perform a refresh. */ + gnc_register_record (rw); + + if (!goto_blank && next_transaction) + gnc_split_register_expand_current_trans (sr, FALSE); + + /* Now move. */ + if (goto_blank) + gnc_register_jump_to_blank (rw); + else if (next_transaction) + gnc_register_goto_next_trans_row (rw); + else + gnucash_register_goto_next_virt_row (rw->reg); +} + +static void +gnc_register_record_cb (GnucashRegister *reg, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_register_enter (rw, FALSE); +} + +/* jsled: default 'delete' handler */ +static gboolean +gnc_register_delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + GNCRegWidget *rw = data; + DEBUG( "gnc_reg[widget]_delete_cb in" ); + gnc_register_check_close (rw); + + gnc_ledger_display_close (rw->ledger); + DEBUG("gnc_reg[widget]_delete_cb out [true]"); + return FALSE; /* let the user handle correctly. */ +} + +/* jsled: widget cleanup */ +static void +gnc_register_destroy_cb(GtkWidget *widget, gpointer data) +{ + GNCRegWidget *rw = GNC_REGWIDGET(widget); + SCM id; + + DEBUG( "Got gnc_regwidget_destroy cb" ); + gnc_ledger_display_close (rw->ledger); + + id = rw->toolbar_change_callback_id; + gnc_unregister_option_change_callback_id(id); + + DEBUG ("destroyed GNCRegWidget"); +} + +/* jsled: what to do? */ +static gncUIWidget +gnc_register_get_parent(GNCLedgerDisplay *ledger) +{ + GNCRegWidget *rw = gnc_ledger_display_get_user_data (ledger); + + if (rw == NULL) + return NULL; + + return rw->window; +} + +static char * +gnc_reg_get_name (GNCRegWidget *rw, gboolean for_window) +{ + Account *leader; + SplitRegister *reg; + gboolean single_account; + gchar *account_name; + gchar *reg_name; + gchar *name; + + if (rw == NULL) + return NULL; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + switch (reg->type) + { + case GENERAL_LEDGER: + case INCOME_LEDGER: + if (for_window) + reg_name = _("General Ledger"); + else + reg_name = _("General Ledger Report"); + single_account = FALSE; + break; + case PORTFOLIO_LEDGER: + if (for_window) + reg_name = _("Portfolio"); + else + reg_name = _("Portfolio Report"); + single_account = FALSE; + break; + case SEARCH_LEDGER: + if (for_window) + reg_name = _("Search Results"); + else + reg_name = _("Search Results Report"); + single_account = FALSE; + break; + default: + if (for_window) + reg_name = _("Register"); + else + reg_name = _("Register Report"); + single_account = TRUE; + break; + } + + leader = gnc_ledger_display_leader (rw->ledger); + + if ((leader != NULL) && single_account) + { + account_name = xaccAccountGetFullName (leader, + gnc_get_account_separator ()); + + name = g_strconcat (account_name, " - ", reg_name, NULL); + + g_free(account_name); + } + else + name = g_strdup (reg_name); + + return name; +} + +static void +gnc_toolbar_change_cb (void *data) +{ + GNCRegWidget *rw = data; + + gnc_reg_refresh_toolbar (rw); +} + +/********************************************************************\ + * WAS: regWindowLedger( GNCLedgerDisplay *ledger ); * +\********************************************************************/ +static void +gnc_regWidget_init( GNCRegWidget *rw ) +{ + rw->sort_type = BY_STANDARD; + rw->width = -1; + rw->height = -1; + + gtk_signal_connect (GTK_OBJECT(rw), "destroy", + GTK_SIGNAL_FUNC (gnc_register_destroy_cb), NULL); + +} + +struct foo { + char * signal_name; + void (*handler)(); +}; + +static void +gnc_regWidget_init2( GNCRegWidget *rw, GNCLedgerDisplay *ledger, GtkWindow *win ) +{ + static struct foo bar[] = { + { "enter_ent", recordCB }, + { "cancel_ent", cancelCB }, + { "delete_ent", deleteCB }, + { "dup_ent", duplicateCB }, + { "expand_ent", expand_ent_cb }, + { "blank", new_trans_cb }, + { "jump", jump_cb }, + { NULL, NULL } + }; + SplitRegister *reg; + gboolean show_all; + gboolean has_date; + int i; + + rw->window = GTK_WIDGET(win); + rw->ledger = ledger; + + /* attach predefined handlers */ + for ( i = 0; bar[i].signal_name != NULL; i++ ) { + gtk_signal_connect( GTK_OBJECT(rw), + bar[i].signal_name, + GTK_SIGNAL_FUNC(bar[i].handler), + NULL ); + } + + rw->statusbar = gnc_regWidget_create_status_bar(rw); + /*gtk_box_pack_end(GTK_BOX(rw), rw->statusbar, FALSE, FALSE, 0);*/ + + /* The tool bar */ + { + SCM id; + + rw->toolbar = gnc_register_create_tool_bar(rw); + gtk_container_set_border_width(GTK_CONTAINER(rw->toolbar), 2); + /*gtk_box_pack_start( GTK_BOX(rw), rw->toolbar, FALSE, TRUE, 0 );*/ + + id = gnc_register_option_change_callback(gnc_toolbar_change_cb, rw, + "General", "Toolbar Buttons"); + /* jsled: FIXME */ + rw->toolbar_change_callback_id = id; + } + + gnc_register_create_menus( rw, rw->statusbar ); + rw->popup_menu = gnc_register_create_popup_menu (rw); + + reg = gnc_ledger_display_get_split_register (rw->ledger); + gnc_ledger_display_set_user_data (rw->ledger, rw); + + gtk_signal_connect (GTK_OBJECT(rw->window), "delete-event", + GTK_SIGNAL_FUNC (gnc_register_delete_cb), rw); + + /* jsled: we actaully want these, but later */ + gnc_ledger_display_set_handlers (rw->ledger, + regDestroy, + gnc_register_get_parent); + + show_all = gnc_lookup_boolean_option ("Register", + "Show All Transactions", + TRUE); + + { + Query *q = gnc_ledger_display_get_query (rw->ledger); + + has_date = xaccQueryHasTermType (q, PD_DATE); + } + + if (has_date) + show_all = FALSE; + + /* Now that we have a date range, remove any existing + * maximum on the number of splits returned. */ + xaccQuerySetMaxSplits (gnc_ledger_display_get_query (rw->ledger), -1); + + /* The CreateTable will do the actual gui init, returning a widget */ + { + GtkWidget *register_widget; + GtkWidget *popup; + guint num_rows; + + /* FIXME_jsled: need to pass in caller's request for the number of + * lines. For now, we expect the caller to have called + * 'set_initial_rows' before creating us. */ + + register_widget = gnucash_register_new (reg->table); + + gtk_container_add (GTK_CONTAINER(rw), register_widget); + + rw->reg = GNUCASH_REGISTER (register_widget); + + /* jsled: FIXME: do we _really_ need the window? + * + * Seems like we do ... some magic regarding gnucash-sheet sizing is + * going on with the window's width and height. -- 2002.04.14 + */ + GNUCASH_SHEET(rw->reg->sheet)->window = GTK_WIDGET(win); + + /* jsled: we actually want these... */ + gtk_signal_connect (GTK_OBJECT(register_widget), "activate_cursor", + GTK_SIGNAL_FUNC(gnc_register_record_cb), rw); + gtk_signal_connect (GTK_OBJECT(register_widget), "redraw_all", + GTK_SIGNAL_FUNC(gnc_register_redraw_all_cb), rw); + gtk_signal_connect (GTK_OBJECT(register_widget), "redraw_help", + GTK_SIGNAL_FUNC(gnc_register_redraw_help_cb), rw); + gnucash_register_attach_popup (GNUCASH_REGISTER(register_widget), + rw->popup_menu, rw); + + gnc_table_init_gui (register_widget, reg); + } + +#if 0 + /* jsled: something's not right ... enabling this causes segfault... + * Gtk-CRITICAL **: file gtkstyle.c: line 515 (gtk_style_attach): assertion `window != NULL' failed. + * Gdk-CRITICAL **: file gdkwindow.c: line 716 (gdk_window_ref): assertion `window != NULL' failed. + * Gtk-CRITICAL **: file gtkstyle.c: line 515 (gtk_style_attach): assertion `window != NULL' failed. + */ + { + gboolean use_double_line; + GtkCheckMenuItem *check; + + use_double_line = gnc_lookup_boolean_option ("Register", + "Double Line Mode", + FALSE); + + /* be sure to initialize the gui elements associated with the cursor */ + gnc_split_register_config (reg, reg->type, reg->style, use_double_line); + + check = GTK_CHECK_MENU_ITEM (rw->double_line_check); + + gtk_signal_handler_block_by_func + (GTK_OBJECT (check), + GTK_SIGNAL_FUNC (gnc_register_double_line_cb), rw); + + gtk_check_menu_item_set_active (check, use_double_line); + + gtk_signal_handler_unblock_by_func + (GTK_OBJECT (check), + GTK_SIGNAL_FUNC (gnc_register_double_line_cb), rw); + } +#endif /* 0 */ + + /* jsled: FIXME: prefix && loading/saving window state + * Some argument can be made that this is the caller's responsibility. + */ +#if 0 + { + int *width; + char *prefix; + + switch (reg->type) + { + case STOCK_REGISTER: + case PORTFOLIO_LEDGER: + case CURRENCY_REGISTER: + prefix = "reg_stock_win"; + width = &last_stock_width; + break; + + default: + prefix = "reg_win"; + width = &last_width; + break; + } + + if (*width == 0) + gnc_get_window_size (prefix, width, NULL); + + gtk_window_set_default_size (GTK_WINDOW(win), *width, 0); + } +#endif /* 0 */ + + gtk_widget_show_all (GTK_WIDGET(rw)); + + gnc_split_register_show_present_divider (reg, TRUE); + + gnc_ledger_display_refresh (rw->ledger); + gnc_reg_refresh_toolbar (rw); +} + +static void +gnc_reg_refresh_toolbar (GNCRegWidget *rw) +{ + GtkToolbarStyle tbstyle; + + if ((rw == NULL) || (rw->toolbar == NULL)) + return; + + tbstyle = gnc_get_toolbar_style (); + + gtk_toolbar_set_style (GTK_TOOLBAR (rw->toolbar), tbstyle); + gtk_widget_show_all( GTK_WIDGET(rw) ); +} + +/* jsled: generic */ +static gnc_numeric +gnc_account_present_balance (Account *account) +{ + GList *list; + GList *node; + time_t today; + struct tm *tm; + + if (!account) + return gnc_numeric_zero (); + + today = time (NULL); + + tm = localtime (&today); + + tm->tm_hour = 23; + tm->tm_min = 59; + tm->tm_sec = 59; + tm->tm_isdst = -1; + + today = mktime (tm); + + list = xaccAccountGetSplitList (account); + + for (node = g_list_last (list); node; node = node->prev) + { + Split *split = node->data; + + if (xaccTransGetDate (xaccSplitGetParent (split)) <= today) + return xaccSplitGetBalance (split); + } + + return gnc_numeric_zero (); +} + +/* jsled: generic function. */ +static GNCPrice * +account_latest_price (Account *account) +{ + GNCBook *book; + GNCPriceDB *pdb; + gnc_commodity *commodity; + gnc_commodity *currency; + + commodity = xaccAccountGetCommodity (account); + currency = gnc_default_currency (); + + book = gnc_get_current_book (); + pdb = gnc_book_get_pricedb (book); + + return gnc_pricedb_lookup_latest (pdb, commodity, currency); +} + +/* jsled: deps: window, summary labels, + * I think we want to re-emit this signal? + * Or just tell Users they need get at it? */ +static void +gnc_register_redraw_all_cb (GnucashRegister *g_reg, gpointer data) +{ + GNCRegWidget *rw = data; + Account *leader; + gboolean expand; + gboolean sensitive; + SplitRegister *reg; + + leader = gnc_ledger_display_leader (rw->ledger); + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + expand = gnc_split_register_current_trans_expanded (reg); + + gtk_signal_handler_block_by_data + (GTK_OBJECT (rw->split_button), rw); + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON (rw->split_button), expand); + gtk_signal_handler_unblock_by_data + (GTK_OBJECT (rw->split_button), rw); + + gtk_signal_handler_block_by_data + (GTK_OBJECT (rw->split_menu_check), rw); + gtk_check_menu_item_set_active + (GTK_CHECK_MENU_ITEM (rw->split_menu_check), expand); + gtk_signal_handler_unblock_by_data + (GTK_OBJECT (rw->split_menu_check), rw); + + gtk_check_menu_item_set_active + (GTK_CHECK_MENU_ITEM (rw->split_popup_check), expand); + + sensitive = reg->style == REG_STYLE_LEDGER; + + gtk_widget_set_sensitive (rw->split_button, sensitive); + gtk_widget_set_sensitive (rw->split_menu_check, sensitive); + gtk_widget_set_sensitive (rw->split_popup_check, sensitive); +} + +static void +gnc_register_redraw_help_cb (GnucashRegister *g_reg, gpointer data) +{ + GNCRegWidget *rw = data; + SplitRegister *reg; + const char *status; + char *help; + + if (!rw) + return; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + help = gnc_table_get_help (reg->table); + + status = help ? help : ""; + + gnome_appbar_set_default (GNOME_APPBAR(rw->statusbar), status); + + g_free (help); +} + +#if 0 +/* jsled: window-manip. */ +static void +gnc_reg_save_size (RegWindow *regData) +{ + SplitRegister *reg; + int *width; + char *prefix; + + reg = gnc_ledger_display_get_split_register (regData->ledger); + + switch (reg->type) + { + case STOCK_REGISTER: + case PORTFOLIO_LEDGER: + case CURRENCY_REGISTER: + prefix = "reg_stock_win"; + width = &last_stock_width; + break; + default: + prefix = "reg_win"; + width = &last_width; + break; + } + + gdk_window_get_geometry (regData->window->window, NULL, NULL, + width, NULL, NULL); + + gnc_save_window_size (prefix, *width, 0); +} +#endif /* 0 */ + +/********************************************************************\ + * regDestroy() +\********************************************************************/ + +static void +regDestroy (GNCLedgerDisplay *ledger) +{ + GNCRegWidget *rw = gnc_ledger_display_get_user_data (ledger); + + DEBUG("regDestroy"); + + if (rw) + { + SplitRegister *reg; + + /* jsled: FIXME */ +#if 0 + gnc_reg_save_size (rw); +#endif /* 0 */ + + reg = gnc_ledger_display_get_split_register (ledger); + + if (reg && reg->table) + gnc_table_save_state (reg->table); + + } + + DEBUG("regDestroy out"); + gnc_ledger_display_set_user_data (ledger, NULL); +} + +/********************************************************************\ + * cutCB -- cut the selection to the clipboard * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +cutCB (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnucash_register_cut_clipboard (rw->reg); +} + + +/********************************************************************\ + * copyCB -- copy the selection to the clipboard * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +copyCB (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnucash_register_copy_clipboard (rw->reg); +} + + +/********************************************************************\ + * pasteCB -- paste the clipboard to the selection * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +pasteCB (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnucash_register_paste_clipboard (rw->reg); +} + + +/********************************************************************\ + * cutTransCB -- cut the current transaction to the clipboard * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +cutTransCB (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_split_register_cut_current + (gnc_ledger_display_get_split_register (rw->ledger)); +} + + +/********************************************************************\ + * copyTransCB -- copy the current transaction to the clipboard * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +copyTransCB(GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_split_register_copy_current + (gnc_ledger_display_get_split_register (rw->ledger)); +} + + +/********************************************************************\ + * pasteTransCB -- paste the transaction clipboard to the selection * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +pasteTransCB (GtkWidget *w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_split_register_paste_current + (gnc_ledger_display_get_split_register (rw->ledger)); +} + + +#if 0 +/********************************************************************\ + * xferCB -- open up the transfer window * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +xferCB (GtkWidget * w, gpointer data) +{ + GNCRegWidget *rw = data; + + gnc_xfer_dialog (rw->window, + gnc_ledger_display_leader (rw->ledger)); +} + + +/********************************************************************\ + * stockSplitCB -- open up the stock split druid * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +stockSplitCB (GtkWidget * w, gpointer data) +{ + RegWindow *regData = data; + + gnc_stock_split_dialog (gnc_ledger_display_leader (regData->ledger)); +} + + +/********************************************************************\ + * editCB -- open up the account edit window * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +editCB(GtkWidget * w, gpointer data) +{ + RegWindow *regData = data; + Account *account = gnc_ledger_display_leader (regData->ledger); + + if (account == NULL) + return; + + gnc_ui_edit_account_window(account); +} + + +/********************************************************************\ + * startRecnCB -- open up the reconcile window... called from * + * menubar. * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +startRecnCB(GtkWidget * w, gpointer data) +{ + RegWindow *regData = data; + Account *account = gnc_ledger_display_leader (regData->ledger); + + if (account == NULL) + return; + + recnWindow(regData->window, account); +} + +static gboolean +gnc_register_include_date(RegWindow *regData, time_t date) +{ + RegDateWindow *regDateData; + time_t start, end; + gboolean changed = FALSE; + + regDateData = regData->date_window; + + start = gnc_date_edit_get_date(GNC_DATE_EDIT(regDateData->start_date)); + end = gnc_date_edit_get_date(GNC_DATE_EDIT(regDateData->end_date)); + + if (date < start) + { + gnc_date_edit_set_time(GNC_DATE_EDIT(regDateData->start_date), date); + changed = TRUE; + } + + if (date > end) + { + gnc_date_edit_set_time(GNC_DATE_EDIT(regDateData->end_date), date); + changed = TRUE; + } + + if (changed) + gnc_register_set_date_range(regData); + + return changed; +} +#endif /* 0 */ + +/********************************************************************\ + * recordCB * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +recordCB (GNCRegWidget *rw, gpointer data) +{ + gnc_register_enter (rw, TRUE); +} + + +static void +gnc_transaction_delete_toggle_cb(GtkToggleButton *button, gpointer data) +{ + GtkWidget *text = gtk_object_get_user_data(GTK_OBJECT(button)); + gchar *s = data; + gint pos = 0; + + gtk_editable_delete_text(GTK_EDITABLE(text), 0, -1); + gtk_editable_insert_text(GTK_EDITABLE(text), s, strlen(s), &pos); +} + +/* jsled: seems generic enough... should probably be moved to a + * better/more-generic place. */ + +static gboolean +trans_has_reconciled_splits (Transaction *trans) +{ + GList *node; + + for (node = xaccTransGetSplitList (trans); node; node = node->next) + { + Split *split = node->data; + + switch (xaccSplitGetReconcile (split)) + { + case YREC: + case FREC: + return TRUE; + + default: + break; + } + } + + return FALSE; +} + +typedef enum +{ + DELETE_TRANS, + DELETE_SPLITS, + DELETE_CANCEL +} DeleteType; + +/********************************************************************\ + * gnc_transaction_delete_query * + * creates and displays a dialog which asks the user wheter they * + * want to delete a whole transaction, or just a split. * + * It returns a DeleteType code indicating the user's choice. * + * * + * Args: parent - the parent window the dialog should use * + * Returns: DeleteType choice indicator * + \*******************************************************************/ +static DeleteType +gnc_transaction_delete_query (GtkWindow *parent, Transaction *trans) +{ + GtkWidget *dialog; + GtkWidget *dvbox; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *trans_button; + GtkWidget *splits_button; + GtkWidget *text; + GSList *group; + gint pos = 0; + gint result; + gboolean reconciled; + + const char *usual = _("This selection will delete the whole " + "transaction. This is what you usually want."); + const char *usual_recn = _("This selection will delete the whole " + "transaction.\n\n" + "You would be deleting a transaction " + "with reconciled splits!"); + const char *warn = _("Warning: Just deleting all the other splits will " + "make your account unbalanced. You probably " + "shouldn't do this unless you're going to " + "immediately add another split to bring the " + "transaction back into balance."); + const char *warn_recn = _("You would be deleting reconciled splits!"); + const char *cbuf; + char *buf; + + DeleteType return_value; + + reconciled = trans_has_reconciled_splits (trans); + + dialog = gnome_dialog_new(_("Delete Transaction"), + GNOME_STOCK_BUTTON_OK, + GNOME_STOCK_BUTTON_CANCEL, + NULL); + + gnome_dialog_set_default(GNOME_DIALOG(dialog), 0); + gnome_dialog_close_hides(GNOME_DIALOG(dialog), TRUE); + gnome_dialog_set_parent(GNOME_DIALOG(dialog), parent); + + dvbox = GNOME_DIALOG(dialog)->vbox; + + frame = gtk_frame_new(NULL); + gtk_container_border_width(GTK_CONTAINER(frame), 5); + + vbox = gtk_vbox_new(TRUE, 3); + gtk_container_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(frame), vbox); + + text = gtk_text_new(NULL, NULL); + + trans_button = + gtk_radio_button_new_with_label(NULL, + _("Delete the whole transaction")); + gtk_object_set_user_data(GTK_OBJECT(trans_button), text); + gtk_box_pack_start(GTK_BOX(vbox), trans_button, TRUE, TRUE, 0); + + gtk_signal_connect(GTK_OBJECT(trans_button), "toggled", + GTK_SIGNAL_FUNC(gnc_transaction_delete_toggle_cb), + (gpointer) (reconciled ? usual_recn : usual)); + + group = gtk_radio_button_group(GTK_RADIO_BUTTON(trans_button)); + splits_button = + gtk_radio_button_new_with_label(group, _("Delete all the other splits")); + gtk_object_set_user_data(GTK_OBJECT(splits_button), text); + gtk_box_pack_start(GTK_BOX(vbox), splits_button, TRUE, TRUE, 0); + + if (reconciled) + buf = g_strconcat (warn, "\n\n", warn_recn, NULL); + else + buf = g_strdup (warn); + + gtk_signal_connect(GTK_OBJECT(splits_button), "toggled", + GTK_SIGNAL_FUNC(gnc_transaction_delete_toggle_cb), + (gpointer) buf); + + gtk_box_pack_start(GTK_BOX(dvbox), frame, TRUE, TRUE, 0); + + cbuf = reconciled ? usual_recn : usual; + gtk_editable_insert_text(GTK_EDITABLE(text), cbuf, strlen(cbuf), &pos); + gtk_text_set_line_wrap(GTK_TEXT(text), TRUE); + gtk_text_set_word_wrap(GTK_TEXT(text), TRUE); + gtk_text_set_editable(GTK_TEXT(text), FALSE); + gtk_box_pack_start(GTK_BOX(dvbox), text, FALSE, FALSE, 0); + + gtk_widget_show_all(dvbox); + + result = gnome_dialog_run_and_close(GNOME_DIALOG(dialog)); + + g_free (buf); + + if (result != 0) + return_value = DELETE_CANCEL; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(trans_button))) + return_value = DELETE_TRANS; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(splits_button))) + return_value = DELETE_SPLITS; + else + return_value = DELETE_CANCEL; + + gtk_widget_destroy(dialog); + + return return_value; +} + +/* jsled: old cbs */ +/* This is really tied to the SplitRegister, but that's fine for now. */ + +/********************************************************************\ + * deleteCB * + * * + * Args: widget - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +deleteCB(GNCRegWidget *rw, gpointer data) +{ + SplitRegisterStyle style; + CursorClass cursor_class; + SplitRegister *reg; + Transaction *trans; + char *buf = NULL; + Split *split; + gint result; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + /* get the current split based on cursor position */ + split = gnc_split_register_get_current_split(reg); + if (split == NULL) + { + gnc_split_register_cancel_cursor_split_changes (reg); + return; + } + + trans = xaccSplitGetParent(split); + style = reg->style; + cursor_class = gnc_split_register_get_current_cursor_class (reg); + + /* Deleting the blank split just cancels */ + { + Split *blank_split = gnc_split_register_get_blank_split (reg); + + if (split == blank_split) + { + gnc_split_register_cancel_cursor_trans_changes (reg); + return; + } + } + + if (cursor_class == CURSOR_CLASS_NONE) + return; + + /* On a split cursor, just delete the one split. */ + if (cursor_class == CURSOR_CLASS_SPLIT) + { + const char *format = _("Are you sure you want to delete\n %s\n" + "from the transaction\n %s ?"); + const char *recn_warn = _("You would be deleting a reconciled split!"); + const char *memo; + const char *desc; + char recn; + + memo = xaccSplitGetMemo (split); + memo = (memo && *memo) ? memo : _("(no memo)"); + + desc = xaccTransGetDescription (trans); + desc = (desc && *desc) ? desc : _("(no description)"); + + /* ask for user confirmation before performing permanent damage */ + buf = g_strdup_printf (format, memo, desc); + + recn = xaccSplitGetReconcile (split); + if (recn == YREC || recn == FREC) + { + char *new_buf; + + new_buf = g_strconcat (buf, "\n\n", recn_warn, NULL); + g_free (buf); + buf = new_buf; + } + + result = gnc_verify_dialog_parented (rw->window, buf, FALSE); + + g_free(buf); + + if (!result) + return; + + gnc_split_register_delete_current_split (reg); + return; + } + + g_return_if_fail(cursor_class == CURSOR_CLASS_TRANS); + + /* On a transaction cursor with 2 or fewer splits in single or double + * mode, we just delete the whole transaction, kerblooie */ + if ((xaccTransCountSplits(trans) <= 2) && (style == REG_STYLE_LEDGER)) + { + const char *message = _("Are you sure you want to delete the current " + "transaction?"); + const char *recn_warn = _("You would be deleting a transaction " + "with reconciled splits!"); + char *buf; + + if (trans_has_reconciled_splits (trans)) + buf = g_strconcat (message, "\n\n", recn_warn, NULL); + else + buf = g_strdup (message); + + result = gnc_verify_dialog_parented (rw->window, buf, FALSE); + + g_free (buf); + + if (!result) + return; + + gnc_split_register_delete_current_trans (reg); + return; + } + + /* At this point we are on a transaction cursor with more than 2 splits + * or we are on a transaction cursor in multi-line mode or an auto mode. + * We give the user two choices: delete the whole transaction or delete + * all the splits except the transaction split. */ + { + DeleteType del_type; + + del_type = gnc_transaction_delete_query (GTK_WINDOW(rw->window), + trans); + + if (del_type == DELETE_CANCEL) + return; + + if (del_type == DELETE_TRANS) + { + gnc_split_register_delete_current_trans (reg); + return; + } + + if (del_type == DELETE_SPLITS) + { + gnc_split_register_emtpy_current_trans (reg); + return; + } + } +} + +/********************************************************************\ + * duplicateCB * + * * + * Args: widget - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void duplicateCB(GNCRegWidget *rw, gpointer data) +{ + gnc_split_register_duplicate_current + (gnc_ledger_display_get_split_register (rw->ledger)); +} + + +/********************************************************************\ + * cancelCB * + * * + * Args: w - the widget that called us * + * data - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +cancelCB(GNCRegWidget *rw, gpointer data) +{ + gnc_split_register_cancel_cursor_trans_changes + (gnc_ledger_display_get_split_register (rw->ledger)); +} + + +/********************************************************************\ + * gnc_register_check_close * + * * + * Args: regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +gnc_register_check_close(GNCRegWidget *rw) +{ + gboolean pending_changes; + SplitRegister *reg; + + reg = gnc_ledger_display_get_split_register (rw->ledger); + + pending_changes = gnc_split_register_changed (reg); + if (pending_changes) + { + const char *message = _("The current transaction has been changed.\n" + "Would you like to record it?"); + if (gnc_verify_dialog_parented(rw->window, message, TRUE)) + gnc_register_enter(rw, TRUE); + else + gnc_split_register_cancel_cursor_trans_changes (reg); + } +} + +#if 0 +/********************************************************************\ + * closeCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +closeCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + + gnc_register_check_close (regData); + + gnc_ledger_display_close (regData->ledger); +} + +static void +report_helper (RegWindow *regData, SCM func, Query *query) +{ + SplitRegister *reg = gnc_ledger_display_get_split_register (regData->ledger); + char *str; + SCM qtype; + SCM args; + SCM arg; + + g_return_if_fail (gh_procedure_p (func)); + + args = SCM_EOL; + + /* FIXME: when we drop support older guiles, drop the (char *) coercion. */ + arg = gh_str02scm ((char *) gnc_split_register_get_credit_string (reg)); + args = gh_cons (arg, args); + + /* FIXME: when we drop support older guiles, drop the (char *) coercion. */ + arg = gh_str02scm ((char *) gnc_split_register_get_debit_string (reg)); + args = gh_cons (arg, args); + + str = gnc_reg_get_name (regData, FALSE); + arg = gh_str02scm (str); + args = gh_cons (arg, args); + g_free (str); + + arg = gh_bool2scm (reg->use_double_line); + args = gh_cons (arg, args); + + arg = gh_bool2scm (reg->style == REG_STYLE_JOURNAL); + args = gh_cons (arg, args); + + qtype = gh_eval_str(""); + g_return_if_fail (qtype != SCM_UNDEFINED); + + if (!query) + { + query = gnc_ledger_display_get_query (regData->ledger); + g_return_if_fail (query != NULL); + } + + arg = gw_wcp_assimilate_ptr (query, qtype); + args = gh_cons (arg, args); + if (arg == SCM_UNDEFINED) + return; + + gh_apply (func, args); +} + +/********************************************************************\ + * reportCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +reportCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + SCM func; + + func = gh_eval_str ("gnc:show-register-report"); + g_return_if_fail (gh_procedure_p (func)); + + report_helper (regData, func, NULL); +} + +/********************************************************************\ + * invoiceCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +invoiceCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + SCM func; + + func = gh_eval_str ("gnc:show-invoice-report"); + g_return_if_fail (gh_procedure_p (func)); + + report_helper (regData, func, NULL); +} + +/********************************************************************\ + * invoiceTransCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +invoiceTransCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + SplitRegister *reg; + Split *split; + Query *query; + SCM func; + + reg = gnc_ledger_display_get_split_register (regData->ledger); + + split = gnc_split_register_get_current_split (reg); + if (!split) + return; + + func = gh_eval_str ("gnc:show-invoice-report"); + g_return_if_fail (gh_procedure_p (func)); + + query = xaccMallocQuery (); + + xaccQuerySetGroup (query, gnc_get_current_group ()); + + xaccQueryAddGUIDMatch (query, xaccSplitGetGUID (split), + GNC_ID_SPLIT, QUERY_AND); + + report_helper (regData, func, query); +} + +/********************************************************************\ + * printReportCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +printReportCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + SCM func; + + func = gh_eval_str ("gnc:print-register-report"); + g_return_if_fail (gh_procedure_p (func)); + + report_helper (regData, func, NULL); +} + +/********************************************************************\ + * dateCB * + * * + * Args: widget - the widget that called us * + * data - regData - the data struct for this register * + * Return: none * +\********************************************************************/ +static void +dateCB (GtkWidget *widget, gpointer data) +{ + RegWindow *regData = data; + + gnc_register_show_date_window(regData); +} +#endif /* 0 */ + +/********************************************************************\ + * helpCB * + * * + * Args: widget - the widget that called us * + * data - not used * + * Return: none * +\********************************************************************/ +static void +helpCB (GtkWidget *widget, gpointer data) +{ + helpWindow (NULL, NULL, HH_REGWIN); +} + +GtkWidget* +gnc_regWidget_get_style_menu( GNCRegWidget *rw ) +{ + return rw->style_menu; +} + +GtkWidget* +gnc_regWidget_get_sort_menu( GNCRegWidget *rw ) +{ + return rw->sort_menu; +} + +GtkWidget* +gnc_regWidget_get_edit_menu( GNCRegWidget *rw ) +{ + return rw->edit_menu; +} + +GtkWidget* +gnc_regWidget_get_transaction_menu( GNCRegWidget *rw ) +{ + return rw->transaction_menu; +} + +GtkWidget* +gnc_regWidget_get_toolbar( GNCRegWidget *rw ) +{ + return rw->toolbar; +} + +GtkWidget* +gnc_regWidget_get_statusbar( GNCRegWidget *rw ) +{ + return rw->statusbar; +} + +GtkWidget* +gnc_regWidget_get_popup( GNCRegWidget *rw ) +{ + return rw->popup_menu; +} + +GnucashSheet* +gnc_regWidget_get_sheet( GNCRegWidget *rw ) +{ + return rw->reg; +} diff --git a/src/register/ledger-core/gnc-regwidget.h b/src/register/ledger-core/gnc-regwidget.h new file mode 100644 index 0000000000..43538c14f1 --- /dev/null +++ b/src/register/ledger-core/gnc-regwidget.h @@ -0,0 +1,104 @@ +/********************************************************************\ + * gnc-regwidget.h -- A widget for the common register look-n-feel. * + * Copyright (C) 2001 Joshua Sled * + * * + * 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, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +#ifndef GNC_REGWIDGET_H +#define GNC_REGWIDGET_H + +#include +#include +#include "config.h" + +#include "gnc-ledger-display.h" +#include "gnucash-sheet.h" + +#define GNC_REGWIDGET(obj) GTK_CHECK_CAST( obj, gnc_regWidget_get_type(), GNCRegWidget ) +#define GNC_REGWIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST( klass, gnc_regWidget_get_type(), GNCRegWidgetClass ) +#define IS_GNC_REGWIDGET(obj) GTK_CHECK_TYPE( obj, gnc_regWidget_get_type() ) + +typedef struct _GNCRegWidget GNCRegWidget; +typedef struct _GNCRegWidgetClass GNCRegWidgetClass; + +struct _GNCRegWidget { + /* The "parent" widget */ + GtkVBox vbox; + + /* Top level window */ + /* jsled: used by the jump cbs; can we get by w/o knowing this? inv. layering */ + GtkWidget * window; + gint width; + gint height; + + SCM toolbar_change_callback_id; + GtkWidget * toolbar; + GtkWidget * statusbar; + + GtkWidget * popup_menu; + + GtkWidget * style_menu; + GtkWidget * sort_menu; + GtkWidget * edit_menu; + GtkWidget * transaction_menu; + GtkWidget * help_menu; + + GtkWidget * double_line_check; + + GtkWidget * split_button; + GtkWidget * split_menu_check; + GtkWidget * split_popup_check; + + GNCLedgerDisplay * ledger; + /* The actual sheet widget */ + GnucashRegister *reg; + + sort_type_t sort_type; +}; + +struct _GNCRegWidgetClass { + GtkVBoxClass parent_class; + + /* Signal prototype holders */ + void (*enter_ent_cb)( GNCRegWidget *w, gpointer user_data ); + void (*cancel_ent_cb)( GNCRegWidget *w, gpointer user_data ); + void (*delete_ent_cb)( GNCRegWidget *w, gpointer user_data ); + void (*dup_ent_cb)( GNCRegWidget *w, gpointer user_data ); + void (*expand_ent_cb)( GNCRegWidget *w, gpointer user_data ); + void (*blank_cb)( GNCRegWidget *w, gpointer user_data ); + void (*jump_cb)( GNCRegWidget *w, gpointer user_data ); +}; + +guint gnc_regWidget_get_type( void ); + +GtkWidget *gnc_regWidget_new( GNCLedgerDisplay *ld, GtkWindow *parent ); + +GnucashSheet *gnc_regWidget_get_sheet( GNCRegWidget *rw ); + +GtkWidget *gnc_regWidget_get_style_menu( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_sort_menu( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_edit_menu( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_transaction_menu( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_help_menu( GNCRegWidget *rw ); + +GtkWidget *gnc_regWidget_get_toolbar( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_statusbar( GNCRegWidget *rw ); +GtkWidget *gnc_regWidget_get_popup( GNCRegWidget *rw ); + +#endif /* !defined(GNC_REGWIDGET_H) */