static gboolean _get_template_split_account(GncSxInstance *instance, Split *template_split, Account **split_acct, GList **creation_errors) { GncGUID *acct_guid; kvp_frame *split_kvpf; kvp_value *kvp_val; split_kvpf = xaccSplitGetSlots(template_split); /* contains the guid of the split's actual account. */ kvp_val = kvp_frame_get_slot_path(split_kvpf, GNC_SX_ID, GNC_SX_ACCOUNT, NULL); if (kvp_val == NULL) { GString *err = g_string_new(""); g_string_printf(err, "Null account kvp value for SX [%s], cancelling creation.", xaccSchedXactionGetName(instance->parent->sx)); g_critical("%s", err->str); if (creation_errors != NULL) *creation_errors = g_list_append(*creation_errors, err); else g_string_free(err, TRUE); return FALSE; } acct_guid = kvp_value_get_guid( kvp_val ); *split_acct = xaccAccountLookup(acct_guid, gnc_get_current_book()); if (*split_acct == NULL) { char guid_str[GUID_ENCODING_LENGTH+1]; GString *err; guid_to_string_buff((const GncGUID*)acct_guid, guid_str); err = g_string_new(""); g_string_printf(err, "Unknown account for guid [%s], cancelling SX [%s] creation.", guid_str, xaccSchedXactionGetName(instance->parent->sx)); g_critical("%s", err->str); if (creation_errors != NULL) *creation_errors = g_list_append(*creation_errors, err); else g_string_free(err, TRUE); return FALSE; } return TRUE; }
static gchar* gsidca_get_name(GncDenseCalModel *model, guint tag) { GncSxInstanceDenseCalAdapter *adapter = GNC_SX_INSTANCE_DENSE_CAL_ADAPTER(model); GncSxInstances *insts = (GncSxInstances*)g_list_find_custom(adapter->instances->sx_instance_list, GUINT_TO_POINTER(tag), gsidca_find_sx_with_tag)->data; if (insts == NULL) return NULL; return xaccSchedXactionGetName(insts->sx); }
static gint _name_comparator(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { gint rtn; GncSxListTreeModelAdapter *adapter = GNC_SX_LIST_TREE_MODEL_ADAPTER(user_data); GncSxInstances *a_inst, *b_inst; gchar *a_caseless, *b_caseless; a_inst = gsltma_get_sx_instances_from_orig_iter(adapter, a); b_inst = gsltma_get_sx_instances_from_orig_iter(adapter, b); if (a_inst == NULL && b_inst == NULL) return 0; if (a_inst == NULL) return 1; if (b_inst == NULL) return -1; a_caseless = g_utf8_casefold(xaccSchedXactionGetName(a_inst->sx), -1); b_caseless = g_utf8_casefold(xaccSchedXactionGetName(b_inst->sx), -1); rtn = g_strcmp0(a_caseless, b_caseless); g_free(a_caseless); g_free(b_caseless); return rtn; }
static void _get_sx_formula_value(GncSxInstance *instance, Split *template_split, gnc_numeric *numeric, GList **creation_errors, const char *formula_key) { kvp_frame *split_kvpf; kvp_value *kvp_val; char *formula_str, *parseErrorLoc; split_kvpf = xaccSplitGetSlots(template_split); kvp_val = kvp_frame_get_slot_path(split_kvpf, GNC_SX_ID, formula_key, NULL); formula_str = kvp_value_get_string(kvp_val); if (formula_str != NULL && strlen(formula_str) != 0) { GHashTable *parser_vars = gnc_sx_instance_get_variables_for_parser(instance->variable_bindings); if (!gnc_exp_parser_parse_separate_vars(formula_str, numeric, &parseErrorLoc, parser_vars)) { GString *err = g_string_new(""); g_string_printf(err, "Error parsing SX [%s] key [%s]=formula [%s] at [%s]: %s", xaccSchedXactionGetName(instance->parent->sx), formula_key, formula_str, parseErrorLoc, gnc_exp_parser_error_string()); g_critical("%s", err->str); if (creation_errors != NULL) *creation_errors = g_list_append(*creation_errors, err); else g_string_free(err, TRUE); } if (parser_vars != NULL) { g_hash_table_destroy(parser_vars); } } }
static void gnc_plugin_page_sx_list_cmd_delete(GtkAction *action, GncPluginPageSxList *page) { GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page); GtkTreeSelection *selection; GList *selected_paths, *to_delete = NULL; GtkTreeModel *model; selection = gtk_tree_view_get_selection(priv->tree_view); selected_paths = gtk_tree_selection_get_selected_rows(selection, &model); if (g_list_length(selected_paths) == 0) { g_warning("no selection for delete."); return; } to_delete = gnc_g_list_map(selected_paths, (GncGMapFunc)_argument_reorder_fn, priv->tree_view); { GList *list; for (list = to_delete; list != NULL; list = list->next) { g_debug("to-delete [%s]\n", xaccSchedXactionGetName((SchedXaction*)list->data)); } } /* FIXME: Does this always refer to only one transaction? Or could multiple SXs be deleted as well? Ideally, the number of to-be-deleted SXs should be mentioned here; see dialog-sx-since-last-run.cpp:807 */ if (gnc_verify_dialog(NULL, FALSE, "%s", _("Do you really want to delete this scheduled transaction?"))) { g_list_foreach(to_delete, (GFunc)_destroy_sx, NULL); } g_list_free(to_delete); g_list_foreach(selected_paths, (GFunc)gtk_tree_path_free, NULL); g_list_free(selected_paths); }
static void gsslrtma_populate_tree_store(GncSxSlrTreeModelAdapter *model) { GtkTreeIter sx_tree_iter; GList *sx_iter; int instances_index = -1; for (sx_iter = model->instances->sx_instance_list; sx_iter != NULL; sx_iter = sx_iter->next) { GncSxInstances *instances = (GncSxInstances*)sx_iter->data; char last_occur_date_buf[MAX_DATE_LENGTH+1]; { const GDate *last_occur = xaccSchedXactionGetLastOccurDate(instances->sx); if (last_occur == NULL || !g_date_valid(last_occur)) { g_stpcpy(last_occur_date_buf, _("Never")); } else { qof_print_gdate(last_occur_date_buf, MAX_DATE_LENGTH, last_occur); } } if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(model->real), &sx_tree_iter, NULL, ++instances_index)) { gtk_tree_store_append(model->real, &sx_tree_iter, NULL); } gtk_tree_store_set(model->real, &sx_tree_iter, SLR_MODEL_COL_NAME, xaccSchedXactionGetName(instances->sx), SLR_MODEL_COL_INSTANCE_STATE, NULL, SLR_MODEL_COL_VARAIBLE_VALUE, NULL, SLR_MODEL_COL_INSTANCE_VISIBILITY, FALSE, SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE, SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE, -1); // Insert instance information { GList *inst_iter; GtkTreeIter inst_tree_iter; char instance_date_buf[MAX_DATE_LENGTH+1]; int instance_index = -1; for (inst_iter = instances->instance_list; inst_iter != NULL; inst_iter = inst_iter->next) { GncSxInstance *inst = (GncSxInstance*)inst_iter->data; qof_print_gdate(instance_date_buf, MAX_DATE_LENGTH, &inst->date); if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(model->real), &inst_tree_iter, &sx_tree_iter, ++instance_index)) { gtk_tree_store_append(model->real, &inst_tree_iter, &sx_tree_iter); } gtk_tree_store_set(model->real, &inst_tree_iter, SLR_MODEL_COL_NAME, instance_date_buf, SLR_MODEL_COL_INSTANCE_STATE, _(gnc_sx_instance_state_names[inst->state]), SLR_MODEL_COL_VARAIBLE_VALUE, NULL, SLR_MODEL_COL_INSTANCE_VISIBILITY, TRUE, SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE, SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, inst->state != SX_INSTANCE_STATE_CREATED, -1); // Insert variable information { GList *vars = NULL, *var_iter; GtkTreeIter var_tree_iter; gint visible_variable_index = -1; vars = gnc_sx_instance_get_variables(inst); for (var_iter = vars; var_iter != NULL; var_iter = var_iter->next) { GncSxVariable *var = (GncSxVariable*)var_iter->data; GString *tmp_str; if (!var->editable) continue; if (gnc_numeric_check(var->value) == GNC_ERROR_OK) { _var_numeric_to_string(&var->value, &tmp_str); } else { tmp_str = g_string_new(_("(Need Value)")); } if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(model->real), &var_tree_iter, &inst_tree_iter, ++visible_variable_index)) { gtk_tree_store_append(model->real, &var_tree_iter, &inst_tree_iter); } gtk_tree_store_set(model->real, &var_tree_iter, SLR_MODEL_COL_NAME, var->name, SLR_MODEL_COL_INSTANCE_STATE, NULL, SLR_MODEL_COL_VARAIBLE_VALUE, tmp_str->str, SLR_MODEL_COL_INSTANCE_VISIBILITY, FALSE, SLR_MODEL_COL_VARIABLE_VISIBILITY, TRUE, SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE - 1); g_string_free(tmp_str, TRUE); } g_list_free(vars); _consume_excess_rows(model->real, visible_variable_index, &inst_tree_iter, &var_tree_iter); } } // if there are more instance iters, remove _consume_excess_rows(model->real, instance_index, &sx_tree_iter, &inst_tree_iter); } } _consume_excess_rows(model->real, instances_index, NULL, &sx_tree_iter); }
static gboolean create_each_transaction_helper(Transaction *template_txn, void *user_data) { Transaction *new_txn; GList *txn_splits, *template_splits; Split *copying_split; gnc_commodity *first_cmdty = NULL; gboolean err_flag = FALSE; SxTxnCreationData *creation_data; creation_data = (SxTxnCreationData*)user_data; /* FIXME: In general, this should [correctly] deal with errors such as not finding the approrpiate Accounts and not being able to parse the formula|credit/debit strings. */ new_txn = xaccTransClone(template_txn); xaccTransBeginEdit(new_txn); g_debug("creating template txn desc [%s] for sx [%s]", xaccTransGetDescription(new_txn), xaccSchedXactionGetName(creation_data->instance->parent->sx)); /* clear any copied KVP data */ qof_instance_set_slots(QOF_INSTANCE(new_txn), kvp_frame_new()); /* Bug#500427: copy the notes, if any */ if (xaccTransGetNotes(template_txn) != NULL) { xaccTransSetNotes(new_txn, g_strdup(xaccTransGetNotes(template_txn))); } xaccTransSetDate(new_txn, g_date_get_day(&creation_data->instance->date), g_date_get_month(&creation_data->instance->date), g_date_get_year(&creation_data->instance->date)); /* the accounts and amounts are in the kvp_frames of the splits. */ template_splits = xaccTransGetSplitList(template_txn); txn_splits = xaccTransGetSplitList(new_txn); if ((template_splits == NULL) || (txn_splits == NULL)) { g_critical("transaction w/o splits for sx [%s]", xaccSchedXactionGetName(creation_data->instance->parent->sx)); xaccTransDestroy(new_txn); xaccTransCommitEdit(new_txn); return FALSE; } for (; txn_splits && template_splits; txn_splits = txn_splits->next, template_splits = template_splits->next) { Split *template_split; Account *split_acct; gnc_commodity *split_cmdty = NULL; /* FIXME: Ick. This assumes that the split lists will be ordered identically. :( They are, but we'd rather not have to count on it. --jsled */ template_split = (Split*)template_splits->data; copying_split = (Split*)txn_splits->data; if (!_get_template_split_account(creation_data->instance, template_split, &split_acct, creation_data->creation_errors)) { err_flag = TRUE; break; } /* clear out any copied Split frame data. */ qof_instance_set_slots(QOF_INSTANCE(copying_split), kvp_frame_new()); split_cmdty = xaccAccountGetCommodity(split_acct); if (first_cmdty == NULL) { first_cmdty = split_cmdty; xaccTransSetCurrency(new_txn, first_cmdty); } xaccSplitSetAccount(copying_split, split_acct); { gnc_numeric credit_num, debit_num, final; gint gncn_error; credit_num = gnc_numeric_zero(); debit_num = gnc_numeric_zero(); _get_credit_formula_value(creation_data->instance, template_split, &credit_num, creation_data->creation_errors); _get_debit_formula_value(creation_data->instance, template_split, &debit_num, creation_data->creation_errors); final = gnc_numeric_sub_fixed( debit_num, credit_num ); gncn_error = gnc_numeric_check(final); if (gncn_error != GNC_ERROR_OK) { GString *err = g_string_new(""); g_string_printf(err, "error %d in SX [%s] final gnc_numeric value, using 0 instead", gncn_error, xaccSchedXactionGetName(creation_data->instance->parent->sx)); g_critical("%s", err->str); if (creation_data->creation_errors != NULL) *creation_data->creation_errors = g_list_append(*creation_data->creation_errors, err); else g_string_free(err, TRUE); final = gnc_numeric_zero(); }
xmlNodePtr gnc_schedXaction_dom_tree_create(SchedXaction *sx) { xmlNodePtr ret; const GDate *date; gint instCount; const GncGUID *templ_acc_guid; gboolean allow_2_2_incompat = TRUE; gchar *name = g_strdup (xaccSchedXactionGetName(sx)); templ_acc_guid = xaccAccountGetGUID(sx->template_acct); /* FIXME: this should be the same as the def in io-gncxml-v2.c */ ret = xmlNewNode (NULL, BAD_CAST GNC_SCHEDXACTION_TAG); if (allow_2_2_incompat) xmlSetProp(ret, BAD_CAST "version", BAD_CAST schedxaction_version2_string); else xmlSetProp(ret, BAD_CAST "version", BAD_CAST schedxaction_version_string); xmlAddChild( ret, guid_to_dom_tree(SX_ID, xaccSchedXactionGetGUID(sx)) ); xmlNewTextChild( ret, NULL, BAD_CAST SX_NAME, checked_char_cast (name)); g_free (name); if (allow_2_2_incompat) { xmlNewTextChild( ret, NULL, BAD_CAST SX_ENABLED, BAD_CAST ( sx->enabled ? "y" : "n" ) ); } xmlNewTextChild( ret, NULL, BAD_CAST SX_AUTOCREATE, BAD_CAST ( sx->autoCreateOption ? "y" : "n" ) ); xmlNewTextChild( ret, NULL, BAD_CAST SX_AUTOCREATE_NOTIFY, BAD_CAST ( sx->autoCreateNotify ? "y" : "n" ) ); xmlAddChild(ret, int_to_dom_tree(SX_ADVANCE_CREATE_DAYS, sx->advanceCreateDays)); xmlAddChild(ret, int_to_dom_tree(SX_ADVANCE_REMIND_DAYS, sx->advanceRemindDays)); instCount = gnc_sx_get_instance_count( sx, NULL ); xmlAddChild( ret, int_to_dom_tree( SX_INSTANCE_COUNT, instCount ) ); xmlAddChild( ret, gdate_to_dom_tree( SX_START, xaccSchedXactionGetStartDate(sx) ) ); date = xaccSchedXactionGetLastOccurDate(sx); if ( g_date_valid( date ) ) { xmlAddChild( ret, gdate_to_dom_tree( SX_LAST, date ) ); } if ( xaccSchedXactionHasOccurDef(sx) ) { xmlAddChild(ret, int_to_dom_tree( SX_NUM_OCCUR, xaccSchedXactionGetNumOccur(sx))); xmlAddChild(ret, int_to_dom_tree( SX_REM_OCCUR, xaccSchedXactionGetRemOccur(sx))); } else if ( xaccSchedXactionHasEndDate(sx) ) { xmlAddChild( ret, gdate_to_dom_tree( SX_END, xaccSchedXactionGetEndDate(sx) ) ); } /* output template account GncGUID */ xmlAddChild( ret, guid_to_dom_tree(SX_TEMPL_ACCT, templ_acc_guid)); if (allow_2_2_incompat) { xmlNodePtr schedule_node = xmlNewNode(NULL, BAD_CAST "sx:schedule"); GList *schedule = gnc_sx_get_schedule(sx); for (; schedule != NULL; schedule = schedule->next) { xmlAddChild(schedule_node, recurrence_to_dom_tree("gnc:recurrence", (Recurrence*)schedule->data)); } xmlAddChild(ret, schedule_node); } /* Output deferred-instance list. */ { xmlNodePtr instNode; SXTmpStateData *tsd; GList *l; for ( l = gnc_sx_get_defer_instances( sx ); l; l = l->next ) { tsd = (SXTmpStateData*)l->data; instNode = xmlNewNode( NULL, BAD_CAST SX_DEFER_INSTANCE ); if ( g_date_valid( &tsd->last_date ) ) { xmlAddChild( instNode, gdate_to_dom_tree( SX_LAST, &tsd->last_date ) ); } xmlAddChild( instNode, int_to_dom_tree( SX_REM_OCCUR, tsd->num_occur_rem ) ); xmlAddChild( instNode, int_to_dom_tree( SX_INSTANCE_COUNT, tsd->num_inst ) ); xmlAddChild( ret, instNode ); } } /* output kvp_frame */ { xmlNodePtr kvpnode = kvp_frame_to_dom_tree( SX_SLOTS, xaccSchedXactionGetSlots(sx) ); if ( kvpnode ) { xmlAddChild(ret, kvpnode); } } return ret; }
static gboolean gnc_schedXaction_end_handler(gpointer data_for_children, GSList* data_from_children, GSList* sibling_data, gpointer parent_data, gpointer global_data, gpointer *result, const gchar *tag) { SchedXaction *sx; gboolean successful = FALSE; xmlNodePtr tree = (xmlNodePtr)data_for_children; gxpf_data *gdata = (gxpf_data*)global_data; struct sx_pdata sx_pdata; if ( parent_data ) { return TRUE; } if ( !tag ) { return TRUE; } g_return_val_if_fail( tree, FALSE ); sx = xaccSchedXactionMalloc( gdata->bookdata ); memset(&sx_pdata, 0, sizeof(sx_pdata)); sx_pdata.sx = sx; sx_pdata.book = gdata->bookdata; g_assert( sx_dom_handlers != NULL ); successful = dom_tree_generic_parse( tree, sx_dom_handlers, &sx_pdata ); if (!successful) { g_critical("failed to parse scheduled xaction"); xmlElemDump( stdout, NULL, tree ); gnc_sx_begin_edit( sx ); xaccSchedXactionDestroy( sx ); goto done; } if (tree->properties) { gchar *sx_name = xaccSchedXactionGetName(sx); xmlAttr *attr; for (attr = tree->properties; attr != NULL; attr = attr->next) { xmlChar *attr_value = attr->children->content; g_debug("sx attribute name[%s] value[%s]", attr->name, attr_value); if (strcmp((const char *)attr->name, "version") != 0) { g_warning("unknown sx attribute [%s]", attr->name); continue; } // if version == 1.0.0: ensure freqspec, no recurrence // if version == 2.0.0: ensure recurrence, no freqspec. if (strcmp((const char *)attr_value, schedxaction_version_string) == 0) { if (!sx_pdata.saw_freqspec) g_critical("did not see freqspec in version 1 sx [%s]", sx_name); if (sx_pdata.saw_recurrence) g_warning("saw recurrence in supposedly version 1 sx [%s]", sx_name); } if (strcmp((const char *)attr_value, schedxaction_version2_string) == 0) { if (sx_pdata.saw_freqspec) g_warning("saw freqspec in version 2 sx [%s]", sx_name); if (!sx_pdata.saw_recurrence) g_critical("did not find recurrence in version 2 sx [%s]", sx_name); } } } // generic_callback -> book_callback: insert the SX in the book gdata->cb( tag, gdata->parsedata, sx ); /* FIXME: this should be removed somewhere near 1.8 release time. */ if ( sx->template_acct == NULL ) { Account *ra = NULL; const char *id = NULL; Account *acct = NULL; sixtp_gdv2 *sixdata = gdata->parsedata; QofBook *book; book = sixdata->book; /* We're dealing with a pre-200107<near-end-of-month> rgmerk change re: storing template accounts. */ /* Fix: get account with name of our GncGUID from the template accounts. Make that our template_acct pointer. */ /* THREAD-UNSAFE */ id = guid_to_string( xaccSchedXactionGetGUID( sx ) ); ra = gnc_book_get_template_root(book); if ( ra == NULL ) { g_warning( "Error getting template root account from being-parsed Book." ); xmlFreeNode( tree ); return FALSE; } acct = gnc_account_lookup_by_name( ra, id ); if ( acct == NULL ) { g_warning("no template account with name [%s]", id); xmlFreeNode( tree ); return FALSE; } g_debug("template account name [%s] for SX with GncGUID [%s]", xaccAccountGetName( acct ), id ); /* FIXME: free existing template account. * HUH????? We only execute this if there isn't * currently an existing template account, don't we? * <rgmerk> */ sx->template_acct = acct; } done: xmlFreeNode( tree ); return successful; }