*** empty log message ***

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2073 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-03-12 11:07:49 +00:00
parent 1fc99b4ef2
commit cb4ea32bfa
10 changed files with 386 additions and 38 deletions

View File

@ -255,6 +255,67 @@ xaccSRSetReverseBalanceCallback(SRReverseBalanceCallback callback)
}
/* copies basic split values from 'from' split to 'to' split.
* doesn't copy reconciled flag, or open the parent transactions
* for editing. Does *not* insert the 'to' split into an account!! */
static void
gnc_copy_split(Split *from, Split *to)
{
if ((from == NULL) || (to == NULL))
return;
xaccSplitSetMemo(to, xaccSplitGetMemo(from));
xaccSplitSetAction(to, xaccSplitGetAction(from));
xaccSplitSetDocref(to, xaccSplitGetDocref(from));
xaccSplitSetSharePriceAndAmount(to,
xaccSplitGetSharePrice(from),
xaccSplitGetShareAmount(from));
}
/* copies the basic transaction values and the splits from the
* 'from' trans to the 'to' trans. Any existing splits in the
* 'to' trans are deleted. Does *not* open the 'to' trans for
* editing!!! Splits are copied using gnc_copy_split above.
* The new splits will be in exactly the same order as in
* the 'from' transaction. */
static void
gnc_copy_trans(Transaction *from, Transaction *to)
{
Split *from_split, *to_split;
Timespec timespec;
int num_splits;
int i;
if ((from == NULL) || (to == NULL))
return;
/* remove the old splits */
to_split = xaccTransGetSplit(to, 0);
while (to_split != NULL)
{
xaccSplitDestroy(to_split);
to_split = xaccTransGetSplit(to, 0);
}
/* add in the new splits */
num_splits = xaccTransCountSplits(from);
for (i = 0; i < num_splits; i++)
{
from_split = xaccTransGetSplit(from, i);
to_split = xaccMallocSplit();
gnc_copy_split(from_split, to_split);
xaccTransAppendSplit(to, to_split);
}
/* now do the transaction-specific values */
xaccTransGetDateTS(from, &timespec);
xaccTransSetDateTS(to, &timespec);
xaccTransSetDescription(to, xaccTransGetDescription(from));
xaccTransSetDocref(to, xaccTransGetDocref(from));
}
/* ======================================================== */
/* this callback gets called when the user clicks on the gui
* in such a way as to leave the current transaction, and to
@ -583,6 +644,144 @@ xaccSRGetSplitRowCol (SplitRegister *reg, Split *split,
/* ======================================================== */
Split *
xaccSRDuplicateCurrent (SplitRegister *reg)
{
SRInfo *info = xaccSRGetInfo(reg);
CursorType cursor_type;
unsigned int changed;
Transaction *trans;
Split *return_split;
Split *split;
split = xaccSRGetCurrentSplit(reg);
trans = xaccSplitGetParent(split);
/* This shouldn't happen, but be paranoid. */
if (trans == NULL)
return NULL;
cursor_type = xaccSplitRegisterGetCursorType(reg);
/* Can't do anything with this. */
if (cursor_type == CURSOR_NONE)
return NULL;
/* This shouldn't happen, but be paranoid. */
if ((split == NULL) && (cursor_type == CURSOR_TRANS))
return NULL;
changed = xaccSplitRegisterGetChangeFlag(reg);
/* See if we were asked to duplicate an unchanged blank split.
* There's no point in doing that! */
if (!changed && ((split == NULL) || (split == info->blank_split)))
return NULL;
/* If the cursor has been edited, we are going to have to commit
* it before we can duplicate. Make sure the user wants to do that. */
if (changed)
{
GNCVerifyResult result;
result = gnc_ok_cancel_dialog_parented(xaccSRGetParent(reg),
TRANS_CHANGED_MSG,
GNC_VERIFY_OK);
if (result == GNC_VERIFY_CANCEL)
return NULL;
xaccSRSaveRegEntry(reg, NULL);
/* If the split is NULL, then we were on a blank split row
* in an expanded transaction. The new split (created by
* xaccSRSaveRegEntry above) will be the last split in the
* current transaction, as it was just added. */
if (split == NULL)
split = xaccTransGetSplit(trans, xaccTransCountSplits(trans) - 1);
}
/* Ok, we are now ready to make the copy. */
if (cursor_type == CURSOR_SPLIT)
{
Split *new_split;
Account *account;
/* We are on a split in an expanded transaction.
* Just copy the split and add it to the transaction. */
new_split = xaccMallocSplit();
gnc_copy_split(split, new_split);
account = xaccSplitGetAccount(split);
xaccTransBeginEdit(trans, GNC_T);
xaccAccountBeginEdit(account, GNC_T);
xaccTransAppendSplit(trans, new_split);
xaccAccountInsertSplit(account, new_split);
xaccAccountCommitEdit(account);
xaccTransCommitEdit(trans);
return_split = new_split;
}
else
{
Transaction *new_trans;
int num_splits;
int i;
/* We are on a transaction row. Copy the whole transaction. */
new_trans = xaccMallocTransaction();
xaccTransBeginEdit(new_trans, GNC_T);
gnc_copy_trans(trans, new_trans);
num_splits = xaccTransCountSplits(trans);
return_split = NULL;
/* Link the new splits into the accounts. */
for (i = 0; i < num_splits; i++)
{
Account *account;
Split *old_split;
Split *new_split;
old_split = xaccTransGetSplit(trans, i);
account = xaccSplitGetAccount(old_split);
new_split = xaccTransGetSplit(new_trans, i);
xaccAccountBeginEdit(account, GNC_T);
xaccAccountInsertSplit(account, new_split);
xaccAccountCommitEdit(account);
/* Returned split is the transaction split */
if (old_split == split)
return_split = new_split;
}
xaccTransCommitEdit(new_trans);
/* This shouldn't happen, but be paranoid. */
if (return_split == NULL)
return_split = xaccTransGetSplit(new_trans, 0);
}
/* Refresh the GUI. */
gnc_transaction_ui_refresh(trans);
gnc_refresh_main_window();
return return_split;
}
/* ======================================================== */
void
xaccSRDeleteCurrentSplit (SplitRegister *reg)
{
@ -598,8 +797,8 @@ xaccSRDeleteCurrentSplit (SplitRegister *reg)
return;
/* If we just deleted the blank split, clean up. The user is
* allowed to delete the blank split as a method for discarding any
* edits they may have made to it. */
* allowed to delete the blank split as a method for discarding
* any edits they may have made to it. */
if (split == info->blank_split)
{
account = xaccSplitGetAccount(split);
@ -609,8 +808,7 @@ xaccSRDeleteCurrentSplit (SplitRegister *reg)
/* make a copy of all of the accounts that will be
* affected by this deletion, so that we can update
* their register windows after the deletion.
*/
* their register windows after the deletion. */
trans = xaccSplitGetParent(split);
num_splits = xaccTransCountSplits(trans);
affected_accounts = (Account **) malloc((num_splits + 1) *

View File

@ -78,9 +78,8 @@ static short module = MOD_ENGINE;
\********************************************************************/
void
xaccInitSplit( Split * split )
{
xaccInitSplit(Split * split)
{
/* fill in some sane defaults */
split->acc = NULL;
split->parent = NULL;
@ -104,18 +103,18 @@ xaccInitSplit( Split * split )
split->cost_basis = 0.0;
split->tickee = 0;
}
}
/********************************************************************\
\********************************************************************/
Split *
xaccMallocSplit( void )
{
xaccMallocSplit(void)
{
Split *split = (Split *)_malloc(sizeof(Split));
xaccInitSplit (split);
return split;
}
}
/********************************************************************\
\********************************************************************/
@ -160,7 +159,7 @@ xaccCloneSplit (Split *s)
void
xaccFreeSplit( Split *split )
{
{
if (!split) return;
if (split->memo) free (split->memo);
@ -477,7 +476,7 @@ xaccSplitSetBaseValue (Split *s, double value, char * base_currency)
}
}
/* be more precise -- the value depends on the curency
/* be more precise -- the value depends on the currency
* we want it expressed in.
*/
if (!safe_strcmp(s->acc->currency, base_currency)) {

View File

@ -204,10 +204,65 @@ gnc_foundation_query_dialog(const gchar *title,
return query_dialog;
}
/********************************************************************\
* gnc_ok_cancel_dialog_parented *
* 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 window *
* message - the message to display *
* default - the button that will be the default *
* Return: the result the user selected *
\********************************************************************/
GNCVerifyResult
gnc_ok_cancel_dialog_parented(gncUIWidget parent, const char *message,
GNCVerifyResult default_result)
{
GtkWidget *dialog = NULL;
gint default_button;
gint result;
dialog = gnome_message_box_new(message,
GNOME_MESSAGE_BOX_QUESTION,
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
NULL);
switch (default_result)
{
case GNC_VERIFY_OK:
default_button = 0;
break;
case GNC_VERIFY_CANCEL:
default_button = 1;
break;
default:
PWARN("gnc_verify_cancel_dialog: bad default button\n");
default_button = 0;
break;
}
gnome_dialog_set_default(GNOME_DIALOG(dialog), default_button);
if (parent != NULL)
gnome_dialog_set_parent(GNOME_DIALOG(dialog), GTK_WINDOW(parent));
result = gnome_dialog_run_and_close(GNOME_DIALOG(dialog));
switch (result)
{
case 0:
return GNC_VERIFY_OK;
case 1:
default:
return GNC_VERIFY_CANCEL;
}
}
/********************************************************************\
* gnc_verify_cancel_dialog *
* display a message, and asks the user to press "Yes", "No", or *
* "Cancel"
* "Cancel" *
* *
* NOTE: This function does not return until the dialog is closed *
* *

View File

@ -118,7 +118,7 @@ void
recnRefresh(Account *account)
{
RecnWindow *recnData;
FIND_IN_LIST (RecnWindow, recnList, account, account, recnData);
if (recnData == NULL)
return;

View File

@ -1,6 +1,7 @@
/********************************************************************\
* window-reconcile.h -- the reconcile window *
* Copyright (C) 1997 Robin D. Clark *
* Copyright (C) 1998-2000 Linas Vepstas *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *

View File

@ -31,6 +31,7 @@
#include <gnome.h>
#include "gnome-top-level.h"
#include "MultiLedger.h"
#include "LedgerUtils.h"
#include "MainWindow.h"

View File

@ -3,6 +3,7 @@
* Copyright (C) 1997 Robin D. Clark *
* Copyright (C) 1998 Linas Vepstas *
* Copyright (C) 1999 Jeremy Collins ( gtk-xmhtml port ) *
* Copyright (C) 2000 Dave Peticolas <peticola@cs.ucdavis.edu> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
@ -35,6 +36,7 @@
#include "option-util.h"
#include "guile-util.h"
#include "dialog-options.h"
#include "ui-callbacks.h"
#include "query-user.h"
#include "messages.h"
#include "util.h"
@ -222,14 +224,21 @@ static char *
gnc_run_report(ReportData *report_data)
{
SCM result, nil;
gncUIWidget window;
if (!gh_procedure_p(report_data->rendering_thunk))
return NULL;
window = gnc_html_window_get_window(reportwindow);
gnc_set_busy_cursor(window);
nil = gh_eval_str("()");
result = gfec_apply(report_data->rendering_thunk, nil,
gnc_report_error_dialog);
gnc_unset_busy_cursor(window);
if (!gh_string_p(result))
return NULL;

View File

@ -24,7 +24,7 @@
(define (gnc:leap-year? year)
(if (= (remainder year 4) 0)
(if (= (remainder year 100) 0)
(if (= (remainder year 400) 0) #t #f)
(if (= (remainder (+ year 1900) 400) 0) #t #f)
#t)
#f))
@ -47,10 +47,31 @@
(/ (gnc:date-get-year-day lt) (* 1.0 (gnc:days-in-year
(gnc:date-get-year lt)))))))
;; return the number of years (in floating point format) between two dates.
(define (gnc:date-year-delta caltime1 caltime2)
(let* ((lt1 (localtime caltime1))
(lt2 (localtime caltime2))
(day1 (gnc:date-get-year-day lt1))
(day2 (gnc:date-get-year-day lt2))
(year1 (gnc:date-get-year lt1))
(year2 (gnc:date-get-year lt2))
(dayadj1 (if (and (not (gnc:leap-year? year1))
(>= day1 59))
(+ day1 1)
day1))
(dayadj2 (if (and (not (gnc:leap-year? year2))
(>= day2 59))
(+ day2 1)
day2)))
(+ (- (gnc:date-get-year lt2) (gnc:date-get-year lt1))
(/ (- dayadj2 dayadj1)
366.0))))
;; convert a date in seconds since 1970 into # of months since 1970
(define (gnc:date-to-month-fraction caltime)
(let ((lt (localtime caltime)))
(+ (* 12 (- (gnc:date-get-year lt) 1970.0))
(gnc:date-get-month lt)
(/ (- (gnc:date-get-month-day lt) 1.0) (gnc:days-in-month
(gnc:date-get-month lt)
(gnc:date-get-year lt))))))
@ -60,10 +81,10 @@
(define (gnc:date-to-week-fraction caltime)
(/ (- (/ (/ caltime 3600.0) 24) 3) 7))
;; convert a date in seconds since 1970 into # of days since Jan 1, 1970
;; convert a date in seconds since 1970 into # of days since Feb 28, 1970
;; ignoring leap-seconds
(define (gnc:date-to-day-fraction caltime)
(/ (/ caltime 3600.0) 24))
(- (/ (/ caltime 3600.0) 24) 59))
;; Modify a date
(define (moddate op adate delta)

View File

@ -38,6 +38,29 @@
((gnc:budget-year) (gnc:date-to-year-fraction caltime))
(else (gnc:debug "undefined period type in budget!") #f)))
(define (gnc:date-N-delta caltime1 caltime2 type)
(case type
((gnc:budget-day)
(- (gnc:date-to-day-fraction caltime2)
(gnc:date-to-day-fraction caltime1)))
((gnc:budget-week)
(- (gnc:date-to-week-fraction caltime2)
(gnc:date-to-week-fraction caltime1)))
((gnc:budget-month)
(- (gnc:date-to-month-fraction caltime2)
(gnc:date-to-month-fraction caltime1)))
((gnc:budget-year) (gnc:date-year-delta caltime1 caltime2))
(else (gnc:debug "undefined period type in budget!") #f)))
;; returns the "day number" of the specified period.
(define (gnc:date-to-N-remainder caltime type)
(case type
((gnc:budget-day) 0)
((gnc:budget-week) (gnc:date-get-week-day (localtime caltime)))
((gnc:budget-month) (gnc:date-get-month-day (localtime caltime)))
((gnc:budget-year) (gnc:date-get-year-day (localtime caltime)))
(else (gnc:debug "undefined period type in budget!") #f)))
;; describe a time type
(define (gnc:date-describe-type type)
(case type
@ -60,20 +83,23 @@
(define budget-entry-structure
(make-record-type
"budget-entry-structure"
'(description amount accounts period period-type budget-type)))
'(description amount accounts period period-type budget-type
trigger-day)))
(define (make-budget-entry desc amt acct per ptype budget-type)
(define (make-budget-entry desc amt acct per ptype budget-type trig-day)
((record-constructor budget-entry-structure)
desc amt acct per ptype budget-type))
desc amt acct per ptype budget-type trig-day))
(define gnc:budget-entries
(list
(make-budget-entry "lunch" 8 '("Food:Lunch") 1
'gnc:budget-day 'gnc:budget-recurring)
'gnc:budget-day 'gnc:budget-recurring 0)
(make-budget-entry "junk food" 0.50 '("Food:Junk") 1
'gnc:budget-day 'gnc:budget-recurring)
'gnc:budget-day 'gnc:budget-recurring 0)
(make-budget-entry "car repairs" 2500 '("Car:Repairs") 5
'gnc:budget-year 'gnc:budget-contingency)))
'gnc:budget-year 'gnc:budget-contingency 0)
(make-budget-entry "rent" 312.50 '("Household:Rent") 1
'gnc:budget-month 'gnc:budget-trigger 15)))
(define (budget-entry-get-description budget-entry)
((record-accessor budget-entry-structure 'description) budget-entry))
@ -90,6 +116,9 @@
(define (budget-entry-get-period-type budget-entry)
((record-accessor budget-entry-structure 'period-type) budget-entry))
(define (budget-entry-get-trigger-day budget-entry)
((record-accessor budget-entry-structure 'trigger-day) budget-entry))
(define (budget-description-html-proc)
(lambda (budget-line)
(html-generic-cell #f #f #f
@ -120,6 +149,10 @@
(gnc:date-describe-type
(budget-entry-get-period-type (budget-line-get-entry budget-line))))))
(define (budget-trigger-day-html-proc)
(lambda (budget-line)
(html-number-cell
#f #f "%i" (budget-entry-get-trigger-day (budget-line-get-entry budget-line)))))
;; budget report: a vector with indexes corresponding to the budget
;; 0 - actual: the amount spend / recieved
@ -135,11 +168,11 @@
(make-record-type
"budget-report-structure"
'(actual budgeted num-periods minimum-expected maximum-expected
time-remaining)))
time-remaining num-triggers)))
(define (make-empty-budget-report)
((record-constructor budget-report-structure)
0 0 0 0 0 0))
0 0 0 0 0 0 0))
(define (budget-report-get-actual brep)
((record-accessor budget-report-structure 'actual) brep))
@ -159,6 +192,9 @@
(define (budget-report-get-time-remaining brep)
((record-accessor budget-report-structure 'time-remaining) brep))
(define (budget-report-get-num-triggers brep)
((record-accessor budget-report-structure 'num-triggers) brep))
(define (budget-actual-html-proc)
(lambda (budget-line)
(html-currency-cell #f #f (budget-report-get-actual
@ -171,7 +207,7 @@
(define (budget-num-periods-html-proc)
(lambda (budget-line)
(html-number-cell #f #f "%.1f" (budget-report-get-num-periods
(html-number-cell #f #f "%.6f" (budget-report-get-num-periods
(budget-line-get-report budget-line)))))
(define (budget-minimum-expected-html-proc)
@ -189,6 +225,11 @@
(html-number-cell #f #f "%.1f" (budget-report-get-time-remaining
(budget-line-get-report budget-line)))))
(define (budget-num-triggers-html-proc)
(lambda (budget-line)
(html-number-cell #f #f "%.0f" (budget-report-get-num-triggers
(budget-line-get-report budget-line)))))
(define budget-line-structure
(make-record-type "budget-line-structure"
'(entry report)))
@ -212,13 +253,11 @@
;; calculate the # of periods on a budget line.
;; dates are in # seconds after 1970
(define (budget-calculate-periods! budget-line begin-date end-date)
(let* ((entry (budget-line-get-entry budget-line))
(N-type (budget-entry-get-period-type entry))
(begin-N (gnc:date-to-N-fraction begin-date N-type))
(end-N (gnc:date-to-N-fraction end-date N-type)))
(let ((entry (budget-line-get-entry budget-line)))
((record-modifier budget-report-structure 'num-periods)
(budget-line-get-report budget-line)
(/ (- end-N begin-N)
(/ (gnc:date-N-delta begin-date end-date
(budget-entry-get-period-type entry))
(budget-entry-get-period entry)))))
;; calculate the budgeted value.
@ -234,7 +273,7 @@
(define (budget-calculate-expected! budget-line)
(let ((brep (budget-line-get-report budget-line))
(entry (budget-line-get-entry budget-line)))
; fixme: contingency type budget entries may have a lower minimum
; fixme: contingency type budget entries may have a lower minimum
((record-modifier budget-report-structure 'minimum-expected) brep
(* (budget-entry-get-amount entry)
(floor (budget-report-get-num-periods brep))))
@ -252,6 +291,20 @@
(* (- (ceiling periods) periods)
(budget-entry-get-period entry)))))
;; calculate the number of times the trigger day occurs in the budget
;; period
(define (budget-calculate-num-triggers! budget-line begin-date end-date)
(let* ((entry (budget-line-get-entry budget-line))
(brep (budget-line-get-report budget-line))
(N-type (budget-entry-get-period-type entry))
(trigger-day (budget-entry-get-trigger-day entry)))
((record-modifier budget-report-structure 'num-triggers) brep
(+ -1
(if (<= (gnc:date-to-N-remainder begin-date N-type) trigger-day) 1 0)
(if (>= (gnc:date-to-N-remainder end-date N-type) trigger-day) 1 0)
(- (floor (gnc:date-to-N-fraction end-date N-type))
(floor (gnc:date-to-N-fraction begin-date N-type)))))))
;; given an account name, return the budget line
;; return #f if there is no budget line for that account
(define (budget-get-line account-name budget)
@ -369,9 +422,10 @@
(budget-calculate-periods! line begin-date-secs end-date-secs)
(budget-calculate-budgeted! line)
(budget-calculate-expected! line)
(budget-calculate-time-remaining! line)))
(budget-calculate-time-remaining! line)
(budget-calculate-num-triggers! line begin-date-secs end-date-secs)))
budget-list)
(gnc:debug "c")
(let ((report-headers '())
@ -386,12 +440,14 @@
"Period"
""
"Actual"
"Trigger Day"
"Budgeted"
"Number of Periods"
"Lower Limit"
"Upper Limit"
"Time Remaining"
""))
""
"Num Triggers"))
(set! report-procs (list
budget-description-html-proc
budget-amount-html-proc
@ -399,12 +455,14 @@
budget-period-html-proc
budget-period-type-html-proc
budget-actual-html-proc
budget-trigger-day-html-proc
budget-budgeted-html-proc
budget-num-periods-html-proc
budget-minimum-expected-html-proc
budget-maximum-expected-html-proc
budget-time-remaining-html-proc
budget-period-type-html-proc)))
budget-period-type-html-proc
budget-num-triggers-html-proc)))
((balancing)
(set! report-headers (list
"Description"

View File

@ -32,7 +32,8 @@ typedef enum
{
GNC_VERIFY_NO,
GNC_VERIFY_YES,
GNC_VERIFY_CANCEL
GNC_VERIFY_CANCEL,
GNC_VERIFY_OK
} GNCVerifyResult;
@ -43,6 +44,11 @@ gnc_verify_cancel_dialog_parented(gncUIWidget parent,
const char *message,
GNCVerifyResult default_result);
GNCVerifyResult
gnc_ok_cancel_dialog_parented(gncUIWidget parent,
const char *message,
GNCVerifyResult default_result);
void gnc_warning_dialog_parented(gncUIWidget parent, const char *message);
gncBoolean gnc_verify_dialog( const char *message,