GnuCash  5.6-150-g038405b370+
dialog-sx-since-last-run.c
1 /********************************************************************\
2  * dialog-sx-since-last-run.c : dialog for scheduled transaction *
3  * since-last-run processing. *
4  * Copyright (C) 2006 Joshua Sled <jsled@asynchronous.org> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of version 2 and/or version 3 of the *
8  * GNU General Public License as published by the Free Software *
9  * Foundation. *
10  * *
11  * As a special exception, permission is granted to link the binary *
12  * module resultant from this code with the OpenSSL project's *
13  * "OpenSSL" library (or modified versions of it that use the same *
14  * license as the "OpenSSL" library), and distribute the linked *
15  * executable. You must obey the GNU General Public License in all *
16  * respects for all of the code used other than "OpenSSL". If you *
17  * modify this file, you may extend this exception to your version *
18  * of the file, but you are not obligated to do so. If you do not *
19  * wish to do so, delete this exception statement from your version *
20  * of this file. *
21  * *
22  * This program is distributed in the hope that it will be useful, *
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
25  * GNU General Public License for more details. *
26  * *
27  * You should have received a copy of the GNU General Public License*
28  * along with this program; if not, contact: *
29  * *
30  * Free Software Foundation Voice: +1-617-542-5942 *
31  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
32  * Boston, MA 02110-1301, USA gnu@gnu.org *
33 \********************************************************************/
34 
35 #include <config.h>
36 #include <glib.h>
37 #include <gtk/gtk.h>
38 
39 #include "dialog-utils.h"
40 #include "gnc-sx-instance-model.h"
41 #include "dialog-sx-since-last-run.h"
42 
43 #include "gnc-prefs.h"
44 #include "gnc-ui.h"
45 #include "gnc-ui-util.h"
46 #include "gnc-glib-utils.h"
47 #include "Query.h"
48 #include "qof.h"
49 #include "gnc-ledger-display.h"
51 #include "gnc-main-window.h"
52 #include "gnc-component-manager.h"
53 #include "gnc-gui-query.h"
54 #include "gnc-session.h"
55 
56 #undef G_LOG_DOMAIN
57 #define G_LOG_DOMAIN "gnc.gui.sx.slr"
58 
59 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI_SX;
60 
61 #define DIALOG_SX_SINCE_LAST_RUN_CM_CLASS "dialog-sx-since-last-run"
62 
63 #define GNC_PREF_SET_REVIEW "review-transactions"
64 #define GNC_PREF_SLR_SORT_COL "sort-column"
65 #define GNC_PREF_SLR_SORT_ASC "sort-ascending"
66 #define GNC_PREF_SLR_SORT_DEPTH "sort-depth"
67 
69 {
70  GtkWidget *dialog;
71  gint component_id;
72  GncSxSlrTreeModelAdapter *editing_model;
73  GtkTreeView *instance_view;
74  GtkToggleButton *review_created_txns_toggle;
75  GList *created_txns;
76 
77  GtkCellEditable *temp_ce; // used when editing values
78  gint sort_selection_depth; // used when sorting transaction column
79 };
80 
81 /* ------------------------------------------------------------ */
82 
83 
85 {
86  GObject parent;
87 
88  /* protected: */
89  gulong updated_cb_id;
90  gboolean disposed;
91 
92  GncSxInstanceModel *instances;
93  GtkTreeStore *real;
94 };
95 
96 typedef struct _GncSxSlrTreeModelAdapterClass
97 {
98  GObjectClass parent;
100 
101 GType gnc_sx_slr_tree_model_adapter_get_type (void);
102 static void gnc_sx_slr_tree_model_adapter_interface_init (GtkTreeModelIface *tree_model);
103 GncSxSlrTreeModelAdapter* gnc_sx_slr_tree_model_adapter_new (GncSxInstanceModel *instances);
104 static void gnc_sx_slr_tree_model_adapter_dispose (GObject *obj);
105 static void gnc_sx_slr_tree_model_adapter_finalize (GObject *obj);
106 
107 GncSxInstanceModel* gnc_sx_slr_tree_model_adapter_get_instance_model (GncSxSlrTreeModelAdapter *slr_model);
108 
110 GncSxInstance* gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter);
111 static GncSxInstance* _gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model,
112  GtkTreeIter *iter,
113  gboolean check_depth);
114 
116 gboolean gnc_sx_slr_model_get_instance_and_variable (GncSxSlrTreeModelAdapter *model,
117  GtkTreeIter *iter,
118  GncSxInstance **instance_loc,
119  GncSxVariable **var_loc);
120 
121 void gnc_sx_slr_model_effect_change (GncSxSlrTreeModelAdapter *model,
122  gboolean auto_create_only,
123  GList **created_transaction_guids,
124  GList **creation_errors);
125 
126 GtkTreeModel* gnc_sx_get_slr_state_model (void);
127 
128 #define GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER (gnc_sx_slr_tree_model_adapter_get_type ())
129 #define GNC_SX_SLR_TREE_MODEL_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapter))
130 #define GNC_SX_SLR_TREE_MODEL_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapterClass))
131 #define GNC_IS_SX_SLR_TREE_MODEL_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER))
132 #define GNC_IS_SX_SLR_TREE_MODEL_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER))
133 #define GNC_SX_SLR_TREE_MODEL_ADAPTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapterClass))
134 
135 /* ------------------------------------------------------------ */
136 
137 static void _show_created_transactions (GncSxSinceLastRunDialog *app_dialog, GList *created_txn_guids);
138 
139 static void close_handler (gpointer user_data);
140 static void dialog_destroy_cb (GtkWidget *object, GncSxSinceLastRunDialog *app_dialog);
141 static void dialog_response_cb (GtkDialog *dialog, gint response_id, GncSxSinceLastRunDialog *app_dialog);
142 
143 #define debug_path(fn, text, path) {\
144  gchar *path_string = gtk_tree_path_to_string (path);\
145  fn("%s %s", text, path_string? path_string : "NULL");\
146  g_free (path_string);\
147 }
148 
149 /* ------------------------------------------------------------ */
150 
151 static void
152 _var_numeric_to_string (gnc_numeric *value, GString **str)
153 {
154  *str = g_string_sized_new (5);
155  g_string_printf (*str, "%0.2f", gnc_numeric_to_double (*value));
156 }
157 
158 /* ------------------------------------------------------------ */
159 
160 G_DEFINE_TYPE_WITH_CODE (GncSxSlrTreeModelAdapter, gnc_sx_slr_tree_model_adapter, G_TYPE_OBJECT,
161  G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, gnc_sx_slr_tree_model_adapter_interface_init))
162 
163 static void
164 gnc_sx_slr_tree_model_adapter_class_init (GncSxSlrTreeModelAdapterClass *klass)
165 {
166  GObjectClass *obj_class = G_OBJECT_CLASS(klass);
167 
168  obj_class->dispose = gnc_sx_slr_tree_model_adapter_dispose;
169  obj_class->finalize = gnc_sx_slr_tree_model_adapter_finalize;
170 }
171 
172 static GtkTreeModelFlags
173 gsslrtma_get_flags (GtkTreeModel *tree_model)
174 {
175  return gtk_tree_model_get_flags (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real));
176 }
177 
178 static gint
179 gsslrtma_get_n_columns (GtkTreeModel *tree_model)
180 {
181  return gtk_tree_model_get_n_columns (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real));
182 }
183 
184 static GType
185 gsslrtma_get_column_type (GtkTreeModel *tree_model, gint index)
186 {
187  return gtk_tree_model_get_column_type (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), index);
188 }
189 
190 static gboolean
191 gsslrtma_get_iter (GtkTreeModel *tree_model,
192  GtkTreeIter *iter,
193  GtkTreePath *path)
194 {
195  return gtk_tree_model_get_iter (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, path);
196 }
197 
198 static GtkTreePath*
199 gsslrtma_get_path (GtkTreeModel *tree_model,
200  GtkTreeIter *iter)
201 {
202  return gtk_tree_model_get_path (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
203 }
204 
205 static void
206 gsslrtma_get_value (GtkTreeModel *tree_model,
207  GtkTreeIter *iter,
208  gint column,
209  GValue *value)
210 {
211  gtk_tree_model_get_value (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, column, value);
212 }
213 
214 static gboolean
215 gsslrtma_iter_next (GtkTreeModel *tree_model,
216  GtkTreeIter *iter)
217 {
218  return gtk_tree_model_iter_next (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
219 }
220 
221 static gboolean
222 gsslrtma_iter_children (GtkTreeModel *tree_model,
223  GtkTreeIter *iter,
224  GtkTreeIter *parent)
225 {
226  return gtk_tree_model_iter_children (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, parent);
227 }
228 
229 static gboolean
230 gsslrtma_iter_has_child (GtkTreeModel *tree_model,
231  GtkTreeIter *iter)
232 {
233  return gtk_tree_model_iter_has_child (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
234 }
235 
236 static gint
237 gsslrtma_iter_n_children (GtkTreeModel *tree_model,
238  GtkTreeIter *iter)
239 {
240  return gtk_tree_model_iter_n_children (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
241 }
242 
243 static gboolean
244 gsslrtma_iter_nth_child (GtkTreeModel *tree_model,
245  GtkTreeIter *iter,
246  GtkTreeIter *parent,
247  gint n)
248 {
249  return gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, parent, n);
250 }
251 
252 static gboolean
253 gsslrtma_iter_parent (GtkTreeModel *tree_model,
254  GtkTreeIter *iter,
255  GtkTreeIter *child)
256 {
257  return gtk_tree_model_iter_parent (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, child);
258 }
259 
260 static void
261 gsslrtma_ref_node (GtkTreeModel *tree_model,
262  GtkTreeIter *iter)
263 {
264  gtk_tree_model_ref_node (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
265 }
266 
267 static void
268 gsslrtma_unref_node (GtkTreeModel *tree_model,
269  GtkTreeIter *iter)
270 {
271  gtk_tree_model_unref_node (GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
272 }
273 
274 static void
275 gnc_sx_slr_tree_model_adapter_interface_init (GtkTreeModelIface *tree_model)
276 {
277  tree_model->get_flags = gsslrtma_get_flags;
278  tree_model->get_n_columns = gsslrtma_get_n_columns;
279  tree_model->get_column_type = gsslrtma_get_column_type;
280  tree_model->get_iter = gsslrtma_get_iter;
281  tree_model->get_path = gsslrtma_get_path;
282  tree_model->get_value = gsslrtma_get_value;
283  tree_model->iter_next = gsslrtma_iter_next;
284  tree_model->iter_children = gsslrtma_iter_children;
285  tree_model->iter_has_child = gsslrtma_iter_has_child;
286  tree_model->iter_n_children = gsslrtma_iter_n_children;
287  tree_model->iter_nth_child = gsslrtma_iter_nth_child;
288  tree_model->iter_parent = gsslrtma_iter_parent;
289  tree_model->ref_node = gsslrtma_ref_node;
290  tree_model->unref_node = gsslrtma_unref_node;
291 }
292 
293 static void
294 gsslrtma_proxy_row_changed (GtkTreeModel *treemodel,
295  GtkTreePath *arg1,
296  GtkTreeIter *arg2,
297  gpointer user_data)
298 {
299  g_signal_emit_by_name (user_data, "row-changed", arg1, arg2);
300 }
301 
302 static void
303 gsslrtma_proxy_row_deleted (GtkTreeModel *treemodel,
304  GtkTreePath *arg1,
305  gpointer user_data)
306 {
307  g_signal_emit_by_name (user_data, "row-deleted", arg1);
308 }
309 
310 static void
311 gsslrtma_proxy_row_has_child_toggled (GtkTreeModel *treemodel,
312  GtkTreePath *arg1,
313  GtkTreeIter *arg2,
314  gpointer user_data)
315 {
316  g_signal_emit_by_name (user_data, "row-has-child-toggled", arg1, arg2);
317 }
318 
319 static void
320 gsslrtma_proxy_row_inserted (GtkTreeModel *treemodel,
321  GtkTreePath *arg1,
322  GtkTreeIter *arg2,
323  gpointer user_data)
324 {
325  g_signal_emit_by_name (user_data, "row-inserted", arg1, arg2);
326 }
327 
328 static void
329 gsslrtma_proxy_rows_reordered (GtkTreeModel *treemodel,
330  GtkTreePath *arg1,
331  GtkTreeIter *arg2,
332  gpointer arg3,
333  gpointer user_data)
334 {
335  g_signal_emit_by_name (user_data, "rows-reordered", arg1, arg2, arg3);
336 }
337 
338 // model columns
339 enum
340 {
341  SLR_MODEL_COL_NAME = 0,
342  SLR_MODEL_COL_INSTANCE_PTR,
343  SLR_MODEL_COL_INSTANCE_STATE,
344  SLR_MODEL_COL_VARAIBLE_VALUE,
345  SLR_MODEL_COL_INSTANCE_VISIBILITY,
346  SLR_MODEL_COL_VARIABLE_VISIBILITY,
347  SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY,
348  SLR_MODEL_COL_INSTANCE_DATE,
349 };
350 
351 static void
352 gnc_sx_slr_tree_model_adapter_init (GncSxSlrTreeModelAdapter *adapter)
353 {
354  // columns: thing-name, ptr, instance-state, variable-value, instance-visible, variable-visible, instance_state_sensitivity, date
355  // at depth=0: <sx>, instances, N/A, N/A N/A, N/A N/A N/A
356  // at depth=1: <instance>, instance, <state>, N/A, <valid>, N/A, <valid> <date>
357  // at depth=2: <variable>, var, N/A, <value>, N/A, <valid>, N/A N/A
358  adapter->real = gtk_tree_store_new (8, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT64);
359 
360  g_signal_connect (adapter->real, "row-changed", G_CALLBACK(gsslrtma_proxy_row_changed), adapter);
361  g_signal_connect (adapter->real, "row-deleted", G_CALLBACK(gsslrtma_proxy_row_deleted), adapter);
362  g_signal_connect (adapter->real, "row-has-child-toggled", G_CALLBACK(gsslrtma_proxy_row_has_child_toggled), adapter);
363  g_signal_connect (adapter->real, "row-inserted", G_CALLBACK(gsslrtma_proxy_row_inserted), adapter);
364  g_signal_connect (adapter->real, "rows-reordered", G_CALLBACK(gsslrtma_proxy_rows_reordered), adapter);
365 }
366 
367 static char* gnc_sx_instance_state_names[] =
368 {
369  N_("Ignored"),
370  N_("Postponed"),
371  N_("To-Create"),
372  N_("Reminder"),
373  N_("Created"),
374  NULL
375 };
376 
377 static GtkTreeModel* _singleton_slr_state_model = NULL;
378 
379 GtkTreeModel*
380 gnc_sx_get_slr_state_model (void)
381 {
382  if (_singleton_slr_state_model == NULL)
383  {
384  int i;
385  GtkTreeIter iter;
386 
387  _singleton_slr_state_model = GTK_TREE_MODEL(gtk_list_store_new (1, G_TYPE_STRING));
388  for (i = 0; i != SX_INSTANCE_STATE_CREATED; i++)
389  {
390  gtk_list_store_insert_with_values (GTK_LIST_STORE(_singleton_slr_state_model),
391  &iter,
392  SX_INSTANCE_STATE_MAX_STATE + 1,
393  0, _(gnc_sx_instance_state_names[i]), -1);
394  }
395  }
396  return _singleton_slr_state_model;
397 }
398 
399 static void
400 _consume_excess_rows (GtkTreeStore *store, int last_index, GtkTreeIter *parent_iter, GtkTreeIter *maybe_invalid_iter)
401 {
402  if (last_index == -1)
403  {
404  // try to get whatever was there beforehand, if it exists
405  if (!gtk_tree_model_iter_children (GTK_TREE_MODEL(store), maybe_invalid_iter, parent_iter))
406  return;
407  }
408  else
409  {
410  // increment the iter, or bail out.
411  if (!gtk_tree_model_iter_next (GTK_TREE_MODEL(store), maybe_invalid_iter))
412  return;
413  }
414 
415  // consume until we're done.
416  while (gtk_tree_store_remove (store, maybe_invalid_iter));
417 }
418 
419 
420 static void
421 gsslrtma_populate_tree_store (GncSxSlrTreeModelAdapter *model)
422 {
423  GtkTreeIter sx_tree_iter;
424  GList *sx_iter;
425  int instances_index = -1;
426 
427  for (sx_iter = gnc_sx_instance_model_get_sx_instances_list (model->instances); sx_iter != NULL; sx_iter = sx_iter->next)
428  {
429  GncSxInstances *instances = (GncSxInstances*)sx_iter->data;
430  char last_occur_date_buf[MAX_DATE_LENGTH+1];
431 
432  {
433  const GDate *last_occur = xaccSchedXactionGetLastOccurDate (instances->sx);
434  if (last_occur == NULL || !g_date_valid (last_occur))
435  {
436  g_stpcpy (last_occur_date_buf, _("Never"));
437  }
438  else
439  {
440  qof_print_gdate (last_occur_date_buf,
442  last_occur);
443  }
444  }
445 
446  // if there are no instances for the instance skip adding
447  if (g_list_length (instances->instance_list) == 0)
448  continue;
449 
450  if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(model->real), &sx_tree_iter, NULL, ++instances_index))
451  {
452  gtk_tree_store_append (model->real, &sx_tree_iter, NULL);
453  }
454 
455  gtk_tree_store_set (model->real, &sx_tree_iter,
456  SLR_MODEL_COL_NAME, xaccSchedXactionGetName (instances->sx),
457  SLR_MODEL_COL_INSTANCE_STATE, NULL,
458  SLR_MODEL_COL_VARAIBLE_VALUE, NULL,
459  SLR_MODEL_COL_INSTANCE_VISIBILITY, FALSE,
460  SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE,
461  SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE,
462  SLR_MODEL_COL_INSTANCE_DATE, INT64_MAX,
463  SLR_MODEL_COL_INSTANCE_PTR, instances,
464  -1);
465 
466  if (qof_log_check (GNC_MOD_GUI_SX, QOF_LOG_DEBUG))
467  {
468  gchar *path_str = gtk_tree_path_to_string (gtk_tree_model_get_path (GTK_TREE_MODEL(model->real), &sx_tree_iter));
469  DEBUG("Add schedule [%s], instances %p at path [%s]", xaccSchedXactionGetName (instances->sx), instances, path_str);
470  g_free (path_str);
471  }
472 
473  // Insert instance information
474  {
475  GList *inst_iter;
476  GtkTreeIter inst_tree_iter;
477  char instance_date_buf[MAX_DATE_LENGTH+1];
478  int instance_index = -1;
479 
480  for (inst_iter = instances->instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
481  {
482  GncSxInstance *inst = (GncSxInstance*)inst_iter->data;
483  qof_print_gdate (instance_date_buf, MAX_DATE_LENGTH, &inst->date);
484  time64 t = gdate_to_time64 (inst->date);
485 
486  if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(model->real), &inst_tree_iter, &sx_tree_iter, ++instance_index))
487  {
488  gtk_tree_store_append (model->real, &inst_tree_iter, &sx_tree_iter);
489  }
490  gtk_tree_store_set (model->real, &inst_tree_iter,
491  SLR_MODEL_COL_NAME, instance_date_buf,
492  SLR_MODEL_COL_INSTANCE_STATE, _(gnc_sx_instance_state_names[inst->state]),
493  SLR_MODEL_COL_VARAIBLE_VALUE, NULL,
494  SLR_MODEL_COL_INSTANCE_VISIBILITY, TRUE,
495  SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE,
496  SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, inst->state != SX_INSTANCE_STATE_CREATED,
497  SLR_MODEL_COL_INSTANCE_DATE, t,
498  SLR_MODEL_COL_INSTANCE_PTR, inst,
499  -1);
500 
501  // Insert variable information
502  {
503  GList *vars = NULL, *var_iter;
504  GtkTreeIter var_tree_iter;
505  gint visible_variable_index = -1;
506 
507  vars = gnc_sx_instance_get_variables (inst);
508  for (var_iter = vars; var_iter != NULL; var_iter = var_iter->next)
509  {
510  GncSxVariable *var = (GncSxVariable*)var_iter->data;
511  GString *tmp_str;
512 
513  if (!var->editable)
514  continue;
515 
516  if (gnc_numeric_check (var->value) == GNC_ERROR_OK)
517  {
518  _var_numeric_to_string (&var->value, &tmp_str);
519  }
520  else
521  {
522  tmp_str = g_string_new (_("(Need Value)"));
523  }
524 
525  if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(model->real),
526  &var_tree_iter, &inst_tree_iter,
527  ++visible_variable_index))
528  {
529  gtk_tree_store_append (model->real, &var_tree_iter, &inst_tree_iter);
530  }
531  gtk_tree_store_set (model->real, &var_tree_iter,
532  SLR_MODEL_COL_NAME, var->name,
533  SLR_MODEL_COL_INSTANCE_STATE, NULL,
534  SLR_MODEL_COL_VARAIBLE_VALUE, tmp_str->str,
535  SLR_MODEL_COL_INSTANCE_VISIBILITY, FALSE,
536  SLR_MODEL_COL_VARIABLE_VISIBILITY, TRUE,
537  SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE,
538  SLR_MODEL_COL_INSTANCE_DATE, INT64_MAX,
539  SLR_MODEL_COL_INSTANCE_PTR, var,
540  -1);
541  g_string_free (tmp_str, TRUE);
542  }
543  g_list_free (vars);
544 
545  _consume_excess_rows (model->real, visible_variable_index, &inst_tree_iter, &var_tree_iter);
546  }
547  }
548 
549  // if there are more instance iters, remove
550  _consume_excess_rows (model->real, instance_index, &sx_tree_iter, &inst_tree_iter);
551  }
552  }
553  _consume_excess_rows (model->real, instances_index, NULL, &sx_tree_iter);
554 }
555 
556 GncSxInstanceModel*
557 gnc_sx_slr_tree_model_adapter_get_instance_model (GncSxSlrTreeModelAdapter *slr_model)
558 {
559  return slr_model->instances;
560 }
561 
563 gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter)
564 {
565  return _gnc_sx_slr_model_get_instance (model, iter, TRUE);
566 }
567 
568 static GncSxInstance*
569 _gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter, gboolean check_depth)
570 {
571  GtkTreePath *model_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
572  gint *indices, instances_index, instance_index;
573  GncSxInstance *instance = NULL;
574  GtkTreeIter new_iter;
575 
576  debug_path (DEBUG, "model path is:", model_path);
577 
578  if (check_depth && gtk_tree_path_get_depth (model_path) != 2)
579  {
580  PWARN("path depth not equal to 2");
581  gtk_tree_path_free (model_path);
582  return NULL;
583  }
584 
585  if (gtk_tree_path_get_depth (model_path) == 1)
586  {
587  PWARN("path depth equal to 1");
588  gtk_tree_path_free (model_path);
589  return NULL;
590  }
591 
592  indices = gtk_tree_path_get_indices (model_path);
593  instances_index = indices[0];
594  instance_index = indices[1];
595 
596  gtk_tree_path_free (model_path);
597 
598  model_path = gtk_tree_path_new_from_indices (instances_index, instance_index, -1);
599 
600  debug_path (DEBUG, "new model path is:", model_path);
601 
602  if (gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &new_iter, model_path))
603  gtk_tree_model_get (GTK_TREE_MODEL(model), &new_iter, SLR_MODEL_COL_INSTANCE_PTR, &instance, -1);
604 
605  gtk_tree_path_free (model_path);
606 
607  DEBUG("instance is %p", instance);
608 
609  return instance;
610 }
611 
612 gboolean
613 gnc_sx_slr_model_get_instance_and_variable (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter, GncSxInstance **instance_loc, GncSxVariable **var_loc)
614 {
615  GtkTreePath *model_path;
616  gint *indices, variable_index;
617  GncSxInstance *instance;
618  GList *variables;
619 
620  instance = _gnc_sx_slr_model_get_instance (model, iter, FALSE);
621  if (instance == NULL)
622  {
623  gchar *iter_str = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL(model), iter);
624  PWARN("instance is NULL for iter %s", iter_str);
625  g_free (iter_str);
626  return FALSE;
627  }
628  variables = gnc_sx_instance_get_variables (instance);
629 
630  model_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
631  if (gtk_tree_path_get_depth (model_path) != 3)
632  {
633  gchar *path_str = gtk_tree_path_to_string (model_path);
634  PWARN("invalid path [%s] for variable, not at depth 3", path_str);
635  gtk_tree_path_free (model_path);
636  g_free (path_str);
637  return FALSE;
638  }
639 
640  debug_path (DEBUG, "model path is:", model_path);
641 
642  indices = gtk_tree_path_get_indices (model_path);
643  variable_index = indices[2];
644 
645  gtk_tree_path_free (model_path);
646 
647  if (variable_index < 0 || variable_index >= g_list_length (variables))
648  {
649  PWARN("variable index %d out of range", variable_index);
650  g_list_free (variables);
651  return FALSE;
652  }
653 
654  if (instance_loc != NULL)
655  {
656  *instance_loc = instance;
657  }
658 
659  if (var_loc != NULL)
660  {
661  GncSxVariable *var;
662 
663  gtk_tree_model_get (GTK_TREE_MODEL(model), iter, SLR_MODEL_COL_INSTANCE_PTR, &var, -1);
664 
665  *var_loc = var;
666  }
667  g_list_free (variables);
668  return TRUE;
669 }
670 
674 static gint
675 _variable_list_index (GList *variables, GncSxVariable *variable)
676 {
677  gint index = 0;
678  for (; variables != NULL; variables = variables->next)
679  {
680  GncSxVariable *var = (GncSxVariable*)variables->data;
681  if (!var->editable)
682  continue;
683  if (variable == var)
684  return index;
685  index++;
686  }
687  return -1;
688 }
689 
690 typedef struct _findInstanceData
691 {
692  gpointer find_item;
693  GtkTreePath *found_path;
695 
696 static gboolean
697 for_each_find_item (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
698 {
699  FindInstanceData* to_find = (FindInstanceData*)user_data;
700  gpointer item;
701 
702  gtk_tree_model_get (model, iter, SLR_MODEL_COL_INSTANCE_PTR, &item, -1);
703 
704  if (item == to_find->find_item)
705  {
706  to_find->found_path = gtk_tree_path_copy (path);
707  return TRUE;
708  }
709  return FALSE;
710 }
711 
712 static GtkTreePath*
713 _get_model_path_for_item (GtkTreeModel *model, gpointer find_item)
714 {
715  GtkTreePath *model_path = NULL;
716  FindInstanceData* to_find_data;
717 
718  to_find_data = (FindInstanceData*)g_new0 (FindInstanceData, 1);
719  to_find_data->find_item = find_item;
720  to_find_data->found_path = NULL;
721 
722  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)for_each_find_item, to_find_data);
723 
724  if (to_find_data->found_path)
725  {
726  model_path = gtk_tree_path_copy (to_find_data->found_path);
727  gtk_tree_path_free (to_find_data->found_path);
728  }
729  g_free (to_find_data);
730 
731  return model_path;
732 }
733 
734 static GtkTreePath*
735 _get_model_path_for_instance (GtkTreeModel *model, GncSxInstance *instance)
736 {
737  return _get_model_path_for_item (model, instance);
738 }
739 
740 static GtkTreePath*
741 _get_model_path_for_instances (GtkTreeModel *model, GncSxInstances *instances)
742 {
743  return _get_model_path_for_item (model, instances);
744 }
745 
746 static GtkTreePath*
747 _get_path_for_variable (GncSxSinceLastRunDialog *app_dialog, GncSxInstance *instance, GncSxVariable *variable)
748 {
749  GncSxSlrTreeModelAdapter *model = app_dialog->editing_model;
750  GtkTreeModel *sort_model = gtk_tree_view_get_model (app_dialog->instance_view);
751  gint *indices, instances_index, instance_index, variable_index;
752  GtkTreePath *view_path, *model_path;
753  GList *variables;
754 
755  model_path = _get_model_path_for_instance (GTK_TREE_MODEL(model), instance);
756 
757  if (!model_path)
758  {
759  PWARN("model path is NULL for instance %p", instance);
760  return NULL;
761  }
762 
763  debug_path (DEBUG, "instance model path is:", model_path);
764 
765  indices = gtk_tree_path_get_indices (model_path);
766  instances_index = indices[0];
767  instance_index = indices[1];
768 
769  gtk_tree_path_free (model_path);
770 
771  variables = gnc_sx_instance_get_variables (instance);
772  variable_index = _variable_list_index (variables, variable);
773  g_list_free (variables);
774  if (variable_index == -1)
775  return NULL;
776 
777  model_path = gtk_tree_path_new_from_indices (instances_index, instance_index, variable_index, -1);
778  debug_path (DEBUG, "model variable path is:", model_path);
779 
780  view_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT(sort_model), model_path);
781  gtk_tree_path_free (model_path);
782 
783  debug_path (DEBUG, "return view variable path is:", view_path);
784 
785  return view_path;
786 }
787 
788 static void
789 gsslrtma_added_cb (GncSxInstanceModel *instances, SchedXaction *added_sx, gpointer user_data)
790 {
791  GncSxSlrTreeModelAdapter *model = GNC_SX_SLR_TREE_MODEL_ADAPTER(user_data);
792  // this is wasteful, but fine.
793  gsslrtma_populate_tree_store (model);
794 }
795 
796 static void
797 gsslrtma_updated_cb (GncSxInstanceModel *instances, SchedXaction *updated_sx, gpointer user_data)
798 {
799  GncSxSlrTreeModelAdapter *model = GNC_SX_SLR_TREE_MODEL_ADAPTER(user_data);
800  gnc_sx_instance_model_update_sx_instances (instances, updated_sx);
801  gsslrtma_populate_tree_store (model);
802 }
803 
804 static void
805 gsslrtma_removing_cb (GncSxInstanceModel *inst_model, SchedXaction *to_remove_sx, gpointer user_data)
806 {
807  GncSxSlrTreeModelAdapter *model = GNC_SX_SLR_TREE_MODEL_ADAPTER(user_data);
808  GtkTreePath *model_path;
809  GtkTreeIter tree_iter;
810  GList *iter;
811  GncSxInstances *instances;
812 
813  // get instances, create path, remove
814  for (iter = gnc_sx_instance_model_get_sx_instances_list (inst_model); iter != NULL; iter = iter->next)
815  {
816  instances = (GncSxInstances*)iter->data;
817  if (instances->sx == to_remove_sx)
818  break;
819  }
820  if (iter == NULL)
821  {
822  PWARN("could not find sx %p in the model", to_remove_sx);
823  return; // couldn't find sx in our model, which is weird.
824  }
825 
826  model_path = _get_model_path_for_instances (GTK_TREE_MODEL(model), instances);
827 
828  debug_path (DEBUG, "remove model_path", model_path);
829 
830  if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model->real), &tree_iter, model_path))
831  {
832  gchar *path_str = gtk_tree_path_to_string (model_path);
833  PWARN("invalid path [%s] for instances %p to remove", path_str, instances);
834  gtk_tree_path_free (model_path);
835  g_free (path_str);
836  return;
837  }
838  gtk_tree_path_free (model_path);
839 
840  gtk_tree_store_remove (model->real, &tree_iter);
841 
842  gnc_sx_instance_model_remove_sx_instances (inst_model, to_remove_sx);
843 }
844 
845 static void
846 gnc_sx_slr_tree_model_adapter_dispose (GObject *obj)
847 {
848  GncSxSlrTreeModelAdapter *adapter;
849  g_return_if_fail (obj != NULL);
850  adapter = GNC_SX_SLR_TREE_MODEL_ADAPTER(obj);
851  g_return_if_fail (!adapter->disposed);
852  adapter->disposed = TRUE;
853 
854  g_object_unref (G_OBJECT(adapter->instances));
855  adapter->instances = NULL;
856  g_object_unref (G_OBJECT(adapter->real));
857  adapter->real = NULL;
858 
859  G_OBJECT_CLASS(gnc_sx_slr_tree_model_adapter_parent_class)->dispose (obj);
860 }
861 
862 static void
863 gnc_sx_slr_tree_model_adapter_finalize (GObject *obj)
864 {
865  g_return_if_fail (obj != NULL);
866  G_OBJECT_CLASS(gnc_sx_slr_tree_model_adapter_parent_class)->finalize (obj);
867 }
868 
869 GncSxSlrTreeModelAdapter*
870 gnc_sx_slr_tree_model_adapter_new (GncSxInstanceModel *instances)
871 {
872  GncSxSlrTreeModelAdapter *rtn;
873  rtn = GNC_SX_SLR_TREE_MODEL_ADAPTER(g_object_new (GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, NULL));
874  rtn->instances = instances;
875  g_object_ref (G_OBJECT(rtn->instances));
876  gsslrtma_populate_tree_store (rtn);
877  g_signal_connect (G_OBJECT(rtn->instances), "added", (GCallback)gsslrtma_added_cb, (gpointer)rtn);
878  rtn->updated_cb_id = g_signal_connect (G_OBJECT(rtn->instances), "updated", (GCallback)gsslrtma_updated_cb, (gpointer)rtn);
879  g_signal_connect (G_OBJECT(rtn->instances), "removing", (GCallback)gsslrtma_removing_cb, (gpointer)rtn);
880  return rtn;
881 }
882 
883 void
884 gnc_ui_sx_creation_error_dialog (GList **creation_errors)
885 {
886  GtkWidget *dialog = NULL;
887  gchar *message = NULL;
888  if (*creation_errors == NULL) return;
889  message = gnc_g_list_stringjoin (*creation_errors, "\n");
890  g_list_free_full (*creation_errors, g_free);
891  creation_errors = NULL;
892  dialog = gtk_message_dialog_new (NULL, 0,
893  GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
894  "\t%s\t", _("Invalid Transactions"));
895  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
896  "%s", message);
897  g_signal_connect_swapped (dialog, "response",
898  G_CALLBACK(gtk_widget_destroy), dialog);
899  gtk_dialog_run (GTK_DIALOG(dialog));
900  g_free (message);
901 }
902 
903 static GtkTreePath *
904 instance_get_model_path (GtkTreeView *view, const gchar *path)
905 {
906  GtkTreePath *view_path = gtk_tree_path_new_from_string (path);
907  GtkTreeModelSort *sort_model = GTK_TREE_MODEL_SORT(gtk_tree_view_get_model (view));
908 
909  GtkTreePath *model_path = gtk_tree_model_sort_convert_path_to_child_path (sort_model, view_path);
910 
911  gtk_tree_path_free (view_path);
912 
913  return model_path;
914 }
915 
916 static void
917 instance_state_changed_cb (GtkCellRendererText *cell,
918  const gchar *path,
919  const gchar *value,
920  GncSxSinceLastRunDialog *dialog)
921 {
922  GncSxInstance *inst;
923  int i;
924  GncSxInstanceState new_state;
925  GtkTreePath *model_path = instance_get_model_path (dialog->instance_view, path);
926  GtkTreeIter tree_iter;
927 
928  DEBUG("change instance state to [%s] at path [%s]", value, path);
929 
930  debug_path (DEBUG, "instance model path is:", model_path);
931 
932  for (i = 0; i < SX_INSTANCE_STATE_CREATED; i++)
933  {
934  if (strcmp (value, _(gnc_sx_instance_state_names[i])) == 0)
935  break;
936  }
937  if (i == SX_INSTANCE_STATE_CREATED)
938  {
939  PWARN("unknown value [%s]", value);
940  return;
941  }
942  new_state = i;
943 
944  if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(dialog->editing_model), &tree_iter, model_path))
945  {
946  gtk_tree_path_free (model_path);
947  PWARN("unknown path [%s]", path);
948  return;
949  }
950  gtk_tree_path_free (model_path);
951 
952  inst = gnc_sx_slr_model_get_instance (dialog->editing_model, &tree_iter);
953 
954  if (inst == NULL)
955  {
956  PWARN("invalid path [%s]", path);
957  return;
958  }
959 
960  DEBUG("instance is %p", inst);
961 
962  gnc_sx_instance_model_change_instance_state (dialog->editing_model->instances, inst, new_state);
963 }
964 
965 static void
966 control_scroll_bars (GncSxSinceLastRunDialog *dialog)
967 {
968  GtkWidget *sw = gtk_widget_get_parent (GTK_WIDGET(dialog->instance_view));
969  GtkWidget *vsbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW(sw));
970  gboolean enable = TRUE;
971 
972  if (dialog->temp_ce)
973  enable = FALSE;
974 
975  gtk_widget_set_sensitive (vsbar, enable);
976  gtk_widget_set_visible (vsbar, enable);
977 }
978 
979 static void
980 variable_value_changed_cb (GtkCellRendererText *cell,
981  const gchar *path,
982  const gchar *value,
983  GncSxSinceLastRunDialog *dialog)
984 {
985  GncSxVariable *var = NULL;
986  GncSxInstance *inst;
987  gnc_numeric parsed_num;
988  char *endStr = NULL;
989  GtkTreePath *model_path = instance_get_model_path (dialog->instance_view, path);
990  GtkTreeIter tree_iter;
991 
992  DEBUG("change variable to [%s] at view path [%s]", value, path);
993 
994  debug_path (DEBUG, "instance model path is:", model_path);
995 
996  dialog->temp_ce = NULL;
997  control_scroll_bars (dialog);
998 
999  if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(dialog->editing_model), &tree_iter, model_path))
1000  {
1001  gtk_tree_path_free (model_path);
1002  PWARN("invalid path [%s]", path);
1003  return;
1004  }
1005  gtk_tree_path_free (model_path);
1006 
1007  if (!gnc_sx_slr_model_get_instance_and_variable (dialog->editing_model, &tree_iter, &inst, &var))
1008  {
1009  PWARN("path [%s] doesn't correspond to a valid variable", path);
1010  return;
1011  }
1012 
1013  if (!xaccParseAmount (value, TRUE, &parsed_num, &endStr)
1014  || gnc_numeric_check (parsed_num) != GNC_ERROR_OK)
1015  {
1016  gchar *value_copy = g_strdup (value);
1017  DEBUG ("value=[%s] endStr[%s]", value, endStr);
1018  if (strlen (g_strstrip (value_copy)) == 0)
1019  {
1020  gnc_numeric invalid_num = gnc_numeric_error (GNC_ERROR_ARG);
1021  gnc_sx_instance_model_set_variable (dialog->editing_model->instances, inst, var, &invalid_num);
1022  }
1023  else
1024  {
1025  PWARN("error parsing value [%s]", value);
1026  }
1027  g_free (value_copy);
1028  return;
1029  }
1030 
1031  if (inst->state == SX_INSTANCE_STATE_REMINDER)
1032  {
1033  gnc_sx_instance_model_change_instance_state (dialog->editing_model->instances, inst,
1034  SX_INSTANCE_STATE_TO_CREATE);
1035  }
1036  gnc_sx_instance_model_set_variable (dialog->editing_model->instances, inst, var, &parsed_num);
1037 }
1038 
1039 static void
1040 variable_value_start_changed_cb (GtkCellRenderer *renderer, GtkCellEditable *editable,
1041  gchar *path, gpointer user_data)
1042 {
1043  GncSxSinceLastRunDialog *dialog = user_data;
1044  dialog->temp_ce = editable;
1045  control_scroll_bars (dialog);
1046 }
1047 
1048 static void
1049 variable_value_cancel_changed_cb (GtkCellRenderer *renderer, gpointer user_data)
1050 {
1051  GncSxSinceLastRunDialog *dialog = user_data;
1052  dialog->temp_ce = NULL;
1053  control_scroll_bars (dialog);
1054 }
1055 
1056 static gint
1057 _sort_text (const gchar *text_a, const gchar *text_b)
1058 {
1059  gchar *a_caseless, *b_caseless;
1060  gint rtn = 0;
1061 
1062  if (text_a == NULL && text_b == NULL) return 0;
1063  if (text_a == NULL) return 1;
1064  if (text_b == NULL) return -1;
1065 
1066  a_caseless = g_utf8_casefold (text_a, -1);
1067  b_caseless = g_utf8_casefold (text_b, -1);
1068  rtn = g_strcmp0 (a_caseless, b_caseless);
1069  g_free (a_caseless);
1070  g_free (b_caseless);
1071 
1072  return rtn;
1073 }
1074 
1075 static gint
1076 _transaction_sort_func_date (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b)
1077 {
1078  GtkTreePath *path_a = gtk_tree_model_get_path (model, iter_a);
1079  gint depth = gtk_tree_path_get_depth (path_a);
1080  gint64 date_a = 0, date_b = 0;
1081  gint rtn = 0;
1082 
1083  gtk_tree_path_free (path_a);
1084 
1085  if (depth == 3)
1086  return rtn;
1087 
1088  // if top level, look at the first date for order
1089  if (depth == 1)
1090  {
1091  GtkTreeIter child_iter_a, child_iter_b;
1092 
1093  if (gtk_tree_model_iter_nth_child (model, &child_iter_a, iter_a, 0))
1094  gtk_tree_model_get (model, &child_iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
1095 
1096  if (gtk_tree_model_iter_nth_child (model, &child_iter_b, iter_b, 0))
1097  gtk_tree_model_get (model, &child_iter_b, SLR_MODEL_COL_INSTANCE_DATE, &date_b, -1);
1098 
1099  if (date_a > date_b)
1100  rtn = 1;
1101  if (date_b > date_a)
1102  rtn = -1;
1103 
1104  if (rtn == 0) // if dates are equal, look at name
1105  {
1106  gchar *name_text_a, *name_text_b;
1107 
1108  gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_NAME, &name_text_a, -1);
1109  gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_NAME, &name_text_b, -1);
1110 
1111  rtn = _sort_text (name_text_a, name_text_b);
1112 
1113  g_free (name_text_a);
1114  g_free (name_text_b);
1115  }
1116  return rtn;
1117  }
1118 
1119  gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
1120  gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_INSTANCE_DATE, &date_b, -1);
1121 
1122  if (date_a > date_b)
1123  rtn = 1;
1124  if (date_b > date_a)
1125  rtn = -1;
1126 
1127  return rtn;
1128 }
1129 
1130 static gint
1131 _transaction_sort_func_desc (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b)
1132 {
1133  GtkTreePath *path_a = gtk_tree_model_get_path (model, iter_a);
1134  gint depth = gtk_tree_path_get_depth (path_a);
1135  gchar *name_text_a, *name_text_b;
1136  gint rtn = 0;
1137 
1138  gtk_tree_path_free (path_a);
1139 
1140  if (depth == 3)
1141  return rtn;
1142 
1143  if (depth == 1)
1144  {
1145  gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_NAME, &name_text_a, -1);
1146  gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_NAME, &name_text_b, -1);
1147 
1148  rtn = _sort_text (name_text_a, name_text_b);
1149 
1150  g_free (name_text_a);
1151  g_free (name_text_b);
1152  }
1153 
1154  if (depth == 2)
1155  {
1156  gint64 date_a = 0, date_b = 0;
1157 
1158  gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
1159  gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_INSTANCE_DATE, &date_b, -1);
1160 
1161  if (date_a > date_b)
1162  rtn = 1;
1163  if (date_b > date_a)
1164  rtn = -1;
1165  }
1166  return rtn;
1167 }
1168 
1169 static gint
1170 _transaction_sort_func (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
1171 {
1172  GncSxSinceLastRunDialog *dialog = user_data;
1173 
1174  if (dialog->sort_selection_depth == 1)
1175  return _transaction_sort_func_desc (model, iter_a, iter_b);
1176  else
1177  return _transaction_sort_func_date (model, iter_a, iter_b);
1178 }
1179 
1180 static gboolean
1181 finish_editing_before_ok_cb (GtkWidget *button, GdkEvent *event,
1182  GncSxSinceLastRunDialog *dialog)
1183 {
1184  // finish editing
1185  if (dialog->temp_ce)
1186  gtk_cell_editable_editing_done (dialog->temp_ce);
1187 
1188  dialog->temp_ce = NULL;
1189 
1190  return FALSE;
1191 }
1192 
1193 static gboolean
1194 scroll_event (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
1195 {
1196  GncSxSinceLastRunDialog *dialog = user_data;
1197 
1198  if (dialog->temp_ce)
1199  return TRUE;
1200  else
1201  return FALSE;
1202 }
1203 
1204 static void
1205 set_transaction_sort_column_tooltip (GncSxSinceLastRunDialog *dialog)
1206 {
1207  GtkTreeViewColumn *col = gtk_tree_view_get_column (GTK_TREE_VIEW(dialog->instance_view), 0);
1208  const gchar *date_text = _("Highlight a date first to sort by occurrence date.");
1209  const gchar *sched_text = _("Highlight a schedule first to sort by schedule name.");
1210  gchar *tooltip;
1211 
1212  if (dialog->sort_selection_depth == 1)
1213  tooltip = g_strconcat (sched_text, " *\n", date_text, NULL);
1214  else
1215  tooltip = g_strconcat (sched_text, "\n", date_text, " *", NULL);
1216 
1217  gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (col), tooltip);
1218  g_free (tooltip);
1219 }
1220 
1221 static gboolean
1222 follow_select_tree_path (GtkTreeView *view)
1223 {
1224  GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
1225  GtkTreeModel *sort_model;
1226  GtkTreeIter iter;
1227 
1228  if (gtk_tree_selection_get_selected (selection, &sort_model, &iter))
1229  {
1230  GtkTreePath *view_path = gtk_tree_model_get_path (sort_model, &iter);
1231 
1232  gtk_tree_view_scroll_to_cell (view, view_path, NULL, TRUE, 0.5, 0.0);
1233 
1234  gtk_tree_path_free (view_path);
1235  }
1236  return FALSE;
1237 }
1238 
1239 static void
1240 sort_column_changed (GtkTreeSortable* self, gpointer user_data)
1241 {
1242  // this is triggered before a sort change
1243  GncSxSinceLastRunDialog *dialog = user_data;
1244  GtkTreeIter iter;
1245  GtkTreeSelection *selection = gtk_tree_view_get_selection (dialog->instance_view);
1246  GtkTreeModel *sort_model;
1247 
1248  if (gtk_tree_selection_get_selected (selection, &sort_model, &iter))
1249  {
1250  GtkTreePath *view_path = gtk_tree_model_get_path (sort_model, &iter);
1251 
1252  dialog->sort_selection_depth = gtk_tree_path_get_depth (view_path);
1253 
1254  gtk_tree_path_free (view_path);
1255  }
1256  else
1257  dialog->sort_selection_depth = 1;
1258 
1259  set_transaction_sort_column_tooltip (dialog);
1260 
1261  g_idle_add ((GSourceFunc)follow_select_tree_path, dialog->instance_view);
1262 }
1263 
1264 static void
1265 since_last_run_dialog (GtkWindow *parent, GncSxInstanceModel *sx_instances, GList *auto_created_txn_guids)
1266 {
1267  GncSxSinceLastRunDialog *dialog;
1268  GtkBuilder *builder;
1269  GtkWidget *ok_button;
1270 
1271  dialog = g_new0 (GncSxSinceLastRunDialog, 1);
1272 
1273  builder = gtk_builder_new ();
1274  gnc_builder_add_from_file (builder, "dialog-sx.glade", "since_last_run_dialog");
1275 
1276  dialog->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "since_last_run_dialog"));
1277  gtk_window_set_transient_for (GTK_WINDOW(dialog->dialog), parent);
1278 
1279  // Set the name of this dialog so it can be easily manipulated with css
1280  gtk_widget_set_name (GTK_WIDGET(dialog->dialog), "gnc-id-sx-since-last-run");
1281  gnc_widget_style_context_add_class (GTK_WIDGET(dialog->dialog), "gnc-class-sx");
1282 
1283  dialog->editing_model = gnc_sx_slr_tree_model_adapter_new (sx_instances);
1284  dialog->review_created_txns_toggle = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "review_txn_toggle"));
1285 
1286  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->review_created_txns_toggle),
1287  gnc_prefs_get_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SET_REVIEW));
1288 
1289  dialog->created_txns = auto_created_txn_guids;
1290 
1291  ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "okbutton2"));
1292 
1293  g_signal_connect (G_OBJECT(ok_button), "button-press-event",
1294  G_CALLBACK(finish_editing_before_ok_cb), dialog);
1295 
1296  {
1297  GtkCellRenderer *renderer;
1298  GtkTreeViewColumn *col;
1299  GtkTreeModel *sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(dialog->editing_model));
1300 
1301  dialog->instance_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "instance_view"));
1302  gtk_tree_view_set_model (dialog->instance_view, GTK_TREE_MODEL(sort_model));
1303  g_object_unref (sort_model);
1304 
1305  /* default sort order */
1306  dialog->sort_selection_depth = gnc_prefs_get_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_DEPTH);
1307  gboolean sort_ascending = gnc_prefs_get_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_ASC);
1308  gint sort_column = gnc_prefs_get_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_COL);
1309  GtkSortType sort_type = sort_ascending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
1310 
1311  if (sort_column != 0)
1312  sort_column = 0;
1313 
1314  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(sort_model),
1315  sort_column, sort_type);
1316 
1317  g_signal_connect (G_OBJECT(dialog->instance_view), "scroll-event",
1318  G_CALLBACK(scroll_event), dialog);
1319 
1320  renderer = gtk_cell_renderer_text_new ();
1321  col = gtk_tree_view_column_new_with_attributes (_("Transaction"), renderer,
1322  "text", SLR_MODEL_COL_NAME,
1323  NULL);
1324  gtk_tree_view_append_column (dialog->instance_view, col);
1325 
1326  gtk_tree_view_column_set_sort_column_id (col, SLR_MODEL_COL_NAME);
1327 
1328  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sort_model), SLR_MODEL_COL_NAME,
1329  _transaction_sort_func, dialog, NULL);
1330 
1331  set_transaction_sort_column_tooltip (dialog);
1332 
1333  renderer = gtk_cell_renderer_combo_new ();
1334  g_object_set (G_OBJECT(renderer),
1335  "model", gnc_sx_get_slr_state_model (),
1336  "text-column", 0,
1337  "has-entry", FALSE,
1338  "editable", TRUE,
1339  NULL);
1340  g_signal_connect (G_OBJECT(renderer),
1341  "edited",
1342  G_CALLBACK(instance_state_changed_cb),
1343  dialog);
1344  col = gtk_tree_view_column_new_with_attributes (_("Status"), renderer,
1345  "text", SLR_MODEL_COL_INSTANCE_STATE,
1346  "visible", SLR_MODEL_COL_INSTANCE_VISIBILITY,
1347  // you might think only "sensitive" is required to
1348  // control the ability of the combo box to select
1349  // a new state, but you'd be wrong.
1350  "editable", SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY,
1351  "sensitive", SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY,
1352  NULL);
1353 
1354  g_signal_connect (G_OBJECT(sort_model), "sort-column-changed",
1355  G_CALLBACK(sort_column_changed), dialog);
1356 
1357  renderer = gtk_cell_renderer_pixbuf_new ();
1358  g_object_set (G_OBJECT(renderer),
1359  "icon-name", "pan-down-symbolic",
1360  NULL);
1361  gtk_tree_view_column_pack_end (col, renderer, FALSE);
1362  gtk_tree_view_column_set_attributes (col, renderer,
1363  "visible", SLR_MODEL_COL_INSTANCE_VISIBILITY,
1364  "sensitive", SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY,
1365  NULL);
1366  gtk_tree_view_append_column (dialog->instance_view, col);
1367  gtk_tree_view_column_set_resizable (col, FALSE);
1368 
1369  renderer = gtk_cell_renderer_text_new ();
1370  g_object_set (G_OBJECT(renderer),
1371  "editable", TRUE,
1372  NULL);
1373  g_signal_connect (G_OBJECT(renderer),
1374  "edited",
1375  G_CALLBACK(variable_value_changed_cb),
1376  dialog);
1377 
1378  g_signal_connect (G_OBJECT(renderer),
1379  "editing-started",
1380  G_CALLBACK(variable_value_start_changed_cb),
1381  dialog);
1382 
1383  g_signal_connect (G_OBJECT(renderer),
1384  "editing-canceled",
1385  (GCallback)variable_value_cancel_changed_cb,
1386  dialog);
1387 
1388  col = gtk_tree_view_column_new_with_attributes (_("Value"), renderer,
1389  "text", SLR_MODEL_COL_VARAIBLE_VALUE,
1390  "visible", SLR_MODEL_COL_VARIABLE_VISIBILITY,
1391  NULL);
1392  gtk_tree_view_append_column (dialog->instance_view, col);
1393 
1394  gtk_tree_view_expand_all (dialog->instance_view);
1395  }
1396 
1397  // Set grid lines option to preference
1398  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(dialog->instance_view), gnc_tree_view_get_grid_lines_pref ());
1399 
1400  g_signal_connect (G_OBJECT(dialog->dialog), "response", G_CALLBACK(dialog_response_cb), dialog);
1401  g_signal_connect (G_OBJECT(dialog->dialog), "destroy", G_CALLBACK(dialog_destroy_cb), dialog);
1402 
1403  gnc_restore_window_size (GNC_PREFS_GROUP_STARTUP, GTK_WINDOW(dialog->dialog), parent);
1404 
1405  dialog->component_id = gnc_register_gui_component (DIALOG_SX_SINCE_LAST_RUN_CM_CLASS,
1406  NULL, close_handler, dialog);
1407  gnc_gui_component_set_session (dialog->component_id,
1408  gnc_get_current_session ());
1409 
1410  gtk_widget_show_all (dialog->dialog);
1411 
1412  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, dialog);
1413 
1414  g_object_unref (G_OBJECT(builder));
1415 }
1416 
1417 static void
1418 sx_since_last_run_dialog (GncSxInstanceModel *sx_instances, int book_opened)
1419 {
1420  if (qof_book_is_readonly (gnc_get_current_book ()))
1421  return;
1422 
1423  GncSxSummary summary;
1424 
1425  gnc_sx_instance_model_summarize (sx_instances, &summary);
1426 
1427  if (book_opened)
1428  gnc_sx_summary_print (&summary);
1429 
1430  GList *auto_created_txns = NULL;
1431  GList *creation_errors = NULL;
1432 
1433  gnc_sx_instance_model_effect_change (sx_instances, TRUE, &auto_created_txns, &creation_errors);
1434 
1435  if (auto_created_txns)
1436  gnc_gui_refresh_all ();
1437 
1438  if (summary.need_dialog)
1439  since_last_run_dialog (gnc_ui_get_main_window (NULL), sx_instances, auto_created_txns);
1440  else
1441  {
1442  if (summary.num_auto_create_no_notify_instances == 0)
1443  {
1444  if (!book_opened)
1445  {
1446  const char *nothing_to_do_msg = _( "There are no Scheduled Transactions to be entered at this time." );
1447 
1448  gnc_info_dialog (gnc_ui_get_main_window (NULL), "%s", nothing_to_do_msg);
1449  }
1450  }
1451  else if (!book_opened || gnc_prefs_get_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SHOW_AT_FOPEN))
1452  {
1453  gnc_info_dialog (gnc_ui_get_main_window (NULL), ngettext
1454  /* Translators: %d is the number of transactions. This is a ngettext(3) message. */
1455  ("There are no Scheduled Transactions to be entered at this time. "
1456  "(%d transaction automatically created)",
1457  "There are no Scheduled Transactions to be entered at this time. "
1458  "(%d transactions automatically created)",
1461  }
1462  g_list_free (auto_created_txns);
1463  }
1464 
1465  g_object_unref (G_OBJECT(sx_instances));
1466 
1467  if (creation_errors)
1468  gnc_ui_sx_creation_error_dialog (&creation_errors);
1469 }
1470 
1471 void
1472 gnc_ui_sx_since_last_run_dialog (GncSxInstanceModel *sx_instances)
1473 {
1474  sx_since_last_run_dialog (sx_instances, FALSE);
1475 }
1476 
1477 void
1478 gnc_sx_sxsincelast_book_opened (void)
1479 {
1480  if (!gnc_prefs_get_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_RUN_AT_FOPEN))
1481  return;
1482 
1483  sx_since_last_run_dialog (gnc_sx_get_current_instances (), TRUE);
1484 
1485 }
1486 
1487 static void
1488 _show_created_transactions (GncSxSinceLastRunDialog *app_dialog, GList *created_txn_guids)
1489 {
1490  GNCLedgerDisplay *ledger;
1491  GncPluginPage *page;
1492  Query *book_query, *guid_query, *query;
1493  GList *guid_iter;
1494 
1495  book_query = qof_query_create_for (GNC_ID_SPLIT);
1496  guid_query = qof_query_create_for (GNC_ID_SPLIT);
1497  qof_query_set_book (book_query, gnc_get_current_book ());
1498  for (guid_iter = created_txn_guids; guid_iter != NULL; guid_iter = guid_iter->next)
1499  {
1500  xaccQueryAddGUIDMatch (guid_query, (GncGUID*)guid_iter->data, GNC_ID_TRANS, QOF_QUERY_OR);
1501  }
1502  query = qof_query_merge (book_query, guid_query, QOF_QUERY_AND);
1503  // inspired by dialog-find-transactions:do_find_cb:
1504  ledger = gnc_ledger_display_query (query, SEARCH_LEDGER, REG_STYLE_JOURNAL);
1505  gnc_ledger_display_refresh (ledger);
1506  page = gnc_plugin_page_register_new_ledger (ledger);
1507  g_object_set (G_OBJECT(page), "page-name", _("Created Transactions"), NULL);
1508  gnc_main_window_open_page (NULL, page);
1509 
1510  qof_query_destroy (query);
1511  qof_query_destroy (book_query);
1512  qof_query_destroy (guid_query);
1513 }
1514 
1515 static void
1516 close_handler (gpointer user_data)
1517 {
1518  GncSxSinceLastRunDialog *app_dialog = user_data;
1519  GtkSortType order;
1520  gint column;
1521 
1522  if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE(
1523  gtk_tree_view_get_model (app_dialog->instance_view)),
1524  &column, &order))
1525  {
1526  gboolean sort_ascending = TRUE;
1527  if (order == GTK_SORT_DESCENDING)
1528  sort_ascending = FALSE;
1529 
1530  gnc_prefs_set_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_ASC, sort_ascending);
1531  gnc_prefs_set_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_COL, column);
1532  gnc_prefs_set_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_DEPTH,
1533  app_dialog->sort_selection_depth);
1534  }
1535 
1536  gnc_save_window_size (GNC_PREFS_GROUP_STARTUP, GTK_WINDOW(app_dialog->dialog));
1537  gtk_widget_destroy (app_dialog->dialog);
1538  g_free (app_dialog);
1539 }
1540 
1541 static void
1542 dialog_destroy_cb (GtkWidget *object, GncSxSinceLastRunDialog *app_dialog)
1543 {
1544  gnc_unregister_gui_component (app_dialog->component_id);
1545 
1546  g_object_unref (G_OBJECT(app_dialog->editing_model));
1547  app_dialog->editing_model = NULL;
1548 }
1549 
1550 static void
1551 dialog_response_cb (GtkDialog *dialog, gint response_id, GncSxSinceLastRunDialog *app_dialog)
1552 {
1553  GList* creation_errors = NULL;
1554  switch (response_id)
1555  {
1556  case GTK_RESPONSE_HELP:
1557  gnc_gnome_help (GTK_WINDOW(dialog), DF_MANUAL, DL_SX_SLR);
1558  break;
1559 
1560  case GTK_RESPONSE_OK:
1561  // @@fixme validate current state(GError *errs);
1562  // - [ ] instance state constraints
1563  // - [x] required variable binding
1564  // - [?] ability to create transactions
1565  {
1566  GList *unbound_variables;
1567  gint unbound_len;
1568  unbound_variables = gnc_sx_instance_model_check_variables (app_dialog->editing_model->instances);
1569  unbound_len = g_list_length (unbound_variables);
1570  PINFO("%d variables unbound", unbound_len);
1571  if (unbound_len > 0)
1572  {
1573  // focus first variable
1574  GncSxVariableNeeded *first_unbound;
1575  GtkTreePath *variable_path;
1576  GtkTreeViewColumn *variable_col;
1577  gint variable_view_column = 2;
1578  gboolean start_editing = TRUE;
1579 
1580  first_unbound = (GncSxVariableNeeded*)unbound_variables->data;
1581 
1582  variable_path = _get_path_for_variable (app_dialog, first_unbound->instance, first_unbound->variable);
1583  variable_col = gtk_tree_view_get_column (app_dialog->instance_view, variable_view_column);
1584 
1585  gtk_tree_view_set_cursor (app_dialog->instance_view, variable_path, variable_col, start_editing);
1586 
1587  gtk_tree_view_scroll_to_cell (app_dialog->instance_view, variable_path, variable_col,
1588  TRUE, 0.5, 0.5);
1589 
1590  gtk_tree_path_free (variable_path);
1591  g_list_foreach (unbound_variables, (GFunc)g_free, NULL);
1592  g_list_free (unbound_variables);
1593  return;
1594  }
1595  }
1596  gnc_suspend_gui_refresh ();
1597  gnc_sx_slr_model_effect_change (app_dialog->editing_model, FALSE, &app_dialog->created_txns, &creation_errors);
1598  gnc_resume_gui_refresh ();
1599  gnc_gui_refresh_all (); // force a refresh of all registers
1600  if (creation_errors)
1601  gnc_ui_sx_creation_error_dialog (&creation_errors);
1602 
1603  if (gtk_toggle_button_get_active (app_dialog->review_created_txns_toggle)
1604  && g_list_length (app_dialog->created_txns) > 0)
1605  {
1606  _show_created_transactions (app_dialog, app_dialog->created_txns);
1607  }
1608 
1609  /* FALL THROUGH */
1610  case GTK_RESPONSE_CANCEL:
1611  case GTK_RESPONSE_DELETE_EVENT:
1612  g_list_free (app_dialog->created_txns);
1613  app_dialog->created_txns = NULL;
1614  gnc_close_gui_component (app_dialog->component_id);
1615  break;
1616  default:
1617  PWARN("unknown response id [%d]", response_id);
1618  break;
1619  }
1620 }
1621 
1626 void
1627 gnc_sx_slr_model_effect_change (GncSxSlrTreeModelAdapter *model,
1628  gboolean auto_create_only,
1629  GList **created_transaction_guids,
1630  GList **creation_errors)
1631 {
1632  if (qof_book_is_readonly (gnc_get_current_book ()))
1633  {
1634  /* Is the book read-only? Then don't change anything here. */
1635  return;
1636  }
1637 
1638  g_signal_handler_block (model->instances, model->updated_cb_id);
1639  gnc_sx_instance_model_effect_change (model->instances, auto_create_only, created_transaction_guids, creation_errors);
1640  g_signal_handler_unblock (model->instances, model->updated_cb_id);
1641 }
Public declarations for GncLedgerDisplay class.
void gnc_ledger_display_refresh(GNCLedgerDisplay *ld)
redisplay/redraw only the indicated window.
gboolean xaccParseAmount(const char *in_str, gboolean monetary, gnc_numeric *result, char **endstr)
Parses in_str to obtain a numeric result.
The instance data structure for a content plugin.
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
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.
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
utility functions for the GnuCash UI
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gint num_auto_create_no_notify_instances
The number of automatically-created instances that do no request notification.
size_t qof_print_gdate(char *buf, size_t bufflen, const GDate *gd)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:598
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gboolean gnc_prefs_set_int(const gchar *group, const gchar *pref_name, gint value)
Store an integer value into the preferences backend.
Definition: gnc-prefs.cpp:288
void gnc_sx_instance_model_summarize(GncSxInstanceModel *model, GncSxSummary *summary)
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_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_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Display a data plugin page in a window.
gint gnc_prefs_get_int(const gchar *group, const gchar *pref_name)
Get an integer value from the preferences backend.
Functions for adding content to a window.
GncPluginPage * gnc_plugin_page_register_new_ledger(GNCLedgerDisplay *ledger)
Create a new "register" plugin page, given a pointer to an already created ledger.
void gnc_sx_summary_print(const GncSxSummary *summary)
Debug output to trace file.
G_DEFINE_TYPE_WITH_CODE(GncMainWindow, gnc_main_window, GTK_TYPE_APPLICATION_WINDOW, G_IMPLEMENT_INTERFACE(GNC_TYPE_WINDOW, gnc_window_main_window_init)) static guint main_window_signals[LAST_SIGNAL]
A holding place for all the signals generated by the main window code.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
gboolean qof_log_check(QofLogModule domain, QofLogLevel level)
Check to see if the given log_module is configured to log at the given log_level. ...
Definition: qoflog.cpp:330
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
Functions providing a register page for the GnuCash UI.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome&#39;s yelp for linux, and open to a given link within a gi...
gboolean gnc_prefs_set_bool(const gchar *group, const gchar *pref_name, gboolean value)
Store a boolean value into the preferences backend.
Definition: gnc-prefs.cpp:277
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)
Create a gnc_numeric object that signals the error condition noted by error_code, rather than a numbe...
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
Argument is not a valid number.
Definition: gnc-numeric.h:224
time64 gdate_to_time64(GDate d)
Turns a GDate into a time64, returning the first second of the day.
Definition: gnc-date.cpp:1323
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Combine two queries together using the Boolean set (logical) operator &#39;op&#39;.
Definition: qofquery.cpp:1129
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
Definition: gnc-date.h:108
GDate date
the instance date.
GList * gnc_sx_instance_get_variables(GncSxInstance *inst)
GLib helper routines.
Generic api to store and retrieve preferences.
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) ...
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition: qofbook.cpp:497
gnc_numeric value
only numeric values are supported.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
GncSxInstanceState state
the current state of the instance (during editing)
GncSxInstanceModel * gnc_sx_get_current_instances(void)
Shorthand for get_instances(now, FALSE);.
GNCLedgerDisplay * gnc_ledger_display_query(Query *query, SplitRegisterType type, SplitRegisterStyle style)
display a general ledger for an arbitrary query
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
GList * instance_list
GList<GncSxInstance*>
No error.
Definition: gnc-numeric.h:223
gboolean need_dialog
If the dialog needs to be displayed.
The type used to store guids in C.
Definition: guid.h:75
A Query.
Definition: qofquery.cpp:74
GList * gnc_sx_instance_model_check_variables(GncSxInstanceModel *model)