Remove FreqSpec.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16387 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Joshua Sled 2007-08-05 21:24:16 +00:00
parent 7d15dbd105
commit f5923ae956
28 changed files with 38 additions and 3227 deletions

View File

@ -140,7 +140,7 @@ void qof_log_init_filename_special(const char *log_to_filename);
# log.ger.path=level
gnc.engine.sx=debug
gnc.gui.sx=debug
gnc.gui.freqspec=debug
gnc.import-export.qif.parse=debug
[output]
# to=["stderr"|"stdout"|filename]
to=stderr

View File

@ -134,8 +134,6 @@ gnc_book_dom_tree_create(QofBook *book)
xaccAccountTreeForEachTransaction (gnc_book_get_root_account(book),
traverse_txns, ret);
xmlAddChild(ret, gnc_freqSpec_dom_tree_create (book));
/* xxx FIXME hack alert how are we going to handle
* gnc_book_get_template_group handled ??? */
xmlAddChild(ret, gnc_schedXaction_dom_tree_create(

View File

@ -44,39 +44,7 @@
#include "sixtp-dom-parsers.h"
#include "SchedXaction.h"
#include "FreqSpecP.h"
/**
* The XML output should look something like:
* <freqspec>
* <fs:monthly>
* <fs:interval>2</fs:interval>
* <fs:offset>1</fs:offset>
* <fs:day>21</fs:day>
* </fs:monthly>
* <fs:id>...</fs:id>
* </freqspec>
*
* <freqspec>
*
* <fs:composite>
* <freqspec>
* <fs:weekly>
* <fs:interval>2</fs:interval>
* <fs:offset>3</fs:offset>
* </fs:weekly>
* </freqspec>
* <freqspec>
* <fs:weekly>
* <fs:interval>2</fs:interval>
* <fs:offset>12</fs:offset>
* </fs:weekly>
* </freqspec>
* </fs:composite>
* <fs:id>...</fs:id>
* </freqspec>
*
**/
#include "FreqSpec.h"
const gchar *freqspec_version_string = "1.0.0";
@ -122,7 +90,6 @@ struct uiFreqTypeTuple uiFreqTypeStrs[] = {
**/
typedef struct
{
FreqSpec *fs; /* FreqSpec we're parsing into. */
QofBook *book; /* Book we're loading into. */
Recurrence *recurrence;
@ -141,7 +108,6 @@ typedef struct
static void
fspd_init( fsParseData *fspd )
{
fspd->fs = NULL;
fspd->list = NULL;
fspd->book = NULL;
fspd->recurrence = g_new0(Recurrence, 1);
@ -155,139 +121,6 @@ fspd_init( fsParseData *fspd )
g_date_clear( &fspd->once_day, 1 );
}
xmlNodePtr
gnc_freqSpec_dom_tree_create( FreqSpec *fs )
{
xmlNodePtr ret;
xmlNodePtr xmlSub;
ret = xmlNewNode( NULL, BAD_CAST "gnc:freqspec" );
xmlSetProp( ret, BAD_CAST "version", BAD_CAST freqspec_version_string );
xmlAddChild( ret, guid_to_dom_tree( "fs:id", qof_instance_get_guid(fs) ) );
xmlSub = text_to_dom_tree( "fs:ui_type",
uiFreqTypeStrs[ xaccFreqSpecGetUIType(fs) ].str );
xmlAddChild( ret, xmlSub );
switch( fs->type ) {
case INVALID: {
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:none" );
xmlAddChild( ret, xmlSub );
} break;
case ONCE: {
if (!g_date_valid(&fs->s.once.date))
{
xmlSub = xmlNewNode(NULL, BAD_CAST "fs:none");
}
else
{
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:once" );
xmlAddChild( xmlSub,
gdate_to_dom_tree( "fs:date",
&fs->s.once.date ) );
}
xmlAddChild( ret, xmlSub );
} break;
case DAILY: {
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:daily" );
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:interval",
fs->s.daily.interval_days )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:offset",
fs->s.daily.offset_from_epoch )
);
xmlAddChild( ret, xmlSub );
} break;
case WEEKLY: {
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:weekly" );
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:interval",
fs->s.weekly.interval_weeks )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:offset",
fs->s.weekly.offset_from_epoch )
);
xmlAddChild( ret, xmlSub );
} break;
case MONTHLY: {
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:monthly" );
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:interval",
fs->s.monthly.interval_months )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:offset",
fs->s.monthly.offset_from_epoch )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:day",
fs->s.monthly.day_of_month )
);
xmlAddChild( ret, xmlSub );
} break;
case MONTH_RELATIVE: {
xmlSub = xmlNewNode( NULL, BAD_CAST "fs:month_relative" );
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:interval",
fs->s.month_relative.interval_months )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:offset",
fs->s.month_relative.offset_from_epoch )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:weekday",
fs->s.month_relative.weekday )
);
xmlAddChild( xmlSub,
guint_to_dom_tree(
"fs:occurrence",
fs->s.month_relative.occurrence )
);
xmlAddChild( ret, xmlSub );
} break;
case COMPOSITE: {
GList *subelts;
xmlNodePtr xmlComposites;
xmlComposites = xmlNewNode( NULL, BAD_CAST "fs:composite" );
subelts = fs->s.composites.subSpecs;
while( subelts ) {
xmlAddChild( xmlComposites,
gnc_freqSpec_dom_tree_create(
subelts->data ) );
subelts = subelts->next;
}
xmlAddChild( ret, xmlComposites );
} break;
default:
g_return_val_if_fail( FALSE, NULL );
}
return ret;
}
static struct dom_tree_handler fs_dom_handlers[];
static
@ -311,7 +144,6 @@ fs_uift_handler( xmlNodePtr node, gpointer data)
g_return_val_if_fail( nodeTxt, FALSE );
for ( i=0; (tmp = uiFreqTypeStrs[i].str) != NULL; i++ ) {
if ( safe_strcmp( nodeTxt, tmp ) == 0 ) {
xaccFreqSpecSetUIType( fspd->fs, uiFreqTypeStrs[i].uift );
fspd->uift = uiFreqTypeStrs[i].uift;
g_free( nodeTxt );
return TRUE;
@ -414,14 +246,8 @@ gboolean
fs_subelement_handler( xmlNodePtr node, gpointer data )
{
fsParseData *fspd = data;
FreqSpec *fs;
GList *recurrences;
fs = dom_tree_to_freqSpec( node, fspd->book );
if ( fs == NULL )
return FALSE;
fspd->list = g_list_append( fspd->list, fs );
recurrences = dom_tree_freqSpec_to_recurrences(node, fspd->book);
if (recurrences == NULL)
return FALSE;
@ -463,10 +289,7 @@ fs_none_handler( xmlNodePtr node, gpointer data )
successful = dom_tree_generic_parse( node,
fs_union_dom_handlers,
fspd );
if ( !successful )
return FALSE;
fspd->fs->type = INVALID;
return TRUE;
return successful;
}
static
@ -483,8 +306,6 @@ fs_once_handler( xmlNodePtr node, gpointer data )
return FALSE;
recurrenceSet(fspd->recurrence, 0, PERIOD_ONCE, &fspd->once_day);
fspd->fs->type = ONCE;
fspd->fs->s.once.date = fspd->once_day;
return TRUE;
}
@ -502,9 +323,6 @@ fs_daily_handler(xmlNodePtr node, gpointer data)
g_date_set_julian(&offset_date, fspd->offset == 0 ? 7 : fspd->offset);
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_DAY, &offset_date);
fspd->fs->type = DAILY;
fspd->fs->s.daily.interval_days = fspd->interval;
fspd->fs->s.daily.offset_from_epoch = fspd->offset;
return TRUE;
}
@ -525,10 +343,6 @@ fs_weekly_handler( xmlNodePtr node, gpointer data )
g_date_set_julian(&offset_date, fspd->offset == 0 ? 7 : fspd->offset);
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_WEEK, &offset_date);
fspd->fs->type = WEEKLY;
fspd->fs->s.weekly.interval_weeks = fspd->interval;
fspd->fs->s.weekly.offset_from_epoch = fspd->offset;
return TRUE;
}
@ -560,11 +374,6 @@ fs_monthly_handler( xmlNodePtr node, gpointer data)
recurrenceSet(fspd->recurrence, fspd->interval, PERIOD_MONTH, &offset_date);
}
fspd->fs->type = MONTHLY;
fspd->fs->s.monthly.interval_months = fspd->interval;
fspd->fs->s.monthly.offset_from_epoch = fspd->offset;
fspd->fs->s.monthly.day_of_month = fspd->day;
return successful;
}
@ -583,7 +392,6 @@ fs_guid_handler( xmlNodePtr node, gpointer data)
fsParseData *fspd = data;
GUID *guid;
guid = dom_tree_to_guid( node );
qof_instance_set_guid(fspd->fs, guid);
return TRUE;
}
@ -596,12 +404,7 @@ fs_composite_handler( xmlNodePtr node, gpointer data)
successful = dom_tree_generic_parse( node,
fs_union_dom_handlers,
fspd );
if ( !successful )
return FALSE;
fspd->fs->type = COMPOSITE;
fspd->fs->s.composites.subSpecs = fspd->list;
return TRUE;
return successful;
}
static struct dom_tree_handler fs_dom_handlers[] = {
@ -643,11 +446,9 @@ gnc_freqSpec_end_handler(gpointer data_for_children,
g_return_val_if_fail( tree, FALSE );
fspd.fs = xaccFreqSpecMalloc(globaldata->book);
successful = dom_tree_generic_parse( tree, fs_dom_handlers, &fspd );
if (!successful) {
xmlElemDump( stdout, NULL, tree );
xaccFreqSpecFree( fspd.fs );
}
xmlFreeNode(tree);
@ -667,13 +468,10 @@ common_parse(fsParseData *fspd, xmlNodePtr node, QofBook *book)
gboolean successful;
fspd->book = book;
fspd->fs = xaccFreqSpecMalloc(book);
successful = dom_tree_generic_parse( node, fs_dom_handlers, fspd );
if (!successful)
{
xmlElemDump(stdout, NULL, node);
xaccFreqSpecFree( fspd->fs );
fspd->fs = NULL;
}
}
@ -689,12 +487,3 @@ dom_tree_freqSpec_to_recurrences(xmlNodePtr node, QofBook *book)
}
return fspd.recurrence_list;
}
FreqSpec*
dom_tree_to_freqSpec(xmlNodePtr node, QofBook *book)
{
fsParseData fspd;
fspd_init( &fspd );
common_parse(&fspd, node, book);
return fspd.fs;
}

