First pass at a Book Closing dialog (#106383)

Helps the user to auto-zeroize Income and Expense accounts.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16713 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins 2007-12-24 04:40:53 +00:00
parent 27fcf8ff7c
commit 8ca76d3635
7 changed files with 685 additions and 0 deletions

View File

@ -27,6 +27,7 @@ libgncmod_gnome_utils_la_SOURCES = \
account-quickfill.c \
cursors.c \
dialog-account.c \
dialog-book-close.c \
dialog-commodity.c \
dialog-options.c \
dialog-preferences.c \
@ -100,6 +101,7 @@ gncinclude_HEADERS = \
QuickFill.h \
account-quickfill.h \
dialog-account.h \
dialog-book-close.h \
dialog-commodity.h \
dialog-preferences.h \
dialog-options.h \

View File

@ -0,0 +1,327 @@
/********************************************************************\
* dialog-book-close.c -- dialog for helping the user close the *
* book at the end of the year by adding *
* zero-izing splits to all Income and *
* Expense accounts *
* *
* Copyright (C) 2007-8 Derek Atkins <derek@ihtfp.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, 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 *
\********************************************************************/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glade/glade.h>
#include "dialog-utils.h"
#include "gnc-engine.h"
#include "Transaction.h"
#include "Split.h"
#include "Account.h"
#include "gnc-ui.h"
#include "gnc-gui-query.h"
#include "dialog-book-close.h"
#include "gnc-account-sel.h"
#include "gnc-date-edit.h"
void gnc_book_close_response_cb(GtkDialog *, gint, GtkDialog *);
struct CloseBookWindow
{
/* Passed in by the creator */
QofBook* book;
/* Parts of the dialog */
GtkWidget* dialog;
GtkWidget* close_date_widget;
GtkWidget* income_acct_widget;
GtkWidget* expense_acct_widget;
GtkWidget* desc_widget;
/* The final settings */
time_t close_date;
const char* desc;
};
struct CloseAccountsCB
{
struct CloseBookWindow* cbw;
Account* base_acct;
GNCAccountType acct_type;
GHashTable* txns;
guint hash_size;
};
struct CACBTransactionList
{
gnc_commodity* cmdty;
Transaction* txn;
gnc_numeric total;
};
static struct CACBTransactionList*
find_or_create_txn(struct CloseAccountsCB* cacb, gnc_commodity* cmdty)
{
struct CACBTransactionList* txn;
g_return_val_if_fail(cacb, NULL);
g_return_val_if_fail(cmdty, NULL);
txn = g_hash_table_lookup(cacb->txns, cmdty);
if (!txn)
{
txn = g_new0(struct CACBTransactionList, 1);
txn->cmdty = cmdty;
txn->total = gnc_numeric_zero();
txn->txn = xaccMallocTransaction(cacb->cbw->book);
xaccTransBeginEdit(txn->txn);
xaccTransSetDateEnteredSecs(txn->txn, time(NULL));
xaccTransSetDatePostedSecs(txn->txn, cacb->cbw->close_date);
xaccTransSetDescription(txn->txn, cacb->cbw->desc);
xaccTransSetCurrency(txn->txn, cmdty);
g_hash_table_insert(cacb->txns, cmdty, txn);
}
return txn;
}
/* Make sure that the account is of the correct type.
* then make sure the account has a balance as of the closing date.
* then get the account commodity and find the appropriate
* balancing transaction for that commodity and add this balance
* to it.
*/
static void close_accounts_cb(Account *a, gpointer data)
{
struct CloseAccountsCB* cacb = data;
struct CACBTransactionList* txn;
gnc_commodity* acct_commodity;
Split* split;
gnc_numeric bal;
g_return_if_fail(a);
g_return_if_fail(cacb);
g_return_if_fail(cacb->cbw);
g_return_if_fail(cacb->txns);
if (cacb->acct_type != xaccAccountGetType(a))
return;
bal = xaccAccountGetBalanceAsOfDate(a, cacb->cbw->close_date);
if (gnc_numeric_zero_p(bal))
return;
acct_commodity = xaccAccountGetCommodity(a);
g_assert(acct_commodity);
txn = find_or_create_txn(cacb, acct_commodity);
g_assert(txn);
split = xaccMallocSplit(cacb->cbw->book);
xaccSplitSetParent(split, txn->txn);
xaccAccountBeginEdit(a);
xaccAccountInsertSplit(a, split);
xaccSplitSetBaseValue(split, gnc_numeric_neg(bal), acct_commodity);
xaccAccountCommitEdit(a);
txn->total = gnc_numeric_add(txn->total, bal, GNC_DENOM_AUTO,
GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
}
static void finish_txn_cb(gnc_commodity* cmdty,
struct CACBTransactionList* txn,
struct CloseAccountsCB* cacb)
{
Account* acc;
Split* split;
g_return_if_fail(cmdty);
g_return_if_fail(txn);
g_return_if_fail(cacb);
g_return_if_fail(cacb->hash_size);
/* If we only have one currency and the base account uses
* that currency, then we can use that account. Otherwise,
* create a subaccount for each currency.
*/
if (cacb->hash_size == 1 &&
gnc_commodity_equal(cmdty, xaccAccountGetCommodity(cacb->base_acct)))
acc = cacb->base_acct;
else
{
acc = xaccMallocAccount(cacb->cbw->book);
xaccAccountBeginEdit(acc);
xaccAccountSetType(acc, ACCT_TYPE_EQUITY);
xaccAccountSetName(acc, gnc_commodity_get_mnemonic(cmdty));
xaccAccountSetDescription(acc, gnc_commodity_get_mnemonic(cmdty));
xaccAccountCommitEdit(acc);
}
g_assert(acc);
/* Create the split for the Equity account to balance out
* all the accounts of this. Use the "total".
*/
split = xaccMallocSplit(cacb->cbw->book);
xaccSplitSetParent(split, txn->txn);
xaccAccountBeginEdit(acc);
xaccAccountInsertSplit(acc, split);
xaccSplitSetBaseValue(split, txn->total, cmdty);
xaccAccountCommitEdit(acc);
xaccTransCommitEdit(txn->txn);
}
static void close_accounts_of_type(struct CloseBookWindow* cbw,
Account* acct,
GNCAccountType acct_type)
{
struct CloseAccountsCB cacb;
Account* root_acct;
g_return_if_fail(cbw);
g_return_if_fail(acct);
cacb.cbw = cbw;
cacb.base_acct = acct;
cacb.acct_type = acct_type;
cacb.txns = g_hash_table_new_full(g_direct_hash,
(GEqualFunc)gnc_commodity_equal,
NULL, g_free);
/* Iterate through all accounts and set up the balancing splits */
root_acct = gnc_book_get_root_account(cbw->book);
gnc_account_foreach_descendant(root_acct, close_accounts_cb, &cacb);
/* now iterate through the transactions and handle each currency */
cacb.hash_size = g_hash_table_size(cacb.txns);
if (cacb.hash_size)
g_hash_table_foreach(cacb.txns, (GHFunc)finish_txn_cb, &cacb);
/* Destroy the table, freeing the used memory */
g_hash_table_destroy(cacb.txns);
}
void
gnc_book_close_response_cb(GtkDialog *dialog, gint response, GtkDialog *unused)
{
struct CloseBookWindow* cbw;
Account* income_acct;
Account* expense_acct;
g_return_if_fail(dialog);
cbw = g_object_get_data(G_OBJECT(dialog), "CloseBookWindow");
g_return_if_fail(cbw);
switch (response)
{
case GTK_RESPONSE_HELP:
gnc_gnome_help(HF_HELP, HL_GLOBPREFS);
break;
case GTK_RESPONSE_OK:
cbw->close_date = gnc_date_edit_get_date(GNC_DATE_EDIT(cbw->close_date_widget));
cbw->desc = gtk_entry_get_text(GTK_ENTRY(cbw->desc_widget));
income_acct = gnc_account_sel_get_account(GNC_ACCOUNT_SEL(cbw->income_acct_widget));
expense_acct = gnc_account_sel_get_account(GNC_ACCOUNT_SEL(cbw->expense_acct_widget));
if (!income_acct)
{
gnc_error_dialog(cbw->dialog, "%s",
_("Please select an Equity account to hold the total Period Income."));
break;
}
if (!expense_acct)
{
gnc_error_dialog(cbw->dialog, "%s",
_("Please select an Equity account to hold the total Period Expense."));
break;
}
close_accounts_of_type(cbw, income_acct, ACCT_TYPE_INCOME);
close_accounts_of_type(cbw, expense_acct, ACCT_TYPE_EXPENSE);
/* FALLTHROUGH */
default:
gtk_widget_destroy(GTK_WIDGET(dialog));
break;
}
}
void gnc_ui_close_book (QofBook* book)
{
struct CloseBookWindow *cbw;
GladeXML* xml;
GtkWidget* box;
GList* equity_list = NULL;
g_return_if_fail(book);
cbw = g_new0(struct CloseBookWindow, 1);
g_return_if_fail(cbw);
cbw->book = book;
/* Open the dialog */
xml = gnc_glade_xml_new("dialog-book-close.glade", "Close Book");
cbw->dialog = glade_xml_get_widget(xml, "Close Book");
/* close date */
box = glade_xml_get_widget(xml, "date_box");
cbw->close_date_widget = gnc_date_edit_new(time(NULL), FALSE, FALSE);
gtk_box_pack_start(GTK_BOX(box), cbw->close_date_widget, TRUE, TRUE, 0);
/* income acct */
equity_list = g_list_prepend(equity_list, GINT_TO_POINTER(ACCT_TYPE_EQUITY));
box = glade_xml_get_widget(xml, "income_acct_box");
cbw->income_acct_widget = gnc_account_sel_new();
gnc_account_sel_set_acct_filters(GNC_ACCOUNT_SEL(cbw->income_acct_widget),
equity_list);
gnc_account_sel_set_new_account_ability(GNC_ACCOUNT_SEL(cbw->income_acct_widget), TRUE);
gtk_box_pack_start(GTK_BOX(box), cbw->income_acct_widget, TRUE, TRUE, 0);
/* expense acct */
box = glade_xml_get_widget(xml, "expense_acct_box");
cbw->expense_acct_widget = gnc_account_sel_new();
gnc_account_sel_set_acct_filters(GNC_ACCOUNT_SEL(cbw->expense_acct_widget),
equity_list);
gnc_account_sel_set_new_account_ability(GNC_ACCOUNT_SEL(cbw->expense_acct_widget), TRUE);
gtk_box_pack_start(GTK_BOX(box), cbw->expense_acct_widget, TRUE, TRUE, 0);
/* desc */
cbw->desc_widget = glade_xml_get_widget(xml, "desc_entry");
/* Autoconnect signals */
glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func,
cbw->dialog);
/* Clean up the xml data structure when the dialog is destroyed */
g_object_set_data_full(G_OBJECT(cbw->dialog), "dialog-book-close.glade",
xml, g_object_unref);
g_object_set_data_full(G_OBJECT(cbw->dialog), "CloseBookWindow", cbw,
g_free);
/* Run the dialog */
gtk_widget_show_all(cbw->dialog);
g_list_free(equity_list);
}

View File

@ -0,0 +1,49 @@
/********************************************************************\
* dialog-book-close.h -- dialog for helping the user close the *
* book at the end of the year by adding *
* zero-izing splits to all Income and *
* Expense accounts *
* *
* Copyright (C) 2007-8 Derek Atkins <derek@ihtfp.com> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, 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 *
\********************************************************************/
#ifndef DIALOG_BOOK_CLOSE_H
#define DIALOG_BOOK_CLOSE_H
/** @addtogroup GUI
@{ */
/** @file dialog-book-close.h
*
* This file contains the functions to present a GUI to select
* a book closing date and accounts into which to close the
* Income and Expense accounts.
*/
/** Create and run the dialog to close the book.
*
* @param book This parameter specifies the book whose data
* will be closed.
*/
void gnc_ui_close_book (QofBook* book);
/** @} */
#endif /* DIALOG_BOOK_CLOSE_H */

View File

@ -1,6 +1,7 @@
gladedir = $(GNC_GLADE_DIR)
glade_DATA = \
commodity.glade \
dialog-book-close.glade \
dialog-query-list.glade \
dialog-reset-warnings.glade \
druid-provider-multifile.glade \

View File

@ -0,0 +1,293 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkDialog" id="Close Book">
<property name="visible">True</property>
<property name="title" translatable="yes">Close Book</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<property name="has_separator">True</property>
<signal name="response" handler="gnc_book_close_response_cb" last_modification_time="Mon, 24 Dec 2007 03:23:33 GMT"/>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="helpbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-11</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="cancelbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-6</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-5</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="n_rows">4</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Closing Date:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Income Total:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">Expense Total:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="date_box">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="income_acct_box">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="expense_acct_box">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">Description:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="desc_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">•</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -37,7 +37,9 @@
#include <string.h>
#include "gnc-plugin-basic-commands.h"
#include "gnc-ui-util.h"
#include "dialog-book-close.h"
#include "dialog-chart-export.h"
#include "dialog-fincalc.h"
#include "dialog-find-transactions.h"
@ -76,6 +78,7 @@ static void gnc_main_window_cmd_actions_scheduled_transaction_editor (GtkAction
static void gnc_main_window_cmd_actions_since_last_run (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_actions_close_books (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_tools_financial_calculator (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_tools_close_book (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_tools_find_transactions (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_tools_price_editor (GtkAction *action, GncMainWindowActionData *data);
static void gnc_main_window_cmd_tools_commodity_editor (GtkAction *action, GncMainWindowActionData *data);
@ -157,6 +160,9 @@ static GtkActionEntry gnc_plugin_actions [] = {
{ "ToolsFinancialCalculatorAction", NULL, N_("_Financial Calculator"), NULL,
N_("Use the financial calculator"),
G_CALLBACK (gnc_main_window_cmd_tools_financial_calculator) },
{ "ToolsBookCloseAction", NULL, N_("_Close Book"), NULL,
N_("Close the Book at the end of the Period"),
G_CALLBACK (gnc_main_window_cmd_tools_close_book) },
/* Help menu */
@ -527,6 +533,12 @@ gnc_main_window_cmd_tools_financial_calculator (GtkAction *action, GncMainWindow
gnc_ui_fincalc_dialog_create();
}
static void
gnc_main_window_cmd_tools_close_book (GtkAction *action, GncMainWindowActionData *data)
{
gnc_ui_close_book(gnc_get_current_book());
}
static void
gnc_main_window_cmd_tools_find_transactions (GtkAction *action, GncMainWindowActionData *data)
{

View File

@ -59,6 +59,7 @@
<menuitem name="ToolsPriceEditor" action="ToolsPriceEditorAction"/>
<menuitem name="ToolsCommodityEditor" action="ToolsCommodityEditorAction"/>
<menuitem name="ToolsFinancialCalculator" action="ToolsFinancialCalculatorAction"/>
<menuitem name="ToolsBookClose" action="ToolsBookCloseAction"/>
</placeholder>
</menu>