GnuCash  5.6-150-g038405b370+
gnc-plugin-page-sx-list.cpp
1 /********************************************************************\
2  * gnc-plugin-page-sx-list.cpp : scheduled transaction plugin *
3  * *
4  * Copyright (C) 2006 Joshua Sled <jsled@asynchronous.org> *
5  * Copyright (C) 2011 Robert Fewell *
6  * *
7  * This program is free software; you can redistribute it and/or *
8  * modify it under the terms of version 2 and/or version 3 of the *
9  * GNU General Public License as published by the Free Software *
10  * Foundation. *
11  * *
12  * As a special exception, permission is granted to link the binary *
13  * module resultant from this code with the OpenSSL project's *
14  * "OpenSSL" library (or modified versions of it that use the same *
15  * license as the "OpenSSL" library), and distribute the linked *
16  * executable. You must obey the GNU General Public License in all *
17  * respects for all of the code used other than "OpenSSL". If you *
18  * modify this file, you may extend this exception to your version *
19  * of the file, but you are not obligated to do so. If you do not *
20  * wish to do so, delete this exception statement from your version *
21  * of this file. *
22  * *
23  * This program is distributed in the hope that it will be useful, *
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
26  * GNU General Public License for more details. *
27  * *
28  * You should have received a copy of the GNU General Public License*
29  * along with this program; if not, contact: *
30  * *
31  * Free Software Foundation Voice: +1-617-542-5942 *
32  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
33  * Boston, MA 02110-1301, USA gnu@gnu.org *
34 \********************************************************************/
35 
44 #include <config.h>
45 
46 #include <gtk/gtk.h>
47 #include <glib.h>
48 #include <glib/gi18n.h>
49 
50 #include <gnc-gobject-utils.h>
51 #include "SX-book.h"
52 #include "Split.h"
53 #include "Transaction.h"
54 #include "dialog-sx-editor.h"
55 #include "dialog-utils.h"
56 #include "dialog-sx-since-last-run.h"
57 #include "gnc-commodity.h"
58 #include "gnc-component-manager.h"
59 #include "gnc-date.h"
60 #include "gnc-dense-cal.h"
61 #include "gnc-engine.h"
62 #include "gnc-event.h"
63 #include "gnc-glib-utils.h"
64 #include "gnc-icons.h"
65 #include "gnc-main-window.h"
66 #include "gnc-plugin.h"
67 #include "gnc-plugin-page-sx-list.h"
68 #include "gnc-prefs.h"
69 #include "gnc-session.h"
70 #include "gnc-sx-instance-dense-cal-adapter.h"
71 #include "gnc-sx-instance-model.h"
72 #include "gnc-sx-list-tree-model-adapter.h"
73 #include "gnc-tree-view-sx-list.h"
74 #include "gnc-ui-util.h"
75 #include "gnc-ui.h"
76 #include "gnc-window.h"
77 
78 #undef G_LOG_DOMAIN
79 #define G_LOG_DOMAIN "gnc.gui.plugin-page.sx-list"
80 
81 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI_SX;
82 
83 #define PLUGIN_PAGE_SX_LIST_CM_CLASS "plugin-page-sx-list"
84 #define STATE_SECTION "SX Transaction List"
85 #define GNC_PREF_DIVIDER_POS "divider-position"
86 #define GNC_PREF_NUM_OF_MONTHS "number-of-months"
87 
89 {
90  gboolean disposed;
91 
92  GtkWidget* widget;
93  gint gnc_component_id;
94 
95  GncSxInstanceDenseCalAdapter *dense_cal_model;
96  GncDenseCal* gdcal;
97 
98  GncSxInstanceModel* instances;
99  GtkTreeView* tree_view;
100  GList *selected_list;
101 
103 
104 G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageSxList, gnc_plugin_page_sx_list, GNC_TYPE_PLUGIN_PAGE)
105 
106 #define GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(o) \
107  ((GncPluginPageSxListPrivate*)gnc_plugin_page_sx_list_get_instance_private ((GncPluginPageSxList*)o))
108 
109 /************************************************************
110  * Prototypes *
111  ************************************************************/
112 /* Plugin Actions */
113 static void gnc_plugin_page_sx_list_dispose (GObject *object);
114 static void gnc_plugin_page_sx_list_finalize (GObject *object);
115 
116 static GtkWidget *gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page);
117 static void gnc_plugin_page_sx_list_destroy_widget (GncPluginPage *plugin_page);
118 static void gnc_plugin_page_sx_list_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
119 static GncPluginPage *gnc_plugin_page_sx_list_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
120 
121 static gboolean gppsl_key_press_cb (GtkTreeView *tree_view, GdkEventKey *event, gpointer user_data);
122 static void gppsl_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
123  GtkTreeViewColumn *column, gpointer user_data);
124 
125 static void gnc_plugin_page_sx_list_cmd_new (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
126 static void gnc_plugin_page_sx_list_cmd_edit (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
127 static void gnc_plugin_page_sx_list_cmd_delete (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
128 static void gnc_plugin_page_sx_list_cmd_run (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
129 static void gnc_plugin_page_sx_list_cmd_refresh (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
130 static void gnc_plugin_page_sx_list_cmd_save_layout (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
131 static void gnc_plugin_page_sx_list_cmd_edit_tax_options (GSimpleAction *simple, GVariant *paramter, gpointer user_data);
132 
133 /* Command callbacks */
134 static GActionEntry gnc_plugin_page_sx_list_actions [] =
135 {
136  { "SxListAction", nullptr, nullptr, nullptr, nullptr },
137  { "SxListNewAction", gnc_plugin_page_sx_list_cmd_new, nullptr, nullptr, nullptr },
138  { "SxListEditAction", gnc_plugin_page_sx_list_cmd_edit, nullptr, nullptr, nullptr },
139  { "SxListDeleteAction", gnc_plugin_page_sx_list_cmd_delete, nullptr, nullptr, nullptr },
140  { "SxListRunAction", gnc_plugin_page_sx_list_cmd_run, nullptr, nullptr, nullptr },
141  { "ViewRefreshAction", gnc_plugin_page_sx_list_cmd_refresh, nullptr, nullptr, nullptr },
142  { "ViewSaveLayoutAction", gnc_plugin_page_sx_list_cmd_save_layout, nullptr, nullptr, nullptr },
143  { "EditTaxOptionsAction", gnc_plugin_page_sx_list_cmd_edit_tax_options, nullptr, nullptr, nullptr },
144 };
146 static guint gnc_plugin_page_sx_list_n_actions = G_N_ELEMENTS(gnc_plugin_page_sx_list_actions);
147 
149 static const gchar *gnc_plugin_load_ui_items [] =
150 {
151  "FilePlaceholder3",
152  "EditPlaceholder3",
153  "EditPlaceholder5",
154  "ViewPlaceholder4",
155  "SchedulePlaceholder0",
156  nullptr,
157 };
158 
159 
162 {
163  GncPluginPageSxList *plugin_page;
164  const GList *object = gnc_gobject_tracking_get_list (GNC_PLUGIN_PAGE_SX_LIST_NAME);
165  if (object && GNC_IS_PLUGIN_PAGE_SX_LIST(object->data))
166  plugin_page = GNC_PLUGIN_PAGE_SX_LIST(object->data);
167  else
168  {
169  plugin_page = GNC_PLUGIN_PAGE_SX_LIST(g_object_new (GNC_TYPE_PLUGIN_PAGE_SX_LIST, nullptr));
170  }
171  return GNC_PLUGIN_PAGE(plugin_page);
172 }
173 
174 
179 static gboolean
180 gnc_plugin_page_sx_list_focus_widget (GncPluginPage *sx_plugin_page)
181 {
182  if (GNC_IS_PLUGIN_PAGE_SX_LIST(sx_plugin_page))
183  {
184  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(sx_plugin_page);
185  GtkTreeView *tree_view = priv->tree_view;
186 
187  /* Disable the Transaction Menu */
188  GAction *action = gnc_main_window_find_action (GNC_MAIN_WINDOW(sx_plugin_page->window), "TransactionAction");
189  g_simple_action_set_enabled (G_SIMPLE_ACTION(action), false);
190  /* Enable the Schedule Menu */
191  action = gnc_main_window_find_action (GNC_MAIN_WINDOW(sx_plugin_page->window), "ScheduledAction");
192  g_simple_action_set_enabled (G_SIMPLE_ACTION(action), true);
193  /* Disable the FilePrintAction */
194  action = gnc_main_window_find_action (GNC_MAIN_WINDOW(sx_plugin_page->window), "FilePrintAction");
195  g_simple_action_set_enabled (G_SIMPLE_ACTION(action), false);
196 
197  gnc_main_window_update_menu_and_toolbar (GNC_MAIN_WINDOW(sx_plugin_page->window),
198  sx_plugin_page,
199  gnc_plugin_load_ui_items);
200 
201  if (GTK_IS_TREE_VIEW(tree_view))
202  {
203  if (!gtk_widget_is_focus (GTK_WIDGET(tree_view)))
204  gtk_widget_grab_focus (GTK_WIDGET(tree_view));
205  }
206  }
207  return false;
208 }
209 
210 static void
211 gnc_plugin_page_sx_list_class_init (GncPluginPageSxListClass *klass)
212 {
213  GObjectClass *object_class = G_OBJECT_CLASS(klass);
214  GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);
215 
216  object_class->dispose = gnc_plugin_page_sx_list_dispose;
217  object_class->finalize = gnc_plugin_page_sx_list_finalize;
218 
219  gnc_plugin_class->tab_icon = GNC_ICON_ACCOUNT;
220  gnc_plugin_class->plugin_name = GNC_PLUGIN_PAGE_SX_LIST_NAME;
221  gnc_plugin_class->create_widget = gnc_plugin_page_sx_list_create_widget;
222  gnc_plugin_class->destroy_widget = gnc_plugin_page_sx_list_destroy_widget;
223  gnc_plugin_class->save_page = gnc_plugin_page_sx_list_save_page;
224  gnc_plugin_class->recreate_page = gnc_plugin_page_sx_list_recreate_page;
225  gnc_plugin_class->focus_page_function = gnc_plugin_page_sx_list_focus_widget;
226 }
227 
228 
229 static void
230 gnc_plugin_page_sx_list_init (GncPluginPageSxList *plugin_page)
231 {
232  GSimpleActionGroup *simple_action_group;
233  GncPluginPage *parent;
234 
235  /* Init parent declared variables */
236  parent = GNC_PLUGIN_PAGE(plugin_page);
237  g_object_set(G_OBJECT(plugin_page),
238  "page-name", _("Scheduled Transactions"),
239  "ui-description", "gnc-plugin-page-sx-list.ui",
240  nullptr);
241 
242  gnc_plugin_page_add_book (parent, gnc_get_current_book());
243  simple_action_group = gnc_plugin_page_create_action_group (parent, "GncPluginPageSxListActions");
244  g_action_map_add_action_entries (G_ACTION_MAP(simple_action_group),
245  gnc_plugin_page_sx_list_actions,
246  gnc_plugin_page_sx_list_n_actions,
247  plugin_page);
248 }
249 
250 
251 static void
252 gnc_plugin_page_sx_list_dispose (GObject *object)
253 {
254  GncPluginPageSxList *page;
256 
257  page = GNC_PLUGIN_PAGE_SX_LIST(object);
258  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(page));
259  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
260  g_return_if_fail (priv != nullptr);
261 
262  g_return_if_fail (!priv->disposed);
263  priv->disposed = true;
264 
265  g_object_unref (G_OBJECT(priv->dense_cal_model));
266  priv->dense_cal_model = nullptr;
267  g_object_unref (GTK_WIDGET(priv->gdcal));
268  priv->gdcal = nullptr;
269  g_object_unref (G_OBJECT(priv->instances));
270  priv->instances = nullptr;
271 
272  G_OBJECT_CLASS(gnc_plugin_page_sx_list_parent_class)->dispose (object);
273 }
274 
275 
276 static void
277 gnc_plugin_page_sx_list_finalize (GObject *object)
278 {
279  GncPluginPageSxList *page;
281 
282  page = GNC_PLUGIN_PAGE_SX_LIST(object);
283  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(page));
284  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
285  g_return_if_fail (priv != nullptr);
286 
287  G_OBJECT_CLASS(gnc_plugin_page_sx_list_parent_class)->finalize (object);
288 }
289 
290 
291 /* Virtual Functions */
292 static void
293 gnc_plugin_page_sx_list_refresh_cb (GHashTable *changes, gpointer user_data)
294 {
295  auto page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
297 
298  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(page));
299 
300  /* We're only looking for forced updates here. */
301  if (changes)
302  return;
303 
304  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
305  gtk_widget_queue_draw (priv->widget);
306 }
307 
308 
309 static void
310 gnc_plugin_page_sx_list_close_cb (gpointer user_data)
311 {
312  GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(user_data);
313  gnc_main_window_close_page (plugin_page);
314 }
315 
316 
317 static void
318 gppsl_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
319 {
320  GncPluginPage *page;
321  GAction *edit_action, *delete_action, *run_action;
322  gboolean selection_state = true;
323 
324  page = GNC_PLUGIN_PAGE(user_data);
325  edit_action = gnc_plugin_page_get_action (page, "SxListEditAction");
326  delete_action = gnc_plugin_page_get_action (page, "SxListDeleteAction");
327  run_action = gnc_plugin_page_get_action (page, "SxListRunAction");
328  selection_state = gtk_tree_selection_count_selected_rows (selection) == 0
329  ? false
330  : true;
331  g_simple_action_set_enabled (G_SIMPLE_ACTION(edit_action), selection_state);
332  g_simple_action_set_enabled (G_SIMPLE_ACTION(delete_action), selection_state);
333  g_simple_action_set_enabled (G_SIMPLE_ACTION(run_action), selection_state);
334 }
335 
336 
337 static void
338 gppsl_update_selected_list (GncPluginPageSxList *page, gboolean reset, SchedXaction *sx)
339 {
340  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
341 
342  if (reset && priv->selected_list)
343  {
344  g_list_free (priv->selected_list);
345  priv->selected_list = nullptr;
346  }
347  if (sx)
348  priv->selected_list = g_list_prepend (priv->selected_list, sx);
349 }
350 
351 
352 static void
353 gppsl_model_populated_cb (GtkTreeModel *tree_model, GncPluginPageSxList *page)
354 {
355  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
356  GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree_view));
357  gboolean found = false;
358 
359  if (priv->selected_list)
360  {
361  // walk the list to see if we can reselect the sx
362  for (GList *list = priv->selected_list; list != nullptr; list = list->next)
363  {
364  SchedXaction *sx = GNC_SCHEDXACTION(list->data);
365  GtkTreePath *path = gtk_tree_path_new_first ();
366 
367  // loop through the model trying to find selected sx's
368  while (gnc_tree_view_path_is_valid (GNC_TREE_VIEW(priv->tree_view), path))
369  {
370  SchedXaction *sx_tmp = gnc_tree_view_sx_list_get_sx_from_path (
371  GNC_TREE_VIEW_SX_LIST(priv->tree_view), path);
372  if (sx_tmp == sx)
373  {
374  found = true;
375  break;
376  }
377  gtk_tree_path_next (path);
378  }
379  if (found)
380  gtk_tree_selection_select_path (selection, path);
381 
382  gtk_tree_path_free (path);
383  }
384  }
385  // this could be on load or if sx is deleted
386  if (!found)
387  {
388  GtkTreePath *path = gtk_tree_path_new_first ();
389  gtk_tree_selection_select_path (selection, path);
390  gtk_tree_path_free (path);
391  }
392 }
393 
394 
395 static void
396 treeview_popup (GtkTreeView *treeview, GdkEvent *event, GncPluginPageSxList *page)
397 {
398  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
399  GtkWidget *menu, *menuitem;
400  gchar *full_action_name;
401  const gchar *group_name = gnc_plugin_page_get_simple_action_group_name (GNC_PLUGIN_PAGE(page));
402 
403  menu = gtk_menu_new();
404 
405  menuitem = gtk_menu_item_new_with_mnemonic (_("_New Schedule"));
406  full_action_name = g_strconcat (group_name, ".SxListNewAction", nullptr);
407  gtk_actionable_set_action_name (GTK_ACTIONABLE(menuitem), full_action_name);
408  g_free (full_action_name);
409  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
410 
411  menuitem = gtk_menu_item_new_with_mnemonic (_("_Edit Schedule"));
412  full_action_name = g_strconcat (group_name, ".SxListEditAction", nullptr);
413  gtk_actionable_set_action_name (GTK_ACTIONABLE(menuitem), full_action_name);
414  g_free (full_action_name);
415  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
416 
417  menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete Schedule"));
418  full_action_name = g_strconcat (group_name, ".SxListDeleteAction", nullptr);
419  gtk_actionable_set_action_name (GTK_ACTIONABLE(menuitem), full_action_name);
420  g_free (full_action_name);
421  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
422 
423  menuitem = gtk_menu_item_new_with_mnemonic (_("_Run Schedule"));
424  full_action_name = g_strconcat (group_name, ".SxListRunAction", nullptr);
425  gtk_actionable_set_action_name (GTK_ACTIONABLE(menuitem), full_action_name);
426  g_free (full_action_name);
427  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
428 
429  gtk_menu_attach_to_widget (GTK_MENU(menu), GTK_WIDGET(priv->tree_view), nullptr);
430  gtk_widget_show_all (menu);
431  gtk_menu_popup_at_pointer (GTK_MENU(menu), event);
432 }
433 
434 static gboolean
435 treeview_button_press (GtkTreeView *treeview, GdkEvent *event,
436  GncPluginPageSxList *page)
437 {
438  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
439  GtkTreeView *tree_view = GTK_TREE_VIEW(priv->tree_view);
440 
441  if (event->type == GDK_BUTTON_PRESS)
442  {
443  GdkEventButton *event_button = (GdkEventButton*)event;
444  if (event_button->button == GDK_BUTTON_SECONDARY)
445  {
446  GtkTreePath *path = nullptr;
447  if (gtk_tree_view_get_path_at_pos (priv->tree_view, event_button->x, event_button->y,
448  &path, nullptr, nullptr, nullptr))
449  {
450  GtkTreeSelection *selection = gtk_tree_view_get_selection (priv->tree_view);
451 
452  if (!gtk_tree_selection_path_is_selected (selection, path))
453  {
454  gtk_tree_selection_unselect_all (selection);
455  gtk_tree_selection_select_path (selection, path);
456  }
457  }
458  gtk_tree_path_free (path);
459 
460  treeview_popup (tree_view, event, page);
461  return true;
462  }
463  }
464  return false;
465 }
466 
467 static gboolean
468 treeview_popup_menu (GtkTreeView *treeview, GncPluginPageSxList *page)
469 {
470  treeview_popup (treeview, nullptr, page);
471  return true;
472 }
473 
474 static GtkWidget *
475 gnc_plugin_page_sx_list_create_widget (GncPluginPage *plugin_page)
476 {
477  GncPluginPageSxList *page;
479  GtkWidget *widget;
480  GtkWidget *vbox;
481  GtkWidget *label;
482  GtkWidget *swin;
483  GtkWindow *window;
484 
485  page = GNC_PLUGIN_PAGE_SX_LIST(plugin_page);
486  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
487  if (priv->widget != nullptr)
488  return priv->widget;
489 
490  window = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(page)));
491 
492  /* Create Vpaned widget for top level */
493  widget = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
494  priv->widget = widget;
495  gtk_widget_show (priv->widget);
496 
497  // Set the name for this widget so it can be easily manipulated with css
498  gtk_widget_set_name (GTK_WIDGET(priv->widget), "gnc-id-sx-page");
499 
500  /* Add vbox and label */
501  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
502  gtk_box_set_homogeneous (GTK_BOX(vbox), false);
503  gtk_paned_pack1 (GTK_PANED(widget), vbox, true, false);
504 
505  label = gtk_label_new (_("Transactions"));
506  gnc_widget_style_context_add_class (GTK_WIDGET(label), "gnc-class-strong");
507  gtk_widget_set_margin_start (GTK_WIDGET(label), 6);
508  gnc_label_set_alignment (label, 0.0, 0);
509  gtk_widget_show (label);
510  gtk_box_pack_start (GTK_BOX(vbox), label, false, false, 0);
511  gtk_widget_show (vbox);
512 
513  /* Create scrolled window for top area */
514  swin = gtk_scrolled_window_new (nullptr, nullptr);
515  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(swin),
516  GTK_POLICY_AUTOMATIC,
517  GTK_POLICY_AUTOMATIC);
518  gtk_box_pack_start (GTK_BOX(vbox), swin, true, true, 5);
519  gtk_widget_show (swin);
520 
521  /* Set the paned position from the preferences, default 160 */
522  gtk_paned_set_position (GTK_PANED(priv->widget),
523  gnc_prefs_get_int (GNC_PREFS_GROUP_SXED,
524  GNC_PREF_DIVIDER_POS));
525 
526  {
527  GDate end;
528  g_date_clear (&end, 1);
529  gnc_gdate_set_today (&end);
530  g_date_add_years (&end, 1);
531  priv->instances = GNC_SX_INSTANCE_MODEL(gnc_sx_get_instances (&end, true));
532  }
533 
534  {
535  GAction *edit_action, *delete_action, *run_action;
536  edit_action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "SxListEditAction");
537  delete_action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "SxListDeleteAction");
538  run_action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), "SxListRunAction");
539  g_simple_action_set_enabled (G_SIMPLE_ACTION(edit_action), false);
540  g_simple_action_set_enabled (G_SIMPLE_ACTION(delete_action), false);
541  g_simple_action_set_enabled (G_SIMPLE_ACTION(run_action), false);
542  }
543 
544  {
545  GtkTreeSelection *selection;
546  GtkTreePath *path = gtk_tree_path_new_first ();
547 
548  priv->tree_view = GTK_TREE_VIEW(gnc_tree_view_sx_list_new (priv->instances));
549  g_object_set (G_OBJECT(priv->tree_view),
550  "state-section", STATE_SECTION,
551  "show-column-menu", true,
552  nullptr);
553  gtk_container_add (GTK_CONTAINER(swin), GTK_WIDGET(priv->tree_view));
554 
555  selection = gtk_tree_view_get_selection (priv->tree_view);
556  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
557 
558  g_signal_connect (G_OBJECT(selection), "changed",
559  (GCallback)gppsl_selection_changed_cb, (gpointer)page);
560  g_signal_connect (G_OBJECT(priv->tree_view), "key-press-event",
561  (GCallback)gppsl_key_press_cb, (gpointer)page);
562  g_signal_connect (G_OBJECT(priv->tree_view), "row-activated",
563  (GCallback)gppsl_row_activated_cb, (gpointer)page);
564  g_signal_connect (G_OBJECT(gtk_tree_view_get_model (GTK_TREE_VIEW(priv->tree_view))),
565  "model-populated", (GCallback)gppsl_model_populated_cb, (gpointer)page);
566 
567  gtk_tree_selection_select_path (selection, path);
568  gtk_tree_path_free (path);
569  }
570 
571  g_signal_connect (G_OBJECT(priv->tree_view), "button-press-event",
572  G_CALLBACK(treeview_button_press), page);
573  g_signal_connect (G_OBJECT(priv->tree_view), "popup-menu",
574  G_CALLBACK(treeview_popup_menu), page);
575 
576  /* Add vbox and label */
577  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
578  gtk_box_set_homogeneous (GTK_BOX(vbox), false);
579  gtk_paned_pack2 (GTK_PANED(widget), vbox, true, false);
580 
581  label = gtk_label_new (_("Upcoming Transactions"));
582  gnc_widget_style_context_add_class (GTK_WIDGET(label), "gnc-class-strong");
583  gtk_widget_set_margin_start (GTK_WIDGET(label), 6);
584  gnc_label_set_alignment (label, 0.0, 0);
585  gtk_widget_show (label);
586 
587  gtk_box_pack_start (GTK_BOX(vbox), label, false, false, 0);
588  gtk_widget_show (vbox);
589 
590  /* Create scrolled window for bottom area */
591  swin = gtk_scrolled_window_new (nullptr, nullptr);
592  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(swin),
593  GTK_POLICY_AUTOMATIC,
594  GTK_POLICY_AUTOMATIC);
595  gtk_box_pack_start (GTK_BOX(vbox), swin, true, true, 5);
596  gtk_widget_show (swin);
597 
598  {
599  priv->dense_cal_model = gnc_sx_instance_dense_cal_adapter_new (GNC_SX_INSTANCE_MODEL(priv->instances));
600  priv->gdcal = GNC_DENSE_CAL(gnc_dense_cal_new_with_model (window, GNC_DENSE_CAL_MODEL(priv->dense_cal_model)));
601  g_object_ref_sink (priv->gdcal);
602 
603  /* Set number of months from preference, default 12 */
604  auto num_months = gnc_prefs_get_int (GNC_PREFS_GROUP_SXED, GNC_PREF_NUM_OF_MONTHS);
605  if (num_months == 0)
606  {
607  PWARN ("Got invalid value '0' for number of months to display. This suggests a gsettings configuration issue. Continuing with a default value of 12 instead.");
608  num_months = 12;
609  }
610  gnc_dense_cal_set_num_months (priv->gdcal, num_months);
611 
612  gtk_container_add (GTK_CONTAINER(swin), GTK_WIDGET(priv->gdcal));
613  }
614 
615  priv->gnc_component_id = gnc_register_gui_component ("plugin-page-sx-list",
616  gnc_plugin_page_sx_list_refresh_cb,
617  gnc_plugin_page_sx_list_close_cb,
618  page);
619  gnc_gui_component_set_session (priv->gnc_component_id,
620  gnc_get_current_session ());
621 
622  g_signal_connect (G_OBJECT(plugin_page), "inserted",
623  G_CALLBACK(gnc_plugin_page_inserted_cb),
624  nullptr);
625 
626  return priv->widget;
627 }
628 
629 
630 static void
631 gnc_plugin_page_sx_list_destroy_widget (GncPluginPage *plugin_page)
632 {
633  GncPluginPageSxList *page;
635 
636  page = GNC_PLUGIN_PAGE_SX_LIST(plugin_page);
637  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
638 
639  // Remove the page_changed signal callback
640  gnc_plugin_page_disconnect_page_changed (GNC_PLUGIN_PAGE(plugin_page));
641 
642  // Remove the page focus idle function if present
643  g_idle_remove_by_data (plugin_page);
644 
645  if (priv->widget)
646  {
647  g_object_unref (G_OBJECT(priv->widget));
648  priv->widget = nullptr;
649  }
650 
651  if (priv->selected_list)
652  g_list_free (priv->selected_list);
653 
654  if (priv->gnc_component_id)
655  {
656  gnc_unregister_gui_component (priv->gnc_component_id);
657  priv->gnc_component_id = 0;
658  }
659 }
660 
661 
669 static void
670 gnc_plugin_page_sx_list_save_page (GncPluginPage *plugin_page,
671  GKeyFile *key_file,
672  const gchar *group_name)
673 {
674  GncPluginPageSxList *page;
676 
677  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(plugin_page));
678  g_return_if_fail (key_file != nullptr);
679  g_return_if_fail (group_name != nullptr);
680 
681  page = GNC_PLUGIN_PAGE_SX_LIST(plugin_page);
682  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
683 
684  g_key_file_set_integer (key_file, group_name, "dense_cal_num_months",
685  gnc_dense_cal_get_num_months (priv->gdcal));
686 
687  g_key_file_set_integer (key_file, group_name, "paned_position",
688  gtk_paned_get_position (GTK_PANED(priv->widget)));
689 }
690 
691 
700 static GncPluginPage *
701 gnc_plugin_page_sx_list_recreate_page (GtkWidget *window,
702  GKeyFile *key_file,
703  const gchar *group_name)
704 {
705  GncPluginPageSxList *page;
707 
708  g_return_val_if_fail (key_file, nullptr);
709  g_return_val_if_fail (group_name, nullptr);
710 
711  /* Create the new page. */
712  page = GNC_PLUGIN_PAGE_SX_LIST(gnc_plugin_page_sx_list_new ());
713  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
714 
715  /* Install it now so we can them manipulate the created widget */
716  gnc_main_window_open_page (GNC_MAIN_WINDOW(window), GNC_PLUGIN_PAGE(page));
717 
718  {
719  GError *err = nullptr;
720  gint num_months = g_key_file_get_integer (key_file, group_name, "dense_cal_num_months", &err);
721  if (err == nullptr)
722  gnc_dense_cal_set_num_months (priv->gdcal, num_months);
723  else
724  g_error_free (err);
725  }
726 
727  {
728  GError *err = nullptr;
729  gint paned_position = g_key_file_get_integer (key_file, group_name,
730  "paned_position", &err);
731  if (err == nullptr)
732  gtk_paned_set_position (GTK_PANED(priv->widget), paned_position);
733  else
734  g_error_free (err);
735  }
736 
737  return GNC_PLUGIN_PAGE(page);
738 }
739 
740 
741 static void
742 gnc_plugin_page_sx_list_cmd_new (GSimpleAction *simple,
743  GVariant *parameter,
744  gpointer user_data)
745 {
746  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
747  GtkWindow *window = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));
748  SchedXaction *new_sx;
749  gboolean new_sx_flag = true;
750 
751  new_sx = xaccSchedXactionMalloc (gnc_get_current_book());
752  {
753  GDate now;
754  Recurrence *r = g_new0 (Recurrence, 1);
755  GList *schedule;
756 
757  g_date_clear (&now, 1);
758  gnc_gdate_set_today (&now);
759  recurrenceSet (r, 1, PERIOD_MONTH, &now, WEEKEND_ADJ_NONE);
760  schedule = gnc_sx_get_schedule (new_sx);
761  schedule = g_list_append (schedule, r);
762  gnc_sx_set_schedule (new_sx, schedule);
763  }
764  gnc_ui_scheduled_xaction_editor_dialog_create (window, new_sx, new_sx_flag);
765  gppsl_update_selected_list (plugin_page, true, new_sx);
766 }
767 
768 static void
769 gnc_plugin_page_sx_list_cmd_refresh (GSimpleAction *simple,
770  GVariant *parameter,
771  gpointer user_data)
772 {
773  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
775 
776  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(plugin_page));
777 
778  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(plugin_page);
779  gtk_widget_queue_draw (priv->widget);
780 }
781 
782 static void
783 gnc_plugin_page_sx_list_cmd_save_layout (GSimpleAction *simple,
784  GVariant *parameter,
785  gpointer user_data)
786 {
787  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
789  gint paned_position;
790 
791  g_return_if_fail (GNC_IS_PLUGIN_PAGE_SX_LIST(plugin_page));
792 
793  priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(plugin_page);
794 
795  paned_position = gtk_paned_get_position (GTK_PANED(priv->widget));
796 
797  gnc_prefs_set_int (GNC_PREFS_GROUP_SXED, GNC_PREF_DIVIDER_POS,
798  paned_position);
799 
800  gnc_prefs_set_int (GNC_PREFS_GROUP_SXED, GNC_PREF_NUM_OF_MONTHS,
801  gnc_dense_cal_get_num_months (priv->gdcal));
802 }
803 
804 static void
805 _edit_sx(gpointer data, gpointer user_data)
806 {
807  gnc_ui_scheduled_xaction_editor_dialog_create (GTK_WINDOW(user_data),
808  GNC_SCHEDXACTION(data), false);
809 }
810 
811 static SchedXaction*
812 _argument_reorder_fn (GtkTreePath* list_path_data, GncTreeViewSxList* user_tree_view)
813 {
814  return gnc_tree_view_sx_list_get_sx_from_path (user_tree_view, list_path_data);
815 }
816 
817 
818 static void
819 gnc_plugin_page_sx_list_cmd_edit (GSimpleAction *simple,
820  GVariant *parameter,
821  gpointer user_data)
822 {
823  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
824  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(plugin_page);
825  GtkWindow *window = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));
826  GtkTreeSelection *selection;
827  GList *selected_paths, *to_edit;
828  GtkTreeModel *model;
829 
830  selection = gtk_tree_view_get_selection (priv->tree_view);
831  selected_paths = gtk_tree_selection_get_selected_rows (selection, &model);
832  if (!gnc_list_length_cmp (selected_paths, 0))
833  {
834  g_warning ("no selection edit.");
835  return;
836  }
837 
838  to_edit = gnc_g_list_map (selected_paths,
839  (GncGMapFunc)_argument_reorder_fn,
840  priv->tree_view);
841 
842  gppsl_update_selected_list (plugin_page, true, nullptr);
843  for (GList *list = to_edit; list != nullptr; list = list->next)
844  {
845  DEBUG ("to-edit [%s]\n", xaccSchedXactionGetName (GNC_SCHEDXACTION(list->data)));
846  gppsl_update_selected_list (plugin_page, false, GNC_SCHEDXACTION(list->data));
847  }
848 
849  g_list_foreach (to_edit, (GFunc)_edit_sx, window);
850  g_list_free (to_edit);
851  g_list_foreach (selected_paths, (GFunc)gtk_tree_path_free, nullptr);
852  g_list_free (selected_paths);
853 }
854 
855 
856 static void
857 gnc_plugin_page_sx_list_cmd_edit_tax_options (GSimpleAction *simple,
858  GVariant *parameter,
859  gpointer user_data)
860 {
861  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
862  GtkWidget *window = GTK_WIDGET(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));
863 
864  ENTER ("(action %p, page %p)", simple, plugin_page);
865  gnc_tax_info_dialog (window, nullptr);
866  LEAVE (" ");
867 }
868 
869 static gboolean
870 gppsl_is_enable_column_visible (GtkTreeView *tree_view)
871 {
872  gboolean retval = FALSE;
873  GList *columns = gtk_tree_view_get_columns (tree_view);
874 
875  for (GList *node = columns; node; node = node->next)
876  {
877  GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(node->data);
878  gint id = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(col), MODEL_COLUMN));
879 
880  if (id == SXLTMA_COL_ENABLED)
881  {
882  retval = gtk_tree_view_column_get_visible(col);
883  break;
884  }
885  }
886  g_list_free (columns);
887  return retval;
888 }
889 
890 static gboolean
891 gppsl_set_toggle (GtkTreeView *tree_view)
892 {
893  GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
894  GtkTreeModel *model;
895  GList *sel_list = gtk_tree_selection_get_selected_rows (selection, &model);
896  gint num_selected = gtk_tree_selection_count_selected_rows (selection);
897  gint num_toggled = 0;
898 
899  for (GList *node = sel_list; node; node = node->next)
900  {
901  GtkTreePath *path = (GtkTreePath *)node->data;
902  GtkTreeIter iter;
903 
904  if (gtk_tree_model_get_iter (model, &iter, path))
905  {
906  gboolean toggled;
907 
908  gtk_tree_model_get (model, &iter, SXLTMA_COL_ENABLED, &toggled, -1);
909 
910  if (toggled)
911  {
912  num_toggled++;
913  }
914  }
915  gtk_tree_path_free (path);
916  }
917  g_list_free (sel_list);
918 
919  return num_toggled != num_selected;
920 }
921 
922 static void
923 gppsl_set_list (GncPluginPageSxList *sx_plugin_page, gboolean enable)
924 {
925  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(sx_plugin_page);
926  GtkTreeView *tree_view = priv->tree_view;
927  GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
928  GtkTreeModel *model;
929  GList *sel_list = gtk_tree_selection_get_selected_rows (selection, &model);
930  GList *sx_list = nullptr;
931 
932  gppsl_update_selected_list (sx_plugin_page, true, nullptr);
933 
934  for (GList *node = sel_list; node; node = node->next)
935  {
936  GtkTreePath *path = (GtkTreePath *)node->data;
937  GncTreeViewSxList *view = GNC_TREE_VIEW_SX_LIST(tree_view);
938  SchedXaction *sx = gnc_tree_view_sx_list_get_sx_from_path (view, path);
939 
940  if (sx)
941  {
942  GtkTreeIter iter;
943 
944  gppsl_update_selected_list (sx_plugin_page, false, sx);
945 
946  if (gtk_tree_model_get_iter (model, &iter, path))
947  {
948  gboolean toggled;
949 
950  gtk_tree_model_get (model, &iter, SXLTMA_COL_ENABLED, &toggled, -1);
951  if (enable != toggled)
952  {
953  sx_list = g_list_prepend (sx_list, sx);
954  }
955  }
956  }
957 
958  gtk_tree_path_free (path);
959  }
960  g_list_free (sel_list);
961 
962  for (GList *node = sx_list; node; node = node->next)
963  {
964  if (node == sx_list)
965  {
966  if (node->next)
967  {
969  }
970  }
971  else if (!node->next)
972  {
973  qof_event_resume ();
974  }
975 
976  SchedXaction *sx = GNC_SCHEDXACTION(node->data);
977 
978  xaccSchedXactionSetEnabled (sx, enable);
979  }
980  g_list_free (sx_list);
981 }
982 
983 static gboolean
984 gppsl_key_press_cb (GtkTreeView *tree_view, GdkEventKey *event, gpointer user_data)
985 {
986  if (event->keyval != GDK_KEY_space || !gppsl_is_enable_column_visible (tree_view))
987  {
988  return FALSE;
989  }
990 
991  g_signal_stop_emission_by_name (G_OBJECT(tree_view), "key-press-event");
992 
993  gboolean enable = gppsl_set_toggle (tree_view);
994 
995  gppsl_set_list (GNC_PLUGIN_PAGE_SX_LIST(user_data), enable);
996 
997  return TRUE;
998 }
999 
1000 
1001 static void
1002 gppsl_row_activated_cb (GtkTreeView *tree_view,
1003  GtkTreePath *path,
1004  GtkTreeViewColumn *column,
1005  gpointer user_data)
1006 {
1007  GncPluginPageSxList *page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
1008  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(page);
1009  GtkWindow *window = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(page)));
1010 
1011  SchedXaction *sx = gnc_tree_view_sx_list_get_sx_from_path (
1012  GNC_TREE_VIEW_SX_LIST(priv->tree_view), path);
1013  gnc_ui_scheduled_xaction_editor_dialog_create (window, sx, false);
1014  gppsl_update_selected_list (page, true, sx);
1015 }
1016 
1017 
1018 static void
1019 _destroy_sx(gpointer data, gpointer user_data)
1020 {
1021  SchedXactions *sxes;
1022  auto sx = GNC_SCHEDXACTION(data);
1023  QofBook *book;
1024  book = gnc_get_current_book ();
1025  sxes = gnc_book_get_schedxactions (book);
1026 
1027  DEBUG("deleting sx [%s]", xaccSchedXactionGetName (sx));
1028 
1029  gnc_sxes_del_sx (sxes, sx);
1030  gnc_sx_begin_edit (sx);
1032 }
1033 
1034 
1035 static void
1036 _destroy_sx_names (gpointer data, gpointer user_data)
1037 {
1038  auto sx = GNC_SCHEDXACTION(data);
1039  GList **to_delete_names = (GList**)user_data;
1040  *to_delete_names = g_list_append (*to_delete_names, xaccSchedXactionGetName (sx));
1041 }
1042 
1043 
1044 static void
1045 gnc_plugin_page_sx_list_cmd_delete (GSimpleAction *simple,
1046  GVariant *parameter,
1047  gpointer user_data)
1048 {
1049  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
1050  GncPluginPageSxListPrivate *priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(plugin_page);
1051  GtkTreeSelection *selection = gtk_tree_view_get_selection (priv->tree_view);
1052  GList *selected_paths, *to_delete = nullptr, *to_delete_names = nullptr;
1053  GtkTreeModel *model;
1054  GtkWindow *window;
1055  gchar *message = nullptr;
1056  gint length;
1057  gchar *text_list_of_scheduled_transaction_names = nullptr;
1058 
1059  selected_paths = gtk_tree_selection_get_selected_rows (selection, &model);
1060  if (!gnc_list_length_cmp (selected_paths, 0))
1061  {
1062  g_warning ("no selection for delete.");
1063  return;
1064  }
1065 
1066  to_delete = gnc_g_list_map (selected_paths,
1067  (GncGMapFunc)_argument_reorder_fn,
1068  priv->tree_view);
1069 
1070  g_list_foreach (to_delete, (GFunc)_destroy_sx_names, &to_delete_names);
1071 
1072  window = GTK_WINDOW(gnc_plugin_page_get_window (GNC_PLUGIN_PAGE(plugin_page)));
1073 
1074  length = g_list_length (to_delete);
1075 
1076  text_list_of_scheduled_transaction_names = gnc_g_list_stringjoin (to_delete_names, "\n");
1077 
1078  /* Translators: This is a ngettext(3) message, question followed by list of scheduled transactions to be deleted */
1079  message = g_strdup_printf ("%s\n\n%s",
1080  ngettext ("Do you really want to delete this scheduled transaction?",
1081  "Do you really want to delete these scheduled transactions?",
1082  length),
1083  text_list_of_scheduled_transaction_names);
1084 
1085  g_free (text_list_of_scheduled_transaction_names);
1086  g_list_free (to_delete_names);
1087 
1088  if (gnc_verify_dialog (window, false, "%s", message))
1089  {
1090  gppsl_update_selected_list (plugin_page, true, nullptr);
1091 
1092  g_list_foreach (to_delete, (GFunc)_destroy_sx, nullptr);
1093  }
1094 
1095  g_free (message);
1096  g_list_free (to_delete);
1097  g_list_foreach (selected_paths, (GFunc)gtk_tree_path_free, nullptr);
1098  g_list_free (selected_paths);
1099 }
1100 
1101 static void
1102 gnc_plugin_page_sx_list_cmd_run (GSimpleAction *simple,
1103  GVariant *parameter,
1104  gpointer user_data)
1105 {
1106  auto plugin_page = GNC_PLUGIN_PAGE_SX_LIST(user_data);
1107  auto priv = GNC_PLUGIN_PAGE_SX_LIST_GET_PRIVATE(plugin_page);
1108  auto selection = gtk_tree_view_get_selection (priv->tree_view);
1109  GtkTreeModel *model;
1110  auto selected_paths = gtk_tree_selection_get_selected_rows (selection, &model);
1111 
1112  if (!selected_paths)
1113  {
1114  PWARN ("no selection for run.");
1115  return;
1116  }
1117 
1118  auto to_run = gnc_g_list_map (selected_paths, (GncGMapFunc)_argument_reorder_fn, priv->tree_view);
1119 
1120  gnc_ui_sx_since_last_run_dialog (gnc_sx_get_select_instances (to_run));
1121 
1122  g_list_free (to_run);
1123  g_list_foreach (selected_paths, (GFunc)gtk_tree_path_free, nullptr);
1124  g_list_free (selected_paths);
1125 }
1126 
GtkWidget * gnc_plugin_page_get_window(GncPluginPage *page)
Retrieve a pointer to the GncMainWindow (GtkWindow) containing this page.
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule)
GList * gnc_g_list_map(GList *list, GncGMapFunc fn, gpointer user_data)
const gchar * tab_icon
The relative name of the icon that should be shown on the tab for this page.
gboolean(* focus_page_function)(GncPluginPage *plugin_page)
This function performs specific actions to set the focus on a specific widget.
GList * gnc_sx_get_schedule(const SchedXaction *sx)
void gnc_main_window_update_menu_and_toolbar(GncMainWindow *window, GncPluginPage *page, const gchar **ui_updates)
Update the main window menu with the placeholders listed in ui_updates and load the page specific too...
The instance data structure for a content plugin.
const GList * gnc_gobject_tracking_get_list(const gchar *name)
Get a list of all known objects of a specified type.
Date and Time handling routines.
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
utility functions for the GnuCash UI
GncTreeView implementation for Scheduled Transaction List.
GncPluginPage *(* recreate_page)(GtkWidget *window, GKeyFile *file, const gchar *group)
Create a new page based on the information saved during a previous instantiation of gnucash...
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
Functions that are supported by all types of windows.
void gnc_gdate_set_today(GDate *gd)
Set a GDate to the current day.
Definition: gnc-date.cpp:1306
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
GtkWidget * window
The window that contains the display widget for this plugin.
API for Transactions and Splits (journal entries)
GSimpleActionGroup * gnc_plugin_page_create_action_group(GncPluginPage *page, const gchar *group_name)
Create the GSimpleActionGroup object associated with this page.
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
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.
void(* destroy_widget)(GncPluginPage *plugin_page)
Function called to destroy the display widget for a particular type of plugin.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
The class data structure for a content plugin.
Gobject helper routines.
GAction * gnc_main_window_find_action(GncMainWindow *window, const gchar *action_name)
Find the GAction in the main window.
void gnc_plugin_page_disconnect_page_changed(GncPluginPage *page)
Disconnect the page_changed_id signal callback.
Anchor Scheduled Transaction info in a book.
const gchar * plugin_name
The textual name of this plugin.
GtkWidget *(* create_widget)(GncPluginPage *plugin_page)
Function called to create the display widget for a particular type of plugin.
const gchar * gnc_plugin_page_get_simple_action_group_name(GncPluginPage *page)
Retrieve the simple action group name associated with this plugin page.
Additional event handling code.
All type declarations for the whole Gnucash engine.
void(* save_page)(GncPluginPage *page, GKeyFile *file, const gchar *group)
Save enough information about this page so that it can be recreated next time the user starts gnucash...
GLib helper routines.
Generic api to store and retrieve preferences.
GncSxInstanceModel * gnc_sx_get_select_instances(GList *sel_sxes)
Allocates a new SxInstanceModel and fills it with generated instances for the given scheduled transac...
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 ...
void qof_event_suspend(void)
Suspend all engine events.
Definition: qofevent.cpp:145
void qof_event_resume(void)
Resume engine event generation.
Definition: qofevent.cpp:156
void gnc_plugin_page_inserted_cb(GncPluginPage *page, gpointer user_data)
Set up the page_changed callback for when the current page is changed.
void gnc_main_window_close_page(GncPluginPage *page)
Remove a data plugin page from a window and display the previous page.
Functions for adding plugins to a GnuCash window.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
#define GNC_TYPE_PLUGIN_PAGE_SX_LIST
Functions providing a list of scheduled transactions as a plugin page.
GncPluginPage * gnc_plugin_page_sx_list_new(void)
void gnc_plugin_page_add_book(GncPluginPage *page, QofBook *book)
Add a book reference to the specified page.
SchedXaction * xaccSchedXactionMalloc(QofBook *book)
Creates and initializes a scheduled transaction.
gint gnc_list_length_cmp(const GList *list, size_t len)
Scans the GList elements the minimum number of iterations required to test it against a specified siz...
API for Transactions and Splits (journal entries)
GAction * gnc_plugin_page_get_action(GncPluginPage *page, const gchar *name)
Retrieve a GAction object associated with this page.
void xaccSchedXactionDestroy(SchedXaction *sx)
Cleans up and frees a SchedXaction and its associated data.
Commodity handling public routines.