GnuCash c935c2f+
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions
gnc-sx-instance-model.h File Reference
#include <config.h>
#include <glib.h>
#include <glib-object.h>
#include "gnc-numeric.h"
#include "SchedXaction.h"

Go to the source code of this file.

Data Structures

struct  GncSxInstances
 
struct  GncSxVariable
 
struct  GncSxInstance
 
struct  GncSxVariableNeeded
 
struct  GncSxSummary
 

Macros

#define GNC_TYPE_SX_INSTANCE_MODEL   (gnc_sx_instance_model_get_type ())
 

Enumerations

enum  GncSxInstanceState {
  SX_INSTANCE_STATE_IGNORED , SX_INSTANCE_STATE_POSTPONED , SX_INSTANCE_STATE_TO_CREATE , SX_INSTANCE_STATE_REMINDER ,
  SX_INSTANCE_STATE_CREATED , SX_INSTANCE_STATE_MAX_STATE
}
 

Functions

GncSxInstanceModel * gnc_sx_get_current_instances (void)
 Shorthand for get_instances(now, FALSE);.
 
GncSxInstanceModel * gnc_sx_get_instances (const GDate *range_end, gboolean include_disabled)
 Allocates a new SxInstanceModel and fills it with generated instances for all scheduled transactions up to the given range_end date.
 
GncSxInstanceModel * gnc_sx_get_select_instances (GList *sel_sxes)
 Allocates a new SxInstanceModel and fills it with generated instances for the given scheduled transactions up to now.
 
void gnc_sx_instance_model_update_sx_instances (GncSxInstanceModel *model, SchedXaction *sx)
 Regenerates and updates the GncSxInstances* for the given SX.
 
void gnc_sx_instance_model_remove_sx_instances (GncSxInstanceModel *model, SchedXaction *sx)
 
void gnc_sx_scrub_split_numerics (gpointer psplit, gpointer user)
 Fix up numerics where they've gotten out-of-sync with the formulas.
 
GList * gnc_sx_instance_get_variables (GncSxInstance *inst)
 
Accountgnc_sx_get_template_transaction_account (const SchedXaction *sx)
 
GHashTable * gnc_sx_instance_get_variables_for_parser (GHashTable *instance_var_hash)
 
GncSxVariablegnc_sx_variable_new_full (gchar *name, gnc_numeric value, gboolean editable)
 
void gnc_sx_variable_free (GncSxVariable *var)
 
void gnc_sx_instance_model_change_instance_state (GncSxInstanceModel *model, GncSxInstance *instance, GncSxInstanceState new_state)
 There is a constraint around a sequence of upcoming instance states.
 
void gnc_sx_instance_model_set_variable (GncSxInstanceModel *model, GncSxInstance *instance, GncSxVariable *variable, gnc_numeric *new_value)
 
GList * gnc_sx_instance_model_check_variables (GncSxInstanceModel *model)
 
void gnc_sx_instance_model_effect_change (GncSxInstanceModel *model, gboolean auto_create_only, GList **created_transaction_guids, GList **creation_errors)
 Really ("effectively") create the transactions from the SX instances in the given model.
 
void gnc_sx_instance_model_summarize (GncSxInstanceModel *model, GncSxSummary *summary)
 
void gnc_sx_summary_print (const GncSxSummary *summary)
 Debug output to trace file.
 
void gnc_sx_get_variables (SchedXaction *sx, GHashTable *var_hash)
 
int gnc_sx_parse_vars_from_formula (const char *formula, GHashTable *var_hash, gnc_numeric *result)
 
void gnc_sx_randomize_variables (GHashTable *vars)
 
GHashTable * gnc_g_hash_new_guid_numeric (void)
 Returns a GHashTable<GUID*, gnc_numeric*> with no destructor for the key, but a destructor for the value set.
 
void gnc_sx_all_instantiate_cashflow (GList *all_sxes, const GDate *range_start, const GDate *range_end, GHashTable *map, GList **creation_errors)
 Instantiates the cash flow of all given SXs (in the given GList<SchedXAction*>) into the GHashTable<GUID*, gnc_numeric*> for the given date range.
 
GHashTable * gnc_sx_all_instantiate_cashflow_all (GDate range_start, GDate range_end)
 Simplified wrapper around gnc_sx_all_instantiate_cashflow(): Run that function on all SX of the current book for the given date range.
 
GList * gnc_sx_instance_model_get_sx_instances_list (GncSxInstanceModel *model)
 Returns the list of GncSxInstances in the model (Each element in the list has type GncSxInstances)
 

Macro Definition Documentation

