updates from Rob Browning

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@886 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-06-15 05:06:14 +00:00
parent f17dc96166
commit e3facf3f20
7 changed files with 1241 additions and 53 deletions

View File

@ -42,7 +42,8 @@ OTHER_OBJS := ../obj/gnome/*.o ../engine/obj/*.o ../register/obj/gnome/*.o
######################################################################
# See Makefile.common for information about these variables.
GNOME_SRCS := main.c MainWindow.c MenuBar.c RegWindow.c Dialogs.c
GNOME_SRCS := main.c MainWindow.c MenuBar.c RegWindow.c Dialogs.c xtutil.c \
RecnWindow.c
# AccWindow.c AccountMenu.c AdjBWindow.c \
# BuildMenu.c Destroy.c FileBox.c HelpWindow.c \
# RecnWindow.c RegWindow.c Reports.c TextBox.c \

631
src/gnome/RecnWindow.c Normal file
View File

@ -0,0 +1,631 @@
/********************************************************************\
* RecnWindow.c -- the reconcile window *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#define _GNU_SOURCE
#include <stdio.h>
#include <gnome.h>
#include "config.h"
#include "Account.h"
#include "date.h"
#include "Group.h"
#include "RecnWindow.h"
#include "RegWindow.h"
#include "MainWindow.h"
#include "messages.h"
#include "util.h"
//#include "xtutil.h"
/** STRUCTS *********************************************************/
struct _RecnWindow
{
Account *acc; /* The account that we are reconciling */
double ddiff; /* The amount to reconcile */
GtkWidget *dialog; /* The reconcile window dialog */
GtkWidget *difference; /* Text field, amount left to reconcile */
GtkWidget *totDebit; /* Text field, total debit reconciled */
GtkWidget *totCredit; /* Text field, total credit reconciled */
GtkWidget *debit; /* Debit matrix show unreconciled debit */
GtkWidget *credit; /* Credit matrix, shows credits... */
char * symbol; /* Currency symbol or 's' for shares */
};
/** PROTOTYPES ******************************************************/
static void recnRecalculateBalance( RecnWindow *recnData );
static void recnClose(GtkWidget *w, gpointer data);
static void recnOkCB(GtkWidget *w, gpointer data);
static void recnCancelCB(GtkWidget *w, gpointer data);
static void recnCB(GtkWidget *w, gpointer data);
/** GLOBALS *********************************************************/
static RecnWindow **recnList = NULL;
/********************************************************************/
/********************************************************************\
* recnRefresh *
* refreshes the transactions in the reconcile window *
* *
* Args: recnData -- the reconcile window to refresh *
* Return: none *
\********************************************************************/
void
recnRefresh(Account *acc)
{
int i;
Split *split;
RecnWindow *recnData;
GList *debit_items = NULL;
GList *credit_items = NULL;
FIND_IN_LIST (RecnWindow, recnList, acc, acc, recnData);
if(!recnData) return;
/* Build lists of the non-reconciled transactions */
i=0;
split = xaccAccountGetSplit(acc, i);
while(split)
{
char *item_str = NULL;
Transaction *trans = xaccSplitGetParent (split);
const char split_recn = xaccSplitGetReconcile(split);
if( YREC != split_recn)
{
double themount;
int acc_type;
/* for stock accounts, show share quantity,
* not currency amount */
acc_type = xaccAccountGetType (acc);
if((STOCK == acc_type) || (MUTUAL == acc_type)) {
themount = xaccSplitGetShareAmount (split);
} else {
themount = xaccSplitGetValue (split);
}
asprintf(&item_str, "%c %s %s %s %.2f",
split_recn,
xaccTransGetNum(trans),
xaccTransGetDateStr(trans),
xaccTransGetDescription(trans),
DABS(themount));
{
GtkWidget *list_item = gtk_list_item_new();
GtkWidget *check_button = gtk_check_button_new_with_label(item_str);
gtk_signal_connect(GTK_OBJECT(check_button), "toggled",
recnCB, (gpointer) recnData);
gtk_container_add(GTK_CONTAINER(list_item), check_button);
gtk_widget_show(list_item);
gtk_widget_show(check_button);
gtk_object_set_user_data(GTK_OBJECT(check_button), (gpointer) split);
if(themount < 0)
{
fprintf(stderr, "Adding debit: %s\n", item_str);
debit_items = g_list_append(debit_items, (gpointer) list_item);
} else {
fprintf(stderr, "Adding credit: %s\n", item_str);
credit_items = g_list_append(credit_items, (gpointer) list_item);
}
free(item_str);
}
}
i++;
split = xaccAccountGetSplit (acc, i);
}
/* NOTE: an improvement of the current design would be to use the
* user-data in the rows to detect where transactions need
* to be inserted/delete, instead of deleting and re-inserting
* all the transactions! */
/* Delete all the entries in the debit and credit matrices */
gtk_list_clear_items(GTK_LIST(recnData->debit), 0, -1);
gtk_list_clear_items(GTK_LIST(recnData->credit), 0, -1);
/* the gtk list becomes the owner of the item lists, so don't free */
gtk_list_append_items(GTK_LIST(recnData->debit), debit_items);
gtk_list_append_items(GTK_LIST(recnData->credit), credit_items);
recnRecalculateBalance(recnData);
}
static void
recn_recalc_share_balance_helper(gpointer item, gpointer data) {
double *total = (double *) data;
GtkListItem *li = GTK_LIST_ITEM(item);
GtkCheckButton *checkbutton = GTK_CHECK_BUTTON(li->item.bin.child);
Split *split = gtk_object_get_user_data(GTK_OBJECT(checkbutton));
const char recn = xaccSplitGetReconcile(split);
if(GTK_TOGGLE_BUTTON(checkbutton)->active) {
*total += xaccSplitGetShareAmount(split);
}
}
static void
recn_recalc_non_share_balance_helper(gpointer item, gpointer data) {
double *total = (double *) data;
GtkListItem *li = GTK_LIST_ITEM(item);
GtkCheckButton *checkbutton = GTK_CHECK_BUTTON(li->item.bin.child);
Split *split = gtk_object_get_user_data(GTK_OBJECT(checkbutton));
const char recn = xaccSplitGetReconcile(split);
if(GTK_TOGGLE_BUTTON(checkbutton)->active) {
*total += xaccSplitGetValue(split);
}
}
/********************************************************************\
* recnRecalculateBalance *
* refreshes the balances in the reconcile window *
* *
* Args: recnData -- the reconcile window to refresh *
* Return: none *
\********************************************************************/
static void
recnRecalculateBalance(RecnWindow *recnData)
{
Account *acc = recnData ->acc;
char *amt;
double ddebit = 0.0;
double dcredit = 0.0;
double ddiff = 0.0;
short shrs = 0;
int acc_type;
acc_type = xaccAccountGetType (acc);
if ((STOCK == acc_type) || (MUTUAL == acc_type)) shrs = 1;
/* Calculate the total debit: */
ddebit = 0.0;
{
const GFunc func = (shrs) ?
(GFunc) recn_recalc_share_balance_helper :
(GFunc) recn_recalc_non_share_balance_helper;
/* Calculate the total debit and credit */
g_list_foreach(GTK_LIST(recnData->debit)->children, func, &ddebit);
g_list_foreach(GTK_LIST(recnData->credit)->children, func, &dcredit);
}
shrs *= PRTSHR;
shrs |= PRTSYM;
/* Update the difference field, and the total fields */
amt = xaccPrintAmount(DABS(ddebit), shrs);
{
char *str = NULL;
asprintf(&str, "%s %s", DEBITS_C_STR, amt);
gtk_frame_set_label(GTK_FRAME(recnData->totDebit), str);
free(str);
}
amt = xaccPrintAmount(dcredit, shrs);
{
char *str = NULL;
asprintf(&str, "%s %s", CREDITS_C_STR, amt);
gtk_frame_set_label(GTK_FRAME(recnData->totCredit), str);
free(str);
}
ddiff = recnData->ddiff + dcredit + ddebit;
amt = xaccPrintAmount(ddiff, shrs);
gtk_label_set(GTK_LABEL(recnData->difference), amt);
}
/********************************************************************\
* startRecnWindow: gets the ending balance for reconcile window *
\********************************************************************/
static void
startRecnOkCB(GtkWidget *w, gpointer data)
{
*((int *) data) = 1;
}
static void
startRecnCancelCB(GtkWidget *w, gpointer data)
{
*((int *) data) = 0;
}
/********************************************************************\
* startRecnWindow *
* opens up the window to prompt the user to enter the ending *
* balance from bank statement *
* *
* NOTE: This dialog does not return until the user presses "Ok" *
* or "Cancel" *
* *
* Args: parent - the parent of this window *
* acc - the account to reconcile *
* diff - returns the amount from ending balance field *
* Return: True, if the user presses "Ok", else False *
* Global: app - the app context *
\********************************************************************/
gboolean
startRecnWindow(GtkWidget *parent, Account *acc, double *diff)
{
GtkWidget *dialog;
char * amt;
double dendBalance;
int result;
short shrs = 0;
int acc_type;
char *title = NULL;
setBusyCursor(parent);
/* Get the previous ending balance. Use the published
* account interface for this, since the ending balance
* may have to be adjusted for stock price fluctuations.
*/
dendBalance = xaccAccountGetReconciledBalance(acc);
acc_type = xaccAccountGetType(acc);
if((STOCK == acc_type) || (MUTUAL == acc_type)) shrs = 1;
shrs *= PRTSHR;
shrs |= PRTSYM;
amt = xaccPrintAmount (dendBalance, shrs);
/* Create the dialog box... */
asprintf(&title, "%s: %s", xaccAccountGetName(acc), RECONCILE_STR);
dialog = gnome_dialog_new(title,
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
GNOME_STOCK_BUTTON_HELP,
NULL);
free(title);
gnome_dialog_set_modal(GNOME_DIALOG(dialog));
gnome_dialog_set_default(GNOME_DIALOG(dialog), 1);
gnome_dialog_set_close(GNOME_DIALOG(dialog), FALSE);
gnome_dialog_close_hides(GNOME_DIALOG(dialog), FALSE);
gnome_dialog_button_connect(GNOME_DIALOG(dialog), 0,
GTK_SIGNAL_FUNC(startRecnOkCB),
(gpointer) &result);
gnome_dialog_button_connect(GNOME_DIALOG(dialog), 1,
GTK_SIGNAL_FUNC(startRecnCancelCB),
(gpointer) &result);
fprintf(stderr, "Not implemented: helpMenubarCB\n");
/*
gnome_dialog_button_connect(GNOME_DIALOG(dialog), 2,
GTK_SIGNAL_FUNC(helpMenubarCB),
(gpointer) HMB_RECNWIN);
*/
{
GtkWidget *main_area = gtk_hbox_new(TRUE, 0);
GtkWidget *left_column = gtk_vbox_new(FALSE, 0);
GtkWidget *right_column = gtk_vbox_new(FALSE, 0);
GtkWidget *prev_title = gtk_label_new(PREV_BALN_C_STR);
GtkWidget *end_title = gtk_label_new(END_BALN_C_STR);
GtkWidget *prev_value = gtk_label_new(amt);
GtkWidget *end_value = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dialog)->vbox), main_area,
TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(main_area), left_column, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(main_area), right_column, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(left_column), prev_title, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(left_column), end_title, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(right_column), prev_value, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(right_column), end_value, TRUE, TRUE, 0);
gtk_widget_show(main_area);
gtk_widget_show(left_column);
gtk_widget_show(right_column);
gtk_widget_show(prev_title);
gtk_widget_show(end_title);
gtk_widget_show(prev_value);
gtk_widget_show(end_value);
gtk_widget_show(dialog);
unsetBusyCursor(parent);
result = -1;
while(result == -1) {
while(result == -1) {
gtk_main_iteration();
}
/* Get the amount from the "end-balance" field */
{
gchar *str = gtk_entry_get_text(GTK_ENTRY(end_value));
double val=0.0;
if(result == 1) {
if(sscanf(str, "%lf", &val ) == 1) {
*diff = dendBalance - val;
} else {
errorBox(dialog, "Ending balance must be a number.");
result = -1;
}
}
}
}
gnome_dialog_close(dialog);
}
fprintf(stderr, "Returning result: %d\n", result);
return result;
}
/********************************************************************\
* recnWindow *
* opens up the window to reconcile an account *
* *
* Args: parent - the parent of this window *
* account - the account to reconcile *
* Return: recnData - the instance of this RecnWindow *
\********************************************************************/
RecnWindow *
recnWindow(GtkWidget *parent, Account *acc)
{
int position;
RecnWindow *recnData;
double ddiff;
gchar *title = NULL;
/* Popup a little window to prompt the user to enter the
* ending balance for his/her bank statement */
if(!startRecnWindow(parent,acc,&ddiff) ) {
return NULL;
}
FETCH_FROM_LIST(RecnWindow, recnList, acc, acc, recnData);
setBusyCursor(parent);
recnData->ddiff = ddiff;
asprintf(&title, "%s: %s", xaccAccountGetName (acc), RECONCILE_STR);
recnData->dialog = gnome_dialog_new(title,
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
GNOME_STOCK_BUTTON_HELP,
NULL);
free(title);
/* here we connect the "destroy" event to a signal handler.
* This event occurs when we call gtk_widget_destroy() on the window,
* or if we return 'FALSE' in the "delete_event" callback. */
gtk_signal_connect (GTK_OBJECT (recnData->dialog), "destroy",
GTK_SIGNAL_FUNC(recnClose), (gpointer) recnData);
gnome_dialog_set_modal(GNOME_DIALOG(recnData->dialog));
gnome_dialog_set_default(GNOME_DIALOG(recnData->dialog), 1);
gnome_dialog_set_close(GNOME_DIALOG(recnData->dialog), FALSE);
gnome_dialog_close_hides(GNOME_DIALOG(recnData->dialog), FALSE);
gnome_dialog_button_connect(GNOME_DIALOG(recnData->dialog), 0,
GTK_SIGNAL_FUNC(recnOkCB),
(gpointer) recnData);
gnome_dialog_button_connect(GNOME_DIALOG(recnData->dialog), 1,
GTK_SIGNAL_FUNC(recnCancelCB),
(gpointer) recnData);
fprintf(stderr, "Not implemented: helpMenubarCB\n");
/*
XtAddCallback( widget, XmNactivateCallback,
helpMenubarCB, (XtPointer)HMB_RECNWIN );
*/
//String labels[] = {"", NUM_STR, DATE_STR, DESC_STR, AMT_STR };
//unsigned char alignments[] = {XmALIGNMENT_CENTER,
// XmALIGNMENT_END,
// XmALIGNMENT_CENTER,
// XmALIGNMENT_BEGINNING,
// XmALIGNMENT_END};
{
GtkWidget *main_area = gtk_vbox_new(FALSE, 0);
GtkWidget *debcred_area = gtk_hbox_new(TRUE, 0);
GtkWidget *debits_frame = gtk_frame_new(DEBITS_C_STR);
GtkWidget *credits_frame = gtk_frame_new(CREDITS_C_STR);
GtkWidget *debits_list = gtk_list_new();
GtkWidget *credits_list = gtk_list_new();
GtkWidget *difference_align = gtk_alignment_new(0.5, 0.5, 0, 0);
GtkWidget *difference_box = gtk_hbox_new(FALSE, 0);
GtkWidget *difference_label = gtk_label_new(DIFF_C_STR);
GtkWidget *difference_value = gtk_label_new("");
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(recnData->dialog)->vbox),
main_area, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(main_area), debcred_area, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(debcred_area), debits_frame, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(debcred_area), credits_frame, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(debits_frame), debits_list);
gtk_container_add(GTK_CONTAINER(credits_frame), credits_list);
gtk_box_pack_end(GTK_BOX(main_area), difference_align, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(difference_align), difference_box);
gtk_box_pack_start(GTK_BOX(difference_box), difference_label,
TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(difference_box), difference_value,
TRUE, TRUE, 0);
recnData->debit = debits_list;
recnData->totDebit = debits_frame;
recnData->credit = credits_list;
recnData->totCredit = credits_frame;
recnData->difference = difference_value;
gtk_widget_show(main_area);
gtk_widget_show(debcred_area);
gtk_widget_show(debits_frame);
gtk_widget_show(credits_frame);
gtk_widget_show(debits_list);
gtk_widget_show(credits_list);
gtk_widget_show(difference_align);
gtk_widget_show(difference_box);
gtk_widget_show(difference_label);
gtk_widget_show(difference_value);
gtk_widget_show(recnData->dialog);
}
/* now that the matices are set up, fill 'em in with transactions: */
recnRefresh (acc);
/* and then refresh the total/difference balance fields: */
recnRecalculateBalance(recnData);
unsetBusyCursor(parent);
return recnData;
}
/********************************************************************\
* Don't delete any structures -- the close callback will handle this *
\********************************************************************/
void
xaccDestroyRecnWindow(Account *acc)
{
RecnWindow *recnData;
FIND_IN_LIST(RecnWindow, recnList, acc, acc, recnData);
if(!recnData) return;
gnome_dialog_close(recnData->dialog);
}
/********************************************************************\
* recnClose *
* frees memory allocated for an recnWindow, and other cleanup *
* stuff *
* *
* Args: mw - the widget that called us *
* cd - recnData - the data struct for this window *
* cb - *
* Return: none *
\********************************************************************/
static void
recnClose(GtkWidget *w, gpointer data)
{
RecnWindow *recnData = (RecnWindow *) data;
Account *acc = recnData->acc;
REMOVE_FROM_LIST (RecnWindow, recnList, acc, acc);
free(recnData);
DEBUG("closed RecnWindow");
}
static void
recn_ok_cb_set_reconciled_helper(gpointer item, gpointer data) {
double *total = (double *) data;
GtkListItem *li = GTK_LIST_ITEM(item);
GtkCheckButton *checkbutton = GTK_CHECK_BUTTON(li->item.bin.child);
Split *split = gtk_object_get_user_data(GTK_OBJECT(checkbutton));
const char recn = xaccSplitGetReconcile(split);
if(GTK_TOGGLE_BUTTON(checkbutton)->active) {
xaccSplitSetReconcile (split, YREC);
}
}
/********************************************************************\
* recnOkCB *
* saves account stuff, when the user clicks "Ok" *
* *
* Args: mw - the widget that called us *
* cd - recnData - the data struct for this window *
* cb - *
* Return: none *
* Global: data *
\********************************************************************/
static void
recnOkCB(GtkWidget *w, gpointer data)
{
RecnWindow *recnData = (RecnWindow *) data;
/* Update the debit and credit transactions reconciled state */
g_list_foreach(GTK_LIST(recnData->debit)->children,
recn_ok_cb_set_reconciled_helper, NULL);
g_list_foreach(GTK_LIST(recnData->credit)->children,
recn_ok_cb_set_reconciled_helper, NULL);
/* refresh the register window */
accRefresh(recnData->acc);
gnome_dialog_close(recnData->dialog);
}
static void
recnCancelCB(GtkWidget *w, gpointer data)
{
RecnWindow *recnData = (RecnWindow *) data;
fprintf(stderr, "X\n");
gnome_dialog_close(recnData->dialog);
fprintf(stderr, "Y\n");
}
/********************************************************************\
* recnCB *
* called whenever the users does anything in the debit/credit *
* matrices *
* *
* Args: mw - the matrix widget that called us *
* cd - recnData - the data struct for this window *
* cb - *
* Return: none *
\********************************************************************/
static void
recnCB(GtkWidget *w, gpointer data)
{
RecnWindow *recnData = (RecnWindow *) data;
/* recalculate the total/difference balance fields: */
recnRecalculateBalance(recnData);
}
/*
Local Variables:
tab-width: 2
indent-tabs-mode: nil
eval: (c-set-style "gnu")
End:
*/

