]> 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-2019 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
29 #include "hub-account.h"
30 #include "hub-scheduled.h"
31 #include "hub-spending.h"
32 #include "hub-transaction.h"
33
34 #include "dsp-account.h"
35 #include "ui-assist-import.h"
36 #include "ui-assist-start.h"
37 #include "ui-account.h"
38 #include "ui-currency.h"
39 #include "ui-payee.h"
40 #include "ui-category.h"
41 #include "ui-archive.h"
42 #include "ui-assign.h"
43 #include "ui-budget.h"
44 #include "ui-pref.h"
45 #include "ui-hbfile.h"
46 #include "ui-transaction.h"
47 #include "ui-tag.h"
48
49 #include "rep-balance.h"
50 #include "rep-budget.h"
51 #include "rep-stats.h"
52 #include "rep-time.h"
53 #include "rep-vehicle.h"
54
55 #include "gtk-chart.h"
56
57 //old url prior 2019
58 //#define HOMEBANK_URL_HELP "http://homebank.free.fr/help/"
59 //#define HOMEBANK_URL_HELP_ONLINE "https://launchpad.net/homebank/+addquestion"
60 //#define HOMEBANK_URL_HELP_PROBLEM "https://launchpad.net/homebank/+filebug"
61 //#define HOMEBANK_URL_HELP_TRANSLATE "https://launchpad.net/homebank/+translations"
62
63 #define HOMEBANK_URL_HELP "index.html"
64 #define HOMEBANK_URL_HELP_ONLINE "http://homebank.free.fr/support.php"
65 #define HOMEBANK_URL_HELP_UPDATES "http://homebank.free.fr/downloads.php"
66 #define HOMEBANK_URL_HELP_PROBLEM "http://homebank.free.fr/development.php#bug"
67 #define HOMEBANK_URL_HELP_TRANSLATE "http://homebank.free.fr/development.php#translate"
68
69
70 /****************************************************************************/
71 /* Debug macros */
72 /****************************************************************************/
73 #define MYDEBUG 0
74
75 #if MYDEBUG
76 #define DB(x) (x);
77 #else
78 #define DB(x);
79 #endif
80
81 /* our global datas */
82 extern struct HomeBank *GLOBALS;
83 extern struct Preferences *PREFS;
84 extern gchar *homebank_pixmaps_dir;
85
86
87 /* our functions prototype */
88 static void ui_mainwindow_action_new(void);
89 static void ui_mainwindow_action_open(void);
90 static void ui_mainwindow_action_save(void);
91 static void ui_mainwindow_action_saveas(void);
92 static void ui_mainwindow_action_revert(void);
93 static void ui_mainwindow_action_openbak(void);
94 static void ui_mainwindow_action_properties(void);
95 static void ui_mainwindow_action_close(void);
96 static void ui_mainwindow_action_quit(void);
97
98 static void ui_mainwindow_action_defcurrency(void);
99 static void ui_mainwindow_action_defaccount(void);
100 static void ui_mainwindow_action_defpayee(void);
101 static void ui_mainwindow_action_defcategory(void);
102 static void ui_mainwindow_action_defarchive(void);
103 static void ui_mainwindow_action_defbudget(void);
104 static void ui_mainwindow_action_defassign(void);
105 static void ui_mainwindow_action_deftag(void);
106 static void ui_mainwindow_action_preferences(void);
107
108 static void ui_mainwindow_action_toggle_toolbar(GtkToggleAction *action);
109 static void ui_mainwindow_action_toggle_upcoming(GtkToggleAction *action);
110 static void ui_mainwindow_action_toggle_topspending(GtkToggleAction *action);
111 static void ui_mainwindow_action_toggle_minor(GtkToggleAction *action);
112
113 static void ui_mainwindow_action_showtransactions(GtkAction *action);
114
115 static void ui_mainwindow_action_addtransactions(void);
116 static void ui_mainwindow_action_checkscheduled(void);
117
118 static void ui_mainwindow_action_statistic(void);
119 static void ui_mainwindow_action_trendtime(void);
120 static void ui_mainwindow_action_budget(void);
121 static void ui_mainwindow_action_balance(void);
122 static void ui_mainwindow_action_vehiclecost(void);
123
124 static void ui_mainwindow_action_import(GtkAction *action);
125 static void ui_mainwindow_action_export(void);
126 static void ui_mainwindow_action_anonymize(void);
127 static void ui_mainwindow_action_file_statistics(void);
128
129 static void ui_mainwindow_action_pluginprefs(void);
130
131 static void ui_mainwindow_action_help(void);
132 void ui_mainwindow_action_help_welcome(void);
133 static void ui_mainwindow_action_help_online(void);
134 static void ui_mainwindow_action_help_updates(void);
135 static void ui_mainwindow_action_help_releasenotes(void);
136 static void ui_mainwindow_action_help_translate(void);
137 static void ui_mainwindow_action_help_problem(void);
138 static void ui_mainwindow_action_about(void);
139
140
141 static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager);
142
143 void ui_mainwindow_open(GtkWidget *widget, gpointer user_data);
144
145 void ui_mainwindow_save(GtkWidget *widget, gpointer user_data);
146 void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data);
147 void ui_mainwindow_action(GtkWidget *widget, gpointer user_data);
148 void ui_mainwindow_toggle_minor(GtkWidget *widget, gpointer user_data);
149 void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data);
150
151 void ui_mainwindow_update(GtkWidget *widget, gpointer user_data);
152 void ui_mainwindow_addtransactions(GtkWidget *widget, gpointer user_data);
153 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
154
155 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
156
157 static void ui_mainwindow_showprefs(gint page);
158
159 static GtkActionEntry entries[] = {
160
161 /* name, icon-name, label */
162
163 { "FileMenu" , NULL, N_("_File"), NULL, NULL, NULL },
164 //{ "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL },
165 { "RecentMenu" , NULL, N_("Open _Recent"), NULL, NULL, NULL },
166 { "EditMenu" , NULL, N_("_Edit"), NULL, NULL, NULL },
167 { "ViewMenu" , NULL, N_("_View"), NULL, NULL, NULL },
168 { "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL },
169 { "TxnMenu" , NULL, N_("_Transactions"), NULL, NULL, NULL },
170 { "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL },
171 { "ToolsMenu" , NULL, N_("_Tools"), NULL, NULL, NULL },
172 { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL },
173 { "HelpMenu" , NULL, N_("_Help"), NULL, NULL, NULL },
174
175 // { "Import" , NULL, N_("Import") },
176 // { "Export" , NULL, N_("Export to") },
177 /* name, icon-name, label, accelerator, tooltip */
178
179 /* FileMenu */
180 { "New" , ICONNAME_HB_FILE_NEW , N_("_New") , "<control>N", N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) },
181 { "Open" , ICONNAME_HB_FILE_OPEN , N_("_Open...") , "<control>O", N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) },
182 { "Save" , ICONNAME_HB_FILE_SAVE , N_("_Save") , "<control>S", N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) },
183 { "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) },
184
185 { "Revert" , ICONNAME_REVERT , N_("Revert") , NULL, N_("Revert to a saved version of this file"), G_CALLBACK (ui_mainwindow_action_revert) },
186 { "OpenBak" , NULL , N_("Restore backup") , NULL, N_("Restore from a backup file"), G_CALLBACK (ui_mainwindow_action_openbak) },
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 { "Import" , ICONNAME_HB_FILE_IMPORT , N_("Import...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
194 //{ "ImportQIF" , ICONNAME_HB_FILE_IMPORT , N_("QIF file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
195 //{ "ImportOFX" , ICONNAME_HB_FILE_IMPORT , N_("OFX/QFX file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
196 //{ "ImportCSV" , ICONNAME_HB_FILE_IMPORT , N_("CSV file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
197
198 { "ExportQIF" , ICONNAME_HB_FILE_EXPORT , N_("Export as QIF...") , NULL, N_("Export all account in a QIF file"), G_CALLBACK (ui_mainwindow_action_export) },
199
200 /* EditMenu */
201 { "Preferences", ICONNAME_PREFERENCES , N_("Preferences..."), NULL, N_("Configure HomeBank"), G_CALLBACK (ui_mainwindow_action_preferences) },
202
203 /* ManageMenu */
204 { "Currency" , ICONNAME_HB_CURRENCY , N_("Currencies...") , NULL, N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) },
205 { "Account" , ICONNAME_HB_ACCOUNT , N_("Acc_ounts...") , NULL, N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) },
206 { "Payee" , ICONNAME_HB_PAYEE , N_("_Payees...") , NULL, N_("Configure the payees"), G_CALLBACK (ui_mainwindow_action_defpayee) },
207 { "Category" , ICONNAME_HB_CATEGORY , N_("Categories...") , NULL, N_("Configure the categories"), G_CALLBACK (ui_mainwindow_action_defcategory) },
208 { "Archive" , ICONNAME_HB_ARCHIVE , N_("Scheduled/Template...") , NULL, N_("Configure the scheduled/template transactions"), G_CALLBACK (ui_mainwindow_action_defarchive) },
209 { "Budget" , ICONNAME_HB_BUDGET , N_("Budget...") , NULL, N_("Configure the budget"), G_CALLBACK (ui_mainwindow_action_defbudget) },
210 { "Assign" , ICONNAME_HB_ASSIGN , N_("Assignments..."), NULL, N_("Configure the automatic assignments"), G_CALLBACK (ui_mainwindow_action_defassign) },
211 { "Tag" , NULL , N_("Tags..."), NULL, N_("Configure the tags"), G_CALLBACK (ui_mainwindow_action_deftag) },
212
213 /* TxnMenu */
214 { "AddTxn" , ICONNAME_HB_OPE_ADD , N_("Add...") , NULL, N_("Add transactions"), G_CALLBACK (ui_mainwindow_action_addtransactions) },
215 { "ShowTxn" , ICONNAME_HB_OPE_SHOW , N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) },
216 //beware ShowAllTxn is used to detect showall
217 { "ShowAllTxn" , ICONNAME_HB_OPE_SHOW , N_("Show all...") , NULL, N_("Shows all account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) },
218 { "Scheduler" , NULL , N_("Set scheduler...") , NULL, N_("Configure the transaction scheduler"), G_CALLBACK (ui_mainwindow_action_properties) },
219 { "AddScheduled", NULL , N_("Post scheduled"), NULL, N_("Post pending scheduled transactions"), G_CALLBACK (ui_mainwindow_action_checkscheduled) },
220
221 /* ReportMenu */
222 { "RStatistics" , ICONNAME_HB_REP_STATS , N_("_Statistics...") , NULL, N_("Open the Statistics report"), G_CALLBACK (ui_mainwindow_action_statistic) },
223 { "RTrendTime" , ICONNAME_HB_REP_TIME , N_("_Trend Time...") , NULL, N_("Open the Trend Time report"), G_CALLBACK (ui_mainwindow_action_trendtime) },
224 { "RBudget" , ICONNAME_HB_REP_BUDGET , N_("B_udget...") , NULL, N_("Open the Budget report"), G_CALLBACK (ui_mainwindow_action_budget) },
225 { "RBalance" , ICONNAME_HB_REP_BALANCE, N_("Balance...") , NULL, N_("Open the Balance report"), G_CALLBACK (ui_mainwindow_action_balance) },
226 { "RVehiculeCost", ICONNAME_HB_REP_CAR , N_("_Vehicle cost...") , NULL, N_("Open the Vehicle cost report"), G_CALLBACK (ui_mainwindow_action_vehiclecost) },
227
228 /* Tools */
229 { "Welcome" , NULL , N_("Show welcome dialog...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_help_welcome) },
230 { "FileStats" , NULL , N_("File statistics...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_file_statistics) },
231 { "Anonymize" , NULL , N_("Anonymize...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_anonymize) },
232
233 /* Plugins */
234 { "PluginPreferences", "prf-plugins", N_("_Plugins..."), "<control>U", N_("Configure plugin preferences"), G_CALLBACK(ui_mainwindow_action_pluginprefs) },
235
236 /* HelpMenu */
237 { "Contents" , ICONNAME_HELP , N_("_Contents") , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) },
238 { "Online" , "lpi-help" , N_("Get Help Online...") , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) },
239
240 { "Updates" , NULL , N_("Check for updates...") , NULL, N_("Visit HomeBank website to check for update"), G_CALLBACK (ui_mainwindow_action_help_updates) },
241 { "ReleaseNotes", NULL , N_("Release Notes") , NULL, N_("Display the release notes"), G_CALLBACK (ui_mainwindow_action_help_releasenotes) },
242 { "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) },
243 { "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) },
244
245 { "About" , ICONNAME_ABOUT , N_("_About") , NULL, N_("About HomeBank") ,G_CALLBACK (ui_mainwindow_action_about) },
246
247 };
248 static guint n_entries = G_N_ELEMENTS (entries);
249
250
251 static GtkToggleActionEntry toggle_entries[] = {
252 /* name , icon-name, label, accelerator, tooltip, callback, is_active */
253 { "Toolbar" , NULL , N_("_Toolbar") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_toolbar), TRUE },
254 { "Spending" , NULL , N_("_Top spending") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_topspending), TRUE },
255 { "BottomLists", NULL , N_("_Bottom Lists") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE },
256 { "AsMinor" , NULL , N_("Euro minor"), "<control>M", NULL, G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE },
257 };
258
259 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
260
261
262 static const gchar *ui_info =
263 "<ui>"
264
265 " <menubar name='MenuBar'>"
266 " <menu action='FileMenu'>"
267 " <menuitem action='New'/>"
268 " <menuitem action='Open'/>"
269 " <menuitem action='RecentMenu'/>"
270 " <separator/>"
271 " <menuitem action='Save'/>"
272 " <menuitem action='SaveAs'/>"
273 " <separator/>"
274 " <menuitem action='Import'/>"
275 /*" <menu action='ImportMenu'>"
276 " <menuitem action='ImportQIF'/>"
277 " <menuitem action='ImportOFX'/>"
278 " <menuitem action='ImportCSV'/>"
279 " </menu>"*/
280 " <menuitem action='ExportQIF'/>"
281 // future: print to come here
282 " <separator/>"
283 " <menuitem action='Revert'/>"
284 " <menuitem action='OpenBak'/>"
285 " <separator/>"
286 " <menuitem action='Properties'/>"
287 " <separator/>"
288 " <menuitem action='Close'/>"
289 " <menuitem action='Quit'/>"
290 " </menu>"
291 " <menu action='EditMenu'>"
292 " <menuitem action='Preferences'/>"
293 " </menu>"
294 " <menu action='ViewMenu'>"
295 " <menuitem action='Toolbar'/>"
296 " <separator/>"
297 " <menuitem action='Spending'/>"
298 " <menuitem action='BottomLists'/>"
299 " <separator/>"
300 " <menuitem action='AsMinor'/>"
301 " </menu>"
302 " <menu action='ManageMenu'>"
303 " <menuitem action='Account'/>"
304 " <menuitem action='Payee'/>"
305 " <menuitem action='Category'/>"
306 " <menuitem action='Archive'/>"
307 " <menuitem action='Budget'/>"
308 " <menuitem action='Assign'/>"
309 " <menuitem action='Currency'/>"
310 " <menuitem action='Tag'/>"
311 " </menu>"
312 " <menu action='TxnMenu'>"
313 " <menuitem action='AddTxn'/>"
314 " <menuitem action='ShowTxn'/>"
315 " <menuitem action='ShowAllTxn'/>"
316 " <separator/>"
317 " <menuitem action='Scheduler'/>"
318 " <menuitem action='AddScheduled'/>"
319 " </menu>"
320 " <menu action='ReportMenu'>"
321 " <menuitem action='RStatistics'/>"
322 " <menuitem action='RTrendTime'/>"
323 " <menuitem action='RBalance'/>"
324 " <menuitem action='RBudget'/>"
325 " <menuitem action='RVehiculeCost'/>"
326 " </menu>"
327 " <menu action='ToolsMenu'>"
328 " <menuitem action='Welcome'/>"
329 " <menuitem action='FileStats'/>"
330 " <separator/>"
331 " <menuitem action='Anonymize'/>"
332 " </menu>"
333 " <menu action='PluginMenu'>"
334 " <separator/>"
335 " <menuitem action='PluginPreferences'/>"
336 " <separator/>"
337 " </menu>"
338 " <menu action='HelpMenu'>"
339 " <menuitem action='Contents'/>"
340 " <menuitem action='Online'/>"
341 " <separator/>"
342 " <menuitem action='Updates'/>"
343 " <menuitem action='ReleaseNotes'/>"
344 " <menuitem action='Problem'/>"
345 " <menuitem action='Translate'/>"
346 " <separator/>"
347 " <menuitem action='About'/>"
348 " </menu>"
349 " </menubar>"
350
351 " <toolbar name='ToolBar'>"
352 " <toolitem action='New'/>"
353 // here Open + recent is coded
354 " <toolitem action='Save'/>"
355 " <separator/>"
356 " <toolitem action='Account'/>"
357 " <toolitem action='Payee'/>"
358 " <toolitem action='Category'/>"
359 " <toolitem action='Archive'/>"
360 " <toolitem action='Budget'/>"
361 " <toolitem action='Assign'/>"
362 " <toolitem action='Currency'/>"
363 " <separator/>"
364 " <toolitem action='ShowTxn'/>"
365 " <toolitem action='AddTxn'/>"
366 " <separator/>"
367 " <toolitem action='RStatistics'/>"
368 " <toolitem action='RTrendTime'/>"
369 " <toolitem action='RBalance'/>"
370 " <toolitem action='RBudget'/>"
371 " <toolitem action='RVehiculeCost'/>"
372 " <separator/>"
373 " </toolbar>"
374
375 "</ui>";
376
377
378
379 /* TODO: a bouger */
380
381
382 /*
383 **
384 */
385 void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data)
386 {
387 //struct hbfile_data *data;
388 gchar *basename;
389 gchar *title;
390 gchar *secondtext;
391 gint result;
392
393 DB( g_print("\n[ui-mainwindow] revert\n") );
394
395 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
396
397 basename = g_path_get_basename(GLOBALS->xhb_filepath);
398 title = g_strdup_printf (
399 _("Revert unsaved changes to file '%s'?"), basename);
400
401 secondtext =
402 _("- Changes made to the file will be permanently lost\n"
403 "- File will be reloaded from the last save (.xhb~)");
404
405 result = ui_dialog_msg_confirm_alert(
406 GTK_WINDOW(GLOBALS->mainwindow),
407 title,
408 secondtext,
409 _("_Revert")
410 );
411
412 g_free(title);
413 g_free(basename);
414
415 if( result == GTK_RESPONSE_OK )
416 {
417 DB( g_print(" - should revert\n") );
418
419 hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
420 ui_mainwindow_open_internal(widget, NULL);
421 hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
422 }
423
424 }
425
426
427 static void
428 activate_url (GtkAboutDialog *about,
429 const gchar *link,
430 gpointer data)
431 {
432 DB( g_print("activate url %s\n", link) );
433
434 homebank_util_url_show (link);
435 }
436
437 static void hbfile_about(void)
438 {
439 GtkWidget *dialog;
440 GdkPixbuf *pixbuf;
441 gchar *pathfilename;
442 gchar *version;
443
444 static const gchar *artists[] = {
445 "Maxime DOYEN",
446 NULL
447 };
448
449 static const gchar *authors[] = {
450 "Lead developer:\n" \
451 "Maxime DOYEN",
452 "\nContributors:\n" \
453 "Charles MCGARVEY (Plugin system, Perl support)\n" \
454 "Ga\xc3\xabtan LORIDANT (Maths formulas for charts)\n",
455 NULL
456 };
457
458 /*
459 const gchar *documenters[] = {
460 "Maxime DOYEN",
461 NULL
462 };
463 */
464
465 static const gchar *copyright = "Copyright \xc2\xa9 1995-2019 - Maxime DOYEN";
466
467
468
469 version = g_strdup_printf (PACKAGE_VERSION "\n<small>Running against GTK+ %d.%d.%d</small>",
470 gtk_get_major_version (),
471 gtk_get_minor_version (),
472 gtk_get_micro_version ());
473
474 dialog = gtk_about_dialog_new();
475
476 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(GLOBALS->mainwindow));
477 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
478
479 gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(dialog), g_get_application_name ());
480 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), version);
481 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), copyright);
482 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("Free, easy, personal accounting for everyone"));
483 gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0);
484
485 //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), );
486 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr");
487 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
488
489 gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "homebank");
490
491 pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL);
492 pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL);
493 g_free(pathfilename);
494
495 if( pixbuf )
496 {
497 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf);
498 g_object_unref (pixbuf);
499 }
500
501 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
502 gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists);
503 //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), );
504 //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), );
505
506 g_signal_connect (dialog, "activate-link", G_CALLBACK (activate_url), NULL);
507
508 gtk_dialog_run (GTK_DIALOG (dialog));
509
510 gtk_widget_destroy (dialog);
511
512 g_free(version);
513
514 }
515
516
517 /* hbfile action functions -------------------- */
518 static void ui_mainwindow_action_new(void)
519 {
520 GtkWidget *widget = GLOBALS->mainwindow;
521
522 if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
523 {
524 //clear all, and init GLOBALS->xhb_filepath to default
525 ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE)); // GPOINTER_TO_INT(
526 ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
527
528 ui_start_assistant();
529 //ui_hub_account_populate(GLOBALS->mainwindow, NULL);
530 //ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
531 //ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
532 }
533 }
534
535 static void ui_mainwindow_action_open(void)
536 {
537 ui_mainwindow_open(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
538 }
539
540 static void ui_mainwindow_action_openbak(void)
541 {
542 ui_mainwindow_open(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
543 }
544
545 static void ui_mainwindow_action_save(void)
546 {
547 ui_mainwindow_save(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
548 }
549
550 static void ui_mainwindow_action_saveas(void)
551 {
552 ui_mainwindow_save(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
553 }
554
555 static void ui_mainwindow_action_revert(void)
556 {
557 ui_mainwindow_revert(GLOBALS->mainwindow, NULL);
558 }
559
560 static void ui_mainwindow_action_close(void)
561 {
562 GtkWidget *widget = GLOBALS->mainwindow;
563
564 if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
565 {
566 //clear all, and init GLOBALS->xhb_filepath to default
567 ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE));
568 ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
569 }
570
571 }
572
573
574 static void ui_mainwindow_action_quit(void)
575 {
576 gboolean result;
577
578 //emulate the wm close button
579 g_signal_emit_by_name(GLOBALS->mainwindow, "delete-event", NULL, &result);
580 }
581
582
583 static void ui_mainwindow_action_file_statistics(void)
584 {
585 ui_dialog_file_statistics();
586 }
587
588
589 static void ui_mainwindow_action_pluginprefs(void)
590 {
591 ui_mainwindow_showprefs(PREF_PLUGINS);
592 }
593
594
595 static void ui_mainwindow_action_properties(void)
596 {
597 create_defhbfile_dialog();
598 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
599 }
600
601 static void ui_mainwindow_action_anonymize(void)
602 {
603 gint result;
604 gchar *title;
605 gchar *secondtext;
606
607 title = _("Are you sure you want to anonymize the file?");
608
609 secondtext =
610 _("Proceeding will anonymize any text, \n"
611 "like 'account x', 'payee y', 'memo z', ...");
612
613 result = ui_dialog_msg_confirm_alert(
614 GTK_WINDOW(GLOBALS->mainwindow),
615 title,
616 secondtext,
617 _("_Anonymize")
618 );
619
620 //#1707201
621 //if( result == GTK_RESPONSE_CANCEL )
622 // return;
623 if( result == GTK_RESPONSE_OK )
624 {
625 hbfile_anonymize();
626 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
627 }
628 }
629
630
631 static void ui_mainwindow_action_defcurrency(void)
632 {
633 ui_cur_manage_dialog();
634 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
635 }
636
637
638 static void ui_mainwindow_action_defaccount(void)
639 {
640 ui_acc_manage_dialog();
641
642 //our global list has changed, so update the treeview
643 //todo: optimize this, should not call compute balance here
644 account_compute_balances ();
645 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
646
647 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE));
648 }
649
650 static void ui_mainwindow_action_defpayee(void)
651 {
652 ui_pay_manage_dialog();
653 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
654 }
655
656 static void ui_mainwindow_action_defcategory(void)
657 {
658 ui_cat_manage_dialog();
659 //todo:why refresh upcoming here??
660 //ui_mainwindow_populate_upcoming(GLOBALS->mainwindow, NULL);
661 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
662 }
663
664
665 //TODO: not ideal to do this
666 void ui_mainwindow_defarchive(Archive *arc)
667 {
668 struct hbfile_data *data;
669 GtkTreeModel *model;
670
671 data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
672
673 // upcoming list have direct pointer to the arc (which may change during edit)
674 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
675 gtk_list_store_clear (GTK_LIST_STORE(model));
676
677 ui_arc_manage_dialog(arc);
678
679 ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
680
681 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
682 }
683
684
685 static void ui_mainwindow_action_defarchive(void)
686 {
687 ui_mainwindow_defarchive(NULL);
688 }
689
690
691 static void ui_mainwindow_action_defbudget(void)
692 {
693 ui_bud_manage_dialog();
694 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
695 }
696
697
698 static void ui_mainwindow_action_defassign(void)
699 {
700
701 ui_asg_manage_dialog();
702
703 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
704 }
705
706
707 static void ui_mainwindow_action_deftag(void)
708 {
709
710 ui_tag_manage_dialog();
711
712 //ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
713 }
714
715
716 static void ui_mainwindow_action_preferences(void)
717 {
718 ui_mainwindow_showprefs(PREF_GENERAL);
719 }
720
721 static void ui_mainwindow_showprefs(gint page)
722 {
723 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
724
725 defpref_dialog_new(page);
726 if(!PREFS->euro_active)
727 {
728 GtkToggleAction *action = (GtkToggleAction *)gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor");
729
730 gtk_toggle_action_set_active(action, FALSE);
731 ui_mainwindow_action_toggle_minor(action);
732 }
733 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL+UF_REFRESHALL));
734 }
735
736 /* display action */
737
738 static void ui_mainwindow_action_toggle_toolbar(GtkToggleAction *action)
739 {
740 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
741
742 PREFS->wal_toolbar = gtk_toggle_action_get_active(action);
743 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
744 }
745
746 static void ui_mainwindow_action_toggle_upcoming(GtkToggleAction *action)
747 {
748 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
749
750 PREFS->wal_upcoming = gtk_toggle_action_get_active(action);
751 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
752 }
753
754 static void ui_mainwindow_action_toggle_topspending(GtkToggleAction *action)
755 {
756 //struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
757
758 PREFS->wal_spending = gtk_toggle_action_get_active(action);
759 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_VISUAL));
760 }
761
762 static void ui_mainwindow_action_toggle_minor(GtkToggleAction *action)
763 {
764 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
765
766 GLOBALS->minor = gtk_toggle_action_get_active(action);
767
768 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
769 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc));
770
771 // top spending
772 gtk_chart_show_minor(GTK_CHART(data->RE_pie), GLOBALS->minor);
773
774 ui_hub_spending_update(data->window, data);
775
776 }
777
778 static void ui_mainwindow_action_showtransactions(GtkAction *action)
779 {
780 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
781 GtkWidget *window;
782 gboolean showall = FALSE;
783
784 if( action != NULL )
785 {
786 DB( g_print(" actioname=%s\n", gtk_action_get_name(action)) );
787 if( hb_string_compare((gchar *)gtk_action_get_name(action), "ShowAllTxn" ) == 0 )
788 showall = TRUE;
789 }
790
791 //TODO: change this
792 if( data->acc && showall == FALSE )
793 {
794 if( data->acc->window == NULL )
795 {
796 window = register_panel_window_new(data->acc);
797 register_panel_window_init(window, NULL);
798 }
799 else
800 {
801 if(GTK_IS_WINDOW(data->acc->window))
802 gtk_window_present(GTK_WINDOW(data->acc->window));
803 }
804 }
805 else
806 {
807 if( GLOBALS->alltxnwindow == NULL )
808 {
809 window = register_panel_window_new(NULL);
810 register_panel_window_init(window, NULL);
811 }
812 else
813 {
814 if(GTK_IS_WINDOW(GLOBALS->alltxnwindow))
815 gtk_window_present(GTK_WINDOW(GLOBALS->alltxnwindow));
816 }
817 }
818 }
819
820
821 static void ui_mainwindow_action_addtransactions(void)
822 {
823 ui_mainwindow_addtransactions(GLOBALS->mainwindow, NULL);
824 }
825
826 static void ui_mainwindow_action_checkscheduled(void)
827 {
828 ui_hub_scheduled_postall(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
829 }
830
831 static void ui_mainwindow_action_statistic(void)
832 {
833 ui_repdist_window_new();
834 }
835
836 static void ui_mainwindow_action_trendtime(void)
837 {
838 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
839
840 ui_reptime_window_new(data->acc != NULL ? data->acc->key : 0);
841 }
842
843 static void ui_mainwindow_action_budget(void)
844 {
845 repbudget_window_new();
846 }
847
848 static void ui_mainwindow_action_balance(void)
849 {
850 struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
851
852 repbalance_window_new(data->acc != NULL ? data->acc->key : 0);
853 }
854
855 static void ui_mainwindow_action_vehiclecost(void)
856 {
857 repcost_window_new();
858 }
859
860 static void ui_mainwindow_action_import(GtkAction *action)
861 {
862 /*const gchar *name;
863 gint filetype = FILETYPE_UNKNOWN;
864
865 name = gtk_action_get_name(action);
866
867 if( g_str_has_suffix (name, "QIF"))
868 filetype= FILETYPE_QIF;
869 else
870 if( g_str_has_suffix (name, "OFX"))
871 filetype= FILETYPE_OFX;
872 else
873 if( g_str_has_suffix (name, "CSV"))
874 filetype= FILETYPE_CSV_HB;*/
875
876 //DB( g_print("action %s type=%d\n", name, filetype) );
877
878 ui_import_assistant_new(NULL);
879
880 }
881
882
883 static void ui_mainwindow_action_about(void)
884 {
885 hbfile_about();
886
887
888 }
889
890
891 static void ui_mainwindow_action_export(void)
892 {
893 gchar *filename;
894
895 if( ui_file_chooser_qif(NULL, &filename) == TRUE )
896 {
897 hb_export_qif_account_all(filename);
898 g_free( filename );
899 }
900 }
901
902
903 static void ui_mainwindow_action_help(void)
904 {
905 gchar *link;
906
907 link = g_build_filename("file:///", homebank_app_get_help_dir(), HOMEBANK_URL_HELP, NULL );
908 homebank_util_url_show (link);
909 g_free(link);
910 }
911
912
913 static void ui_mainwindow_action_help_releasenotes(void)
914 {
915 gchar *link;
916
917 #ifdef G_OS_WIN32
918 link = g_build_filename("file:///", homebank_app_get_datas_dir(), "ChangeLog.txt", NULL );
919 #else
920 link = g_build_filename("file:///", homebank_app_get_datas_dir(), "ChangeLog", NULL );
921 #endif
922 homebank_util_url_show (link);
923 g_free(link);
924 }
925
926
927 //todo: move this to a ui-assist-welcome.c
928
929 static void ui_mainwindow_action_help_welcome1 (GtkButton *button, gpointer user_data)
930 {
931 gtk_dialog_response (GTK_DIALOG(user_data), 1);
932 }
933
934 static void ui_mainwindow_action_help_welcome2 (GtkButton *button, gpointer user_data)
935 {
936 gtk_dialog_response (GTK_DIALOG(user_data), 2);
937 }
938
939 static void ui_mainwindow_action_help_welcome3 (GtkButton *button, gpointer user_data)
940 {
941 gtk_dialog_response (GTK_DIALOG(user_data), 3);
942 }
943
944 static void ui_mainwindow_action_help_welcome4 (GtkButton *button, gpointer user_data)
945 {
946 gtk_dialog_response (GTK_DIALOG(user_data), 4);
947 }
948
949 static void ui_mainwindow_action_help_welcome5 (GtkButton *button, gpointer user_data)
950 {
951 gtk_dialog_response (GTK_DIALOG(user_data), 5);
952 }
953
954 void ui_mainwindow_action_help_welcome(void)
955 {
956 GtkWidget *dialog, *content_area;
957 GtkWidget *mainvbox, *widget, *label;
958
959 dialog = gtk_dialog_new_with_buttons (_("Welcome to HomeBank"),
960 GTK_WINDOW(GLOBALS->mainwindow),
961 0,
962 _("_Close"),
963 GTK_RESPONSE_ACCEPT,
964 NULL);
965
966 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
967
968 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
969 gtk_box_pack_start (GTK_BOX (content_area), mainvbox, FALSE, FALSE, 0);
970 gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
971
972 label = make_label (_("HomeBank"), 0, 0);
973 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
974 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
975
976 label = make_label (_("Free, easy, personal accounting for everyone"), 0, 0);
977 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
978
979 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
980 gtk_box_pack_start (GTK_BOX (content_area), widget, FALSE, FALSE, 0);
981
982 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
983 gtk_box_pack_start (GTK_BOX (content_area), mainvbox, TRUE, TRUE, 0);
984 gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
985
986 label = make_label (_("What do you want to do:"), 0, 0);
987 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
988 gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
989
990 widget = gtk_button_new_with_mnemonic(_("Read HomeBank _Manual"));
991 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
992 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog);
993
994 widget = gtk_button_new_with_mnemonic(_("Configure _preferences"));
995 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
996 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog);
997
998 widget = gtk_button_new_with_mnemonic(_("Create a _new file"));
999 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
1000 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome3), dialog);
1001
1002 widget = gtk_button_new_with_mnemonic(_("_Open an existing file"));
1003 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
1004 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome4), dialog);
1005
1006 widget = gtk_button_new_with_mnemonic(_("Open the _example file"));
1007 gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
1008 g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome5), dialog);
1009
1010 //connect all our signals
1011 g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &dialog);
1012
1013 gtk_widget_show_all (dialog);
1014
1015 //wait for the user
1016 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1017
1018 // cleanup and destroy
1019 gtk_widget_destroy (dialog);
1020
1021 // do appropriate action
1022 switch(result)
1023 {
1024 case 1:
1025 ui_mainwindow_action_help();
1026 break;
1027 case 2:
1028 ui_mainwindow_action_preferences();
1029 break;
1030 case 3:
1031 ui_mainwindow_action_new();
1032 break;
1033 case 4:
1034 ui_mainwindow_action_open();
1035 break;
1036 case 5:
1037 hbfile_change_filepath(g_build_filename(homebank_app_get_datas_dir(), "example.xhb", NULL));
1038 ui_mainwindow_open_internal(GLOBALS->mainwindow, NULL);
1039 break;
1040 }
1041
1042 }
1043
1044
1045 static void ui_mainwindow_action_help_updates(void)
1046 {
1047 const gchar *link = HOMEBANK_URL_HELP_UPDATES;
1048
1049 homebank_util_url_show (link);
1050 }
1051
1052
1053 static void ui_mainwindow_action_help_online(void)
1054 {
1055 const gchar *link = HOMEBANK_URL_HELP_ONLINE;
1056
1057 homebank_util_url_show (link);
1058 }
1059
1060
1061 static void ui_mainwindow_action_help_translate(void)
1062 {
1063 const gchar *link = HOMEBANK_URL_HELP_TRANSLATE;
1064
1065 homebank_util_url_show (link);
1066 }
1067
1068
1069 static void ui_mainwindow_action_help_problem(void)
1070 {
1071 const gchar *link = HOMEBANK_URL_HELP_PROBLEM;
1072
1073 homebank_util_url_show (link);
1074 }
1075
1076
1077 /* hbfile functions -------------------- */
1078
1079
1080 /*
1081 **
1082 */
1083 static void ui_mainwindow_selection(GtkTreeSelection *treeselection, gpointer user_data)
1084 {
1085 ui_mainwindow_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(UF_SENSITIVE));
1086 }
1087
1088
1089 static void ui_mainwindow_close_openbooks(void)
1090 {
1091 GList *lacc, *elt;
1092
1093 DB( g_print("\n[ui-mainwindow] close openbooks\n") );
1094
1095 lacc = elt = g_hash_table_get_values(GLOBALS->h_acc);
1096 while (elt != NULL)
1097 {
1098 Account *item = elt->data;
1099
1100 if(item->window)
1101 {
1102 gtk_widget_destroy(GTK_WIDGET(item->window));
1103 item->window = NULL;
1104 }
1105
1106 elt = g_list_next(elt);
1107 }
1108 g_list_free(lacc);
1109
1110 }
1111
1112
1113
1114 /*
1115 **
1116 */
1117 void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data)
1118 {
1119 struct hbfile_data *data;
1120 gboolean file_clear = GPOINTER_TO_INT(user_data);
1121
1122 DB( g_print("\n[ui-mainwindow] clear\n") );
1123
1124 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1125
1126 // Close opened account window
1127 // Clear TreeView
1128 ui_mainwindow_close_openbooks();
1129 gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
1130 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc))));
1131 gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
1132
1133 data->showall = FALSE;
1134 ui_hub_account_setup(data);
1135
1136 hbfile_cleanup(file_clear);
1137 hbfile_setup(file_clear);
1138
1139 }
1140
1141
1142 /*
1143 ** add some transactions directly
1144 */
1145 void ui_mainwindow_addtransactions(GtkWidget *widget, gpointer user_data)
1146 {
1147 struct hbfile_data *data;
1148 GtkWidget *window;
1149 gint result = 1;
1150 guint32 date;
1151 gint account, count;
1152
1153 DB( g_print("\n[ui-mainwindow] add transactions\n") );
1154
1155 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1156
1157 /* init the transaction */
1158 date = homebank_app_date_get_julian();
1159
1160 //#1656531
1161 account = 0;
1162 if(data->acc != NULL)
1163 account = data->acc->key;
1164
1165 window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE, account);
1166 count = 0;
1167 while(result == HB_RESPONSE_ADD || result == HB_RESPONSE_ADDKEEP)
1168 {
1169 Transaction *ope;
1170
1171 /* fill in the transaction */
1172 if( result == HB_RESPONSE_ADD )
1173 {
1174 ope = da_transaction_malloc();
1175 ope->date = date;
1176 ope->kacc = account;
1177
1178 if( PREFS->heritdate == FALSE ) //fix: 318733
1179 ope->date = GLOBALS->today;
1180
1181 da_transaction_set_default_template(ope);
1182 }
1183
1184 // normally we can't be in addkeep without initialized ope with add
1185
1186 deftransaction_set_transaction(window, ope);
1187
1188 result = gtk_dialog_run (GTK_DIALOG (window));
1189
1190 DB( g_print(" - dialog result is %d\n", result) );
1191
1192 if(result == HB_RESPONSE_ADD || result == HB_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
1193 {
1194 deftransaction_get(window, NULL);
1195 transaction_add(GTK_WINDOW(GLOBALS->mainwindow), ope);
1196
1197 DB( g_print(" - added 1 transaction to %d\n", ope->kacc) );
1198
1199 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
1200
1201 count++;
1202 //todo: still usefull ? store last date
1203 date = ope->date;
1204 }
1205
1206 if( result == HB_RESPONSE_ADD )
1207 {
1208 da_transaction_free(ope);
1209 ope = NULL;
1210 }
1211
1212 }
1213
1214
1215 deftransaction_dispose(window, NULL);
1216 gtk_widget_destroy (window);
1217
1218 /* todo optimize this */
1219 if(count > 0)
1220 {
1221 GLOBALS->changes_count += count;
1222 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
1223 }
1224 }
1225
1226
1227 gboolean ui_mainwindow_open_backup_check_confirm(gchar *filepath)
1228 {
1229 gboolean retval = FALSE;
1230 gchar *basename, *secondtext;
1231 gboolean result;
1232
1233 basename = g_path_get_basename(filepath);
1234 secondtext = g_strdup_printf (
1235 _("Your are about to open the backup file '%s'.\n\nAre you sure you want to do this ?"), basename);
1236
1237 result = ui_dialog_msg_confirm_alert(
1238 GTK_WINDOW(GLOBALS->mainwindow),
1239 _("Open the backup file ?"),
1240 secondtext,
1241 _("_Open backup")
1242 );
1243
1244 g_free(secondtext);
1245 g_free(basename);
1246
1247 if( result == GTK_RESPONSE_OK )
1248 retval = TRUE;
1249
1250 return retval;
1251 }
1252
1253
1254 /*
1255 **
1256 */
1257 void ui_mainwindow_open(GtkWidget *widget, gpointer user_data)
1258 {
1259 //struct hbfile_data *data;
1260 gboolean bakmode = GPOINTER_TO_INT(user_data);;
1261 gboolean doopen = TRUE;
1262 gchar *filename = NULL;
1263
1264 DB( g_print("\n[ui-mainwindow] open\n") );
1265
1266 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1267
1268 //#1791554 do ask for save confirm
1269 if( bakmode != TRUE )
1270 doopen = ui_dialog_msg_savechanges(widget,NULL);
1271
1272 if( doopen == TRUE )
1273 {
1274 if( ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename, bakmode) == TRUE )
1275 {
1276 //#1710955 test for backup open
1277 if( hbfile_file_isbackup(filename) )
1278 {
1279 if( ui_mainwindow_open_backup_check_confirm(filename) == TRUE )
1280 {
1281 GLOBALS->hbfile_is_bak = TRUE;
1282 }
1283 else
1284 {
1285 g_free(filename);
1286 return;
1287 }
1288 }
1289
1290 hbfile_change_filepath(filename);
1291 ui_mainwindow_open_internal(widget, NULL);
1292 }
1293 }
1294 }
1295
1296
1297 /*
1298 * open the file stored in GLOBALS->xhb_filepath
1299 */
1300 void ui_mainwindow_open_internal(GtkWidget *widget, gpointer user_data)
1301 {
1302 struct hbfile_data *data;
1303 gint r;
1304
1305 DB( g_print("\n[ui-mainwindow] open internal\n") );
1306
1307 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1308
1309 if( GLOBALS->xhb_filepath != NULL )
1310 {
1311 DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) );
1312
1313 ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
1314 GLOBALS->hbfile_is_new = FALSE;
1315
1316 r = homebank_load_xml(GLOBALS->xhb_filepath);
1317 if( r == XML_OK )
1318 {
1319 DB( g_print(" - file loaded ok : rcode=%d\n", r) );
1320
1321 GLOBALS->xhb_timemodified = hbfile_file_get_time_modified(GLOBALS->xhb_filepath);
1322 hbfile_file_hasrevert(GLOBALS->xhb_filepath);
1323
1324 if(PREFS->appendscheduled)
1325 scheduled_post_all_pending();
1326
1327 if(PREFS->do_update_currency)
1328 ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow));
1329
1330 homebank_lastopenedfiles_save();
1331
1332 //todo: delete this after computing done at xml read
1333 account_compute_balances();
1334
1335 ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath);
1336 }
1337 else
1338 {
1339 gchar *msg = _("Unknown error");
1340
1341 switch(r)
1342 {
1343 case XML_IO_ERROR:
1344 msg = _("I/O error for file '%s'.");
1345 break;
1346 case XML_FILE_ERROR:
1347 msg = _("The file '%s' is not a valid HomeBank file.");
1348 break;
1349 case XML_VERSION_ERROR:
1350 msg = _("The file '%s' was saved with a higher version of HomeBank\nand cannot be loaded by the current version.");
1351 break;
1352 }
1353
1354 ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
1355 _("File error"),
1356 msg,
1357 GLOBALS->xhb_filepath
1358 );
1359
1360 ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
1361
1362 }
1363
1364 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
1365 ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
1366 ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
1367 ui_hub_transaction_populate(data);
1368
1369 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
1370 }
1371
1372
1373 }
1374
1375
1376 /*
1377 **
1378 */
1379 void ui_mainwindow_save(GtkWidget *widget, gpointer user_data)
1380 {
1381 struct hbfile_data *data;
1382 gboolean saveas = GPOINTER_TO_INT(user_data);
1383 gchar *filename = NULL;
1384 gint r = XML_UNSET;
1385
1386 DB( g_print("\n[ui-mainwindow] save\n") );
1387
1388 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1389
1390 if( GLOBALS->hbfile_is_new == TRUE )
1391 saveas = 1;
1392
1393 //#1710955 test for backup open
1394 if( GLOBALS->hbfile_is_bak == TRUE )
1395 {
1396 //todo: later for backup, should also remove datetime and .bak
1397 hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
1398 saveas = 1;
1399 }
1400
1401 if(saveas == 1)
1402 {
1403 if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename, FALSE) == TRUE)
1404 {
1405 DB( g_print(" + should save as '%s'\n", filename) );
1406 homebank_file_ensure_xhb(filename);
1407 homebank_backup_current_file();
1408 r = homebank_save_xml(GLOBALS->xhb_filepath);
1409 GLOBALS->hbfile_is_new = FALSE;
1410 GLOBALS->hbfile_is_bak = FALSE;
1411 }
1412 else
1413 return;
1414 }
1415 else
1416 {
1417 guint64 time_modified = hbfile_file_get_time_modified (GLOBALS->xhb_filepath);
1418 gint result = GTK_RESPONSE_OK;
1419
1420 DB( g_print(" + should quick save '%s'\n + time: open=%lu :: now=%lu\n", GLOBALS->xhb_filepath, GLOBALS->xhb_timemodified, time_modified) );
1421
1422 if( GLOBALS->xhb_timemodified != time_modified )
1423 {
1424 result = ui_dialog_msg_confirm_alert(
1425 GTK_WINDOW(GLOBALS->mainwindow),
1426 _("The file has been modified since reading it."),
1427 _("If you save it, all the external changes could be lost. Save it anyway?"),
1428 _("S_ave Anyway")
1429 );
1430
1431 if( result != GTK_RESPONSE_OK )
1432 return;
1433 }
1434
1435 DB( g_print(" + saving...\n") );
1436 homebank_file_ensure_xhb(NULL);
1437 homebank_backup_current_file();
1438 r = homebank_save_xml(GLOBALS->xhb_filepath);
1439 }
1440
1441 if(r == XML_OK)
1442 {
1443 DB( g_print(" + OK...\n") );
1444 GLOBALS->changes_count = 0;
1445 GLOBALS->xhb_timemodified = hbfile_file_get_time_modified (GLOBALS->xhb_filepath);
1446 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
1447 }
1448 else
1449 {
1450 gchar *msg = _("I/O error for file '%s'.");
1451
1452 ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
1453 _("File error"),
1454 msg,
1455 GLOBALS->xhb_filepath
1456 );
1457 }
1458 }
1459
1460
1461 void ui_mainwindow_update(GtkWidget *widget, gpointer user_data)
1462 {
1463 struct hbfile_data *data;
1464 gint flags;
1465
1466 DB( g_print("\n[ui-mainwindow] update %p\n", user_data) );
1467
1468 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1469 //data = INST_DATA(widget);
1470
1471 flags = GPOINTER_TO_INT(user_data);
1472
1473 /* set window title */
1474 if(flags & UF_TITLE)
1475 {
1476 gchar *basename;
1477 gchar *changed;
1478
1479 DB( g_print(" 1: wintitle %p\n", data->wintitle) );
1480
1481 basename = g_path_get_basename(GLOBALS->xhb_filepath);
1482
1483 DB( g_print(" global changes: %d\n", GLOBALS->changes_count) );
1484
1485 g_free(data->wintitle);
1486
1487 changed = (GLOBALS->changes_count > 0) ? "*" : "";
1488
1489 #if MYDEBUG == 1
1490 data->wintitle = g_strdup_printf("%s%s (%d)- %s - " PROGNAME, changed, basename, GLOBALS->changes_count, GLOBALS->owner);
1491 #else
1492 data->wintitle = g_strdup_printf("%s%s - %s - " PROGNAME, changed, basename, GLOBALS->owner);
1493 #endif
1494
1495 gtk_window_set_title (GTK_WINDOW (gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), data->wintitle);
1496
1497 g_free(basename);
1498 }
1499
1500 /* update disabled things */
1501 if(flags & UF_SENSITIVE)
1502 {
1503 GtkTreeSelection *selection;
1504 GtkTreeModel *model;
1505 GtkTreeIter iter;
1506 GtkTreePath *path;
1507 gboolean active,sensitive;
1508
1509 DB( g_print(" 2: disabled, opelist count\n") );
1510
1511 //#1656531
1512 data->acc = NULL;
1513
1514 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc));
1515 active = gtk_tree_selection_get_selected(selection, &model, &iter);
1516 if(active)
1517 {
1518 Account *acc;
1519 gint depth;
1520
1521 path = gtk_tree_model_get_path(model, &iter);
1522 depth = gtk_tree_path_get_depth(path);
1523
1524 if( depth > 1 )
1525 {
1526 DB( g_print(" depth is %d\n", depth) );
1527
1528 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPACC_DATAS, &acc, -1);
1529 data->acc = acc;
1530 }
1531 else
1532 active = FALSE;
1533 }
1534
1535 DB( g_print(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) );
1536
1537 // save
1538 sensitive = (GLOBALS->changes_count != 0 ) ? TRUE : FALSE;
1539 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Save"), sensitive);
1540
1541 // backup
1542 sensitive = ( (GLOBALS->changes_count != 0) && GLOBALS->xhb_hasrevert ) ? TRUE : FALSE;
1543 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Revert"), sensitive);
1544 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/OpenBak"), sensitive);
1545
1546 // define off ?
1547 sensitive = GLOBALS->define_off == 0 ? TRUE : FALSE;
1548 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Account"), sensitive);
1549 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Payee"), sensitive);
1550 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Category"), sensitive);
1551 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
1552 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/EditMenu/Preferences"), sensitive);
1553
1554 // empty account list: disable Archives, Edit, Filter, Add, Statistics, Overdrawn, Car Cost
1555 sensitive = da_acc_length() > 0 ? TRUE : FALSE;
1556 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Close"), sensitive);
1557 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Archive"), sensitive);
1558 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddTxn"), sensitive);
1559 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowTxn"), sensitive);
1560 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RStatistics"), sensitive);
1561 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RTrendTime"), sensitive);
1562 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBudget"), sensitive);
1563 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBalance"), sensitive);
1564 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RVehiculeCost"), sensitive);
1565
1566 // empty category list: disable Budget
1567 sensitive = da_cat_length() > 1 ? TRUE : FALSE;
1568 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
1569
1570 //#1501129 no need to disable, P & C can be created from assign dialog
1571 //sensitive = ((da_cat_length() > 1) || (da_pay_length() > 1)) ? TRUE : FALSE;
1572 //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive);
1573
1574 // empty archive list: disable scheduled check
1575 sensitive = g_list_length(GLOBALS->arc_list) > 0 ? TRUE : FALSE;
1576 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddScheduled"), sensitive);
1577
1578 // no active account: disable Edit, Over
1579 //disabled 5.2.6
1580 /* sensitive = (active == TRUE ) ? TRUE : FALSE;
1581 if(data->acc && data->acc->window != NULL)
1582 sensitive = FALSE;
1583 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowTxn"), sensitive);
1584 */
1585 }
1586
1587 /* update toolbar, list */
1588 if(flags & UF_VISUAL)
1589 {
1590 DB( g_print(" 8: visual\n") );
1591
1592 if(PREFS->toolbar_style == 0)
1593 gtk_toolbar_unset_style(GTK_TOOLBAR(data->toolbar));
1594 else
1595 gtk_toolbar_set_style(GTK_TOOLBAR(data->toolbar), PREFS->toolbar_style-1);
1596
1597 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_acc), PREFS->grid_lines);
1598 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
1599
1600 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_upc), PREFS->grid_lines);
1601 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc));
1602
1603 DB( g_print(" - show toolbar=%d\n", PREFS->wal_toolbar) );
1604 if(PREFS->wal_toolbar)
1605 gtk_widget_show(GTK_WIDGET(data->toolbar));
1606 else
1607 gtk_widget_hide(GTK_WIDGET(data->toolbar));
1608
1609
1610 DB( g_print(" - show top_spending=%d\n", PREFS->wal_spending) );
1611
1612 hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), PREFS->date_range_wal);
1613
1614 if(PREFS->wal_spending)
1615 gtk_widget_show(GTK_WIDGET(data->GR_top));
1616 else
1617 gtk_widget_hide(GTK_WIDGET(data->GR_top));
1618
1619
1620
1621 DB( g_print(" - show upcoming=%d\n", PREFS->wal_upcoming) );
1622 if(PREFS->wal_upcoming)
1623 gtk_widget_show(GTK_WIDGET(data->GR_upc));
1624 else
1625 gtk_widget_hide(GTK_WIDGET(data->GR_upc));
1626
1627 DB( g_print(" minor %d\n", PREFS->euro_active) );
1628 gtk_action_set_visible(gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor"), PREFS->euro_active);
1629 }
1630
1631 /* update balances */
1632 if(flags & UF_BALANCE)
1633 {
1634
1635 DB( g_print(" 4: balances\n") );
1636
1637 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
1638
1639 //minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
1640
1641 /*
1642 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[0]), data->bank, minor);
1643 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[1]), data->today, minor);
1644 hb-label_set_colvalue(GTK_LABEL(data->TX_balance[2]), data->future, minor);
1645 */
1646 }
1647
1648 if(flags & UF_REFRESHALL)
1649 {
1650 DB( g_print(" 16: refreshall\n") );
1651
1652 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
1653 ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
1654 ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
1655 ui_hub_transaction_populate(data);
1656 }
1657
1658
1659 }
1660
1661
1662
1663 static void
1664 ui_mainwindow_onRowActivated (GtkTreeView *treeview,
1665 GtkTreePath *path,
1666 GtkTreeViewColumn *col,
1667 gpointer userdata)
1668 {
1669 GtkTreeModel *model;
1670 GtkTreeIter iter;
1671
1672 DB( g_print ("\n[ui-mainwindow] A row has been double-clicked!\n") );
1673
1674 model = gtk_tree_view_get_model(treeview);
1675
1676 if (gtk_tree_model_get_iter(model, &iter, path))
1677 {
1678 Account *acc;
1679
1680 gtk_tree_model_get(model, &iter, LST_DSPACC_DATAS, &acc, -1);
1681
1682 if( acc != NULL )
1683 {
1684
1685 DB( g_print ("Double-clicked row contains name %s\n", acc->name) );
1686
1687 ui_mainwindow_action_showtransactions(NULL);
1688
1689 //g_free(name);
1690 }
1691 }
1692 }
1693
1694
1695 static void ui_mainwindow_destroy(GtkTreeView *treeview, gpointer user_data)
1696 {
1697 DB( g_print("\n[ui-mainwindow] destroy\n") );
1698
1699 }
1700
1701
1702 /*
1703 **
1704 */
1705 static gboolean ui_mainwindow_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1706 {
1707 struct hbfile_data *data = user_data;
1708 struct WinGeometry *wg;
1709 gboolean retval = FALSE;
1710
1711 GValue widget_value = G_VALUE_INIT;
1712 ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL);
1713
1714 DB( g_print("\n[ui-mainwindow] delete-event\n") );
1715
1716 //store position and size
1717 wg = &PREFS->wal_wg;
1718 gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
1719 gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
1720 GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(widget));
1721 GdkWindowState state = gdk_window_get_state(gdk_window);
1722 wg->s = (state & GDK_WINDOW_STATE_MAXIMIZED) ? 1 : 0;
1723 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) );
1724
1725 PREFS->wal_vpaned = gtk_paned_get_position(GTK_PANED(data->vpaned));
1726 PREFS->wal_hpaned = gtk_paned_get_position(GTK_PANED(data->hpaned));
1727 DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
1728
1729 if(PREFS->pnl_list_tab)
1730 g_free(PREFS->pnl_list_tab);
1731 PREFS->pnl_list_tab = g_strdup(gtk_stack_get_visible_child_name(GTK_STACK(data->stack)));
1732
1733 //todo
1734 if(ui_dialog_msg_savechanges(widget, NULL) == FALSE)
1735 {
1736 retval = TRUE;
1737 }
1738 else
1739 {
1740 //todo: retval is useless and below should move to destroy
1741 retval = TRUE;
1742 gtk_widget_destroy(data->LV_top);
1743
1744 g_free(data->wintitle);
1745 da_flt_free(data->filter);
1746 g_free(user_data);
1747
1748 gtk_main_quit();
1749 }
1750
1751 //TRUE:stop other handlers from being invoked for the event | FALSE: propagate
1752 return retval;
1753 }
1754
1755
1756 static void ui_mainwindow_recent_chooser_item_activated_cb (GtkRecentChooser *chooser, struct hbfile_data *data)
1757 {
1758 gchar *uri, *path;
1759 GError *error = NULL;
1760
1761 uri = gtk_recent_chooser_get_current_uri (chooser);
1762
1763 path = g_filename_from_uri (uri, NULL, NULL);
1764 if (error)
1765 {
1766 g_warning ("Could not convert uri \"%s\" to a local path: %s", uri, error->message);
1767 g_error_free (error);
1768 return;
1769 }
1770
1771 if( ui_dialog_msg_savechanges(data->window, NULL) == TRUE )
1772 {
1773
1774 //todo: FixMe
1775 /*
1776 if (! load)
1777 {
1778 gpw_recent_remove (gpw, path);
1779 }
1780 */
1781
1782 hbfile_change_filepath(path);
1783 ui_mainwindow_open_internal(data->window, NULL);
1784 }
1785 else
1786 {
1787 g_free (path);
1788 }
1789 g_free (uri);
1790 }
1791
1792
1793 void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path)
1794 {
1795 GtkRecentData *recent_data;
1796 gchar *uri;
1797 GError *error = NULL;
1798
1799 DB( g_print("\n[ui-mainwindow] recent_add\n") );
1800
1801 DB( g_print(" - file has .xhb suffix = %d\n", g_str_has_suffix (path, ".xhb") ) );
1802
1803 if( g_str_has_suffix (path, ".xhb") == FALSE ) //ignore reverted file
1804 return;
1805
1806 uri = g_filename_to_uri (path, NULL, &error);
1807 if (error)
1808 {
1809 g_warning ("Could not convert uri \"%s\" to a local path: %s", uri, error->message);
1810 g_error_free (error);
1811 return;
1812 }
1813
1814 recent_data = g_slice_new (GtkRecentData);
1815
1816 recent_data->display_name = NULL;
1817 recent_data->description = NULL;
1818 recent_data->mime_type = "application/x-homebank";
1819 recent_data->app_name = (gchar *) g_get_application_name ();
1820 recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
1821 recent_data->groups = NULL;
1822 recent_data->is_private = FALSE;
1823
1824 if (!gtk_recent_manager_add_full (data->recent_manager,
1825 uri,
1826 recent_data))
1827 {
1828 g_warning ("Unable to add '%s' to the list of recently used documents", uri);
1829 }
1830
1831 g_free (uri);
1832 g_free (recent_data->app_exec);
1833 g_slice_free (GtkRecentData, recent_data);
1834
1835 }
1836
1837
1838
1839
1840
1841 enum
1842 {
1843 TARGET_URI_LIST
1844 };
1845
1846 static GtkTargetEntry drop_types[] =
1847 {
1848 {"text/uri-list", 0, TARGET_URI_LIST}
1849 };
1850
1851 static void ui_mainwindow_drag_data_received (GtkWidget *widget,
1852 GdkDragContext *context,
1853 gint x, gint y,
1854 GtkSelectionData *selection_data,
1855 guint info, guint time, GtkWindow *window)
1856 {
1857 gchar **uris, **str;
1858 gchar *newseldata;
1859 gint n_uris, filetype, slen;
1860 GError *error = NULL;
1861
1862 if (info != TARGET_URI_LIST)
1863 return;
1864
1865 DB( g_print("\n[ui-mainwindow] drag_data_received\n") );
1866
1867 /* On MS-Windows, it looks like `selection_data->data' is not NULL terminated. */
1868 slen = gtk_selection_data_get_length(selection_data);
1869 newseldata = g_new (gchar, slen + 1);
1870 memcpy (newseldata, gtk_selection_data_get_data(selection_data), slen);
1871 newseldata[slen] = 0;
1872 //DB( g_print(" - seldata ='%s'\n", gtk_selection_data_get_data(selection_data) ) );
1873 //DB( g_print(" - newseldata ='%s'\n", newseldata ) );
1874
1875 uris = g_uri_list_extract_uris (newseldata);
1876 n_uris = g_strv_length(uris);
1877 DB( g_print(" - dragged %d files (len=%d)\n", n_uris, slen ) );
1878
1879 g_free(newseldata);
1880
1881 //single file: check for xhb
1882 if(n_uris == 1)
1883 {
1884 filetype = hb_filename_type_get_by_extension(*uris);
1885
1886 DB( g_print(" - filetype is homebank (%d)\n", filetype) );
1887
1888 if( filetype == FILETYPE_HOMEBANK )
1889 {
1890 gchar *path = g_filename_from_uri (*uris, NULL, &error);
1891
1892 if( path != NULL )
1893 {
1894 DB( g_print(" - path is '%s'\n", path) );
1895 hbfile_change_filepath(g_strdup(path));
1896 ui_mainwindow_open_internal(GTK_WIDGET(window), NULL);
1897 goto end_drop;
1898 }
1899 else
1900 {
1901 g_warning ("Could not convert uri to local path: %s", error->message);
1902 g_error_free (error);
1903 }
1904 g_free (path);
1905 }
1906 /* we no more manage error here
1907 ui_dialog_msg_infoerror(GTK_WINDOW(window), GTK_MESSAGE_ERROR,
1908 _("File error"),
1909 _("The file %s is not a valid HomeBank file."),
1910 path);
1911 */
1912 }
1913
1914 //collect known filetype to import
1915 DB( g_print(" - collect %d files\n", n_uris) );
1916
1917 gchar **paths = g_new (gchar *, n_uris + 1);
1918 slen = 0;
1919 for (str = uris; *str; str++)
1920 {
1921 filetype = hb_filename_type_get_by_extension(*str);
1922 if( filetype != FILETYPE_HOMEBANK && filetype != FILETYPE_UNKNOWN )
1923 {
1924 gchar *path = g_filename_from_uri (*str, NULL, NULL);
1925
1926 if( path != NULL )
1927 {
1928 DB( g_print(" - append %d '%s'\n", slen, path ) );
1929 paths[slen++] = path;
1930 }
1931 }
1932 }
1933 paths[slen] = NULL;
1934
1935 if( slen > 0 )
1936 {
1937 ui_import_assistant_new( paths );
1938 }
1939
1940
1941 end_drop:
1942 g_strfreev (uris);
1943 }
1944
1945
1946 static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager)
1947 {
1948 GtkWidget *recent_menu;
1949 GtkRecentFilter *filter;
1950
1951 recent_menu = gtk_recent_chooser_menu_new_for_manager (manager);
1952 gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (recent_menu), FALSE);
1953 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (recent_menu), GTK_RECENT_SORT_MRU);
1954 //todo: add a user pref for this
1955 gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (recent_menu), 10);
1956 gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (recent_menu), FALSE);
1957 //gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (recent_menu), TRUE);
1958
1959 filter = gtk_recent_filter_new ();
1960 //gtk_recent_filter_add_application (filter, g_get_application_name());
1961 gtk_recent_filter_add_pattern (filter, "*.[Xx][Hh][Bb]");
1962 gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (recent_menu), filter);
1963
1964 return recent_menu;
1965 }
1966
1967
1968 static void ui_mainwindow_create_menu_bar_and_toolbar(struct hbfile_data *data, GtkWidget *mainvbox)
1969 {
1970 GtkUIManager *manager;
1971 GtkActionGroup *actions;
1972 GtkAction *action;
1973 GError *error = NULL;
1974
1975 manager = gtk_ui_manager_new ();
1976 data->manager = manager;
1977
1978 gtk_window_add_accel_group (GTK_WINDOW (data->window),
1979 gtk_ui_manager_get_accel_group(manager));
1980
1981 actions = gtk_action_group_new ("MainWindow");
1982 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
1983
1984 gtk_action_group_add_actions (actions,
1985 entries,
1986 n_entries,
1987 NULL);
1988
1989 gtk_action_group_add_toggle_actions (actions,
1990 toggle_entries,
1991 n_toggle_entries,
1992 NULL);
1993
1994 gtk_ui_manager_insert_action_group (data->manager, actions, 0);
1995 g_object_unref (actions);
1996 data->actions = actions;
1997
1998 /* set short labels to use in the toolbar */
1999 action = gtk_action_group_get_action(actions, "Open");
2000 g_object_set(action, "short_label", _("Open"), NULL);
2001
2002 //action = gtk_action_group_get_action(action_group, "Save");
2003 //g_object_set(action, "is_important", TRUE, NULL);
2004
2005 action = gtk_action_group_get_action(actions, "Account");
2006 g_object_set(action, "short_label", _("Account"), NULL);
2007
2008 action = gtk_action_group_get_action(actions, "Payee");
2009 g_object_set(action, "short_label", _("Payee"), NULL);
2010
2011 action = gtk_action_group_get_action(actions, "Category");
2012 g_object_set(action, "short_label", _("Category"), NULL);
2013
2014 action = gtk_action_group_get_action(actions, "Archive");
2015 //TRANSLATORS: an archive is stored transaction buffers (kind of bookmark to prefill manual insertion)
2016 g_object_set(action, "short_label", _("Archive"), NULL);
2017
2018 action = gtk_action_group_get_action(actions, "Budget");
2019 g_object_set(action, "short_label", _("Budget"), NULL);
2020
2021 action = gtk_action_group_get_action(actions, "ShowTxn");
2022 g_object_set(action, "short_label", _("Show"), NULL);
2023
2024 action = gtk_action_group_get_action(actions, "AddTxn");
2025 g_object_set(action, "is_important", TRUE, "short_label", _("Add"), NULL);
2026
2027 action = gtk_action_group_get_action(actions, "RStatistics");
2028 g_object_set(action, "short_label", _("Statistics"), NULL);
2029
2030 action = gtk_action_group_get_action(actions, "RBudget");
2031 g_object_set(action, "short_label", _("Budget"), NULL);
2032
2033 action = gtk_action_group_get_action(actions, "RBalance");
2034 g_object_set(action, "short_label", _("Balance"), NULL);
2035
2036 action = gtk_action_group_get_action(actions, "RVehiculeCost");
2037 g_object_set(action, "short_label", _("Vehicle cost"), NULL);
2038
2039 /* now load the UI definition */
2040 gtk_ui_manager_add_ui_from_string (data->manager, ui_info, -1, &error);
2041 if (error != NULL)
2042 {
2043 g_message ("Building menus failed: %s", error->message);
2044 g_error_free (error);
2045 }
2046
2047
2048 data->recent_manager = gtk_recent_manager_get_default ();
2049
2050 data->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
2051 gtk_box_pack_start (GTK_BOX (mainvbox),
2052 data->menubar,
2053 FALSE,
2054 FALSE,
2055 0);
2056
2057 /* recent files menu */
2058 data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
2059
2060 g_signal_connect (data->recent_menu,
2061 "item-activated",
2062 G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
2063 data);
2064
2065 GtkWidget *widget = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/RecentMenu");
2066 gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), data->recent_menu);
2067
2068
2069 data->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
2070 gtk_box_pack_start (GTK_BOX (mainvbox),
2071 data->toolbar,
2072 FALSE,
2073 FALSE,
2074 0);
2075
2076 /* add the custom Open button to the toolbar */
2077 GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_HB_FILE_OPEN, GTK_ICON_SIZE_BUTTON);
2078 GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open"));
2079 gtk_tool_item_set_tooltip_text (open_button, _("Open a file"));
2080
2081 GtkWidget *recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
2082 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), recent_menu);
2083 gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), _("Open a recently used file"));
2084
2085 g_signal_connect (recent_menu,
2086 "item-activated",
2087 G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
2088 data);
2089
2090 action = gtk_action_group_get_action (data->actions, "Open");
2091 g_object_set (action, "short_label", _("Open"), NULL);
2092 //gtk_action_connect_proxy (action, GTK_WIDGET (open_button));
2093 gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button), action);
2094
2095 gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), open_button, 1);
2096
2097 }
2098
2099
2100 /*
2101 ** the window creation
2102 */
2103 GtkWidget *create_hbfile_window(GtkWidget *do_widget)
2104 {
2105 struct hbfile_data *data;
2106 struct WinGeometry *wg;
2107 GtkWidget *mainvbox, *vbox, *box, *vpaned, *hpaned, *sidebar, *stack;
2108 GtkWidget *widget, *page;
2109 GtkWidget *window;
2110 GtkAction *action;
2111
2112 DB( g_print("\n[ui-mainwindow] create main window\n") );
2113
2114 data = g_malloc0(sizeof(struct hbfile_data));
2115 if(!data) return NULL;
2116
2117 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2118
2119 //store our window private data
2120 g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
2121 DB( g_print(" - new window=%p, inst_data=%p\n", window, data) );
2122
2123 // this is our mainwindow, so store it to GLOBALS data
2124 data->window = window;
2125 GLOBALS->mainwindow = window;
2126
2127 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2128 gtk_container_add (GTK_CONTAINER (window), mainvbox);
2129
2130 ui_mainwindow_create_menu_bar_and_toolbar (data, mainvbox);
2131
2132 #if HB_UNSTABLE_SHOW == TRUE
2133 GtkWidget *bar, *label;
2134
2135 bar = gtk_info_bar_new ();
2136 gtk_box_pack_start (GTK_BOX (mainvbox), bar, FALSE, FALSE, 0);
2137 gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_WARNING);
2138 label = make_label(NULL, 0.5, 0.5);
2139 gtk_label_set_markup (GTK_LABEL(label), "Unstable Development Version");
2140 gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label, FALSE, FALSE, 0);
2141 #endif
2142
2143 /* Add the main area */
2144 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2145 //gtk_container_set_border_width (GTK_CONTAINER(vbox), SPACING_MEDIUM);
2146 gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
2147
2148 vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
2149 data->vpaned = vpaned;
2150 gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
2151
2152 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
2153 data->hpaned = hpaned;
2154 gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
2155
2156 widget = ui_hub_account_create(data);
2157 //gtk_widget_set_size_request (widget, 100, -1);
2158 gtk_paned_pack1 (GTK_PANED(hpaned), widget, FALSE, FALSE);
2159
2160 widget = ui_hub_spending_create(data);
2161 //gtk_widget_set_size_request (widget, -1, 100);
2162 gtk_paned_pack2 (GTK_PANED(hpaned), widget, TRUE, FALSE);
2163
2164 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2165 data->GR_upc = box;
2166 gtk_paned_pack2 (GTK_PANED(vpaned), box, TRUE, FALSE);
2167
2168 sidebar = gtk_stack_sidebar_new ();
2169 gtk_box_pack_start (GTK_BOX (box), sidebar, FALSE, FALSE, 0);
2170
2171 stack = gtk_stack_new ();
2172 //gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
2173 gtk_stack_sidebar_set_stack (GTK_STACK_SIDEBAR (sidebar), GTK_STACK (stack));
2174 data->stack = stack;
2175 gtk_box_pack_start (GTK_BOX (box), stack, TRUE, TRUE, 0);
2176
2177 page = ui_hub_scheduled_create(data);
2178 gtk_stack_add_titled (GTK_STACK (stack), page, "sched", _("Scheduled"));
2179 //gtk_paned_pack2 (GTK_PANED(vpaned), widget, TRUE, FALSE);
2180
2181 page = ui_hub_transaction_create(data, HUB_TXN_TYPE_FUTURE);
2182 gtk_stack_add_titled (GTK_STACK (stack), page, "futur", _("Future"));
2183
2184 page = ui_hub_transaction_create(data, HUB_TXN_TYPE_REMIND);
2185 gtk_stack_add_titled (GTK_STACK (stack), page, "remin", _("Remind"));
2186
2187
2188 //setup, init and show window
2189 wg = &PREFS->wal_wg;
2190 if(wg->s == 0)
2191 {
2192 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
2193 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
2194 }
2195 else
2196 gtk_window_maximize(GTK_WINDOW(window));
2197
2198 gtk_widget_show_all (window);
2199
2200 //#1662197/1660910 moved after resize/show
2201 DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
2202
2203 if(PREFS->wal_hpaned > 0)
2204 gtk_paned_set_position(GTK_PANED(data->hpaned), PREFS->wal_hpaned);
2205 if(PREFS->wal_vpaned > 0)
2206 gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned);
2207
2208 if( PREFS->pnl_list_tab != NULL )
2209 gtk_stack_set_visible_child_name (GTK_STACK(data->stack), PREFS->pnl_list_tab);
2210
2211
2212 //todo: move this elsewhere
2213 DB( g_print(" - setup stuff\n") );
2214
2215 data->filter = da_flt_malloc();
2216 filter_reset(data->filter);
2217 hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), PREFS->date_range_wal);
2218
2219 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Toolbar");
2220 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_toolbar);
2221 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Spending");
2222 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_spending);
2223 action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/BottomLists");
2224 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_upcoming);
2225
2226 /* Drag and drop support, set targets to NULL because we add the
2227 default uri_targets below */
2228
2229 /* support for opening a file by dragging onto the project window */
2230 gtk_drag_dest_set (GTK_WIDGET (window),
2231 GTK_DEST_DEFAULT_ALL,
2232 drop_types,
2233 G_N_ELEMENTS (drop_types),
2234 GDK_ACTION_COPY);
2235
2236 g_signal_connect (G_OBJECT (window), "drag-data-received",
2237 G_CALLBACK (ui_mainwindow_drag_data_received), window);
2238
2239 //connect all our signals
2240 DB( g_print(" - connect signals\n") );
2241
2242 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc)), "changed", G_CALLBACK (ui_mainwindow_selection), NULL);
2243 g_signal_connect (GTK_TREE_VIEW(data->LV_acc ), "row-activated", G_CALLBACK (ui_mainwindow_onRowActivated), GINT_TO_POINTER(2));
2244
2245 /* GtkWindow events */
2246 g_signal_connect (window, "delete-event", G_CALLBACK (ui_mainwindow_dispose), (gpointer)data);
2247 g_signal_connect (window, "destroy", G_CALLBACK (ui_mainwindow_destroy), NULL);
2248
2249 //gtk_action_group_set_sensitive(data->actions, FALSE);
2250
2251 return window;
2252 }
2253
This page took 0.14841 seconds and 4 git commands to generate.