◆ GNC_TYPE_SX_INSTANCE_MODEL

#define GNC_TYPE_SX_INSTANCE_MODEL   (gnc_sx_instance_model_get_type ())

Definition at line 37 of file gnc-sx-instance-model.h.

Enumeration Type Documentation

◆ GncSxInstanceState

enum GncSxInstanceState

Definition at line 52 of file gnc-sx-instance-model.h.

53{
54 SX_INSTANCE_STATE_IGNORED,
55 SX_INSTANCE_STATE_POSTPONED,
56 SX_INSTANCE_STATE_TO_CREATE,
57 SX_INSTANCE_STATE_REMINDER,
58 SX_INSTANCE_STATE_CREATED,
59 SX_INSTANCE_STATE_MAX_STATE
60} GncSxInstanceState;

Function Documentation

◆ gnc_g_hash_new_guid_numeric()

GHashTable * gnc_g_hash_new_guid_numeric ( void  )

Returns a GHashTable<GUID*, gnc_numeric*> with no destructor for the key, but a destructor for the value set.

The returned value must be free'd with g_hash_table_destroy or g_hash_table_unref.

Definition at line 1720 of file gnc-sx-instance-model.c.

1721{
1722 return g_hash_table_new_full (guid_hash_to_guint, guid_g_hash_table_equal,
1723 NULL, gnc_numeric_free);
1724}
guint guid_hash_to_guint(gconstpointer ptr)
Hash function for a GUID.
Definition guid.cpp:255
gint guid_g_hash_table_equal(gconstpointer guid_a, gconstpointer guid_b)
Equality function for two GUIDs in a GHashTable.
Definition guid.cpp:269

◆ gnc_sx_all_instantiate_cashflow()

void gnc_sx_all_instantiate_cashflow ( GList *  all_sxes,
const GDate *  range_start,
const GDate *  range_end,
GHashTable *  map,
GList **  creation_errors 
)

Instantiates the cash flow of all given SXs (in the given GList<SchedXAction*>) into the GHashTable<GUID*, gnc_numeric*> for the given date range.

Each SX is counted with multiplicity as it has occurrences in the given date range.

The creation_errors list, if non-NULL, receive any errors that occurred during creation, similar as in gnc_sx_instance_model_effect_change().

Definition at line 1953 of file gnc-sx-instance-model.c.

1956{
1957 SxAllCashflow userdata;
1958 userdata.hash = map;
1959 userdata.creation_errors = creation_errors;
1960 userdata.range_start = range_start;
1961 userdata.range_end = range_end;
1962
1963 /* The work is done in the callback for each SX */
1964 g_list_foreach(all_sxes, instantiate_cashflow_cb, &userdata);
1965}

◆ gnc_sx_all_instantiate_cashflow_all()

GHashTable * gnc_sx_all_instantiate_cashflow_all ( GDate  range_start,
GDate  range_end 
)

Simplified wrapper around gnc_sx_all_instantiate_cashflow(): Run that function on all SX of the current book for the given date range.

Ignore any potential error messages. Returns a newly allocated GHashTable with the result, which is a GHashTable<GUID*, gnc_numeric*>, identical to what gnc_g_hash_new_guid_numeric() would return. The returned value must be free'd with g_hash_table_destroy.

Definition at line 1968 of file gnc-sx-instance-model.c.

1969{
1970 GHashTable *result_map = gnc_g_hash_new_guid_numeric();
1971 GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
1972 gnc_sx_all_instantiate_cashflow(all_sxes,
1973 &range_start, &range_end,
1974 result_map, NULL);
1975 return result_map;
1976}

◆ gnc_sx_get_current_instances()

GncSxInstanceModel * gnc_sx_get_current_instances ( void  )

Shorthand for get_instances(now, FALSE);.

Definition at line 594 of file gnc-sx-instance-model.c.

595{
596 GDate now;
597 g_date_clear(&now, 1);
598 gnc_gdate_set_time64 (&now, gnc_time (NULL));
599 return gnc_sx_get_instances(&now, FALSE);
600}
void gnc_gdate_set_time64(GDate *gd, time64 time)
Set a GDate to a time64.
time64 gnc_time(time64 *tbuf)
get the current time
Definition gnc-date.cpp:262

◆ gnc_sx_get_instances()

GncSxInstanceModel * gnc_sx_get_instances ( const GDate *  range_end,
gboolean  include_disabled 
)

Allocates a new SxInstanceModel and fills it with generated instances for all scheduled transactions up to the given range_end date.

The caller must unref the returned object by g_object_unref(G_OBJECT(inst_model)); when no longer in use.

