]> Dogcows Code - chaz/homebank/blob - src/dsp_mainwindow.c
Merge branch 'master' into ext-perl
[chaz/homebank] / src / dsp_mainwindow.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2017 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank 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, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "dsp_mainwindow.h"
24
25 #include "ext.h"
26
27 #include "list_account.h"
28 #include "list_upcoming.h"
29 #include "list_topspending.h"
30
31 #include "dsp_account.h"
32 #include "ui-assist-import.h"
33 #include "ui-assist-start.h"
34 #include "ui-account.h"
35 #include "ui-currency.h"
36 #include "ui-payee.h"
37 #include "ui-category.h"
38 #include "ui-archive.h"
39 #include "ui-assign.h"
40 #include "ui-budget.h"
41 #include "ui-pref.h"
42 #include "ui-hbfile.h"
43 #include "ui-transaction.h"
44
45 #include "rep_balance.h"
46 #include "rep_budget.h"
47 #include "rep_stats.h"
48 #include "rep_time.h"
49 #include "rep_vehicle.h"
50
51 #include "gtk-chart.h"
52
53 //#define HOMEBANK_URL_HELP "http://homebank.free.fr/help/"
54 #define HOMEBANK_URL_HELP "index.html"
55 #define HOMEBANK_URL_HELP_ONLINE "https://launchpad.net/homebank/+addquestion"
56 #define HOMEBANK_URL_HELP_TRANSLATE "https://launchpad.net/homebank/+translations"
57 #define HOMEBANK_URL_HELP_PROBLEM "https://launchpad.net/homebank/+filebug"
58
59
60 /****************************************************************************/
61 /* Debug macros */
62 /****************************************************************************/
63 #define MYDEBUG 0
64
65 #if MYDEBUG
66 #define DB(x) (x);
67 #else
68 #define DB(x);
69 #endif
70
71 /* our global datas */
72 extern struct HomeBank *GLOBALS;
73 extern struct Preferences *PREFS;
74 extern gchar *homebank_pixmaps_dir;
75
76
77 /* our functions prototype */
78 static void ui_mainwindow_action_new(void);
79 static void ui_mainwindow_action_open(void);
80 static void ui_mainwindow_action_save(void);
81 static void ui_mainwindow_action_saveas(void);
82 static void ui_mainwindow_action_revert(void);
83 static void ui_mainwindow_action_properties(void);
84 static void ui_mainwindow_action_close(void);
85 static void ui_mainwindow_action_quit(void);
86
87 static void ui_mainwindow_action_defcurrency(void);
88 static void ui_mainwindow_action_defaccount(void);
89 static void ui_mainwindow_action_defpayee(void);
90 static void ui_mainwindow_action_defcategory(void);
91 static void ui_mainwindow_action_defarchive(void);
92 static void ui_mainwindow_action_defbudget(void);
93 static void ui_mainwindow_action_defassign(void);
94 static void ui_mainwindow_action_preferences(void);
95
96 static void ui_mainwindow_action_toggle_toolbar(GtkToggleAction *action);
97 static void ui_mainwindow_action_toggle_upcoming(GtkToggleAction *action);
98 static void ui_mainwindow_action_toggle_topspending(GtkToggleAction *action);
99 static void ui_mainwindow_action_toggle_minor(GtkToggleAction *action);
100
101 static void ui_mainwindow_action_showtransactions(void);
102 static void ui_mainwindow_action_addtransactions(void);
103 static void ui_mainwindow_action_checkscheduled(void);
104
105 static void ui_mainwindow_action_statistic(void);
106 static void ui_mainwindow_action_trendtime(void);
107 static void ui_mainwindow_action_budget(void);
108 static void ui_mainwindow_action_balance(void);
109 static void ui_mainwindow_action_vehiclecost(void);
110
111 static void ui_mainwindow_action_import(GtkAction *action);
112 static void ui_mainwindow_action_export(void);
113 static void ui_mainwindow_action_anonymize(void);
114 static void ui_mainwindow_action_file_statistics(void);
115
116 static void ui_mainwindow_action_pluginprefs(void);
117
118 static void ui_mainwindow_action_help(void);
119 void ui_mainwindow_action_help_welcome(void);
120 static void ui_mainwindow_action_help_online(void);
121 static void ui_mainwindow_action_help_translate(void);
122 static void ui_mainwindow_action_help_problem(void);
123 static void ui_mainwindow_action_about(void);
124
125
126 static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager);
127
128 static void ui_mainwindow_populate_topspending(GtkWidget *widget, gpointer user_data);
129
130 void ui_mainwindow_open(GtkWidget *widget, gpointer user_data);
131
132 void ui_mainwindow_save(GtkWidget *widget, gpointer user_data);
133 void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data);
134 void ui_mainwindow_action(GtkWidget *widget, gpointer user_data);
135 void ui_mainwindow_toggle_minor(GtkWidget *widget, gpointer user_data);
136 void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data);
137
138 gboolean ui_dialog_msg_savechanges(GtkWidget *widget, gpointer user_data);
139
140 void ui_mainwindow_update(GtkWidget *widget, gpointer user_data);
141 void ui_mainwindow_addtransactions(GtkWidget *widget, gpointer user_data);
142 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
143
144 static void ui_panel_topspending_update(GtkWidget *widget, gpointer user_data);
145
146 static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data);
147 void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data);
148
149 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
150
151 static void ui_mainwindow_showprefs(gint page);
152
153 extern gchar *CYA_ACC_TYPE[];
154
155 gchar *CYA_CATSUBCAT[] = {
156 N_("Category"),
157 N_("Subcategory"),
158 NULL
159 };
160
161
162 static GtkActionEntry entries[] = {
163
164 /* name, icon-name, label */
165
166 { "FileMenu" , NULL, N_("_File"), NULL, NULL, NULL },
167 { "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL },
168 { "EditMenu" , NULL, N_("_Edit"), NULL, NULL, NULL },
169 { "ViewMenu" , NULL, N_("_View"), NULL, NULL, NULL },
170 { "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL },
171 { "TxnMenu" , NULL, N_("_Transactions"), NULL, NULL, NULL },
172 { "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL },
173 { "ToolsMenu" , NULL, N_("_Tools"), NULL, NULL, NULL },
174 { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL },
175 { "HelpMenu" , NULL, N_("_Help"), NULL, NULL, NULL },
176
177 // { "Import" , NULL, N_("Import") },
178 // { "Export" , NULL, N_("Export to") },
179 /* name, icon-name, label, accelerator, tooltip */
180
181 /* FileMenu */
182 { "New" , ICONNAME_NEW , N_("_New") , "<control>N", N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) },
183 { "Open" , ICONNAME_OPEN , N_("_Open...") , "<control>O", N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) },
184 { "Save" , ICONNAME_SAVE , N_("_Save") , "<control>S", N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) },
185 { "SaveAs" , ICONNAME_SAVE_AS , N_("Save _As...") , "<shift><control>S", N_("Save the current file with a different name"), G_CALLBACK (ui_mainwindow_action_saveas) },
186 { "Revert" , ICONNAME_REVERT , N_("Revert") , NULL, N_("Revert to a saved version of this file"), G_CALLBACK (ui_mainwindow_action_revert) },
187
188 { "Properties" , ICONNAME_PROPERTIES , N_("Properties..."), NULL, N_("Configure the file"), G_CALLBACK (ui_mainwindow_action_properties) },
189 { "Close" , ICONNAME_CLOSE , N_("_Close") , "<control>W", N_("Close the current file"), G_CALLBACK (ui_mainwindow_action_close) },
190 { "Quit" , ICONNAME_QUIT , N_("_Quit") , "<control>Q", N_("Quit HomeBank"), G_CALLBACK (ui_mainwindow_action_quit) },
191
192 /* Exchange */
193 { "ImportQIF" , ICONNAME_HB_FILE_IMPORT , N_("QIF file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
194 { "ImportOFX" , ICONNAME_HB_FILE_IMPORT , N_("OFX/QFX file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
195 { "ImportCSV" , ICONNAME_HB_FILE_IMPORT , N_("CSV file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
196
197 { "ExportQIF" , ICONNAME_HB_FILE_EXPORT , N_("Export QIF file...") , NULL, N_("Export all account in a QIF file"), G_CALLBACK (ui_mainwindow_action_export) },
198
199 /* EditMenu */
200 { "Preferences", ICONNAME_PREFERENCES , N_("Preferences..."), NULL, N_("Configure HomeBank"), G_CALLBACK (ui_mainwindow_action_preferences) },
201
202 /* ManageMenu */
203 { "Currency" , ICONNAME_HB_CURRENCY , N_("Currencies...") , NULL, N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) },
204 { "Account" , ICONNAME_HB_ACCOUNT , N_("Acc_ounts...") , NULL, N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) },
205 { "Payee" , ICONNAME_HB_PAYEE , N_("_Payees...") , NULL, N_("Configure the payees"), G_CALLBACK (ui_mainwindow_action_defpayee) },
206 { "Category" , ICONNAME_HB_CATEGORY , N_("Categories...") , NULL, N_("Configure the categories"), G_CALLBACK (ui_mainwindow_action_defcategory) },
207 { "Archive" , ICONNAME_HB_ARCHIVE , N_("Scheduled/Template...") , NULL, N_("Configure the scheduled/template transactions"), G_CALLBACK (ui_mainwindow_action_defarchive) },
208 { "Budget" , ICONNAME_HB_BUDGET , N_("Budget...") , NULL, N_("Configure the budget"), G_CALLBACK (ui_mainwindow_action_defbudget) },
209 { "Assign" , ICONNAME_HB_ASSIGN , N_("Assignments..."), NULL, N_("Configure the automatic assignments"), G_CALLBACK (ui_mainwindow_action_defassign) },
210
211 /* TxnMenu */
212 { "ShowOpe" , ICONNAME_HB_OPE_SHOW , N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) },
213 { "AddOpe" , ICONNAME_HB_OPE_ADD , N_("Add...") , NULL, N_("Add transactions"), G_CALLBACK (ui_mainwindow_action_addtransactions) },
214 { "Scheduler" , NULL , N_("Set scheduler...") , NULL, N_("Configure the transaction scheduler"), G_CALLBACK (ui_mainwindow_action_properties) },
215 { "AddScheduled", NULL , N_("Post scheduled"), NULL, N_("Post pending scheduled transactions"), G_CALLBACK (ui_mainwindow_action_checkscheduled) },
216
217 /* ReportMenu */
218 { "RStatistics" , ICONNAME_HB_REP_STATS , N_("_Statistics...") , NULL, N_("Open the Statistics report"), G_CALLBACK (ui_mainwindow_action_statistic) },
219 { "RTrendTime" , ICONNAME_HB_REP_TIME , N_("_Trend Time...") , NULL, N_("Open the Trend Time report"), G_CALLBACK (ui_mainwindow_action_trendtime) },
220 { "RBudget" , ICONNAME_HB_REP_BUDGET , N_("B_udget...") , NULL, N_("Open the Budget report"), G_CALLBACK (ui_mainwindow_action_budget) },
221 { "RBalance" , ICONNAME_HB_REP_BALANCE, N_("Balance...") , NULL, N_("Open the Balance report"), G_CALLBACK (ui_mainwindow_action_balance) },
222 { "RVehiculeCost", ICONNAME_HB_REP_CAR , N_("_Vehicle cost...") , NULL, N_("Open the Vehicle cost report"), G_CALLBACK (ui_mainwindow_action_vehiclecost) },
223
224 /* Tools */
225 { "Welcome" , NULL , N_("Show welcome dialog...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_help_welcome) },
226 { "FileStats" , NULL , N_("File statistics...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_file_statistics) },
227 { "Anonymize" , NULL , N_("Anonymize...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_anonymize) },
228
229 /* Plugins */
230 { "PluginPreferences", "prf-plugins", N_("_Plugins..."), "<control>U", N_("Configure plugin preferences"), G_CALLBACK(ui_mainwindow_action_pluginprefs) },
231
232 /* HelpMenu */
233 { "Contents" , ICONNAME_HELP , N_("_Contents") , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) },
234 { "Online" , "lpi-help" , N_("Get Help Online...") , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) },
235 { "Translate" , "lpi-translate" , N_("Translate this Application..."), NULL, N_("Connect to the LaunchPad website to help translate this application"), G_CALLBACK (ui_mainwindow_action_help_translate) },
236 { "Problem" , "lpi-bug" , N_("Report a Problem...") , NULL, N_("Connect to the LaunchPad website to help fix problems"), G_CALLBACK (ui_mainwindow_action_help_problem) },
237
238 { "About" , ICONNAME_ABOUT , N_("_About") , NULL, N_("About HomeBank") ,G_CALLBACK (ui_mainwindow_action_about) },
239
240 };
241 static guint n_entries = G_N_ELEMENTS (entries);
242
243
244 static GtkToggleActionEntry toggle_entries[] = {
245 /* name , icon-name, label, accelerator, tooltip, callback, is_active */
246 { "Toolbar" , NULL , N_("_Toolbar") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_toolbar), TRUE },
247 { "Spending" , NULL , N_("_Top spending") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_topspending), TRUE },
248 { "Upcoming" , NULL , N_("_Scheduled list") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE },
249 { "AsMinor" , NULL , N_("Euro minor"), "<control>M", NULL, G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE },
250 };
251
252 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
253
254
255 static const gchar *ui_info =
256 "<ui>"
257
258 " <menubar name='MenuBar'>"
259 " <menu action='FileMenu'>"
260 " <menuitem action='New'/>"
261 " <menuitem action='Open'/>"
262 " <separator/>"
263 " <menuitem action='Save'/>"
264 " <menuitem action='SaveAs'/>"
265 " <menuitem action='Revert'/>"
266 " <separator/>"
267 " <menuitem action='Properties'/>"
268 " <separator/>"
269 " <menu action='ImportMenu'>"
270 " <menuitem action='ImportQIF'/>"
271 " <menuitem action='ImportOFX'/>"
272 " <menuitem action='ImportCSV'/>"
273 " </menu>"
274 " <menuitem action='ExportQIF'/>"
275 //" <separator/>"
276 // print to come here
277 " <separator/>"
278 " <menuitem action='Close'/>"
279 " <menuitem action='Quit'/>"
280 " </menu>"
281 " <menu action='EditMenu'>"
282 " <menuitem action='Preferences'/>"
283 " </menu>"
284 " <menu action='ViewMenu'>"
285 " <menuitem action='Toolbar'/>"
286 " <separator/>"
287 " <menuitem action='Spending'/>"
288 " <menuitem action='Upcoming'/>"
289 " <separator/>"
290 " <menuitem action='AsMinor'/>"
291 " </menu>"
292 " <menu action='ManageMenu'>"
293 " <menuitem action='Account'/>"
294 " <menuitem action='Payee'/>"
295 " <menuitem action='Category'/>"
296 " <menuitem action='Archive'/>"
297 " <menuitem action='Budget'/>"
298 " <menuitem action='Assign'/>"
299 " <menuitem action='Currency'/>"
300 " </menu>"
301 " <menu action='TxnMenu'>"
302 " <menuitem action='ShowOpe'/>"
303 " <menuitem action='AddOpe'/>"
304 " <separator/>"
305 " <menuitem action='Scheduler'/>"
306 " <menuitem action='AddScheduled'/>"
307 " </menu>"
308 " <menu action='ReportMenu'>"
309 " <menuitem action='RStatistics'/>"
310 " <menuitem action='RTrendTime'/>"
311 " <menuitem action='RBalance'/>"
312 " <menuitem action='RBudget'/>"
313 " <menuitem action='RVehiculeCost'/>"
314 " </menu>"
315 " <menu action='ToolsMenu'>"
316 " <menuitem action='Welcome'/>"
317 " <menuitem action='FileStats'/>"
318 " <separator/>"
319 " <menuitem action='Anonymize'/>"
320 " </menu>"
321 " <menu action='PluginMenu'>"
322 " <separator/>"
323 " <menuitem action='PluginPreferences'/>"
324 " <separator/>"
325 " </menu>"
326 " <menu action='HelpMenu'>"
327 " <menuitem action='Contents'/>"
328 " <separator/>"
329 " <menuitem action='Online'/>"
330 " <menuitem action='Translate'/>"
331 " <menuitem action='Problem'/>"
332 " <separator/>"
333 " <menuitem action='About'/>"
334 " </menu>"
335 " </menubar>"
336
337 " <toolbar name='ToolBar'>"
338 " <toolitem action='New'/>"
339 // here Open + recent is coded
340 " <toolitem action='Save'/>"
341 " <separator/>"
342 " <toolitem action='Account'/>"
343 " <toolitem action='Payee'/>"
344 " <toolitem action='Category'/>"
345 " <toolitem action='Archive'/>"
346 " <toolitem action='Budget'/>"
347 " <toolitem action='Assign'/>"
348 " <toolitem action='Currency'/>"
349 " <separator/>"
350 " <toolitem action='ShowOpe'/>"
351 " <toolitem action='AddOpe'/>"
352 " <separator/>"
353 " <toolitem action='RStatistics'/>"
354 " <toolitem action='RTrendTime'/>"
355 " <toolitem action='RBalance'/>"
356 " <toolitem action='RBudget'/>"
357 " <toolitem action='RVehiculeCost'/>"
358 " <separator/>"
359 " </toolbar>"
360
361 "</ui>";
362
363
364
365 /* TODO: a bouger */
366
367
368 /*
369 **
370 */
371 void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data)
372 {
373 //struct hbfile_data *data;
374 gchar *basename;
375 gchar *title;
376 gchar *secondtext;
377 gint result;
378
379 DB( g_print("\n[ui-mainwindow] revert\n") );
380
381 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
382
383 basename = g_path_get_basename(GLOBALS->xhb_filepath);
384 title = g_strdup_printf (
385 _("Revert unsaved changes to file '%s'?"), basename);
386
387 secondtext =
388 _("- Changes made to the file will be permanently lost\n"
389 "- File will be reloaded from the last save (.xhb~)");
390
391 result = ui_dialog_msg_confirm_alert(
392 GTK_WINDOW(GLOBALS->mainwindow),
393 title,
394 secondtext,
395 _("_Revert")
396 );
397
398 g_free(title);
399 g_free(basename);
400
401 if( result == GTK_RESPONSE_OK )
402 {
403 DB( g_print(" - should revert\n") );
404
405 hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
406 ui_mainwindow_open_internal(widget, NULL);
407 hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
408 }
409
410 }
411
412
413 static void
414 activate_url (GtkAboutDialog *about,
415 const gchar *link,
416 gpointer data)
417 {
418 DB( g_print("activate url %s\n", link) );
419
420 homebank_util_url_show (link);
421 }
422
423 static void hbfile_about(void)
424 {
425 GtkWidget *dialog;
426 GdkPixbuf *pixbuf;
427 gchar *pathfilename;
428 gchar *version;
429
430 static const gchar *artists[] = {
431 "Maxime DOYEN",
432 NULL
433 };
434
435 static const gchar *authors[] = {
436 "Lead developer:\n" \
437 "Maxime DOYEN",
438 "\nContributors:\n" \
439 "Charles MCGARVEY (Plugin system, Perl support)\n" \
440 "Ga\xc3\xabtan LORIDANT (Maths formulas for charts)\n",
441 NULL
442 };
443
444 /*
445 const gchar *documenters[] = {
446 "Maxime DOYEN",
447 NULL
448 };
449 */
450
451 static const gchar *copyright = "Copyright \xc2\xa9 1995-2017 - Maxime DOYEN";
452
453
454
455 version = g_strdup_printf (PACKAGE_VERSION "\n<small>Running against GTK+ %d.%d.%d</small>",
456 gtk_get_major_version (),
457 gtk_get_minor_version (),
458 gtk_get_micro_version ());
459
460 dialog = gtk_about_dialog_new();
461
462 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(GLOBALS->mainwindow));
463 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
464
465 gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(dialog), g_get_application_name ());
466 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), version);
467 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), copyright);
468 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("Free, easy, personal accounting for everyone"));
469 gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0);
470
471 //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), );
472 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr");
473 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
474
475 gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "homebank");
476
477 pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL);
478 pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL);
479 g_free(pathfilename);
480
481 if( pixbuf )
482 {
483 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf);
484 g_object_unref (pixbuf);
485 }
486
487 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
488 gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists);
489 //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), );
490 //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), );
491
492 g_signal_connect (dialog, "activate-link", G_CALLBACK (activate_url), NULL);
493
494 gtk_dialog_run (GTK_DIALOG (dialog));
495
496 gtk_widget_destroy (dialog);
497
498 g_free(version);
499
500 }
501
502
503 /* hbfile action functions -------------------- */
504 static void ui_mainwindow_action_new(void)
505 {
506 GtkWidget *widget = GLOBALS->mainwindow;
507
508 if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
509 {
510 //clear all, and init GLOBALS->xhb_filepath to default
511 ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE)); // GPOINTER_TO_INT(
512 ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
513
514 ui_start_assistant();
515 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
516 ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
517 ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
518 }
519 }
520
521 static void ui_mainwindow_action_open(void)
522 {
523 ui_mainwindow_open(GLOBALS->mainwindow, NULL);
524 }
525
526 static void ui_mainwindow_action_save(void)
527 {
528 ui_mainwindow_save(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
529 }
530
531 static void ui_mainwindow_action_saveas(void)
532 {
533 ui_mainwindow_save(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
534 }
535
536 static void ui_mainwindow_action_revert(void)
537 {
538 ui_mainwindow_revert(GLOBALS->mainwindow, NULL);
539 }
540
541 static void ui_mainwindow_action_close(void)
542 {
543 GtkWidget *widget = GLOBALS->mainwindow;
544
545 if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
546 {
547 //clear all, and init GLOBALS->xhb_filepath to default
548 ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE));
549 ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
550 }
551
552 }
553
554
555 static void ui_mainwindow_action_quit(void)
556 {
557 gboolean result;
558
559 //gtk_widget_destroy(GLOBALS->mainwindow);
560
561 g_signal_emit_by_name(GLOBALS->mainwindow, "delete-event", NULL, &result);
562
563 //gtk_main_quit();
564 }
565
566 static void ui_mainwindow_action_file_statistics(void)
567 {
568 ui_dialog_file_statistics();
569 }
570
571
572 static void ui_mainwindow_action_pluginprefs(void)
573 {
574 ui_mainwindow_showprefs(PREF_PLUGINS);
575 }
576
577
578 static void ui_mainwindow_action_properties(void)
579 {
580 create_defhbfile_dialog();
581 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
582 }
583
584 static void ui_mainwindow_action_anonymize(void)
585 {
586 gint result;
587 gchar *title;
588 gchar *secondtext;
589
590 title = _("Are you sure you want to anonymize the file?");
591
592 secondtext =
593 _("Proceeding will anonymize any text, \n"
594 "like 'account x', 'payee y', 'memo z', ...");
595
596 result = ui_dialog_msg_confirm_alert(
597 GTK_WINDOW(GLOBALS->mainwindow),
598 title,
599 secondtext,
600 _("_Anonymize")
601 );
602
603 if( result == GTK_RESPONSE_CANCEL )
604 return;
605
606 hbfile_anonymize();
607 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
608 }
609
610
611 static void ui_mainwindow_action_defcurrency(void)
612 {
613 ui_cur_manage_dialog();
614 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
615 }
616
617
618 static void ui_mainwindow_action_defaccount(void)
619 {
620 ui_acc_manage_dialog();
621
622 //our global list has changed, so update the treeview
623 //todo: optimize this, should not call compute balance here
624 account_compute_balances ();
625 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
626
627 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE));
628 }
629
630 static void ui_mainwindow_action_defpayee(void)
631 {
632 ui_pay_manage_dialog();
633 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
634 }
635
636 static void ui_mainwindow_action_defcategory(void)
637 {
638 ui_cat_manage_dialog();
639 //todo:why refresh upcoming here??
640 //ui_mainwindow_populate_upcoming(GLOBALS->mainwindow, NULL);
641 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
642 }
643
644
645 static void ui_mainwindow_defarchive(Archive *arc)
646 {
647 struct hbfile_data *data;
648 GtkTreeModel *model;
649
650 data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
651
652 // upcoming list have direct pointer to the arc (which may have changed)
653 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
654 gtk_list_store_clear (GTK_LIST_STORE(model));
655
656 ui_arc_manage_dialog(arc);
657
658 ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
659
660 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
661 }
662
663
664 static void ui_mainwindow_action_defarchive(void)
665 {
666 ui_mainwindow_defarchive(NULL);
667 }
668
669
670 static void ui_mainwindow_action_defbudget(void)
671 {
672 ui_bud_manage_dialog();
673 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
674 }
675
676
677 static void ui_mainwindow_action_defassign(void)
678 {
679
680 ui_asg_manage_dialog();
681
682 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
683 }
684
685
686 static void ui_mainwindow_action_preferences(void)
687 {
688 ui_mainwindow_showprefs(PREF_GENERAL);
689 }
690
691 static void ui_mainwindow_showprefs(gint page)
692 {
693 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
694
695 defpref_dialog_new(page);
696 if(!PREFS->euro_active)
697 {
698 GtkToggleAction *action = (GtkToggleAction *)gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor");
699
700 gtk_toggle_action_set_active(action, FALSE);
701 ui_mainwindow_action_toggle_minor(action);
702 }
703 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL+UF_REFRESHALL));
704 }
705
706 /* display action */
707
708 static void ui_mainwindow_action_toggle_toolbar(GtkToggleAction *action)
709 {
710 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
711
712 PREFS->wal_toolbar = gtk_toggle_action_get_active(action);
713 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
714 }
715
716 static void ui_mainwindow_action_toggle_upcoming(GtkToggleAction *action)
717 {
718 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
719
720 PREFS->wal_upcoming = gtk_toggle_action_get_active(action);
721 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
722 }
723
724 static void ui_mainwindow_action_toggle_topspending(GtkToggleAction *action)
725 {
726 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
727
728 PREFS->wal_spending = gtk_toggle_action_get_active(action);
729 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
730 }
731
732 static void ui_mainwindow_action_toggle_minor(GtkToggleAction *action)
733 {
734 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
735
736 GLOBALS->minor = gtk_toggle_action_get_active(action);
737
738 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
739 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc));
740
741 // top spending
742 gtk_chart_show_minor(GTK_CHART(data->RE_pie), GLOBALS->minor);
743
744 ui_panel_topspending_update(data->window, data);
745
746 }
747
748 static void ui_mainwindow_action_showtransactions(void)
749 {
750 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
751 GtkWidget *window;
752
753 //todo:change this
754 if( data->acc )
755 {
756 if( data->acc->window == NULL )
757 {
758 window = register_panel_window_new(data->acc->key, data->acc);
759 register_panel_window_init(window, NULL);
760 }
761 else
762 {
763 if(GTK_IS_WINDOW(data->acc->window))
764 gtk_window_present(data->acc->window);
765
766 }
767 }
768 }
769
770
771 static void ui_mainwindow_action_addtransactions(void)
772 {
773 ui_mainwindow_addtransactions(GLOBALS->mainwindow, NULL);
774 }
775
776 static void ui_mainwindow_action_checkscheduled(void)
777 {
778 ui_mainwindow_scheduled_postall(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
779 }
780
781 static void ui_mainwindow_action_statistic(void)
782 {
783 ui_repdist_window_new();
784 }
785
786 static void ui_mainwindow_action_trendtime(void)
787 {
788 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
789
790 ui_reptime_window_new(data->acc != NULL ? data->acc->key : 0);
791 }
792
793 static void ui_mainwindow_action_budget(void)
794 {
795 repbudget_window_new();
796 }
797
798 static void ui_mainwindow_action_balance(void)
799 {
800 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
801
802 repbalance_window_new(data->acc != NULL ? data->acc->key : 0);
803 }
804
805 static void ui_mainwindow_action_vehiclecost(void)
806 {
807 repcost_window_new();
808 }
809
810 static void ui_mainwindow_action_import(GtkAction *action)
811 {
812 const gchar *name;
813 gint filetype = FILETYPE_UNKNOW;
814
815 name = gtk_action_get_name(action);
816
817 if( g_str_has_suffix (name, "QIF"))
818 filetype= FILETYPE_QIF;
819 else
820 if( g_str_has_suffix (name, "OFX"))
821 filetype= FILETYPE_OFX;
822 else
823 if( g_str_has_suffix (name, "CSV"))
824 filetype= FILETYPE_CSV_HB;
825
826 DB( g_print("action %s type=%d\n", name, filetype) );
827
828 ui_import_assistant_new(filetype);
829
830 }
831
832
833 static void ui_mainwindow_action_about(void)
834 {
835 hbfile_about();
836
837
838 }
839
840 static void ui_mainwindow_action_export(void)
841 {
842 gchar *filename;
843
844 if( ui_file_chooser_qif(NULL, &filename) == TRUE )
845 {
846 hb_export_qif_account_all(filename);
847 g_free( filename );
848 }
849 }
850
851 static void ui_mainwindow_action_help(void)
852 {
853 gchar *link;
854
855 link = g_build_filename("file:///", homebank_app_get_help_dir(), HOMEBANK_URL_HELP, NULL );
856 homebank_util_url_show (link);
857
858 g_free(link);
859 }
860
861
862 //todo: move this to a ui-assist-welcome.c
863
864 static void ui_mainwindow_action_help_welcome1 (GtkButton *button, gpointer user_data)
865 {
866 gtk_dialog_response (GTK_DIALOG(user_data), 1);
867 }
868
869 static void ui_mainwindow_action_help_welcome2 (GtkButton *button, gpointer user_data)
870 {
871 gtk_dialog_response (GTK_DIALOG(user_data), 2);
872 }
873
874 static void ui_mainwindow_action_help_welcome3 (GtkButton *button, gpointer user_data)
875 {
876 gtk_dialog_response (GTK_DIALOG(user_data), 3);
877 }
878
879 static void ui_mainwindow_action_help_welcome4 (GtkButton *button, gpointer user_data)
880 {
881 gtk_dialog_response (GTK_DIALOG(user_data), 4);
882 }
883
884 static void ui_mainwindow_action_help_welcome5 (GtkButton *button, gpointer user_data)
885 {
886 gtk_dialog_response (GTK_DIALOG(user_data), 5);
887 }
888
889 void ui_mainwindow_action_help_welcome(void)
890 {
891 GtkWidget *dialog, *content_area;
892 GtkWidget *mainvbox, *widget, *label;
893
894 dialog = gtk_dialog_new_with_buttons (_("Welcome to HomeBank"),
895 GTK_WINDOW(GLOBALS->mainwindow),
896 0,
897 _("_Close"),
898 GTK_RESPONSE_ACCEPT,
899 NULL);
900
901 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
902
903 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
904 gtk_box_pack_start (GTK_BOX (content_area), mainvbox, FALSE, FALSE, 0);
905 gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
906
907 label = make_label (_("HomeBank"), 0, 0);
908 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
909 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
910
911 label = make_label (_("Free, easy, personal accounting for everyone"), 0, 0);
912 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
913
914 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
915 gtk_box_pack_start (GTK_BOX (content_area), widget, FALSE, FALSE, 0);
916
917 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
918 gtk_box_pack_start (GTK_BOX (content_area), mainvbox, TRUE, TRUE, 0);
919 gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
920
921 label = make_label (_("What do you want to do:"), 0, 0);
922 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
923 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
924
925 widget = gtk_button_new_with_mnemonic(_("Read HomeBank _Manual"));
926 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
927 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog);
928
929 widget = gtk_button_new_with_mnemonic(_("Configure _preferences"));
930 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
931 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog);
932
933 widget = gtk_button_new_with_mnemonic(_("Create a _new file"));
934 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
935 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome3), dialog);
936
937 widget = gtk_button_new_with_mnemonic(_("_Open an existing file"));
938 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
939 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome4), dialog);
940
941 widget = gtk_button_new_with_mnemonic(_("Open the _example file"));
942 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
943 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome5), dialog);
944
945 //connect all our signals
946 g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &dialog);
947
948 gtk_widget_show_all (dialog);
949
950 //wait for the user
951 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
952
953 // cleanup and destroy
954 gtk_widget_destroy (dialog);
955
956 // do appropriate action
957 switch(result)
958 {
959 case 1:
960 ui_mainwindow_action_help();
961 break;
962 case 2:
963 ui_mainwindow_action_preferences();
964 break;
965 case 3:
966 ui_mainwindow_action_new();
967 break;
968 case 4:
969 ui_mainwindow_action_open();
970 break;
971 case 5:
972 hbfile_change_filepath(g_build_filename(homebank_app_get_datas_dir(), "example.xhb", NULL));
973 ui_mainwindow_open_internal(GLOBALS->mainwindow, NULL);
974 break;
975 }
976
977 }
978
979
980
981 static void ui_mainwindow_action_help_online(void)
982 {
983 const gchar *link = HOMEBANK_URL_HELP_ONLINE;
984
985 homebank_util_url_show (link);
986
987 }
988
989 static void ui_mainwindow_action_help_translate(void)
990 {
991 const gchar *link = HOMEBANK_URL_HELP_TRANSLATE;
992
993 homebank_util_url_show (link);
994
995 }
996
997 static void ui_mainwindow_action_help_problem(void)
998 {
999 const gchar *link = HOMEBANK_URL_HELP_PROBLEM;
1000
1001 homebank_util_url_show (link);
1002
1003 }
1004
1005
1006
1007
1008 /* hbfile functions -------------------- */
1009
1010
1011
1012
1013 /*
1014 **
1015 */
1016 static void ui_mainwindow_selection(GtkTreeSelection *treeselection, gpointer user_data)
1017 {
1018 ui_mainwindow_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(UF_SENSITIVE));
1019 }
1020
1021
1022 static void ui_mainwindow_close_openbooks(void)
1023 {
1024 GList *lacc, *elt;
1025
1026 DB( g_print("\n[ui-mainwindow] close openbooks\n") );
1027
1028 lacc = elt = g_hash_table_get_values(GLOBALS->h_acc);
1029 while (elt != NULL)
1030 {
1031 Account *item = elt->data;
1032
1033 if(item->window)
1034 {
1035 gtk_widget_destroy(GTK_WIDGET(item->window));
1036 item->window = NULL;
1037 }
1038
1039 elt = g_list_next(elt);
1040 }
1041 g_list_free(lacc);
1042
1043 }
1044
1045
1046
1047 /*
1048 **
1049 */
1050 void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data)
1051 {
1052 struct hbfile_data *data;
1053 gboolean file_clear = GPOINTER_TO_INT(user_data);
1054
1055 DB( g_print("\n[ui-mainwindow] clear\n") );
1056
1057 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1058
1059 // Close opened account window
1060 // Clear TreeView
1061 ui_mainwindow_close_openbooks();
1062 gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
1063 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc))));
1064 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
1065
1066 data->showall = FALSE;
1067
1068 hbfile_cleanup(file_clear);
1069 hbfile_setup(file_clear);
1070
1071 }
1072
1073
1074 /*
1075 ** add some transactions directly
1076 */
1077 void ui_mainwindow_addtransactions(GtkWidget *widget, gpointer user_data)
1078 {
1079 struct hbfile_data *data;
1080 GtkWidget *window;
1081 gint result = 1;
1082 guint32 date;
1083 gint account, count;
1084
1085 DB( g_print("\n[ui-mainwindow] add transactions\n") );
1086
1087 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1088
1089 /* init the transaction */
1090 date = homebank_app_date_get_julian();
1091
1092 //#1656531
1093 account = 0;
1094 if(data->acc != NULL)
1095 account = data->acc->key;
1096
1097 window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE);
1098 count = 0;
1099 while(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP)
1100 {
1101 Transaction *ope;
1102
1103 /* fill in the transaction */
1104 if( result == GTK_RESPONSE_ADD )
1105 {
1106 ope = da_transaction_malloc();
1107 ope->date = date;
1108 ope->kacc = account;
1109
1110 if( PREFS->heritdate == FALSE ) //fix: 318733
1111 ope->date = GLOBALS->today;
1112 }
1113
1114 // normally we can't be in addkeep without initialized ope with add
1115
1116 deftransaction_set_transaction(window, ope);
1117
1118 result = gtk_dialog_run (GTK_DIALOG (window));
1119
1120 DB( g_print(" - dialog result is %d\n", result) );
1121
1122 if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
1123 {
1124 deftransaction_get(window, NULL);
1125 transaction_add(ope, NULL, ope->kacc);
1126
1127 DB( g_print(" - added 1 transaction to %d\n", ope->kacc) );
1128
1129 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
1130
1131 count++;
1132 //todo: still usefull ? store last date
1133 date = ope->date;
1134 }
1135
1136 if( result == GTK_RESPONSE_ADD )
1137 {
1138 da_transaction_free(ope);
1139 ope = NULL;
1140 }
1141
1142 }
1143
1144
1145 deftransaction_dispose(window, NULL);
1146 gtk_widget_destroy (window);
1147
1148 /* todo optimize this */
1149 if(count > 0)
1150 {
1151 GLOBALS->changes_count += count;
1152 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
1153 }
1154 }
1155
1156 struct tmptop
1157 {
1158 guint32 key;
1159 gdouble value;
1160 };
1161
1162
1163 #define MAX_TOPSPENDING 5
1164
1165
1166 static gint tmptop_compare_func(struct tmptop *tt1, struct tmptop *tt2)
1167 {
1168 return tt1->value > tt2->value ? 1 : -1;
1169 }
1170
1171
1172 static void ui_panel_topspending_update(GtkWidget *widget, gpointer user_data)
1173 {
1174 struct hbfile_data *data;
1175 GtkTreeModel *model;
1176 gchar *title;
1177 gchar strbuffer[G_ASCII_DTOSTR_BUF_SIZE];
1178
1179 DB( g_print("\n[ui-mainwindow] topspending_update\n") );
1180
1181 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1182
1183 hb_strfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, data->toptotal, GLOBALS->kcur, GLOBALS->minor);
1184 //hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->kcur, GLOBALS->minor);
1185 title = g_strdup_printf("%s %s", _("Top spending"), strbuffer);
1186
1187 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top));
1188
1189 gtk_chart_set_color_scheme(GTK_CHART(data->RE_pie), PREFS->report_color_scheme);
1190 gtk_chart_set_currency(GTK_CHART(data->RE_pie), GLOBALS->kcur);
1191 gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, title, NULL);
1192
1193 g_free(title);
1194
1195 //future usage
1196 gchar *fu = _("Top %d spending"); title = fu;
1197 }
1198
1199
1200 static void ui_mainwindow_populate_topspending(GtkWidget *widget, gpointer user_data)
1201 {
1202 struct hbfile_data *data;
1203 GtkTreeModel *model;
1204 GtkTreeIter iter;
1205 GList *list;
1206 gint type, range;
1207 guint n_result, i, n_items;
1208 GArray *garray;
1209 gdouble total, other;
1210 Account *acc;
1211
1212
1213 DB( g_print("\n[ui-mainwindow] populate_topspending\n") );
1214
1215 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1216
1217 type = radio_get_active(GTK_CONTAINER(data->RA_type));
1218 range = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range));
1219
1220 DB( g_print(" - type=%d, range=%d\n", type, range) );
1221 DB( g_print(" - pref range=%d\n", PREFS->date_range_wal) );
1222
1223 if(range == FLT_RANGE_OTHER)
1224 return;
1225
1226 filter_preset_daterange_set(data->filter, range, 0);
1227
1228
1229 n_result = da_cat_get_max_key() + 1;
1230 total = 0.0;
1231
1232 DB( g_print(" - max key is %d\n", n_result) );
1233
1234 /* allocate some memory */
1235 garray = g_array_sized_new(FALSE, FALSE, sizeof(struct tmptop), n_result);
1236
1237 if(garray)
1238 {
1239 struct tmptop zero = { .key=0, .value=0.0 };
1240 GQueue *txn_queue;
1241
1242 //DB( g_print(" - array length=%d\n", garray->len) );
1243
1244 for(i=0 ; i<n_result ; i++)
1245 {
1246 g_array_append_vals(garray, &zero, 1);
1247 //g_array_insert_vals(garray, i, &zero, 1);
1248
1249 //struct tmptop *tt = &g_array_index (garray, struct tmptop, i);
1250 //DB( g_print("%4d, %4d %f\n", i, tt->key, tt->value) );
1251 }
1252
1253 //DB( g_print("\n - end array length=%d\n", garray->len) );
1254
1255 //todo: not ideal, has ot force to get_acc for each txn below
1256 txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
1257
1258 /* compute the results */
1259 list = g_queue_peek_head_link(txn_queue);
1260 while (list != NULL)
1261 {
1262 Transaction *ope = list->data;
1263
1264 //DB( g_print(" - eval txn: '%s', cat=%d ==> flt-test=%d\n", ope->wording, ope->kcat, filter_test(data->filter, ope)) );
1265
1266 if( !(ope->paymode == PAYMODE_INTXFER) )
1267 {
1268 guint32 pos = 0;
1269 gdouble trn_amount;
1270
1271 //todo: optimize here
1272 trn_amount = ope->amount;
1273 acc = da_acc_get(ope->kacc);
1274 if(acc)
1275 trn_amount = hb_amount_base(ope->amount, acc->kcur);
1276
1277 if( ope->flags & OF_SPLIT )
1278 {
1279 guint nbsplit = da_splits_count(ope->splits);
1280 Split *split;
1281 struct tmptop *item;
1282
1283 for(i=0;i<nbsplit;i++)
1284 {
1285 split = ope->splits[i];
1286 pos = category_report_id(split->kcat, type);
1287
1288 trn_amount = hb_amount_base(split->amount, acc->kcur);
1289 //trn_amount = split->amount;
1290 //#1297054 if( trn_amount < 0 ) {
1291 item = &g_array_index (garray, struct tmptop, pos);
1292 item->key = pos;
1293 item->value += trn_amount;
1294 //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) );
1295 //}
1296 }
1297 }
1298 else
1299 {
1300 struct tmptop *item;
1301
1302 pos = category_report_id(ope->kcat, type);
1303
1304 //#1297054 if( trn_amount < 0 ) {
1305 item = &g_array_index (garray, struct tmptop, pos);
1306 item->key = pos;
1307 item->value += trn_amount;
1308 //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) );
1309 //}
1310 }
1311
1312
1313 }
1314
1315 list = g_list_next(list);
1316 }
1317
1318 g_queue_free (txn_queue);
1319
1320 // we need to sort this and limit before
1321 g_array_sort(garray, (GCompareFunc)tmptop_compare_func);
1322
1323 n_items = MIN(garray->len,MAX_TOPSPENDING);
1324 other = 0;
1325 for(i=0 ; i<garray->len ; i++)
1326 {
1327 struct tmptop *item;
1328
1329 item = &g_array_index (garray, struct tmptop, i);
1330 if(item->value < 0)
1331 {
1332 total += item->value;
1333
1334 if(i >= n_items)
1335 other += item->value;
1336
1337 DB( g_print(" - %d : k='%d' v='%f' t='%f'\n", i, item->key, item->value, total) );
1338
1339 }
1340 }
1341
1342 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top));
1343 gtk_list_store_clear (GTK_LIST_STORE(model));
1344 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
1345 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_top), NULL); /* Detach model from view */
1346
1347 /* insert into the treeview */
1348 for(i=0 ; i<MIN(garray->len,MAX_TOPSPENDING) ; i++)
1349 {
1350 gchar *name;
1351 Category *entry;
1352 struct tmptop *item;
1353 gdouble value;
1354
1355 item = &g_array_index (garray, struct tmptop, i);
1356
1357 if(!item->value) continue;
1358
1359 value = hb_amount_round(item->value, 2);
1360 entry = da_cat_get(item->key);
1361 if(entry == NULL) continue;
1362
1363 name = entry->key == 0 ? _("(no category)") : da_cat_get_fullname(entry);
1364
1365 // append test
1366 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1367 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1368 LST_TOPSPEND_ID, i,
1369 LST_TOPSPEND_KEY, 0,
1370 LST_TOPSPEND_NAME, name,
1371 LST_TOPSPEND_AMOUNT, value,
1372 //LST_TOPSPEND_RATE, (gint)(((ABS(value)*100)/ABS(total)) + 0.5),
1373 -1);
1374
1375 }
1376
1377 // append test
1378 if(ABS(other) > 0)
1379 {
1380 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1381 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1382 LST_TOPSPEND_ID, n_items,
1383 LST_TOPSPEND_KEY, 0,
1384 LST_TOPSPEND_NAME, _("Other"),
1385 LST_TOPSPEND_AMOUNT, other,
1386 //LST_TOPSPEND_RATE, (gint)(((ABS(other)*100)/ABS(total)) + 0.5),
1387 -1);
1388 }
1389
1390 /* Re-attach model to view */
1391 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_top), model);
1392 g_object_unref(model);
1393
1394
1395 // update chart and widgets
1396 {
1397 gchar *daterange;
1398
1399 data->toptotal = total;
1400 ui_panel_topspending_update(widget, data);
1401
1402 daterange = filter_daterange_text_get(data->filter);
1403 gtk_widget_set_tooltip_markup(GTK_WIDGET(data->CY_range), daterange);
1404 g_free(daterange);
1405 }
1406 }
1407
1408 /* free our memory */
1409 g_array_free (garray, TRUE);
1410
1411 }
1412
1413
1414 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1415 /* scheduled */
1416 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1417 static Archive *
1418 ui_mainwindow_scheduled_get_selected_item(GtkTreeView *treeview)
1419 {
1420 GtkTreeSelection *treeselection;
1421 GtkTreeModel *model;
1422 GtkTreeIter iter;
1423
1424 treeselection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
1425 if( gtk_tree_selection_get_selected(treeselection, &model, &iter) )
1426 {
1427 Archive *arc;
1428
1429 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPUPC_DATAS, &arc, -1);
1430 return arc;
1431 }
1432
1433 return NULL;
1434 }
1435
1436
1437 static void ui_mainwindow_scheduled_onRowActivated (GtkTreeView *treeview,
1438 GtkTreePath *path,
1439 GtkTreeViewColumn *col,
1440 gpointer userdata)
1441 {
1442 //struct hbfile_data *data;
1443 Archive *arc;
1444
1445 DB( g_print ("\n[ui-mainwindow] A scheduled row has been double-clicked!\n") );
1446
1447 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(treeview, GTK_TYPE_WINDOW)), "inst_data");
1448
1449 arc = ui_mainwindow_scheduled_get_selected_item(treeview);
1450 ui_mainwindow_defarchive(arc);
1451 }
1452
1453
1454 static void ui_mainwindow_scheduled_do_post(Archive *arc, gboolean doedit, gpointer user_data)
1455 {
1456 struct hbfile_data *data = user_data;
1457 GtkWidget *window;
1458 gint result;
1459 Transaction *txn;
1460
1461 window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, TRUE);
1462
1463 /* fill in the transaction */
1464 txn = da_transaction_malloc();
1465 da_transaction_init_from_template(txn, arc);
1466 txn->date = scheduled_get_postdate(arc, arc->nextdate);
1467
1468 deftransaction_set_transaction(window, txn);
1469
1470 result = gtk_dialog_run (GTK_DIALOG (window));
1471
1472 DB( g_print(" - dialog result is %d\n", result) );
1473
1474 if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
1475 {
1476 deftransaction_get(window, NULL);
1477 transaction_add(txn, NULL, txn->kacc);
1478 GLOBALS->changes_count++;
1479
1480 scheduled_date_advance(arc);
1481
1482 DB( g_print(" - added 1 transaction to %d\n", txn->kacc) );
1483 }
1484
1485 da_transaction_free(txn);
1486
1487 deftransaction_dispose(window, NULL);
1488 gtk_widget_destroy (window);
1489
1490 }
1491
1492
1493 static void ui_mainwindow_scheduled_editpost_cb(GtkWidget *widget, gpointer user_data)
1494 {
1495 struct hbfile_data *data = user_data;
1496
1497 Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
1498
1499 if( (arc != NULL) )
1500 {
1501 ui_mainwindow_scheduled_do_post(arc, TRUE, data);
1502 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
1503 }
1504 }
1505
1506
1507 static void ui_mainwindow_scheduled_post_cb(GtkWidget *widget, gpointer user_data)
1508 {
1509 struct hbfile_data *data = user_data;
1510
1511 Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
1512
1513 if( (arc != NULL) )
1514 {
1515 if( scheduled_is_postable(arc) )
1516 {
1517 Transaction *txn = da_transaction_malloc ();
1518
1519 da_transaction_init_from_template(txn, arc);
1520 txn->date = scheduled_get_postdate(arc, arc->nextdate);
1521 transaction_add(txn, NULL, 0);
1522
1523 GLOBALS->changes_count++;
1524 scheduled_date_advance(arc);
1525
1526 da_transaction_free (txn);
1527 }
1528 else
1529 {
1530 ui_mainwindow_scheduled_do_post(arc, FALSE, data);
1531 }
1532
1533 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
1534 }
1535 }
1536
1537
1538 static void ui_mainwindow_scheduled_skip_cb(GtkWidget *widget, gpointer user_data)
1539 {
1540 struct hbfile_data *data = user_data;
1541
1542 Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
1543 if( (arc != NULL) && (arc->flags & OF_AUTO) )
1544 {
1545 GLOBALS->changes_count++;
1546 scheduled_date_advance(arc);
1547
1548 ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
1549 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
1550 }
1551 }
1552
1553
1554
1555 static void ui_mainwindow_scheduled_update(GtkWidget *widget, gpointer user_data)
1556 {
1557 struct hbfile_data *data;
1558 //gint filter;
1559
1560 DB( g_print("\n[ui-mainwindow] scheduled update\n") );
1561
1562 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1563
1564 //filter = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_sched_filter));
1565
1566 Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
1567
1568 if(arc)
1569 {
1570 DB( g_print("archive is %s\n", arc->wording) );
1571
1572 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), TRUE);
1573 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE);
1574 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), TRUE);
1575 }
1576 else
1577 {
1578 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), FALSE);
1579 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE);
1580 gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), FALSE);
1581 }
1582
1583 }
1584
1585
1586
1587 static void ui_mainwindow_scheduled_selection_cb(GtkTreeSelection *treeselection, gpointer user_data)
1588 {
1589
1590
1591 ui_mainwindow_scheduled_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(UF_SENSITIVE));
1592 }
1593
1594
1595
1596 /*
1597 ** called after load, importamiga, on demand
1598 */
1599 void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data)
1600 {
1601 //struct hbfile_data *data;
1602 gint count;
1603 gint usermode = GPOINTER_TO_INT(user_data);
1604
1605 DB( g_print("\n[ui-mainwindow] check scheduled\n") );
1606
1607 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1608
1609 count = scheduled_post_all_pending();
1610
1611 //inform the user
1612 if(usermode == TRUE)
1613 {
1614 gchar *txt;
1615
1616 //#125534
1617 if( count > 0 )
1618 {
1619 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_REFRESHALL));
1620 }
1621
1622 if(count == 0)
1623 txt = _("No transaction to add");
1624 else
1625 txt = _("transaction added: %d");
1626
1627 ui_dialog_msg_infoerror(GTK_WINDOW(GLOBALS->mainwindow), GTK_MESSAGE_INFO,
1628 _("Check scheduled transactions result"),
1629 txt,
1630 count);
1631 }
1632
1633 }
1634
1635
1636 static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data)
1637 {
1638 struct hbfile_data *data;
1639 GtkTreeModel *model;
1640 GtkTreeIter iter;
1641 GList *list;
1642 gdouble totexp = 0;
1643 gdouble totinc = 0;
1644 gint count = 0;
1645 gchar buffer[256];
1646 guint32 maxpostdate;
1647 GDate *date;
1648 //Account *acc;
1649
1650 DB( g_print("\n[ui-mainwindow] scheduled populate list\n") );
1651
1652 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1653
1654 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
1655 gtk_list_store_clear (GTK_LIST_STORE(model));
1656
1657 homebank_app_date_get_julian();
1658
1659 maxpostdate = scheduled_date_get_post_max();
1660
1661 date = g_date_new_julian (maxpostdate);
1662 g_date_strftime (buffer, 256-1, PREFS->date_format, date);
1663 g_date_free(date);
1664
1665 gtk_label_set_text(GTK_LABEL(data->LB_maxpostdate), buffer);
1666
1667
1668 list = g_list_first(GLOBALS->arc_list);
1669 while (list != NULL)
1670 {
1671 Archive *arc = list->data;
1672 Account *acc;
1673 gdouble inc, exp;
1674 guint nbdays, nblate;
1675
1676 if((arc->flags & OF_AUTO) ) //&& arc->kacc > 0)
1677 {
1678 count++;
1679 nbdays = arc->nextdate - maxpostdate;
1680 nblate = scheduled_get_latepost_count(arc, GLOBALS->today);
1681
1682 DB( g_print(" - append '%s' : %d\n", arc->wording, nbdays) );
1683
1684 if(arc->flags & OF_INCOME)
1685 {
1686 inc = arc->amount;
1687 exp = 0.0;
1688 }
1689 else
1690 {
1691 exp = arc->amount;
1692 inc = 0.0;
1693 }
1694
1695 /* insert normal txn */
1696 acc = da_acc_get(arc->kacc);
1697 if( acc)
1698 {
1699 totinc += hb_amount_base(inc, acc->kcur);
1700 totexp += hb_amount_base(exp, acc->kcur);
1701 }
1702 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1703 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1704 LST_DSPUPC_DATAS, arc,
1705 LST_DSPUPC_ACCOUNT, acc,
1706 LST_DSPUPC_WORDING, arc->wording,
1707 LST_DSPUPC_EXPENSE, exp,
1708 LST_DSPUPC_INCOME, inc,
1709 LST_DSPUPC_REMAINING, nbdays,
1710 LST_DSPUPC_NB_LATE, nblate,
1711 -1);
1712
1713 /* insert internal xfer txn : 1378836 */
1714 if(arc->paymode == PAYMODE_INTXFER)
1715 {
1716 acc = da_acc_get(arc->kxferacc);
1717 if( acc)
1718 {
1719 totinc += hb_amount_base(-inc, acc->kcur);
1720 totexp += hb_amount_base(-exp, acc->kcur);
1721 }
1722 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1723 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1724 LST_DSPUPC_DATAS, arc,
1725 LST_DSPUPC_ACCOUNT, acc,
1726 LST_DSPUPC_WORDING, arc->wording,
1727 LST_DSPUPC_EXPENSE, -inc,
1728 LST_DSPUPC_INCOME, -exp,
1729 LST_DSPUPC_REMAINING, nbdays,
1730 LST_DSPUPC_NB_LATE, nblate,
1731 -1);
1732 }
1733
1734 }
1735 list = g_list_next(list);
1736 }
1737
1738 // insert total
1739 if(count > 0 )
1740 {
1741 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1742 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1743 LST_DSPUPC_DATAS, NULL,
1744 LST_DSPUPC_ACCOUNT, NULL,
1745 LST_DSPUPC_WORDING, _("Total"),
1746 LST_DSPUPC_EXPENSE, totexp,
1747 LST_DSPUPC_INCOME, totinc,
1748 -1);
1749 }
1750
1751
1752 ui_mainwindow_scheduled_update(widget, NULL);
1753
1754 }
1755
1756
1757
1758
1759 /*
1760 **
1761 */
1762 void ui_mainwindow_open(GtkWidget *widget, gpointer user_data)
1763 {
1764 //struct hbfile_data *data;
1765 gchar *filename = NULL;
1766
1767 DB( g_print("\n[ui-mainwindow] open\n") );
1768
1769 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1770
1771 if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
1772 {
1773 if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename) == TRUE)
1774 {
1775 hbfile_change_filepath(filename);
1776
1777 ui_mainwindow_open_internal(widget, NULL);
1778
1779
1780 }
1781 }
1782 }
1783
1784 /*
1785 * open the file stored in GLOBALS->xhb_filepath
1786 */
1787 void ui_mainwindow_open_internal(GtkWidget *widget, gpointer user_data)
1788 {
1789 struct hbfile_data *data;
1790 gint r;
1791
1792 DB( g_print("\n[ui-mainwindow] open internal\n") );
1793
1794 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1795
1796 DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) );
1797
1798 if( GLOBALS->xhb_filepath != NULL )
1799 {
1800 ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
1801 GLOBALS->hbfile_is_new = FALSE;
1802
1803 r = homebank_load_xml(GLOBALS->xhb_filepath);
1804 if( r == XML_OK )
1805 {
1806 DB( g_print(" - file loaded ok : rcode=%d\n", r) );
1807
1808 hbfile_file_hasbackup(GLOBALS->xhb_filepath);
1809
1810 if(PREFS->appendscheduled)
1811 scheduled_post_all_pending();
1812
1813 if(PREFS->do_update_currency)
1814 ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow));
1815
1816 homebank_lastopenedfiles_save();
1817
1818 //todo: delete this after computing done at xml read
1819 account_compute_balances();
1820
1821 ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath);
1822 }
1823 else
1824 {
1825 gchar *msg = _("Unknow error");
1826
1827 switch(r)
1828 {
1829 case XML_IO_ERROR:
1830 msg = _("I/O error for file '%s'.");
1831 break;
1832 case XML_FILE_ERROR:
1833 msg = _("The file '%s' is not a valid HomeBank file.");
1834 break;
1835 case XML_VERSION_ERROR:
1836 msg = _("The file '%s' was saved with a higher version of HomeBank\nand cannot be loaded by the current version.");
1837 break;
1838 }
1839
1840 ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
1841 _("File error"),
1842 msg,
1843 GLOBALS->xhb_filepath
1844 );
1845
1846 ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
1847
1848 }
1849
1850 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
1851 ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
1852 ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
1853 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
1854 }
1855
1856
1857 }
1858
1859 /*
1860 **
1861 */
1862 void ui_mainwindow_save(GtkWidget *widget, gpointer user_data)
1863 {
1864 struct hbfile_data *data;
1865 gboolean saveas = GPOINTER_TO_INT(user_data);
1866 gchar *filename = NULL;
1867 gint r = XML_UNSET;
1868
1869 DB( g_print("\n[ui-mainwindow] save\n") );
1870
1871 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1872
1873 if( GLOBALS->hbfile_is_new == TRUE )
1874 saveas = 1;
1875
1876 if(saveas == 1)
1877 {
1878 if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename) == TRUE)
1879 {
1880 DB( g_print(" + should save as '%s'\n", filename) );
1881 homebank_file_ensure_xhb(filename);
1882 homebank_backup_current_file();
1883 r = homebank_save_xml(GLOBALS->xhb_filepath);
1884 GLOBALS->hbfile_is_new = FALSE;
1885 }
1886 else
1887 return;
1888 }
1889 else
1890 {
1891 DB( g_print(" + should quick save %s\n", GLOBALS->xhb_filepath) );
1892 homebank_file_ensure_xhb(NULL);
1893 homebank_backup_current_file();
1894 r = homebank_save_xml(GLOBALS->xhb_filepath);
1895 }
1896
1897
1898 if(r == XML_OK)
1899 {
1900 GLOBALS->changes_count = 0;
1901 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
1902 }
1903 else
1904 {
1905 gchar *msg = _("I/O error for file '%s'.");
1906
1907 ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
1908 _("File error"),
1909 msg,
1910 GLOBALS->xhb_filepath
1911 );
1912
1913 }
1914
1915
1916 }
1917
1918
1919 static void ui_panel_accounts_expand_all(GtkWidget *widget, gpointer user_data)
1920 {
1921 struct hbfile_data *data;
1922
1923 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1924 gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
1925 }
1926
1927
1928 static void ui_panel_accounts_collapse_all(GtkWidget *widget, gpointer user_data)
1929 {
1930 struct hbfile_data *data;
1931
1932 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1933 gtk_tree_view_collapse_all(GTK_TREE_VIEW(data->LV_acc));
1934 }
1935
1936
1937
1938 static GHashTable *ui_panel_accounts_groups_get(GList *lacc, gint groupby, gboolean showall)
1939 {
1940 GHashTable *hash;
1941 GList *elt;
1942 gchar *groupname;
1943 gint nballoc;
1944
1945 nballoc = da_acc_length ();
1946 hash = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
1947 elt = g_list_first(lacc);
1948 while (elt != NULL)
1949 {
1950 Account *acc = elt->data;
1951 GPtrArray *group;
1952
1953 if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
1954 {
1955 if( groupby == DSPACC_GROUP_BY_BANK )
1956 {
1957 groupname = _("(no institution)");
1958 if( (acc->bankname != NULL) && strlen(acc->bankname) > 0 )
1959 groupname = acc->bankname;
1960 }
1961 else
1962 {
1963 //pre 5.1.3 historical by type display
1964 groupname = _(CYA_ACC_TYPE[acc->type]);
1965 }
1966
1967 if( g_hash_table_contains(hash, groupname) == FALSE )
1968 {
1969 g_hash_table_insert(hash, g_strdup(groupname), g_ptr_array_sized_new(nballoc) );
1970 //DB( g_print(" - type hash insert '%s' = %d\n", groupname, inserted) );
1971 }
1972
1973 group = g_hash_table_lookup(hash, groupname);
1974 if( group != NULL )
1975 {
1976 g_ptr_array_add(group, (gpointer)acc);
1977 DB( g_print(" -- add '%s' to group '%s'\n", acc->name, groupname) );
1978 }
1979 }
1980 elt = g_list_next(elt);
1981 }
1982
1983 return hash;
1984 }
1985
1986
1987
1988
1989
1990
1991 void ui_mainwindow_populate_accounts(GtkWidget *widget, gpointer user_data)
1992 {
1993 struct hbfile_data *data;
1994 GtkTreeModel *model;
1995 GtkTreeIter iter1, child_iter;
1996 GList *lacc, *elt;
1997 Account *acc;
1998 guint j, nbtype;
1999 gdouble gtbank, gttoday, gtfuture;
2000
2001 GHashTable *h_group;
2002 GHashTableIter grp_iter;
2003 gpointer key, value;
2004
2005 DB( g_print("\n[ui-mainwindow] populate accounts\n") );
2006
2007 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
2008
2009 /* here we create a count and a list of every account pointer by type */
2010 lacc = elt = g_hash_table_get_values(GLOBALS->h_acc);
2011
2012 h_group = ui_panel_accounts_groups_get(lacc, PREFS->pnl_acc_show_by, data->showall);
2013 g_list_free(lacc);
2014
2015
2016 gtbank = gttoday = gtfuture = 0;
2017
2018 DB( g_print(" populate listview\n") );
2019
2020 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc));
2021 gtk_tree_store_clear (GTK_TREE_STORE(model));
2022
2023 nbtype = 0;
2024 g_hash_table_iter_init (&grp_iter, h_group);
2025 while (g_hash_table_iter_next (&grp_iter, &key, &value))
2026 {
2027 GPtrArray *gpa = value;
2028 gdouble tbank, ttoday, tfuture;
2029
2030 if(gpa != NULL)
2031 {
2032 nbtype++;
2033 //1: Header: Bank, Cash, ...
2034 //DB( g_print(" - append type '%s'\n", CYA_ACC_TYPE[i]) );
2035 DB( g_print("\n - append type '%d'\n", key) );
2036
2037 gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL);
2038 gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
2039 LST_DSPACC_DATATYPE, DSPACC_TYPE_HEADER,
2040 LST_DSPACC_NAME, key,
2041 -1);
2042
2043 tbank = ttoday = tfuture = 0;
2044
2045 //2: Accounts for real
2046 for(j=0;j<gpa->len;j++)
2047 {
2048 acc = g_ptr_array_index(gpa, j);
2049
2050 //tbank += acc->bal_bank;
2051 //ttoday += acc->bal_today;
2052 //tfuture += acc->bal_future;
2053 tbank += hb_amount_base(acc->bal_bank, acc->kcur);
2054 ttoday += hb_amount_base(acc->bal_today, acc->kcur);
2055 tfuture += hb_amount_base(acc->bal_future, acc->kcur);
2056
2057 DB( g_print(" - insert '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) );
2058
2059 gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1);
2060 gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter,
2061 LST_DSPACC_DATAS, acc,
2062 LST_DSPACC_DATATYPE, DSPACC_TYPE_NORMAL,
2063 LST_DSPACC_BANK, acc->bal_bank,
2064 LST_DSPACC_TODAY, acc->bal_today,
2065 LST_DSPACC_FUTURE, acc->bal_future,
2066 -1);
2067 }
2068
2069 if(gpa->len > 1)
2070 {
2071 DB( g_print(" - type totals :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
2072
2073 // insert the total line
2074 gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1);
2075 gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter,
2076 LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL,
2077 LST_DSPACC_NAME, _("Total"),
2078 LST_DSPACC_BANK, tbank,
2079 LST_DSPACC_TODAY, ttoday,
2080 LST_DSPACC_FUTURE, tfuture,
2081 -1);
2082 }
2083
2084 /* set balance to header to display when collasped */
2085 DB( g_print(" - enrich totals to header :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
2086 gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
2087 LST_DSPACC_BANK, tbank,
2088 LST_DSPACC_TODAY, ttoday,
2089 LST_DSPACC_FUTURE, tfuture,
2090 -1);
2091
2092 /* add to grand total */
2093 gtbank += tbank;
2094 gttoday += ttoday;
2095 gtfuture += tfuture;
2096
2097 }
2098
2099 }
2100
2101 DB( g_print(" - grand totals :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) );
2102
2103 // Grand total
2104 if( nbtype > 1 )
2105 {
2106 gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL);
2107 gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
2108 LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL,
2109 LST_DSPACC_NAME, _("Grand total"),
2110 LST_DSPACC_BANK, gtbank,
2111 LST_DSPACC_TODAY, gttoday,
2112 LST_DSPACC_FUTURE, gtfuture,
2113 -1);
2114 }
2115
2116
2117 gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
2118
2119 DB( g_print(" - free ressources\n") );
2120
2121 g_hash_table_iter_init (&grp_iter, h_group);
2122 while (g_hash_table_iter_next (&grp_iter, &key, &value))
2123 {
2124 g_ptr_array_free (value, TRUE);
2125 }
2126 g_hash_table_destroy (h_group);
2127
2128 }
2129
2130
2131 void ui_mainwindow_update(GtkWidget *widget, gpointer user_data)
2132 {
2133 struct hbfile_data *data;
2134 gint flags;
2135
2136 DB( g_print("\n[ui-mainwindow] refresh_display\n") );
2137
2138 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
2139 //data = INST_DATA(widget);
2140
2141 flags = GPOINTER_TO_INT(user_data);
2142
2143 /* set window title */
2144 if(flags & UF_TITLE)
2145 {
2146 gchar *basename;
2147 gchar *changed;
2148
2149 DB( g_print(" + 1: wintitle %x\n", data->wintitle) );
2150
2151 basename = g_path_get_basename(GLOBALS->xhb_filepath);
2152
2153 DB( g_print(" global changes: %d\n", GLOBALS->changes_count) );
2154
2155 g_free(data->wintitle);
2156
2157 changed = (GLOBALS->changes_count > 0) ? "*" : "";
2158
2159 data->wintitle = g_strdup_printf("%s%s - %s - " PROGNAME, changed, basename, GLOBALS->owner);
2160
2161 gtk_window_set_title (GTK_WINDOW (gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), data->wintitle);
2162
2163 g_free(basename);
2164 }
2165
2166 /* update disabled things */
2167 if(flags & UF_SENSITIVE)
2168 {
2169 GtkTreeSelection *selection;
2170 GtkTreeModel *model;
2171 GtkTreeIter iter;
2172 GtkTreePath *path;
2173 gboolean active,sensitive;
2174
2175 DB( g_print(" + 2: disabled, opelist count\n") );
2176
2177 //#1656531
2178 data->acc = NULL;
2179
2180 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc));
2181 active = gtk_tree_selection_get_selected(selection, &model, &iter);
2182 if(active)
2183 {
2184 Account *acc;
2185 gint depth;
2186
2187 path = gtk_tree_model_get_path(model, &iter);
2188 depth = gtk_tree_path_get_depth(path);
2189
2190 if( depth > 1 )
2191 {
2192 DB( g_print(" depth is %d\n", depth) );
2193
2194 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPACC_DATAS, &acc, -1);
2195 data->acc = acc;
2196 }
2197 else
2198 active = FALSE;
2199 }
2200
2201
2202 // no change: disable save
2203 DB( g_print(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) );
2204
2205
2206 sensitive = (GLOBALS->changes_count != 0 ) ? TRUE : FALSE;
2207 //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/SaveAs"), sensitive);
2208 //if(sensitive == TRUE && GLOBALS->hbfile_is_new == TRUE) sensitive = FALSE;
2209 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Save"), sensitive);
2210 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Revert"), GLOBALS->xhb_hasbak);
2211
2212
2213 // define off ?
2214 sensitive = GLOBALS->define_off == 0 ? TRUE : FALSE;
2215
2216 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Account"), sensitive);
2217 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Payee"), sensitive);
2218 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Category"), sensitive);
2219 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
2220 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/EditMenu/Preferences"), sensitive);
2221
2222 // empty account list: disable Import, Archives, Edit, Filter, Add, Statistics, Overdrawn, Car Cost
2223 sensitive = da_acc_length() > 0 ? TRUE : FALSE;
2224
2225 //gtk_action_set_sensitive(gtk_ui_manager_get_action(data-data->manager, "/MenuBar/FileMenu/Import"), sensitive);
2226
2227 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Close"), sensitive);
2228 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Archive"), sensitive);
2229 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddOpe"), sensitive);
2230 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
2231 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RStatistics"), sensitive);
2232 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RTrendTime"), sensitive);
2233 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBudget"), sensitive);
2234 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBalance"), sensitive);
2235 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RVehiculeCost"), sensitive);
2236
2237 // empty category list: disable Budget
2238 sensitive = da_cat_length() > 1 ? TRUE : FALSE;
2239 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
2240
2241 //#1501129 no need to disable, P & C can be created from assign dialog
2242 //sensitive = ((da_cat_length() > 1) || (da_pay_length() > 1)) ? TRUE : FALSE;
2243 //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive);
2244
2245 // empty archive list: disable scheduled check
2246 sensitive = g_list_length(GLOBALS->arc_list) > 0 ? TRUE : FALSE;
2247
2248 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddScheduled"), sensitive);
2249
2250 // no active account: disable Edit, Over
2251 sensitive = (active == TRUE ) ? TRUE : FALSE;
2252 if(data->acc && data->acc->window != NULL)
2253 sensitive = FALSE;
2254
2255 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
2256
2257 }
2258
2259 /* update toolbar, list */
2260 if(flags & UF_VISUAL)
2261 {
2262 DB( g_print(" + 8: visual\n") );
2263
2264 if(PREFS->toolbar_style == 0)
2265 gtk_toolbar_unset_style(GTK_TOOLBAR(data->toolbar));
2266 else
2267 gtk_toolbar_set_style(GTK_TOOLBAR(data->toolbar), PREFS->toolbar_style-1);
2268
2269 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_acc), PREFS->grid_lines);
2270 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
2271
2272 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_upc), PREFS->grid_lines);
2273 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc));
2274
2275 DB( g_print(" - show toolbar=%d\n", PREFS->wal_toolbar) );
2276 if(PREFS->wal_toolbar)
2277 gtk_widget_show(GTK_WIDGET(data->toolbar));
2278 else
2279 gtk_widget_hide(GTK_WIDGET(data->toolbar));
2280
2281
2282 DB( g_print(" - show top_spending=%d\n", PREFS->wal_spending) );
2283
2284 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_wal);
2285
2286 if(PREFS->wal_spending)
2287 gtk_widget_show(GTK_WIDGET(data->GR_top));
2288 else
2289 gtk_widget_hide(GTK_WIDGET(data->GR_top));
2290
2291
2292
2293 DB( g_print(" - show upcoming=%d\n", PREFS->wal_upcoming) );
2294 if(PREFS->wal_upcoming)
2295 gtk_widget_show(GTK_WIDGET(data->GR_upc));
2296 else
2297 gtk_widget_hide(GTK_WIDGET(data->GR_upc));
2298
2299 DB( g_print(" minor %d\n", PREFS->euro_active) );
2300 gtk_action_set_visible(gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor"), PREFS->euro_active);
2301 }
2302
2303 /* update balances */
2304 if(flags & UF_BALANCE)
2305 {
2306
2307 DB( g_print(" + 4: balances\n") );
2308
2309 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
2310
2311 //minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
2312
2313 /*
2314 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[0]), data->bank, minor);
2315 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[1]), data->today, minor);
2316 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[2]), data->future, minor);
2317 */
2318 }
2319
2320 if(flags & UF_REFRESHALL)
2321 {
2322 DB( g_print(" + 8: refreshall\n") );
2323
2324 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
2325 ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
2326 ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
2327 }
2328
2329
2330 }
2331
2332
2333
2334 static void
2335 ui_mainwindow_onRowActivated (GtkTreeView *treeview,
2336 GtkTreePath *path,
2337 GtkTreeViewColumn *col,
2338 gpointer userdata)
2339 {
2340 GtkTreeModel *model;
2341 GtkTreeIter iter;
2342
2343 DB( g_print ("\n[ui-mainwindow] A row has been double-clicked!\n") );
2344
2345 model = gtk_tree_view_get_model(treeview);
2346
2347 if (gtk_tree_model_get_iter(model, &iter, path))
2348 {
2349 Account *acc;
2350
2351 gtk_tree_model_get(model, &iter, LST_DSPACC_DATAS, &acc, -1);
2352
2353 if( acc != NULL )
2354 {
2355
2356 DB( g_print ("Double-clicked row contains name %s\n", acc->name) );
2357
2358 ui_mainwindow_action_showtransactions();
2359
2360 //g_free(name);
2361 }
2362 }
2363 }
2364
2365 /*
2366 **
2367 */
2368 static gboolean ui_mainwindow_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
2369 {
2370 struct hbfile_data *data = user_data;
2371 struct WinGeometry *wg;
2372 gboolean retval = FALSE;
2373
2374 GValue widget_value = G_VALUE_INIT;
2375 ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL);
2376
2377 DB( g_print("\n[ui-mainwindow] dispose\n") );
2378
2379 //store position and size
2380 wg = &PREFS->wal_wg;
2381 gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
2382 gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
2383 GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(widget));
2384 GdkWindowState state = gdk_window_get_state(gdk_window);
2385 wg->s = (state & GDK_WINDOW_STATE_MAXIMIZED) ? 1 : 0;
2386
2387 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d s=%d, state=%d\n", wg->l, wg->t, wg->w, wg->h, wg->s, state & GDK_WINDOW_STATE_MAXIMIZED) );
2388
2389 PREFS->wal_vpaned = gtk_paned_get_position(GTK_PANED(data->vpaned));
2390 PREFS->wal_hpaned = gtk_paned_get_position(GTK_PANED(data->hpaned));
2391
2392 DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
2393
2394 //todo
2395 if(ui_dialog_msg_savechanges(widget, NULL) == FALSE)
2396 {
2397 retval = TRUE;
2398 }
2399 else
2400 {
2401 DB( g_print(" free wintitle %x\n", data->wintitle) );
2402
2403 gtk_widget_destroy(data->LV_top);
2404
2405 g_free(data->wintitle);
2406 da_filter_free(data->filter);
2407 g_free(user_data);
2408 gtk_main_quit();
2409 }
2410
2411
2412
2413 //delete-event TRUE abort/FALSE destroy
2414 return retval;
2415 }
2416
2417
2418 static void ui_mainwindow_recent_chooser_item_activated_cb (GtkRecentChooser *chooser, struct hbfile_data *data)
2419 {
2420 gchar *uri, *path;
2421 GError *error = NULL;
2422
2423 uri = gtk_recent_chooser_get_current_uri (chooser);
2424
2425 path = g_filename_from_uri (uri, NULL, NULL);
2426 if (error)
2427 {
2428 g_warning ("Could not convert uri \"%s\" to a local path: %s", uri, error->message);
2429 g_error_free (error);
2430 return;
2431 }
2432
2433 if( ui_dialog_msg_savechanges(data->window, NULL) == TRUE )
2434 {
2435
2436 //todo: FixMe
2437 /*
2438 if (! load)
2439 {
2440 gpw_recent_remove (gpw, path);
2441 }
2442 */
2443
2444 hbfile_change_filepath(path);
2445 ui_mainwindow_open_internal(data->window, NULL);
2446 }
2447 else
2448 {
2449 g_free (path);
2450 }
2451 g_free (uri);
2452 }
2453
2454
2455 static void ui_mainwindow_window_screen_changed_cb (GtkWidget *widget,
2456 GdkScreen *old_screen,
2457 struct hbfile_data *data)
2458 {
2459
2460 DB( g_print("\n[ui-mainwindow] screen_changed_cb\n") );
2461
2462
2463 data->recent_manager = gtk_recent_manager_get_default ();
2464
2465 gtk_menu_detach (GTK_MENU (data->recent_menu));
2466 g_object_unref (G_OBJECT (data->recent_menu));
2467
2468 data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
2469
2470 g_signal_connect (data->recent_menu,
2471 "item-activated",
2472 G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
2473 data);
2474
2475 //menu_item = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/OpenRecent");
2476 //gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), data->recent_menu);
2477 }
2478
2479
2480 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path)
2481 {
2482 GtkRecentData *recent_data;
2483 gchar *uri;
2484 GError *error = NULL;
2485
2486 DB( g_print("\n[ui-mainwindow] recent_add\n") );
2487
2488 DB( g_print(" - file has .xhb suffix = %d\n", g_str_has_suffix (path, ".xhb") ) );
2489
2490 if( g_str_has_suffix (path, ".xhb") == FALSE ) //ignore reverted file
2491 return;
2492
2493 uri = g_filename_to_uri (path, NULL, &error);
2494 if (error)
2495 {
2496 g_warning ("Could not convert uri \"%s\" to a local path: %s", uri, error->message);
2497 g_error_free (error);
2498 return;
2499 }
2500
2501 recent_data = g_slice_new (GtkRecentData);
2502
2503 recent_data->display_name = NULL;
2504 recent_data->description = NULL;
2505 recent_data->mime_type = "application/x-homebank";
2506 recent_data->app_name = (gchar *) g_get_application_name ();
2507 recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
2508 recent_data->groups = NULL;
2509 recent_data->is_private = FALSE;
2510
2511 if (!gtk_recent_manager_add_full (data->recent_manager,
2512 uri,
2513 recent_data))
2514 {
2515 g_warning ("Unable to add '%s' to the list of recently used documents", uri);
2516 }
2517
2518 g_free (uri);
2519 g_free (recent_data->app_exec);
2520 g_slice_free (GtkRecentData, recent_data);
2521
2522 }
2523
2524
2525
2526
2527
2528 enum
2529 {
2530 TARGET_URI_LIST
2531 };
2532
2533 static GtkTargetEntry drop_types[] =
2534 {
2535 {"text/uri-list", 0, TARGET_URI_LIST}
2536 };
2537
2538 static void ui_mainwindow_drag_data_received (GtkWidget *widget,
2539 GdkDragContext *context,
2540 gint x, gint y,
2541 GtkSelectionData *selection_data,
2542 guint info, guint time, GtkWindow *window)
2543 {
2544 gchar **uris, **str;
2545 gchar *newseldata;
2546 gint filetype, slen;
2547
2548 if (info != TARGET_URI_LIST)
2549 return;
2550
2551 DB( g_print("\n[ui-mainwindow] drag_data_received\n") );
2552
2553 /* On MS-Windows, it looks like `selection_data->data' is not NULL terminated. */
2554 slen = gtk_selection_data_get_length(selection_data);
2555 newseldata = g_new (gchar, slen + 1);
2556 memcpy (newseldata, gtk_selection_data_get_data(selection_data), slen);
2557 newseldata[slen] = 0;
2558
2559 uris = g_uri_list_extract_uris (newseldata);
2560
2561 DB( g_print(" - dragged %d %d files\n", slen, g_strv_length(uris) ) );
2562
2563 str = uris;
2564 //for (str = uris; *str; str++)
2565 if( *str )
2566 {
2567 GError *error = NULL;
2568 gchar *path = g_filename_from_uri (*str, NULL, &error);
2569
2570 if (path)
2571 {
2572 filetype = homebank_alienfile_recognize(path);
2573
2574 DB( g_print(" - dragged %s, type is %d\n", path, filetype ) );
2575
2576 if( filetype == FILETYPE_HOMEBANK)
2577 {
2578 hbfile_change_filepath(g_strdup(path));
2579 ui_mainwindow_open_internal(GTK_WIDGET(window), NULL);
2580 }
2581 else
2582 {
2583 //todo: future here to implement import for other filetype
2584 // ui_import_assistant_new();
2585 // + write a method into assistant to catch other filename
2586
2587
2588 ui_dialog_msg_infoerror(GTK_WINDOW(window), GTK_MESSAGE_ERROR,
2589 _("File error"),
2590 _("The file %s is not a valid HomeBank file."),
2591 path
2592 );
2593
2594
2595 }
2596
2597 }
2598 else
2599 {
2600 g_warning ("Could not convert uri to local path: %s", error->message);
2601
2602 g_error_free (error);
2603 }
2604 g_free (path);
2605 }
2606 g_strfreev (uris);
2607
2608 g_free(newseldata);
2609 }
2610
2611
2612 static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager)
2613 {
2614 GtkWidget *toolbar_recent_menu;
2615 GtkRecentFilter *filter;
2616
2617 toolbar_recent_menu = gtk_recent_chooser_menu_new_for_manager (manager);
2618
2619 gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (toolbar_recent_menu),
2620 FALSE);
2621 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (toolbar_recent_menu),
2622 GTK_RECENT_SORT_MRU);
2623 //todo: add a user pref for this
2624 gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (toolbar_recent_menu),
2625 10);
2626
2627
2628 //gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (toolbar_recent_menu), FALSE);
2629
2630 //gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (toolbar_recent_menu), TRUE);
2631
2632 filter = gtk_recent_filter_new ();
2633 //gtk_recent_filter_add_application (filter, g_get_application_name());
2634 gtk_recent_filter_add_pattern (filter, "*.[Xx][Hh][Bb]");
2635 gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (toolbar_recent_menu), filter);
2636
2637 return toolbar_recent_menu;
2638 }
2639
2640
2641 static void ui_mainwindow_create_menu_bar_and_toolbar(struct hbfile_data *data, GtkWidget *mainvbox)
2642 {
2643 GtkUIManager *manager;
2644 GtkActionGroup *actions;
2645 GtkAction *action;
2646 GError *error = NULL;
2647
2648 manager = gtk_ui_manager_new ();
2649 data->manager = manager;
2650
2651 gtk_window_add_accel_group (GTK_WINDOW (data->window),
2652 gtk_ui_manager_get_accel_group(manager));
2653
2654 actions = gtk_action_group_new ("MainWindow");
2655 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
2656
2657 gtk_action_group_add_actions (actions,
2658 entries,
2659 n_entries,
2660 NULL);
2661
2662 gtk_action_group_add_toggle_actions (actions,
2663 toggle_entries,
2664 n_toggle_entries,
2665 NULL);
2666
2667 gtk_ui_manager_insert_action_group (data->manager, actions, 0);
2668 g_object_unref (actions);
2669 data->actions = actions;
2670
2671 /* set short labels to use in the toolbar */
2672 action = gtk_action_group_get_action(actions, "Open");
2673 g_object_set(action, "short_label", _("Open"), NULL);
2674
2675 //action = gtk_action_group_get_action(action_group, "Save");
2676 //g_object_set(action, "is_important", TRUE, NULL);
2677
2678 action = gtk_action_group_get_action(actions, "Account");
2679 g_object_set(action, "short_label", _("Account"), NULL);
2680
2681 action = gtk_action_group_get_action(actions, "Payee");
2682 g_object_set(action, "short_label", _("Payee"), NULL);
2683
2684 action = gtk_action_group_get_action(actions, "Category");
2685 g_object_set(action, "short_label", _("Category"), NULL);
2686
2687 action = gtk_action_group_get_action(actions, "Archive");
2688 //TRANSLATORS: an archive is stored transaction buffers (kind of bookmark to prefill manual insertion)
2689 g_object_set(action, "short_label", _("Archive"), NULL);
2690
2691 action = gtk_action_group_get_action(actions, "Budget");
2692 g_object_set(action, "short_label", _("Budget"), NULL);
2693
2694 action = gtk_action_group_get_action(actions, "ShowOpe");
2695 g_object_set(action, "short_label", _("Show"), NULL);
2696
2697 action = gtk_action_group_get_action(actions, "AddOpe");
2698 g_object_set(action, "is_important", TRUE, "short_label", _("Add"), NULL);
2699
2700 action = gtk_action_group_get_action(actions, "RStatistics");
2701 g_object_set(action, "short_label", _("Statistics"), NULL);
2702
2703 action = gtk_action_group_get_action(actions, "RBudget");
2704 g_object_set(action, "short_label", _("Budget"), NULL);
2705
2706 action = gtk_action_group_get_action(actions, "RBalance");
2707 g_object_set(action, "short_label", _("Balance"), NULL);
2708
2709 action = gtk_action_group_get_action(actions, "RVehiculeCost");
2710 g_object_set(action, "short_label", _("Vehicle cost"), NULL);
2711
2712 /* now load the UI definition */
2713 gtk_ui_manager_add_ui_from_string (data->manager, ui_info, -1, &error);
2714 if (error != NULL)
2715 {
2716 g_message ("Building menus failed: %s", error->message);
2717 g_error_free (error);
2718 }
2719
2720 //todo: this generate a warning
2721 data->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
2722 gtk_box_pack_start (GTK_BOX (mainvbox),
2723 data->menubar,
2724 FALSE,
2725 FALSE,
2726 0);
2727
2728 data->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
2729 gtk_box_pack_start (GTK_BOX (mainvbox),
2730 data->toolbar,
2731 FALSE,
2732 FALSE,
2733 0);
2734
2735 /* recent files menu */
2736
2737 data->recent_manager = gtk_recent_manager_get_default ();
2738
2739 data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
2740
2741 g_signal_connect (data->recent_menu,
2742 "item-activated",
2743 G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
2744 data);
2745
2746 /*
2747 widget = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/OpenRecent");
2748 gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), data->recent_menu);
2749 */
2750
2751 /* test */
2752 /* add the custom Open button to the toolbar */
2753 GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_OPEN, GTK_ICON_SIZE_BUTTON);
2754
2755 GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open"));
2756 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), data->recent_menu);
2757
2758 gtk_tool_item_set_tooltip_text (open_button, _("Open a file"));
2759 gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), _("Open a recently used file"));
2760
2761 action = gtk_action_group_get_action (data->actions, "Open");
2762 g_object_set (action, "short_label", _("Open"), NULL);
2763 //gtk_action_connect_proxy (action, GTK_WIDGET (open_button));
2764 gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button), action);
2765
2766 gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), open_button, 1);
2767 /* end test */
2768
2769 }
2770
2771 /* Callback function for the undo action */
2772 /*static void
2773 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
2774 {
2775 g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)));
2776 }*/
2777
2778 static void
2779 activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
2780 {
2781 struct hbfile_data *data = user_data;
2782 GVariant *old_state, *new_state;
2783
2784 old_state = g_action_get_state (G_ACTION (action));
2785 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
2786
2787 DB( g_print ("Toggle action %s activated, state changes from %d to %d\n",
2788 g_action_get_name (G_ACTION (action)),
2789 g_variant_get_boolean (old_state),
2790 g_variant_get_boolean (new_state)) );
2791
2792 data->showall = g_variant_get_boolean (new_state);
2793 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
2794
2795 g_simple_action_set_state (action, new_state);
2796 g_variant_unref (old_state);
2797 }
2798
2799 static void
2800 activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
2801 {
2802 //struct hbfile_data *data = user_data;
2803 GVariant *old_state, *new_state;
2804
2805 old_state = g_action_get_state (G_ACTION (action));
2806 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
2807
2808 DB( g_print ("Radio action %s activated, state changes from %s to %s\n",
2809 g_action_get_name (G_ACTION (action)),
2810 g_variant_get_string (old_state, NULL),
2811 g_variant_get_string (new_state, NULL)) );
2812
2813 PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_TYPE;
2814 if( !strcmp("bank", g_variant_get_string(new_state, NULL)) )
2815 PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_BANK;
2816
2817 ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
2818
2819 g_simple_action_set_state (action, new_state);
2820 g_variant_unref (old_state);
2821 }
2822
2823
2824 static const GActionEntry actions[] = {
2825 // { "paste", activate_action, NULL, NULL, NULL, {0,0,0} },
2826 { "showall" , activate_toggle, NULL, "false", NULL, {0,0,0} },
2827 { "groupby", activate_radio, "s", "'type'", NULL, {0,0,0} }
2828 };
2829
2830
2831 static GtkWidget *ui_mainwindow_create_youraccounts(struct hbfile_data *data)
2832 {
2833 GtkWidget *panel, *label, *widget, *sw, *tbar, *hbox, *image;
2834 GtkToolItem *toolitem;
2835
2836 panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2837 gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
2838
2839 sw = gtk_scrolled_window_new (NULL, NULL);
2840 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
2841 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2842 gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0);
2843 widget = (GtkWidget *)create_list_account();
2844 data->LV_acc = widget;
2845 gtk_container_add (GTK_CONTAINER (sw), widget);
2846
2847 //list toolbar
2848 tbar = gtk_toolbar_new();
2849 gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
2850 gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
2851 gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
2852 gtk_box_pack_start (GTK_BOX (panel), tbar, FALSE, FALSE, 0);
2853
2854 label = make_label_group(_("Your accounts"));
2855 toolitem = gtk_tool_item_new();
2856 gtk_container_add (GTK_CONTAINER(toolitem), label);
2857 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2858
2859 toolitem = gtk_separator_tool_item_new ();
2860 gtk_tool_item_set_expand (toolitem, TRUE);
2861 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
2862 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2863
2864 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2865 toolitem = gtk_tool_item_new();
2866 gtk_container_add (GTK_CONTAINER(toolitem), hbox);
2867 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2868
2869 widget = make_image_button(ICONNAME_HB_BUTTON_EXPAND, _("Expand all"));
2870 data->BT_expandall = widget;
2871 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2872
2873 widget = make_image_button(ICONNAME_HB_BUTTON_COLLAPSE, _("Collapse all"));
2874 data->BT_collapseall = widget;
2875 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2876
2877 toolitem = gtk_separator_tool_item_new ();
2878 gtk_tool_item_set_expand (toolitem, FALSE);
2879 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
2880 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2881
2882
2883 //gmenu test (see test folder into gtk)
2884 widget = gtk_menu_button_new();
2885 gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget), GTK_ARROW_UP);
2886 gtk_widget_set_halign (widget, GTK_ALIGN_END);
2887 image = gtk_image_new_from_icon_name (ICONNAME_EMBLEM_SYSTEM, GTK_ICON_SIZE_MENU);
2888 g_object_set (widget, "image", image, NULL);
2889
2890 toolitem = gtk_tool_item_new();
2891 gtk_container_add (GTK_CONTAINER(toolitem), widget);
2892 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2893
2894 GMenu *menu, *section;
2895
2896 menu = g_menu_new ();
2897 //g_menu_append (menumodel, "About", "actions.undo");
2898 //g_menu_append (menumodel, "Test", "actions.redo");
2899 section = g_menu_new ();
2900 g_menu_append (section, _("Show all"), "actions.showall");
2901 g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
2902 g_object_unref (section);
2903
2904 section = g_menu_new ();
2905 g_menu_append (section, _("By type"), "actions.groupby::type");
2906 g_menu_append (section, _("By institition"), "actions.groupby::bank");
2907 g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
2908 g_object_unref (section);
2909
2910
2911 GSimpleActionGroup *group = g_simple_action_group_new ();
2912 g_action_map_add_action_entries (G_ACTION_MAP (group), actions, G_N_ELEMENTS (actions), data);
2913
2914 //init radio
2915 GAction *action = g_action_map_lookup_action (G_ACTION_MAP (group), "groupby");
2916 const gchar *value = (PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE) ? "type" : "bank";
2917 g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (value));
2918
2919 gtk_widget_insert_action_group (widget, "actions", G_ACTION_GROUP(group));
2920
2921 gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (widget), G_MENU_MODEL (menu));
2922
2923 return panel;
2924 }
2925
2926
2927 static GtkWidget *ui_mainwindow_create_topspending(struct hbfile_data *data)
2928 {
2929 GtkWidget *panel, *hbox, *tbar;
2930 GtkWidget *label, *widget;
2931 GtkToolItem *toolitem;
2932
2933 widget = (GtkWidget *)create_list_topspending();
2934 data->LV_top = widget;
2935
2936 panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2937 gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
2938 data->GR_top = panel;
2939
2940 /* chart + listview */
2941 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2942 gtk_box_pack_start (GTK_BOX (panel), hbox, TRUE, TRUE, 0);
2943
2944 widget = gtk_chart_new(CHART_TYPE_PIE);
2945 data->RE_pie = widget;
2946 gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol);
2947 gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE);
2948 gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
2949
2950 //list toolbar
2951 tbar = gtk_toolbar_new();
2952 gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
2953 gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
2954 gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
2955 gtk_box_pack_start (GTK_BOX (panel), tbar, FALSE, FALSE, 0);
2956
2957 label = make_label_group(_("Where your money goes"));
2958 toolitem = gtk_tool_item_new();
2959 gtk_container_add (GTK_CONTAINER(toolitem), label);
2960 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2961
2962 toolitem = gtk_separator_tool_item_new ();
2963 gtk_tool_item_set_expand (toolitem, TRUE);
2964 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
2965 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2966
2967 /* total + date range */
2968 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
2969 toolitem = gtk_tool_item_new();
2970 gtk_container_add (GTK_CONTAINER(toolitem), hbox);
2971 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
2972
2973 data->CY_range = make_daterange(label, FALSE);
2974 gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0);
2975
2976 widget = make_radio(CYA_CATSUBCAT, TRUE, GTK_ORIENTATION_HORIZONTAL);
2977 data->RA_type = widget;
2978 gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2979
2980 return panel;
2981 }
2982
2983
2984 static GtkWidget *ui_mainwindow_scheduled_create(struct hbfile_data *data)
2985 {
2986 GtkWidget *panel, *hbox, *vbox, *bbox, *sw, *tbar;
2987 GtkWidget *label, *widget;
2988 GtkToolItem *toolitem;
2989
2990 panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2991 gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
2992 data->GR_upc = panel;
2993
2994 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2995 //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0);
2996 //gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL);
2997 //gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL);
2998 //gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL);
2999 gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0);
3000
3001 sw = gtk_scrolled_window_new (NULL, NULL);
3002 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
3003 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3004 gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
3005
3006 widget = (GtkWidget *)create_list_upcoming();
3007 data->LV_upc = widget;
3008 gtk_container_add (GTK_CONTAINER (sw), widget);
3009
3010 tbar = gtk_toolbar_new();
3011 gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
3012 gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
3013 gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
3014 gtk_box_pack_start (GTK_BOX (vbox), tbar, FALSE, FALSE, 0);
3015
3016 label = make_label_group(_("Scheduled transactions"));
3017 toolitem = gtk_tool_item_new();
3018 gtk_container_add (GTK_CONTAINER(toolitem), label);
3019 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
3020
3021 toolitem = gtk_separator_tool_item_new ();
3022 gtk_tool_item_set_expand (toolitem, FALSE);
3023 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
3024 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
3025
3026
3027 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
3028 toolitem = gtk_tool_item_new();
3029 gtk_container_add (GTK_CONTAINER(toolitem), bbox);
3030 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
3031
3032 widget = gtk_button_new_with_label(_("Skip"));
3033 data->BT_sched_skip = widget;
3034 gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
3035
3036 widget = gtk_button_new_with_label(_("Edit & Post"));
3037 data->BT_sched_editpost = widget;
3038 gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
3039
3040 //TRANSLATORS: Posting a scheduled transaction is the action to materialize it into its target account.
3041 //TRANSLATORS: Before that action the automated transaction occurrence is pending and not yet really existing.
3042 widget = gtk_button_new_with_label (_("Post"));
3043 data->BT_sched_post = widget;
3044 gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
3045
3046 toolitem = gtk_separator_tool_item_new ();
3047 gtk_tool_item_set_expand (toolitem, FALSE);
3048 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
3049 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
3050
3051 hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
3052 gtk_widget_set_valign (hbox, GTK_ALIGN_CENTER);
3053 toolitem = gtk_tool_item_new();
3054 gtk_container_add (GTK_CONTAINER(toolitem), hbox);
3055 gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
3056
3057 label = make_label(_("maximum post date"), 0.0, 0.7);
3058 gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
3059 gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
3060 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3061
3062 label = make_label(NULL, 0.0, 0.7);
3063 data->LB_maxpostdate = label;
3064 gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
3065 gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
3066 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3067
3068 return panel;
3069 }
3070
3071
3072 /*
3073 ** the window creation
3074 */
3075 GtkWidget *create_hbfile_window(GtkWidget *do_widget)
3076 {
3077 struct hbfile_data *data;
3078 struct WinGeometry *wg;
3079 GtkWidget *mainvbox, *vbox, *vpaned, *hpaned;
3080 GtkWidget *widget;
3081 GtkWidget *window;
3082 GtkAction *action;
3083
3084 DB( g_print("\n[ui-mainwindow] create main window\n") );
3085
3086 data = g_malloc0(sizeof(struct hbfile_data));
3087 if(!data) return NULL;
3088
3089 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3090
3091 //store our window private data
3092 g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
3093 DB( g_print(" - new window=%x, inst_data=%0x\n", window, data) );
3094
3095 // this is our mainwindow, so store it to GLOBALS data
3096 data->window = window;
3097 GLOBALS->mainwindow = window;
3098
3099 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3100 gtk_container_add (GTK_CONTAINER (window), mainvbox);
3101
3102 ui_mainwindow_create_menu_bar_and_toolbar (data, mainvbox);
3103
3104 #if HB_UNSTABLE_SHOW == TRUE
3105 GtkWidget *bar, *label;
3106
3107 bar = gtk_info_bar_new ();
3108 gtk_box_pack_start (GTK_BOX (mainvbox), bar, FALSE, FALSE, 0);
3109 gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_WARNING);
3110 label = make_label(NULL, 0.5, 0.5);
3111 gtk_label_set_markup (GTK_LABEL(label), "Unstable Development Version");
3112 gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label, FALSE, FALSE, 0);
3113 #endif
3114
3115 /* Add the main area */
3116 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3117 //gtk_container_set_border_width (GTK_CONTAINER(vbox), SPACING_MEDIUM);
3118 gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
3119
3120 vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3121 data->vpaned = vpaned;
3122 gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
3123
3124 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3125 data->hpaned = hpaned;
3126 gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
3127
3128 widget = ui_mainwindow_scheduled_create(data);
3129 gtk_paned_pack2 (GTK_PANED(vpaned), widget, FALSE, FALSE);
3130
3131 widget = ui_mainwindow_create_youraccounts(data);
3132 gtk_paned_pack1 (GTK_PANED(hpaned), widget, FALSE, FALSE);
3133
3134 widget = ui_mainwindow_create_topspending(data);
3135 gtk_paned_pack2 (GTK_PANED(hpaned), widget, FALSE, FALSE);
3136
3137
3138 DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
3139
3140 if(PREFS->wal_hpaned > 0)
3141 gtk_paned_set_position(GTK_PANED(data->hpaned), PREFS->wal_hpaned);
3142 if(PREFS->wal_vpaned > 0)
3143 gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned);
3144
3145 //setup, init and show window
3146 wg = &PREFS->wal_wg;
3147 if(wg->s == 0)
3148 {
3149 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
3150 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
3151 }
3152 else
3153 gtk_window_maximize(GTK_WINDOW(window));
3154
3155 gtk_widget_show_all (window);
3156
3157 //todo: move this elsewhere
3158 DB( g_print(" - setup stuff\n") );
3159
3160 data->filter = da_filter_malloc();
3161 filter_default_all_set(data->filter);
3162 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_wal);
3163
3164 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Toolbar");
3165 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_toolbar);
3166 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Spending");
3167 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_spending);
3168 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Upcoming");
3169 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_upcoming);
3170
3171 /* Drag and drop support, set targets to NULL because we add the
3172 default uri_targets below */
3173
3174 /* support for opening a file by dragging onto the project window */
3175 gtk_drag_dest_set (GTK_WIDGET (window),
3176 GTK_DEST_DEFAULT_ALL,
3177 drop_types,
3178 G_N_ELEMENTS (drop_types),
3179 GDK_ACTION_COPY);
3180
3181 g_signal_connect (G_OBJECT (window), "drag-data-received",
3182 G_CALLBACK (ui_mainwindow_drag_data_received), window);
3183
3184
3185
3186 //connect all our signals
3187 DB( g_print(" - connect signals\n") );
3188
3189
3190 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc)), "changed", G_CALLBACK (ui_mainwindow_selection), NULL);
3191 g_signal_connect (GTK_TREE_VIEW(data->LV_acc ), "row-activated", G_CALLBACK (ui_mainwindow_onRowActivated), GINT_TO_POINTER(2));
3192 g_signal_connect (G_OBJECT (data->BT_expandall ), "clicked" , G_CALLBACK (ui_panel_accounts_expand_all), NULL);
3193 g_signal_connect (G_OBJECT (data->BT_collapseall), "clicked" , G_CALLBACK (ui_panel_accounts_collapse_all), NULL);
3194
3195 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_upc)), "changed", G_CALLBACK (ui_mainwindow_scheduled_selection_cb), NULL);
3196 g_signal_connect (GTK_TREE_VIEW(data->LV_upc), "row-activated", G_CALLBACK (ui_mainwindow_scheduled_onRowActivated), NULL);
3197 g_signal_connect (G_OBJECT (data->BT_sched_skip), "clicked", G_CALLBACK (ui_mainwindow_scheduled_skip_cb), data);
3198 g_signal_connect (G_OBJECT (data->BT_sched_editpost), "clicked", G_CALLBACK (ui_mainwindow_scheduled_editpost_cb), data);
3199 g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data);
3200
3201 widget = radio_get_nth_widget(GTK_CONTAINER(data->RA_type), 1);
3202 if(widget)
3203 g_signal_connect (widget, "toggled", G_CALLBACK (ui_mainwindow_populate_topspending), &data);
3204
3205 g_signal_connect (data->CY_range, "changed", G_CALLBACK (ui_mainwindow_populate_topspending), NULL);
3206
3207
3208 /* GtkWindow events */
3209 g_signal_connect (window, "delete-event", G_CALLBACK (ui_mainwindow_dispose), (gpointer)data);
3210
3211
3212 g_signal_connect (window, "screen-changed",
3213 G_CALLBACK (ui_mainwindow_window_screen_changed_cb),
3214 data);
3215
3216
3217 //gtk_action_group_set_sensitive(data->actions, FALSE);
3218
3219
3220 return window;
3221 }
3222
This page took 0.19709 seconds and 4 git commands to generate.