50
src/gnome/RecnWindow.h Normal file
View File

@ -0,0 +1,50 @@
/********************************************************************\
* RecnWindow.h -- the reconcile window *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#ifndef __RECONCILE_H__
#define __RECONCILE_H__
#include <gtk/gtk.h>
#include "config.h"
#include "Account.h"
/** GLOBALS *********************************************************/
/** STRUCTS *********************************************************/
typedef struct _RecnWindow RecnWindow;
/** PROTOTYPES ******************************************************/
void recnRefresh(Account *account);
RecnWindow *recnWindow(GtkWidget *parent, Account *account);
/*
* The xaccDestroyRecnWindow() subroutine can be called from
* anywhere to shut down the Register window. Used primarily when
* destroying the underlying account.
*/
void xaccDestroyRecnWindow(Account *);
#endif

View File

@ -34,6 +34,7 @@
#include "config.h"
#include "Account.h"
#include "AccountP.h"
//#include "AdjBWindow.h"
//#include "BuildMenu.h"
#include "Group.h"
@ -42,7 +43,7 @@
#include "MainWindow.h"
#include "main.h"
#include "messages.h"
//#include "RecnWindow.h"
#include "RecnWindow.h"
#include "RegWindow.h"
#include "Transaction.h"
#include "util.h"
@ -65,7 +66,6 @@ struct _RegWindow {
/* display widgets */
GtkWidget * dialog;
GtkWidget * reg; /* The matrix widget... */
GtkWidget * balance; /* The balance text field */
GtkWidget * record; /* the record transaction button */
};
@ -85,13 +85,14 @@ void regRefresh (RegWindow *regData);
static void closeRegWindow(GtkWidget * mw, gpointer data);
static void startRecnCB(GtkWidget *w, gpointer data);
static void deleteCB(GtkWidget *w, gpointer data);
static void recordCB(GtkWidget *w, gpointer data);
static void cancelCB(GtkWidget *w, gpointer data);
#if 0
static void startRecnCB( GtkWidget * mw, XtPointer cd, XtPointer cb );
static void startAdjBCB( GtkWidget * mw, XtPointer cd, XtPointer cb );
static void recordCB( GtkWidget * mw, XtPointer cd, XtPointer cb );
static void deleteCB( GtkWidget * mw, XtPointer cd, XtPointer cb );
static void cancelCB( GtkWidget * mw, XtPointer cd, XtPointer cb );
#endif
@ -187,9 +188,9 @@ ledgerIsMember (RegWindow *reg, Account * acc) {
\********************************************************************/
RegWindow *
regWindowSimple(Account *acc) {
RegWindow *retval;
RegWindow *retval = (RegWindow *) 1; /* for error case later */
int acc_type;
int reg_type;
int reg_type = 0;
acc_type = xaccAccountGetType (acc);
@ -223,9 +224,14 @@ regWindowSimple(Account *acc) {
case EQUITY:
reg_type = EQUITY_REGISTER;
break;
default:
fprintf(stderr,
"regWindowSimple: Unknown account type (serious error)\n");
retval = NULL;
break;
}
retval = regWindowLedger (acc, NULL, reg_type);
if(retval) retval = regWindowLedger (acc, NULL, reg_type);
return retval;
}
@ -337,11 +343,11 @@ RegWindow *
regWindowLedger(Account *lead_acc, Account **acclist, int ledger_type)
{
RegWindow *regData = NULL;
//GtkWidget * menubar, pane, buttonform, frame, reg, widget;
GtkWidget *reg = NULL;
int position=0;
char *windowname;
//char buf [BUFSIZE];
GtkWidget *register_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *register_vbox = gtk_vbox_new(FALSE, 0);
GtkWidget *table_frame = gtk_frame_new(NULL);
fprintf(stderr, "regWindowLedger(%p, %p, %d)\n",
lead_acc, acclist, ledger_type);
@ -452,13 +458,13 @@ regWindowLedger(Account *lead_acc, Account **acclist, int ledger_type)
switch (regData->type) {
case GENERAL_LEDGER:
case INCOME_LEDGER:
asprintf(&windowname, "%s General Ledger", acc_name);
asprintf(&windowname, "%s (general ledger)", acc_name);
break;
case PORTFOLIO:
asprintf(&windowname, "%s Portfolio", acc_name);
asprintf(&windowname, "%s (portfolio)", acc_name);
break;
default:
asprintf(&windowname, "%s Register", acc_name);
asprintf(&windowname, "%s (register)", acc_name);
break;
}
} else {
@ -467,11 +473,17 @@ regWindowLedger(Account *lead_acc, Account **acclist, int ledger_type)
assert(windowname);
//setBusyCursor(parent);
regData->dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_box_pack_start(GTK_BOX(register_vbox), table_frame, TRUE, TRUE, 0);
regData->dialog = table_frame;
///* Initialize callbacks */
//gtk_signal_connect(GTK_OBJECT(toolBar[exit]), "clicked",
// GTK_SIGNAL_FUNC (file_cmd_quit), NULL);
gtk_window_set_title(GTK_WINDOW(regData->dialog), windowname);
gtk_window_set_title(GTK_WINDOW(register_window), windowname);
/* when the window is given the "delete_event" signal (this is given
* by the window manager (usually the 'close' option, or on the
@ -735,7 +747,56 @@ regWindowLedger(Account *lead_acc, Account **acclist, int ledger_type)
gtk_widget_set_usize(regData->dialog, list_width + 80, 500);
}
gtk_widget_show(regData->dialog);
/* Add controls at the bottom. */
{
GtkWidget *hb = gtk_handle_box_new();
GtkWidget *toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
GTK_TOOLBAR_TEXT);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
"Record",
"Commit modifications to "
"the current transaction.",
"Commit modifications to "
"the current transaction.",
NULL,
GTK_SIGNAL_FUNC(recordCB), (gpointer) regData);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
"Cancel",
"Cancel modifications to "
"the current transaction.",
"Cancel modifications to "
"the current transaction.",
NULL,
GTK_SIGNAL_FUNC(cancelCB), (gpointer) regData);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
"Delete",
"Delete the current transaction.",
"Delete the current transaction.",
NULL,
GTK_SIGNAL_FUNC(deleteCB), (gpointer) regData);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
"Reconcile",
"Reconcile transactions with bank statement.",
"Reconcile transactions with bank statement.",
NULL,
GTK_SIGNAL_FUNC(startRecnCB),
(gpointer) regData);
gtk_box_pack_end(GTK_BOX(register_vbox), hb, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(hb), toolbar);
gtk_widget_show(toolbar);
gtk_widget_show(hb);
}
gtk_container_add(GTK_CONTAINER(register_window), register_vbox);
gtk_widget_show(table_frame);
gtk_widget_show(register_vbox);
gtk_widget_show(register_window);
if(windowname) free(windowname);
return regData;
}
@ -760,23 +821,34 @@ void regRefresh (RegWindow *regData)
xaccAccountGetSplitList (regData->leader),
regData->leader);
xaccAccountRecomputeBalance(regData->leader);
/* hack alert -- this is incorrect for multi-account ledgers */
if( NULL != regData->balance ) {
char buf [BUFSIZE];
char * amt;
double prt_balance, prt_clearedBalance;
if( NULL != regData->dialog ) {
char *reglabel = NULL;
char *balance_str, *cleared_balance_str, *reconciled_balance_str;
double prt_balance, prt_clearedBalance, prt_reconciledBalance;
prt_balance = xaccAccountGetBalance (regData->leader);
prt_clearedBalance = xaccAccountGetClearedBalance (regData->leader);
amt = xaccPrintAmount (prt_balance, PRTSYM);
strcpy (buf, amt);
strcat (buf, "\n");
amt = xaccPrintAmount (prt_clearedBalance, PRTSYM);
strcat (buf, amt);
//XmTextSetString( regData->balance, buf );
prt_reconciledBalance =
xaccAccountGetReconciledBalance (regData->leader);
balance_str = strdup(xaccPrintAmount(prt_balance, PRTSYM));
cleared_balance_str = strdup(xaccPrintAmount(prt_clearedBalance, PRTSYM));
reconciled_balance_str =
strdup(xaccPrintAmount(prt_reconciledBalance, PRTSYM));
asprintf(&reglabel, "%s (Reconciled: %s) (Cleared: %s) (Final: %s)",
xaccAccountGetName(regData->leader),
reconciled_balance_str,
cleared_balance_str,
balance_str
);
gtk_frame_set_label(GTK_FRAME(regData->dialog), reglabel);
free(balance_str);
free(cleared_balance_str);
free(reconciled_balance_str);
free(reglabel);
}
}
@ -888,6 +960,8 @@ closeRegWindow( GtkWidget * mw, gpointer data)
RegWindow *regData = (RegWindow *)data;
Account *acc = regData->leader;
fprintf(stderr, "Closing register safely\n");
/* Save any unsaved changes */
xaccSaveRegEntry (regData->ledger);
@ -933,6 +1007,8 @@ startAdjBCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
adjBWindow( toplevel, acc );
}
#endif
/********************************************************************\
* startRecnCB -- open up the reconcile window... called from *
* menubar. *
@ -943,9 +1019,9 @@ startAdjBCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
* Return: none *
\********************************************************************/
static void
startRecnCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
startRecnCB(GtkWidget * w, gpointer data)
{
RegWindow *regData = (RegWindow *)cd;
RegWindow *regData = (RegWindow *) data;
Account *acc;
/* Must have number of accounts be one. If not one,
@ -958,7 +1034,7 @@ startRecnCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
if (1 != regData->numAcc) return;
acc = regData->blackacc[0];
}
recnWindow( toplevel, acc );
recnWindow(w, acc);
}
/********************************************************************\
@ -970,9 +1046,9 @@ startRecnCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
* Return: none *
\********************************************************************/
static void
recordCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
recordCB( GtkWidget *w, gpointer data)
{
RegWindow *regData = (RegWindow *)cd;
RegWindow *regData = (RegWindow *) data;
xaccSaveRegEntry (regData->ledger);
}
@ -987,9 +1063,9 @@ recordCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
\********************************************************************/
static void
deleteCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
deleteCB(GtkWidget *widget, gpointer data)
{
RegWindow *regData = (RegWindow *)cd;
RegWindow *regData = (RegWindow *) data;
Split * split;
Transaction *trans;
char buf[BUFSIZE];
@ -1004,7 +1080,7 @@ deleteCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
* permanent damage */
trans = xaccSplitGetParent (split);
sprintf (buf, TRANS_DEL_MSG, xaccTransGetDescription (trans));
if (!verifyBox (toplevel, buf)) return;
if (!verifyBox(toplevel, buf)) return;
/* make a copy of all of the accounts that will be
* affected by this deletion, so that we can update
@ -1036,17 +1112,16 @@ deleteCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
* Return: none *
\********************************************************************/
static void
cancelCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
cancelCB( GtkWidget *w, gpointer data)
{
RegWindow *regData = (RegWindow *)cd;
Split * split;
RegWindow *regData = (RegWindow *) data;
Split * split;
/* when cancelling edits, reload the cursor from the transaction */
split = xaccGetCurrentSplit (regData->ledger);
xaccLoadRegEntry (regData->ledger, split);
xaccRefreshTableGUI (regData->ledger->table);
}
#endif /* 0 */
/************************** END OF FILE *************************/
@ -1054,8 +1129,6 @@ cancelCB( GtkWidget * mw, XtPointer cd, XtPointer cb )
Local Variables:
tab-width: 2
indent-tabs-mode: nil
mode: c
c-indentation-style: gnu
eval: (c-set-offset 'substatement-open 0)
eval: (c-set-style "gnu")
End:
*/

View File

@ -111,6 +111,36 @@ void file_cmd_quit (GtkWidget *widget, gpointer data)
gtk_main_quit();
}
static void
foreach_split_in_group(AccountGroup *g, void (*f)(Split *)) {
const int num_accts = xaccGroupGetNumAccounts(g);
Account **acc_list = (Account **) _malloc((num_accts + 1) *
sizeof(Account *));
Account *acct;
int i, pos;
Split **splits;
Split **split_cursor;
for(i = 0, pos = 0; i < num_accts; i++) {
acct = xaccGetAccountFromID(g, i);
if(acct) {
acc_list[pos++] = acct;
}
}
acc_list[pos] = NULL;
splits = accListGetSortedSplits(acc_list);
split_cursor = splits;
while(*split_cursor) {
f(*split_cursor);
split_cursor++;
}
_free(splits);
_free(acc_list);
}
/********************************************************************\
* main *
* the entry point for the program... sets up the top level widget *
@ -172,7 +202,7 @@ main( int argc, char *argv[] )
/* load the accounts data from datafile*/
topgroup = xaccReadAccountGroup (datafile);
if ( topgroup == NULL )
{
GtkWidget *dialog;
@ -224,8 +254,8 @@ prepare_app()
Local Variables:
tab-width: 2
indent-tabs-mode: nil
mode: c-mode
mode: c
c-indentation-style: gnu
eval: (c-set-offset 'block-open '-)
eval: (c-set-offset 'substatement-open 0)
End:
*/

353
src/gnome/xtutil.c Normal file
View File

@ -0,0 +1,353 @@
/********************************************************************\
* util.c -- utility functions that are used everywhere else for *
* xacc (X-Accountant) *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#include "config.h"
#include "messages.h"
#include "util.h"
#include "xtutil.h"
#if 0
/** GLOBALS *********************************************************/
extern XtAppContext app;
extern int realized;
/********************************************************************\
* dateCB -- ensures the data the user enters in the date field *
* is in a valid format. *
* *
* Args: mw - the widget that called us *
* cd - *
* cb - the callback struct *
* Return: none *
\********************************************************************/
void
dateCB( Widget mw, XtPointer cd, XtPointer cb )
{
XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)cb;
char input;
/* TODO: ??? add support for date field accelerator keys!! */
if( cbs->text->ptr != NULL )
{
input = (cbs->text->ptr)[0];
switch( input )
{
case '/':
case '.':
case '-':
/* Make sure that there is at most two separators */
{
String str = XmTextGetString(mw);
int i,count=0;
for( i=0; str[i] != '\0'; i++ )
if( str[i] == input )
count++;
if( count >= 2 )
cbs->doit = False;
}
break;
case 0x0:
/* if delete key (for example) is hit, then input string */
/* will be an empty string. In such a case, allow the input */
cbs->doit = True;
break;
default:
/* only accept the input if it is a number */
cbs->doit = isNum(input);
}
}
}
/********************************************************************\
* amountCB -- ensures the data entered in the amount field is in *
* a valid format. *
* *
* Args: mw - the widget that called us *
* cd - *
* cb - the callback struct *
* Return: none *
\********************************************************************/
void
amountCB(GtkWidget *w, gpointer data)
{
XmTextVerifyCallbackStruct *cbs = (XmTextVerifyCallbackStruct *)cb;
char input;
if( cbs->text->ptr != NULL )
{
input = (cbs->text->ptr)[0];
switch( input )
{
case '.':
/* Make sure that there is only one '.' */
{
String str = XmTextGetString(mw);
int i,count=0;
for( i=0; str[i] != '\0'; i++ )
if( str[i] == '.' )
count++;
if( count >= 1 )
cbs->doit = False;
}
break;
default:
/* only accept the input if it is a number */
cbs->doit = isNum(input);
}
}
}
/********************************************************************\
* noeditCB *
* makes an Xbae matrix non-editable *
* *
* Args: mw - the widget that called us *
* cd - *
* cb - *
* Return: none *
\********************************************************************/
void
noeditCB( Widget mw, XtPointer cd, XtPointer cb )
{
XbaeMatrixEnterCellCallbackStruct *cbs =
(XbaeMatrixEnterCellCallbackStruct * )cb;
cbs->doit = False;
}
/********************************************************************\
* destroyShellCB *
* a callback to destroy a widget (cd, not w, because we want to *
* destroy a window, not a button!) *
* *
* Args: mw - the widget that called us *
* cd - the widget to destroy *
* cb - *
* Return: none *
\********************************************************************/
void
destroyShellCB( Widget w, XtPointer cd, XtPointer cb )
{
Widget window = (Widget)cd;
XtDestroyWidget(window);
}
#endif
/********************************************************************\
* setBusyCursor *
* sets the cursor to the busy watch *
* *
* Args: w - the widget over which to make cursor busy *
* Return: none *
\********************************************************************/
void
setBusyCursor(GtkWidget *w)
{
fprintf(stderr, "Unimplemented: setBusyCursor\n");
#if 0
if( realized )
{
static Cursor watch = 0;
if( watch == 0 )
watch = XCreateFontCursor(XtDisplay(w),XC_watch);
XDefineCursor(XtDisplay(w),XtWindow(w),watch);
XmUpdateDisplay(w);
}
#endif
}
/********************************************************************\
* unsetBusyCursor *
* sets the cursor to the default cursor *
* *
* Args: w - the widget over which to make cursor normal *
* Return: none *
\********************************************************************/
void
unsetBusyCursor(GtkWidget *w)
{
fprintf(stderr, "Unimplemented: unsetBusyCursor\n");
# if 0
if( realized )
{
XUndefineCursor(XtDisplay(w),XtWindow(w));
XmUpdateDisplay(w);
}
# endif
}
/********************************************************************\
**************** VERIFYBOX STUFF ***********************************
\********************************************************************/
struct verify_callback_data {
gboolean finished;
gboolean value;
};
static void
verify_cb_yes(GtkWidget *w, gpointer data) {
struct verify_callback_data *result = (struct verify_callback_data *) data;
result->value = TRUE;
result->finished = TRUE;
}
static void
verify_cb_no(GtkWidget *w, gpointer data) {
struct verify_callback_data *result = (struct verify_callback_data *) data;
result->value = FALSE;
result->finished = TRUE;
}
/********************************************************************\
* verifyBox *
* display a message, and asks the user to press "Ok" or "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *
* Args: parent - the parent widget *
* text - the message to display *
* Return: none *
\********************************************************************/
gboolean
verifyBox(GtkWidget *parent, const char *text)
{
GtkWidget *verify_box = NULL;
GtkWidget *verify_text = NULL;
struct verify_callback_data result;
verify_box = gnome_dialog_new(text,
GNOME_STOCK_BUTTON_YES,
GNOME_STOCK_BUTTON_NO,
NULL);
gnome_dialog_set_modal(GNOME_DIALOG(verify_box));
gnome_dialog_set_default(GNOME_DIALOG(verify_box), 1);
gnome_dialog_set_close(GNOME_DIALOG(verify_box), TRUE);
gnome_dialog_button_connect(GNOME_DIALOG(verify_box), 0,
GTK_SIGNAL_FUNC(verify_cb_yes),
(gpointer) &result);
gnome_dialog_button_connect(GNOME_DIALOG(verify_box), 1,
GTK_SIGNAL_FUNC(verify_cb_no),
(gpointer) &result);
verify_text = gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(verify_box)->vbox),
verify_text, FALSE, FALSE, 0);
gtk_widget_show(verify_text);
result.finished = FALSE;
gtk_widget_show(verify_box);
setBusyCursor(parent);
while(!result.finished) {
gtk_main_iteration();
}
unsetBusyCursor(parent);
//gnome_dialog_close(GNOME_DIALOG(verify_box));
return result.value;
}
/********************************************************************\
*********************************************************************
\********************************************************************/
static void
error_cb_ok(GtkWidget *w, gpointer data) {
*((gboolean *) data) = TRUE;
}
/********************************************************************\
* errorBox *
* displays an error dialog box *
* *
* Args: w - the parent widget *
* message - the error message to display *
* Return: none *
\********************************************************************/
void
errorBox(GtkWidget *parent, const char *message )
{
GtkWidget *error_box = NULL;
GtkWidget *error_text = NULL;
gboolean finished = FALSE;
error_box = gnome_dialog_new("GnuCash: error",
GNOME_STOCK_BUTTON_OK,
NULL);
gnome_dialog_button_connect(GNOME_DIALOG(error_box), 0,
GTK_SIGNAL_FUNC(error_cb_ok),
(gpointer) &finished);
gnome_dialog_set_modal(GNOME_DIALOG(error_box));
gnome_dialog_set_default(GNOME_DIALOG(error_box), 0);
gnome_dialog_set_close(GNOME_DIALOG(error_box), TRUE);
error_text = gtk_label_new(message);
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(error_box)->vbox),
error_text, FALSE, FALSE, 0);
gtk_widget_show(error_text);
gtk_widget_show(error_box);
setBusyCursor(parent);
while(!finished) {
gtk_main_iteration();
}
unsetBusyCursor(parent);
}
/************************* END OF FILE ******************************\
\********************************************************************/
/*
Local Variables:
tab-width: 2
indent-tabs-mode: nil
eval: (c-set-style "gnu")
End:
*/

50
src/gnome/xtutil.h Normal file
View File

@ -0,0 +1,50 @@
/********************************************************************\
* xtutil.h -- utility functions that are used everywhere else for *
* xacc (X-Accountant) *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#ifndef __XACC_XT_UTIL_H__
#define __XACC_XT_UTIL_H__
#include <gnome.h>
#include <stdlib.h>
#include "config.h"
/** PROTOTYPES ******************************************************/
#if 0
void dateCB( Widget mw, XtPointer cd, XtPointer cb );
void amountCB( Widget mw, XtPointer cd, XtPointer cb );
void noeditCB( Widget mw, XtPointer cd, XtPointer cb );
void destroyShellCB( Widget w, XtPointer cd, XtPointer cb );
void setBusyCursor( GtkWidget *w );
void unsetBusyCursor( GtkWidget *w );
void errorBox( GtkWidget *parent, const char *message );
#endif
gboolean verifyBox( GtkWidget *parent, const char *text );
#endif /* __XACC_XT_UTIL_H__ */