Definition at line 603 of file gnc-sx-instance-model.c.

604{
605 GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
606 GncSxInstanceModel *instances;
607
608 g_assert(range_end != NULL);
609 g_assert(g_date_valid(range_end));
610
611 instances = gnc_sx_instance_model_new();
612 instances->include_disabled = include_disabled;
613 instances->range_end = *range_end;
614
615 if (include_disabled)
616 {
617 instances->sx_instance_list = gnc_g_list_map(all_sxes, (GncGMapFunc)_gnc_sx_gen_instances, (gpointer)range_end);
618 }
619 else
620 {
621 GList *sx_iter = g_list_first(all_sxes);
622 GList *enabled_sxes = NULL;
623
624 for (; sx_iter != NULL; sx_iter = sx_iter->next)
625 {
626 SchedXaction *sx = (SchedXaction*)sx_iter->data;
627 if (xaccSchedXactionGetEnabled(sx))
628 {
629 enabled_sxes = g_list_prepend (enabled_sxes, sx);
630 }
631 }
632 enabled_sxes = g_list_reverse (enabled_sxes);
633 instances->sx_instance_list = gnc_g_list_map(enabled_sxes, (GncGMapFunc)_gnc_sx_gen_instances, (gpointer)range_end);
634 g_list_free(enabled_sxes);
635 }
636
637 return instances;
638}
GList * gnc_g_list_map(GList *list, GncGMapFunc fn, gpointer user_data)

◆ gnc_sx_get_select_instances()

GncSxInstanceModel * gnc_sx_get_select_instances ( GList *  sel_sxes)

Allocates a new SxInstanceModel and fills it with generated instances for the given scheduled transactions up to now.

If no instance exists for a given scheduled transaction, the next instance is generated.

The caller must unref the returned object by g_object_unref(G_OBJECT(inst_model)); when no longer in use.

Definition at line 641 of file gnc-sx-instance-model.c.

642{
643 GncSxInstanceModel *instances;
644 GDate now;
645
646 g_date_clear(&now, 1);
647 gnc_gdate_set_time64(&now, gnc_time(NULL));
648
649 instances = gnc_sx_instance_model_new();
650 instances->include_disabled = TRUE;
651 instances->range_end = now;
652
653 instances->sx_instance_list = gnc_g_list_map(sel_sxes, (GncGMapFunc)sx_gen_select_instances, (gpointer)&now);
654
655 return instances;
656}

◆ gnc_sx_get_template_transaction_account()

Account * gnc_sx_get_template_transaction_account ( const SchedXaction *  sx)

Definition at line 379 of file gnc-sx-instance-model.c.

380{
381 Account *template_root, *sx_template_acct;
382 char sx_guid_str[GUID_ENCODING_LENGTH+1];
383
384 template_root = gnc_book_get_template_root(gnc_get_current_book());
386 sx_template_acct = gnc_account_lookup_by_name(template_root, sx_guid_str);
387 return sx_template_acct;
388}
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
Definition Account.cpp:3093
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition guid.h:84
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition guid.cpp:208
#define xaccSchedXactionGetGUID(X)
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
Definition SX-book.cpp:65
STRUCTS.

◆ gnc_sx_get_variables()

void gnc_sx_get_variables ( SchedXaction *  sx,
GHashTable *  var_hash 
)

Definition at line 391 of file gnc-sx-instance-model.c.

392{
393 Account *sx_template_acct = gnc_sx_get_template_transaction_account(sx);
394 xaccAccountForEachTransaction(sx_template_acct, _get_vars_helper, var_hash);
395}
gint xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, void *data)
The xaccAccountForEachTransaction() routine will traverse all of the transactions in account and call...
Definition Account.cpp:5150

◆ gnc_sx_instance_get_variables()

GList * gnc_sx_instance_get_variables ( GncSxInstance inst)
Returns
GList<GncSxVariable*>. Caller owns the list, but not the items.

Definition at line 475 of file gnc-sx-instance-model.c.

476{
477 GList *vars = NULL;
478 g_hash_table_foreach(inst->variable_bindings, _build_list_from_hash_elts, &vars);
479 return g_list_sort (vars, _compare_GncSxVariables);
480}
GHashTable * variable_bindings
variable bindings.

◆ gnc_sx_instance_get_variables_for_parser()

GHashTable * gnc_sx_instance_get_variables_for_parser ( GHashTable *  instance_var_hash)
Returns
caller-owned data struct.
caller-owned.

Definition at line 225 of file gnc-sx-instance-model.c.

