GnuCash  5.6-150-g038405b370+
gnc-plugin-budget.c
1 /* Copyright (C) 2005 Chris Shoemaker <c.shoemaker@cox.net>
2  *
3  * gnc-plugin-budget.c --
4  * (based on gnc-plugin-account-tree.c)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, contact:
18  *
19  * Free Software Foundation Voice: +1-617-542-5942
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21  * Boston, MA 02110-1301, USA gnu@gnu.org
22  */
23 
24 #include <config.h>
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <string.h>
29 
30 #include "gnc-plugin-budget.h"
31 #include "gnc-plugin-page-budget.h"
32 #include "gnc-tree-model-budget.h"
33 
34 #include "qof.h"
35 #include "gnc-features.h"
36 #include "gnc-ui-util.h"
37 #include "gnc-ui.h"
38 #include "gnc-component-manager.h"
39 
40 #define PLUGIN_ACTIONS_NAME "gnc-plugin-budget-actions"
41 #define PLUGIN_UI_FILENAME "gnc-plugin-budget.ui"
42 
43 static QofLogModule log_module = GNC_MOD_GUI;
44 
45 static void gnc_plugin_budget_finalize (GObject *object);
46 
47 /* Command Callbacks */
48 static void gnc_plugin_budget_cmd_new_budget (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
49 static void gnc_plugin_budget_cmd_open_budget (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
50 static void gnc_plugin_budget_cmd_copy_budget (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
51 static void gnc_plugin_budget_cmd_delete_budget (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
52 
53 static GActionEntry gnc_plugin_actions [] =
54 {
55  { "ActionsBudgetAction", NULL, NULL, NULL, NULL },
56  { "NewBudgetAction", gnc_plugin_budget_cmd_new_budget, NULL, NULL, NULL },
57  { "OpenBudgetAction", gnc_plugin_budget_cmd_open_budget, NULL, NULL, NULL },
58  { "CopyBudgetAction", gnc_plugin_budget_cmd_copy_budget, NULL, NULL, NULL },
59  { "DeleteBudgetAction", gnc_plugin_budget_cmd_delete_budget, NULL, NULL, NULL },
60 
61 };
63 static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
64 
66 static const gchar *gnc_plugin_load_ui_items [] =
67 {
68  "ActionsPlaceholder3",
69  NULL,
70 };
71 
72 static const gchar *plugin_writeable_actions[] =
73 {
74  /* actions which must be disabled on a readonly book. */
75  "NewBudgetAction",
76  "CopyBudgetAction",
77  "DeleteBudgetAction",
78  NULL
79 };
80 
82 {
83  GncPlugin gnc_plugin;
84 };
85 
86 GncPlugin *
87 gnc_plugin_budget_new (void)
88 {
89  GncPluginBudget *plugin;
90  ENTER(" ");
91 
92  /* Reference the budget page plugin to ensure it exists in the gtk
93  * type system. */
94  GNC_TYPE_PLUGIN_PAGE_BUDGET;
95 
96  plugin = g_object_new (GNC_TYPE_PLUGIN_BUDGET, NULL);
97  LEAVE(" ");
98  return GNC_PLUGIN(plugin);
99 }
100 
101 static void
102 page_changed (GncMainWindow *window, GncPluginPage *page, gpointer user_data)
103 {
104  GSimpleActionGroup *simple_action_group =
106 
107  if (qof_book_is_readonly (gnc_get_current_book()))
108  gnc_plugin_set_actions_enabled (G_ACTION_MAP(simple_action_group), plugin_writeable_actions,
109  FALSE);
110 }
111 
112 static void
113 add_to_window (GncPlugin *plugin, GncMainWindow *mainwindow, GQuark type)
114 {
115  g_signal_connect (mainwindow, "page_changed", G_CALLBACK (page_changed), plugin);
116 }
117 
118 static void
119 remove_from_window (GncPlugin *plugin, GncMainWindow *window, GQuark type)
120 {
121  g_signal_handlers_disconnect_by_func (window, G_CALLBACK(page_changed), plugin);
122 }
123 
124 G_DEFINE_TYPE(GncPluginBudget, gnc_plugin_budget, GNC_TYPE_PLUGIN)
125 
126 static void
127 gnc_plugin_budget_class_init (GncPluginBudgetClass *klass)
128 {
129  GObjectClass *object_class = G_OBJECT_CLASS(klass);
130  GncPluginClass *plugin_class = GNC_PLUGIN_CLASS(klass);
131 
132  ENTER (" ");
133  object_class->finalize = gnc_plugin_budget_finalize;
134 
135  plugin_class->plugin_name = GNC_PLUGIN_BUDGET_NAME;
136  plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
137  plugin_class->actions = gnc_plugin_actions;
138  plugin_class->n_actions = gnc_plugin_n_actions;
139  plugin_class->ui_filename = PLUGIN_UI_FILENAME;
140  plugin_class->ui_updates = gnc_plugin_load_ui_items;
141  plugin_class->add_to_window = add_to_window;
142  plugin_class->remove_from_window = remove_from_window;
143 
144  LEAVE (" ");
145 }
146 
147 static void
148 gnc_plugin_budget_init (GncPluginBudget *plugin)
149 {
150 }
151 
152 static void
153 gnc_plugin_budget_finalize (GObject *object)
154 {
155  g_return_if_fail (GNC_IS_PLUGIN_BUDGET(object));
156 
157  ENTER(" ");
158  G_OBJECT_CLASS (gnc_plugin_budget_parent_class)->finalize(object);
159  LEAVE(" ");
160 
161 }
162 
163 /************************************************************
164  * Command Callbacks *
165  ************************************************************/
166 
167 /* Make a new budget; put it in a page; open the page. */
168 static void
169 gnc_plugin_budget_cmd_new_budget (GSimpleAction *simple,
170  GVariant *parameter,
171  gpointer user_data)
172 {
173  GncMainWindowActionData *data = user_data;
174  GncBudget *budget;
175  GncPluginPage *page;
176  gchar *description, *date;
177  QofBook *book = gnc_get_current_book();
178 
179  g_return_if_fail (data != NULL);
180 
181  if (!gnc_features_check_used (book, GNC_FEATURE_BUDGET_UNREVERSED))
182  {
183  gnc_features_set_used (book, GNC_FEATURE_BUDGET_UNREVERSED);
184  PWARN ("Setting feature BUDGET_UNREVERSED. This book now requires \
185 GnuCash 3.8 or later.");
186  }
187 
188  budget = gnc_budget_new (gnc_get_current_book());
189  page = gnc_plugin_page_budget_new (budget);
190 
192  description = g_strdup_printf ("%s: %s", _("Created"), date);
193  gnc_budget_set_description (budget, description);
194  g_free (description);
195  g_free (date);
196 
197  gnc_main_window_open_page (data->window, page);
198 }
199 
200 /* If only one budget exists, open it; otherwise user selects one to open */
201 static void
202 gnc_plugin_budget_cmd_open_budget (GSimpleAction *simple,
203  GVariant *parameter,
204  gpointer user_data)
205 {
206  GncMainWindowActionData *data = user_data;
207  guint count;
208  QofBook *book;
209  GncBudget *bgt = NULL;
210  QofCollection *col;
211 
212  g_return_if_fail (data != NULL);
213 
214  book = gnc_get_current_book ();
215  col = qof_book_get_collection (book, GNC_ID_BUDGET);
216  count = qof_collection_count (col);
217  if (count > 0)
218  {
219  if (count == 1)
220  bgt = gnc_budget_get_default (book);
221  else
222  bgt = gnc_budget_gui_select_budget (GTK_WINDOW(data->window), book);
223 
224  if (bgt)
225  gnc_main_window_open_page (data->window,
227  }
228  else /* if no budgets exist yet, just open a new budget */
229  gnc_plugin_budget_cmd_new_budget (simple, parameter, user_data);
230 }
231 
232 /* If only one budget exists, create a copy of it; otherwise user selects one to copy */
233 static void
234 gnc_plugin_budget_cmd_copy_budget (GSimpleAction *simple,
235  GVariant *parameter,
236  gpointer user_data)
237 {
238  GncMainWindowActionData *data = user_data;
239  guint count;
240  QofBook *book;
241  GncBudget *bgt = NULL;
242  QofCollection *col;
243 
244  g_return_if_fail (data != NULL);
245 
246  book = gnc_get_current_book ();
247  col = qof_book_get_collection (book, GNC_ID_BUDGET);
248  count = qof_collection_count (col);
249  if (count > 0)
250  {
251  if (count == 1)
252  bgt = gnc_budget_get_default(book);
253  else
254  bgt = gnc_budget_gui_select_budget (GTK_WINDOW(data->window), book);
255 
256  if (bgt)
257  {
258  GncBudget* copy;
259  gchar* name;
260 
261  copy = gnc_budget_clone (bgt);
262  name = g_strdup_printf ("Copy of %s", gnc_budget_get_name (bgt));
263  gnc_budget_set_name (copy, name);
264  g_free (name);
265 
266  gnc_main_window_open_page (data->window,
268  }
269  }
270  else /* if no budgets exist yet, just open a new budget */
271  gnc_plugin_budget_cmd_new_budget (simple, parameter, user_data);
272 }
273 
274 /* user selects budget to delete */
275 static void
276 gnc_plugin_budget_cmd_delete_budget (GSimpleAction *simple,
277  GVariant *parameter,
278  gpointer user_data)
279 {
280  GncMainWindowActionData *data = user_data;
281  GncBudget *bgt;
282  QofBook *book;
283 
284  g_return_if_fail (data != NULL);
285 
286  book = gnc_get_current_book ();
287  if (qof_collection_count (qof_book_get_collection (book, GNC_ID_BUDGET)) == 0)
288  return;
289 
290  bgt = gnc_budget_gui_select_budget (GTK_WINDOW(data->window), book);
291  if (!bgt) return;
292 
293  gnc_budget_gui_delete_budget (bgt);
294 }
295 
296 /************************************************************
297  * Other Functions *
298  ************************************************************/
299 
300 static void
301 row_activated_cb (GtkTreeView *tv, GtkTreePath *path,
302  GtkTreeViewColumn *column, gpointer user_data)
303 {
304  gtk_dialog_response (GTK_DIALOG(user_data), GTK_RESPONSE_OK);
305 }
306 
307 GncBudget *
308 gnc_budget_gui_select_budget (GtkWindow *parent, QofBook *book)
309 {
310  GncBudget *bgt;
311  GtkDialog *dlg;
312  GtkTreeView *tv;
313  GtkTreeIter iter;
314  GtkTreeSelection *sel;
315  GtkTreeModel *tm;
316  gint response;
317  gboolean ok;
318 
319  dlg = GTK_DIALOG(gtk_dialog_new_with_buttons (
320  _("Select a Budget"), parent, GTK_DIALOG_MODAL,
321  _("_Cancel"), GTK_RESPONSE_CANCEL,
322  _("_OK"), GTK_RESPONSE_OK, NULL));
323 
324  tv = GTK_TREE_VIEW(gtk_tree_view_new ());
325  sel = gtk_tree_view_get_selection (tv);
326  gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE);
327  g_signal_connect (tv, "row-activated", G_CALLBACK(row_activated_cb), dlg);
328  tm = gnc_tree_model_budget_new (book);
329  gnc_tree_view_budget_set_model (tv, tm);
330  g_object_unref (tm);
331  gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area (dlg)), GTK_WIDGET(tv));
332  gtk_widget_show_all (GTK_WIDGET(dlg));
333 
334  // Preselect the default budget
335  bgt = gnc_budget_get_default (book);
336 
337  if (bgt && gnc_tree_model_budget_get_iter_for_budget (tm, &iter, bgt))
338  {
339  GtkTreePath *path = gtk_tree_model_get_path (tm, &iter);
340  gtk_tree_view_set_cursor (tv, path, NULL, FALSE);
341  gtk_tree_path_free (path);
342  }
343 
344  bgt = NULL;
345  response = gtk_dialog_run (dlg);
346  switch (response)
347  {
348  case GTK_RESPONSE_OK:
349  ok = gtk_tree_selection_get_selected (sel, &tm, &iter);
350  if (ok)
351  bgt = gnc_tree_model_budget_get_budget (tm, &iter);
352  break;
353  default:
354  break;
355  }
356 
357  gtk_widget_destroy (GTK_WIDGET(dlg));
358  return bgt;
359 }
360 
The instance data structure for a content plugin.
utility functions for the GnuCash UI
GncBudget * gnc_budget_new(QofBook *book)
Creates and initializes a Budget.
Definition: gnc-budget.cpp:305
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
GncPluginPage * gnc_plugin_page_budget_new(GncBudget *budget)
Create a new "budget" plugin 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.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
GncBudget * gnc_budget_clone(const GncBudget *old_b)
Clones a budget creating a copy.
Definition: gnc-budget.cpp:355
char * gnc_print_time64(time64 time, const char *format)
print a time64 as a date string per format
Definition: gnc-date.cpp:369
void gnc_plugin_set_actions_enabled(GActionMap *action_map, const gchar **action_names, gboolean enable)
This function sets the sensitivity of a GAction in a specific group.
Definition: gnc-plugin.c:250
void gnc_budget_set_name(GncBudget *budget, const gchar *name)
Set/Get the name of the Budget.
Definition: gnc-budget.cpp:386
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
Definition: qofbook.cpp:497
void gnc_budget_set_description(GncBudget *budget, const gchar *description)
Set/Get the description of the Budget.
Definition: gnc-budget.cpp:411
#define PLUGIN_ACTIONS_NAME
The label given to the main window for this plugin.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
GSimpleActionGroup * gnc_main_window_get_action_group(GncMainWindow *window, const gchar *group_name)
Retrieve a specific set of user interface actions from a window.
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
guint qof_collection_count(const QofCollection *col)
return the number of entities in the collection.
Definition: qofid.cpp:244
Take from locale information.
Definition: gnc-date.h:128
const gchar * qof_date_format_get_string(QofDateFormat df)
This function returns a strftime formatting string for printing an all numeric date (e...
Definition: gnc-date.cpp:501
provides some utilities for working with the list of budgets in a book.
#define PLUGIN_UI_FILENAME
The name of the UI description file for this plugin.
Utility functions for file access.