diff --git a/Makefile.am b/Makefile.am index 965873ecf3..33ac0c776e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ EXTRA_DIST = \ macros/compiler-flags.m4 \ macros/ac_pkg_swig.m4 \ macros/legacy_macros.m4 \ + macros/introspection.m4 \ po/gnucash.pot \ po/POTFILES.in \ po/POTFILES.skip \ diff --git a/configure.ac b/configure.ac index 8a0f5019ef..57d5fea5e4 100644 --- a/configure.ac +++ b/configure.ac @@ -23,6 +23,7 @@ AC_PREREQ(2.59) AC_INIT([GnuCash], [2.4.99], [gnucash-devel@gnucash.org]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_SRCDIR(src/engine/Transaction.h) +AC_CONFIG_MACRO_DIR(macros) #Change this in development versions when changing anything that #affects stored data structures. Reset to zero when bumping version. @@ -101,12 +102,6 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", AM_GLIB_GNU_GETTEXT - -# Enable only when we have autoconf --version >= 2.59 -# on all platforms. Note that AC_PREREQ(2.59) may be -# insufficient to actually use v2.59 on OSX -#AC_CONFIG_MACRO_DIR(macros) - AC_PROG_INSTALL PKG_PROG_PKG_CONFIG @@ -232,6 +227,8 @@ fi # We require glib >= 2.20, released together with gtk-2.16 PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.20 gthread-2.0 gobject-2.0 gmodule-2.0) +GOBJECT_INTROSPECTION_CHECK([0.6.7]) + AC_CHECK_HEADERS(dirent.h dlfcn.h dl.h utmp.h locale.h mcheck.h unistd.h wctype.h) # Gnucash replaced dlopen/dlsym by the g_module functions; dlsym diff --git a/src/engine/Account.c b/src/engine/Account.c index dccb0c1ca4..ebe8c13119 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -288,7 +288,7 @@ mark_account (Account *acc) \********************************************************************/ /* GObject Initialization */ -G_DEFINE_TYPE(Account, gnc_account, QOF_TYPE_INSTANCE) +G_DEFINE_TYPE(GncAccount, gnc_account, QOF_TYPE_INSTANCE) static void gnc_account_init(Account* acc) @@ -534,7 +534,7 @@ gnc_account_set_property (GObject *object, } static void -gnc_account_class_init (AccountClass *klass) +gnc_account_class_init (GncAccountClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); diff --git a/src/engine/Account.h b/src/engine/Account.h index 30106cdd63..8d4aa28ef6 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -48,35 +48,35 @@ #include "gnc-engine.h" #include "policy.h" -typedef gnc_numeric (*xaccGetBalanceFn)( const Account *account ); +typedef gnc_numeric (*xaccGetBalanceFn)( const GncAccount *account ); typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); typedef gnc_numeric (*xaccGetBalanceAsOfDateFn) ( - Account *account, time_t date); + GncAccount *account, time_t date); -typedef void (*AccountCb)(Account *a, gpointer data); -typedef gpointer (*AccountCb2)(Account *a, gpointer data); +typedef void (*AccountCb)(GncAccount *a, gpointer data); +typedef gpointer (*AccountCb2)(GncAccount *a, gpointer data); typedef struct { QofInstanceClass parent_class; -} AccountClass; +} GncAccountClass; /* --- type macros --- */ #define GNC_TYPE_ACCOUNT (gnc_account_get_type ()) #define GNC_ACCOUNT(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_ACCOUNT, Account)) + (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_ACCOUNT, GncAccount)) #define GNC_ACCOUNT_CLASS(k) \ - (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_ACCOUNT, AccountClass)) + (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_ACCOUNT, GncAccountClass)) #define GNC_IS_ACCOUNT(o) \ (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_ACCOUNT)) #define GNC_IS_ACCOUNT_CLASS(k) \ (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_ACCOUNT)) #define GNC_ACCOUNT_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_ACCOUNT, AccountClass)) + (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_ACCOUNT, GncAccountClass)) GType gnc_account_get_type(void); /** The account types are used to determine how the transaction data @@ -164,14 +164,14 @@ typedef enum -/** @name Account Constructors, Edit/Commit, Comparison +/** @name GncAccount Constructors, Edit/Commit, Comparison @{ */ /** Constructor */ -Account * xaccMallocAccount (QofBook *book); +GncAccount * xaccMallocAccount (QofBook *book); /** Create a new root level account. */ -Account * gnc_account_create_root (QofBook *book); +GncAccount * gnc_account_create_root (QofBook *book); /** The xaccCloneAccount() does the same as xaccCloneAccountSimple(), * except that it also also places a pair of GncGUID-pointers @@ -179,7 +179,7 @@ Account * gnc_account_create_root (QofBook *book); * The guid pointers are stored under the under the kvp * path "gemini". */ -Account * xaccCloneAccount (const Account *source, QofBook *book); +GncAccount * xaccCloneAccount (const GncAccount *source, QofBook *book); /** The xaccCloneAccountSimple() routine makes a simple copy of the * indicated account, placing it in the indicated book. It copies @@ -191,23 +191,23 @@ Account * xaccCloneAccount (const Account *source, QofBook *book); * Note that this routines does *NOT* use the 'gemini' kvp value * to indicate where it was copied from. */ -Account * xaccCloneAccountSimple (const Account *source, QofBook *book); +GncAccount * xaccCloneAccountSimple (const GncAccount *source, QofBook *book); /** The xaccAccountBeginEdit() subroutine is the first phase of * a two-phase-commit wrapper for account updates. */ -void xaccAccountBeginEdit (Account *account); +void xaccAccountBeginEdit (GncAccount *account); /** ThexaccAccountCommitEdit() subroutine is the second phase of * a two-phase-commit wrapper for account updates. */ -void xaccAccountCommitEdit (Account *account); +void xaccAccountCommitEdit (GncAccount *account); /** The xaccAccountDestroy() routine can be used to get rid of an * account. The account should have been opened for editing * (by calling xaccAccountBeginEdit()) before calling this routine.*/ -void xaccAccountDestroy (Account *account); +void xaccAccountDestroy (GncAccount *account); /** Compare two accounts for equality - this is a deep compare. */ -gboolean xaccAccountEqual(const Account *a, const Account* b, +gboolean xaccAccountEqual(const GncAccount *a, const GncAccount* b, gboolean check_guids); /** The xaccAccountOrder() subroutine defines a sorting order @@ -218,13 +218,13 @@ gboolean xaccAccountEqual(const Account *a, const Account* b, * the account codes are compared, and if these are equal, then * account types, and, if these are equal, the account names. */ -int xaccAccountOrder (const Account *account_1, const Account *account_2); +int xaccAccountOrder (const GncAccount *account_1, const GncAccount *account_2); /** @} */ /* ------------------ */ -/** @name Account lookup and GncGUID routines +/** @name GncAccount lookup and GncGUID routines @{ */ /** Returns the account separation character chosen by the user. @@ -236,8 +236,8 @@ gunichar gnc_get_account_separator (void); void gnc_set_account_separator (const gchar *separator); /*@ dependent @*/ -Account *gnc_book_get_root_account(QofBook *book); -void gnc_book_set_root_account(QofBook *book, Account *root); +GncAccount *gnc_book_get_root_account(QofBook *book); +void gnc_book_set_root_account(QofBook *book, GncAccount *root); /** @deprecated */ #define xaccAccountGetGUID(X) qof_entity_get_guid(QOF_INSTANCE(X)) @@ -246,7 +246,7 @@ void gnc_book_set_root_account(QofBook *book, Account *root); /** The xaccAccountLookup() subroutine will return the * account associated with the given id, or NULL * if there is no such account. */ -/*@ dependent @*/ Account * xaccAccountLookup (const GncGUID *guid, QofBook *book); +/*@ dependent @*/ GncAccount * xaccAccountLookup (const GncGUID *guid, QofBook *book); #define xaccAccountLookupDirect(g,b) xaccAccountLookup(&(g),b) /** @} */ @@ -279,30 +279,30 @@ GList *gnc_account_list_name_violations (QofBook *book, const gchar *separator); /* ------------------ */ -/** @name Account general setters/getters +/** @name GncAccount general setters/getters @{ */ -QofBook *gnc_account_get_book(const Account *account); +QofBook *gnc_account_get_book(const GncAccount *account); /** Set the account's type */ -void xaccAccountSetType (Account *account, GNCAccountType); +void xaccAccountSetType (GncAccount *account, GNCAccountType); /** Set the account's name */ -void xaccAccountSetName (Account *account, const char *name); +void xaccAccountSetName (GncAccount *account, const char *name); /** Set the account's accounting code */ -void xaccAccountSetCode (Account *account, const char *code); +void xaccAccountSetCode (GncAccount *account, const char *code); /** Set the account's description */ -void xaccAccountSetDescription (Account *account, const char *desc); +void xaccAccountSetDescription (GncAccount *account, const char *desc); /** Set the account's Color */ -void xaccAccountSetColor (Account *account, const char *color); +void xaccAccountSetColor (GncAccount *account, const char *color); /** Set the account's notes */ -void xaccAccountSetNotes (Account *account, const char *notes); -/** Set the last num field of an Account */ -void xaccAccountSetLastNum (Account *account, const char *num); +void xaccAccountSetNotes (GncAccount *account, const char *notes); +/** Set the last num field of an GncAccount */ +void xaccAccountSetLastNum (GncAccount *account, const char *num); /** Set the account's lot order policy */ -void gnc_account_set_policy (Account *account, GNCPolicy *policy); +void gnc_account_set_policy (GncAccount *account, GNCPolicy *policy); /** Get the account's type */ -GNCAccountType xaccAccountGetType (const Account *account); +GNCAccountType xaccAccountGetType (const GncAccount *account); /** Is the account a stock, mutual fund or currency? */ -gboolean xaccAccountIsPriced(const Account *acc); +gboolean xaccAccountIsPriced(const GncAccount *acc); /** This function will set the starting commodity balance for this * account. This routine is intended for use with backends that do @@ -311,7 +311,7 @@ gboolean xaccAccountIsPriced(const Account *acc); * return all of the splits after some certain date, and the * 'starting balance' will represent the summation of the splits up * to that date. */ -void gnc_account_set_start_balance (Account *acc, +void gnc_account_set_start_balance (GncAccount *acc, const gnc_numeric start_baln); /** This function will set the starting cleared commodity balance for @@ -321,7 +321,7 @@ void gnc_account_set_start_balance (Account *acc, * typically return all of the splits after some certain date, and * the 'starting balance' will represent the summation of the splits * up to that date. */ -void gnc_account_set_start_cleared_balance (Account *acc, +void gnc_account_set_start_cleared_balance (GncAccount *acc, const gnc_numeric start_baln); /** This function will set the starting reconciled commodity balance @@ -331,20 +331,20 @@ void gnc_account_set_start_cleared_balance (Account *acc, * typically return all of the splits after some certain date, and * the 'starting balance' will represent the summation of the splits * up to that date. */ -void gnc_account_set_start_reconciled_balance (Account *acc, +void gnc_account_set_start_reconciled_balance (GncAccount *acc, const gnc_numeric start_baln); /** Tell the account that the running balances may be incorrect and * need to be recomputed. * * @param acc Set the flag on this account. */ -void gnc_account_set_balance_dirty (Account *acc); +void gnc_account_set_balance_dirty (GncAccount *acc); /** Tell the account believes that the splits may be incorrectly * sorted and need to be resorted. * * @param acc Set the flag on this account. */ -void gnc_account_set_sort_dirty (Account *acc); +void gnc_account_set_sort_dirty (GncAccount *acc); /** Find the given split in an account. * @@ -354,7 +354,7 @@ void gnc_account_set_sort_dirty (Account *acc); * * @result TRUE is the split is found in the accounts list of splits. * FALSE otherwise. */ -gboolean gnc_account_find_split (Account *acc, Split *s); +gboolean gnc_account_find_split (GncAccount *acc, Split *s); /** Insert the given split from an account. * @@ -365,7 +365,7 @@ gboolean gnc_account_find_split (Account *acc, Split *s); * @result TRUE is the split is successfully added to the set of * splits in the account. FALSE if the addition fails for any reason * (including that the split is already in the account). */ -gboolean gnc_account_insert_split (Account *acc, Split *s); +gboolean gnc_account_insert_split (GncAccount *acc, Split *s); /** Remove the given split from an account. * @@ -376,32 +376,32 @@ gboolean gnc_account_insert_split (Account *acc, Split *s); * @result TRUE is the split is successfully removed from the set of * splits in the account. FALSE if the removal fails for any * reason. */ -gboolean gnc_account_remove_split (Account *acc, Split *s); +gboolean gnc_account_remove_split (GncAccount *acc, Split *s); /** Get the account's name */ -const char * xaccAccountGetName (const Account *account); +const char * xaccAccountGetName (const GncAccount *account); /** Get the account's accounting code */ -const char * xaccAccountGetCode (const Account *account); +const char * xaccAccountGetCode (const GncAccount *account); /** Get the account's description */ -const char * xaccAccountGetDescription (const Account *account); +const char * xaccAccountGetDescription (const GncAccount *account); /** Get the account's color */ -const char * xaccAccountGetColor (const Account *account); +const char * xaccAccountGetColor (const GncAccount *account); /** Get the account's notes */ -const char * xaccAccountGetNotes (const Account *account); -/** Get the last num field of an Account */ -const char * xaccAccountGetLastNum (const Account *account); +const char * xaccAccountGetNotes (const GncAccount *account); +/** Get the last num field of an GncAccount */ +const char * xaccAccountGetLastNum (const GncAccount *account); /** Get the account's lot order policy */ -GNCPolicy *gnc_account_get_policy (Account *account); +GNCPolicy *gnc_account_get_policy (GncAccount *account); /** Retrieve the starting commodity balance for this account. */ -gnc_numeric gnc_account_get_start_balance (Account *acc); +gnc_numeric gnc_account_get_start_balance (GncAccount *acc); /** Retrieve the starting cleared commodity balance for this * account. */ -gnc_numeric gnc_account_get_start_cleared_balance (Account *acc); +gnc_numeric gnc_account_get_start_cleared_balance (GncAccount *acc); /** Retrieve the starting reconciled commodity balance for this * account. */ -gnc_numeric gnc_account_get_start_reconciled_balance (Account *acc); +gnc_numeric gnc_account_get_start_reconciled_balance (GncAccount *acc); /** Get an indication of whether the account believes that the running * balances may be incorrect and need to be recomputed. @@ -410,7 +410,7 @@ gnc_numeric gnc_account_get_start_reconciled_balance (Account *acc); * * @return TRUE if the running account balances need to be recomputed. * FALSE if they are correct. */ -gboolean gnc_account_get_balance_dirty (Account *acc); +gboolean gnc_account_get_balance_dirty (GncAccount *acc); /** Get an indication of whether the account believes that the splits * may be incorrectly sorted and need to be resorted. @@ -419,18 +419,18 @@ gboolean gnc_account_get_balance_dirty (Account *acc); * * @return TRUE if the splits in the account need to be resorted. * FALSE if the sort order is correct. */ -gboolean gnc_account_get_sort_dirty (Account *acc); +gboolean gnc_account_get_sort_dirty (GncAccount *acc); /** The following recompute the partial balances (stored with the * transaction) and the total balance, for this account */ -void xaccAccountRecomputeBalance (Account *); +void xaccAccountRecomputeBalance (GncAccount *); /** The xaccAccountSortSplits() routine will resort the account's * splits if the sort is dirty. If 'force' is true, the account * is sorted even if the editlevel is not zero. */ -void xaccAccountSortSplits (Account *acc, gboolean force); +void xaccAccountSortSplits (GncAccount *acc, gboolean force); /** The gnc_account_get_full_name routine returns the fully qualified name * of the account using the given separator char. The name must be @@ -445,7 +445,7 @@ void xaccAccountSortSplits (Account *acc, gboolean force); * hack alert -- since it breaks the rule of string allocation, maybe this * routine should not be in this library, but some utility library? */ -gchar * gnc_account_get_full_name (const Account *account); +gchar * gnc_account_get_full_name (const GncAccount *account); /** Set a string that identifies the Finance::Quote backend that * should be used to retrieve online prices. See price-quotes.scm @@ -453,31 +453,31 @@ gchar * gnc_account_get_full_name (const Account *account); * * @deprecated Price quote information is now stored on the * commodity, not the account. */ -void dxaccAccountSetPriceSrc (Account *account, const char *src); +void dxaccAccountSetPriceSrc (GncAccount *account, const char *src); /** Get a string that identifies the Finance::Quote backend that * should be used to retrieve online prices. See price-quotes.scm * for more information. * * @deprecated Price quote information is now stored on the * commodity, not the account. */ -const char * dxaccAccountGetPriceSrc (const Account *account); +const char * dxaccAccountGetPriceSrc (const GncAccount *account); /** Returns a per-account flag: Prior to reconciling an account which charges or pays interest, this flag tells whether to prompt the user to enter a transaction for the interest charge or payment. This per-account flag overrides the global preference. */ -gboolean xaccAccountGetAutoInterestXfer (const Account *account, +gboolean xaccAccountGetAutoInterestXfer (const GncAccount *account, gboolean default_value); /** Sets a per-account flag: Prior to reconciling an account which charges or pays interest, this flag tells whether to prompt the user to enter a transaction for the interest charge or payment. This per-account flag overrides the global preference. */ -void xaccAccountSetAutoInterestXfer (Account *account, gboolean value); +void xaccAccountSetAutoInterestXfer (GncAccount *account, gboolean value); /** @} */ -/** @name Account Commodity setters/getters +/** @name GncAccount Commodity setters/getters - * Accounts are used to store an amount of 'something', that 'something' + * GncAccounts are used to store an amount of 'something', that 'something' * is called the 'commodity'. An account can only hold one kind of * commodity. The following are used to get and set the commodity, * and also to set the SCU, the 'Smallest Commodity Unit'. @@ -507,52 +507,52 @@ void xaccAccountSetAutoInterestXfer (Account *account, gboolean value); */ /** Set the account's commodity */ -void xaccAccountSetCommodity (Account *account, gnc_commodity *comm); +void xaccAccountSetCommodity (GncAccount *account, gnc_commodity *comm); /** Get the account's commodity */ -/*@ dependent @*/ gnc_commodity * xaccAccountGetCommodity (const Account *account); +/*@ dependent @*/ gnc_commodity * xaccAccountGetCommodity (const GncAccount *account); /** Return the SCU for the account. If a non-standard SCU has been * set for the account, that is returned; else the default SCU for * the account commodity is returned. */ -int xaccAccountGetCommoditySCU (const Account *account); +int xaccAccountGetCommoditySCU (const GncAccount *account); /** Return the 'internal' SCU setting. This returns the over-ride * SCU for the account (which might not be set, and might be zero). */ -int xaccAccountGetCommoditySCUi (const Account *account); +int xaccAccountGetCommoditySCUi (const GncAccount *account); /** Set the SCU for the account. Normally, this routine is not * required, as the default SCU for an account is given by its * commodity. */ -void xaccAccountSetCommoditySCU (Account *account, int frac); +void xaccAccountSetCommoditySCU (GncAccount *account, int frac); /** Set the flag indicating that this account uses a non-standard SCU. */ -void xaccAccountSetNonStdSCU (Account *account, gboolean flag); +void xaccAccountSetNonStdSCU (GncAccount *account, gboolean flag); /** Return boolean, indicating whether this account uses a * non-standard SCU. */ -gboolean xaccAccountGetNonStdSCU (const Account *account); +gboolean xaccAccountGetNonStdSCU (const GncAccount *account); /**@}*/ -/** @name Account Balance +/** @name GncAccount Balance @{ */ /** Get the current balance of the account, which may include future splits */ -gnc_numeric xaccAccountGetBalance (const Account *account); +gnc_numeric xaccAccountGetBalance (const GncAccount *account); /** Get the current balance of the account, only including cleared transactions */ -gnc_numeric xaccAccountGetClearedBalance (const Account *account); +gnc_numeric xaccAccountGetClearedBalance (const GncAccount *account); /** Get the current balance of the account, only including reconciled transactions */ -gnc_numeric xaccAccountGetReconciledBalance (const Account *account); -gnc_numeric xaccAccountGetPresentBalance (const Account *account); -gnc_numeric xaccAccountGetProjectedMinimumBalance (const Account *account); +gnc_numeric xaccAccountGetReconciledBalance (const GncAccount *account); +gnc_numeric xaccAccountGetPresentBalance (const GncAccount *account); +gnc_numeric xaccAccountGetProjectedMinimumBalance (const GncAccount *account); /** Get the balance of the account as of the date specified */ -gnc_numeric xaccAccountGetBalanceAsOfDate (Account *account, +gnc_numeric xaccAccountGetBalanceAsOfDate (GncAccount *account, time_t date); /* These two functions convert a given balance from one commodity to @@ -565,45 +565,45 @@ gnc_numeric xaccAccountGetBalanceAsOfDate (Account *account, probably some better place for them, but where? gnc-commodity.h? */ gnc_numeric xaccAccountConvertBalanceToCurrency( - const Account *account, /* for book */ + const GncAccount *account, /* for book */ gnc_numeric balance, const gnc_commodity *balance_currency, const gnc_commodity *new_currency); gnc_numeric xaccAccountConvertBalanceToCurrencyAsOfDate( - const Account *account, /* for book */ + const GncAccount *account, /* for book */ gnc_numeric balance, gnc_commodity *balance_currency, gnc_commodity *new_currency, time_t date); /* These functions get some type of balance in the desired commodity. 'report_commodity' may be NULL to use the account's commodity. */ gnc_numeric xaccAccountGetBalanceInCurrency ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); gnc_numeric xaccAccountGetClearedBalanceInCurrency ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); gnc_numeric xaccAccountGetReconciledBalanceInCurrency ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); gnc_numeric xaccAccountGetPresentBalanceInCurrency ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); gnc_numeric xaccAccountGetProjectedMinimumBalanceInCurrency ( - const Account *account, const gnc_commodity *report_commodity, + const GncAccount *account, const gnc_commodity *report_commodity, gboolean include_children); /* This function gets the balance as of the given date in the desired commodity. */ gnc_numeric xaccAccountGetBalanceAsOfDateInCurrency( - Account *account, time_t date, gnc_commodity *report_commodity, + GncAccount *account, time_t date, gnc_commodity *report_commodity, gboolean include_children); gnc_numeric xaccAccountGetBalanceChangeForPeriod ( - Account *acc, time_t date1, time_t date2, gboolean recurse); + GncAccount *acc, time_t date1, time_t date2, gboolean recurse); /** @} */ -/** @name Account Children and Parents. +/** @name GncAccount Children and Parents. * The set of accounts is represented as a doubly-linked tree, so that given * any account, both its parent and its children can be easily found. @@ -634,7 +634,7 @@ gnc_numeric xaccAccountGetBalanceChangeForPeriod ( * * @param child The account to attach. */ -void gnc_account_append_child (Account *new_parent, Account *child); +void gnc_account_append_child (GncAccount *new_parent, GncAccount *child); /** This function will remove the speified child account from the * specified parent account. It will NOT free the associated memory @@ -646,7 +646,7 @@ void gnc_account_append_child (Account *new_parent, Account *child); * removed. * * @param child The child account to remove. */ -void gnc_account_remove_child (Account *parent, Account *child); +void gnc_account_remove_child (GncAccount *parent, GncAccount *child); /** This routine returns a pointer to the parent of the specified * account. If the account has no parent, i.e it is either the root @@ -657,7 +657,7 @@ void gnc_account_remove_child (Account *parent, Account *child); * @return A pointer to the parent account node, or NULL if there is * no parent account. */ /*@ dependent @*/ -Account * gnc_account_get_parent (const Account *account); +GncAccount * gnc_account_get_parent (const GncAccount *account); /** This routine returns the root account of the account tree that the * specified account belongs to. It is the equivalent of repeatedly @@ -668,7 +668,7 @@ Account * gnc_account_get_parent (const Account *account); * * @return The root node of the account tree to which this account * belongs. NULL if the account is not part of any account tree. */ -Account * gnc_account_get_root (Account *account); +GncAccount * gnc_account_get_root (GncAccount *account); /** This routine indicates whether the spcified account is the root * node of an account tree. @@ -676,7 +676,7 @@ Account * gnc_account_get_root (Account *account); * @param account A pointer to any account. * * @return TRUE if this account is of type ROOT. FALSE otherwise. */ -gboolean gnc_account_is_root (const Account *account); +gboolean gnc_account_is_root (const GncAccount *account); /** This routine returns a GList of all children of the specified * account. This function only returns the immediate children of the @@ -688,8 +688,8 @@ gboolean gnc_account_is_root (const Account *account); * @return A GList of account pointers, or NULL if there are no * children. It is the callers responsibility to free any returned * list with the g_list_free() function. */ -GList *gnc_account_get_children (const Account *account); -GList *gnc_account_get_children_sorted (const Account *account); +GList *gnc_account_get_children (const GncAccount *account); +GList *gnc_account_get_children_sorted (const GncAccount *account); /** Return the number of children of the specified account. The * returned number does not include the account itself. @@ -697,7 +697,7 @@ GList *gnc_account_get_children_sorted (const Account *account); * @param account The account to query. * * @return The number of children of the specified account. */ -gint gnc_account_n_children (const Account *account); +gint gnc_account_n_children (const GncAccount *account); /** Return the index of the specified child within the list of the * parent's children. The first child index is 0. This function @@ -710,7 +710,7 @@ gint gnc_account_n_children (const Account *account); * * @return The index of the child account within the specified * parent, or -1. */ -gint gnc_account_child_index (const Account *parent, const Account *child); +gint gnc_account_child_index (const GncAccount *parent, const GncAccount *child); /** Return the n'th child account of the specified parent account. If * the parent account is not specified or the child index number is @@ -722,7 +722,7 @@ gint gnc_account_child_index (const Account *parent, const Account *child); * returned. * * @return A pointer to the specified child account, or NULL */ -Account *gnc_account_nth_child (const Account *parent, gint num); +GncAccount *gnc_account_nth_child (const GncAccount *parent, gint num); /** This routine returns a flat list of all of the accounts that are * descendants of the specified account. This includes not only the @@ -739,7 +739,7 @@ Account *gnc_account_nth_child (const Account *parent, gint num); * @return A GList of account pointers, or NULL if there are no * descendants. It is the callers responsibility to free any returned * list with the g_list_free() function. */ -GList * gnc_account_get_descendants (const Account *account); +GList * gnc_account_get_descendants (const GncAccount *account); /** This function returns a GList containing all the descendants of * the specified account, sorted at each level. This includes not @@ -759,7 +759,7 @@ GList * gnc_account_get_descendants (const Account *account); * @return A GList of account pointers, or NULL if there are no * descendants. It is the callers responsibility to free any returned * list with the g_list_free() function. */ -GList *gnc_account_get_descendants_sorted (const Account *account); +GList *gnc_account_get_descendants_sorted (const GncAccount *account); /** Return the number of descendants of the specified account. The * returned number does not include the account itself. @@ -767,7 +767,7 @@ GList *gnc_account_get_descendants_sorted (const Account *account); * @param account The account to query. * * @return The number of descendants of the specified account. */ -gint gnc_account_n_descendants (const Account *account); +gint gnc_account_n_descendants (const GncAccount *account); /** Return the number of levels of this account below the root * account. @@ -775,7 +775,7 @@ gint gnc_account_n_descendants (const Account *account); * @param account The account to query. * * @return The number of levels below the root. */ -gint gnc_account_get_current_depth (const Account *account); +gint gnc_account_get_current_depth (const GncAccount *account); /** Return the number of levels of descendants accounts below the * specified account. The returned number does not include the @@ -784,7 +784,7 @@ gint gnc_account_get_current_depth (const Account *account); * @param account The account to query. * * @return The number of levels of descendants. */ -gint gnc_account_get_tree_depth (const Account *account); +gint gnc_account_get_tree_depth (const GncAccount *account); /** @name ForEach @{ @@ -798,11 +798,11 @@ gint gnc_account_get_tree_depth (const Account *account); * @param account A pointer to the account on whose children the * function should be called. * - * @param func A function taking two arguments, an Account and a + * @param func A function taking two arguments, an GncAccount and a * gpointer. * * @param user_data This data will be passed to each call of func. */ -void gnc_account_foreach_child (const Account *account, +void gnc_account_foreach_child (const GncAccount *account, AccountCb func, /*@ null @*/ gpointer user_data); /** This method will traverse the immediate children of this accounts, @@ -816,11 +816,11 @@ void gnc_account_foreach_child (const Account *account, * @param account A pointer to the account on whose children the * function should be called. * - * @param func A function taking two arguments, an Account and a + * @param func A function taking two arguments, an GncAccount and a * gpointer. * * @param user_data This data will be passed to each call of func. */ -gpointer gnc_account_foreach_child_until (const Account *account, +gpointer gnc_account_foreach_child_until (const GncAccount *account, AccountCb2 func, /*@ null @*/ gpointer user_data); @@ -833,11 +833,11 @@ gpointer gnc_account_foreach_child_until (const Account *account, * @param account A pointer to the account on whose descendants the * function should be called. * - * @param func A function taking two arguments, an Account and a + * @param func A function taking two arguments, an GncAccount and a * gpointer. * * @param user_data This data will be passed to each call of func. */ -void gnc_account_foreach_descendant (const Account *account, +void gnc_account_foreach_descendant (const GncAccount *account, AccountCb func, /*@ null @*/ gpointer user_data); /** This method will traverse all children of this accounts and their @@ -851,11 +851,11 @@ void gnc_account_foreach_descendant (const Account *account, * @param account A pointer to the account on whose descendants the * function should be called. * - * @param func A function taking two arguments, an Account and a + * @param func A function taking two arguments, an GncAccount and a * gpointer. * * @param user_data This data will be passed to each call of func. */ -gpointer gnc_account_foreach_descendant_until (const Account *account, +gpointer gnc_account_foreach_descendant_until (const GncAccount *account, AccountCb2 func, /*@ null @*/ gpointer user_data); @@ -871,7 +871,7 @@ gpointer gnc_account_foreach_descendant_until (const Account *account, * that the moved accounts will have the to_parent's book parent * as well. */ -void gnc_account_join_children (Account *to_parent, Account *from_parent); +void gnc_account_join_children (GncAccount *to_parent, GncAccount *from_parent); /** The gnc_account_copy_children() subroutine will copy all child * accounts from the "src" account to the "dest" account, preserving @@ -880,35 +880,35 @@ void gnc_account_join_children (Account *to_parent, Account *from_parent); * routine will *NOT* copy any splits/transactions. It will copy the * KVP trees in each account. */ -void gnc_account_copy_children (Account *dest, Account *src); +void gnc_account_copy_children (GncAccount *dest, GncAccount *src); /** The gnc_account_merge_children() subroutine will go through an * account, merging all child accounts that have the same name and * description. This function is useful when importing Quicken(TM) * files. */ -void gnc_account_merge_children (Account *parent); +void gnc_account_merge_children (GncAccount *parent); /** @} */ /** DOCUMENT ME! */ -void xaccAccountSetReconcileChildrenStatus(Account *account, gboolean status); +void xaccAccountSetReconcileChildrenStatus(GncAccount *account, gboolean status); /** DOCUMENT ME! */ -gboolean xaccAccountGetReconcileChildrenStatus(const Account *account); +gboolean xaccAccountGetReconcileChildrenStatus(const GncAccount *account); /** Returns true if the account is 'ancestor' or has 'ancestor' as an * ancestor. An ancestor account may be the accounts parent, its * parent's parent, its parent's parent's parent, etc. Returns false * if either one is NULL. */ -gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor); +gboolean xaccAccountHasAncestor(const GncAccount *acc, const GncAccount *ancestor); #define xaccAccountGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X)) /** @} */ -/** @name Lookup Accounts and Subaccounts by name or code +/** @name Lookup GncAccounts and Subaccounts by name or code @{ */ /** The gnc_account_lookup_by_name() subroutine fetches the account by @@ -920,19 +920,19 @@ gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor); * @return A pointer to the account with the specified name, or NULL * if the account was not found. */ -Account *gnc_account_lookup_by_name (const Account *parent, const char *name); +GncAccount *gnc_account_lookup_by_name (const GncAccount *parent, const char *name); /** The gnc_account_lookup_full_name() subroutine works like * gnc_account_lookup_by_name, but uses fully-qualified names using the * given separator. */ -Account *gnc_account_lookup_by_full_name (const Account *any_account, +GncAccount *gnc_account_lookup_by_full_name (const GncAccount *any_account, const gchar *name); /** The gnc_account_lookup_full_name() subroutine works like * gnc_account_lookup_by_name, but uses the account code. */ -Account *gnc_account_lookup_by_code (const Account *parent, +GncAccount *gnc_account_lookup_by_code (const GncAccount *parent, const char *code); /** @} */ @@ -987,7 +987,7 @@ guint32 xaccAccountTypesValid(void); /* ------------------ */ -/** @name Account split/transaction list management +/** @name GncAccount split/transaction list management @{ */ /** The xaccAccountInsertSplit() method will insert the indicated @@ -1007,11 +1007,11 @@ guint32 xaccAccountTypesValid(void); * of the list. No other part of the code should have access to the * internal data structure used by this object. */ -SplitList* xaccAccountGetSplitList (const Account *account); +SplitList* xaccAccountGetSplitList (const GncAccount *account); /** The xaccAccountMoveAllSplits() routine reassigns each of the splits * in accfrom to accto. */ -void xaccAccountMoveAllSplits (Account *accfrom, Account *accto); +void xaccAccountMoveAllSplits (GncAccount *accfrom, GncAccount *accto); /** The xaccAccountForEachTransaction() routine will traverse all of * the transactions in @a account and call the callback @@ -1041,23 +1041,23 @@ void xaccAccountMoveAllSplits (Account *accfrom, Account *accto); * it will not traverse transactions present only in the remote * database. */ -gint xaccAccountForEachTransaction(const Account *account, +gint xaccAccountForEachTransaction(const GncAccount *account, TransactionCallback proc, void *data); /** Returns a pointer to the transaction, not a copy. */ -Transaction * xaccAccountFindTransByDesc(const Account *account, +Transaction * xaccAccountFindTransByDesc(const GncAccount *account, const char *description); /** Returns a pointer to the split, not a copy. */ -Split * xaccAccountFindSplitByDesc(const Account *account, +Split * xaccAccountFindSplitByDesc(const GncAccount *account, const char *description); /** @} */ /* ------------------ */ -/** @name Account lots +/** @name GncAccount lots @{ */ /** The xaccAccountInsertLot() method will register the indicated lot @@ -1065,8 +1065,8 @@ Split * xaccAccountFindSplitByDesc(const Account *account, * belong to this account. If the lot is already in another account, * the lot, and all of the splits in it, will be moved from that * account to this account. */ -void xaccAccountInsertLot (Account *, GNCLot *); -void xaccAccountRemoveLot (Account *, GNCLot *); +void xaccAccountInsertLot (GncAccount *, GNCLot *); +void xaccAccountRemoveLot (GncAccount *, GNCLot *); /** The xaccAccountGetLotList() routine returns a list of all lots in * this account. @@ -1076,7 +1076,7 @@ void xaccAccountRemoveLot (Account *, GNCLot *); * @return A GList of lot pointers, or NULL if there are no lots in * this account children. It is the callers responsibility to free * any returned list with the g_list_free() function. */ -LotList* xaccAccountGetLotList (const Account *account); +LotList* xaccAccountGetLotList (const GncAccount *account); /** The xaccAccountForEachLot() method will apply the function 'proc' * to each lot in the account. If 'proc' returns a non-NULL value, @@ -1085,7 +1085,7 @@ LotList* xaccAccountGetLotList (const Account *account); * the Lots will be traversed. */ gpointer xaccAccountForEachLot( - const Account *acc, + const GncAccount *acc, gpointer (*proc)(GNCLot *lot, gpointer user_data), /*@ null @*/ gpointer user_data); @@ -1094,7 +1094,7 @@ gpointer xaccAccountForEachLot( * If sort_func is NULL, then the returned list has no particular order. * The caller must free to returned list. */ -LotList * xaccAccountFindOpenLots (const Account *acc, +LotList * xaccAccountFindOpenLots (const GncAccount *acc, gboolean (*match_func)(GNCLot *lot, gpointer user_data), /*@ null @*/ gpointer user_data, GCompareFunc sort_func); @@ -1106,33 +1106,33 @@ LotList * xaccAccountFindOpenLots (const Account *acc, @{ */ /** DOCUMENT ME! */ -gboolean xaccAccountGetReconcileLastDate (const Account *account, +gboolean xaccAccountGetReconcileLastDate (const GncAccount *account, time_t *last_date); /** DOCUMENT ME! */ -void xaccAccountSetReconcileLastDate (Account *account, time_t last_date); +void xaccAccountSetReconcileLastDate (GncAccount *account, time_t last_date); /** DOCUMENT ME! */ -gboolean xaccAccountGetReconcileLastInterval (const Account *account, +gboolean xaccAccountGetReconcileLastInterval (const GncAccount *account, int *months, int *days); /** DOCUMENT ME! */ -void xaccAccountSetReconcileLastInterval (Account *account, +void xaccAccountSetReconcileLastInterval (GncAccount *account, int months, int days); /** DOCUMENT ME! */ -gboolean xaccAccountGetReconcilePostponeDate (const Account *account, +gboolean xaccAccountGetReconcilePostponeDate (const GncAccount *account, time_t *postpone_date); /** DOCUMENT ME! */ -void xaccAccountSetReconcilePostponeDate (Account *account, +void xaccAccountSetReconcilePostponeDate (GncAccount *account, time_t postpone_date); /** DOCUMENT ME! */ -gboolean xaccAccountGetReconcilePostponeBalance (const Account *account, +gboolean xaccAccountGetReconcilePostponeBalance (const GncAccount *account, gnc_numeric *balance); /** DOCUMENT ME! */ -void xaccAccountSetReconcilePostponeBalance (Account *account, +void xaccAccountSetReconcilePostponeBalance (GncAccount *account, gnc_numeric balance); /** DOCUMENT ME! */ -void xaccAccountClearReconcilePostpone (Account *account); +void xaccAccountClearReconcilePostpone (GncAccount *account); /** @} */ @@ -1154,7 +1154,7 @@ typedef enum * @param account The account whose flag should be retrieved. * * @return The current state of the account's "placeholder" flag. */ -gboolean xaccAccountGetPlaceholder (const Account *account); +gboolean xaccAccountGetPlaceholder (const GncAccount *account); /** Set the "placeholder" flag for an account. If this flag is set * then the account may not be modified by the user. @@ -1162,14 +1162,14 @@ gboolean xaccAccountGetPlaceholder (const Account *account); * @param account The account whose flag should be retrieved. * * @param val The new state for the account's "placeholder" flag. */ -void xaccAccountSetPlaceholder (Account *account, gboolean val); +void xaccAccountSetPlaceholder (GncAccount *account, gboolean val); /** Returns PLACEHOLDER_NONE if account is NULL or neither account nor * any descendant of account is a placeholder. If account is a * placeholder, returns PLACEHOLDER_THIS. Otherwise, if any * descendant of account is a placeholder, return PLACEHOLDER_CHILD. */ -GNCPlaceholderType xaccAccountGetDescendantPlaceholder(const Account *account); +GNCPlaceholderType xaccAccountGetDescendantPlaceholder(const GncAccount *account); /** @} */ /** @name Account Hidden flag @@ -1183,7 +1183,7 @@ GNCPlaceholderType xaccAccountGetDescendantPlaceholder(const Account *account); * @param acc The account whose flag should be retrieved. * * @return The current state of the account's "hidden" flag. */ -gboolean xaccAccountGetHidden (const Account *acc); +gboolean xaccAccountGetHidden (const GncAccount *acc); /** Set the "hidden" flag for an account. If this flag is set then * the account (and any children) will be hidden from the user unless @@ -1192,7 +1192,7 @@ gboolean xaccAccountGetHidden (const Account *acc); * @param acc The account whose flag should be retrieved. * * @param val The new state for the account's "hidden" flag. */ -void xaccAccountSetHidden (Account *acc, gboolean val); +void xaccAccountSetHidden (GncAccount *acc, gboolean val); /** Should this account be "hidden". If this flag is set for this * account (or any parent account) then the account should be hidden @@ -1203,7 +1203,7 @@ void xaccAccountSetHidden (Account *acc, gboolean val); * @param acc The account whose flag should be retrieved. * * @return Whether or not this account should be "hidden". */ -gboolean xaccAccountIsHidden (const Account *acc); +gboolean xaccAccountIsHidden (const GncAccount *acc); /** @} */ /** @name Account Tax related getters/setters @@ -1211,21 +1211,21 @@ gboolean xaccAccountIsHidden (const Account *acc); */ /** DOCUMENT ME! */ -gboolean xaccAccountGetTaxRelated (const Account *account); +gboolean xaccAccountGetTaxRelated (const GncAccount *account); /** DOCUMENT ME! */ -void xaccAccountSetTaxRelated (Account *account, gboolean tax_related); +void xaccAccountSetTaxRelated (GncAccount *account, gboolean tax_related); /** DOCUMENT ME! */ -const char * xaccAccountGetTaxUSCode (const Account *account); +const char * xaccAccountGetTaxUSCode (const GncAccount *account); /** DOCUMENT ME! */ -void xaccAccountSetTaxUSCode (Account *account, const char *code); +void xaccAccountSetTaxUSCode (GncAccount *account, const char *code); /** DOCUMENT ME! */ -const char * xaccAccountGetTaxUSPayerNameSource (const Account *account); +const char * xaccAccountGetTaxUSPayerNameSource (const GncAccount *account); /** DOCUMENT ME! */ -void xaccAccountSetTaxUSPayerNameSource (Account *account, const char *source); +void xaccAccountSetTaxUSPayerNameSource (GncAccount *account, const char *source); /** DOCUMENT ME! */ -gint64 xaccAccountGetTaxUSCopyNumber (const Account *account); +gint64 xaccAccountGetTaxUSCopyNumber (const GncAccount *account); /** DOCUMENT ME! */ -void xaccAccountSetTaxUSCopyNumber (Account *account, gint64 copy_number); +void xaccAccountSetTaxUSCopyNumber (GncAccount *account, gint64 copy_number); /** @} */ @@ -1238,18 +1238,18 @@ void xaccAccountSetTaxUSCopyNumber (Account *account, gint64 copy_number); * over the account tree. The mark is *not* stored in the database/file * format. When accounts are newly created, the mark is set to zero. */ -void xaccAccountSetMark (Account *account, short mark); +void xaccAccountSetMark (GncAccount *account, short mark); /** Get the mark set by xaccAccountSetMark */ -short xaccAccountGetMark (const Account *account); +short xaccAccountGetMark (const GncAccount *account); /** The xaccClearMark will find the root account, and clear the mark in * the entire account tree. */ -void xaccClearMark (Account *account, short val); +void xaccClearMark (GncAccount *account, short val); /** The xaccClearMarkDown will clear the mark only in this and in * sub-accounts.*/ -void xaccClearMarkDown (Account *account, short val); +void xaccClearMarkDown (GncAccount *account, short val); /** @} */ /** @name Staged Traversal @@ -1296,7 +1296,7 @@ void xaccClearMarkDown (Account *account, short val); * This is done so that a new sequence of staged traversals can * begin. */ -void gnc_account_tree_begin_staged_transaction_traversals(Account *acc); +void gnc_account_tree_begin_staged_transaction_traversals(GncAccount *acc); /** xaccSplitsBeginStagedTransactionTraversals() resets the traversal * marker for each transaction which is a parent of one of the @@ -1308,7 +1308,7 @@ void xaccSplitsBeginStagedTransactionTraversals(SplitList *splits); * marker for each transaction which is a parent of one of the * splits in the account. */ -void xaccAccountBeginStagedTransactionTraversals(const Account *account); +void xaccAccountBeginStagedTransactionTraversals(const GncAccount *account); /** xaccTransactionTraverse() checks the stage of the given transaction. * If the transaction hasn't reached the given stage, the transaction @@ -1335,7 +1335,7 @@ gboolean xaccSplitTransactionTraverse(Split *split, int stage); * of them to a different account. To do so risks a crash. */ -int xaccAccountStagedTransactionTraversal(const Account *a, +int xaccAccountStagedTransactionTraversal(const GncAccount *a, unsigned int stage, TransactionCallback thunk, void *data); @@ -1353,7 +1353,7 @@ int xaccAccountStagedTransactionTraversal(const Account *a, * of them to a different account. To do so risks a crash. */ -int gnc_account_tree_staged_transaction_traversal(const Account *account, +int gnc_account_tree_staged_transaction_traversal(const GncAccount *account, unsigned int stage, TransactionCallback thunk, void *data); @@ -1389,7 +1389,7 @@ int gnc_account_tree_staged_transaction_traversal(const Account *account, * gnc_account_tree_staged_transaction_traversal(g, 42, proc, data); */ -int xaccAccountTreeForEachTransaction(Account *acc, +int xaccAccountTreeForEachTransaction(GncAccount *acc, TransactionCallback proc, void *data); /** @} */ @@ -1404,12 +1404,12 @@ int xaccAccountTreeForEachTransaction(Account *acc, * it. * * These two funcs take control of their gnc_commodity args. Don't free */ -void DxaccAccountSetCurrency (Account *account, gnc_commodity *currency); +void DxaccAccountSetCurrency (GncAccount *account, gnc_commodity *currency); /** @deprecated The current API associates only one thing with an * account: the 'commodity'. Use xaccAccountGetCommodity() to fetch * it. */ -gnc_commodity * DxaccAccountGetCurrency (const Account *account); +gnc_commodity * DxaccAccountGetCurrency (const GncAccount *account); /** Set the timezone to be used when interpreting the results from a * given Finance::Quote backend. Unfortunately, the upstream sources @@ -1418,18 +1418,18 @@ gnc_commodity * DxaccAccountGetCurrency (const Account *account); * @deprecated Price quote information is now stored on the * commodity, not the account. */ -void dxaccAccountSetQuoteTZ (Account *account, const char *tz); +void dxaccAccountSetQuoteTZ (GncAccount *account, const char *tz); /** Get the timezone to be used when interpreting the results from a * given Finance::Quote backend. Unfortunately, the upstream sources * don't label their output, so the user has to specify this bit. * * @deprecated Price quote information is now stored on the * commodity, not the account. */ -const char * dxaccAccountGetQuoteTZ (const Account *account); +const char * dxaccAccountGetQuoteTZ (const GncAccount *account); /** @} */ -/** @name Account parameter names +/** @name GncAccount parameter names @{ */ #define ACCOUNT_KVP "kvp" diff --git a/src/engine/AccountP.h b/src/engine/AccountP.h index d8ada468b8..03c10034f4 100644 --- a/src/engine/AccountP.h +++ b/src/engine/AccountP.h @@ -49,7 +49,7 @@ * No one outside of the engine should ever include this file. */ -/** \struct Account */ +/** \struct GncAccount */ struct account_s { QofInstance inst; diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index aa53d709a5..74177b887e 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -1,5 +1,9 @@ SUBDIRS = . test-core test +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --add-include-path=$(top_builddir)/src/libqof/qof +INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) + pkglib_LTLIBRARIES = libgncmod-engine.la AM_CPPFLAGS = \ @@ -216,3 +220,24 @@ CLEANFILES = $(BUILT_SOURCES) gnucash .scm-links \ MAINTAINERCLEANFILES = swig-engine.c swig-business-core.c INCLUDES = -DG_LOG_DOMAIN=\"gnc.engine\" +if HAVE_INTROSPECTION +include ${INTROSPECTION_MAKEFILE} +introspection_sources = $(gncinclude_HEADERS) + +INTROSPECTION_GIRS += Gncengine.gir +Gncengine_gir_INCLUDES = GObject-2.0 GLib-2.0 Qof-1 +Gncengine_gir_NAMESPACE = Gnc +Gncengine_gir_CFLAGS = ${AM_CPPFLAGS} -I$(top_builddir) +Gncengine_gir_LIBS = libgncmod-engine.la +Gncengine_gir_FILES = $(introspection_sources) + + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = GncEngine.typelib + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif + diff --git a/src/engine/Split.h b/src/engine/Split.h index 1333149cd8..2a14d6da19 100644 --- a/src/engine/Split.h +++ b/src/engine/Split.h @@ -38,8 +38,8 @@ typedef struct _SplitClass SplitClass; #include -#include "gnc-commodity.h" #include "gnc-engine.h" +#include "gnc-commodity.h" /* --- type macros --- */ #define GNC_TYPE_SPLIT (gnc_split_get_type ()) diff --git "a/src/gnome-utils/gnc-main-window.c100644 01901c6c8752987f426cff1e6534ba0b27867fae\tsrc/gnome-utils/ui/Makefile.am100644 94c76a9e4c6a8f6ceaacfff0c1ed4c9e3d4128e1\tsrc/gnome-utils/ui/gnc-main-window-ui.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui-quartz.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui.xml" "b/src/gnome-utils/gnc-main-window.c100644 01901c6c8752987f426cff1e6534ba0b27867fae\tsrc/gnome-utils/ui/Makefile.am100644 94c76a9e4c6a8f6ceaacfff0c1ed4c9e3d4128e1\tsrc/gnome-utils/ui/gnc-main-window-ui.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui-quartz.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui.xml" deleted file mode 100644 index dbfdae9089..0000000000 --- "a/src/gnome-utils/gnc-main-window.c100644 01901c6c8752987f426cff1e6534ba0b27867fae\tsrc/gnome-utils/ui/Makefile.am100644 94c76a9e4c6a8f6ceaacfff0c1ed4c9e3d4128e1\tsrc/gnome-utils/ui/gnc-main-window-ui.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui-quartz.xml0 0000000000000000000000000000000000000000\tsrc/gnome-utils/ui/gnc-windows-menu-ui.xml" +++ /dev/null @@ -1,4349 +0,0 @@ -/* - * gnc-main-window.c -- GtkWindow which represents the - * GnuCash main window. - * - * Copyright (C) 2003 Jan Arne Petersen - * Copyright (C) 2003,2005,2006 David Hampton - * - * 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 - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 - * Boston, MA 02110-1301, USA gnu@gnu.org - */ - -/** @addtogroup Windows - @{ */ -/** @addtogroup GncMainWindow Main Window functions. - @{ */ -/** @file gnc-main-window.c - @brief Functions for adding content to a window. - @author Copyright (C) 2003 Jan Arne Petersen - @author Copyright (C) 2003,2005,2006 David Hampton -*/ -#include "config.h" - -#include -#include -#include -#include "guile-mappings.h" - -#include "gnc-plugin.h" -#include "gnc-plugin-manager.h" -#include "gnc-main-window.h" - -#include "dialog-preferences.h" -#include "dialog-reset-warnings.h" -#include "dialog-transfer.h" -#include "dialog-utils.h" -#include "file-utils.h" -#include "gnc-component-manager.h" -#include "gnc-engine.h" -#include "gnc-file.h" -#include "gnc-gkeyfile-utils.h" -#include "gnc-gnome-utils.h" -#include "gnc-gobject-utils.h" -#include "gnc-gui-query.h" -#include "gnc-hooks.h" -#include "gnc-session.h" -#include "gnc-ui.h" -#include "gnc-ui-util.h" -#include "gnc-uri-utils.h" -#include "core-utils/gnc-version.h" -#include "gnc-window.h" -#include "gnc-main.h" -#include "gnc-gconf-utils.h" -// +JSLED -//#include "gnc-html.h" -#include "gnc-autosave.h" -#include "print-session.h" -#ifdef MAC_INTEGRATION -#include -#endif - -/** Names of signals generated by the main window. */ -enum -{ - PAGE_ADDED, - PAGE_CHANGED, - LAST_SIGNAL -}; - -/** This label is used to provide a mapping from a visible page widget - * back to the corresponding GncPluginPage object. */ -#define PLUGIN_PAGE_LABEL "plugin-page" - -#define PLUGIN_PAGE_CLOSE_BUTTON "close-button" -#define PLUGIN_PAGE_TAB_LABEL "label" - -#define KEY_SHOW_CLOSE_BUTTON "tab_close_buttons" -#define KEY_TAB_NEXT_RECENT "tab_next_recent" -#define KEY_TAB_POSITION "tab_position" -#define KEY_TAB_WIDTH "tab_width" - -#define GNC_MAIN_WINDOW_NAME "GncMainWindow" - - -/* Static Globals *******************************************************/ - -/** The debugging module that this .o belongs to. */ -static QofLogModule log_module = GNC_MOD_GUI; -/** A pointer to the parent class of an embedded window. */ -static GObjectClass *parent_class = NULL; -/** An identifier that indicates a "main" window. */ -static GQuark window_type = 0; -/** A list of all extant main windows. This is for convenience as the - * same information can be obtained from the object tracking code. */ -static GList *active_windows = NULL; - -/* Declarations *********************************************************/ -static void gnc_main_window_class_init (GncMainWindowClass *klass); -static void gnc_main_window_init (GncMainWindow *window, GncMainWindowClass *klass); -static void gnc_main_window_finalize (GObject *object); -static void gnc_main_window_destroy (GtkObject *object); - -static void gnc_main_window_setup_window (GncMainWindow *window); -static void gnc_window_main_window_init (GncWindowIface *iface); -static void gnc_main_window_update_all_menu_items (void); - -/* Callbacks */ -static void gnc_main_window_add_widget (GtkUIManager *merge, GtkWidget *widget, GncMainWindow *window); -static void gnc_main_window_switch_page (GtkNotebook *notebook, GtkNotebookPage *notebook_page, gint pos, GncMainWindow *window); -static void gnc_main_window_page_reordered (GtkNotebook *notebook, GtkWidget *child, guint pos, GncMainWindow *window); -static void gnc_main_window_plugin_added (GncPlugin *manager, GncPlugin *plugin, GncMainWindow *window); -static void gnc_main_window_plugin_removed (GncPlugin *manager, GncPlugin *plugin, GncMainWindow *window); -static void gnc_main_window_engine_commit_error_callback( gpointer data, QofBackendError errcode ); - -/* Command callbacks */ -static void gnc_main_window_cmd_page_setup (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_file_properties (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_file_close (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_file_quit (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_edit_cut (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_edit_copy (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_edit_paste (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_edit_preferences (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_view_refresh (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_view_toolbar (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_view_summary (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_view_statusbar (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_actions_reset_warnings (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_actions_rename_page (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_window_new (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_window_move_page (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_window_raise (GtkAction *action, GtkRadioAction *current, GncMainWindow *window); -static void gnc_main_window_cmd_help_tutorial (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_help_contents (GtkAction *action, GncMainWindow *window); -static void gnc_main_window_cmd_help_about (GtkAction *action, GncMainWindow *window); - -static void do_popup_menu(GncPluginPage *page, GdkEventButton *event); -static gboolean gnc_main_window_popup_menu_cb (GtkWidget *widget, GncPluginPage *page); - -#ifdef MAC_INTEGRATION -static void gnc_quartz_shutdown(GtkOSXApplication *theApp, gpointer data); -static gboolean gnc_quartz_should_quit(GtkOSXApplication *theApp, GncMainWindow *window); -static void gnc_quartz_set_menu(GncMainWindow* window); -#endif - -/** The instance private data structure for an embedded window - * object. */ -typedef struct GncMainWindowPrivate -{ - /** The dock (vbox) at the top of the window containing the - * menubar and toolbar. These items are generated bu the UI - * manager and stored here when the UI manager provides them - * to the main window. */ - GtkWidget *menu_dock; - /** The toolbar created by the UI manager. This pointer - * provides easy access for showing/hiding the toolbar. */ - GtkWidget *toolbar; - /** The notebook containing all the pages in this window. */ - GtkWidget *notebook; - /** A pointer to the status bar at the bottom edge of the - * window. This pointer provides easy access for - * updating/showing/hiding the status bar. */ - GtkWidget *statusbar; - /** A pointer to the progress bar at the bottom right of the - * window that is contained in the status bar. This pointer - * provides easy access for updating the progressbar. */ - GtkWidget *progressbar; - - /** The group of all actions provided by the main window - * itself. This does not include any action provided by menu - * or content plugins. */ - GtkActionGroup *action_group; - - /** A list of all pages that are installed in this window. */ - GList *installed_pages; - /** A list of pages in order of use (most recent -> least recent) */ - GList *usage_order; - /** The currently selected page. */ - GncPluginPage *current_page; - /** The identifier for this window's engine event handler. */ - gint event_handler_id; - - /** A hash table of all action groups that have been installed - * into this window. The keys are the name of an action - * group, the values are structures of type - * MergedActionEntry. */ - GHashTable *merged_actions_table; -} GncMainWindowPrivate; - -#define GNC_MAIN_WINDOW_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_MAIN_WINDOW, GncMainWindowPrivate)) - -/** This data structure maintains information about one action groups - * that has been installed in this window. */ -typedef struct -{ - /** The merge identifier for this action group. This number - * is provided by the UI manager. */ - guint merge_id; - /** The action group itself. This contains all actions added - * by a single menu or content plugin. */ - GtkActionGroup *action_group; -} MergedActionEntry; - -/** A holding place for all the signals generated by the main window - * code. */ -static guint main_window_signals[LAST_SIGNAL] = { 0 }; - - -/** An array of all of the actions provided by the main window code. - * This includes some placeholder actions for the menus that are - * visible in the menu bar but have no action associated with - * them. */ -static GtkActionEntry gnc_menu_actions [] = -{ - /* Toplevel */ - - { "FileAction", NULL, N_("_File"), NULL, NULL, NULL, }, - { "EditAction", NULL, N_("_Edit"), NULL, NULL, NULL }, - { "ViewAction", NULL, N_("_View"), NULL, NULL, NULL }, - { "ActionsAction", NULL, N_("_Actions"), NULL, NULL, NULL }, - { "TransactionAction", NULL, N_("Tra_nsaction"), NULL, NULL, NULL }, - { "ReportsAction", NULL, N_("_Reports"), NULL, NULL, NULL }, - { "ToolsAction", NULL, N_("_Tools"), NULL, NULL, NULL }, - { "ExtensionsAction", NULL, N_("E_xtensions"), NULL, NULL, NULL }, - { "WindowsAction", NULL, N_("_Windows"), NULL, NULL, NULL }, - { "HelpAction", NULL, N_("_Help"), NULL, NULL, NULL }, - - /* File menu */ - - { "FileImportAction", NULL, N_("_Import"), NULL, NULL, NULL }, - { "FileExportAction", NULL, N_("_Export"), NULL, NULL, NULL }, - { - "FilePrintAction", GTK_STOCK_PRINT, N_("_Print..."), "p", - N_("Print the currently active page"), NULL - }, -#ifndef GTK_STOCK_PAGE_SETUP -# define GTK_STOCK_PAGE_SETUP NULL -#endif - { - "FilePageSetupAction", GTK_STOCK_PAGE_SETUP, N_("Pa_ge Setup..."), "p", - N_("Specify the page size and orientation for printing"), - G_CALLBACK (gnc_main_window_cmd_page_setup) - }, - { - "FilePropertiesAction", GTK_STOCK_PROPERTIES, N_("Proper_ties"), "Return", - N_("Edit the properties of the current file"), - G_CALLBACK (gnc_main_window_cmd_file_properties) - }, - { - "FileCloseAction", GTK_STOCK_CLOSE, N_("_Close"), NULL, - N_("Close the currently active page"), - G_CALLBACK (gnc_main_window_cmd_file_close) - }, - { - "FileQuitAction", GTK_STOCK_QUIT, N_("_Quit"), NULL, - N_("Quit this application"), - G_CALLBACK (gnc_main_window_cmd_file_quit) - }, - - /* Edit menu */ - - { - "EditCutAction", GTK_STOCK_CUT, N_("Cu_t"), NULL, - N_("Cut the current selection and copy it to clipboard"), - G_CALLBACK (gnc_main_window_cmd_edit_cut) - }, - { - "EditCopyAction", GTK_STOCK_COPY, N_("_Copy"), NULL, - N_("Copy the current selection to clipboard"), - G_CALLBACK (gnc_main_window_cmd_edit_copy) - }, - { - "EditPasteAction", GTK_STOCK_PASTE, N_("_Paste"), NULL, - N_("Paste the clipboard content at the cursor position"), - G_CALLBACK (gnc_main_window_cmd_edit_paste) - }, - { - "EditPreferencesAction", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), NULL, - N_("Edit the global preferences of GnuCash"), - G_CALLBACK (gnc_main_window_cmd_edit_preferences) - }, - - /* View menu */ - - { - "ViewSortByAction", NULL, N_("_Sort By..."), NULL, - N_("Select sorting criteria for this page view"), NULL - }, - { - "ViewFilterByAction", NULL, N_("_Filter By..."), NULL, - N_("Select the account types that should be displayed."), NULL - }, - { - "ViewRefreshAction", GTK_STOCK_REFRESH, N_("_Refresh"), "r", - N_("Refresh this window"), - G_CALLBACK (gnc_main_window_cmd_view_refresh) - }, - - /* Actions menu */ - - { "ScrubMenuAction", NULL, N_("_Check & Repair"), NULL, NULL, NULL }, - { - "ActionsForgetWarningsAction", NULL, N_("Reset _Warnings..."), NULL, - N_("Reset the state of all warning messages so they will be shown again."), - G_CALLBACK (gnc_main_window_cmd_actions_reset_warnings) - }, - { - "ActionsRenamePageAction", NULL, N_("Re_name Page"), NULL, - N_("Rename this page."), - G_CALLBACK (gnc_main_window_cmd_actions_rename_page) - }, - - /* Windows menu */ - - { - "WindowNewAction", NULL, N_("_New Window"), NULL, - N_("Open a new top-level GnuCash window."), - G_CALLBACK (gnc_main_window_cmd_window_new) - }, - { - "WindowMovePageAction", NULL, N_("New Window with _Page"), NULL, - N_("Move the current page to a new top-level GnuCash window."), - G_CALLBACK (gnc_main_window_cmd_window_move_page) - }, - - /* Help menu */ - - { - "HelpTutorialAction", GNOME_STOCK_BOOK_BLUE, N_("Tutorial and Concepts _Guide"), NULL, - N_("Open the GnuCash Tutorial"), - G_CALLBACK (gnc_main_window_cmd_help_tutorial) - }, - { - "HelpContentsAction", GTK_STOCK_HELP, N_("_Contents"), "F1", - N_("Open the GnuCash Help"), - G_CALLBACK (gnc_main_window_cmd_help_contents) - }, - { - "HelpAboutAction", GNOME_STOCK_ABOUT, N_("_About"), NULL, - N_("About GnuCash"), - G_CALLBACK (gnc_main_window_cmd_help_about) - }, -}; -/** The number of actions provided by the main window. */ -static guint gnc_menu_n_actions = G_N_ELEMENTS (gnc_menu_actions); - -/** An array of all of the toggle action provided by the main window - * code. */ -static GtkToggleActionEntry toggle_actions [] = -{ - { - "ViewToolbarAction", NULL, N_("_Toolbar"), NULL, - N_("Show/hide the toolbar on this window"), - G_CALLBACK (gnc_main_window_cmd_view_toolbar), TRUE - }, - { - "ViewSummaryAction", NULL, N_("Su_mmary Bar"), NULL, - N_("Show/hide the summary bar on this window"), - G_CALLBACK (gnc_main_window_cmd_view_summary), TRUE - }, - { - "ViewStatusbarAction", NULL, N_("Stat_us Bar"), NULL, - N_("Show/hide the status bar on this window"), - G_CALLBACK (gnc_main_window_cmd_view_statusbar), TRUE - }, -}; -/** The number of toggle actions provided by the main window. */ -static guint n_toggle_actions = G_N_ELEMENTS (toggle_actions); - -/** An array of all of the radio action provided by the main window - * code. */ -static GtkRadioActionEntry radio_entries [] = -{ - { "Window0Action", NULL, N_("Window _1"), NULL, NULL, 0 }, - { "Window1Action", NULL, N_("Window _2"), NULL, NULL, 1 }, - { "Window2Action", NULL, N_("Window _3"), NULL, NULL, 2 }, - { "Window3Action", NULL, N_("Window _4"), NULL, NULL, 3 }, - { "Window4Action", NULL, N_("Window _5"), NULL, NULL, 4 }, - { "Window5Action", NULL, N_("Window _6"), NULL, NULL, 5 }, - { "Window6Action", NULL, N_("Window _7"), NULL, NULL, 6 }, - { "Window7Action", NULL, N_("Window _8"), NULL, NULL, 7 }, - { "Window8Action", NULL, N_("Window _9"), NULL, NULL, 8 }, - { "Window9Action", NULL, N_("Window _0"), NULL, NULL, 9 }, -}; -/** The number of radio actions provided by the main window. */ -static guint n_radio_entries = G_N_ELEMENTS (radio_entries); - - -/** These are the "important" actions provided by the main window. - * Their labels will appear when the toolbar is set to "Icons and - * important text" (e.g. GTK_TOOLBAR_BOTH_HORIZ) mode. */ -static const gchar *gnc_menu_important_actions[] = -{ - "FileCloseAction", - NULL, -}; - - -/** The following are in the main window so they will always be - * present in the menu structure, but they are never sensitive. - * These actions should be overridden in child windows where they - * have meaning. */ -static const gchar *always_insensitive_actions[] = -{ - "FilePrintAction", - NULL -}; - - -/** The following items in the main window should be made insensitive - * at startup time. The sensitivity will be changed by some later - * event. */ -static const gchar *initially_insensitive_actions[] = -{ - "FileCloseAction", - NULL -}; - - -/** The following are in the main window so they will always be - * present in the menu structure, but they are always hidden. - * These actions should be overridden in child windows where they - * have meaning. */ -static const gchar *always_hidden_actions[] = -{ - "ViewSortByAction", - "ViewFilterByAction", - NULL -}; - - -/** If a page is flagged as immutable, then the following actions - * cannot be performed on that page. */ -static const gchar *immutable_page_actions[] = -{ - "FileCloseAction", - NULL -}; - - -/** The following actions can only be performed if there are multiple - * pages in a window. */ -static const gchar *multiple_page_actions[] = -{ - "WindowMovePageAction", - NULL -}; - - -/* This data structure holds the tooltops for all notebook tabs. - * Typically these are used to provide the full path of a register - * page. */ -static GtkTooltips *tips = NULL; - -/************************************************************ - * * - ************************************************************/ -#define WINDOW_COUNT "WindowCount" -#define WINDOW_STRING "Window %d" -#define WINDOW_GEOMETRY "WindowGeometry" -#define WINDOW_POSITION "WindowPosition" -#define WINDOW_MAXIMIZED "WindowMaximized" -#define TOOLBAR_VISIBLE "ToolbarVisible" -#define STATUSBAR_VISIBLE "StatusbarVisible" -#define SUMMARYBAR_VISIBLE "SummarybarVisible" -#define WINDOW_FIRSTPAGE "FirstPage" -#define WINDOW_PAGECOUNT "PageCount" -#define WINDOW_PAGEORDER "PageOrder" -#define PAGE_TYPE "PageType" -#define PAGE_NAME "PageName" -#define PAGE_STRING "Page %d" - -typedef struct -{ - GKeyFile *key_file; - const gchar *group_name; - gint window_num; - gint page_num; - gint page_offset; -} GncMainWindowSaveData; - - -/* Iterator function to walk all pages in all windows, calling the - * specified function for each page. */ -void -gnc_main_window_foreach_page (GncMainWindowPageFunc fn, gpointer user_data) -{ - GncMainWindowPrivate *priv; - GncMainWindow *window; - GncPluginPage *page; - GList *w, *p; - - ENTER(" "); - for (w = active_windows; w; w = g_list_next(w)) - { - window = w->data; - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - for (p = priv->installed_pages; p; p = g_list_next(p)) - { - page = p->data; - fn(page, user_data); - } - } - LEAVE(" "); -} - - -/** Restore a single page to a window. This function calls a page - * specific function to create the actual page. It then handles all - * the common tasks such as insuring the page is installed into a - * window, updating the page name, and anything else that might be - * common to all pages. - * - * @param window The GncMainWindow where the new page will be - * installed. - * - * @param data A data structure containing state about the - * window/page restoration process. */ -static void -gnc_main_window_restore_page (GncMainWindow *window, - GncMainWindowSaveData *data) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - gchar *page_group, *page_type = NULL, *name = NULL; - const gchar *class_type; - GError *error = NULL; - - ENTER("window %p, data %p (key file %p, window %d, page start %d, page num %d)", - window, data, data->key_file, data->window_num, data->page_offset, - data->page_num); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page_group = g_strdup_printf(PAGE_STRING, - data->page_offset + data->page_num); - page_type = g_key_file_get_string(data->key_file, page_group, - PAGE_TYPE, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - page_group, PAGE_TYPE, error->message); - goto cleanup; - } - - /* See if the page already exists. */ - page = g_list_nth_data(priv->installed_pages, data->page_num); - if (page) - { - class_type = GNC_PLUGIN_PAGE_GET_CLASS(page)->plugin_name; - if (strcmp(page_type, class_type) != 0) - { - g_warning("error: page types don't match: state %s, existing page %s", - page_type, class_type); - goto cleanup; - } - } - else - { - /* create and install the page */ - page = gnc_plugin_page_recreate_page(GTK_WIDGET(window), page_type, - data->key_file, page_group); - if (page) - { - /* Does the page still need to be installed into the window? */ - if (page->window == NULL) - { - gnc_plugin_page_set_use_new_window(page, FALSE); - gnc_main_window_open_page(window, page); - } - - /* Restore the page name */ - name = g_key_file_get_string(data->key_file, page_group, - PAGE_NAME, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - page_group, PAGE_NAME, error->message); - /* Fall through and still show the page. */ - } - else - { - DEBUG("updating page name for %p to %s.", page, name); - main_window_update_page_name(page, name); - g_free(name); - } - } - } - - LEAVE("ok"); -cleanup: - if (error) - g_error_free(error); - if (page_type) - g_free(page_type); - g_free(page_group); -} - - -/** Restore all the pages in a given window. This function restores - * all the window specific attributes, then calls a helper function - * to restore all the pages that are contained in the window. - * - * @param window The GncMainWindow whose pages should be restored. - * - * @param data A data structure containing state about the - * window/page restoration process. */ -static void -gnc_main_window_restore_window (GncMainWindow *window, GncMainWindowSaveData *data) -{ - GncMainWindowPrivate *priv; - GtkAction *action; - gint *pos, *geom, *order; - gsize length; - gboolean max, visible, desired_visibility; - gchar *window_group; - gint page_start, page_count, i; - GError *error = NULL; - - /* Setup */ - ENTER("window %p, data %p (key file %p, window %d)", - window, data, data->key_file, data->window_num); - window_group = g_strdup_printf(WINDOW_STRING, data->window_num + 1); - - /* Get this window's notebook info */ - page_count = g_key_file_get_integer(data->key_file, - window_group, WINDOW_PAGECOUNT, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_PAGECOUNT, error->message); - goto cleanup; - } - if (page_count == 0) - { - /* Shound never happen, but has during alpha testing. Having this - * check doesn't hurt anything. */ - goto cleanup; - } - page_start = g_key_file_get_integer(data->key_file, - window_group, WINDOW_FIRSTPAGE, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_FIRSTPAGE, error->message); - goto cleanup; - } - - /* Build a window if we don't already have one */ - if (window == NULL) - { - DEBUG("Window %d doesn't exist. Creating new window.", data->window_num); - DEBUG("active_windows %p.", active_windows); - if (active_windows) - DEBUG("first window %p.", active_windows->data); - window = gnc_main_window_new(); - gtk_widget_show(GTK_WIDGET(window)); - } - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - - /* Get the window coordinates, etc. */ - geom = g_key_file_get_integer_list(data->key_file, window_group, - WINDOW_GEOMETRY, &length, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_GEOMETRY, error->message); - g_error_free(error); - error = NULL; - } - else if (length != 2) - { - g_warning("invalid number of values for group %s key %s", - window_group, WINDOW_GEOMETRY); - } - else - { - gtk_window_resize(GTK_WINDOW(window), geom[0], geom[1]); - DEBUG("window (%p) size %dx%d", window, geom[0], geom[1]); - } - /* keep the geometry for a test whether the windows position - is offscreen */ - - pos = g_key_file_get_integer_list(data->key_file, window_group, - WINDOW_POSITION, &length, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_POSITION, error->message); - g_error_free(error); - error = NULL; - } - else if (length != 2) - { - g_warning("invalid number of values for group %s key %s", - window_group, WINDOW_POSITION); - } - else if ((pos[0] + (geom ? geom[0] : 0) < 0) || - (pos[0] > gdk_screen_width()) || - (pos[1] + (geom ? geom[1] : 0) < 0) || - (pos[1] > gdk_screen_height())) - { -// g_debug("position %dx%d, size%dx%d is offscreen; will not move", -// pos[0], pos[1], geom[0], geom[1]); - } - else - { - gtk_window_move(GTK_WINDOW(window), pos[0], pos[1]); - DEBUG("window (%p) position %dx%d", window, pos[0], pos[1]); - } - if (geom) - { - g_free(geom); - } - if (pos) - { - g_free(pos); - } - - max = g_key_file_get_boolean(data->key_file, window_group, - WINDOW_MAXIMIZED, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_MAXIMIZED, error->message); - g_error_free(error); - error = NULL; - } - else if (max) - { - gtk_window_maximize(GTK_WINDOW(window)); - } - - /* Common view menu items */ - action = gnc_main_window_find_action(window, "ViewToolbarAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - desired_visibility = g_key_file_get_boolean(data->key_file, window_group, - TOOLBAR_VISIBLE, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, TOOLBAR_VISIBLE, error->message); - g_error_free(error); - error = NULL; - } - else if (visible != desired_visibility) - { - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), desired_visibility); - } - - action = gnc_main_window_find_action(window, "ViewSummaryAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - desired_visibility = g_key_file_get_boolean(data->key_file, window_group, - SUMMARYBAR_VISIBLE, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, TOOLBAR_VISIBLE, error->message); - g_error_free(error); - error = NULL; - } - else if (visible != desired_visibility) - { - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), desired_visibility); - } - - action = gnc_main_window_find_action(window, "ViewStatusbarAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - desired_visibility = g_key_file_get_boolean(data->key_file, window_group, - STATUSBAR_VISIBLE, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, TOOLBAR_VISIBLE, error->message); - g_error_free(error); - error = NULL; - } - else if (visible != desired_visibility) - { - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), desired_visibility); - } - - /* Now populate the window with pages. */ - for (i = 0; i < page_count; i++) - { - data->page_offset = page_start; - data->page_num = i; - gnc_main_window_restore_page(window, data); - - /* give the page a chance to display */ - while (gtk_events_pending ()) - gtk_main_iteration (); - } - - /* Restore page ordering within the notebook. Use +1 notation so the - * numbers in the page order match the page sections, at least for - * the one window case. */ - order = g_key_file_get_integer_list(data->key_file, window_group, - WINDOW_PAGEORDER, &length, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - window_group, WINDOW_PAGEORDER, error->message); - g_error_free(error); - error = NULL; - } - else if (length != page_count) - { - g_warning("%s key %s length %" G_GSIZE_FORMAT " differs from window page count %d", - window_group, WINDOW_PAGEORDER, length, page_count); - } - else - { - /* Dump any list that might exist */ - g_list_free(priv->usage_order); - priv->usage_order = NULL; - /* Now rebuild the list from the key file. */ - for (i = 0; i < length; i++) - { - gpointer page = g_list_nth_data(priv->installed_pages, order[i] - 1); - if (page) - { - priv->usage_order = g_list_append(priv->usage_order, page); - } - } - gtk_notebook_set_current_page (GTK_NOTEBOOK(priv->notebook), - order[0] - 1); - } - if (order) - { - g_free(order); - } - - LEAVE("window %p", window); -cleanup: - if (error) - g_error_free(error); - g_free(window_group); -} - -void -gnc_main_window_restore_all_windows(const GKeyFile *keyfile) -{ - gint i, window_count; - GError *error = NULL; - GncMainWindowSaveData data; - GncMainWindow *window; - - /* We use the same struct for reading and for writing, so we cast - away the const. */ - data.key_file = (GKeyFile *) keyfile; - window_count = g_key_file_get_integer(data.key_file, STATE_FILE_TOP, - WINDOW_COUNT, &error); - if (error) - { - g_warning("error reading group %s key %s: %s", - STATE_FILE_TOP, WINDOW_COUNT, error->message); - g_error_free(error); - LEAVE("can't read count"); - return; - } - - /* Restore all state information on the open windows. Window - numbers in state file are 1-based. GList indices are 0-based. */ - gnc_set_busy_cursor (NULL, TRUE); - for (i = 0; i < window_count; i++) - { - data.window_num = i; - window = g_list_nth_data(active_windows, i); - gnc_main_window_restore_window(window, &data); - } - gnc_unset_busy_cursor (NULL); -} - -void -gnc_main_window_restore_default_state(void) -{ - GtkAction *action; - GncMainWindow *window; - - /* The default state should be to have an Account Tree page open - * in the window. */ - DEBUG("no saved state file"); - window = g_list_nth_data(active_windows, 0); - action = gnc_main_window_find_action(window, "ViewAccountTreeAction"); - gtk_action_activate(action); -} - -/** Save the state of a single page to a disk. This function handles - * all the common tasks such as saving the page type and name, and - * anything else that might be common to all pages. It then calls a - * page specific function to save the actual page. - * - * @param page The GncPluginPage whose state should be saved. - * - * @param data A data structure containing state about the - * window/page saving process. */ -static void -gnc_main_window_save_page (GncPluginPage *page, GncMainWindowSaveData *data) -{ - gchar *page_group; - const gchar *plugin_name, *page_name; - - ENTER("page %p, data %p (key file %p, window %d, page %d)", - page, data, data->key_file, data->window_num, data->page_num); - plugin_name = gnc_plugin_page_get_plugin_name(page); - page_name = gnc_plugin_page_get_page_name(page); - if (!plugin_name || !page_name) - { - LEAVE("not saving invalid page"); - return; - } - page_group = g_strdup_printf(PAGE_STRING, data->page_num++); - g_key_file_set_string(data->key_file, page_group, PAGE_TYPE, plugin_name); - g_key_file_set_string(data->key_file, page_group, PAGE_NAME, page_name); - - gnc_plugin_page_save_page(page, data->key_file, page_group); - g_free(page_group); - LEAVE(" "); -} - - -/** Saves all the pages in a single window to a disk. This function - * saves all the window specific attributes, then calls a helper - * function to save all the pages that are contained in the window. - * - * @param window The GncMainWindow whose pages should be saved. - * - * @param data A data structure containing state about the - * window/page saving process. */ -static void -gnc_main_window_save_window (GncMainWindow *window, GncMainWindowSaveData *data) -{ - GncMainWindowPrivate *priv; - GtkAction *action; - gint i, num_pages, coords[4], *order; - gboolean maximized, visible; - gchar *window_group; - - /* Setup */ - ENTER("window %p, data %p (key file %p, window %d)", - window, data, data->key_file, data->window_num); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - - /* Check for bogus window structures. */ - num_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)); - if (0 == num_pages) - { - LEAVE("empty window %p", window); - return; - } - - /* Save this window's notebook info */ - window_group = g_strdup_printf(WINDOW_STRING, data->window_num++); - g_key_file_set_integer(data->key_file, window_group, - WINDOW_PAGECOUNT, num_pages); - g_key_file_set_integer(data->key_file, window_group, - WINDOW_FIRSTPAGE, data->page_num); - - /* Save page ordering within the notebook. Use +1 notation so the - * numbers in the page order match the page sections, at least for - * the one window case. */ - order = g_malloc(sizeof(gint) * num_pages); - for (i = 0; i < num_pages; i++) - { - gpointer page = g_list_nth_data(priv->usage_order, i); - order[i] = g_list_index(priv->installed_pages, page) + 1; - } - g_key_file_set_integer_list(data->key_file, window_group, - WINDOW_PAGEORDER, order, num_pages); - g_free(order); - - /* Save the window coordinates, etc. */ - gtk_window_get_position(GTK_WINDOW(window), &coords[0], &coords[1]); - gtk_window_get_size(GTK_WINDOW(window), &coords[2], &coords[3]); - maximized = (gdk_window_get_state((GTK_WIDGET(window))->window) - & GDK_WINDOW_STATE_MAXIMIZED) != 0; - g_key_file_set_integer_list(data->key_file, window_group, - WINDOW_POSITION, &coords[0], 2); - g_key_file_set_integer_list(data->key_file, window_group, - WINDOW_GEOMETRY, &coords[2], 2); - g_key_file_set_boolean(data->key_file, window_group, - WINDOW_MAXIMIZED, maximized); - DEBUG("window (%p) position %dx%d, size %dx%d, %s", window, coords[0], coords[1], - coords[2], coords[3], - maximized ? "maximized" : "not maximized"); - - /* Common view menu items */ - action = gnc_main_window_find_action(window, "ViewToolbarAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - g_key_file_set_boolean(data->key_file, window_group, - TOOLBAR_VISIBLE, visible); - action = gnc_main_window_find_action(window, "ViewSummaryAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - g_key_file_set_boolean(data->key_file, window_group, - SUMMARYBAR_VISIBLE, visible); - action = gnc_main_window_find_action(window, "ViewStatusbarAction"); - visible = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); - g_key_file_set_boolean(data->key_file, window_group, - STATUSBAR_VISIBLE, visible); - - /* Save individual pages in this window */ - g_list_foreach(priv->installed_pages, (GFunc)gnc_main_window_save_page, data); - - g_free(window_group); - LEAVE("window %p", window); -} - -void -gnc_main_window_save_all_windows(GKeyFile *keyfile) -{ - GncMainWindowSaveData data; - - /* Set up the iterator data structures */ - data.key_file = keyfile; - data.window_num = 1; - data.page_num = 1; - - g_key_file_set_integer(data.key_file, - STATE_FILE_TOP, WINDOW_COUNT, - g_list_length(active_windows)); - /* Dump all state information on the open windows */ - g_list_foreach(active_windows, (GFunc)gnc_main_window_save_window, &data); -} - - -gboolean -gnc_main_window_finish_pending (GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GList *item; - - g_return_val_if_fail(GNC_IS_MAIN_WINDOW(window), TRUE); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - for (item = priv->installed_pages; item; item = g_list_next(item)) - { - if (!gnc_plugin_page_finish_pending(item->data)) - { - return FALSE; - } - } - return TRUE; -} - - -gboolean -gnc_main_window_all_finish_pending (void) -{ - const GList *windows, *item; - - windows = gnc_gobject_tracking_get_list(GNC_MAIN_WINDOW_NAME); - for (item = windows; item; item = g_list_next(item)) - { - if (!gnc_main_window_finish_pending(item->data)) - { - return FALSE; - } - } - return TRUE; -} - - -/** See if the page already exists. For each open window, look - * through the list of pages installed in that window and see if the - * specified page is there. - * - * @internal - * - * @param page The page to search for. - * - * @return TRUE if the page is present in the window, FALSE otherwise. - */ -static gboolean -gnc_main_window_page_exists (GncPluginPage *page) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GList *walker; - - for (walker = active_windows; walker; walker = g_list_next(walker)) - { - window = walker->data; - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (g_list_find(priv->installed_pages, page)) - { - return TRUE; - } - } - return FALSE; -} - - -/** This function prompts the user to save the file with a dialog that - * follows the HIG guidelines. - * - * @internal - * - * @returns This function returns TRUE if the user clicked the Cancel - * button. It returns FALSE if the closing of the window should - * continue. - */ -static gboolean -gnc_main_window_prompt_for_save (GtkWidget *window) -{ - QofSession *session; - QofBook *book; - GtkWidget *dialog; - gint response; - const gchar *filename, *tmp; - const gchar *title = _("Save changes to file %s before closing?"); - /* This should be the same message as in gnc-file.c */ - const gchar *message_mins = - _("If you don't save, changes from the past %d minutes will be discarded."); - const gchar *message_hours = - _("If you don't save, changes from the past %d hours and %d minutes will be discarded."); - const gchar *message_days = - _("If you don't save, changes from the past %d days and %d hours will be discarded."); - time_t oldest_change; - gint minutes, hours, days; - - session = gnc_get_current_session(); - book = qof_session_get_book(session); - filename = qof_session_get_url(session); - if (filename == NULL) - filename = _(""); - if ((tmp = strrchr(filename, '/')) != NULL) - filename = tmp + 1; - - /* Remove any pending auto-save timeouts */ - gnc_autosave_remove_timer(book); - - dialog = gtk_message_dialog_new(GTK_WINDOW(window), - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - title, - filename); - oldest_change = qof_book_get_dirty_time(book); - minutes = (time(NULL) - oldest_change) / 60 + 1; - hours = minutes / 60; - minutes = minutes % 60; - days = hours / 24; - hours = hours % 24; - if (days > 0) - { - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), - message_days, days, hours); - } - else if (hours > 0) - { - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), - message_hours, hours, minutes); - } - else - { - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), - message_mins, minutes); - } - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - _("Close _Without Saving"), GTK_RESPONSE_CLOSE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_APPLY, - NULL); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy(dialog); - - switch (response) - { - case GTK_RESPONSE_APPLY: - gnc_file_save(); - return FALSE; - - case GTK_RESPONSE_CLOSE: - qof_book_mark_saved(book); - return FALSE; - - default: - return TRUE; - } -} - - -static void -gnc_main_window_add_plugin (gpointer plugin, - gpointer window) -{ - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (GNC_IS_PLUGIN (plugin)); - - ENTER(" "); - gnc_plugin_add_to_window (GNC_PLUGIN (plugin), - GNC_MAIN_WINDOW (window), - window_type); - LEAVE(" "); -} - -static void -gnc_main_window_remove_plugin (gpointer plugin, - gpointer window) -{ - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (GNC_IS_PLUGIN (plugin)); - - ENTER(" "); - gnc_plugin_remove_from_window (GNC_PLUGIN (plugin), - GNC_MAIN_WINDOW (window), - window_type); - LEAVE(" "); -} - - -static gboolean -gnc_main_window_timed_quit (gpointer dummy) -{ - if (gnc_file_save_in_progress()) - return TRUE; - - gnc_shutdown (0); - return FALSE; -} - -static gboolean -gnc_main_window_quit(GncMainWindow *window) -{ - QofSession *session; - gboolean needs_save, do_shutdown; - - session = gnc_get_current_session(); - needs_save = qof_book_not_saved(qof_session_get_book(session)) && - !gnc_file_save_in_progress(); - do_shutdown = !needs_save || - (needs_save && !gnc_main_window_prompt_for_save(GTK_WIDGET(window))); - - if (do_shutdown) - { - g_timeout_add(250, gnc_main_window_timed_quit, NULL); - return TRUE; - } - return FALSE; -} - -static gboolean -gnc_main_window_delete_event (GtkWidget *window, - GdkEvent *event, - gpointer user_data) -{ - static gboolean already_dead = FALSE; - - if (already_dead) - return TRUE; - - if (!gnc_main_window_finish_pending(GNC_MAIN_WINDOW(window))) - { - /* Don't close the window. */ - return TRUE; - } - - if (g_list_length(active_windows) > 1) - return FALSE; - - already_dead = gnc_main_window_quit(GNC_MAIN_WINDOW(window)); - return TRUE; -} - - -/** This function handles any event notifications from the engine. - * The only event it currently cares about is the deletion of a book. - * When a book is deleted, it runs through all installed pages - * looking for pages that reference the just (about to be?) deleted - * book. It closes any page it finds so there are no dangling - * references to the book. - * - * @internal - * - * @param entity The guid the item being added, deleted, etc. - * - * @param type The type of the item being added, deleted, etc. This - * function only cares about a type of GNC_ID_BOOK. - * - * @param event_type The type of the event. This function only cares - * about an event type of QOF_EVENT_DESTROY. - * - * @param user_data A pointer to the window data structure. - */ -static void -gnc_main_window_event_handler (QofInstance *entity, QofEventId event_type, - gpointer user_data, gpointer event_data) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GncPluginPage *page; - GList *item, *next; - - /* hard failures */ - g_return_if_fail(GNC_IS_MAIN_WINDOW(user_data)); - - /* soft failures */ - if (!QOF_CHECK_TYPE(entity, QOF_ID_BOOK)) - return; - if (event_type != QOF_EVENT_DESTROY) - return; - - ENTER("entity %p, event %d, window %p, event data %p", - entity, event_type, user_data, event_data); - window = GNC_MAIN_WINDOW(user_data); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - - /* This is not a typical list iteration. We're removing while - * we iterate, so we have to cache the 'next' pointer before - * executing any code in the loop. */ - for (item = priv->installed_pages; item; item = next) - { - next = g_list_next(item); - page = GNC_PLUGIN_PAGE(item->data); - if (gnc_plugin_page_has_book (page, (QofBook *)entity)) - gnc_main_window_close_page (page); - } - LEAVE(" "); -} - - -/** Generate a title for this window based upon the Gnome Human - * Interface Guidelines, v2.0. This title will be used as both the - * window title and the title of the "Window" menu item associated - * with the window. - * - * As a side-effect, the save action is set sensitive iff the book - * is dirty. - * - * @param window The window whose title should be generated. - * - * @return The title for the window. It is the callers - * responsibility to free this string. - * - * @internal - */ -static gchar * -gnc_main_window_generate_title (GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - QofBook *book; - gchar *filename = NULL; - const gchar *book_id = NULL; - const gchar *dirty = ""; - gchar *title; - GtkAction* action; - - /* The save action is sensitive if the book is dirty */ - action = gnc_main_window_find_action (window, "FileSaveAction"); - if (action != NULL) - { - gtk_action_set_sensitive(action, FALSE); - } - if (gnc_current_session_exist()) - { - book_id = qof_session_get_url (gnc_get_current_session ()); - book = gnc_get_current_book(); - if (qof_instance_is_dirty(QOF_INSTANCE(book))) - { - dirty = "*"; - if (action != NULL) - { - gtk_action_set_sensitive(action, TRUE); - } - } - } - - if (!book_id) - filename = g_strdup(_("Unsaved Book")); - else - { - if ( gnc_uri_is_file_uri ( book_id ) ) - { - /* The filename is a true file. - * The Gnome HIG 2.0 recommends only the file name (no path) be used. (p15) */ - gchar *path = gnc_uri_get_path ( book_id ); - filename = g_path_get_basename ( path ); - g_free ( path ); - } - else - { - /* The filename is composed of database connection parameters. - * For this we will show access_method://username@database[:port] */ - filename = gnc_uri_normalize_uri (book_id, FALSE); - } - } - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page = priv->current_page; - if (page) - { - /* The Gnome HIG 2.0 recommends the application name not be used. (p16) - * but several developers prefer to use it anyway. */ - title = g_strdup_printf("%s%s - %s - GnuCash", dirty, filename, - gnc_plugin_page_get_page_name(page)); - } - else - { - title = g_strdup_printf("%s%s - GnuCash", dirty, filename); - } - g_free( filename ); - - return title; -} - - -/** Update the title bar on the specified window. This routine uses - * the gnc_main_window_generate_title() function to create the title. - * It is called whenever the user switched pages in a window, as the - * title includes the name of the current page. - * - * @param window The window whose title should be updated. - * - * @internal - */ -static void -gnc_main_window_update_title (GncMainWindow *window) -{ - gchar *title; - - title = gnc_main_window_generate_title(window); - gtk_window_set_title(GTK_WINDOW(window), title); - g_free(title); -} - -static void -gnc_main_window_update_all_titles (void) -{ - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_title, - NULL); -} - -static void -gnc_main_window_book_dirty_cb (QofBook *book, - gboolean dirty, - gpointer user_data) -{ - gnc_main_window_update_all_titles(); - - /* Auto-save feature */ - gnc_autosave_dirty_handler(book, dirty); -} - -static void -gnc_main_window_attach_to_book (QofSession *session) -{ - QofBook *book; - - g_return_if_fail(session); - - book = qof_session_get_book(session); - qof_book_set_dirty_cb(book, gnc_main_window_book_dirty_cb, NULL); - gnc_main_window_update_all_titles(); -#ifndef MAC_INTEGRATION - gnc_main_window_update_all_menu_items(); -#endif -} - - -/** This data structure is used to describe the requested state of a - * GtkRadioAction, and us used to pass data among several - * functions. */ -struct menu_update -{ - /** The name of the GtkRadioAction to be updated. */ - gchar *action_name; - - /** The new label for this GtkRadioAction. */ - gchar *label; - - /** Whether or not the GtkRadioAction should be visible. */ - gboolean visible; -}; - - -/** Update the label on the specified GtkRadioAction in the specified - * window. This action is displayed as a menu item in the "Windows" - * menu. This function will end up being called whenever the front - * page is changed in any window, or whenever a window is added or - * deleted. - * - * @param window The window whose menu item should be updated. - * - * @param data A data structure containing the name of the - * GtkRadioAction, and describing the new state for this action. - * - * @internal - */ -static void -gnc_main_window_update_one_menu_action (GncMainWindow *window, - struct menu_update *data) -{ - GncMainWindowPrivate *priv; - GtkAction* action; - - ENTER("window %p, action %s, label %s, visible %d", window, - data->action_name, data->label, data->visible); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - action = gtk_action_group_get_action(priv->action_group, data->action_name); - if (action) - g_object_set(G_OBJECT(action), - "label", data->label, - "visible", data->visible, - (char *)NULL); -#ifdef MAC_INTEGRATION - { - GtkOSXApplication *theApp = - g_object_new(GTK_TYPE_OSX_APPLICATION, NULL); - gtk_osxapplication_sync_menubar(theApp); - } -#endif - LEAVE(" "); -} - - -/** Update the window selection GtkRadioAction for a specific window. - * This is fairly simple since the windows are listed in the same - * order that they appear in the active_windows list, so the index - * from the window list is used to generate the name of the action. - * If the code is ever changed to allow more than ten open windows in - * the menu, then the actions in the menu will need to be dynamically - * generated/deleted and it gets harder. - * - * @param window The window whose menu item should be updated. - * - * @internal - */ -static void -gnc_main_window_update_radio_button (GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GtkAction *action, *first_action; - GSList *action_list; - gchar *action_name; - gint index; - - ENTER("window %p", window); - - /* Show the new entry in all windows. */ - index = g_list_index(active_windows, window); - if (index >= n_radio_entries) - { - LEAVE("window %d, only %d actions", index, n_radio_entries); - return; - } - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - action_name = g_strdup_printf("Window%dAction", index); - action = gtk_action_group_get_action(priv->action_group, action_name); - - /* Block the signal so as not to affect window ordering (top to - * bottom) on the screen */ - action_list = gtk_radio_action_get_group(GTK_RADIO_ACTION(action)); - if (action_list) - { - first_action = g_slist_last(action_list)->data; - g_signal_handlers_block_by_func(G_OBJECT(first_action), - G_CALLBACK(gnc_main_window_cmd_window_raise), - window); - DEBUG("blocked signal on %p, set %p active, window %p", first_action, - action, window); - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); - g_signal_handlers_unblock_by_func(G_OBJECT(first_action), - G_CALLBACK(gnc_main_window_cmd_window_raise), - window); - } - g_free(action_name); - LEAVE(" "); -} - - -/** In every window that the user has open, update the "Window" menu - * item that points to the specified window. This keeps the "Window" - * menu items consistent across all open windows. (These items - * cannot be shared because of the way the GtkUIManager code works.) - * - * This function is called whenever the user switches pages in a - * window, or whenever a window is added or deleted. - * - * @param window The window whose menu item should be updated in all - * open windows. - * - * @internal - */ -static void -gnc_main_window_update_menu_item (GncMainWindow *window) -{ - struct menu_update data; - gchar **strings, *title, *expanded; - gint index; - - ENTER("window %p", window); - index = g_list_index(active_windows, window); - if (index > n_radio_entries) - { - LEAVE("skip window %d (only %d entries)", index, n_radio_entries); - return; - } - - /* Figure out the label name. Add the accelerator if possible. */ - title = gnc_main_window_generate_title(window); - strings = g_strsplit(title, "_", 0); - g_free(title); - expanded = g_strjoinv("__", strings); - if (index < 10) - { - data.label = g_strdup_printf("_%d %s", (index + 1) % 10, expanded); - g_free(expanded); - } - else - { - data.label = expanded; - } - g_strfreev(strings); - - data.visible = TRUE; - data.action_name = g_strdup_printf("Window%dAction", index); - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_one_menu_action, - &data); - g_free(data.action_name); - g_free(data.label); - - LEAVE(" "); -} - -/** Update all menu entries for all window menu items in all windows. - * This function is called whenever a window is added or deleted. - * The worst case scenario is where the user has deleted the first - * window, so every single visible item needs to be updated. - * - * @internal - */ -static void -gnc_main_window_update_all_menu_items (void) -{ - struct menu_update data; - gchar *label; - gint i; - - ENTER(""); -#ifndef MAC_INTEGRATION - /* First update the entries for all existing windows */ - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_menu_item, - NULL); - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_radio_button, - NULL); - - /* Now hide any entries that aren't being used. */ - data.visible = FALSE; - for (i = g_list_length(active_windows); i < n_radio_entries; i++) - { - data.action_name = g_strdup_printf("Window%dAction", i); - label = g_strdup_printf("Window _%d", (i - 1) % 10); - data.label = gettext(label); - - g_list_foreach(active_windows, - (GFunc)gnc_main_window_update_one_menu_action, - &data); - - g_free(data.action_name); - g_free(label); - } -#endif - LEAVE(" "); -} - - -/** Show/hide the close box on the tab of a notebook page. This - * function first checks to see if the specified page has a close - * box, and if so, sets its visibility to the requested state. - * - * @internal - * - * @param page The GncPluginPage whose notebook tab should be updated. - * - * @param new_value A pointer to the boolean that indicates whether - * or not the close button should be visible. - */ -static void -gnc_main_window_update_tab_close_one_page (GncPluginPage *page, - gpointer user_data) -{ - gboolean *new_value = user_data; - GtkWidget * close_button; - - ENTER("page %p, visible %d", page, *new_value); - close_button = g_object_get_data(G_OBJECT (page), PLUGIN_PAGE_CLOSE_BUTTON); - if (!close_button) - { - LEAVE("no close button"); - return; - } - - if (*new_value) - gtk_widget_show (close_button); - else - gtk_widget_hide (close_button); - LEAVE(" "); -} - - -/** Show/hide the close box on all pages in all windows. This function - * calls gnc_main_window_update_tab_close() for each plugin page in the - * application. - * - * @internal - * - * @param entry A pointer to the GConfEntry which describes the new - * state of whether close buttons should be visible on notebook tabs. - * - * @param user_data Unused. - */ -static void -gnc_main_window_update_tab_close (GConfEntry *entry, gpointer user_data) -{ - gboolean new_value; - - ENTER(" "); - new_value = gconf_value_get_bool(entry->value); - gnc_main_window_foreach_page( - gnc_main_window_update_tab_close_one_page, - &new_value); - LEAVE(" "); -} - - -/** Update the width of the label in the tab of a notebook page. This - * function adjusts both the width and the ellipsize mode so that the tab - * label looks correct. The special check for a zero value handles the - * case where a user hasn't set a tab width and the gconf default isn't - * detected. - * - * @internal - * - * @param page The GncPluginPage whose notebook tab should be updated. - * - * @param new_value The new width of the label in the tab. - */ -static void -gnc_main_window_update_tab_width_one_page (GncPluginPage *page, - gpointer user_data) -{ - gint *new_value = user_data; - GtkWidget *label; - - ENTER("page %p, visible %d", page, *new_value); - label = g_object_get_data(G_OBJECT (page), PLUGIN_PAGE_TAB_LABEL); - if (!label) - { - LEAVE("no label"); - return; - } - - if (*new_value != 0) - { - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE); - gtk_label_set_max_width_chars(GTK_LABEL(label), *new_value); - } - else - { - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE); - gtk_label_set_max_width_chars(GTK_LABEL(label), 100); - } - LEAVE(" "); -} - - -/** Update the tab label width in all pages in all windows. This function - * calls gnc_main_window_update_tab_width() for each plugin page in the - * application. - * - * @internal - * - * @param entry A pointer to the GConfEntry which describes the new - * size of the tab label width. - * - * @param user_data Unused. - */ -static void -gnc_main_window_update_tab_width (GConfEntry *entry, gpointer user_data) -{ - gint new_value; - - ENTER(" "); - new_value = gconf_value_get_float(entry->value); - gnc_main_window_foreach_page( - gnc_main_window_update_tab_width_one_page, - &new_value); - LEAVE(" "); -} - - -/************************************************************ - * Tab Label Implementation * - ************************************************************/ -static gboolean -main_window_find_tab_items (GncMainWindow *window, - GncPluginPage *page, - GtkWidget **label_p, - GtkWidget **entry_p) -{ - GncMainWindowPrivate *priv; - GtkWidget *tab_hbox, *widget, *event_box; - GList *children, *tmp; - - ENTER("window %p, page %p, label_p %p, entry_p %p", - window, page, label_p, entry_p); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - *label_p = *entry_p = NULL; - - if (!page->notebook_page) - { - LEAVE("invalid notebook_page"); - return FALSE; - } - - event_box = gtk_notebook_get_tab_label(GTK_NOTEBOOK(priv->notebook), - page->notebook_page); - - tab_hbox = gtk_bin_get_child(GTK_BIN(event_box)); - - children = gtk_container_get_children(GTK_CONTAINER(tab_hbox)); - for (tmp = children; tmp; tmp = g_list_next(tmp)) - { - widget = tmp->data; - if (GTK_IS_LABEL(widget)) - { - *label_p = widget; - } - else if (GTK_IS_ENTRY(widget)) - { - *entry_p = widget; - } - } - g_list_free(children); - - LEAVE("label %p, entry %p", *label_p, *entry_p); - return (*label_p && *entry_p); -} - -static gboolean -main_window_find_tab_event (GncMainWindow *window, - GncPluginPage *page, - GtkWidget **event_p) -{ - GncMainWindowPrivate *priv; - GtkWidget *event_box; - - ENTER("window %p, page %p, event %p", - window, page, event_p); - *event_p = NULL; - - if (!page->notebook_page) - { - LEAVE("invalid notebook_page"); - return FALSE; - } - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - event_box = gtk_notebook_get_tab_label(GTK_NOTEBOOK(priv->notebook), - page->notebook_page); - if (GTK_IS_EVENT_BOX(event_box)) - { - *event_p = event_box; - LEAVE("event %p", *event_p); - return (TRUE); - } - - LEAVE("event %p", *event_p); - return (FALSE); -} - -void -main_window_update_page_name (GncPluginPage *page, - const gchar *name_in) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GtkWidget *label, *entry, *event_box; - gchar *name, *old_page_name, *old_page_long_name; - - ENTER(" "); - - if ((name_in == NULL) || (*name_in == '\0')) - { - LEAVE("no string"); - return; - } - name = g_strstrip(g_strdup(name_in)); - - /* Optimization, if the name hasn't changed, don't update X. */ - if (*name == '\0' || 0 == strcmp(name, gnc_plugin_page_get_page_name(page))) - { - g_free(name); - LEAVE("empty string or name unchanged"); - return; - } - - old_page_name = g_strdup( gnc_plugin_page_get_page_name(page)); - old_page_long_name = g_strdup( gnc_plugin_page_get_page_long_name(page)); - - /* Update the plugin */ - gnc_plugin_page_set_page_name(page, name); - - /* Update the notebook tab */ - window = GNC_MAIN_WINDOW(page->window); - if (!window) - { - LEAVE("no window widget available"); - return; - } - - if (main_window_find_tab_items(window, page, &label, &entry)) - gtk_label_set_text(GTK_LABEL(label), name); - - /* Update Tooltip on notebook Tab */ - if (old_page_long_name && old_page_name - && g_strrstr(old_page_long_name, old_page_name) != NULL) - { - gchar *new_page_long_name; - gint string_position; - - string_position = strlen(old_page_long_name) - strlen(old_page_name); - new_page_long_name = g_strconcat(g_strndup(old_page_long_name, string_position), name, NULL); - - gnc_plugin_page_set_page_long_name(page, new_page_long_name); - - if (main_window_find_tab_event(window, page, &event_box)) - gtk_tooltips_set_tip(GTK_TOOLTIPS(tips), event_box, new_page_long_name, NULL); - - g_free(new_page_long_name); - } - - /* Update the notebook menu */ - if (page->notebook_page) - { - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - label = gtk_notebook_get_menu_label (GTK_NOTEBOOK(priv->notebook), - page->notebook_page); - gtk_label_set_text(GTK_LABEL(label), name); - } - - /* Force an update of the window title */ - gnc_main_window_update_title(window); - g_free(old_page_long_name); - g_free(old_page_name); - g_free(name); - LEAVE("done"); -} - - -void -main_window_update_page_color (GncPluginPage *page, - const gchar *color_in) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GtkWidget *event_box; - GdkColor tab_color; - gchar *color_string; - - - ENTER(" "); - - if ((color_in == NULL) || (*color_in == '\0')) - { - LEAVE("no string"); - return; - } - color_string = g_strstrip(g_strdup(color_in)); - - /* Optimization, if the color hasn't changed, don't update. */ - if (*color_string == '\0' || 0 == safe_strcmp(color_string, gnc_plugin_page_get_page_color(page))) - { - g_free(color_string); - LEAVE("empty string or color unchanged"); - return; - } - - /* Update the plugin */ - window = GNC_MAIN_WINDOW(page->window); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - gnc_plugin_page_set_page_color(page, color_string); - - /* Update the notebook tab */ - main_window_find_tab_event(window, page, &event_box); - - if (gdk_color_parse(color_string, &tab_color)) - { - gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, &tab_color); - gtk_widget_modify_bg(event_box, GTK_STATE_ACTIVE, &tab_color); - } - else - { - gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_bg(event_box, GTK_STATE_ACTIVE, NULL); - } - g_free(color_string); - LEAVE("done"); -} - - -static void -gnc_main_window_tab_entry_activate (GtkWidget *entry, - GncPluginPage *page) -{ - GtkWidget *label, *entry2; - - g_return_if_fail(GTK_IS_ENTRY(entry)); - g_return_if_fail(GNC_IS_PLUGIN_PAGE(page)); - - ENTER(""); - if (!main_window_find_tab_items(GNC_MAIN_WINDOW(page->window), - page, &label, &entry2)) - { - LEAVE("can't find required widgets"); - return; - } - - main_window_update_page_name(page, gtk_entry_get_text(GTK_ENTRY(entry))); - - gtk_widget_hide(entry); - gtk_widget_show(label); - LEAVE(""); -} - - -static gboolean -gnc_main_window_tab_entry_editing_done (GtkWidget *entry, - GncPluginPage *page) -{ - ENTER(""); - gnc_main_window_tab_entry_activate(entry, page); - LEAVE(""); - return FALSE; -} - -static gboolean -gnc_main_window_tab_entry_focus_out_event (GtkWidget *entry, - GdkEvent *event, - GncPluginPage *page) -{ - ENTER(""); - gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(entry)); - LEAVE(""); - return FALSE; -} - -static gboolean -gnc_main_window_tab_entry_key_press_event (GtkWidget *entry, - GdkEventKey *event, - GncPluginPage *page) -{ - if (event->keyval == GDK_Escape) - { - GtkWidget *label, *entry2; - - g_return_val_if_fail(GTK_IS_ENTRY(entry), FALSE); - g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE); - - ENTER(""); - if (!main_window_find_tab_items(GNC_MAIN_WINDOW(page->window), - page, &label, &entry2)) - { - LEAVE("can't find required widgets"); - return FALSE; - } - - gtk_entry_set_text(GTK_ENTRY(entry), gtk_label_get_text(GTK_LABEL(label))); - gtk_widget_hide(entry); - gtk_widget_show(label); - LEAVE(""); - } - return FALSE; -} - -/************************************************************ - * Widget Implementation * - ************************************************************/ - -/* Get the type of a gnc main window. - */ -GType -gnc_main_window_get_type (void) -{ - static GType gnc_main_window_type = 0; - - if (gnc_main_window_type == 0) - { - static const GTypeInfo our_info = - { - sizeof (GncMainWindowClass), - NULL, - NULL, - (GClassInitFunc) gnc_main_window_class_init, - NULL, - NULL, - sizeof (GncMainWindow), - 0, - (GInstanceInitFunc) gnc_main_window_init - }; - - static const GInterfaceInfo plugin_info = - { - (GInterfaceInitFunc) gnc_window_main_window_init, - NULL, - NULL - }; - - gnc_main_window_type = g_type_register_static (GTK_TYPE_WINDOW, - GNC_MAIN_WINDOW_NAME, - &our_info, 0); - g_type_add_interface_static (gnc_main_window_type, - GNC_TYPE_WINDOW, - &plugin_info); - } - - return gnc_main_window_type; -} - - -/** Initialize the class for a new gnucash main window. This will set - * up any function pointers that override functions in the parent - * class, and also initialize the signals that this class of widget - * can generate. - * - * @param klass The new class structure created by the object system. - */ -static void -gnc_main_window_class_init (GncMainWindowClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS(klass); - - parent_class = g_type_class_peek_parent (klass); - - window_type = g_quark_from_static_string ("gnc-main-window"); - - object_class->finalize = gnc_main_window_finalize; - - /* GtkObject signals */ - gtkobject_class->destroy = gnc_main_window_destroy; - - g_type_class_add_private(klass, sizeof(GncMainWindowPrivate)); - - /** - * GncMainWindow::page_added: - * @param window: the #GncMainWindow - * @param page: the #GncPluginPage - * - * The "page_added" signal is emitted when a new page is added - * to the notebook of a GncMainWindow. This can be used to - * attach a signal from the page so that menu actions can be - * adjusted based upon events that occur within the page - * (e.g. an account is selected.) - */ - main_window_signals[PAGE_ADDED] = - g_signal_new ("page_added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GncMainWindowClass, page_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - /** - * GncMainWindow::page_changed: - * @param window: the #GncMainWindow - * @param page: the #GncPluginPage - * - * The "page_changed" signal is emitted when a new page is - * selected in the notebook of a GncMainWindow. This can be - * used to to adjust menu actions based upon which page is - * currently displayed in a window. - */ - main_window_signals[PAGE_CHANGED] = - g_signal_new ("page_changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GncMainWindowClass, page_changed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - gnc_gconf_general_register_cb (KEY_SHOW_CLOSE_BUTTON, - gnc_main_window_update_tab_close, - NULL); - gnc_gconf_general_register_cb (KEY_TAB_WIDTH, - gnc_main_window_update_tab_width, - NULL); - gnc_hook_add_dangler(HOOK_BOOK_SAVED, - (GFunc)gnc_main_window_update_all_titles, NULL); - gnc_hook_add_dangler(HOOK_BOOK_OPENED, - (GFunc)gnc_main_window_attach_to_book, NULL); - - tips = gtk_tooltips_new(); -} - - -/** Initialize a new instance of a gnucash main window. This function - * initializes the object private storage space. It also adds the - * new object to a list (for memory tracking purposes). - * - * @param window The new object instance created by the object system. - * - * @param klass A pointer to the class data structure for this - * object. */ -static void -gnc_main_window_init (GncMainWindow *window, - GncMainWindowClass *klass) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - priv->merged_actions_table = - g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - priv->event_handler_id = - qof_event_register_handler(gnc_main_window_event_handler, window); - - gnc_main_window_setup_window (window); - gnc_gobject_tracking_remember(G_OBJECT(window), - G_OBJECT_CLASS(klass)); -} - - -/** Finalize the GncMainWindow object. This function is called from - * the G_Object level to complete the destruction of the object. It - * should release any memory not previously released by the destroy - * function (i.e. the private data structure), then chain up to the - * parent's destroy function. - * - * @param object The object being destroyed. - * - * @internal - */ -static void -gnc_main_window_finalize (GObject *object) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNC_IS_MAIN_WINDOW (object)); - - window = GNC_MAIN_WINDOW (object); - priv = GNC_MAIN_WINDOW_GET_PRIVATE (window); - - if (active_windows == NULL) - { - /* Oops. User killed last window and we didn't catch it. */ - g_idle_add((GSourceFunc)gnc_shutdown, 0); - } - - gnc_gobject_tracking_forget(object); - G_OBJECT_CLASS (parent_class)->finalize (object); -} - - -static void -gnc_main_window_destroy (GtkObject *object) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GncPluginManager *manager; - GList *plugins; - - g_return_if_fail (object != NULL); - g_return_if_fail (GNC_IS_MAIN_WINDOW (object)); - - window = GNC_MAIN_WINDOW (object); - - active_windows = g_list_remove (active_windows, window); - - /* Do these things once */ - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->merged_actions_table) - { - - /* Close any pages in this window */ - while (priv->current_page) - gnc_main_window_close_page(priv->current_page); - - if (gnc_window_get_progressbar_window() == GNC_WINDOW(window)) - gnc_window_set_progressbar_window(NULL); - - /* Update the "Windows" menu in all other windows */ - gnc_main_window_update_all_menu_items(); - - gnc_gconf_remove_notification(G_OBJECT(window), DESKTOP_GNOME_INTERFACE, - GNC_MAIN_WINDOW_NAME); - gnc_gconf_remove_notification(G_OBJECT(window), GCONF_GENERAL, - GNC_MAIN_WINDOW_NAME); - - qof_event_unregister_handler(priv->event_handler_id); - priv->event_handler_id = 0; - - g_hash_table_destroy (priv->merged_actions_table); - priv->merged_actions_table = NULL; - - /* GncPluginManager stuff */ - manager = gnc_plugin_manager_get (); - plugins = gnc_plugin_manager_get_plugins (manager); - g_list_foreach (plugins, gnc_main_window_remove_plugin, window); - g_list_free (plugins); - } - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - - -/* Create a new gnc main window plugin. - */ -GncMainWindow * -gnc_main_window_new (void) -{ - GncMainWindow *window; - GtkWidget *old_window; - - window = g_object_new (GNC_TYPE_MAIN_WINDOW, NULL); - gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); - - old_window = gnc_ui_get_toplevel(); - if (old_window) - { - gint width, height; - gtk_window_get_size (GTK_WINDOW (old_window), &width, &height); - gtk_window_resize (GTK_WINDOW (window), width, height); - if ((gdk_window_get_state((GTK_WIDGET(old_window))->window) - & GDK_WINDOW_STATE_MAXIMIZED) != 0) - { - gtk_window_maximize (GTK_WINDOW (window)); - } - } - active_windows = g_list_append (active_windows, window); - gnc_main_window_update_title(window); - gnc_main_window_update_all_menu_items(); - - gnc_engine_add_commit_error_callback( gnc_main_window_engine_commit_error_callback, window ); - - return window; -} - -/************************************************************ - * Utility Functions * - ************************************************************/ - -static void -gnc_main_window_engine_commit_error_callback( gpointer data, - QofBackendError errcode ) -{ - GncMainWindow* window = GNC_MAIN_WINDOW(data); - GtkWidget* dialog; - const gchar *reason = _("Unable to save to database."); - if ( errcode == ERR_BACKEND_READONLY ) - reason = _("Unable to save to database: Book is marked read-only."); - dialog = gtk_message_dialog_new( GTK_WINDOW(window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "%s", - reason ); - gtk_dialog_run(GTK_DIALOG (dialog)); - gtk_widget_destroy(dialog); - -} - -/** Connect a GncPluginPage to the window. This function will insert - * the page in to the window's notebook and its list of active pages. - * It will also emit the "inserted" signal on the page, and the - * "add_page" signal on the window. - * - * @param window The window where the new page should be added. - * - * @param page The GncPluginPage that should be added to the window. - * The visible widget for this plugin must have already been created. - * - * @param tab_hbox The widget that should be added into the notebook - * tab for this page. Generally this is a GtkLabel, but could also - * be a GtkHBox containing an icon and a label. - * - * @param menu_label The widget that should be added into the - * notebook popup menu for this page. This should be a GtkLabel. - */ -static void -gnc_main_window_connect (GncMainWindow *window, - GncPluginPage *page, - GtkWidget *tab_hbox, - GtkWidget *menu_label) -{ - GncMainWindowPrivate *priv; - GtkNotebook *notebook; - - page->window = GTK_WIDGET(window); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - notebook = GTK_NOTEBOOK (priv->notebook); - priv->installed_pages = g_list_append (priv->installed_pages, page); - priv->usage_order = g_list_prepend (priv->usage_order, page); - gtk_notebook_append_page_menu (notebook, page->notebook_page, - tab_hbox, menu_label); - gtk_notebook_set_tab_reorderable (notebook, page->notebook_page, TRUE); - gnc_plugin_page_inserted (page); - gtk_notebook_set_current_page (notebook, -1); - if (GNC_PLUGIN_PAGE_GET_CLASS(page)->window_changed) - (GNC_PLUGIN_PAGE_GET_CLASS(page)->window_changed)(page, GTK_WIDGET(window)); - g_signal_emit (window, main_window_signals[PAGE_ADDED], 0, page); - - g_signal_connect(G_OBJECT(page->notebook_page), "popup-menu", - G_CALLBACK(gnc_main_window_popup_menu_cb), page); - g_signal_connect_after(G_OBJECT(page->notebook_page), "button-press-event", - G_CALLBACK(gnc_main_window_button_press_cb), page); -} - - -/** Disconnect a GncPluginPage page from the window. If this page is - * currently foremost in the window's notebook, its user interface - * actions will be disconnected and the page's summarybar widget (if - * any) will be removed. The page is then removed from the window's - * notebook and its list of active pages. - * - * @param window The window the page should be removed from. - * - * @param page The GncPluginPage that should be removed from the - * window. - * - * @internal - */ -static void -gnc_main_window_disconnect (GncMainWindow *window, - GncPluginPage *page) -{ - GncMainWindowPrivate *priv; - GtkNotebook *notebook; - GncPluginPage *new_page; - gint page_num; - - /* Disconnect the callbacks */ - g_signal_handlers_disconnect_by_func(G_OBJECT(page->notebook_page), - G_CALLBACK(gnc_main_window_popup_menu_cb), page); - g_signal_handlers_disconnect_by_func(G_OBJECT(page->notebook_page), - G_CALLBACK(gnc_main_window_button_press_cb), page); - - /* Disconnect the page and summarybar from the window */ - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->current_page == page) - { - gnc_plugin_page_unmerge_actions (page, window->ui_merge); - gnc_plugin_page_unselected (page); - priv->current_page = NULL; - } - - /* Remove it from the list of pages in the window */ - priv->installed_pages = g_list_remove (priv->installed_pages, page); - priv->usage_order = g_list_remove (priv->usage_order, page); - - /* Switch to the last recently used page */ - notebook = GTK_NOTEBOOK (priv->notebook); - if (gnc_gconf_get_bool(GCONF_GENERAL, KEY_TAB_NEXT_RECENT, NULL)) - { - new_page = g_list_nth_data (priv->usage_order, 0); - if (new_page) - { - page_num = gtk_notebook_page_num(notebook, new_page->notebook_page); - gtk_notebook_set_current_page(notebook, page_num); - } - } - - /* Remove the page from the notebook */ - page_num = gtk_notebook_page_num(notebook, page->notebook_page); - gtk_notebook_remove_page (notebook, page_num); - - if ( gtk_notebook_get_current_page(notebook) == -1) - { - /* Need to synthesize a page changed signal when the last - * page is removed. The notebook doesn't generate a signal - * for this, therefore the switch_page code in this file - * never gets called to generate this signal. */ - gnc_main_window_switch_page(notebook, NULL, -1, window); - //g_signal_emit (window, main_window_signals[PAGE_CHANGED], 0, NULL); - } - - gnc_plugin_page_removed (page); - - gtk_ui_manager_ensure_update (window->ui_merge); - gnc_window_set_status (GNC_WINDOW(window), page, NULL); -} - - -/************************************************************ - * * - ************************************************************/ - - -void -gnc_main_window_display_page (GncPluginPage *page) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GtkNotebook *notebook; - gint page_num; - - window = GNC_MAIN_WINDOW (page->window); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - notebook = GTK_NOTEBOOK (priv->notebook); - page_num = gtk_notebook_page_num(notebook, page->notebook_page); - gtk_notebook_set_current_page (notebook, page_num); - gtk_window_present(GTK_WINDOW(window)); -} - - -/* Display a data plugin page in a window. If the page already - * exists in any window, then that window will be brought to the - * front and the notebook switch to display the specified page. If - * the page is new then it will be added to the specified window. If - * the window is NULL, the new page will be added to the first - * window. - */ -void -gnc_main_window_open_page (GncMainWindow *window, - GncPluginPage *page) -{ - GncMainWindowPrivate *priv; - GtkWidget *tab_hbox; - GtkWidget *label, *entry, *event_box; - const gchar *icon, *text, *color_string; - GtkWidget *image; - GList *tmp; - gint width; - GdkColor tab_color; - - ENTER("window %p, page %p", window, page); - - if (window) - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (GNC_IS_PLUGIN_PAGE (page)); - g_return_if_fail (gnc_plugin_page_has_books(page)); - - if (gnc_main_window_page_exists(page)) - { - gnc_main_window_display_page(page); - return; - } - - /* Does the page want to be in a new window? */ - if (gnc_plugin_page_get_use_new_window(page)) - { - /* See if there's a blank window. If so, use that. */ - for (tmp = active_windows; tmp; tmp = g_list_next(tmp)) - { - window = GNC_MAIN_WINDOW(tmp->data); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->installed_pages == NULL) - { - break; - } - } - if (tmp == NULL) - window = gnc_main_window_new (); - gtk_widget_show(GTK_WIDGET(window)); - } - else if ((window == NULL) && active_windows) - { - window = active_windows->data; - } - - page->window = GTK_WIDGET(window); - page->notebook_page = gnc_plugin_page_create_widget (page); - g_object_set_data (G_OBJECT (page->notebook_page), - PLUGIN_PAGE_LABEL, page); - - /* - * The page tab. - */ - width = gnc_gconf_get_float(GCONF_GENERAL, KEY_TAB_WIDTH, NULL); - icon = GNC_PLUGIN_PAGE_GET_CLASS(page)->tab_icon; - label = gtk_label_new (gnc_plugin_page_get_page_name(page)); - if (width != 0) - { - gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_MIDDLE); - gtk_label_set_max_width_chars(GTK_LABEL(label), width); - } - gtk_widget_show (label); - - tab_hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (tab_hbox); - - if (icon != NULL) - { - image = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - gtk_box_pack_start (GTK_BOX (tab_hbox), image, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0); - } - else - gtk_box_pack_start (GTK_BOX (tab_hbox), label, TRUE, TRUE, 0); - - event_box = gtk_event_box_new(); - /* Note: this doesn't work properly on Windows with gtk+2.18.x (last - * with 2.18.7). Setting the eventbox visible with that version results - * in the tab's text being invisible. See bug #610675 for more on this. - */ - gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), TRUE); - gtk_widget_show(event_box); - gtk_container_add(GTK_CONTAINER(event_box), tab_hbox); - color_string = gnc_plugin_page_get_page_color(page); - if (color_string == NULL) color_string = ""; - if (gdk_color_parse(color_string, &tab_color)) - { - gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, &tab_color); - gtk_widget_modify_bg(event_box, GTK_STATE_ACTIVE, &tab_color); - } - else - { - gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_bg(event_box, GTK_STATE_ACTIVE, NULL); - } - - text = gnc_plugin_page_get_page_long_name(page); - if (text) - { - gtk_tooltips_set_tip(tips, event_box, text, NULL); - } - - entry = gtk_entry_new(); - gtk_widget_hide (entry); - gtk_box_pack_start (GTK_BOX (tab_hbox), entry, TRUE, TRUE, 0); - g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(gnc_main_window_tab_entry_activate), page); - g_signal_connect(G_OBJECT(entry), "focus-out-event", - G_CALLBACK(gnc_main_window_tab_entry_focus_out_event), - page); - g_signal_connect(G_OBJECT(entry), "key-press-event", - G_CALLBACK(gnc_main_window_tab_entry_key_press_event), - page); - g_signal_connect(G_OBJECT(entry), "editing-done", - G_CALLBACK(gnc_main_window_tab_entry_editing_done), - page); - - /* Add close button - Not for immutable pages */ - if (!g_object_get_data (G_OBJECT (page), PLUGIN_PAGE_IMMUTABLE)) - { - GtkWidget *close_image, *close_button; - GtkRequisition requisition; - - close_button = gtk_button_new(); - gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE); - close_image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); - gtk_widget_show(close_image); - gtk_widget_size_request(close_image, &requisition); - gtk_widget_set_size_request(close_button, requisition.width + 4, - requisition.height + 2); - gtk_button_set_alignment(GTK_BUTTON(close_button), 0.5, 0.5); - gtk_container_add(GTK_CONTAINER(close_button), close_image); - if (gnc_gconf_get_bool(GCONF_GENERAL, KEY_SHOW_CLOSE_BUTTON, NULL)) - gtk_widget_show (close_button); - else - gtk_widget_hide (close_button); - - g_signal_connect_swapped (G_OBJECT (close_button), "clicked", - G_CALLBACK(gnc_main_window_close_page), page); - - gtk_box_pack_start (GTK_BOX (tab_hbox), close_button, FALSE, FALSE, 0); - - g_object_set_data (G_OBJECT (page), PLUGIN_PAGE_CLOSE_BUTTON, close_button); - } - - /* - * The popup menu - */ - label = gtk_label_new (gnc_plugin_page_get_page_name(page)); - - /* - * Now install it all in the window. - */ - gnc_main_window_connect(window, page, event_box, label); - LEAVE(""); -} - - -/* Remove a data plugin page from a window and display the previous - * page. If the page removed was the last page in the window, and - * there is more than one window open, then the entire window will be - * destroyed. - */ -void -gnc_main_window_close_page (GncPluginPage *page) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - - if (!page || !page->notebook_page) - return; - - if (!gnc_plugin_page_finish_pending(page)) - return; - - if (!GNC_IS_MAIN_WINDOW (page->window)) - return; - - window = GNC_MAIN_WINDOW (page->window); - if (!window) - { - g_warning("Page is not in a window."); - return; - } - - gnc_main_window_disconnect(window, page); - gnc_plugin_page_destroy_widget (page); - g_object_unref(page); - - /* If this isn't the last window, go ahead and destroy the window. */ - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->installed_pages == NULL) - { - if (g_list_length(active_windows) > 1) - { - gtk_widget_destroy(GTK_WIDGET(window)); - } - } -} - - -/* Retrieve a pointer to the page that is currently at the front of - * the specified window. Any plugin that needs to manipulate its - * menus based upon the currently selected menu page should connect - * to the "page_changed" signal on a window. The callback function - * from that signal can then call this function to obtain a pointer - * to the current page. - */ -GncPluginPage * -gnc_main_window_get_current_page (GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - return priv->current_page; -} - - -/* Manually add a set of actions to the specified window. Plugins - * whose user interface is not hard coded (e.g. the menu-additions - * plugin) must create their actions at run time, then use this - * function to install them into the window. - */ -void -gnc_main_window_manual_merge_actions (GncMainWindow *window, - const gchar *group_name, - GtkActionGroup *group, - guint merge_id) -{ - GncMainWindowPrivate *priv; - MergedActionEntry *entry; - - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (group_name != NULL); - g_return_if_fail (GTK_IS_ACTION_GROUP(group)); - g_return_if_fail (merge_id > 0); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - entry = g_new0 (MergedActionEntry, 1); - entry->action_group = group; - entry->merge_id = merge_id; - gtk_ui_manager_ensure_update (window->ui_merge); - g_hash_table_insert (priv->merged_actions_table, g_strdup (group_name), entry); -} - - -/* Add a set of actions to the specified window. This function - * should not need to be called directly by plugin implementors. - * Correctly assigning values to the GncPluginClass fields during - * plugin initialization will cause this routine to be automatically - * called. - */ -void -gnc_main_window_merge_actions (GncMainWindow *window, - const gchar *group_name, - GtkActionEntry *actions, - guint n_actions, - GtkToggleActionEntry *toggle_actions, - guint n_toggle_actions, - const gchar *filename, - gpointer user_data) -{ - GncMainWindowPrivate *priv; - GncMainWindowActionData *data; - MergedActionEntry *entry; - GError *error = NULL; - gchar *pathname; - - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (group_name != NULL); - g_return_if_fail (actions != NULL); - g_return_if_fail (n_actions > 0); - g_return_if_fail (filename != NULL); - - data = g_new0 (GncMainWindowActionData, 1); - data->window = window; - data->data = user_data; - - pathname = gnc_gnome_locate_ui_file (filename); - if (pathname == NULL) - return; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - entry = g_new0 (MergedActionEntry, 1); - entry->action_group = gtk_action_group_new (group_name); - gnc_gtk_action_group_set_translation_domain (entry->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (entry->action_group, actions, n_actions, data); - if (toggle_actions != NULL && n_toggle_actions > 0) - { - gtk_action_group_add_toggle_actions (entry->action_group, - toggle_actions, n_toggle_actions, - data); - } - gtk_ui_manager_insert_action_group (window->ui_merge, entry->action_group, 0); - entry->merge_id = gtk_ui_manager_add_ui_from_file (window->ui_merge, pathname, &error); - g_assert(entry->merge_id || error); - if (entry->merge_id) - { - gtk_ui_manager_ensure_update (window->ui_merge); - g_hash_table_insert (priv->merged_actions_table, g_strdup (group_name), entry); - } - else - { - g_critical("Failed to load ui file.\n Filename %s\n Error %s", - filename, error->message); - g_error_free(error); - g_free(entry); - } - g_free(pathname); -} - - -/* Remove a set of actions from the specified window. This function - * should not need to be called directly by plugin implementors. It - * will automatically be called when a plugin is removed from a - * window. - */ -void -gnc_main_window_unmerge_actions (GncMainWindow *window, - const gchar *group_name) -{ - GncMainWindowPrivate *priv; - MergedActionEntry *entry; - - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (group_name != NULL); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->merged_actions_table == NULL) - return; - entry = g_hash_table_lookup (priv->merged_actions_table, group_name); - - if (entry == NULL) - return; - - gtk_ui_manager_remove_action_group (window->ui_merge, entry->action_group); - gtk_ui_manager_remove_ui (window->ui_merge, entry->merge_id); - gtk_ui_manager_ensure_update (window->ui_merge); - - g_hash_table_remove (priv->merged_actions_table, group_name); -} - - -/* Force a full update of the user interface for the specified - * window. This can be an expensive function, but is needed because - * the gtk ui manager doesn't always seem to update properly when - * actions are changed. - */ -void -gnc_main_window_actions_updated (GncMainWindow *window) -{ - GtkActionGroup *force; - - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - - /* Unfortunately gtk_ui_manager_ensure_update doesn't work - * here. Force a full update by adding and removing an empty - * action group. - */ - force = gtk_action_group_new("force_update"); - gtk_ui_manager_insert_action_group (window->ui_merge, force, 0); - gtk_ui_manager_ensure_update (window->ui_merge); - gtk_ui_manager_remove_action_group (window->ui_merge, force); - g_object_unref(force); -} - - -GtkAction * -gnc_main_window_find_action (GncMainWindow *window, const gchar *name) -{ - GtkAction *action = NULL; - const GList *groups, *tmp; - - groups = gtk_ui_manager_get_action_groups(window->ui_merge); - for (tmp = groups; tmp; tmp = g_list_next(tmp)) - { - action = gtk_action_group_get_action(GTK_ACTION_GROUP(tmp->data), name); - if (action) - break; - } - return action; -} - - -/* Retrieve a specific set of user interface actions from a window. - * This function can be used to get an group of action to be - * manipulated when the front page of a window has changed. - */ -GtkActionGroup * -gnc_main_window_get_action_group (GncMainWindow *window, - const gchar *group_name) -{ - GncMainWindowPrivate *priv; - MergedActionEntry *entry; - - g_return_val_if_fail (GNC_IS_MAIN_WINDOW (window), NULL); - g_return_val_if_fail (group_name != NULL, NULL); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->merged_actions_table == NULL) - return NULL; - entry = g_hash_table_lookup (priv->merged_actions_table, group_name); - - if (entry == NULL) - return NULL; - - return entry->action_group; -} - - -static void -gnc_main_window_update_toolbar (GncMainWindow *window) -{ - GtkToolbarStyle style; - GSList *list; - - ENTER("window %p", window); - - style = gnc_get_toolbar_style(); - list = gtk_ui_manager_get_toplevels(window->ui_merge, GTK_UI_MANAGER_TOOLBAR); - g_slist_foreach(list, (GFunc)gtk_toolbar_set_style, GINT_TO_POINTER(style)); - g_slist_free(list); - LEAVE(""); -} - -static void -gnc_main_window_update_tab_position (GncMainWindow *window) -{ - GtkPositionType position = GTK_POS_TOP; - gchar *conf_string; - GncMainWindowPrivate *priv; - - ENTER ("window %p", window); - conf_string = gnc_gconf_get_string (GCONF_GENERAL, - KEY_TAB_POSITION, NULL); - if (conf_string) - { - position = gnc_enum_from_nick (GTK_TYPE_POSITION_TYPE, - conf_string, GTK_POS_TOP); - g_free (conf_string); - } - - priv = GNC_MAIN_WINDOW_GET_PRIVATE (window); - gtk_notebook_set_tab_pos (GTK_NOTEBOOK (priv->notebook), position); - - LEAVE (""); -} - -/* - * Based on code from Epiphany (src/ephy-window.c) - */ -static void -gnc_main_window_update_edit_actions_sensitivity (GncMainWindow *window, gboolean hide) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window)); - GtkAction *action; - gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page = priv->current_page; - if (page && GNC_PLUGIN_PAGE_GET_CLASS(page)->update_edit_menu_actions) - { - (GNC_PLUGIN_PAGE_GET_CLASS(page)->update_edit_menu_actions)(page, hide); - return; - } - - if (GTK_IS_EDITABLE (widget)) - { - gboolean has_selection; - - has_selection = gtk_editable_get_selection_bounds - (GTK_EDITABLE (widget), NULL, NULL); - - can_copy = has_selection; - can_cut = has_selection; - can_paste = TRUE; - } - else if (GTK_IS_TEXT_VIEW (widget)) - { - gboolean has_selection; - GtkTextBuffer *text_buffer; - - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(widget)); - has_selection = gtk_text_buffer_get_selection_bounds - (text_buffer, NULL, NULL); - - can_copy = has_selection; - can_cut = has_selection; - can_paste = TRUE; - } - else - { -#ifdef ORIGINAL_EPIPHANY_CODE - /* For now we assume all actions are possible */ - can_copy = can_cut = can_paste = TRUE; -#else - /* If its not a GtkEditable, we don't know what to do - * with it. */ - can_copy = can_cut = can_paste = FALSE; -#endif - } - - action = gnc_main_window_find_action (window, "EditCopyAction"); - gtk_action_set_sensitive (action, can_copy); - gtk_action_set_visible (action, !hide || can_copy); - action = gnc_main_window_find_action (window, "EditCutAction"); - gtk_action_set_sensitive (action, can_cut); - gtk_action_set_visible (action, !hide || can_cut); - action = gnc_main_window_find_action (window, "EditPasteAction"); - gtk_action_set_sensitive (action, can_paste); - gtk_action_set_visible (action, !hide || can_paste); -} - -static void -gnc_main_window_enable_edit_actions_sensitivity (GncMainWindow *window) -{ - GtkAction *action; - - action = gnc_main_window_find_action (window, "EditCopyAction"); - gtk_action_set_sensitive (action, TRUE); - gtk_action_set_visible (action, TRUE); - action = gnc_main_window_find_action (window, "EditCutAction"); - gtk_action_set_sensitive (action, TRUE); - gtk_action_set_visible (action, TRUE); - action = gnc_main_window_find_action (window, "EditPasteAction"); - gtk_action_set_sensitive (action, TRUE); - gtk_action_set_visible (action, TRUE); -} - -static void -gnc_main_window_edit_menu_show_cb (GtkWidget *menu, - GncMainWindow *window) -{ - gnc_main_window_update_edit_actions_sensitivity (window, FALSE); -} - -static void -gnc_main_window_edit_menu_hide_cb (GtkWidget *menu, - GncMainWindow *window) -{ - gnc_main_window_enable_edit_actions_sensitivity (window); -} - -static void -gnc_main_window_init_menu_updaters (GncMainWindow *window) -{ - GtkWidget *edit_menu_item, *edit_menu; - - edit_menu_item = gtk_ui_manager_get_widget - (window->ui_merge, "/menubar/Edit"); - edit_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (edit_menu_item)); - - g_signal_connect (edit_menu, "show", - G_CALLBACK (gnc_main_window_edit_menu_show_cb), window); - g_signal_connect (edit_menu, "hide", - G_CALLBACK (gnc_main_window_edit_menu_hide_cb), window); -} - -static void -gnc_main_window_gconf_changed (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data) -{ - GncMainWindow *window; - GConfValue *value; - const gchar *key, *key_tail; - - window = GNC_MAIN_WINDOW(user_data); - - key = gconf_entry_get_key(entry); - value = gconf_entry_get_value(entry); - if (!key || !value) - return; - - key_tail = strrchr(key, '/'); - if (key_tail != NULL) - key_tail++; - if (strcmp(key_tail, KEY_TOOLBAR_STYLE) == 0) - { - gnc_main_window_update_toolbar(window); - } - else if (strcmp(key_tail, KEY_TAB_POSITION) == 0) - { - gnc_main_window_update_tab_position(window); - } -} - -/* CS: This callback functions will set the statusbar text to the - * "tooltip" property of the currently selected GtkAction. - * - * This code is directly copied from gtk+/test/testmerge.c. - * Thanks to (L)GPL! */ -typedef struct _ActionStatus ActionStatus; -struct _ActionStatus -{ - GtkAction *action; - GtkWidget *statusbar; -}; - -static void -action_status_destroy (gpointer data) -{ - ActionStatus *action_status = data; - - g_object_unref (action_status->action); - g_object_unref (action_status->statusbar); - - g_free (action_status); -} - -static void -set_tip (GtkWidget *widget) -{ - ActionStatus *data; - gchar *tooltip; - - data = g_object_get_data (G_OBJECT (widget), "action-status"); - - if (data) - { - g_object_get (data->action, "tooltip", &tooltip, NULL); - - gtk_statusbar_push (GTK_STATUSBAR (data->statusbar), 0, - tooltip ? tooltip : ""); - - g_free (tooltip); - } -} - -static void -unset_tip (GtkWidget *widget) -{ - ActionStatus *data; - - data = g_object_get_data (G_OBJECT (widget), "action-status"); - - if (data) - gtk_statusbar_pop (GTK_STATUSBAR (data->statusbar), 0); -} - -static void -connect_proxy (GtkUIManager *merge, - GtkAction *action, - GtkWidget *proxy, - GtkWidget *statusbar) -{ - if (GTK_IS_MENU_ITEM (proxy)) - { - ActionStatus *data; - - data = g_object_get_data (G_OBJECT (proxy), "action-status"); - if (data) - { - g_object_unref (data->action); - g_object_unref (data->statusbar); - - data->action = g_object_ref (action); - data->statusbar = g_object_ref (statusbar); - } - else - { - data = g_new0 (ActionStatus, 1); - - data->action = g_object_ref (action); - data->statusbar = g_object_ref (statusbar); - - g_object_set_data_full (G_OBJECT (proxy), "action-status", - data, action_status_destroy); - - g_signal_connect (proxy, "select", G_CALLBACK (set_tip), NULL); - g_signal_connect (proxy, "deselect", G_CALLBACK (unset_tip), NULL); - } - } -} -/* CS: end copied code from gtk+/test/testmerge.c */ - -static void -gnc_main_window_setup_window (GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GtkWidget *main_vbox; - guint merge_id; - GncPluginManager *manager; - GList *plugins; - GError *error = NULL; - gchar *filename; - - ENTER(" "); - - /* Catch window manager delete signal */ - g_signal_connect (G_OBJECT (window), "delete-event", - G_CALLBACK (gnc_main_window_delete_event), window); - - /* Create widgets and add them to the window */ - main_vbox = gtk_vbox_new (FALSE, 0); - gtk_widget_show (main_vbox); - gtk_container_add (GTK_CONTAINER (window), main_vbox); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - priv->menu_dock = gtk_vbox_new (FALSE, 0); - gtk_widget_show (priv->menu_dock); - gtk_box_pack_start (GTK_BOX (main_vbox), priv->menu_dock, - FALSE, TRUE, 0); - - priv->notebook = gtk_notebook_new (); - g_object_set(G_OBJECT(priv->notebook), - "scrollable", TRUE, - "enable-popup", TRUE, - (char *)NULL); - gtk_widget_show (priv->notebook); - g_signal_connect (G_OBJECT (priv->notebook), "switch-page", - G_CALLBACK (gnc_main_window_switch_page), window); - g_signal_connect (G_OBJECT (priv->notebook), "page-reordered", - G_CALLBACK (gnc_main_window_page_reordered), window); - gtk_box_pack_start (GTK_BOX (main_vbox), priv->notebook, - TRUE, TRUE, 0); - - priv->statusbar = gtk_statusbar_new (); - gtk_widget_show (priv->statusbar); - gtk_box_pack_start (GTK_BOX (main_vbox), priv->statusbar, - FALSE, TRUE, 0); - gtk_statusbar_set_has_resize_grip( GTK_STATUSBAR(priv->statusbar), TRUE ); - - priv->progressbar = gtk_progress_bar_new (); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(priv->progressbar), " "); - gtk_widget_show (priv->progressbar); - gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar, - FALSE, TRUE, 0); - gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(priv->progressbar), - 0.01); - - window->ui_merge = gtk_ui_manager_new (); - - /* Create menu and toolbar information */ - priv->action_group = gtk_action_group_new ("MainWindowActions"); - gnc_gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (priv->action_group, gnc_menu_actions, - gnc_menu_n_actions, window); - gtk_action_group_add_toggle_actions (priv->action_group, - toggle_actions, n_toggle_actions, - window); -#ifndef MAC_INTEGRATION - gtk_action_group_add_radio_actions (priv->action_group, - radio_entries, n_radio_entries, - 0, - G_CALLBACK(gnc_main_window_cmd_window_raise), - window); -#endif - gnc_plugin_update_actions(priv->action_group, - initially_insensitive_actions, - "sensitive", FALSE); - gnc_plugin_update_actions(priv->action_group, - always_insensitive_actions, - "sensitive", FALSE); - gnc_plugin_update_actions(priv->action_group, - always_hidden_actions, - "visible", FALSE); - gnc_plugin_set_important_actions (priv->action_group, - gnc_menu_important_actions); - gtk_ui_manager_insert_action_group (window->ui_merge, priv->action_group, 0); - - g_signal_connect (G_OBJECT (window->ui_merge), "add_widget", - G_CALLBACK (gnc_main_window_add_widget), window); - /* Use the "connect-proxy" signal for tooltip display in the - status bar */ - g_signal_connect (G_OBJECT (window->ui_merge), "connect-proxy", - G_CALLBACK (connect_proxy), priv->statusbar); - - filename = gnc_gnome_locate_ui_file("gnc-main-window-ui.xml"); - - /* Can't do much without a ui. */ - g_assert (filename); - - merge_id = gtk_ui_manager_add_ui_from_file (window->ui_merge, - filename, &error); - g_assert(merge_id || error); - if (merge_id) - { - gtk_window_add_accel_group (GTK_WINDOW (window), - gtk_ui_manager_get_accel_group(window->ui_merge)); - gtk_ui_manager_ensure_update (window->ui_merge); - } - else - { - g_critical("Failed to load ui file.\n Filename %s\n Error %s", - filename, error->message); - g_error_free(error); - g_assert(merge_id != 0); - } - g_free(filename); - - gnc_gconf_add_notification(G_OBJECT(window), GCONF_GENERAL, - gnc_main_window_gconf_changed, - GNC_MAIN_WINDOW_NAME); - gnc_gconf_add_notification(G_OBJECT(window), DESKTOP_GNOME_INTERFACE, - gnc_main_window_gconf_changed, - GNC_MAIN_WINDOW_NAME); - gnc_main_window_update_toolbar(window); - gnc_main_window_update_tab_position(window); - - gnc_main_window_init_menu_updaters(window); - - /* Testing */ - /* Now update the "eXtensions" menu */ - if (!gnc_is_extra_enabled()) - { - GtkAction* action; - - action = gtk_action_group_get_action(priv->action_group, - "ExtensionsAction"); - gtk_action_set_visible(action, FALSE); - } - - /* GncPluginManager stuff */ - manager = gnc_plugin_manager_get (); - plugins = gnc_plugin_manager_get_plugins (manager); - g_list_foreach (plugins, gnc_main_window_add_plugin, window); - g_list_free (plugins); - - g_signal_connect (G_OBJECT (manager), "plugin-added", - G_CALLBACK (gnc_main_window_plugin_added), window); - g_signal_connect (G_OBJECT (manager), "plugin-removed", - G_CALLBACK (gnc_main_window_plugin_removed), window); - - LEAVE(" "); -} - -#ifdef MAC_INTEGRATION -static void -gnc_quartz_shutdown (GtkOSXApplication *theApp, gpointer data) -{ - gnc_shutdown(0); -} - -static gboolean -gnc_quartz_should_quit (GtkOSXApplication *theApp, GncMainWindow *window) -{ - QofSession *session; - gboolean needs_save, do_shutdown; - - gboolean finished = gnc_main_window_all_finish_pending(); - if (!finished) - return TRUE; - session = gnc_get_current_session(); - needs_save = qof_book_not_saved(qof_session_get_book(session)) && - !gnc_file_save_in_progress(); - if (needs_save && gnc_main_window_prompt_for_save(GTK_WIDGET(window))) - return TRUE; - gnc_shutdown(0); - return FALSE; -} - -static void -gnc_quartz_set_menu(GncMainWindow* window) -{ - GtkOSXApplicationMenuGroup *group; - GtkOSXApplication *theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL); - GtkWidget *menu; - GtkWidget *item; - - menu = gtk_ui_manager_get_widget (window->ui_merge, "/menubar"); - if (GTK_IS_MENU_ITEM (menu)) - menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu)); - gtk_widget_hide(menu); - gtk_osxapplication_set_menu_bar (theApp, GTK_MENU_SHELL (menu)); - - item = gtk_ui_manager_get_widget (window->ui_merge, - "/menubar/File/FileQuit"); - if (GTK_IS_MENU_ITEM (item)) - gtk_widget_hide (GTK_WIDGET (item)); - - /* the about group */ - group = gtk_osxapplication_add_app_menu_group (theApp); - - item = gtk_ui_manager_get_widget (window->ui_merge, - "/menubar/Help/HelpAbout"); - if (GTK_IS_MENU_ITEM (item)) - gtk_osxapplication_add_app_menu_item (theApp, group, - GTK_MENU_ITEM (item)); - - /* the preferences group */ - group = gtk_osxapplication_add_app_menu_group (theApp); - - item = gtk_ui_manager_get_widget (window->ui_merge, - "/menubar/Edit/EditPreferences"); - if (GTK_IS_MENU_ITEM (item)) - gtk_osxapplication_add_app_menu_item (theApp, group, - GTK_MENU_ITEM (item)); - - item = gtk_ui_manager_get_widget (window->ui_merge, - "/menubar/Help"); - gtk_osxapplication_set_help_menu(theApp, GTK_MENU_ITEM(item)); - item = gtk_ui_manager_get_widget (window->ui_merge, - "/menubar/Windows"); - gtk_osxapplication_set_window_menu(theApp, GTK_MENU_ITEM(item)); - g_signal_connect(theApp, "NSApplicationBlockTermination", - G_CALLBACK(gnc_quartz_should_quit), window); - -} -#endif //MAC_INTEGRATION - -/* Callbacks */ -static void -gnc_main_window_add_widget (GtkUIManager *merge, - GtkWidget *widget, - GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (GTK_IS_TOOLBAR (widget)) - { - priv->toolbar = widget; - } - - gtk_box_pack_start (GTK_BOX (priv->menu_dock), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); -} - -/** Should a summary bar be visible in this window? In order to - * prevent synchronization issues, the "ViewSummaryBar" - * GtkToggleAction is the sole source of information for whether or - * not any summary bar should be visible in a window. - * - * @param window A pointer to the window in question. - * - * @param action If known, a pointer to the "ViewSummaryBar" - * GtkToggleAction. If NULL, the function will look up this action. - * - * @return TRUE if the summarybar should be visible. - */ -static gboolean -gnc_main_window_show_summarybar (GncMainWindow *window, GtkAction *action) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (action == NULL) - action = gtk_action_group_get_action(priv->action_group, - "ViewSummaryAction"); - if (action == NULL) - return TRUE; - return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); -} - -/** This function is invoked when the GtkNotebook switches pages. It - * is responsible for updating the rest of the window contents - * outside of the notebook. I.E. Updating the user interface, the - * summary bar, etc. This function also emits the "page_changed" - * signal from the window so that any plugin can also learn about the - * fact that the page has changed. - * - * @internal - */ -static void -gnc_main_window_switch_page (GtkNotebook *notebook, - GtkNotebookPage *notebook_page, - gint pos, - GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GtkWidget *child; - GncPluginPage *page; - gboolean immutable, visible; - - ENTER("Notebook %p, page, %p, index %d, window %p", - notebook, notebook_page, pos, window); - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (priv->current_page != NULL) - { - page = priv->current_page; - gnc_plugin_page_unmerge_actions (page, window->ui_merge); - gnc_plugin_page_unselected (page); - } - - child = gtk_notebook_get_nth_page (notebook, pos); - if (child) - { - page = g_object_get_data (G_OBJECT (child), PLUGIN_PAGE_LABEL); - } - else - { - page = NULL; - } - - priv->current_page = page; - - if (page != NULL) - { - /* Update the user interface (e.g. menus and toolbars */ - gnc_plugin_page_merge_actions (page, window->ui_merge); - visible = gnc_main_window_show_summarybar(window, NULL); - gnc_plugin_page_show_summarybar (page, visible); - - /* Allow page specific actions */ - gnc_plugin_page_selected (page); - gnc_window_update_status (GNC_WINDOW(window), page); - - /* Update the page reference info */ - priv->usage_order = g_list_remove (priv->usage_order, page); - priv->usage_order = g_list_prepend (priv->usage_order, page); - } - - /* Update the menus based upon whether this is an "immutable" page. */ - immutable = page && - g_object_get_data (G_OBJECT (page), PLUGIN_PAGE_IMMUTABLE); - gnc_plugin_update_actions(priv->action_group, - immutable_page_actions, - "sensitive", !immutable); - gnc_plugin_update_actions(priv->action_group, - multiple_page_actions, - "sensitive", - g_list_length(priv->installed_pages) > 1); - - gnc_main_window_update_title(window); - gnc_main_window_update_menu_item(window); - - g_signal_emit (window, main_window_signals[PAGE_CHANGED], 0, page); - LEAVE(" "); -} - -/** This function is invoked when a GtkNotebook tab gets reordered by - * drag and drop. It adjusts the list installed_pages to reflect the new - * ordering so that GnuCash saves and restores the tabs correctly. - * - * @internal - */ -static void -gnc_main_window_page_reordered (GtkNotebook *notebook, - GtkWidget *child, - guint pos, - GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - GList *old_link; - - ENTER("Notebook %p, child %p, index %d, window %p", - notebook, child, pos, window); - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - - if (!child) return; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - - page = g_object_get_data (G_OBJECT (child), PLUGIN_PAGE_LABEL); - if (!page) return; - - old_link = g_list_find (priv->installed_pages, page); - if (!old_link) return; - - priv->installed_pages = g_list_delete_link (priv->installed_pages, - old_link); - priv->installed_pages = g_list_insert (priv->installed_pages, - page, pos); - - LEAVE(" "); -} - -static void -gnc_main_window_plugin_added (GncPlugin *manager, - GncPlugin *plugin, - GncMainWindow *window) -{ - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (GNC_IS_PLUGIN (plugin)); - - gnc_plugin_add_to_window (plugin, window, window_type); -} - -static void -gnc_main_window_plugin_removed (GncPlugin *manager, - GncPlugin *plugin, - GncMainWindow *window) -{ - g_return_if_fail (GNC_IS_MAIN_WINDOW (window)); - g_return_if_fail (GNC_IS_PLUGIN (plugin)); - - gnc_plugin_remove_from_window (plugin, window, window_type); -} - - -/* Command callbacks */ -static void -gnc_main_window_cmd_page_setup (GtkAction *action, - GncMainWindow *window) -{ - GtkWindow *gtk_window; - - g_return_if_fail(GNC_IS_MAIN_WINDOW(window)); - - gtk_window = gnc_window_get_gtk_window(GNC_WINDOW(window)); - gnc_ui_page_setup(gtk_window); -} - -static void -gnc_main_window_cmd_file_properties (GtkAction *action, GncMainWindow *window) -{ - SCM func = scm_c_eval_string("gnc:main-window-properties-cb"); - if (!scm_is_procedure (func)) - { - PERR ("not a procedure\n"); - return; - } - scm_call_0(func); -} - -static void -gnc_main_window_cmd_file_close (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - - g_return_if_fail(GNC_IS_MAIN_WINDOW(window)); - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page = priv->current_page; - gnc_main_window_close_page(page); -} - -static void -gnc_main_window_cmd_file_quit (GtkAction *action, GncMainWindow *window) -{ - if (!gnc_main_window_all_finish_pending()) - return; - - gnc_main_window_quit(window); -} - -static void -gnc_main_window_cmd_edit_cut (GtkAction *action, GncMainWindow *window) -{ - GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window)); - GtkTextBuffer *text_buffer; - GtkClipboard *clipboard; - gboolean editable; - - if (GTK_IS_EDITABLE (widget)) - { - gtk_editable_cut_clipboard (GTK_EDITABLE (widget)); - } - else if (GTK_IS_TEXT_VIEW (widget)) - { - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(widget)); - clipboard = gtk_widget_get_clipboard (GTK_WIDGET(text_buffer), - GDK_SELECTION_CLIPBOARD); - editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)); - gtk_text_buffer_cut_clipboard (text_buffer, clipboard, editable); - } -} - -static void -gnc_main_window_cmd_edit_copy (GtkAction *action, GncMainWindow *window) -{ - GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window)); - GtkTextBuffer *text_buffer; - GtkClipboard *clipboard; - - if (GTK_IS_EDITABLE (widget)) - { - gtk_editable_copy_clipboard (GTK_EDITABLE (widget)); - } - else if (GTK_IS_TEXT_VIEW (widget)) - { - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(widget)); - clipboard = gtk_widget_get_clipboard (GTK_WIDGET(text_buffer), - GDK_SELECTION_CLIPBOARD); - gtk_text_buffer_copy_clipboard (text_buffer, clipboard); - } -} - -static void -gnc_main_window_cmd_edit_paste (GtkAction *action, GncMainWindow *window) -{ - GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window)); - GtkTextBuffer *text_buffer; - GtkClipboard *clipboard; - gboolean editable; - - if (GTK_IS_EDITABLE (widget)) - { - gtk_editable_paste_clipboard (GTK_EDITABLE (widget)); - } - else if (GTK_IS_TEXT_VIEW (widget)) - { - text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(widget)); - clipboard = gtk_widget_get_clipboard (GTK_WIDGET(text_buffer), - GDK_SELECTION_CLIPBOARD); - editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (widget)); - gtk_text_buffer_paste_clipboard (text_buffer, clipboard, NULL, FALSE); - } -} - -static void -gnc_main_window_cmd_edit_preferences (GtkAction *action, GncMainWindow *window) -{ - gnc_preferences_dialog (); -} - -static void -gnc_main_window_cmd_view_refresh (GtkAction *action, GncMainWindow *window) -{ -} - -static void -gnc_main_window_cmd_actions_reset_warnings (GtkAction *action, GncMainWindow *window) -{ - gnc_reset_warnings_dialog(GTK_WIDGET(window)); -} - -static void -gnc_main_window_cmd_actions_rename_page (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GncPluginPage *page; - GtkWidget *label, *entry; - - ENTER(" "); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page = priv->current_page; - if (!page) - { - LEAVE("No current page"); - return; - } - - if (!main_window_find_tab_items(window, page, &label, &entry)) - { - LEAVE("can't find required widgets"); - return; - } - - gtk_entry_set_text(GTK_ENTRY(entry), gtk_label_get_text(GTK_LABEL(label))); - gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); - gtk_widget_hide(label); - gtk_widget_show(entry); - gtk_widget_grab_focus(entry); - LEAVE("opened for editing"); -} - -static void -gnc_main_window_cmd_view_toolbar (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) - { - gtk_widget_show (priv->toolbar); - } - else - { - gtk_widget_hide (priv->toolbar); - } -} - -static void -gnc_main_window_cmd_view_summary (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - GList *item; - gboolean visible; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - visible = gnc_main_window_show_summarybar(window, action); - for (item = priv->installed_pages; item; item = g_list_next(item)) - { - gnc_plugin_page_show_summarybar(item->data, visible); - } -} - -static void -gnc_main_window_cmd_view_statusbar (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv; - - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) - { - gtk_widget_show (priv->statusbar); - } - else - { - gtk_widget_hide (priv->statusbar); - } -} - -static void -gnc_main_window_cmd_window_new (GtkAction *action, GncMainWindow *window) -{ - GncMainWindow *new_window; - - /* Create the new window */ - ENTER(" "); - new_window = gnc_main_window_new (); - gtk_widget_show(GTK_WIDGET(new_window)); - LEAVE(" "); -} - -static void -gnc_main_window_cmd_window_move_page (GtkAction *action, GncMainWindow *window) -{ - GncMainWindowPrivate *priv, *new_priv; - GncMainWindow *new_window; - GncPluginPage *page; - GtkNotebook *notebook; - GtkWidget *tab_widget, *menu_widget; - - ENTER("action %p,window %p", action, window); - - /* Setup */ - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - page = priv->current_page; - if (!page) - { - LEAVE("invalid page"); - return; - } - if (!page->notebook_page) - { - LEAVE("invalid notebook_page"); - return; - } - - notebook = GTK_NOTEBOOK (priv->notebook); - tab_widget = gtk_notebook_get_tab_label (notebook, page->notebook_page); - menu_widget = gtk_notebook_get_menu_label (notebook, page->notebook_page); - - /* Ref the page components, then remove it from its old window */ - g_object_ref(page); - g_object_ref(tab_widget); - g_object_ref(menu_widget); - g_object_ref(page->notebook_page); - gnc_main_window_disconnect(window, page); - - /* Create the new window */ - new_window = gnc_main_window_new (); - gtk_widget_show(GTK_WIDGET(new_window)); - - /* Now add the page to the new window */ - gnc_main_window_connect (new_window, page, tab_widget, menu_widget); - - /* Unref the page components now that we're done */ - g_object_unref(page->notebook_page); - g_object_unref(menu_widget); - g_object_unref(tab_widget); - g_object_unref(page); - - /* just a little debugging. :-) */ - new_priv = GNC_MAIN_WINDOW_GET_PRIVATE(new_window); - DEBUG("Moved page %p from window %p to new window %p", - page, window, new_window); - DEBUG("Old window current is %p, new window current is %p", - priv->current_page, priv->current_page); - - LEAVE("page moved"); -} - -static void -gnc_main_window_cmd_window_raise (GtkAction *action, - GtkRadioAction *current, - GncMainWindow *old_window) -{ - GncMainWindow *new_window; - gint value; - - g_return_if_fail(GTK_IS_ACTION(action)); - g_return_if_fail(GTK_IS_RADIO_ACTION(current)); - g_return_if_fail(GNC_IS_MAIN_WINDOW(old_window)); - - ENTER("action %p, current %p, window %p", action, current, old_window); - value = gtk_radio_action_get_current_value(current); - new_window = g_list_nth_data(active_windows, value); - gtk_window_present(GTK_WINDOW(new_window)); - - /* revert the change in the radio group - * impossible while handling "changed" (G_SIGNAL_NO_RECURSE) */ - g_idle_add((GSourceFunc)gnc_main_window_update_radio_button, old_window); - LEAVE(" "); -} - -static void -gnc_main_window_cmd_help_tutorial (GtkAction *action, GncMainWindow *window) -{ - gnc_gnome_help (HF_GUIDE, NULL); -} - -static void -gnc_main_window_cmd_help_contents (GtkAction *action, GncMainWindow *window) -{ - gnc_gnome_help (HF_HELP, NULL); -} - -/** This is a helper function to find a data file and suck it into - * memory. - * - * @param partial The name of the file relative to the gnucash - * specific shared data directory. - * - * @return The text of the file or NULL. The caller is responsible - * for freeing this string. - */ -static gchar * -get_file (const gchar *partial) -{ - gchar *filename, *text = NULL; - - filename = gnc_gnome_locate_data_file(partial); - g_file_get_contents(filename, &text, NULL, NULL); - g_free(filename); - - /* Anything there? */ - if (text && *text) - return text; - - /* Just a empty string or no string at all. */ - if (text) - g_free(text); - return NULL; -} - - -/** This is a helper function to find a data file, suck it into - * memory, and split it into an array of strings. - * - * @param partial The name of the file relative to the gnucash - * specific shared data directory. - * - * @return The text of the file as an array of strings, or NULL. The - * caller is responsible for freeing all the strings and the array. - */ -static gchar ** -get_file_strsplit (const gchar *partial) -{ - gchar *text, **lines; - - text = get_file(partial); - if (!text) - return NULL; - - lines = g_strsplit_set(text, "\r\n", -1); - g_free(text); - return lines; -} - - -/** Create and display the "about" dialog for gnucash. - * - * @param action The GtkAction for the "about" menu item. - * - * @param window The main window whose menu item was activated. - */ -static void -gnc_main_window_cmd_help_about (GtkAction *action, GncMainWindow *window) -{ - const gchar *fixed_message = _("The GnuCash personal finance manager. " - "The GNU way to manage your money!"); - const gchar *copyright = "© 1997-2010 Contributors"; - gchar **authors, **documenters, *license, *message; - GdkPixbuf *logo; - - logo = gnc_gnome_get_gdkpixbuf ("gnucash-icon-48x48.png"); - - authors = get_file_strsplit("doc/AUTHORS"); - documenters = get_file_strsplit("doc/DOCUMENTERS"); - license = get_file("doc/LICENSE"); -#ifdef GNUCASH_SVN - /* Development version */ - message = g_strdup_printf(_("%s This copy was built from svn r%s on %s."), - fixed_message, GNUCASH_SVN_REV, GNUCASH_BUILD_DATE); -#else - message = g_strdup_printf(_("%s This copy was built from r%s on %s."), - fixed_message, GNUCASH_SVN_REV, GNUCASH_BUILD_DATE); -#endif - gtk_show_about_dialog - (GTK_WINDOW (window), - "authors", authors, - "documenters", documenters, - "comments", message, - "copyright", copyright, - "license", license, - "logo", logo, - "name", "GnuCash", - "translator-credits", _("translator_credits"), - "version", VERSION, - "website", "http://www.gnucash.org", - (gchar *)NULL); - - g_free(message); - if (license) g_free(license); - if (documenters) g_strfreev(documenters); - if (authors) g_strfreev(authors); - g_object_unref (logo); -} - - -/************************************************************ - * * - ************************************************************/ - -void -gnc_main_window_show_all_windows(void) -{ - GList *window_iter; -#ifdef MAC_INTEGRATION - GtkOSXApplication *theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL); -#endif - for (window_iter = active_windows; window_iter != NULL; window_iter = window_iter->next) - { - gtk_widget_show(GTK_WIDGET(window_iter->data)); -#ifdef MAC_INTEGRATION - gnc_quartz_set_menu(window_iter->data); -#endif - } -#ifdef MAC_INTEGRATION - g_signal_connect(theApp, "NSApplicationWillTerminate", - G_CALLBACK(gnc_quartz_shutdown), NULL); - gtk_osxapplication_ready(theApp); -#endif -} - -/** Get a pointer to the first active top level window or NULL - * if there is none. - * - * @return A pointer to a GtkWindow object. */ -GtkWidget * -gnc_ui_get_toplevel (void) -{ - GList *window; - - for (window = active_windows; window; window = window->next) - if (gtk_window_is_active (GTK_WINDOW (window->data))) - return window->data; - - return NULL; -} - - -/** Retrieve the gtk window associated with a main window object. - * This function is called via a vector off a generic window - * interface. - * - * @param window A pointer to a generic window. */ -static GtkWindow * -gnc_main_window_get_gtk_window (GncWindow *window) -{ - g_return_val_if_fail (GNC_IS_MAIN_WINDOW (window), NULL); - return GTK_WINDOW(window); -} - - -/** Retrieve the status bar associated with a main window object. - * This function is called via a vector off a generic window - * interface. - * - * @param window_in A pointer to a generic window. */ -static GtkWidget * -gnc_main_window_get_statusbar (GncWindow *window_in) -{ - GncMainWindowPrivate *priv; - GncMainWindow *window; - - g_return_val_if_fail (GNC_IS_MAIN_WINDOW (window_in), NULL); - - window = GNC_MAIN_WINDOW(window_in); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - return priv->statusbar; -} - - -/** Retrieve the progress bar associated with a main window object. - * This function is called via a vector off a generic window - * interface. - * - * @param window_in A pointer to a generic window. */ -static GtkWidget * -gnc_main_window_get_progressbar (GncWindow *window_in) -{ - GncMainWindowPrivate *priv; - GncMainWindow *window; - - g_return_val_if_fail (GNC_IS_MAIN_WINDOW (window_in), NULL); - - window = GNC_MAIN_WINDOW(window_in); - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - return priv->progressbar; -} - - -static void -gnc_main_window_all_ui_set_sensitive (GncWindow *unused, gboolean sensitive) -{ - GncMainWindow *window; - GncMainWindowPrivate *priv; - GList *groupp, *groups, *winp, *tmp; - GtkWidget *close_button; - - for (winp = active_windows; winp; winp = g_list_next(winp)) - { - window = winp->data; - priv = GNC_MAIN_WINDOW_GET_PRIVATE(window); - - groups = gtk_ui_manager_get_action_groups(window->ui_merge); - for (groupp = groups; groupp; groupp = g_list_next(groupp)) - { - gtk_action_group_set_sensitive(GTK_ACTION_GROUP(groupp->data), sensitive); - } - - for (tmp = priv->installed_pages; tmp; tmp = g_list_next(tmp)) - { - close_button = g_object_get_data(tmp->data, PLUGIN_PAGE_CLOSE_BUTTON); - if (!close_button) - continue; - gtk_widget_set_sensitive (close_button, sensitive); - } - } -} - - -/** Initialize the generic window interface for a main window. - * - * @param iface A pointer to the interface data structure to - * populate. */ -static void -gnc_window_main_window_init (GncWindowIface *iface) -{ - iface->get_gtk_window = gnc_main_window_get_gtk_window; - iface->get_statusbar = gnc_main_window_get_statusbar; - iface->get_progressbar = gnc_main_window_get_progressbar; - iface->ui_set_sensitive = gnc_main_window_all_ui_set_sensitive; -} - - -/* Set the window where all progressbar updates should occur. This - * is a wrapper around the gnc_window_set_progressbar_window() - * function. - */ -void -gnc_main_window_set_progressbar_window (GncMainWindow *window) -{ - GncWindow *gncwin; - gncwin = GNC_WINDOW(window); - gnc_window_set_progressbar_window(gncwin); -} - - -/** Popup a contextual menu. This function ends up being called when - * the user right-clicks in the context of a window, or uses the - * keyboard context-menu request key combination (Shift-F10 by - * default). - * - * @param page This is the GncPluginPage corresponding to the visible - * page. - * - * @param event The event parameter passed to the "button-press" - * callback. May be null if there was no event (aka keyboard - * request). - */ -static void -do_popup_menu(GncPluginPage *page, GdkEventButton *event) -{ - GtkUIManager *ui_merge; - GtkWidget *menu; - int button, event_time; - - g_return_if_fail(GNC_IS_PLUGIN_PAGE(page)); - - ENTER("page %p, event %p", page, event); - ui_merge = gnc_plugin_page_get_ui_merge(page); - if (ui_merge == NULL) - { - LEAVE("no ui merge"); - return; - } - - menu = gtk_ui_manager_get_widget(ui_merge, "/MainPopup"); - if (!menu) - { - LEAVE("no menu"); - return; - } - - if (event) - { - button = event->button; - event_time = event->time; - } - else - { - button = 0; - event_time = gtk_get_current_event_time (); - } - - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, event_time); - LEAVE(" "); -} - - -/** Callback function invoked when the user requests that Gnucash - * popup the contextual menu via the keyboard context-menu request - * key combination (Shift-F10 by default). - * - * @param page This is the GncPluginPage corresponding to the visible - * page. - * - * @param widget Whatever widget had focus when the user issued the - * keyboard context-menu request. - * - * @return Always returns TRUE to indicate that the menu request was - * handled. - */ -static gboolean -gnc_main_window_popup_menu_cb (GtkWidget *widget, - GncPluginPage *page) -{ - ENTER("widget %p, page %p", widget, page); - do_popup_menu(page, NULL); - LEAVE(" "); - return TRUE; -} - - -/* Callback function invoked when the user clicks in the content of - * any Gnucash window. If this was a "right-click" then Gnucash will - * popup the contextual menu. - */ -gboolean -gnc_main_window_button_press_cb (GtkWidget *whatever, - GdkEventButton *event, - GncPluginPage *page) -{ - g_return_val_if_fail(GNC_IS_PLUGIN_PAGE(page), FALSE); - - ENTER("widget %p, event %p, page %p", whatever, event, page); - /* Ignore double-clicks and triple-clicks */ - if (event->button == 3 && event->type == GDK_BUTTON_PRESS) - { - do_popup_menu(page, event); - LEAVE("menu shown"); - return TRUE; - } - - LEAVE("other click"); - return FALSE; -} - - -/* CS: Code copied from gtk/gtkactiongroup.c */ -static gchar * -dgettext_swapped (const gchar *msgid, - const gchar *domainname) -{ - /* CS: Pass this through dgettext if and only if msgid is - nonempty. */ - return (msgid && *msgid) ? dgettext (domainname, msgid) : (gchar*) msgid; -} - -/* - * This is copied into GnuCash from Gtk in order to fix problems when - * empty msgids were passed through gettext(). - * - * See http://bugzilla.gnome.org/show_bug.cgi?id=326200 . If that bug - * is fixed in the gtk that we can rely open, then - * gnc_gtk_action_group_set_translation_domain can be replaced by - * gtk_action_group_set_translation_domain again. - */ -void -gnc_gtk_action_group_set_translation_domain (GtkActionGroup *action_group, - const gchar *domain) -{ - g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - - gtk_action_group_set_translate_func (action_group, - (GtkTranslateFunc)dgettext_swapped, - g_strdup (domain), - g_free); -} -/* CS: End of code copied from gtk/gtkactiongroup.c */ - -void -gnc_main_window_all_action_set_sensitive (const gchar *action_name, - gboolean sensitive) -{ - GList *tmp; - GtkAction *action; - - for (tmp = active_windows; tmp; tmp = g_list_next(tmp)) - { - action = gnc_main_window_find_action (tmp->data, action_name); - gtk_action_set_sensitive (action, sensitive); - } -} - -GtkUIManager *gnc_main_window_get_uimanager (GncMainWindow *window) -{ - g_assert(window); - return window->ui_merge; -} - -/** @} */ -/** @} */ diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am index cadee67cad..2a1b852827 100644 --- a/src/libqof/qof/Makefile.am +++ b/src/libqof/qof/Makefile.am @@ -1,5 +1,10 @@ SUBDIRS = . test +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) +INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) + + lib_LTLIBRARIES = libgnc-qof.la libgnc_qof_la_LDFLAGS= -version-info $(LIBQOF_LIBRARY_VERSION) @@ -80,6 +85,28 @@ noinst_HEADERS = \ EXTRA_DIST = \ qofmath128.c +if HAVE_INTROSPECTION +include ${INTROSPECTION_MAKEFILE} +introspection_sources = $(qofinclude_HEADERS) + +INTROSPECTION_GIRS += Qof-1.gir +Qof_1_gir_INCLUDES = GObject-2.0 GLib-2.0 +Qof_1_gir_NAMESPACE = Qof +Qof_1_gir_VERSION = 1 +Qof_1_gir_CFLAGS = ${AM_CPPFLAGS} -I$(top_builddir) +Qof_1_gir_LIBS = libgnc-qof.la +Qof_1_gir_FILES = $(introspection_sources) + + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = Qof-1.typelib + +CLEANFILES = $(gir_DATA) $(typelib_DATA) +endif + if OS_WIN32 libgnc_qof_la_SOURCES += qof-win32.c else diff --git a/src/libqof/qof/qofutil.h b/src/libqof/qof/qofutil.h index f65eacaef7..89d3b626a8 100644 --- a/src/libqof/qof/qofutil.h +++ b/src/libqof/qof/qofutil.h @@ -32,6 +32,7 @@ #ifndef QOF_UTIL_H #define QOF_UTIL_H +#include #include #include "qof.h" #include "qoflog.h"