226{
227 GHashTable *parser_vars;
228
229 parser_vars = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
230 g_hash_table_foreach(instance_var_hash, (GHFunc)_sx_var_to_raw_numeric, parser_vars);
231 return parser_vars;
232}

◆ gnc_sx_instance_model_change_instance_state()

void gnc_sx_instance_model_change_instance_state ( GncSxInstanceModel *  model,
GncSxInstance instance,
GncSxInstanceState  new_state 
)

There is a constraint around a sequence of upcoming instance states.

In short: the last-created state and a list of postponed instances are modeled, but upcoming reminders are not. As such, a reminder can never be before any other (modeled) instance type. For instance, the following sequences are disallowed:

[...] remind <- will be lost/skipped over; must be converted to postponed. to-create <- this will be the last-recorded state. [...]

[...] remind <- same as previous; will be lost/skipped; must be postponed. postponed [...]

remind <- same... ignore [...]

As such, the SinceLastRun model will enforce that there are no previous remind instances at every state change. They will be silently converted to postponed-state transactions.

Definition at line 1557 of file gnc-sx-instance-model.c.

1560{
1561 if (instance->state == new_state)
1562 return;
1563
1564 instance->state = new_state;
1565
1566 // ensure 'remind' constraints are met:
1567 {
1568 GList *inst_iter;
1569 inst_iter = g_list_find(instance->parent->instance_list, instance);
1570 g_assert(inst_iter != NULL);
1571 if (instance->state != SX_INSTANCE_STATE_REMINDER)
1572 {
1573 // iterate backwards, making sure reminders are changed to 'postponed'
1574 for (inst_iter = inst_iter->prev; inst_iter != NULL; inst_iter = inst_iter->prev)
1575 {
1576 GncSxInstance *prev_inst = (GncSxInstance*)inst_iter->data;
1577 if (prev_inst->state != SX_INSTANCE_STATE_REMINDER)
1578 continue;
1579 prev_inst->state = SX_INSTANCE_STATE_POSTPONED;
1580 }
1581 }
1582 else
1583 {
1584 // iterate forward, make sure transactions are set to 'remind'
1585 for (inst_iter = inst_iter->next; inst_iter != NULL; inst_iter = inst_iter->next)
1586 {
1587 GncSxInstance *next_inst = (GncSxInstance*)inst_iter->data;
1588 if (next_inst->state == SX_INSTANCE_STATE_REMINDER)
1589 continue;
1590 next_inst->state = SX_INSTANCE_STATE_REMINDER;
1591 }
1592 }
1593 }
1594
1595 g_signal_emit_by_name(model, "updated", (gpointer)instance->parent->sx);
1596}
GncSxInstanceState state
the current state of the instance (during editing)
GncSxInstances * parent
the parent instances collection.
GList * instance_list
GList<GncSxInstance*>

◆ gnc_sx_instance_model_check_variables()

GList * gnc_sx_instance_model_check_variables ( GncSxInstanceModel *  model)
Returns
List<GncSxVariableNeeded> of unbound {instance,variable} pairs; the caller owns the list and the items.

Definition at line 1618 of file gnc-sx-instance-model.c.