View File

@ -49,74 +49,6 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.backend.file.sx"
/**
* The XML output should look something like:
* <gnc:count-data cd:type="schedXaction">XXX</gnc:count-data>
* ...
* <gnc:schedxaction version="1.0.0">
* <sx:id type="guid">...</sx:id>
* <sx:name>Rent</sx:name>
* <sx:enabled>y</sx:enabled>
* <sx:autoCreate>y</sx:autoCreate>
* <sx:autoCreateNotify>n</sx:autoCreateNotify>
* <sx:advanceCreateDays>0</sx:advanceCreateDays>
* <sx:advanceRemindDays>5</sx:advanceRemindDays>
* <sx:instanceCount>100</sx:instanceCount>
* <sx:lastOccur>
* <gdate>2001-02-28</gdate>
* </sx:lastOccur>
* <sx:start>
* <gdate>2000-12-31</gdate>
* </sx:start>
* <!-- no end -->
* <sx:freq>
* <!-- freq spec tree -->
* </sx:freq>
* <sx:deferredInstance>
* <sx:last>2001-10-02</sx:last>
* [...]
* </sx:deferredInstance>
* [...]
* </gnc:schedxaction>
* <gnc:schedxaction version="1.0.0">
* <sx:id type="guid">...</sx:id>
* <sx:name>Loan 1</sx:name>
* <sx:manual-conf>f</sx:manual-conf>
* <sx:start>
* <gdate>2000-12-31</gdate>
* </sx:start>
* <sx:end type="date">
* <gdate>2004-03-20</gdate>
* </sx:end>
* <sx:instanceCount>100</sx:instanceCount>
* <sx:freq>
* <!-- freqspec tree -->
* </sx:freq>
* </gnc:schedxaction>
* <gnc:schedxaction version="1.0.0">
* <sx:id type="guid">...</sx:id>
* <sx:name>Loan 2</sx:name>
* <sx:manual-conf>f</sx:manual-conf>
* <sx:instanceCount>100</sx:instanceCount>
* <sx:start>
* <gdate>2000-12-31</gdate>
* </sx:start>
* <sx:end type="num_occur">
* <sx:num>42</sx:num>
* </sx:end>
* <sx:freq>
* <!-- freqspec tree -->
* </sx:freq>
* </gnc:schedxaction>
*
* et-cetera...
* bleh.
**/
/*
* All tags should be #defined here
*/
#define SX_ID "sx:id"
#define SX_NAME "sx:name"
#define SX_ENABLED "sx:enabled"
@ -219,16 +151,6 @@ gnc_schedXaction_dom_tree_create(SchedXaction *sx)
guid_to_dom_tree(SX_TEMPL_ACCT,
templ_acc_guid));
if (!allow_2_2_incompat)
{
/* output freq spec */
fsNode = xmlNewNode(NULL, BAD_CAST SX_FREQSPEC);
xmlAddChild( fsNode,
gnc_freqSpec_dom_tree_create(
xaccSchedXactionGetFreqSpec(sx)) );
xmlAddChild( ret, fsNode );
}
if (allow_2_2_incompat)
{
xmlNodePtr schedule_node = xmlNewNode(NULL, "sx:schedule");
@ -495,8 +417,6 @@ sx_freqspec_handler( xmlNodePtr node, gpointer sx_pdata )
g_return_val_if_fail( node, FALSE );
xaccSchedXactionSetFreqSpec(sx, dom_tree_to_freqSpec(node, pdata->book));
schedule = dom_tree_freqSpec_to_recurrences(node, pdata->book);
gnc_sx_set_schedule(sx, schedule);
g_debug("parsed from freqspec [%s]", recurrenceListToString(schedule));

View File

@ -25,7 +25,6 @@
#ifndef GNC_XML_H
#define GNC_XML_H
#include "FreqSpec.h"
#include "SchedXaction.h"
#include "gnc-engine.h"
#include "gnc-pricedb.h"
@ -45,7 +44,6 @@ sixtp* gnc_book_slots_sixtp_parser_create(void);
xmlNodePtr gnc_commodity_dom_tree_create(const gnc_commodity *com);
sixtp* gnc_commodity_sixtp_parser_create(void);
xmlNodePtr gnc_freqSpec_dom_tree_create( FreqSpec *fs );
sixtp* gnc_freqSpec_sixtp_parser_create(void);
xmlNodePtr gnc_lot_dom_tree_create(GNCLot *);

View File

@ -28,7 +28,6 @@
#include "gnc-xml-helper.h"
#include "FreqSpec.h"
#include "gnc-commodity.h"
#include "qof.h"
#include "gnc-budget.h"
@ -38,7 +37,6 @@ GUID* dom_tree_to_guid(xmlNodePtr node);
gnc_commodity* dom_tree_to_commodity_ref(xmlNodePtr node, QofBook *book);
gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node, QofBook *);
FreqSpec* dom_tree_to_freqSpec( xmlNodePtr node, QofBook *book);
GList* dom_tree_freqSpec_to_recurrences(xmlNodePtr node, QofBook *book);
Recurrence* dom_tree_to_recurrence(xmlNodePtr node);

File diff suppressed because it is too large Load Diff

View File

@ -19,67 +19,18 @@
\********************************************************************/
/** @addtogroup SchedXaction
@{ */
/** @addtogroup FreqSpec Specifying Recurring Dates (Periods)
Frequency specifications include how to let an event recur on a
predictable frequency, from a core of once, daily, weekly, monthly or annually.
More complex frequencies like twice weekly, quarterly, bi-annually and
custom frequencies consisting of a series of distinct dates are built from
the core types.
Although defined, MONTH_RELATIVE is not yet supported.
Scheduled transactions have a frequency defined by a frequency
specifier. This specifier, given a start date, end date [present
in the scheduled transaction] and last occurance date [possibly not
present] can be used to determine that a s.transaction should be
instantiated on a given date [the given query date].
There is a split between the UIFreqType and the 'internal' FreqType
to reduce the complexity of some of the code involved.
This still needs to deal with:
. exceptions
. 13 periods: (4 weeks/period 4x13=52 weeks/year)
. yearly 360/365?
. re-based frequencies [based around a non-standard [read:
not-Jan-1-based/fiscal] year]
. "business days" -- m-f sans holidays [per-user list thereof]
\todo add month-relative getter
@{ */
/** @file FreqSpec.h
@brief Period / Date Frequency Specification
@author Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org>
@author Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au>
@author Copyright (c) 2005 Neil Williams <linux@codehelp.co.uk>
*/
#ifndef XACC_FREQSPEC_H
#define XACC_FREQSPEC_H
typedef struct _FreqSpecClass FreqSpecClass;
#include "gnc-engine.h"
#include <glib.h>
#include "qof.h"
/* --- type macros --- */
#define GNC_TYPE_FREQSPEC (gnc_freqspec_get_type ())
#define GNC_FREQSPEC(o) \
(G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_FREQSPEC, FreqSpec))
#define GNC_FREQSPEC_CLASS(k) \
(G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_FREQSPEC, FreqSpecClass))
#define GNC_IS_FREQSPEC(o) \
(G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_FREQSPEC))
#define GNC_IS_FREQSPEC_CLASS(k) \
(G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_FREQSPEC))
#define GNC_FREQSPEC_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_FREQSPEC, FreqSpecClass))
GType gnc_freqspec_get_type(void);
#define ENUM_LIST_TYPE(_) \
_(INVALID,) \
_(ONCE,) \
@ -121,185 +72,6 @@ DEFINE_ENUM( UIFreqType, ENUM_LIST_UI) /**< \enum UIFreqType
AS_STRING_DEC(UIFreqType, ENUM_LIST_UI)
FROM_STRING_DEC(UIFreqType, ENUM_LIST_UI)
/**
* Forward declaration of FreqSpec type for storing
* date repetition information. This is an opaque type.
*/
struct gncp_freq_spec;
typedef struct gncp_freq_spec FreqSpec;
/** PROTOTYPES ******************************************************/
/**
* Allocates memory for a FreqSpec and initializes it.
**/
FreqSpec* xaccFreqSpecMalloc(QofBook *book);
/**
* destroys any private data belonging to the FreqSpec.
* Use this for a stack object.
*/
void xaccFreqSpecCleanUp( FreqSpec *fs );
/**
* Frees a heap allocated FreqSpec.
* This is the opposite of xaccFreqSpecMalloc().
**/
void xaccFreqSpecFree( FreqSpec *fs );
/**
* Gets the type of a FreqSpec.
**/
FreqType xaccFreqSpecGetType( FreqSpec *fs );
/**
* Sets the type of a FreqSpec.
* Setting the type re-initializes any spec-data; this means
* destroying any sub-types in the case of COMPOSITE.
*
* \warning THESE FUNCTIONS HAVE NOT BEEN MAINTAINED THROUGH BEN'S CHANGES.
* They need to be checked.
**/
/* void xaccFreqSpecSetType( FreqSpec *fs, FreqType newType ); */
void xaccFreqSpecSetUIType( FreqSpec *fs, UIFreqType newUIFreqType );
/**
* Returns the frequency part of the FreqSpec, specifically,
* one of the 'user-interface' enumerants.
*/
UIFreqType xaccFreqSpecGetUIType( FreqSpec *fs );
void xaccFreqSpecSetNone( FreqSpec *fs );
/**
* Sets the type to once-off, and initialises the
* date it occurs on.
* Disposes of any previous data.
*/
void xaccFreqSpecSetOnceDate( FreqSpec *fs,
const GDate* when );
/**
* Sets the type to DAILY. Disposes of any previous data.
* Uses the start date to figure
* out how many days after epoch (1/1/1900) this repeat would
* have first occurred on if it had been running back then.
* This is used later to figure out absolute repeat dates.
*/
void xaccFreqSpecSetDaily( FreqSpec *fs,
const GDate* initial_date,
guint interval_days );
/**
* Sets the type to WEEKLY. Disposes of any previous data.
* Uses the inital date to figure out the day of the week to use.
*/
void xaccFreqSpecSetWeekly( FreqSpec *fs,
const GDate* inital_date,
guint interval_weeks );
/**
* Sets the type to MONTHLY. Disposes of any previous data.
* Uses the inital date to figure out the day of the month to use.
*/
void xaccFreqSpecSetMonthly( FreqSpec *fs,
const GDate* inital_date,
guint interval_months );
/**
* Sets the type to MONTH_RELATIVE. Disposes of any previous data.
* Uses the inital date to figure out the day of the month to use.
*/
void xaccFreqSpecSetMonthRelative( FreqSpec *fs,
const GDate* inital_date,
guint interval_months );
/**
* Sets the type to COMPOSITE. Disposes of any previous data.
* You must Add some repeats to the composite before using
* it for repeating.
*/
void xaccFreqSpecSetComposite( FreqSpec *fs );
/**
* Returns a human-readable string of the Frequency. This uses
* UIFreqType to unroll the internal structure. It is an assertion
* failure if the FreqSpec data doesn't match the UIFreqType.
* Caller allocates the GString [natch].
**/
void xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str );
/** DOCUMENT ME! */
int xaccFreqSpecGetOnce( FreqSpec *fs, GDate *outGD );
/** DOCUMENT ME! */
int xaccFreqSpecGetDaily( FreqSpec *fs, int *outRepeat );
/** DOCUMENT ME! */
int xaccFreqSpecGetWeekly( FreqSpec *fs, int *outRepeat, int *outDayOfWeek );
/** DOCUMENT ME! */
int xaccFreqSpecGetMonthly( FreqSpec *fs, int *outRepeat,
int *outDayOfMonth, int *outMonthOffset );
/* FIXME: add month-relative */
/**
* Returns the list of FreqSpecs in a COMPOSITE FreqSpec.
* It is an error to use this if the type is not COMPOSITE.
* The caller should not modify this list;
* only add/remove composites and use this fn to get
* the perhaps-changed list head.
**/
GList* xaccFreqSpecCompositeGet( FreqSpec *fs );
/**
* Adds a FreqSpec to the list in a COMPOSITE FreqSpec; if the
* FreqSpec is not COMPOSITE, this is an assertion failure.
**/
void xaccFreqSpecCompositeAdd( FreqSpec *fs, FreqSpec *fsToAdd );
/**
* Computes the next instance of the FreqSpec after a given input date.
* The object pointed at by 'out_date' is set to the computed value.
* The 'in_date' can be any date. It is gaurenteed that the 'out_date'
* is strictly greater than the 'in_date'. That is, if the 'in_date'
* happens to be a repeat date (e.g. a previous out_date), then
* the out_date will be the next repeat date after that.
**/
void xaccFreqSpecGetNextInstance( FreqSpec *fs,
const GDate* in_date,
GDate* out_date );
/**
* qsort-style comparison of FreqSpecs.
* More frequently-occuring FreqSpecs are sorted before less-frequent FreqSpecs.
* FIXME: What to do for composites?
**/
int gnc_freq_spec_compare( FreqSpec *a, FreqSpec *b );
/** \name QOF handling.
QOF requires parameters to use get and set routines individually -
one parameter, one set routine, one get routine. QOF also passes
parameter values directly and expects to receive the parameter value
directly. These functions provide this mechanism. Note that in each
case, where the xacc.. function uses a *int, QOF uses the int.
In keeping with the rest of QOF, dates are handled as Timespec.
@{
*/
#define QOF_ID_FREQSPEC "FreqSpec"
#define FS_UI_TYPE "fs-frequency"
#define FS_REPEAT "fs-repeat"
#define FS_BASE_DATE "fs-initial-date"
#define FS_MONTH_DAY "fs-day-of-month"
#define FS_MONTH_OFFSET "fs-month-offset"
/** \todo Need support for monthly and weekly extra values and composite. */
gboolean FreqSpecRegister(void);
/** @} */
/** @} */
/** @} */
#endif /* XACC_FREQSPEC_H */

