GnuCash  5.6-150-g038405b370+
top-level.c
1 /********************************************************************\
2  * top-level.c -- Gnome GUI main for GnuCash *
3  * Copyright (C) 1997 Robin D. Clark *
4  * Copyright (C) 1998-2000 Linas Vepstas *
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 
25 #include <config.h>
26 
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29 #include <stdlib.h>
30 
31 #include "TransLog.h"
32 #include "business-options-gnome.h"
33 #include "business-urls.h"
34 #include "combocell.h"
35 #include "dialog-account.h"
36 #include "dialog-doclink.h"
37 #include "dialog-commodity.h"
38 #include "dialog-invoice.h"
39 #include "dialog-preferences.h"
40 #include "dialog-sx-editor.h"
41 #include "dialog-transfer.h"
42 #include "dialog-totd.h"
43 #include "assistant-hierarchy.h"
44 #include "file-utils.h"
45 #include "gnc-component-manager.h"
46 #include "gnc-engine.h"
47 #include "gnc-file.h"
48 #include "gnc-hooks.h"
49 #include "gncInvoice.h"
50 #include "gfec.h"
51 #include "gnc-main-window.h"
52 #include "gnc-menu-extensions.h"
53 #include "gnc-plugin-menu-additions.h" /* FIXME Remove this line*/
54 #include "gnc-plugin-account-tree.h" /* FIXME Remove this line*/
55 #include "gnc-plugin-basic-commands.h" /* FIXME Remove this line*/
56 #include "gnc-plugin-file-history.h" /* FIXME Remove this line*/
57 #include "gnc-plugin-register.h" /* FIXME Remove this line*/
58 #include "gnc-plugin-budget.h"
59 #include "gnc-plugin-business.h"
61 #include "gnc-plugin-manager.h" /* FIXME Remove this line*/
62 #include "gnc-html.h"
63 #include "gnc-gnome-utils.h"
64 #include "gnc-report.h"
65 #include "gnc-split-reg.h"
66 #include "gnc-state.h"
67 #include "gnc-ui.h"
68 #include "gnc-ui-util.h"
69 #include "gnucash-color.h"
70 #include "gnucash-sheet.h"
71 #include "gnucash-style.h"
72 #include "search-core-type.h"
73 #include "search-owner.h"
74 #include "top-level.h"
75 #include "window-report.h"
76 #include "gnc-window.h"
77 #include "gnc-gkeyfile-utils.h"
78 
79 
81 /* This static indicates the debugging module that this .o belongs to. */
82 static QofLogModule log_module = GNC_MOD_GUI;
83 
84 /* ============================================================== */
85 /* HTML Handler for reports. */
86 
87 static gboolean
88 validate_type(const char *url_type, const char *location,
89  const char *entity_type, GNCURLResult *result,
90  GncGUID *guid, QofInstance **entity)
91 {
92  QofCollection *col;
93  QofBook * book = gnc_get_current_book();
94  if (!string_to_guid (location + strlen(url_type), guid))
95  {
96  result->error_message = g_strdup_printf (_("Bad URL: %s"), location);
97  return FALSE;
98  }
99  col = qof_book_get_collection (book, entity_type);
100  *entity = qof_collection_lookup_entity (col, guid);
101  if (NULL == *entity)
102  {
103  result->error_message = g_strdup_printf (_("Entity Not Found: %s"),
104  location);
105  return FALSE;
106  }
107 
108  return TRUE;
109 }
110 
111 
112 static gboolean
113 gnc_html_register_url_cb (const char *location, const char *label,
114  gboolean new_window, GNCURLResult *result)
115 {
116  GncPluginPage *page = NULL;
117  GNCSplitReg * gsr = NULL;
118  Split * split = NULL;
119  Account * account = NULL;
120  Transaction * trans;
121  GncInvoice * invoice;
122  GList * node;
123  GncGUID guid;
124  QofInstance * entity = NULL;
125 
126  g_return_val_if_fail (location != NULL, FALSE);
127  g_return_val_if_fail (result != NULL, FALSE);
128 
129  result->load_to_stream = FALSE;
130 
131  /* href="gnc-register:account=My Bank Account" */
132  if (strncmp("account=", location, 8) == 0)
133  {
134  account = gnc_account_lookup_by_full_name (gnc_get_current_root_account (),
135  location + 8);
136  }
137 
138  /* href="gnc-register:guid=12345678901234567890123456789012" */
139  else if (strncmp ("acct-guid=", location, strlen ("acct-guid=")) == 0)
140  {
141  if (!validate_type("acct-guid=", location, GNC_ID_ACCOUNT, result, &guid, &entity))
142  return FALSE;
143 
144  account = GNC_ACCOUNT(entity);
145  }
146 
147  else if (strncmp ("trans-guid=", location, strlen ("trans-guid=")) == 0)
148  {
149  if (!validate_type("trans-guid=", location, GNC_ID_TRANS, result, &guid, &entity))
150  return FALSE;
151 
152  trans = (Transaction *) entity;
153 
154  for (node = xaccTransGetSplitList (trans); node; node = node->next)
155  {
156  split = node->data;
157  account = xaccSplitGetAccount(split);
158  if (account) break;
159  }
160 
161  if (!account)
162  {
163  result->error_message =
164  g_strdup_printf (_("Transaction with no Accounts: %s"), location);
165  return FALSE;
166  }
167  }
168 
169  else if (strncmp ("trans-doclink-guid=", location,
170  strlen ("trans-doclink-guid=")) == 0)
171  {
172  if (!validate_type("trans-doclink-guid=", location, GNC_ID_TRANS,
173  result, &guid, &entity))
174  return FALSE;
175 
176  trans = (Transaction *) entity;
177  gnc_doclink_open_uri (gnc_ui_get_gtk_window (GTK_WIDGET (result->parent)),
178  xaccTransGetDocLink (trans));
179  return TRUE;
180  }
181 
182  else if (strncmp ("invoice-doclink-guid=", location,
183  strlen ("invoice-doclink-guid=")) == 0)
184  {
185  if (!validate_type("invoice-doclink-guid=", location, GNC_ID_INVOICE,
186  result, &guid, &entity))
187  return FALSE;
188 
189  invoice = (GncInvoice *) entity;
190  gnc_doclink_open_uri (gnc_ui_get_gtk_window (GTK_WIDGET (result->parent)),
191  gncInvoiceGetDocLink (invoice));
192  return TRUE;
193  }
194 
195  else if (strncmp ("split-guid=", location, strlen ("split-guid=")) == 0)
196  {
197  if (!validate_type("split-guid=", location, GNC_ID_SPLIT, result, &guid, &entity))
198  return FALSE;
199 
200  split = (Split *) entity;
201  account = xaccSplitGetAccount(split);
202  }
203 
204  else
205  {
206  result->error_message =
207  g_strdup_printf (_("Unsupported entity type: %s"), location);
208  return FALSE;
209  }
210 
211  page = gnc_plugin_page_register_new (account, FALSE);
212  gnc_main_window_open_page (GNC_MAIN_WINDOW (result->parent), page);
213  if (split)
214  {
216 
217  /* Test for visibility of split */
218  if (gnc_split_reg_clear_filter_for_split (gsr, split))
220 
221  gnc_split_reg_jump_to_split (gsr, split);
222  }
223  return TRUE;
224 }
225 
226 /* ============================================================== */
227 
228 static gboolean
229 gnc_html_price_url_cb (const char *location, const char *label,
230  gboolean new_window, GNCURLResult *result)
231 {
232  GncGUID guid;
233  QofInstance * entity = NULL;
234 
235  g_return_val_if_fail (location != NULL, FALSE);
236  g_return_val_if_fail (result != NULL, FALSE);
237 
238  result->load_to_stream = FALSE;
239 
240  /* href="gnc-register:guid=12345678901234567890123456789012" */
241  if (strncmp ("price-guid=", location, strlen ("price-guid=")) == 0)
242  {
243  if (!validate_type("price-guid=", location, GNC_ID_PRICE, result, &guid, &entity))
244  return FALSE;
245 
246  if (!gnc_price_edit_by_guid (GTK_WIDGET (result->parent), &guid))
247  {
248  result->error_message = g_strdup_printf (_("No such price: %s"),
249  location);
250  return FALSE;
251  }
252  }
253  else
254  {
255  result->error_message = g_strdup_printf (_("Badly formed URL %s"),
256  location);
257  return FALSE;
258  }
259 
260  return TRUE;
261 }
262 
277 static void
278 gnc_restore_all_state (gpointer session, gpointer unused)
279 {
280  GKeyFile *keyfile = NULL;
281  gchar *file_guid = NULL;
282  GError *error = NULL;
283 
284  keyfile = gnc_state_load (session);
285 
286 #ifdef DEBUG
287  /* Debugging: dump a copy to the trace log */
288  {
289  gchar *file_data;
290  gsize file_length;
291  file_data = g_key_file_to_data(keyfile, &file_length, NULL);
292  DEBUG("=== File Data Read===\n%s\n=== File End ===\n", file_data);
293  g_free(file_data);
294  }
295 #endif
296 
297  /* If no state file was found, keyfile will be empty
298  * In that case, let's load the default state */
299  if (!g_key_file_has_group (keyfile, STATE_FILE_TOP))
300  {
302  LEAVE("no state file");
303  goto cleanup;
304  }
305 
306  /* report any other keyfile read error as a warning
307  * but still load default state */
308  file_guid = g_key_file_get_string(keyfile, STATE_FILE_TOP,
309  STATE_FILE_BOOK_GUID, &error);
310  if (error)
311  {
313  g_warning("error reading group %s key %s: %s",
314  STATE_FILE_TOP, STATE_FILE_BOOK_GUID, error->message);
315  LEAVE("no guid in state file");
316  goto cleanup;
317  }
318 
320 
321  /* Clean up */
322  LEAVE("ok");
323 cleanup:
324  if (error)
325  g_error_free(error);
326  if (file_guid)
327  g_free(file_guid);
328 
329  gnc_totd_dialog_reparent ();
330 }
331 
332 
347 static void
348 gnc_save_all_state (gpointer session, gpointer unused)
349 {
350  QofBook *book;
351  gchar guid_string[GUID_ENCODING_LENGTH+1];
352  const GncGUID *guid;
353  GKeyFile *keyfile = NULL;
354 
355  keyfile = gnc_state_get_current ();
356  if (keyfile)
357  {
358  /* Remove existing Window and Page groups from the keyfile
359  * They will be regenerated.
360  */
361  gsize num_groups, curr;
362  gchar **groups = g_key_file_get_groups (keyfile, &num_groups);
363  for (curr=0; curr < num_groups; curr++)
364  {
365  if (g_str_has_prefix (groups[curr], "Window ") ||
366  g_str_has_prefix (groups[curr], "Page "))
367  {
368  DEBUG ("Removing state group %s", groups[curr]);
369  g_key_file_remove_group (keyfile, groups[curr], NULL);
370  }
371  }
372  g_strfreev (groups);
373  }
374 
375  /* Store the book's GncGUID in the top level group */
376  book = qof_session_get_book(session);
377  if (!book)
378  {
379  PERR("Session has no book!");
380  return;
381  }
382  guid = qof_entity_get_guid(QOF_INSTANCE(book));
383  guid_to_string_buff(guid, guid_string);
384  g_key_file_set_string(keyfile, STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
385  guid_string);
386 
388 
389 #ifdef DEBUG
390  /* Debugging: dump a copy to the trace log */
391  {
392  gchar *file_data;
393  gsize file_length;
394  file_data = g_key_file_to_data(keyfile, &file_length, NULL);
395  DEBUG("=== File Data Written===\n%s\n=== File End ===\n", file_data);
396  g_free(file_data);
397  }
398 #endif
399  LEAVE("");
400 }
401 
402 void
403 gnc_main_gui_init (void)
404 {
405  ENTER(" ");
406 
407  if (!gnucash_style_init())
408  gnc_shutdown(1);
409  gnucash_color_init();
410 
411  gnc_html_register_url_handler (URL_TYPE_REGISTER,
412  gnc_html_register_url_cb);
413 
414  gnc_html_register_url_handler (URL_TYPE_PRICE,
415  gnc_html_price_url_cb);
416 
417  /* Register the Owner search type */
418  gnc_search_core_register_type (GNC_OWNER_MODULE_NAME,
419  (GNCSearchCoreNew) gnc_search_owner_new);
420  gnc_business_urls_initialize ();
422 
423  /* FIXME Remove this test code */
433  gnc_plugin_manager_get (), gnc_plugin_register_new ());
435  gnc_plugin_manager_get (), gnc_plugin_business_new ());
436  /* I'm not sure why the FIXME note says to remove this. Maybe
437  each module should be adding its own plugin to the manager?
438  Anyway... Oh, maybe... nah */
440  gnc_plugin_budget_new ());
441  gnc_ui_hierarchy_assistant_initialize();
442 
443  /* Run the ui startup hooks. */
444  gnc_hook_run(HOOK_UI_STARTUP, NULL);
445 
446  gnc_hook_add_dangler(HOOK_BOOK_OPENED,
447  gnc_restore_all_state, NULL, NULL);
448  gnc_hook_add_dangler(HOOK_BOOK_CLOSED,
449  gnc_save_all_state, NULL, NULL);
450  gnc_hook_add_dangler(HOOK_BOOK_CLOSED,
451  (GFunc)gnc_reports_flush_global, NULL, NULL);
452  gnc_hook_add_dangler(HOOK_BOOK_OPENED,
453  (GFunc)gnc_invoice_remind_bills_due_cb, NULL, NULL);
454  gnc_hook_add_dangler(HOOK_BOOK_OPENED,
455  (GFunc)gnc_invoice_remind_invoices_due_cb, NULL, NULL);
456 
457  gnc_ui_sx_initialize();
458 
459  /* Add to preferences under Business */
460  /* The parameters are; glade file, items to add from glade file - last being the dialog, preference tab name */
461  gnc_preferences_add_page("business-prefs.glade", "liststore_printinvoice,days_in_adj,cust_days_in_adj,business_prefs",
462  _("Business"));
463 
464  LEAVE(" ");
465  return;
466 }
467 
468 /****************** END OF FILE **********************/
GncPluginPage * gnc_plugin_page_register_new(Account *account, gboolean subaccounts)
Create a new "register" plugin page, given a pointer to an account.
Functions to load, save and get gui state.
void gnc_preferences_add_page(const gchar *filename, const gchar *widgetname, const gchar *tabname)
This function adds a full page of preferences to the preferences dialog.
void gnc_main_window_restore_all_windows(const GKeyFile *keyfile)
Restore the persistent state of all windows.
The instance data structure for a content plugin.
This file contains the functions to present a gui to the user for creating a new account or editing a...
utility functions for the GnuCash UI
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Definition: qofid.cpp:212
STRUCTS.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264
gboolean string_to_guid(const gchar *string, GncGUID *guid)
Given a string, replace the given guid with the parsed one unless the given value is null...
Functions that are supported by all types of windows.
GncPlugin * gnc_plugin_file_history_new(void)
Create a new file history plugin.
GKeyFile helper routines.
Plugin management functions for the GnuCash UI.
void gnc_plugin_manager_add_plugin(GncPluginManager *manager, GncPlugin *plugin)
Add a plugin to the list maintained by the plugin manager.
void gnc_shutdown(int exit_status)
Shutdown gnucash.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition: guid.cpp:173
Convenience wrapper around GdkRGBA for use in Register Gnome classes.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GtkWindow * gnc_ui_get_gtk_window(GtkWidget *widget)
Get a pointer to the widget&#39;s immediate top level GtkWindow.
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition: gnc-state.c:248
void gnc_main_window_save_all_windows(GKeyFile *keyfile)
Save the persistent state of all windows.
const char * xaccTransGetDocLink(const Transaction *trans)
Gets the transaction Document Link.
void gnc_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Display a data plugin page in a window.
Functions for adding content to a window.
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:574
Functions providing a register page for the GnuCash UI.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition: guid.h:84
Functions providing the file history menu.
Functions providing menu items from scheme code.
Account * gnc_account_lookup_by_full_name(const Account *any_acc, const gchar *name)
The gnc_account_lookup_full_name() subroutine works like gnc_account_lookup_by_name, but uses fully-qualified names using the given separator.
Definition: Account.cpp:3133
GncPluginManager * gnc_plugin_manager_get(void)
Retrieve a pointer to the plugin manager.
Gnome specific utility functions.
Public declarations of GnucashRegister class.
Dialog for handling user preferences.
GncPlugin * gnc_plugin_basic_commands_new(void)
Create a new basic commands menu plugin.
GncPlugin * gnc_plugin_menu_additions_new(void)
Create a new menu_additions plugin.
All type declarations for the whole Gnucash engine.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
Utility functions for file access.
API for the transaction logger.
Business Invoice Interface.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
GncPlugin * gnc_plugin_account_tree_new(void)
Create a new account tree menu plugin.
Provide the menus to create a chart of account page.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Styling functions for RegisterGnome.
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
void gnc_main_window_restore_default_state(GncMainWindow *window)
Restore the persistent state of one window to a sane default.
void gnc_plugin_page_register_clear_current_filter(GncPluginPage *plugin_page)
This function clears the registers current filter.
GKeyFile * gnc_state_load(const QofSession *session)
Load the state from a state file on disk for the given session.
Definition: gnc-state.c:202
The type used to store guids in C.
Definition: guid.h:75
GNCSplitReg * gnc_plugin_page_register_get_gsr(GncPluginPage *plugin_page)
Get the GNCSplitReg data structure associated with this register page.
"select" and "new" commodity windows
Functions providing a basic set of menu items.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
void gnc_business_options_gnome_initialize(void)
Set up the business and counters pages in the File Preferences dialog.