1619{
1620 GList *rtn = NULL;
1621 GList *sx_iter, *inst_iter, *var_list = NULL, *var_iter;
1622
1623 for (sx_iter = model->sx_instance_list; sx_iter != NULL; sx_iter = sx_iter->next)
1624 {
1625 GncSxInstances *instances = (GncSxInstances*)sx_iter->data;
1626 for (inst_iter = instances->instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
1627 {
1628 GncSxInstance *inst = (GncSxInstance*)inst_iter->data;
1629
1630 if (inst->state != SX_INSTANCE_STATE_TO_CREATE)
1631 continue;
1632
1633 g_hash_table_foreach(inst->variable_bindings, (GHFunc)_list_from_hash_elts, &var_list);
1634 for (var_iter = var_list; var_iter != NULL; var_iter = var_iter->next)
1635 {
1636 GncSxVariable *var = (GncSxVariable*)var_iter->data;
1637 if (gnc_numeric_check(var->value) != GNC_ERROR_OK)
1638 {
1639 GncSxVariableNeeded *need = g_new0(GncSxVariableNeeded, 1);
1640 need->instance = inst;
1641 need->variable = var;
1642 rtn = g_list_prepend (rtn, need);
1643 }
1644 }
1645 g_list_free(var_list);
1646 var_list = NULL;
1647 }
1648 }
1649 return rtn;
1650}
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
@ GNC_ERROR_OK
No error.

◆ gnc_sx_instance_model_effect_change()

void gnc_sx_instance_model_effect_change ( GncSxInstanceModel *  model,
gboolean  auto_create_only,
GList **  created_transaction_guids,
GList **  creation_errors 
)

Really ("effectively") create the transactions from the SX instances in the given model.

Definition at line 1446 of file gnc-sx-instance-model.c.

1450{
1451 GList *iter;
1452
1453 if (qof_book_is_readonly(gnc_get_current_book()))
1454 {
1455 /* Is the book read-only? Then don't change anything here. */
1456 return;
1457 }
1458
1459 for (iter = model->sx_instance_list; iter != NULL; iter = iter->next)
1460 {
1461 GList *instance_iter;
1462 GncSxInstances *instances = (GncSxInstances*)iter->data;
1463 GDate *last_occur_date;
1464 gint instance_count = 0;
1465 gint remain_occur_count = 0;
1466
1467 // If there are no instances, then skip; specifically, skip
1468 // re-setting SchedXaction fields, which will dirty the book
1469 // spuriously.
1470 if (g_list_length(instances->instance_list) == 0)
1471 continue;
1472
1473 last_occur_date = (GDate*) xaccSchedXactionGetLastOccurDate(instances->sx);
1474 instance_count = gnc_sx_get_instance_count(instances->sx, NULL);
1475 remain_occur_count = xaccSchedXactionGetRemOccur(instances->sx);
1476
1477 for (instance_iter = instances->instance_list; instance_iter != NULL; instance_iter = instance_iter->next)
1478 {
1479 GncSxInstance *inst = (GncSxInstance*)instance_iter->data;
1480 gboolean sx_is_auto_create;
1481 GList *instance_errors = NULL;
1482
1483 xaccSchedXactionGetAutoCreate(inst->parent->sx, &sx_is_auto_create, NULL);
1484 if (auto_create_only && !sx_is_auto_create)
1485 {
1486 if (inst->state != SX_INSTANCE_STATE_TO_CREATE)
1487 {
1488 break;
1489 }
1490 continue;
1491 }
1492
1493 if (inst->orig_state == SX_INSTANCE_STATE_POSTPONED
1494 && inst->state != SX_INSTANCE_STATE_POSTPONED)
1495 {
1496 // remove from postponed list
1497 g_assert(inst->temporal_state != NULL);
1498 gnc_sx_remove_defer_instance(inst->parent->sx,
1499 inst->temporal_state);
1500 }
1501
1502 switch (inst->state)
1503 {
1504 case SX_INSTANCE_STATE_CREATED:
1505 // nop: we've already processed this.
1506 break;
1507 case SX_INSTANCE_STATE_IGNORED:
1508 increment_sx_state(inst, &last_occur_date, &instance_count, &remain_occur_count);
1509 break;
1510 case SX_INSTANCE_STATE_POSTPONED:
1511 if (inst->orig_state != SX_INSTANCE_STATE_POSTPONED)
1512 {
1513 gnc_sx_add_defer_instance(instances->sx,
1514 gnc_sx_clone_temporal_state (inst->temporal_state));
1515 }
1516 increment_sx_state(inst, &last_occur_date, &instance_count, &remain_occur_count);
1517 break;
1518 case SX_INSTANCE_STATE_TO_CREATE:
1519 create_transactions_for_instance (inst,
1520 created_transaction_guids,
1521 &instance_errors);
1522 if (instance_errors == NULL)
1523 {
1524 increment_sx_state (inst, &last_occur_date,
1525 &instance_count,
1526 &remain_occur_count);
1527 gnc_sx_instance_model_change_instance_state
1528 (model, inst, SX_INSTANCE_STATE_CREATED);
1529 }
1530 else if (creation_errors)
1531 {
1532 *creation_errors = g_list_concat (*creation_errors,
1533 instance_errors);
1534 instance_errors = NULL;
1535 }
1536 break;
1537 case SX_INSTANCE_STATE_REMINDER:
1538 // do nothing
1539 // assert no non-remind instances after this?
1540 break;
1541 default:
1542 g_assert_not_reached();
1543 break;
1544 }
1545
1546 if (instance_errors)
1547 g_list_free_full (instance_errors, g_free);
1548 }
1549
1550 xaccSchedXactionSetLastOccurDate(instances->sx, last_occur_date);
1551 gnc_sx_set_instance_count(instances->sx, instance_count);
1552 xaccSchedXactionSetRemOccur(instances->sx, remain_occur_count);
1553 }
1554}
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition qofbook.cpp:497
SXTmpStateData * gnc_sx_clone_temporal_state(SXTmpStateData *tsd)
Allocates and returns a one-by-one copy of the given temporal state.
gint gnc_sx_get_instance_count(const SchedXaction *sx, SXTmpStateData *stateData)
Get the instance count.
void gnc_sx_remove_defer_instance(SchedXaction *sx, void *deferStateData)
Removes an instance from the deferred list.
void gnc_sx_add_defer_instance(SchedXaction *sx, void *deferStateData)
Adds an instance to the deferred list of the SX.
void gnc_sx_set_instance_count(SchedXaction *sx, gint instance_num)
Sets the instance count to something other than the default.

◆ gnc_sx_instance_model_get_sx_instances_list()

GList * gnc_sx_instance_model_get_sx_instances_list ( GncSxInstanceModel *  model)

Returns the list of GncSxInstances in the model (Each element in the list has type GncSxInstances)

The returned list is owned by the model

Definition at line 1978 of file gnc-sx-instance-model.c.

1979{
1980 return model->sx_instance_list;
1981}

◆ gnc_sx_instance_model_remove_sx_instances()

void gnc_sx_instance_model_remove_sx_instances ( GncSxInstanceModel *  model,
SchedXaction *  sx 
)

Definition at line 1027 of file gnc-sx-instance-model.c.

1028{
1029 GList *instance_link = NULL;
1030
1031 instance_link = g_list_find_custom(model->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
1032 if (instance_link == NULL)
1033 {
1034 g_warning("instance not found!\n");
1035 return;
1036 }
1037
1038 model->sx_instance_list = g_list_remove_link(model->sx_instance_list, instance_link);
1039 gnc_sx_instances_free((GncSxInstances*)instance_link->data);
1040}

◆ gnc_sx_instance_model_set_variable()

void gnc_sx_instance_model_set_variable ( GncSxInstanceModel *  model,
GncSxInstance instance,
GncSxVariable variable,
gnc_numeric *  new_value 
)

Definition at line 1599 of file gnc-sx-instance-model.c.

1603{
1604
1605 if (gnc_numeric_equal(variable->value, *new_value))
1606 return;
1607 variable->value = *new_value;
1608 g_signal_emit_by_name(model, "updated", (gpointer)instance->parent->sx);
1609}
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gnc_numeric value
only numeric values are supported.

◆ gnc_sx_instance_model_summarize()

void gnc_sx_instance_model_summarize ( GncSxInstanceModel *  model,
GncSxSummary summary 
)
Parameters
summaryCaller-provided, populated with a summarization of the state of the model. Specifically, used to determine if there are SLR SXes that need either auto-creation or user-interaction.

Definition at line 1653 of file gnc-sx-instance-model.c.

1654{
1655 GList *sx_iter, *inst_iter;
1656
1657 g_return_if_fail(model != NULL);
1658 g_return_if_fail(summary != NULL);
1659
1660 summary->need_dialog = FALSE;
1661 summary->num_instances = 0;
1662 summary->num_to_create_instances = 0;
1663 summary->num_auto_create_instances = 0;
1665
1666 for (sx_iter = model->sx_instance_list; sx_iter != NULL; sx_iter = sx_iter->next)
1667 {
1668 GncSxInstances *instances = (GncSxInstances*)sx_iter->data;
1669 gboolean sx_is_auto_create = FALSE, sx_notify = FALSE;
1670 xaccSchedXactionGetAutoCreate(instances->sx, &sx_is_auto_create, &sx_notify);
1671 for (inst_iter = instances->instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
1672 {
1673 GncSxInstance *inst = (GncSxInstance*)inst_iter->data;
1674 summary->num_instances++;
1675
1676 if (inst->state == SX_INSTANCE_STATE_TO_CREATE)
1677 {
1678 if (sx_is_auto_create)
1679 {
1680 if (!sx_notify)
1681 {
1683 }
1684 else
1685 {
1686 summary->num_auto_create_instances++;
1687 }
1688 }
1689 else
1690 {
1691 summary->num_to_create_instances++;
1692 }
1693 }
1694 }
1695 }
1696
1697 // if all the instances are 'auto-create, no-notify', then we don't need
1698 // the dialog.
1699 summary->need_dialog
1700 = (summary->num_instances != 0
1701 && summary->num_auto_create_no_notify_instances != summary->num_instances);
1702}
gint num_auto_create_no_notify_instances
The number of automatically-created instances that do no request notification.
gint num_to_create_instances
The number of (not-auto-create) to-create instances.
gboolean need_dialog
If the dialog needs to be displayed.
gint num_instances
The number of total instances (in any state).
gint num_auto_create_instances
The total number of auto-create instances.

◆ gnc_sx_instance_model_update_sx_instances()

void gnc_sx_instance_model_update_sx_instances ( GncSxInstanceModel *  model,
SchedXaction *  sx 
)

Regenerates and updates the GncSxInstances* for the given SX.

Model consumers are probably going to call this in response to seeing the "update" signal, unless they need to be doing something else like finishing an iteration over an existing GncSxInstances*.

Definition at line 899 of file gnc-sx-instance-model.c.

900{
901 GncSxInstances *existing, *new_instances;
902 GList *link;
903
904 link = g_list_find_custom(model->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
905 if (link == NULL)
906 {
907 g_critical("couldn't find sx [%p]\n", sx);
908 return;
909 }
910
911 // merge the new instance data into the existing structure, mutating as little as possible.
912 existing = (GncSxInstances*)link->data;
913 new_instances = sx_instances(model, sx);
914 existing->sx = new_instances->sx;
915 existing->next_instance_date = new_instances->next_instance_date;
916 {
917 GList *existing_iter, *new_iter;
918 gboolean existing_remain, new_remain;
919
920 // step through the lists pairwise, and retain the existing
921 // instance if the dates align, as soon as they don't stop and
922 // cleanup.
923 existing_iter = existing->instance_list;
924 new_iter = new_instances->instance_list;
925 for (; existing_iter != NULL && new_iter != NULL; existing_iter = existing_iter->next, new_iter = new_iter->next)
926 {
927 GncSxInstance *existing_inst, *new_inst;
928 gboolean same_instance_date;
929 existing_inst = (GncSxInstance*)existing_iter->data;
930 new_inst = (GncSxInstance*)new_iter->data;
931
932 same_instance_date = g_date_compare(&existing_inst->date, &new_inst->date) == 0;
933 if (!same_instance_date)
934 break;
935 }
936
937 existing_remain = (existing_iter != NULL);
938 new_remain = (new_iter != NULL);
939
940 if (existing_remain)
941 {
942 // delete excess
943 gnc_g_list_cut(&existing->instance_list, existing_iter);
944 g_list_foreach(existing_iter, (GFunc)gnc_sx_instance_free, NULL);
945 }
946
947 if (new_remain)
948 {
949 // append new
950 GList *new_iter_iter;
951 gnc_g_list_cut(&new_instances->instance_list, new_iter);
952
953 for (new_iter_iter = new_iter; new_iter_iter != NULL; new_iter_iter = new_iter_iter->next)
954 {
955 GncSxInstance *inst = (GncSxInstance*)new_iter_iter->data;
956 inst->parent = existing;
957 existing->instance_list = g_list_append(existing->instance_list, new_iter_iter->data);
958 }
959 g_list_free(new_iter);
960 }
961 }
962
963 // handle variables
964 {
965 GList *removed_var_names = NULL, *added_var_names = NULL;
966 GList *inst_iter = NULL;
967
968 if (existing->variable_names != NULL)
969 {
970 HashListPair removed_cb_data;
971 removed_cb_data.hash = new_instances->variable_names;
972 removed_cb_data.list = NULL;
973 g_hash_table_foreach(existing->variable_names, (GHFunc)_find_unreferenced_vars, &removed_cb_data);
974 removed_var_names = g_list_reverse (removed_cb_data.list);
975 }
976 DEBUG("%d removed variables", g_list_length(removed_var_names));
977
978 if (new_instances->variable_names != NULL)
979 {
980 HashListPair added_cb_data;
981 added_cb_data.hash = existing->variable_names;
982 added_cb_data.list = NULL;
983 g_hash_table_foreach(new_instances->variable_names, (GHFunc)_find_unreferenced_vars, &added_cb_data);
984 added_var_names = g_list_reverse (added_cb_data.list);
985 }
986 DEBUG("%d added variables", g_list_length(added_var_names));
987
988 if (existing->variable_names != NULL)
989 {
990 g_hash_table_destroy(existing->variable_names);
991 }
992 existing->variable_names = new_instances->variable_names;
993 new_instances->variable_names = NULL;
994
995 for (inst_iter = existing->instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
996 {
997 GList *var_iter;
998 GncSxInstance *inst = (GncSxInstance*)inst_iter->data;
999
1000 for (var_iter = removed_var_names; var_iter != NULL; var_iter = var_iter->next)
1001 {
1002 gchar *to_remove_key = (gchar*)var_iter->data;
1003 g_hash_table_remove(inst->variable_bindings, to_remove_key);
1004 }
1005
1006 for (var_iter = added_var_names; var_iter != NULL; var_iter = var_iter->next)
1007 {
1008 gchar *to_add_key = (gchar*)var_iter->data;
1009 if (!g_hash_table_lookup_extended(
1010 inst->variable_bindings, to_add_key, NULL, NULL))
1011 {
1012 GncSxVariable *parent_var
1013 = g_hash_table_lookup(existing->variable_names, to_add_key);
1014 GncSxVariable *var_copy;
1015
1016 g_assert(parent_var != NULL);
1017 var_copy = gnc_sx_variable_new_copy(parent_var);
1018 g_hash_table_insert(inst->variable_bindings, g_strdup(to_add_key), var_copy);
1019 }
1020 }
1021 }
1022 }
1023 gnc_sx_instances_free(new_instances);
1024}
void gnc_g_list_cut(GList **list, GList *cut_point)
Cut a GList into two parts; the cut_point is the beginning of the new list; list may need to be modif...
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
GHashTable * variable_names
<name:char*,GncSxVariable*>

◆ gnc_sx_parse_vars_from_formula()

int gnc_sx_parse_vars_from_formula ( const char *  formula,
GHashTable *  var_hash,
gnc_numeric *  result 
)

Definition at line 235 of file gnc-sx-instance-model.c.

238{
239 gnc_numeric num;
240 char *errLoc = NULL;
241 int toRet = 0;
242 GHashTable *parser_vars;
243
244 // convert var_hash -> variables for the parser.
245 parser_vars = gnc_sx_instance_get_variables_for_parser(var_hash);
246
247 num = gnc_numeric_zero();
248 if (!gnc_exp_parser_parse_separate_vars(formula, &num, &errLoc, parser_vars))
249 {
250 toRet = -1;
251 }
252
253 // convert back.
254 g_hash_table_foreach(parser_vars, (GHFunc)_var_numeric_to_sx_var, var_hash);
255 g_hash_table_destroy(parser_vars);
256
257 if (result != NULL)
258 {
259 *result = num;
260 }
261
262 return toRet;
263}

◆ gnc_sx_randomize_variables()

void gnc_sx_randomize_variables ( GHashTable *  vars)

Definition at line 410 of file gnc-sx-instance-model.c.

411{
412 g_hash_table_foreach(vars, (GHFunc)_set_var_to_random_value, NULL);
413}

◆ gnc_sx_scrub_split_numerics()

void gnc_sx_scrub_split_numerics ( gpointer  psplit,
gpointer  user 
)

Fix up numerics where they've gotten out-of-sync with the formulas.

Ideally this would be done at load time, but it requires gnc_exp_parser to work and neither engine nor the backends can depend on it.

Definition at line 154 of file gnc-sx-instance-model.c.

155{
156 Split *split = GNC_SPLIT (psplit);
157 Transaction *trans = xaccSplitGetParent (split);
158 GList *changes = NULL;
159 scrub_sx_split_numeric (split, TRUE, &changes);
160 scrub_sx_split_numeric (split, FALSE, &changes);
161 if (!changes)
162 return;
163
164 xaccTransBeginEdit (trans);
165 for (GList *n = changes; n; n = n->next)
166 {
167 ScrubItem *change = n->data;
168 qof_instance_set (QOF_INSTANCE (split),
169 change->name, &change->amount,
170 NULL);
171 }
172 xaccTransCommitEdit (trans);
173 g_list_free_full (changes, g_free);
174}
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.

◆ gnc_sx_summary_print()

void gnc_sx_summary_print ( const GncSxSummary summary)

Debug output to trace file.

Definition at line 1705 of file gnc-sx-instance-model.c.

1706{
1707 PINFO("num_instances: %d", summary->num_instances);
1708 PINFO("num_to_create: %d", summary->num_to_create_instances);
1709 PINFO("num_auto_create_instances: %d", summary->num_auto_create_instances);
1710 PINFO("num_auto_create_no_notify_instances: %d", summary->num_auto_create_no_notify_instances);
1711 PINFO("need dialog? %s", summary->need_dialog ? "true" : "false");
1712}
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256

◆ gnc_sx_variable_free()

void gnc_sx_variable_free ( GncSxVariable var)

Definition at line 294 of file gnc-sx-instance-model.c.

295{
296 g_free(var->name);
297 g_free(var);
298}

◆ gnc_sx_variable_new_full()

GncSxVariable * gnc_sx_variable_new_full ( gchar *  name,
gnc_numeric  value,
gboolean  editable 
)

Definition at line 276 of file gnc-sx-instance-model.c.

277{
278 GncSxVariable *var = gnc_sx_variable_new(name);
279 var->value = value;
280 var->editable = editable;
281 return var;
282}