View File

@ -1,99 +0,0 @@
/********************************************************************\
* FreqSpec.h -- Frequency Specification *
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
* Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au> *
* *
* 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 *
* *
\********************************************************************/
/* *******************************************************************\
This file contains private definitions and should not be used by
other parts of the engine. This is private data and is subject to
change.
Currently the only files which include this file are:
FreqSpec.c
gnc-freqspec-xml-v2.c
\********************************************************************/
#ifndef XACC_FREQSPECP_H
#define XACC_FREQSPECP_H
#include "FreqSpec.h"
struct gncp_freq_spec
{
QofInstance entity;
FreqType type;
UIFreqType uift;
union u {
struct {
/* The date on which the single event occurs. */
GDate date;
} once;
struct {
/* number of days from one repeat to the next. */
guint interval_days;
/* epoch is defined by glib to be 1/1/1. Offset
measured in days. 0 <= offset < interval */
guint offset_from_epoch;
} daily;
struct {
/* A week here is measured as 7 days. The first week starts at epoch.
* 1/1/1 was a ?. */
/* number of weeks from one repeat to the next. */
guint interval_weeks;
/* offset measured in days. This combines the week
* offset and the day of the week offset. */
guint offset_from_epoch;
/* guint offset_from_epoch;*/ /* offset measured in weeks, 0 <= offset < interval */
/* guint day_of_week;*/ /* I'm not sure what days each value represents, but it's not important. */
} weekly;
struct {
/* number of months from one repeat to the next. */
guint interval_months;
/* offset measured in months */
guint offset_from_epoch;
/* Which day of the month it occurs on. */
guint day_of_month;
} monthly;
struct {
/* Number of months from one repeat to the next. */
guint interval_months;
/* offset measured in months */
guint offset_from_epoch;
/* stores a value equivalent to a GDateWeekday. */
guint weekday;
/* the 1st occurrence to the 5th occurrence. */
guint occurrence;
} month_relative;
struct {
/* A list of specs for a composite freq. */
GList *subSpecs;
} composites;
} s;
/* temporary storage for QOF */
gint value;
};
struct _FreqSpecClass
{
QofInstanceClass parent_class;
};
#endif /* XACC_FREQSPECP_H */

View File

@ -14,7 +14,6 @@ AM_CFLAGS = \
libgncmod_engine_la_SOURCES = \
Account.c \
FreqSpec.c \
Recurrence.c \
Period.c \
Query.c \
@ -93,7 +92,6 @@ gncinclude_HEADERS = \
noinst_HEADERS = \
AccountP.h \
FreqSpecP.h \
QueryP.h \
ScrubP.h \
SplitP.h \

View File

@ -327,11 +327,14 @@ recurrenceListToString(const GList *r)
str = g_string_new("");
if (r == NULL) {
g_string_append(str, "None");
g_string_append(str, _("None"));
} else {
for(iter = r; iter; iter = iter->next){
if (iter != r)
g_string_append(str, " + ");
{
/* translators: " + " is an separator in a list of string-representations of recurrence frequencies */
g_string_append(str, _(" + "));
}
s = recurrenceToString((Recurrence *)iter->data);
g_string_append(str, s);
g_free(s);
@ -542,15 +545,15 @@ recurrenceListToCompactString(GList *rs)
g_string_printf(buf, _("Monthly"));
if (multiplier > 1)
{
/* translators: %u is the recurrence multipler. */
/* translators: %u is the recurrence multiplier. */
g_string_append_printf(buf, _(" (x%u)"), multiplier);
}
g_string_append_printf(buf, ": ");
_monthly_append_when(r, buf);
} break;
case PERIOD_NTH_WEEKDAY: {
g_warning("nth weekday unhandled");
g_string_printf(buf, "@fixme: nth weekday");
g_warning("nth weekday not handled");
g_string_printf(buf, "@fixme: nth weekday not handled");
} break;
case PERIOD_YEAR: {
g_string_printf(buf, _("Yearly"));
@ -561,7 +564,7 @@ recurrenceListToCompactString(GList *rs)
}
} break;
default:
g_error("unknown Recurrnce period %d", recurrenceGetPeriodType(r));
g_error("unknown Recurrence period %d", recurrenceGetPeriodType(r));
break;
}
}

View File

@ -17,10 +17,6 @@
* and perform the same "next instance" computation for this
* sequence.
*
* Note: Recurrence is similar to FreqSpec, but it represents a
* broader concept than FreqSpec (because it also represents the
* beginning of the recurrence).
*
* Copyright (C) 2005, Chris Shoemaker <c.shoemaker@cox.net>
*
* This program is free software; you can redistribute it and/or

View File

@ -29,7 +29,6 @@
#include "qof.h"
#include "FreqSpec.h"
#include "Account.h"
#include "gnc-book.h"
#include "SX-book.h"
@ -72,7 +71,6 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book)
qof_instance_init_data (&sx->inst, GNC_ID_SCHEDXACTION, book);
sx->schedule = NULL;
sx->freq = xaccFreqSpecMalloc(book);
g_date_clear( &sx->last_date, 1 );
g_date_clear( &sx->start_date, 1 );
@ -176,7 +174,6 @@ xaccSchedXactionFree( SchedXaction *sx )
if ( sx == NULL ) return;
xaccFreqSpecFree( sx->freq );
qof_event_gen( &sx->inst, QOF_EVENT_DESTROY , NULL);
if ( sx->name )
@ -239,24 +236,6 @@ gnc_sx_commit_edit (SchedXaction *sx)
/* ============================================================ */
FreqSpec *
xaccSchedXactionGetFreqSpec( const SchedXaction *sx )
{
return sx->freq;
}
void
xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
{
g_return_if_fail( fs );
gnc_sx_begin_edit(sx);
xaccFreqSpecFree( sx->freq );
sx->freq = fs;
qof_instance_set_dirty(&sx->inst);
gnc_sx_commit_edit(sx);
}
GList*
gnc_sx_get_schedule(const SchedXaction *sx)
{
@ -887,8 +866,6 @@ gboolean
SXRegister(void)
{
static QofParam params[] = {
{ GNC_SX_FREQ_SPEC, QOF_ID_FREQSPEC, (QofAccessFunc)xaccSchedXactionGetFreqSpec,
(QofSetterFunc)xaccSchedXactionSetFreqSpec },
{ GNC_SX_NAME, QOF_TYPE_STRING, (QofAccessFunc)xaccSchedXactionGetName,
(QofSetterFunc)xaccSchedXactionSetName },
{ GNC_SX_START_DATE, QOF_TYPE_DATE, (QofAccessFunc)xaccSchedXactionGetStartDate,

View File

@ -41,7 +41,6 @@ typedef struct _SchedXactionClass SchedXactionClass;
#include <time.h>
#include <glib.h>
#include "qof.h"
#include "FreqSpec.h"
#include "Recurrence.h"
#include "gnc-engine.h"
@ -91,7 +90,6 @@ struct _SchedXaction
gchar *name;
GList *schedule;
FreqSpec *freq;
GDate last_date;
@ -154,13 +152,6 @@ GList* gnc_sx_get_schedule(const SchedXaction *sx);
/** @param[in] schedule A GList<Recurrence*> **/
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule);
FreqSpec *xaccSchedXactionGetFreqSpec( const SchedXaction *sx );
/**
* The FreqSpec is given to the SchedXaction for mem mgmt; it should
* not be freed by the external code.
*/
void xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs );
gchar *xaccSchedXactionGetName( const SchedXaction *sx );
/**
* A copy of the name is made.

View File

@ -28,7 +28,6 @@
#include "gnc-engine.h"
#include "AccountP.h"
#include "TransactionP.h"
#include "FreqSpec.h"
#include "SchedXaction.h"
#include "SX-book-p.h"
#include "gnc-pricedb-p.h"
@ -42,7 +41,6 @@ cashobjects_register(void)
g_return_val_if_fail(xaccAccountRegister(), FALSE);
g_return_val_if_fail ( xaccTransRegister(), FALSE);
g_return_val_if_fail ( xaccSplitRegister(), FALSE);
g_return_val_if_fail ( FreqSpecRegister(), FALSE);
g_return_val_if_fail ( SXRegister (), FALSE);
g_return_val_if_fail ( gnc_sxtt_register(), FALSE);
g_return_val_if_fail(gnc_pricedb_register(),FALSE);

View File

@ -33,7 +33,6 @@
#include "TransactionP.h"
#include "gnc-commodity.h"
#include "gnc-lot-p.h"
#include "FreqSpecP.h"
#include "gnc-pricedb-p.h"
/** gnc file backend library name */

View File

@ -93,7 +93,6 @@
#define GNC_ID_COMMODITY "Commodity"
#define GNC_ID_COMMODITY_NAMESPACE "CommodityNamespace"
#define GNC_ID_COMMODITY_TABLE "CommodityTable"
#define GNC_ID_FREQSPEC "FreqSpec"
#define GNC_ID_LOT "Lot"
#define GNC_ID_PERIOD "Period"
#define GNC_ID_PRICE "Price"

View File

@ -33,7 +33,6 @@
#include "gnc-session.h"
#include "Transaction.h"
#include "TransactionP.h"
#include "FreqSpec.h"
#include "Recurrence.h"
#include "SchedXaction.h"
#include "SX-book.h"

View File

@ -42,7 +42,6 @@ TESTS = \
test-split-vs-account \
test-transaction-reversal \
test-transaction-voiding \
test-freq-spec \
test-recurrence \
test-scm-query \
test-book-merge
@ -64,7 +63,6 @@ check_PROGRAMS = \
test-link \
test-commodities \
test-date \
test-freq-spec \
test-recurrence \
test-guid \
test-account-object \

View File

@ -1,630 +0,0 @@
/*
* Testing routine added by Ben Stanley bds02@uow.edu.au 20010320
* Try to test Joshua Sled's FreqSpec module.
*
*/
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <glib.h>
#include "cashobjects.h"
#include "test-stuff.h"
#include "FreqSpec.h"
#include "gnc-engine.h"
static QofBook *book;
static void
test_once (void)
{
FreqSpec *fs;
guint32 i, start_julian;
GDate date1, date2, next_date;
fs = xaccFreqSpecMalloc(book);
for( start_julian = 1; start_julian < 1000; ++start_julian ) {
g_date_set_julian( &date1, start_julian );
xaccFreqSpecSetOnceDate( fs, &date1 );
for( i = 0; i <= 2 * start_julian; ++i ) {
g_date_set_julian( &date2, start_julian + i );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
do_test( (g_date_compare( &date2, &date1 ) >= 0 &&
!g_date_valid( &next_date ) ) ||
g_date_compare( &date1, &next_date ) == 0,
"once off" );
}
}
fprintf(stdout, " FreqSpec: Single test OK, continuing . . . \r");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void
test_daily (void)
{
guint32 interval, i, start_julian, j;
FreqSpec *fs;
GDate date1, date2, next_date;
fs = xaccFreqSpecMalloc(book);
g_date_set_dmy( &date1, 1, 1, 2000 );
start_julian = g_date_get_julian( &date1 );
for( interval = 1; interval < 400; ++interval ) {
xaccFreqSpecSetDaily( fs, &date1, interval );
for( i = 0; i <= 2 * interval; ++i ) {
g_date_set_julian( &date2, start_julian + i );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
do_test_args(
g_date_get_julian( &next_date ) - g_date_get_julian( &date2 ) ==
interval - (i%interval),
"daily repeats",
__FILE__, __LINE__,
"interval = %d days, days from start = %d",
interval, i );
}
}
/* This tests whether we can correctly generate a sequence of dates,
* and end up in the right place. */
g_date_set_dmy( &date1, 25, 3, 2001 );
for( interval = 1; interval < 20; ++interval ) {
xaccFreqSpecSetDaily( fs, &date1, interval );
for( j = 0; j < 20; ++j ) { /* j=0 passes by luck, but it's not valid */
date2 = date1;
for( i = 0; i < j; ++i ) {
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
date2 = next_date;
}
do_test_args( g_date_get_julian( &date2 ) - g_date_get_julian( &date1 ) == interval*j,
"daily repeats end up in the right place",
__FILE__, __LINE__, "interval = %d days, iters = %d",
interval, j );
}
}
fprintf(stdout, " FreqSpec: Daily test OK, continuing . . . \r");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void
test_weekly (void)
{
guint32 interval, i, start_julian, weekday, j;
FreqSpec *fs;
GDate date1, date2, next_date;
fs = xaccFreqSpecMalloc(book);
/* Use this to test any specific cases which fail,
* for easy access in the debugger. */
/*
g_date_set_dmy( &date1, 2, 1, 1 );
xaccFreqSpecSetWeekly( fs, &date1, 1 );
start_julian = g_date_get_julian( &date1 );
g_date_set_julian( &date2, start_julian + 6 );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
*/
/* date2 should now be 9/1/1, julian date 9. */
for( weekday = 1; weekday <= 7; ++weekday ) {
g_date_set_dmy( &date1, weekday, 1, 1 );
start_julian = g_date_get_julian( &date1 );
for( interval = 1; interval <= 52; ++interval ) {
xaccFreqSpecSetWeekly( fs, &date1, interval );
for( i = 0; i <= 2 * 7 * interval; ++i ) {
g_date_set_julian( &date2, start_julian + i );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
do_test_args(
g_date_get_julian( &next_date ) - g_date_get_julian( &date2 ) ==
interval*7 - (i%(interval*7)),
"weekly repeats",
__FILE__, __LINE__,
"weekday = %d, interval = %d weeks, days from start = %d",
weekday, interval, i );
}
}
}
/* This tests whether we can correctly generate a sequence of dates,
* and end up in the right place. */
g_date_set_dmy( &date1, 25, 3, 2001 );
for( interval = 1; interval < 20; ++interval ) {
xaccFreqSpecSetWeekly( fs, &date1, interval );
for( j = 0; j < 2*53; ++j ) {
date2 = date1;
for( i = 0; i < j; ++i ) {
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
date2 = next_date;
}
do_test_args( g_date_get_julian( &date2 ) - g_date_get_julian( &date1 ) == interval*7*j,
"weekly repeats end up in the right place",
__FILE__, __LINE__, "interval = %d weeks, iters = %d",
interval, j );
}
}
fprintf(stdout, " FreqSpec: Weekly test OK, continuing . . . \r");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void
test_monthly (void)
{
guint32 interval, i, start_julian, monthday, month, j, day_of_year;
FreqSpec *fs;
GDate date0, date1, date2, next_date;
fs = xaccFreqSpecMalloc(book);
/* Use this to test any specific cases which fail,
* for easy access in the debugger. */
/*
g_date_set_dmy( &date1, 1, 1, 1 );
xaccFreqSpecSetMonthly( fs, &date1, 2 );
start_julian = g_date_get_julian( &date1 );
g_date_set_julian( &date2, start_julian + 0 );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
*/
for( monthday = 1; monthday <= 28; ++monthday ) {
for( month = 1; month <= 12; ++month ) {
g_date_set_dmy( &date1, monthday, month, 1 );
start_julian = g_date_get_julian( &date1 );
for( interval = 1; interval <= 24; ++interval ) {
xaccFreqSpecSetMonthly( fs, &date1, interval );
for( i = 0; i <= 2 * 31 * interval; ++i ) {
g_date_set_julian( &date2, start_julian + i );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
do_test_args(
g_date_get_day( &next_date ) == g_date_get_day( &date1 ),
"monthly repeats - check day",
__FILE__, __LINE__,
"monthday = %d, month = %d, interval = %d months, days from start = %d",
monthday, month, interval, i );
do_test_args(
( g_date_get_month( &next_date ) + 12 * (g_date_get_year( &next_date )-1) - 1) %
interval == (month-1) % interval,
"monthly repeats - check month",
__FILE__, __LINE__,
"monthday = %d, month = %d, interval = %d months, days from start = %d",
monthday, month, interval, i );
}
}
}
}
/* This tests whether we can correctly generate a sequence of dates,
* and end up in the right place. */
g_date_set_dmy( &date0, 1, 1, 2000 );
for( day_of_year = 1; day_of_year <= 365*5; ++day_of_year ) {
g_date_set_julian( &date1, g_date_get_julian( &date0 ) + day_of_year-1 );
for( interval = 1; interval < 20; ++interval ) {
xaccFreqSpecSetMonthly( fs, &date1, interval );
for( j = 1; j < 20; ++j ) {
date2 = date1;
for( i = 0; i < j; ++i ) {
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
date2 = next_date;
}
date2 = date1;
g_date_add_months( &date2, interval * j );
do_test_args( g_date_compare( &date2, &next_date ) == 0,
"monthly repeats end up in the right place",
__FILE__, __LINE__, "interval = %d months, iters = %d, day_of_year = %d",
interval, j, day_of_year );
}
}
}
fprintf(stdout, " FreqSpec: Monthly test OK, continuing . . . \r");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void
test_month_relative (void)
{
guint32 interval, i, start_julian, monthday, month, j;
FreqSpec *fs;
GDate date0, date1, date2, next_date;
fs = xaccFreqSpecMalloc(book);
/* Use this to test any specific cases which fail,
* for easy access in the debugger. */
/*
g_date_set_dmy( &date1, 1, 1, 1 );
xaccFreqSpecSetMonthRelative( fs, &date1, 2 );
start_julian = g_date_get_julian( &date1 );
g_date_set_julian( &date2, start_julian + 0 );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
*/
/* This loop does not test for days/occurences which can
* fail to fall in the same month. */
for( monthday = 1; monthday <= 28; ++monthday ) {
for( month = 1; month <= 12; ++month ) {
g_date_set_dmy( &date1, monthday, month, 1 );
start_julian = g_date_get_julian( &date1 );
for( interval = 1; interval <= 24; ++interval ) {
xaccFreqSpecSetMonthRelative( fs, &date1, interval );
for( i = 0; i <= 2 * 31 * interval; ++i ) {
g_date_set_julian( &date2, start_julian + i );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
do_test_args(
g_date_get_weekday( &next_date ) == g_date_get_weekday( &date1 ),
"month relative repeats - check weekday",
__FILE__, __LINE__,
"monthday = %d, month = %d, interval = %d months, days from start = %d, weekday = %d",
monthday, month, interval, i, g_date_get_weekday( &date1 ) );
do_test_args(
(g_date_get_day( &next_date )-1)/7 == (g_date_get_day( &date1 )-1)/7,
"month relative repeats - check occurrence",
__FILE__, __LINE__,
"monthday = %d, month = %d, interval = %d months, days from start = %d, occurrence = %d",
monthday, month, interval, i, (g_date_get_day( &date1 )-1)/7 );
do_test_args(
( g_date_get_month( &next_date ) + 12 * (g_date_get_year( &next_date )-1) - 1) %
interval == (month-1) % interval,
"month relative repeats - check month",
__FILE__, __LINE__,
"monthday = %d, month = %d, interval = %d months, days from start = %d",
monthday, month, interval, i );
}
}
}
}
/* This tests whether we can correctly generate a sequence of dates,
* and end up in the right place. */
/* Unfortunately, I think that this is going to require specifically
* written test cases, for the case where the repeat falls in the next
* (or subsequent) month in the cycle.... */
g_date_set_dmy( &date1, 1, 1, 2000 );
for( interval = 1; interval < 20; ++interval ) {
xaccFreqSpecSetMonthRelative( fs, &date1, interval );
for( j = 1; j < 20; ++j ) {
date2 = date1;
for( i = 0; i < j; ++i ) {
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
date2 = next_date;
}
date2 = date1;
g_date_add_months( &date2, interval * j );
do_test_args( g_date_get_month( &date2 ) == g_date_get_month( &next_date ),
"month_relative repeats end up in the right place - month",
__FILE__, __LINE__, "interval = %d months, iters = %d, weekday = %d",
interval, j, g_date_get_weekday( &date1 ) );
do_test_args( g_date_get_weekday( &date1 ) == g_date_get_weekday( &next_date ),
"month_relative repeats end up in the right place - weekday",
__FILE__, __LINE__, "interval = %d months, iters = %d, weekday = %d",
interval, j, g_date_get_weekday( &date1 ) );
do_test_args( (g_date_get_day( &date2 )-1)/7 == (g_date_get_day( &next_date )-1)/7,
"month_relative repeats end up in the right place - occurrence",
__FILE__, __LINE__, "interval = %d months, iters = %d, weekday = %d",
interval, j, g_date_get_weekday( &date1 ) );
}
}
/* also test oddball cases */
/* This is the fifth Sunday of a five Sunday month. */
g_date_set_dmy( &date0, 29, 4, 2001 );
xaccFreqSpecSetMonthRelative( fs, &date0, 1 );
xaccFreqSpecGetNextInstance( fs, &date0, &next_date );
g_date_set_dmy( &date1, 29, 7, 2001 );
do_test( g_date_compare( &next_date, &date1 ) == 0, "find five-sunday months" );
date2 = next_date;
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
g_date_set_dmy( &date1, 30, 9, 2001 );
do_test( g_date_compare( &next_date, &date1 ) == 0, "find five-sunday months" );
date2 = next_date;
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
g_date_set_dmy( &date1, 30, 12, 2001 );
do_test( g_date_compare( &next_date, &date1 ) == 0, "find five-sunday months" );
date2 = next_date;
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
g_date_set_dmy( &date1, 31, 3, 2002 );
do_test( g_date_compare( &next_date, &date1 ) == 0, "find five-sunday months" );
date2 = next_date;
fprintf(stdout, " FreqSpec: Relative months test OK, continuing . . . \r");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void test_caseA()
{
FreqSpec *fs;
GDate date0, date1, date2, date3;
fs = xaccFreqSpecMalloc(book);
g_date_set_dmy(&date0, 31, 12, 1); /* end of year */
xaccFreqSpecSetMonthly(fs, &date0, 3); /* quarterly */
g_date_set_dmy(&date1, 13, 2, 1); /* Feb 13th */
xaccFreqSpecGetNextInstance( fs, &date1, &date2 );
g_date_set_dmy( &date3, 31, 3, 1 ); /* Should get March 31st */
do_test( g_date_compare( &date2, &date3 ) == 0, "end of quarter" );
xaccFreqSpecFree(fs);
}
static void
test_composite (void)
{
FreqSpec *fs, *fs2;
GDate date0, date1, date2;
fs = xaccFreqSpecMalloc(book);
/* Use this to test any specific cases which fail,
* for easy access in the debugger. */
/*
g_date_set_dmy( &date1, 1, 1, 1 );
xaccFreqSpecSetMonthly( fs, &date1, 2 );
start_julian = g_date_get_julian( &date1 );
g_date_set_julian( &date2, start_julian + 0 );
xaccFreqSpecGetNextInstance( fs, &date2, &next_date );
*/
/* I have not tested this type as thoroughly
* because I expect that the elements from which it
* has been constructed have been pretty much tortured
* in the previous tests. I don't expect anything strange
* to go on here, at least for now... Maybe I'll put
* in more extensive tests later. */
xaccFreqSpecSetComposite( fs );
fs2 = xaccFreqSpecMalloc(book);
g_date_set_dmy( &date0, 29, 3, 2001 ); /* Wednesday */
xaccFreqSpecSetWeekly( fs2, &date0, 2 );
xaccFreqSpecCompositeAdd( fs, fs2 );
fs2 = xaccFreqSpecMalloc(book);
g_date_set_dmy( &date0, 3, 4, 2001 ); /* Tuesday */
xaccFreqSpecSetWeekly( fs2, &date0, 2 );
xaccFreqSpecCompositeAdd( fs, fs2 );
fs2 = xaccFreqSpecMalloc(book);
g_date_set_dmy( &date0, 7, 4, 2001 ); /* Saturday */
xaccFreqSpecSetWeekly( fs2, &date0, 2 );
xaccFreqSpecCompositeAdd( fs, fs2 );
fs2 = 0;
/* OK - now let's iterate it and see if we get the right sequence of dates. */
g_date_set_dmy( &date0, 26, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 29, 3, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0,
"first date in sequence" );
g_date_set_dmy( &date0, 27, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 29, 3, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0,
"first date in sequence" );
g_date_set_dmy( &date0, 28, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 29, 3, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "first date in sequence" );
g_date_set_dmy( &date0, 29, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 3, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "second date in sequence" );
g_date_set_dmy( &date0, 30, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 3, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "second date in sequence" );
g_date_set_dmy( &date0, 31, 3, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 3, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "second date in sequence" );
g_date_set_dmy( &date0, 1, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 3, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "second date in sequence" );
g_date_set_dmy( &date0, 2, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 3, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "second date in sequence" );
g_date_set_dmy( &date0, 3, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 7, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "third date in sequence" );
g_date_set_dmy( &date0, 4, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 7, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "third date in sequence" );
g_date_set_dmy( &date0, 5, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 7, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "third date in sequence" );
g_date_set_dmy( &date0, 6, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 7, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "third date in sequence" );
g_date_set_dmy( &date0, 7, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 12, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fourth date in sequence" );
g_date_set_dmy( &date0, 8, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 12, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fourth date in sequence" );
g_date_set_dmy( &date0, 9, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 12, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fourth date in sequence" );
g_date_set_dmy( &date0, 10, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 12, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fourth date in sequence" );
g_date_set_dmy( &date0, 11, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 12, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fourth date in sequence" );
g_date_set_dmy( &date0, 12, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 17, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fifth date in sequence" );
g_date_set_dmy( &date0, 13, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 17, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fifth date in sequence" );
g_date_set_dmy( &date0, 14, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 17, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fifth date in sequence" );
g_date_set_dmy( &date0, 15, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 17, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fifth date in sequence" );
g_date_set_dmy( &date0, 16, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 17, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "fifth date in sequence" );
g_date_set_dmy( &date0, 17, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 21, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "sixth date in sequence" );
g_date_set_dmy( &date0, 18, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 21, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "sixth date in sequence" );
g_date_set_dmy( &date0, 19, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 21, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "sixth date in sequence" );
g_date_set_dmy( &date0, 20, 4, 2001 );
xaccFreqSpecGetNextInstance( fs, &date0, &date1 );
g_date_set_dmy( &date2, 21, 4, 2001 );
do_test( g_date_compare( &date1, &date2 ) == 0, "sixth date in sequence" );
fprintf(stdout, " FreqSpec: Composite months test OK, cleaning up\n");
fflush(stdout);
xaccFreqSpecFree(fs);
}
static void
test_monthly_31st_bug_104844()
{
gchar date_buf[128];
GDate start, next, expected;
FreqSpec *fs = xaccFreqSpecMalloc(book);
g_date_clear(&next, 1);
g_date_clear(&start, 1);
g_date_set_dmy(&start, 31, 1, 2003);
xaccFreqSpecSetMonthly(fs, &start, 1);
//g_date_add_days(&start, 1);
xaccFreqSpecGetNextInstance(fs, &start, &next);
g_date_clear(&expected, 1);
g_date_set_dmy(&expected, 28, 2, 2003);
g_date_strftime(date_buf, 128, "%c", &next);
do_test(g_date_compare(&expected, &next) == 0, date_buf);
start = next;
xaccFreqSpecGetNextInstance(fs, &start, &next);
g_date_set_dmy(&expected, 31, 3, 2003);
g_date_strftime(date_buf, 128, "%c", &next);
do_test(g_date_compare(&expected, &next) == 0, date_buf);
// test...
g_date_set_dmy(&start, 31, 1, 2003);
xaccFreqSpecSetMonthly(fs, &start, 1);
g_date_set_dmy(&start, 31, 1, 2007);
xaccFreqSpecGetNextInstance(fs, &start, &next);
g_date_set_dmy(&expected, 28, 2, 2007);
g_date_strftime(date_buf, 128, "%c", &next);
do_test(g_date_compare(&expected, &next) == 0, date_buf);
start = next;
xaccFreqSpecGetNextInstance(fs, &start, &next);
g_date_set_dmy(&expected, 31, 3, 2007);
g_date_strftime(date_buf, 128, "%c", &next);
do_test(g_date_compare(&expected, &next) == 0, date_buf);
xaccFreqSpecFree(fs);
}
int
main (int argc, char **argv)
{
QofSession *session;
qof_init();
g_return_val_if_fail(cashobjects_register(), -1);
session = qof_session_new ();
book = qof_session_get_book(session);
test_monthly_31st_bug_104844();
test_once();
test_caseA();
test_daily();
test_weekly();
test_monthly();
test_month_relative();
test_composite();
print_test_results();
qof_session_end(session);
qof_close();
return (get_rv() > 1);
}

View File

@ -25,13 +25,10 @@
#include <glib.h>
#include "test-stuff.h"
#include "FreqSpec.h"
#include "Recurrence.h"
#include "gnc-engine.h"
static QofBook *book;
static FreqSpec *fs;
//#define FREQSPECTEST
static void check_valid(GDate *next, GDate *ref, GDate *start,
guint16 mult, PeriodType pt)
@ -47,16 +44,10 @@ static void check_valid(GDate *next, GDate *ref, GDate *start,
if (!valid) return;
// FreqSpec.h does claim to offer this.
do_test(g_date_compare(ref, next) < 0,
"next date not strictly later than ref date");
startToNext = g_date_get_julian(next) - g_date_get_julian(start);
// FreqSpec *doesn't* offer beginning dates.
#ifndef FREQSPECTEST
do_test(startToNext >= 0, "next date is before start date");
#endif
// Phase test
switch (pt) {
case PERIOD_YEAR:
@ -65,9 +56,6 @@ static void check_valid(GDate *next, GDate *ref, GDate *start,
mult *= 12;
// fall-through
case PERIOD_END_OF_MONTH:
#ifdef FREQSPECTEST
return; // FreqSpec doesn't have this case
#endif
if (pt == PERIOD_END_OF_MONTH)
do_test(g_date_is_last_of_month(next), "end of month phase wrong");
// fall-through
@ -131,36 +119,6 @@ static void check_valid(GDate *next, GDate *ref, GDate *start,
}
#ifdef FREQSPECTEST
static void convert_pt_to_fs(FreqSpec *fs, guint mult,
PeriodType pt, GDate *start)
{
switch (pt) {
case PERIOD_ONCE:
xaccFreqSpecSetOnceDate(fs, start);
break;
case PERIOD_DAY:
xaccFreqSpecSetDaily(fs, start, mult);
break;
case PERIOD_WEEK:
xaccFreqSpecSetWeekly(fs, start, mult);
break;
case PERIOD_MONTH:
xaccFreqSpecSetMonthly(fs, start, mult);
break;
case PERIOD_END_OF_MONTH:
// not handled
case PERIOD_NTH_WEEKDAY:
break;
case PERIOD_YEAR:
xaccFreqSpecSetMonthly(fs, start, 12*mult);
break;
default:
;
}
}
#endif
#define NUM_DATES_TO_TEST 300
#define NUM_DATES_TO_TEST_REF 300
#define NUM_MULT_TO_TEST 10
@ -193,10 +151,6 @@ static void test_all()
mult_reg = recurrenceGetMultiplier(&r);
recurrenceNextInstance(&r, &d_ref, &d_next);
#ifdef FREQSPECTEST
convert_pt_to_fs(fs, mult_reg, pt_reg, &d_start_reg);
xaccFreqSpecGetNextInstance(fs, &d_ref, &d_next);
#endif
check_valid(&d_next, &d_ref, &d_start_reg,
mult_reg, pt_reg);
@ -237,10 +191,6 @@ static void test_specific(PeriodType pt, guint16 mult,
recurrenceSet(&r, mult, pt, &start);
recurrenceNextInstance(&r, &ref, &next);
#ifdef FREQSPECTEST
convert_pt_to_fs(fs, mult, pt, &start);
xaccFreqSpecGetNextInstance(fs, &ref, &next);
#endif
check_valid(&next, &ref, &start, mult, pt);
if (!test_equal(&next, &true_next)) {
@ -344,13 +294,10 @@ static void test_some()
test_specific(PERIOD_MONTH, 1, 1,30,1, 2,27,1, 2,28,1);
test_specific(PERIOD_MONTH, 1, 2,28,1, 3,30,1, 4,28,1);
#ifdef FREQSPECTEST
test_specific(PERIOD_MONTH, 3, 12, 12, 1, 2, 1, 1, 3, 12, 1);
#else
test_specific(PERIOD_END_OF_MONTH, 1, 2,28,1, 3,30,1, 3,31,1);
test_specific(PERIOD_END_OF_MONTH, 5, 4,30,1, 4,21,1, 4,30,1);
test_specific(PERIOD_END_OF_MONTH, 5, 2,28,1, 5,21,1, 7,31,1);
#endif
test_specific(PERIOD_YEAR, 7, 6,8,199, 9,10,1338, 6,8,1340);
test_specific(PERIOD_YEAR, 2, 9,8,838, 6,30,1094, 9,8,1094);
@ -371,7 +318,6 @@ static void test_main()
{
book = qof_book_new ();
fs = xaccFreqSpecMalloc(book);
test_use();
@ -379,7 +325,6 @@ static void test_main()
test_all();
xaccFreqSpecFree(fs);
qof_book_destroy (book);
}

View File

@ -173,35 +173,6 @@ gnc_dense_cal_store_update_info(GncDenseCalStore *model, gchar *info)
g_signal_emit_by_name(model, "update", GUINT_TO_POINTER(1));
}
static void
gdcs_generic_update(GncDenseCalStore *trans, GDate *start, FreqSpec *fs)
{
int i;
GDate date;
date = *start;
/* go one day before what's in the box so we can get the correct start
* date. */
g_date_subtract_days(&date, 1);
xaccFreqSpecGetNextInstance(fs, &date, &date);
i = 0;
while ((i < trans->num_marks)
&& g_date_valid(&date)
/* Do checking against end restriction. */
&& ((trans->end_type == NEVER_END)
|| (trans->end_type == END_ON_DATE
&& g_date_compare(&date, &trans->end_date) <= 0)
|| (trans->end_type == END_AFTER_N_OCCS
&& i < trans->n_occurrences)))
{
*trans->cal_marks[i++] = date;
xaccFreqSpecGetNextInstance(fs, &date, &date);
}
trans->num_real_marks = (i == 0 ? 0 : (i-1));
g_signal_emit_by_name(trans, "update", GUINT_TO_POINTER(1));
}
static void
gdcs_generic_update_recurrences(GncDenseCalStore *trans, GDate *start, GList *recurrences)
{
@ -232,29 +203,6 @@ gdcs_generic_update_recurrences(GncDenseCalStore *trans, GDate *start, GList *re
g_signal_emit_by_name(trans, "update", GUINT_TO_POINTER(1));
}
void
gnc_dense_cal_store_update_no_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs)
{
model->end_type = NEVER_END;
gdcs_generic_update(model, start, fs);
}
void
gnc_dense_cal_store_update_count_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs, int num_occur)
{
model->end_type = END_AFTER_N_OCCS;
model->n_occurrences = num_occur;
gdcs_generic_update(model, start, fs);
}
void
gnc_dense_cal_store_update_date_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs, GDate *end_date)
{
model->end_type = END_ON_DATE;
model->end_date = *end_date;
gdcs_generic_update(model, start, fs);
}
void
gnc_dense_cal_store_update_recurrences_no_end(GncDenseCalStore *model, GDate *start, GList *recurrences)
{

View File

@ -26,7 +26,6 @@
#include "config.h"
#include <glib.h>
#include <glib-object.h>
#include <FreqSpec.h>
#include "gnc-dense-cal-model.h"
#include "gnc-dense-cal.h"
@ -50,10 +49,6 @@ void gnc_dense_cal_store_clear(GncDenseCalStore *model);
void gnc_dense_cal_store_update_name(GncDenseCalStore *model, gchar* name);
void gnc_dense_cal_store_update_info(GncDenseCalStore *model, gchar* info);
void gnc_dense_cal_store_update_no_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs);
void gnc_dense_cal_store_update_count_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs, int num_occur);
void gnc_dense_cal_store_update_date_end(GncDenseCalStore *model, GDate *start, FreqSpec *fs, GDate *end_date);
void gnc_dense_cal_store_update_recurrences_no_end(GncDenseCalStore *model, GDate *start, GList *recurrences);
void gnc_dense_cal_store_update_recurrences_count_end(GncDenseCalStore *model, GDate *start, GList *recurrences, int num_occur);
void gnc_dense_cal_store_update_recurrences_date_end(GncDenseCalStore *model, GDate *start, GList *recurrences, GDate *end_date);

View File

@ -31,11 +31,11 @@
#include <math.h>
#include <time.h>
#include "FreqSpec.h"
#include "dialog-utils.h"
#include "gnc-component-manager.h"
#include "gnc-engine.h"
#include "gnc-frequency.h"
#include "FreqSpec.h"
#include "gnc-ui-util.h"
#undef G_LOG_DOMAIN
@ -148,10 +148,10 @@ gnc_frequency_class_init( GncFrequencyClass *klass )
void
gnc_frequency_init(GncFrequency *gf)
{
int i;
GtkVBox *vb;
GtkWidget *o;
GtkAdjustment *adj;
int i;
GtkVBox* vb;
GtkWidget* o;
GtkAdjustment* adj;
static const struct comboBoxTuple {
char *name;
@ -229,438 +229,6 @@ gnc_frequency_init(GncFrequency *gf)
g_signal_connect(gf->startDate, "date_changed", G_CALLBACK(start_date_changed), gf);
}
static void
do_frequency_setup(GncFrequency *gf, FreqSpec *fs, time_t *secs)
{
UIFreqType uift;
/* Set the start date, but only if present. */
if (secs)
{
gnc_date_edit_set_time( gf->startDate, *secs);
if (NULL == fs)
{
g_signal_emit_by_name( gf, "changed" );
}
}
/* If freq spec not present, then we are done;
* don't change any other settings. */
if (NULL == fs) return;
uift = xaccFreqSpecGetUIType(fs);
switch ( uift )
{
case UIFREQ_NONE:
break;
case UIFREQ_ONCE:
{
GDate theDate;
struct tm stm;
/* set the date */
if ( xaccFreqSpecGetOnce( fs, &theDate ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d vs. FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ));
return;
}
g_date_to_struct_tm( &theDate, &stm );
gnc_date_edit_set_time( gf->startDate, mktime(&stm) );
gtk_notebook_set_current_page( gf->nb, PAGE_ONCE);
gtk_combo_box_set_active( gf->freqComboBox, PAGE_ONCE);
}
break;
case UIFREQ_DAILY:
{
GtkWidget *o;
int dailyMult = -1;
if ( xaccFreqSpecGetDaily( fs, &dailyMult ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d vs. FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ) );
return;
}
o = glade_xml_get_widget( gf->gxml, "daily_spin" );
gtk_spin_button_set_value( GTK_SPIN_BUTTON( o ), dailyMult );
gtk_notebook_set_current_page( gf->nb, PAGE_DAILY);
gtk_combo_box_set_active( gf->freqComboBox, PAGE_DAILY);
}
break;
case UIFREQ_DAILY_MF:
case UIFREQ_WEEKLY:
case UIFREQ_BI_WEEKLY:
{
const char * str;
int weeklyMult = -1;
int dayOfWeek;
GtkWidget *o;
FreqSpec *subFS;
GList *list;
for ( list = xaccFreqSpecCompositeGet( fs );
list; list = g_list_next(list) ) {
subFS = (FreqSpec*)(list->data);
if ( weeklyMult == -1 ) {
if ( subFS == NULL ) {
g_critical("subFS is null");
return;
}
if ( xaccFreqSpecGetWeekly( subFS,
&weeklyMult,
&dayOfWeek ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d, FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ) );
return;
}
} else {
int otherWeeklyMult = -1;
if ( subFS == NULL ) {
g_critical("subFS is null");
return;
}
if ( xaccFreqSpecGetWeekly( subFS,
&otherWeeklyMult,
&dayOfWeek ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d, FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ) );
return;
}
if ( weeklyMult != otherWeeklyMult ) {
g_warning("Inconsistent weekly FreqSpec multipliers seen [first: %d vs. other: %d]",
weeklyMult, otherWeeklyMult );
return;
}
}
if ( dayOfWeek > 6 ) {
g_warning( "dayOfWeek > 6 [%d]", dayOfWeek );
return;
}
str = CHECKBOX_NAMES[dayOfWeek];
o = glade_xml_get_widget( gf->gxml, str );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(o), TRUE );
}
o = glade_xml_get_widget( gf->gxml, "weekly_spin" );
if (uift == UIFREQ_BI_WEEKLY)
weeklyMult = 2;
gtk_spin_button_set_value( GTK_SPIN_BUTTON(o), weeklyMult );
gtk_notebook_set_current_page( gf->nb, PAGE_WEEKLY);
gtk_combo_box_set_active( gf->freqComboBox, PAGE_WEEKLY);
}
break;
case UIFREQ_SEMI_MONTHLY:
{
GtkWidget *o;
GList *list;
int monthlyMult;
FreqSpec *subFS;
int firstDayOfMonth, secondDayOfMonth, monthOffset;
list = xaccFreqSpecCompositeGet( fs );
/* mult */
o = glade_xml_get_widget( gf->gxml, "semimonthly_spin" );
subFS = (FreqSpec*)(g_list_nth( list, 0 )->data);
if ( xaccFreqSpecGetMonthly( subFS, &monthlyMult,
&firstDayOfMonth, &monthOffset ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d, FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ) );
return;
}
gtk_spin_button_set_value( GTK_SPIN_BUTTON(o), monthlyMult );
/* first date */
o = glade_xml_get_widget( gf->gxml, "semimonthly_first" );
gtk_combo_box_set_active( GTK_COMBO_BOX(o), firstDayOfMonth-1 );
/* second date */
subFS = (FreqSpec*)(g_list_nth( list, 1 )->data);
o = glade_xml_get_widget( gf->gxml, "semimonthly_second" );
if ( xaccFreqSpecGetMonthly( subFS, &monthlyMult,
&secondDayOfMonth, &monthOffset ) < 0 ) {
g_warning( "Inappropriate FreqSpec type" );
return;
}
gtk_combo_box_set_active( GTK_COMBO_BOX(o), secondDayOfMonth-1 );
gtk_notebook_set_current_page( gf->nb, PAGE_SEMI_MONTHLY);
gtk_combo_box_set_active( gf->freqComboBox, PAGE_SEMI_MONTHLY);
}
break;
case UIFREQ_MONTHLY:
case UIFREQ_QUARTERLY:
case UIFREQ_TRI_ANUALLY:
case UIFREQ_SEMI_YEARLY:
case UIFREQ_YEARLY:
{
GtkWidget *o;
int monthlyMult, dayOfMonth, monthOffset;
if ( xaccFreqSpecGetMonthly( fs, &monthlyMult,
&dayOfMonth, &monthOffset ) < 0 ) {
g_warning("Inappropriate FreqSpec type [gnc-frequency: %d, FreqSpec: %d]",
uift, xaccFreqSpecGetUIType( fs ) );
return;
}
o = glade_xml_get_widget( gf->gxml, "monthly_spin" );
gtk_spin_button_set_value( GTK_SPIN_BUTTON(o), monthlyMult );
o = glade_xml_get_widget( gf->gxml, "monthly_day" );
gtk_combo_box_set_active( GTK_COMBO_BOX(o), dayOfMonth-1 );
/* set the day-of-month */
gtk_notebook_set_current_page( gf->nb, PAGE_MONTHLY);
gtk_combo_box_set_active( gf->freqComboBox, PAGE_MONTHLY);
}
break;
default:
g_critical( "unknown ui freq type %d", uift);
break;
}
g_signal_emit_by_name( gf, "changed" );
}
static void
gnc_frequency_setup_default( GncFrequency *gf, FreqSpec *fs, GDate *date )
{
time_t secs;
/* If no freq-spec, then set the widget to blank */
if (NULL == fs)
{
UIFreqType uift = UIFREQ_NONE;
int i, page;
page = -1;
for ( i=0; i < UIFREQ_NUM_UI_FREQSPECS+1; i++ )
{
if ( PAGES[i].uiFTVal == uift )
{
page = PAGES[i].idx;
break;
}
}
g_assert( page != -1 );
gtk_notebook_set_current_page( gf->nb, page );
gtk_combo_box_set_active( gf->freqComboBox, page );
}
/* Setup the start date */
if (!date || ! g_date_valid(date) )
{
secs = time(NULL);
}
else
{
struct tm stm;
g_date_to_struct_tm( date, &stm);
secs = mktime (&stm);
}
do_frequency_setup(gf, fs, &secs);
}
void
gnc_frequency_setup( GncFrequency *gf, FreqSpec *fs, GDate *date )
{
time_t secs;
if (!gf) return;
/* Setup the start date */
if (!date || !g_date_valid(date))
{
do_frequency_setup(gf, fs, NULL);
}
else
{
struct tm stm;
g_date_to_struct_tm( date, &stm);
secs = mktime (&stm);
do_frequency_setup(gf, fs, &secs);
}
}
GtkWidget *
gnc_frequency_new( FreqSpec *fs, GDate *date )
{
GncFrequency *toRet;
toRet = g_object_new( gnc_frequency_get_type(), NULL );
gnc_frequency_setup_default( toRet, fs, date );
return GTK_WIDGET(toRet);
}
void
gnc_frequency_save_state( GncFrequency *gf, FreqSpec *fs, GDate *outDate )
{
gint page;
gint day;
GtkWidget *o;
UIFreqType uift;
FreqSpec *tmpFS;
gint tmpInt;
int i;
GDate gd;
time_t start_tt;
start_tt = gnc_date_edit_get_date( gf->startDate );
if ( NULL != outDate )
{
g_date_set_time_t( outDate, start_tt );
}
if (NULL == fs) return;
/* Get the current tab */
page = gtk_notebook_get_current_page( gf->nb );
/* We're going to be creating/destroying FreqSpecs,
* which will cause GUI refreshes. :( */
gnc_suspend_gui_refresh();
g_date_clear (&gd, 1);
g_date_set_time_t( &gd, start_tt );
/*uift = xaccFreqSpecGetUIType( fs );*/
uift = PAGES[page].uiFTVal;
/* Based on value, parse widget values into FreqSpec */
switch ( uift ) {
case UIFREQ_NONE:
xaccFreqSpecSetNone(fs);
xaccFreqSpecSetUIType(fs, UIFREQ_NONE);
break;
case UIFREQ_ONCE:
xaccFreqSpecSetOnceDate(fs, &gd);
xaccFreqSpecSetUIType( fs, uift );
break;
case UIFREQ_DAILY:
o = glade_xml_get_widget( gf->gxml, "daily_spin" );
/* FIXME: initial date should be set correctly. */
{
gint foo;
foo = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(o) );
xaccFreqSpecSetDaily( fs, &gd, foo );
xaccFreqSpecSetUIType( fs, uift );
}
break;
case UIFREQ_WEEKLY:
{
struct tm stm;
GDate gd2;
xaccFreqSpecSetComposite( fs );
xaccFreqSpecSetUIType( fs, uift );
o = glade_xml_get_widget( gf->gxml, "weekly_spin" );
tmpInt = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(o) );
/* assume we have a good calendar that allows week selection. */
/* for-now hack: normalize to Sunday. */
g_date_to_struct_tm( &gd, &stm);
stm.tm_mday -= stm.tm_wday % 7;
g_date_set_time_t( &gd, mktime(&stm) );
/* now, go through the check boxes and add composites based on that date. */
for ( i=0; CHECKBOX_NAMES[i]!=NULL; i++ ) {
o = glade_xml_get_widget( gf->gxml, CHECKBOX_NAMES[i] );
if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ) {
tmpFS = xaccFreqSpecMalloc
(gnc_get_current_book ());
xaccFreqSpecSetUIType( tmpFS, uift );
g_date_clear (&gd2, 1);
gd2 = gd;
/* Add 'i' days off of Sunday... */
g_date_add_days( &gd2, i );
xaccFreqSpecSetWeekly( tmpFS, &gd2, tmpInt );
xaccFreqSpecCompositeAdd( fs, tmpFS );
}
}
break;
}
case UIFREQ_SEMI_MONTHLY:
{
struct tm stm;
/* FIXME: this is b0rken date calculation for mday>28 */
xaccFreqSpecSetComposite( fs );
xaccFreqSpecSetUIType( fs, uift );
o = glade_xml_get_widget( gf->gxml, "semimonthly_spin" );
tmpInt = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(o) );
o = glade_xml_get_widget( gf->gxml, "semimonthly_first" );
day = gtk_combo_box_get_active( GTK_COMBO_BOX(o) )+1;
if (day > 30)
{
g_critical("freq spec doesn't support last-day-of-month");
day = 30;
}
tmpFS = xaccFreqSpecMalloc(gnc_get_current_book ());
g_date_to_struct_tm( &gd, &stm);
if ( day >= stm.tm_mday ) {
/* next month */
stm.tm_mon += 1;
}
/* else, this month */
stm.tm_mday = day;
g_date_set_time_t( &gd, mktime( &stm) );
xaccFreqSpecSetMonthly( tmpFS, &gd, tmpInt );
xaccFreqSpecCompositeAdd( fs, tmpFS );
o = glade_xml_get_widget( gf->gxml, "semimonthly_second" );
day = gtk_combo_box_get_active( GTK_COMBO_BOX(o) )+1;
if (day > 30)
{
g_critical("freq spec doesn't support last-day-of-month");
day = 30;
}
tmpFS = xaccFreqSpecMalloc(gnc_get_current_book ());
start_tt = gnc_date_edit_get_date( gf->startDate );
g_date_set_time_t( &gd, start_tt );
g_date_to_struct_tm( &gd, &stm);
if ( day >= stm.tm_mday ) {
/* next month */
stm.tm_mon += 1;
}
/* else, this month */
stm.tm_mday = day;
g_date_set_time_t( &gd, mktime( &stm ) );
xaccFreqSpecSetMonthly( tmpFS, &gd, tmpInt );
xaccFreqSpecCompositeAdd( fs, tmpFS );
break;
}
case UIFREQ_MONTHLY:
{
o = glade_xml_get_widget( gf->gxml, "monthly_spin" );
tmpInt = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(o));
o = glade_xml_get_widget( gf->gxml, "monthly_day" );
day = gtk_combo_box_get_active( GTK_COMBO_BOX(o) ) + 1;
if (day > 30)
{
g_critical("freq spec doesn't support last-day-of-month");
day = 30;
}
g_date_set_time_t(&gd, time(NULL));
g_date_set_month(&gd, 1);
g_date_set_day(&gd, day);
{
gchar buf[128];
g_date_strftime(buf, 127, "%c", &gd);
g_debug("monthly date [%s]\n", buf);
}
xaccFreqSpecSetMonthly( fs, &gd, tmpInt );
xaccFreqSpecSetUIType( fs, uift );
break;
}
default:
g_critical("Unknown UIFreqType %d", uift);
break;
}
gnc_resume_gui_refresh();
}
static void
spin_changed_helper( GtkAdjustment *adj, gpointer d )
{
@ -734,9 +302,14 @@ gnc_frequency_set_date_label_text(GncFrequency *gf, const gchar *txt)
gtk_label_set_text (lbl, txt);
}
GtkWidget*
gnc_frequency_new_from_recurrence(GList *recurrences, GDate *start_date)
{
return gnc_frequency_new(recurrences, start_date);
}
GtkWidget*
gnc_frequency_new(GList *recurrences, GDate *start_date)
{
GncFrequency *toRet;
toRet = g_object_new(gnc_frequency_get_type(), NULL);
@ -787,6 +360,12 @@ _get_monthly_combobox_index(Recurrence *r)
void
gnc_frequency_setup_recurrence(GncFrequency *gf, GList *recurrences, GDate *start_date)
{
gnc_frequency_setup(gf, recurrences, start_date);
}
void
gnc_frequency_setup(GncFrequency *gf, GList *recurrences, GDate *start_date)
{
gboolean made_changes = FALSE;

View File

@ -26,8 +26,8 @@
#define GNC_FREQUENCY_H
#include "gnc-date-edit.h"
#include "Recurrence.h"
#include "FreqSpec.h"
#include "Recurrence.h"
#define GNC_TYPE_FREQUENCY (gnc_frequency_get_type())
#define GNC_FREQUENCY(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, GNC_TYPE_FREQUENCY, GncFrequency)
@ -67,11 +67,9 @@ struct pageDataTuple
GType gnc_frequency_get_type(void);
/**
* Create a new GncFrequencey widget, reflecting the given FreqSpec \a fs and
* starting on \a start_date. Either or both may be NULL for reasonable
* defaults.
* Either or both param may be NULL for reasonable defaults.
**/
GtkWidget* gnc_frequency_new(FreqSpec *fs, GDate *start_date);
GtkWidget* gnc_frequency_new(GList *recurrences, GDate *start_date);
GtkWidget* gnc_frequency_new_from_recurrence(GList *recurrences, GDate *start_date);
void gnc_frequency_init(GncFrequency *gf);
@ -81,7 +79,7 @@ void gnc_frequency_init(GncFrequency *gf);
* If the FreqSpec is NULL, then no change is made to the widget menus.
* If the date is NULL, then no change is made to the widget date field.
**/
void gnc_frequency_setup(GncFrequency *gf, FreqSpec *fs, GDate *date);
void gnc_frequency_setup(GncFrequency *gf, GList *recurrences, GDate *start_date);
void gnc_frequency_setup_recurrence(GncFrequency *gf, GList *recurrences, GDate *start_date);
/**
@ -89,7 +87,6 @@ void gnc_frequency_setup_recurrence(GncFrequency *gf, GList *recurrences, GDate
* Updates the given FreqSpec if it's not NULL.
* Places the date in outDate, if it's not NULL.
**/
void gnc_frequency_save_state(GncFrequency *gf, FreqSpec *fs, GDate *outDate);
void gnc_frequency_save_to_recurrence(GncFrequency *gf, GList **recurrences, GDate *out_start_date);
/**

View File

@ -41,7 +41,6 @@
#include "qof.h"
#include "gnc-book.h"
#include "Account.h"
#include "FreqSpec.h"
#include "SchedXaction.h"
#include "SX-book.h"
#include "dialog-preferences.h"
@ -948,19 +947,10 @@ gnc_sxed_save_sx( GncSxEditorDialog *sxed )
/* start date and freq spec */
{
FreqSpec *fs;
GDate gdate;
GString *str;
GList *schedule = NULL;
fs = xaccSchedXactionGetFreqSpec( sxed->sx );
gnc_frequency_save_state( sxed->gncfreq, fs, &gdate );
str = g_string_new( "" );
xaccFreqSpecGetFreqStr( fs, str );
g_debug("freq spec: %s", str->str);
g_string_free(str, TRUE);
gnc_frequency_save_to_recurrence(sxed->gncfreq, &schedule, &gdate);
gnc_sx_set_schedule(sxed->sx, schedule);
{

View File

@ -473,7 +473,7 @@ ap_close_period (GnomeDruidPage *druidpage,
}
/* Load up the GUI for the next closing period. */
gnc_frequency_setup (info->period_menu, NULL, &info->closing_date);
gnc_frequency_setup_recurrence(info->period_menu, NULL, &info->closing_date);
show_book_details (info);
return TRUE;

View File

@ -1547,11 +1547,11 @@ ld_pay_save_current( LoanDruidData *ldd )
}
/* if ( rb toggled )
* ensure freqspec/startdate setup
* ensure schedule/startdate setup
* save
* else
* if (freqspec setup)
* remove freqspec/startdate
* remove schedule/startdate
*/
/* neither of these should happen. */