From: Charles McGarvey Date: Wed, 28 Dec 2016 22:59:58 +0000 (-0700) Subject: Merge branch 'master' into ext-perl X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=613fd4014fa5814bf2adce50574d520df8927ce1;hp=-c;p=chaz%2Fhomebank Merge branch 'master' into ext-perl --- 613fd4014fa5814bf2adce50574d520df8927ce1 diff --combined Makefile.am index ac9cc1c,0a66203..de75d0f --- a/Makefile.am +++ b/Makefile.am @@@ -1,9 -1,7 +1,9 @@@ # HomeBank Makefile.am +ACLOCAL_AMFLAGS = -I m4 + #SUBDIRS = src - SUBDIRS = src data images mime po doc plugins -SUBDIRS = src data images mime pixmaps themes po doc ++SUBDIRS = src data images mime pixmaps themes po doc plugins # don't forget to do a 'make check' @@@ -20,9 -18,3 +20,9 @@@ DISTCLEANFILES = ... intltool-extract intltool-merge \ intltool-update \ po/.intltool-merge-cache + +run: all + PERL5LIB=src src/homebank + +debug: all + PERL5LIB=src gdb src/homebank diff --combined configure.ac index dfaa66d,b4680b5..83f6509 --- a/configure.ac +++ b/configure.ac @@@ -2,16 -2,13 +2,17 @@@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) - AC_INIT([homebank], [4.6.3]) + AC_INIT([homebank], [5.1.2]) + #AC_INIT([homebank], [x.x-rc]) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE([1.9 foreign]) +LT_PREREQ([2.2]) +LT_INIT([dlopen]) +AC_CONFIG_MACRO_DIR([m4]) + # If the source code has changed at all, increment REVISION # If any interfaces have been added, removed, or changed, increment CURRENT, and set REVISION to 0. # If any interfaces have been added since the last public release, then increment AGE. @@@ -25,19 -22,26 +26,26 @@@ AC_PROG_INSTAL AC_PROG_INTLTOOL # Checks for libraries. - PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.24 glib-2.0 >= 2.28 gmodule-2.0 >= 2.28) -PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.12 glib-2.0 >= 2.39) ++PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.12 glib-2.0 >= 2.39 gmodule-2.0 >= 2.39) AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) AC_CHECK_LIB(m, pow) + PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26]) + AC_SUBST(LIBSOUP_CFLAGS) + AC_SUBST(LIBSOUP_LIBS) + # general usage flags CFLAGS="${CFLAGS} -Wall -Wmissing-prototypes" + # disable deprecated warnings + CFLAGS="${CFLAGS} -Wno-deprecated-declarations" + # extended flags #CFLAGS="${CFLAGS} -Wextra -Wno-unused-parameter" - #valgrind flags - #CFLAGS="${CFLAGS} -g -O0" + # profiling valgrind/gprof flags + #CFLAGS="${CFLAGS} -g -O0 -pg" # pre-relase # 2 - error as warning for #CFLAGS="${CFLAGS} -Werror" @@@ -62,7 -66,7 +70,7 @@@ the then AC_CHECK_LIB(ofx, ofx_set_status_cb, OFX_0_7="-DOFX_ENABLE") DEPS_LIBS="-lofx ${DEPS_LIBS}" - CFLAGS="${CFLAGS} $OFX_0_7" + CPPFLAGS="${CPPFLAGS} $OFX_0_7" else noofx=true AC_MSG_RESULT([Libofx header missing. Check your libofx installation]) @@@ -74,41 -78,6 +82,41 @@@ els fi AM_CONDITIONAL(NOOFX, test x$noofx = xtrue) +AC_ARG_WITH(perl, + [ --with-perl build with perl plug-in support [default=without]], + [build_perl=$withval], + [build_perl=no] +) +if test x$build_perl != xno +then + test x$build_perl != xyes -a -x "$build_perl" && PERL=$build_perl + AC_PATH_PROG(PERL, perl, perl) + AC_MSG_CHECKING(if perl can be embedded) + if $PERL -MExtUtils::Embed -e "use v5.8" >/dev/null 2>&1 + then + AC_MSG_RESULT(yes) + CPPFLAGS="${CPPFLAGS} -DPERL_ENABLE" + PERL_CPPFLAGS="`$PERL -MExtUtils::Embed -e ccopts`" + PERL_OBJS="ext-perl.o perlxsi.o" + PERL_PRIVLIBEXP="`$PERL -MConfig -e 'print $Config{privlibexp}'`" + PERL_SITELIBEXP="`$PERL -MConfig -e 'print $Config{sitelibexp}'`" + DEPS_LIBS="`$PERL -MExtUtils::Embed -e ldopts` ${DEPS_LIBS}" + if test -e "$PERL_SITELIBEXP/ExtUtils/xsubpp" + then + XSUBPP="$PERL $PERL_SITELIBEXP/ExtUtils/xsubpp" + else + XSUBPP="$PERL $PERL_PRIVLIBEXP/ExtUtils/xsubpp" + fi + else + AC_MSG_ERROR([no working perl found, or perl not version >= 5.8]) + fi +fi +AC_SUBST(PERL_CPPFLAGS) +AC_SUBST(PERL_OBJS) +AC_SUBST(PERL_PRIVLIBEXP) +AC_SUBST(PERL_SITELIBEXP) +AC_SUBST(XSUBPP) + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([libintl.h locale.h stdlib.h string.h]) @@@ -123,7 -92,7 +131,7 @@@ AC_C_VOLATIL AC_CHECK_FUNCS([floor localeconv memset modf pow setlocale sqrt strcasecmp strtoul]) # International support - ALL_LINGUAS="af ar ast be bg br ca cs cy da de el en_AU en_CA en_GB es et eu fa fi fr ga gl he hr hu id is it ja ka ko lt lv mr ms nb nds nl oc pl pt_BR pt pt_PT ro ru si sk sl sr sv tr uk vi zh_CN zh_TW" + ALL_LINGUAS="af ar ast be bg br ca cs cy da de el en_AU en_CA en_GB es et eu fa fi fr gl he hr hu id is it ja ko lt lv mr ms nb nds nl oc pl pt_BR pt pt_PT ro ru si sk sl sr sv tr uk vi zh_CN zh_TW" AM_GLIB_GNU_GETTEXT @@@ -136,14 -105,15 +144,16 @@@ Makefil src/Makefile data/homebank.desktop.in data/Makefile - data/icons/Makefile data/datas/Makefile images/Makefile mime/Makefile - po/Makefile.in + pixmaps/Makefile + themes/Makefile + themes/hicolor/Makefile + po/Makefile.in doc/Makefile doc/images/Makefile +plugins/Makefile ]) AC_OUTPUT @@@ -156,7 -126,6 +166,7 @@@ echo $PACKAGE $VERSIO echo echo Compiler................ : $CC echo Build with OFX support.. : $build_ofx +echo Build with perl support. : $build_perl if test "x$noofx" = "xtrue" ; then echo ........................ : **error** libofx header is missing, ofx feature will be disabled. Check your libofx installation fi diff --combined plugins/hello.pl index c6abdf9,0000000..9171bb2 mode 100644,000000..100644 --- a/plugins/hello.pl +++ b/plugins/hello.pl @@@ -1,281 -1,0 +1,234 @@@ + +# NAME: Hello World +# VERSION: 0.01 +# ABSTRACT: This is the "hello world" of HomeBank plugins. +# AUTHOR: Charles McGarvey +# WEBSITE: http://acme.tld/ +# (These comments are read, before the plugin is executed, to provide some +# information to HomeBank and the user about what this plugin is.) + +eval { HomeBank->version } or die "Cannot run outside of HomeBank"; + +use warnings; +use strict; + +use Scalar::Util qw/weaken/; + +#use Moose; + +#has "cool_beans", + #is => 'rw', + #isa => 'Str', + #lazy => 1, + #default => "Booya!!!"; + + +our $counter = 0; +our $temp; + +my $ACC; + +sub new { + my $class = shift; + my $self = $class->SUPER::new(@_); + + $self->on(account_inserted => sub { + my $acc = shift; + print "account inserted: ", Dumper($acc); + print "account name is ", $acc->name, " and balance is ", $acc->bank_balance, "\n"; + #$acc->name("FOOOOBAR!"); + if ($acc->name eq 'Vacation') { + $acc->remove; + $ACC = $acc; + } + print Dumper($acc->is_inserted); + if ($acc->is_inserted) { + print "IT IS INSERTED\n"; + } else { + print "not inserted\n"; + } + print Dumper($acc->transactions); + }); + + #print $self->cool_beans, "\n"; + #$self->cool_beans(123); + #print $self->cool_beans, "\n"; + - $self->create_menuitem; - + $self; +} + +sub on_create_main_window { + my $self = shift; + my $window = shift; + + if (!$window) { - require Gtk2; ++ require Gtk3; + $window = HomeBank->main_window; + } + + Dump($window); + print Dumper($window); + $window->set_title("foo bar baz"); + print $window->get_title, "\n"; + + HomeBank->hook("my_hook", $window); - - $self->create_menuitem; +} + +my $test_win; + +sub on_test { + my $self = shift; - require Gtk2; ++ require Gtk3; + - my $window = Gtk2::Window->new('toplevel'); ++ my $window = Gtk3::Window->new('toplevel'); + use Devel::Peek; + Dump($window); + print Dumper($window); + $window->set_title("Hello World"); - #$window->signal_connect(delete_event => sub { Gtk2->main_quit }); ++ #$window->signal_connect(delete_event => sub { Gtk3->main_quit }); + $window->signal_connect(delete_event => sub { undef $test_win }); + - my $button = Gtk2::Button->new('Click Me!'); ++ my $button = Gtk3::Button->new('Click Me!'); + Dump($button); + print Dumper($button); + $button->signal_connect(clicked => sub { - print "Hello Gtk2-Perl: $counter (perl plugin: $self)\n"; ++ print "Hello Gtk3-Perl: $counter (perl plugin: $self)\n"; + $counter++; + #if ($temp->is_inserted) { + #print "$temp is inserted\n"; + #} else { + #print "$temp is NOT inserted\n"; + #} + #if ($counter == 5) { + #$temp = undef; + #} + my $acc = HomeBank::Account->get(rand(10)); + print "Changin account named ", $acc->name, " to ", $acc->name($acc), "\n"; + HomeBank->main_window->queue_draw; + + }); + $window->add($button); + + $window->show_all; + $test_win = $window; + + weaken $self; +} + +sub on_enter_main_loop { + my $self = shift; + + use Data::Dumper; + print Dumper(\@_); + my $t = HomeBank::Transaction->new; + print "Transaction:::::::: $t: ", $t->amount, "\n"; + + $temp = HomeBank::Account->get(7); + print "retained account: ", $temp->name, "\n"; + - #require Gtk2; ++ #require Gtk3; + # + my $txn = HomeBank::Transaction->new; + $txn->amount(12.3456); + print Dumper($txn), $txn->amount, "\n"; + #$txn->open; + + my @ret = HomeBank->hook("my_hook", @_, $temp, [qw/foo bar baz/, $txn], { asf => 42, quux => \1, meh => HomeBank->main_window }); + #my @ret = HomeBank->hook("my_hook", @_, HomeBank->main_window, { + #foo => 'bar', baz => 42 + #}); + print Dumper(\@ret); + + print "adding back account...\n"; + $ACC->name("vacation with a different name"); + $ACC->insert; + HomeBank::Account->compute_balances; + print "account name is ", $ACC->name, " and balance is ", $ACC->balance, "\n"; + print Dumper($ACC->transactions); + + my $cloned = $ACC->clone; + $cloned->name("vacation copy"); + $cloned->insert; + #my $asdf = $cloned->open; + #$asdf->set_title("this is a new friggin account"); + + #my $z = HomeBank::Account->get_by_name('Checking'); + for my $xc (HomeBank::File->transactions) { + use DateTime; + my $num = $xc->date; + my $date = DateTime->new($xc->date)->datetime; + print "transaction of amount: ", $xc->amount, "\t", $xc->wording, ", ", $xc->info, ", $num, $date\n"; + } + + HomeBank::File->owner('Billy Murphy'); + #HomeBank::File->anonymize; + print HomeBank::File->owner, "\n"; + + HomeBank::File->baz($ACC); +} + +sub on_deep_hook_recursion { + my $self = shift; + my $level = shift; + print STDERR "recursion is too deep ($level)\n"; + exit -2; +} + +sub on_my_hook { + my $self = shift; + print "This is MY HOOK!!!!!!\n"; + print Dumper(\@_); + + print Dumper($_[2]); + Dump($_[2]); + if ($_[2]) { + print "meh\n"; + } + if ($_[2]->isa('HomeBank::Boolean')) { + print "it is a home;;boolean\n"; + } + if ($_[2]->isa('Types::Serialiser::Boolean')) { + print "it is a types serialiser thingy\n"; + } + if ($_[2]->isa('HomeBank::BooleanBase')) { + print "it is a base bool\n"; + } + + my $win = $_[6]; + if ($win && ref($win) eq 'HASH') { + my $w = $win->{meh}; + if ($w) { + $w->set_title("this is MY HOOK setting a window title"); + } + } + #print Dumper($acc); + #print "transferred account: ", $acc->name, "\n"; + + #my $fff = HomeBank::File->foo({foo => 'asdf', bar => 123456789}); + my $fff = HomeBank::File->meh([qw/hello this is a test 82/, \1, {foo => 'bar'}, 48]); + print Dumper($fff); + + print "my hook done\n"; +} + +sub on_unhandled { + my ($self, $hook) = @_; + warn "Unhandled hook '$hook'\n"; + #HomeBank->warn($hook, 'Hook not handled.'); +} + - sub on_main_window_disposal { - my $self = shift; - print "main window disposed so forgetting about merge id et al.\n"; - delete $self->{merge_id}; - delete $self->{action_group}; - } - +sub DESTROY { + my $self = shift; + print "DESTROYING HELLO WORLD!!!!!!\n"; + if ($test_win) { + print "there is a test_win...\n"; + } + $test_win->destroy if $test_win; - - $self->destroy_menuitem; - } - - sub destroy_menuitem { - my $self = shift; - - return unless $self->{merge_id}; - - my $ui_manager = HomeBank->main_ui_manager; - $ui_manager->remove_action_group($self->{action_group}); - $ui_manager->remove_ui($self->{merge_id}); - } - - sub create_menuitem { - my $self = shift; - - return if $self->{merge_id}; - - require Gtk2; - - my $ui_manager = HomeBank->main_ui_manager; - print Dumper($ui_manager); - return unless $ui_manager; - - $self->{merge_id} = $ui_manager->new_merge_id; - $self->{action_group} = Gtk2::ActionGroup->new('HelloActionGroup'); - - my $action = Gtk2::Action->new(name => 'HelloPlugin', label => 'Booyah!', stock_id => 'prf-plugins', tooltip => 'blaaaargh'); - $action->signal_connect(activate => sub { print "hello!!!!!!!!\n" }); - $self->{action_group}->add_action($action); - - $ui_manager->insert_action_group($self->{action_group}, -1); - $ui_manager->add_ui($self->{merge_id}, 'ui/MenuBar/PluginMenu', 'HelloPlugin', 'HelloPlugin', 'auto', ''); - #$self->{merge_id} = $ui_manager->new_merge_id; - $ui_manager->add_ui($self->{merge_id}, 'ui/ToolBar', 'HelloPluginTool', 'HelloPlugin', 'auto', ''); +} + +sub EXECUTE { + print "the perl plugin is being configured.....\n"; + HomeBank->info("Hello Prefs", "YEEEEEARGGH!!!!!"); +} + +#__PACKAGE__->meta->make_immutable; diff --combined src/Makefile.am index 71c57f1,200e63c..484ce27 --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -1,8 -1,7 +1,8 @@@ common_defines = \ -DSHARE_DIR=\""$(pkgdatadir)"\" \ - -DDATA_DIR=\""$(datadir)"\" + -DDATA_DIR=\""$(datadir)"\" \ + -DPKGLIB_DIR=\""$(pkglibdir)"\" bin_PROGRAMS = homebank @@@ -22,6 -21,10 +22,10 @@@ homebank_SOURCES = enums.h \ gtk-chart.c \ gtk-chart.h \ + gtk-chart-colors.c \ + gtk-chart-colors.h \ + gtk-chart-stack.c \ + gtk-chart-stack.h \ gtk-dateentry.c \ gtk-dateentry.h \ hb-account.c \ @@@ -32,6 -35,8 +36,8 @@@ hb-assign.h \ hb-category.c \ hb-category.h \ + hb-currency.c \ + hb-currency.h \ hb-encoding.c \ hb-encoding.h \ hb-export.c \ @@@ -42,6 -47,9 +48,9 @@@ hb-hbfile.h \ hb-import.c \ hb-import.h \ + hb-import-ofx.c \ + hb-import-qif.c \ + hb-import-csv.c \ hb-misc.c \ hb-misc.h \ hb-payee.c \ @@@ -52,16 -60,14 +61,14 @@@ hb-report.h \ hb-tag.c \ hb-tag.h \ + hb-split.c \ + hb-split.h \ hb-transaction.c \ hb-transaction.h \ hb-xml.c \ hb-xml.h \ homebank.c \ homebank.h \ - imp_qif.c \ - imp_qif.h \ - import.c \ - import.h \ language.c \ language.h \ list_account.c \ @@@ -88,12 -94,16 +95,16 @@@ ui-archive.h \ ui-assign.c \ ui-assign.h \ + ui-assist-import.c \ + ui-assist-import.h \ ui-assist-start.c \ ui-assist-start.h \ ui-budget.c \ ui-budget.h \ ui-category.c \ ui-category.h \ + ui-currency.c \ + ui-currency.h \ ui-dialogs.c \ ui-dialogs.h \ ui-filter.c \ @@@ -104,38 -114,18 +115,41 @@@ ui-payee.h \ ui-pref.c \ ui-pref.h \ + ui-split.c \ + ui-split.h \ ui-transaction.c \ ui-transaction.h \ ui-widgets.c \ - ui-widgets.h + ui-widgets.h \ - gtk-chart-colors.c \ - gtk-chart-colors.h \ + refcount.h \ + ext.c \ + ext.h \ + ext-value.c \ + ext-value.h \ + ext-native.c \ + ext-perl.xs + +EXTRA_homebank_DEPENDENCIES = $(PERL_OBJS) - homebank_LDADD = $(PERL_OBJS) $(DEPS_LIBS) + homebank_LDADD = $(DEPS_LIBS) \ - $(LIBSOUP_LIBS) ++ $(LIBSOUP_LIBS) \ ++ $(PERL_OBJS) AM_CPPFLAGS = \ $(DEPS_CFLAGS) \ + $(LIBSOUP_CFLAGS) \ $(common_defines) +$(PERL_OBJS): CPPFLAGS += $(PERL_CPPFLAGS) + +ext-perl.c: ext-perl.xs typemap + $(XSUBPP) -typemap $(PERL_PRIVLIBEXP)/ExtUtils/typemap -typemap typemap $< >$@ + +perlxsi.c: Makefile + $(PERL) -MExtUtils::Embed -e xsinit -- -std HomeBank + +CLEANFILES = ext-perl.c perlxsi.c + +pluginsupportdir = $(pkglibdir) +pluginsupport_DATA = HomeBank.pm + diff --combined src/dsp_mainwindow.c index 98c5ea1,c96fdc6..707f68a --- a/src/dsp_mainwindow.c +++ b/src/dsp_mainwindow.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -22,17 -22,15 +22,17 @@@ #include "dsp_mainwindow.h" +#include "ext.h" + #include "list_account.h" #include "list_upcoming.h" #include "list_topspending.h" #include "dsp_account.h" - #include "import.h" - #include "imp_qif.h" + #include "ui-assist-import.h" #include "ui-assist-start.h" #include "ui-account.h" + #include "ui-currency.h" #include "ui-payee.h" #include "ui-category.h" #include "ui-archive.h" @@@ -61,6 -59,7 +61,7 @@@ /* Debug macros */ /****************************************************************************/ #define MYDEBUG 0 + #if MYDEBUG #define DB(x) (x); #else @@@ -83,6 -82,7 +84,7 @@@ static void ui_mainwindow_action_proper static void ui_mainwindow_action_close(void); static void ui_mainwindow_action_quit(void); + static void ui_mainwindow_action_defcurrency(void); static void ui_mainwindow_action_defaccount(void); static void ui_mainwindow_action_defpayee(void); static void ui_mainwindow_action_defcategory(void); @@@ -106,12 -106,11 +108,13 @@@ static void ui_mainwindow_action_budget static void ui_mainwindow_action_balance(void); static void ui_mainwindow_action_vehiclecost(void); - static void ui_mainwindow_action_pluginprefs(void); - - static void ui_mainwindow_action_import(void); + static void ui_mainwindow_action_import(GtkAction *action); static void ui_mainwindow_action_export(void); static void ui_mainwindow_action_anonymize(void); + static void ui_mainwindow_action_file_statistics(void); + ++static void ui_mainwindow_action_pluginprefs(void); + static void ui_mainwindow_action_help(void); void ui_mainwindow_action_help_welcome(void); static void ui_mainwindow_action_help_online(void); @@@ -141,90 -140,101 +144,107 @@@ void ui_mainwindow_recent_add (struct h static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data); void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data); - static void ui_mainwindow_showprefs(gint page); + void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path); ++static void ui_mainwindow_showprefs(gint page); + extern gchar *CYA_ACC_TYPE[]; + gchar *CYA_CATSUBCAT[] = { + N_("Category"), + N_("Subcategory"), + NULL + }; + + static GtkActionEntry entries[] = { - /* name, stock id, label */ + /* name, icon-name, label */ - { "FileMenu" , NULL, N_("_File"), NULL, NULL, NULL }, - { "EditMenu" , NULL, N_("_Edit"), NULL, NULL, NULL }, - { "ViewMenu" , NULL, N_("_View"), NULL, NULL, NULL }, - { "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL }, - { "TransactionMenu", NULL, N_("_Transactions"), NULL, NULL, NULL }, - { "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL }, - { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL }, - { "HelpMenu" , NULL, N_("_Help"), NULL, NULL, NULL }, + { "FileMenu" , NULL, N_("_File"), NULL, NULL, NULL }, + { "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL }, + { "EditMenu" , NULL, N_("_Edit"), NULL, NULL, NULL }, + { "ViewMenu" , NULL, N_("_View"), NULL, NULL, NULL }, + { "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL }, + { "TxnMenu" , NULL, N_("_Transactions"), NULL, NULL, NULL }, + { "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL }, + { "ToolsMenu" , NULL, N_("_Tools"), NULL, NULL, NULL }, ++ { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL }, + { "HelpMenu" , NULL, N_("_Help"), NULL, NULL, NULL }, // { "Import" , NULL, N_("Import") }, // { "Export" , NULL, N_("Export to") }, - /* name, stock id, label, accelerator, tooltip */ + /* name, icon-name, label, accelerator, tooltip */ /* FileMenu */ - { "New" , GTK_STOCK_NEW , N_("_New") , NULL, N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) }, - { "Open" , GTK_STOCK_OPEN , N_("_Open...") , NULL, N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) }, - { "Save" , GTK_STOCK_SAVE , N_("_Save") , NULL, N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) }, - { "SaveAs" , GTK_STOCK_SAVE_AS , N_("Save As...") , "S", N_("Save the current file with a different name"), G_CALLBACK (ui_mainwindow_action_saveas) }, - { "Revert" , GTK_STOCK_REVERT_TO_SAVED, N_("Revert") , NULL, N_("Revert to a saved version of this file"), G_CALLBACK (ui_mainwindow_action_revert) }, + { "New" , ICONNAME_NEW , N_("_New") , "N", N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) }, + { "Open" , ICONNAME_OPEN , N_("_Open...") , "O", N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) }, + { "Save" , ICONNAME_SAVE , N_("_Save") , "S", N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) }, + { "SaveAs" , ICONNAME_SAVE_AS , N_("Save _As...") , "S", N_("Save the current file with a different name"), G_CALLBACK (ui_mainwindow_action_saveas) }, + { "Revert" , ICONNAME_REVERT , N_("Revert") , NULL, N_("Revert to a saved version of this file"), G_CALLBACK (ui_mainwindow_action_revert) }, - { "Properties" , GTK_STOCK_PROPERTIES , N_("_Properties..."), NULL, N_("Configure the file"), G_CALLBACK (ui_mainwindow_action_properties) }, - { "Close" , GTK_STOCK_CLOSE , N_("_Close") , NULL, N_("Close the current file"), G_CALLBACK (ui_mainwindow_action_close) }, - { "Quit" , GTK_STOCK_QUIT , N_("_Quit") , NULL, N_("Quit homebank"), G_CALLBACK (ui_mainwindow_action_quit) }, + { "Properties" , ICONNAME_PROPERTIES , N_("Properties..."), NULL, N_("Configure the file"), G_CALLBACK (ui_mainwindow_action_properties) }, + { "Close" , ICONNAME_CLOSE , N_("_Close") , "W", N_("Close the current file"), G_CALLBACK (ui_mainwindow_action_close) }, + { "Quit" , ICONNAME_QUIT , N_("_Quit") , "Q", N_("Quit HomeBank"), G_CALLBACK (ui_mainwindow_action_quit) }, /* Exchange */ - { "FileImport" , "hb-file-import" , N_("Import QIF/OFX/CSV...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) }, - { "ExportQIF" , "hb-file-export" , N_("Export QIF...") , NULL, N_("Open the export to QIF assistant"), G_CALLBACK (ui_mainwindow_action_export) }, - { "Anonymize" , NULL , N_("Anonymize...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_anonymize) }, + { "ImportQIF" , ICONNAME_HB_FILE_IMPORT , N_("QIF file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) }, + { "ImportOFX" , ICONNAME_HB_FILE_IMPORT , N_("OFX/QFX file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) }, + { "ImportCSV" , ICONNAME_HB_FILE_IMPORT , N_("CSV file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) }, + + { "ExportQIF" , ICONNAME_HB_FILE_EXPORT , N_("Export QIF file...") , NULL, N_("Export all account in a QIF file"), G_CALLBACK (ui_mainwindow_action_export) }, /* EditMenu */ - { "Preferences", GTK_STOCK_PREFERENCES, N_("Preferences..."), NULL, N_("Configure homebank"), G_CALLBACK (ui_mainwindow_action_preferences) }, + { "Preferences", ICONNAME_PREFERENCES , N_("Preferences..."), NULL, N_("Configure HomeBank"), G_CALLBACK (ui_mainwindow_action_preferences) }, /* ManageMenu */ - // { "Currency" , "hb-currency" , N_("Currencies...") , NULL, N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) }, - { "Account" , "hb-account" , N_("Acc_ounts...") , NULL, N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) }, - { "Payee" , "hb-payee" , N_("_Payees...") , NULL, N_("Configure the payees"), G_CALLBACK (ui_mainwindow_action_defpayee) }, - { "Category" , "hb-category" , N_("Categories...") , NULL, N_("Configure the categories"), G_CALLBACK (ui_mainwindow_action_defcategory) }, - { "Archive" , "hb-archive" , N_("Scheduled/Template...") , NULL, N_("Configure the scheduled/template transactions"), G_CALLBACK (ui_mainwindow_action_defarchive) }, - { "Budget" , "hb-budget" , N_("Budget...") , NULL, N_("Configure the budget"), G_CALLBACK (ui_mainwindow_action_defbudget) }, - { "Assign" , "hb-assign" , N_("Assignments..."), NULL, N_("Configure the automatic assignments"), G_CALLBACK (ui_mainwindow_action_defassign) }, - - /* TransactionMenu */ - { "ShowOpe" , HB_STOCK_OPE_SHOW, N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) }, - { "AddOpe" , HB_STOCK_OPE_ADD , N_("Add...") , NULL, N_("Add transaction"), G_CALLBACK (ui_mainwindow_action_addtransactions) }, - { "Scheduler" , NULL , N_("Set scheduler...") , NULL, N_("Configure the transaction scheduler"), G_CALLBACK (ui_mainwindow_action_properties) }, - { "AddScheduled" , NULL , N_("Process scheduled..."), NULL, N_("Insert pending scheduled transactions"), G_CALLBACK (ui_mainwindow_action_checkscheduled) }, + { "Currency" , ICONNAME_HB_CURRENCY , N_("Currencies...") , NULL, N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) }, + { "Account" , ICONNAME_HB_ACCOUNT , N_("Acc_ounts...") , NULL, N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) }, + { "Payee" , ICONNAME_HB_PAYEE , N_("_Payees...") , NULL, N_("Configure the payees"), G_CALLBACK (ui_mainwindow_action_defpayee) }, + { "Category" , ICONNAME_HB_CATEGORY , N_("Categories...") , NULL, N_("Configure the categories"), G_CALLBACK (ui_mainwindow_action_defcategory) }, + { "Archive" , ICONNAME_HB_ARCHIVE , N_("Scheduled/Template...") , NULL, N_("Configure the scheduled/template transactions"), G_CALLBACK (ui_mainwindow_action_defarchive) }, + { "Budget" , ICONNAME_HB_BUDGET , N_("Budget...") , NULL, N_("Configure the budget"), G_CALLBACK (ui_mainwindow_action_defbudget) }, + { "Assign" , ICONNAME_HB_ASSIGN , N_("Assignments..."), NULL, N_("Configure the automatic assignments"), G_CALLBACK (ui_mainwindow_action_defassign) }, + + /* TxnMenu */ + { "ShowOpe" , ICONNAME_HB_OPE_SHOW , N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) }, + { "AddOpe" , ICONNAME_HB_OPE_ADD , N_("Add...") , NULL, N_("Add transactions"), G_CALLBACK (ui_mainwindow_action_addtransactions) }, + { "Scheduler" , NULL , N_("Set scheduler...") , NULL, N_("Configure the transaction scheduler"), G_CALLBACK (ui_mainwindow_action_properties) }, + { "AddScheduled", NULL , N_("Post scheduled"), NULL, N_("Post pending scheduled transactions"), G_CALLBACK (ui_mainwindow_action_checkscheduled) }, /* ReportMenu */ - { "RStatistics" , HB_STOCK_REP_STATS , N_("_Statistics...") , NULL, N_("Open the Statistics report"), G_CALLBACK (ui_mainwindow_action_statistic) }, - { "RTrendTime" , HB_STOCK_REP_TIME , N_("_Trend Time...") , NULL, N_("Open the Trend Time report"), G_CALLBACK (ui_mainwindow_action_trendtime) }, - { "RBudget" , HB_STOCK_REP_BUDGET, N_("B_udget...") , NULL, N_("Open the Budget report"), G_CALLBACK (ui_mainwindow_action_budget) }, - { "RBalance" , HB_STOCK_REP_BALANCE, N_("Balance...") , NULL, N_("Open the Balance report"), G_CALLBACK (ui_mainwindow_action_balance) }, - { "RVehiculeCost" , HB_STOCK_REP_CAR , N_("_Vehicle cost...") , NULL, N_("Open the Vehicle cost report"), G_CALLBACK (ui_mainwindow_action_vehiclecost) }, - + { "RStatistics" , ICONNAME_HB_REP_STATS , N_("_Statistics...") , NULL, N_("Open the Statistics report"), G_CALLBACK (ui_mainwindow_action_statistic) }, + { "RTrendTime" , ICONNAME_HB_REP_TIME , N_("_Trend Time...") , NULL, N_("Open the Trend Time report"), G_CALLBACK (ui_mainwindow_action_trendtime) }, + { "RBudget" , ICONNAME_HB_REP_BUDGET , N_("B_udget...") , NULL, N_("Open the Budget report"), G_CALLBACK (ui_mainwindow_action_budget) }, + { "RBalance" , ICONNAME_HB_REP_BALANCE, N_("Balance...") , NULL, N_("Open the Balance report"), G_CALLBACK (ui_mainwindow_action_balance) }, + { "RVehiculeCost", ICONNAME_HB_REP_CAR , N_("_Vehicle cost...") , NULL, N_("Open the Vehicle cost report"), G_CALLBACK (ui_mainwindow_action_vehiclecost) }, + + /* Tools */ + { "Welcome" , NULL , N_("Show welcome dialog...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_help_welcome) }, + { "FileStats" , NULL , N_("File statistics...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_file_statistics) }, + { "Anonymize" , NULL , N_("Anonymize...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_anonymize) }, + ++ /* Plugins */ + { "PluginPreferences", "prf-plugins", N_("_Plugins..."), "U", N_("Configure plugin preferences"), G_CALLBACK(ui_mainwindow_action_pluginprefs) }, + /* HelpMenu */ - { "Contents" , GTK_STOCK_HELP , N_("_Contents") , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) }, - { "Welcome" , NULL , N_("Show welcome dialog...") , NULL, NULL , G_CALLBACK (ui_mainwindow_action_help_welcome) }, - { "Online" , "lpi-help" , N_("Get Help Online...") , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) }, - { "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) }, - { "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) }, + { "Contents" , ICONNAME_HELP , N_("_Contents") , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) }, + { "Online" , "lpi-help" , N_("Get Help Online...") , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) }, + { "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) }, + { "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) }, - { "About" , GTK_STOCK_ABOUT , N_("_About") , NULL, N_("About HomeBank") ,G_CALLBACK (ui_mainwindow_action_about) }, + { "About" , ICONNAME_ABOUT , N_("_About") , NULL, N_("About HomeBank") ,G_CALLBACK (ui_mainwindow_action_about) }, }; static guint n_entries = G_N_ELEMENTS (entries); static GtkToggleActionEntry toggle_entries[] = { - /* name , stockid, label, accelerator, tooltip, callback, is_active */ + /* name , icon-name, label, accelerator, tooltip, callback, is_active */ { "Toolbar" , NULL , N_("_Toolbar") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_toolbar), TRUE }, { "Spending" , NULL , N_("_Top spending") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_topspending), TRUE }, { "Upcoming" , NULL , N_("_Scheduled list") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE }, - { "AsMinor" , NULL , N_("Minor currency"), "M", NULL, G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE }, + { "AsMinor" , NULL , N_("Euro minor"), "M", NULL, G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE }, }; static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries); @@@ -242,14 -252,17 +262,17 @@@ static const gchar *ui_info " " " " " " - " " + " " + " " + " " + " " + " " + " " + " " " " //" " // print to come here " " - " " - " " - " " " " " " " " @@@ -258,21 -271,22 +281,22 @@@ " " " " " " + " " " " " " " " " " " " " " - //" " " " " " " " - " " " " " " + " " + " " " " - " " + " " " " " " " " @@@ -286,16 -300,15 +310,20 @@@ " " " " " " + " " + " " + " " + " " + " " + " " +" " +" " +" " +" " +" " " " " " " " - " " - " " " " " " " " @@@ -306,15 -319,16 +334,16 @@@ " " " " + // here Open + recent is coded " " " " - //" " " " " " " " - " " " " " " + " " + " " " " " " " " @@@ -324,12 -338,12 +353,13 @@@ " " " " " " +" " " " ""; + /* TODO: a bouger */ @@@ -339,51 -353,45 +369,45 @@@ void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data) { //struct hbfile_data *data; - GtkWidget *dialog; gchar *basename; + gchar *title; + gchar *secondtext; gint result; DB( g_print("\n[ui-mainwindow] revert\n") ); //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - basename = g_path_get_basename(GLOBALS->xhb_filepath); - dialog = gtk_message_dialog_new - ( - GTK_WINDOW(GLOBALS->mainwindow), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - _("Revert to the previously saved file of '%s'?"), - basename - ); - g_free(basename); + basename = g_path_get_basename(GLOBALS->xhb_filepath); + title = g_strdup_printf ( + _("Revert unsaved changes to file '%s'?"), basename); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("- Changes made to the file will be permanently lost\n" - "- File will be restored to the last save (.xhb~)") - ); + secondtext = + _("- Changes made to the file will be permanently lost\n" + "- File will be reloaded from the last save (.xhb~)"); - gtk_dialog_add_buttons (GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, 0, - GTK_STOCK_REVERT_TO_SAVED, 1, - NULL); + result = ui_dialog_msg_confirm_alert( + GTK_WINDOW(GLOBALS->mainwindow), + title, + secondtext, + _("_Revert") + ); - result = gtk_dialog_run( GTK_DIALOG( dialog ) ); - gtk_widget_destroy( dialog ); + g_free(title); + g_free(basename); - if( result == 1) + if( result == GTK_RESPONSE_OK ) { DB( g_print(" - should revert\n") ); - hbfile_change_filepath(hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb~")); + hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~")); ui_mainwindow_open_internal(widget, NULL); - hbfile_change_filepath(hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb")); - + hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb")); } } + static void activate_url (GtkAboutDialog *about, const gchar *link, @@@ -396,10 -404,10 +420,10 @@@ static void hbfile_about(void) { - GtkWidget *about; - gchar *pathfilename; + GtkWidget *dialog; GdkPixbuf *pixbuf; - + gchar *pathfilename; + gchar *version; static const gchar *artists[] = { "Maxime DOYEN", @@@ -409,8 -417,7 +433,8 @@@ static const gchar *authors[] = { "Lead developer:\n" \ "Maxime DOYEN", - "\nContributor:\n" \ + "\nContributors:\n" \ + "Charles MCGARVEY (Plugin system, Perl support)\n" \ "Ga\xc3\xabtan LORIDANT (Maths formulas for charts)\n", NULL }; @@@ -422,71 -429,56 +446,56 @@@ }; */ - static const gchar license[] = - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as\n" - "published by the Free Software Foundation; either version 2 of the\n" - "License, or (at your option) any later version.\n\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, " - "MA 02110-1301, USA."; + static const gchar *copyright = "Copyright \xc2\xa9 1995-2016 - Maxime DOYEN"; - static const gchar *copyright = "Copyright \xc2\xa9 1995-2014 - Maxime DOYEN"; - pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL); - pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL); - g_free(pathfilename); + version = g_strdup_printf (PACKAGE_VERSION "\nRunning against GTK+ %d.%d.%d", + gtk_get_major_version (), + gtk_get_minor_version (), + gtk_get_micro_version ()); + + dialog = gtk_about_dialog_new(); - about = gtk_about_dialog_new(); - gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(about), g_get_application_name ()); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), PACKAGE_VERSION); - gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about), copyright); - gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), _("Free, easy, personal accounting for everyone.")); - gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), license); - //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(about), ); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://homebank.free.fr"); - gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "Visit the HomeBank website"); - gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about), authors); - gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about), artists); - //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(about), ); - //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(about), ); - gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about), "homebank"); - gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pixbuf); + gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(GLOBALS->mainwindow)); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - /* - gtk_show_about_dialog(GTK_WINDOW(GLOBALS->mainwindow), - "name", g_get_application_name (), - "logo-icon-name", "homebank", - "logo" , pixbuf, - "artists" , artists, - "authors" , authors, - // "translator-credits" , "trans", - "comments" , _("Free, easy, personal accounting for everyone."), - "license" , license, - "copyright" , copyright, - "version" , PACKAGE_VERSION, - "website" , "http://homebank.free.fr", - "website-label", "Visit the HomeBank website", - NULL); - */ - g_signal_connect (about, "activate-link", G_CALLBACK (activate_url), NULL); + gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(dialog), g_get_application_name ()); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), version); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), copyright); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("Free, easy, personal accounting for everyone")); + gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0); + + //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), ); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr"); + gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website"); - gtk_dialog_run (GTK_DIALOG (about)); + gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "homebank"); - gtk_widget_destroy (about); + pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL); + pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL); + g_free(pathfilename); - g_object_unref (pixbuf); - } + if( pixbuf ) + { + gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf); + g_object_unref (pixbuf); + } + + gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors); + gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists); + //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), ); + //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), ); + g_signal_connect (dialog, "activate-link", G_CALLBACK (activate_url), NULL); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_free(version); + + } /* hbfile action functions -------------------- */ @@@ -499,6 -491,11 +508,11 @@@ GtkWidget *widget = GLOBALS->mainwindow //clear all, and init GLOBALS->xhb_filepath to default ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE)); // GPOINTER_TO_INT( ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL)); + + ui_start_assistant(); + ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); + ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); + ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL); } } @@@ -547,9 -544,12 +561,18 @@@ gboolean result //gtk_main_quit(); } + static void ui_mainwindow_action_file_statistics(void) + { + ui_dialog_file_statistics(); + } ++static void ui_mainwindow_action_pluginprefs(void) ++{ ++ ui_mainwindow_showprefs(PREF_PLUGINS); ++} ++ + static void ui_mainwindow_action_properties(void) { create_defhbfile_dialog(); @@@ -559,28 -559,36 +582,36 @@@ static void ui_mainwindow_action_anonymize(void) { gint result; + gchar *title; + gchar *secondtext; + + title = _("Are you sure you want to anonymize the file?"); + + secondtext = + _("Proceeding will anonymize any text, \n" + "like 'account x', 'payee y', 'memo z', ..."); - result = ui_dialog_msg_question( - GTK_WINDOW(GLOBALS->mainwindow), - _("Anonymize the file ?"), - _("Proceeding will changes name/memo to anonymous datas,\n" - "please confirm.") + result = ui_dialog_msg_confirm_alert( + GTK_WINDOW(GLOBALS->mainwindow), + title, + secondtext, + _("_Anonymize") ); - if( result == GTK_RESPONSE_NO ) + if( result == GTK_RESPONSE_CANCEL ) return; hbfile_anonymize(); ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL)); } - /* + static void ui_mainwindow_action_defcurrency(void) { - //ui_cur_manage_dialog(); - ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE)); + ui_cur_manage_dialog(); + ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL)); } - */ + static void ui_mainwindow_action_defaccount(void) { @@@ -608,7 -616,8 +639,8 @@@ static void ui_mainwindow_action_defcat ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE)); } - static void ui_mainwindow_action_defarchive(void) + + static void ui_mainwindow_defarchive(Archive *arc) { struct hbfile_data *data; GtkTreeModel *model; @@@ -619,7 -628,7 +651,7 @@@ model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc)); gtk_list_store_clear (GTK_LIST_STORE(model)); - ui_arc_manage_dialog(); + ui_arc_manage_dialog(arc); ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); @@@ -627,6 -636,12 +659,12 @@@ } + static void ui_mainwindow_action_defarchive(void) + { + ui_mainwindow_defarchive(NULL); + } + + static void ui_mainwindow_action_defbudget(void) { ui_bud_manage_dialog(); @@@ -644,15 -659,10 +682,15 @@@ static void ui_mainwindow_action_defass static void ui_mainwindow_action_preferences(void) +{ + ui_mainwindow_showprefs(PREF_GENERAL); +} + +static void ui_mainwindow_showprefs(gint page) { struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data"); - defpref_dialog_new(); + defpref_dialog_new(page); if(!PREFS->euro_active) { GtkToggleAction *action = (GtkToggleAction *)gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor"); @@@ -700,7 -710,7 +738,7 @@@ struct hbfile_data *data = g_object_get // top spending gtk_chart_show_minor(GTK_CHART(data->RE_pie), GLOBALS->minor); - hb_label_set_amount(GTK_LABEL(data->TX_topamount), data->toptotal, GLOBALS->minor); + hb_label_set_amount(GTK_LABEL(data->TX_topamount), data->toptotal, GLOBALS->kcur, GLOBALS->minor); } @@@ -766,15 -776,25 +804,25 @@@ static void ui_mainwindow_action_vehicl repcost_window_new(); } - static void ui_mainwindow_action_pluginprefs(void) + static void ui_mainwindow_action_import(GtkAction *action) { - ui_mainwindow_showprefs(PREF_PLUGINS); - } + const gchar *name; + gint filetype = FILETYPE_UNKNOW; - static void ui_mainwindow_action_import(void) - { - ui_import_window_new(); + name = gtk_action_get_name(action); + + if( g_str_has_suffix (name, "QIF")) + filetype= FILETYPE_QIF; + else + if( g_str_has_suffix (name, "OFX")) + filetype= FILETYPE_OFX; + else + if( g_str_has_suffix (name, "CSV")) + filetype= FILETYPE_CSV_HB; + DB( g_print("action %s type=%d\n", name, filetype) ); + + ui_import_assistant_new(filetype); } @@@ -837,35 -857,35 +885,35 @@@ static void ui_mainwindow_action_help_w void ui_mainwindow_action_help_welcome(void) { - GtkWidget *dialog, *content; + GtkWidget *dialog, *content_area; GtkWidget *mainvbox, *widget, *label; dialog = gtk_dialog_new_with_buttons (_("Welcome to HomeBank"), GTK_WINDOW(GLOBALS->mainwindow), 0, - GTK_STOCK_CLOSE, + _("_Close"), GTK_RESPONSE_ACCEPT, NULL); - content = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); + content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); - mainvbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (content), mainvbox, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING); + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start (GTK_BOX (content_area), mainvbox, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM); label = make_label (_("HomeBank"), 0, 0); gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0); - label = make_label (_("Free, easy, personal accounting for everyone."), 0, 0); + label = make_label (_("Free, easy, personal accounting for everyone"), 0, 0); gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0); - widget = gtk_hseparator_new(); - gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0); + widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); + gtk_box_pack_start (GTK_BOX (content_area), widget, FALSE, FALSE, 0); - mainvbox = gtk_vbox_new (FALSE, HB_MAINBOX_SPACING); - gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING); + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM); + gtk_box_pack_start (GTK_BOX (content_area), mainvbox, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM); label = make_label (_("What do you want to do:"), 0, 0); gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); @@@ -875,7 -895,7 +923,7 @@@ gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0); g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog); - widget = gtk_button_new_with_mnemonic(_("Configure _Preferences")); + widget = gtk_button_new_with_mnemonic(_("Configure _preferences")); gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0); g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog); @@@ -998,31 -1018,23 +1046,23 @@@ GList *lacc, *elt */ void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data) { - //struct hbfile_data *data; + struct hbfile_data *data; gboolean file_clear = GPOINTER_TO_INT(user_data); DB( g_print("\n[ui-mainwindow] clear\n") ); - //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); // Close opened account window // Clear TreeView ui_mainwindow_close_openbooks(); - //gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc)))); - //gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc)))); - //gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top)))); + gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc)))); + gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc)))); + gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top)))); hbfile_cleanup(file_clear); hbfile_setup(file_clear); - if(file_clear == TRUE) - { - ui_start_assistant(); - ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); - ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); - ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL); - } - } @@@ -1035,7 -1047,7 +1075,7 @@@ struct hbfile_data *data GtkWidget *window; gint result = 1; guint32 date; - gint account = 1, count; + gint account, count; DB( g_print("\n[ui-mainwindow] add transactions\n") ); @@@ -1043,45 -1055,55 +1083,55 @@@ /* init the transaction */ date = homebank_app_date_get_julian(); + //todo: maybe think about set a default account here + account = 1; if(data->acc != NULL) account = data->acc->key; - window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD); + window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE); count = 0; - while(result == GTK_RESPONSE_ADD) + while(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP) { Transaction *ope; /* fill in the transaction */ - ope = da_transaction_malloc(); - ope->date = date; - ope->kacc = account; + if( result == GTK_RESPONSE_ADD ) + { + ope = da_transaction_malloc(); + ope->date = date; + ope->kacc = account; - if( PREFS->heritdate == FALSE ) //fix: 318733 - ope->date = GLOBALS->today; + if( PREFS->heritdate == FALSE ) //fix: 318733 + ope->date = GLOBALS->today; + } + + // normally we can't be in addkeep without initialized ope with add deftransaction_set_transaction(window, ope); result = gtk_dialog_run (GTK_DIALOG (window)); - DB( g_print(" -> dialog result is %d\n", result) ); + DB( g_print(" - dialog result is %d\n", result) ); - if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT) + if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT) { deftransaction_get(window, NULL); transaction_add(ope, NULL, ope->kacc); - DB( g_print(" -> added 1 transaction to %d\n", ope->kacc) ); + DB( g_print(" - added 1 transaction to %d\n", ope->kacc) ); ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); count++; - //store last date + //todo: still usefull ? store last date date = ope->date; } - da_transaction_free(ope); - ope = NULL; + if( result == GTK_RESPONSE_ADD ) + { + da_transaction_free(ope); + ope = NULL; + } } @@@ -1115,11 -1137,11 +1165,11 @@@ struct hbfile_data *data GtkTreeModel *model; GtkTreeIter iter; GList *list; - gint range; + gint type, range; guint n_result, i, n_items; GArray *garray; gdouble total, other; - //Account *acc; + Account *acc; #define MAX_TOPSPENDING 5 @@@ -1127,15 -1149,16 +1177,16 @@@ data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + type = radio_get_active(GTK_CONTAINER(data->RA_type)); range = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range)); - DB( g_print(" - range=%d\n", range) ); + DB( g_print(" - type=%d, range=%d\n", type, range) ); DB( g_print(" - pref range=%d\n", PREFS->date_range_wal) ); if(range == FLT_RANGE_OTHER) return; - filter_preset_daterange_set(data->filter, range); + filter_preset_daterange_set(data->filter, range, 0); n_result = da_cat_get_max_key() + 1; @@@ -1149,6 -1172,7 +1200,7 @@@ if(garray) { struct tmptop zero = { .key=0, .value=0.0 }; + GQueue *txn_queue; //DB( g_print(" - array length=%d\n", garray->len) ); @@@ -1163,74 -1187,70 +1215,70 @@@ //DB( g_print("\n - end array length=%d\n", garray->len) ); + //todo: not ideal, has ot force to get_acc for each txn below + txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate); + /* compute the results */ - list = g_list_first(GLOBALS->ope_list); + list = g_queue_peek_head_link(txn_queue); while (list != NULL) { Transaction *ope = list->data; - Account *acc; - //debug + //DB( g_print(" - eval txn: '%s', cat=%d ==> flt-test=%d\n", ope->wording, ope->kcat, filter_test(data->filter, ope)) ); - acc = da_acc_get(ope->kacc); - if(acc == NULL) goto next1; - if((acc->flags & (AF_CLOSED|AF_NOREPORT))) goto next1; - if(ope->paymode == PAYMODE_INTXFER) goto next1; - if( !(ope->flags & OF_REMIND) ) + if( !(ope->paymode == PAYMODE_INTXFER) ) { - if( (ope->date >= data->filter->mindate) && (ope->date <= data->filter->maxdate) ) - { - guint32 pos = 0; - gdouble trn_amount; + guint32 pos = 0; + gdouble trn_amount; - //trn_amount = to_base_amount(ope->amount, acc->kcur); - trn_amount = ope->amount; + //todo: optimize here + trn_amount = ope->amount; + acc = da_acc_get(ope->kacc); + if(acc) + trn_amount = hb_amount_base(ope->amount, acc->kcur); - if( ope->flags & OF_SPLIT ) - { - guint nbsplit = da_transaction_splits_count(ope); - Split *split; - struct tmptop *item; - - for(i=0;isplits[i]; - Category *catentry = da_cat_get(split->kcat); - if(catentry) - pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key; - - //trn_amount = to_base_amount(split->amount, acc->kcur); - trn_amount = split->amount; - //#1297054 if( trn_amount < 0 ) { - item = &g_array_index (garray, struct tmptop, pos); - item->key = pos; - item->value += trn_amount; - DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) ); - //} - } - } - else + if( ope->flags & OF_SPLIT ) + { + guint nbsplit = da_splits_count(ope->splits); + Split *split; + struct tmptop *item; + + for(i=0;ikcat); - struct tmptop *item; + split = ope->splits[i]; + pos = category_report_id(split->kcat, type); - if(catentry) - pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key; - + trn_amount = hb_amount_base(split->amount, acc->kcur); + //trn_amount = split->amount; //#1297054 if( trn_amount < 0 ) { item = &g_array_index (garray, struct tmptop, pos); item->key = pos; item->value += trn_amount; - DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) ); + //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) ); //} } + } + else + { + struct tmptop *item; + pos = category_report_id(ope->kcat, type); + + //#1297054 if( trn_amount < 0 ) { + item = &g_array_index (garray, struct tmptop, pos); + item->key = pos; + item->value += trn_amount; + //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) ); + //} } + + } - next1: + list = g_list_next(list); } + g_queue_free (txn_queue); // we need to sort this and limit before g_array_sort(garray, (GCompareFunc)tmptop_compare_func); @@@ -1271,11 -1291,11 +1319,11 @@@ if(!item->value) continue; - value = arrondi(item->value, 2); + value = hb_amount_round(item->value, 2); entry = da_cat_get(item->key); if(entry == NULL) continue; - name = entry->key == 0 ? _("(no category)") : entry->name; + name = entry->key == 0 ? _("(no category)") : da_cat_get_fullname(entry); // append test gtk_list_store_append (GTK_LIST_STORE(model), &iter); @@@ -1307,10 -1327,11 +1355,11 @@@ g_object_unref(model); data->toptotal = total; - hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->minor); + hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->kcur, GLOBALS->minor); gtk_chart_set_color_scheme(GTK_CHART(data->RE_pie), PREFS->report_color_scheme); - gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, NULL); + gtk_chart_set_currency(GTK_CHART(data->RE_pie), GLOBALS->kcur); + gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, NULL, NULL); //gtk_chart_show_legend(GTK_CHART(data->RE_pie), FALSE); /* update info range text */ @@@ -1352,6 -1373,76 +1401,76 @@@ GtkTreeIter iter } + static void ui_mainwindow_scheduled_onRowActivated (GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer userdata) + { + //struct hbfile_data *data; + Archive *arc; + + DB( g_print ("\n[ui-mainwindow] A scheduled row has been double-clicked!\n") ); + + //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(treeview, GTK_TYPE_WINDOW)), "inst_data"); + + arc = ui_mainwindow_scheduled_get_selected_item(treeview); + ui_mainwindow_defarchive(arc); + } + + + static void ui_mainwindow_scheduled_do_post(Archive *arc, gboolean doedit, gpointer user_data) + { + struct hbfile_data *data = user_data; + GtkWidget *window; + gint result; + Transaction *txn; + + window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, TRUE); + + /* fill in the transaction */ + txn = da_transaction_malloc(); + da_transaction_init_from_template(txn, arc); + txn->date = scheduled_get_postdate(arc, arc->nextdate); + + deftransaction_set_transaction(window, txn); + + result = gtk_dialog_run (GTK_DIALOG (window)); + + DB( g_print(" - dialog result is %d\n", result) ); + + if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT) + { + deftransaction_get(window, NULL); + transaction_add(txn, NULL, txn->kacc); + GLOBALS->changes_count++; + + scheduled_date_advance(arc); + + DB( g_print(" - added 1 transaction to %d\n", txn->kacc) ); + } + + da_transaction_free(txn); + + deftransaction_dispose(window, NULL); + gtk_widget_destroy (window); + + } + + + static void ui_mainwindow_scheduled_editpost_cb(GtkWidget *widget, gpointer user_data) + { + struct hbfile_data *data = user_data; + + Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc)); + + if( (arc != NULL) ) + { + ui_mainwindow_scheduled_do_post(arc, TRUE, data); + ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL)); + } + } + + static void ui_mainwindow_scheduled_post_cb(GtkWidget *widget, gpointer user_data) { struct hbfile_data *data = user_data; @@@ -1367,53 -1458,19 +1486,19 @@@ da_transaction_init_from_template(txn, arc); txn->date = scheduled_get_postdate(arc, arc->nextdate); transaction_add(txn, NULL, 0); + GLOBALS->changes_count++; - scheduled_date_advance(arc); da_transaction_free (txn); } else { - GtkWidget *window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD); - gint result; - Transaction *txn; - - /* fill in the transaction */ - txn = da_transaction_malloc(); - da_transaction_init_from_template(txn, arc); - txn->date = scheduled_get_postdate(arc, arc->nextdate); - - deftransaction_set_transaction(window, txn); - - result = gtk_dialog_run (GTK_DIALOG (window)); - - DB( g_print(" -> dialog result is %d\n", result) ); - - if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT) - { - deftransaction_get(window, NULL); - transaction_add(txn, NULL, txn->kacc); - GLOBALS->changes_count++; - - scheduled_date_advance(arc); - - DB( g_print(" -> added 1 transaction to %d\n", txn->kacc) ); - } - - da_transaction_free(txn); - - deftransaction_dispose(window, NULL); - gtk_widget_destroy (window); - + ui_mainwindow_scheduled_do_post(arc, FALSE, data); } - ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_REFRESHALL)); - + ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL)); } - - - } @@@ -1424,9 -1481,11 +1509,11 @@@ struct hbfile_data *data = user_data Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc)); if( (arc != NULL) && (arc->flags & OF_AUTO) ) { + GLOBALS->changes_count++; scheduled_date_advance(arc); ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); + ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE)); } } @@@ -1449,13 -1508,15 +1536,15 @@@ struct hbfile_data *data { DB( g_print("archive is %s\n", arc->wording) ); - gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), TRUE); } else { - gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), FALSE); } } @@@ -1547,6 -1608,8 +1636,8 @@@ GDate *date while (list != NULL) { Archive *arc = list->data; + Account *acc; + gdouble inc, exp; guint nbdays, nblate; if((arc->flags & OF_AUTO) ) //&& arc->kacc > 0) @@@ -1557,22 -1620,55 +1648,55 @@@ DB( g_print(" - append '%s' : %d\n", arc->wording, nbdays) ); + if(arc->flags & OF_INCOME) + { + inc = arc->amount; + exp = 0.0; + } + else + { + exp = arc->amount; + inc = 0.0; + } + + /* insert normal txn */ + acc = da_acc_get(arc->kacc); + if( acc) + { + totinc += hb_amount_base(inc, acc->kcur); + totexp += hb_amount_base(exp, acc->kcur); + } gtk_list_store_append (GTK_LIST_STORE(model), &iter); gtk_list_store_set (GTK_LIST_STORE(model), &iter, LST_DSPUPC_DATAS, arc, + LST_DSPUPC_ACCOUNT, acc, LST_DSPUPC_WORDING, arc->wording, - LST_DSPUPC_EXPENSE, !(arc->flags & OF_INCOME) ? arc->amount : 0.0, - LST_DSPUPC_INCOME, (arc->flags & OF_INCOME) ? arc->amount : 0.0, + LST_DSPUPC_EXPENSE, exp, + LST_DSPUPC_INCOME, inc, LST_DSPUPC_REMAINING, nbdays, LST_DSPUPC_NB_LATE, nblate, -1); - //acc = da_acc_get(arc->kacc); - //total += to_base_amount(arc->amount, acc->kcur); - if(arc->flags & OF_INCOME) - totinc += arc->amount; - else - totexp += arc->amount; + /* insert internal xfer txn : 1378836 */ + if(arc->paymode == PAYMODE_INTXFER) + { + acc = da_acc_get(arc->kxferacc); + if( acc) + { + totinc += hb_amount_base(-inc, acc->kcur); + totexp += hb_amount_base(-exp, acc->kcur); + } + gtk_list_store_append (GTK_LIST_STORE(model), &iter); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, + LST_DSPUPC_DATAS, arc, + LST_DSPUPC_ACCOUNT, acc, + LST_DSPUPC_WORDING, arc->wording, + LST_DSPUPC_EXPENSE, -inc, + LST_DSPUPC_INCOME, -exp, + LST_DSPUPC_REMAINING, nbdays, + LST_DSPUPC_NB_LATE, nblate, + -1); + } } list = g_list_next(list); @@@ -1584,6 -1680,7 +1708,7 @@@ gtk_list_store_append (GTK_LIST_STORE(model), &iter); gtk_list_store_set (GTK_LIST_STORE(model), &iter, LST_DSPUPC_DATAS, NULL, + LST_DSPUPC_ACCOUNT, NULL, LST_DSPUPC_WORDING, _("Total"), LST_DSPUPC_EXPENSE, totexp, LST_DSPUPC_INCOME, totinc, @@@ -1635,7 -1732,7 +1760,7 @@@ gint r data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - DB( g_print(" -> filename: '%s'\n", GLOBALS->xhb_filepath) ); + DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) ); if( GLOBALS->xhb_filepath != NULL ) { @@@ -1645,22 -1742,22 +1770,22 @@@ r = homebank_load_xml(GLOBALS->xhb_filepath); if( r == XML_OK ) { - DB( g_print(" -> file loaded ok : rcode=%d\n", r) ); + DB( g_print(" - file loaded ok : rcode=%d\n", r) ); hbfile_file_hasbackup(GLOBALS->xhb_filepath); if(PREFS->appendscheduled) scheduled_post_all_pending(); + if(PREFS->do_update_currency) + ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow)); + homebank_lastopenedfiles_save(); - //todo: remove this after computing done at xml read + //todo: delete this after computing done at xml read account_compute_balances(); ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath); - ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); - ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); - ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL); } else { @@@ -1689,6 -1786,9 +1814,9 @@@ } + ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); + ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL); + ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL); ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL)); } @@@ -1716,10 -1816,9 +1844,9 @@@ gint r = XML_UNSET { if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename) == TRUE) { - DB( g_print(" + should save as %s\n", GLOBALS->xhb_filepath) ); - hbfile_change_filepath(filename); - homebank_backup_current_file(GLOBALS->xhb_filepath); - homebank_file_ensure_xhb(); + DB( g_print(" + should save as '%s'\n", filename) ); + homebank_file_ensure_xhb(filename); + homebank_backup_current_file(); r = homebank_save_xml(GLOBALS->xhb_filepath); GLOBALS->hbfile_is_new = FALSE; } @@@ -1729,8 -1828,8 +1856,8 @@@ else { DB( g_print(" + should quick save %s\n", GLOBALS->xhb_filepath) ); - homebank_backup_current_file(GLOBALS->xhb_filepath); - homebank_file_ensure_xhb(); + homebank_file_ensure_xhb(NULL); + homebank_backup_current_file(); r = homebank_save_xml(GLOBALS->xhb_filepath); } @@@ -1742,7 -1841,7 +1869,7 @@@ } else { - gchar *msg = _("I/O error for file %s."); + gchar *msg = _("I/O error for file '%s'."); ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR, _("File error"), @@@ -1780,7 -1879,7 +1907,7 @@@ gdouble gtbank, gttoday, gtfuture //#1339572 if( !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) ) { - DB( g_print(" -> insert %d:%s\n", acc->key, acc->name) ); + DB( g_print(" - insert %d:%s\n", acc->key, acc->name) ); if(typeacc[acc->type] == NULL) typeacc[acc->type] = g_ptr_array_sized_new(da_acc_length ()); @@@ -1793,7 -1892,7 +1920,7 @@@ gtbank = gttoday = gtfuture = 0; - DB( g_print(" -> populate listview\n") ); + DB( g_print(" - populate listview\n") ); /* then populate the listview */ @@@ -1810,7 -1909,7 +1937,7 @@@ { nbtype++; //1: Header: Bank, Cash, ... - DB( g_print(" -> append type '%s'\n", CYA_ACC_TYPE[i]) ); + DB( g_print(" - append type '%s'\n", CYA_ACC_TYPE[i]) ); gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL); gtk_tree_store_set (GTK_TREE_STORE(model), &iter1, @@@ -1825,18 -1924,12 +1952,12 @@@ { acc = g_ptr_array_index(gpa, j); - //if(acc->kcur == GLOBALS->kcur) - //{ - tbank += acc->bal_bank; - ttoday += acc->bal_today; - tfuture += acc->bal_future; - /*} - else - { - tbank += to_base_amount(acc->bal_bank, acc->kcur); - ttoday += to_base_amount(acc->bal_today, acc->kcur); - tfuture += to_base_amount(acc->bal_future, acc->kcur); - }*/ + //tbank += acc->bal_bank; + //ttoday += acc->bal_today; + //tfuture += acc->bal_future; + tbank += hb_amount_base(acc->bal_bank, acc->kcur); + ttoday += hb_amount_base(acc->bal_today, acc->kcur); + tfuture += hb_amount_base(acc->bal_future, acc->kcur); DB( g_print(" - insert '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) ); @@@ -1899,7 -1992,7 +2020,7 @@@ gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc)); - DB( g_print(" -> free ressources\n") ); + DB( g_print(" - free ressources\n") ); /* free all temp stuff */ @@@ -1933,11 -2026,11 +2054,11 @@@ gint flags gchar *basename; gchar *changed; - DB( printf(" + 1: wintitle %x\n", (gint)data->wintitle) ); + DB( g_print(" + 1: wintitle %x\n", (gint)data->wintitle) ); basename = g_path_get_basename(GLOBALS->xhb_filepath); - DB( printf(" global changes: %d\n", GLOBALS->changes_count) ); + DB( g_print(" global changes: %d\n", GLOBALS->changes_count) ); g_free(data->wintitle); @@@ -1959,7 -2052,7 +2080,7 @@@ GtkTreePath *path; gboolean active,sensitive; - DB( printf(" + 2: disabled, opelist count\n") ); + DB( g_print(" + 2: disabled, opelist count\n") ); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc)); @@@ -1974,7 -2067,7 +2095,7 @@@ if( depth > 1 ) { - DB( printf(" depth is %d\n", depth) ); + DB( g_print(" depth is %d\n", depth) ); gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPACC_DATAS, &acc, -1); data->acc = acc; @@@ -1991,7 -2084,7 +2112,7 @@@ // no change: disable save - DB( printf(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) ); + DB( g_print(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) ); sensitive = (GLOBALS->changes_count != 0 ) ? TRUE : FALSE; @@@ -2007,7 -2100,6 +2128,6 @@@ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Account"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Payee"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Category"), sensitive); - //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/EditMenu/Preferences"), sensitive); @@@ -2018,54 -2110,60 +2138,60 @@@ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Close"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Archive"), sensitive); - gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/AddOpe"), sensitive); - gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/ShowOpe"), sensitive); + gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddOpe"), sensitive); + gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RStatistics"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RTrendTime"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBudget"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBalance"), sensitive); gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RVehiculeCost"), sensitive); - // empty category list: disable Budget & Budget report + // empty category list: disable Budget sensitive = da_cat_length() > 1 ? TRUE : FALSE; - gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive); + //#1501129 no need to disable, P & C can be created from assign dialog + //sensitive = ((da_cat_length() > 1) || (da_pay_length() > 1)) ? TRUE : FALSE; + //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive); + // empty archive list: disable scheduled check sensitive = g_list_length(GLOBALS->arc_list) > 0 ? TRUE : FALSE; - gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/AddScheduled"), sensitive); + gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddScheduled"), sensitive); // no active account: disable Edit, Over sensitive = (active == TRUE ) ? TRUE : FALSE; if(data->acc && data->acc->window != NULL) sensitive = FALSE; - gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/ShowOpe"), sensitive); + gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive); } /* update toolbar, list */ if(flags & UF_VISUAL) { - DB( printf(" + 8: visual\n") ); + DB( g_print(" + 8: visual\n") ); if(PREFS->toolbar_style == 0) gtk_toolbar_unset_style(GTK_TOOLBAR(data->toolbar)); else gtk_toolbar_set_style(GTK_TOOLBAR(data->toolbar), PREFS->toolbar_style-1); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (data->LV_acc), PREFS->rules_hint); + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_acc), PREFS->grid_lines); gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc)); - DB( printf(" - show toolbar=%d\n", PREFS->wal_toolbar) ); + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_upc), PREFS->grid_lines); + gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc)); + + DB( g_print(" - show toolbar=%d\n", PREFS->wal_toolbar) ); if(PREFS->wal_toolbar) gtk_widget_show(GTK_WIDGET(data->toolbar)); else gtk_widget_hide(GTK_WIDGET(data->toolbar)); - DB( printf(" - show top_spending=%d\n", PREFS->wal_spending) ); + DB( g_print(" - show top_spending=%d\n", PREFS->wal_spending) ); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_wal); @@@ -2076,13 -2174,13 +2202,13 @@@ - DB( printf(" - show upcoming=%d\n", PREFS->wal_upcoming) ); + DB( g_print(" - show upcoming=%d\n", PREFS->wal_upcoming) ); if(PREFS->wal_upcoming) gtk_widget_show(GTK_WIDGET(data->GR_upc)); else gtk_widget_hide(GTK_WIDGET(data->GR_upc)); - DB( printf(" minor %d\n", PREFS->euro_active) ); + DB( g_print(" minor %d\n", PREFS->euro_active) ); gtk_action_set_visible(gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor"), PREFS->euro_active); } @@@ -2090,7 -2188,7 +2216,7 @@@ if(flags & UF_BALANCE) { - DB( printf(" + 4: balances\n") ); + DB( g_print(" + 4: balances\n") ); gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc)); @@@ -2105,7 -2203,7 +2231,7 @@@ if(flags & UF_REFRESHALL) { - DB( printf(" + 8: refreshall\n") ); + DB( g_print(" + 8: refreshall\n") ); ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL); ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL); @@@ -2157,9 -2255,6 +2283,9 @@@ struct hbfile_data *data = user_data struct WinGeometry *wg; gboolean retval = FALSE; + GValue widget_value = G_VALUE_INIT; + ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL); + DB( g_print("\n[ui-mainwindow] dispose\n") ); //store position and size @@@ -2271,7 -2366,7 +2397,7 @@@ void ui_mainwindow_recent_add (struct h DB( g_print("\n[ui-mainwindow] recent_add\n") ); - DB( g_print(" - suffix xhb %d", g_str_has_suffix (path, ".xhb") ) ); + DB( g_print(" - file has .xhb suffix = %d\n", g_str_has_suffix (path, ".xhb") ) ); if( g_str_has_suffix (path, ".xhb") == FALSE ) //ignore reverted file return; @@@ -2328,7 -2423,7 +2454,7 @@@ static void ui_mainwindow_drag_data_rec guint info, guint time, GtkWindow *window) { gchar **uris, **str; - gchar *data; + gchar *newseldata; gint filetype, slen; if (info != TARGET_URI_LIST) @@@ -2338,11 -2433,11 +2464,11 @@@ /* On MS-Windows, it looks like `selection_data->data' is not NULL terminated. */ slen = gtk_selection_data_get_length(selection_data); - data = g_new (gchar, slen + 1); - memcpy (data, gtk_selection_data_get_data(selection_data), slen); - data[slen] = 0; + newseldata = g_new (gchar, slen + 1); + memcpy (newseldata, gtk_selection_data_get_data(selection_data), slen); + newseldata[slen] = 0; - uris = g_uri_list_extract_uris (data); + uris = g_uri_list_extract_uris (newseldata); str = uris; //for (str = uris; *str; str++) @@@ -2359,7 -2454,7 +2485,7 @@@ if( filetype == FILETYPE_HOMEBANK) { - hbfile_change_filepath(path); + hbfile_change_filepath(g_strdup(path)); ui_mainwindow_open_internal(GTK_WIDGET(window), NULL); } else @@@ -2385,6 -2480,8 +2511,8 @@@ g_free (path); } g_strfreev (uris); + + g_free(newseldata); } @@@ -2401,7 -2498,7 +2529,7 @@@ GtkRecentFilter *filter GTK_RECENT_SORT_MRU); //todo: add a user pref for this gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (toolbar_recent_menu), - 5); + 10); //gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (toolbar_recent_menu), FALSE); @@@ -2451,8 -2548,8 +2579,8 @@@ GError *error = NULL action = gtk_action_group_get_action(action_group, "Open"); g_object_set(action, "short_label", _("Open"), NULL); - action = gtk_action_group_get_action(action_group, "Save"); - g_object_set(action, "is_important", TRUE, NULL); + //action = gtk_action_group_get_action(action_group, "Save"); + //g_object_set(action, "is_important", TRUE, NULL); action = gtk_action_group_get_action(action_group, "Account"); g_object_set(action, "short_label", _("Account"), NULL); @@@ -2496,7 -2593,7 +2624,7 @@@ g_error_free (error); } - + //todo: this generate a warning data->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar"); gtk_box_pack_start (GTK_BOX (mainvbox), data->menubar, @@@ -2513,8 -2610,6 +2641,6 @@@ /* recent files menu */ - - data->recent_manager = gtk_recent_manager_get_default (); data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager); @@@ -2529,52 -2624,48 +2655,48 @@@ gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), data->recent_menu); */ - /* testing */ - /* add the custom Open button to the toolbar */ - GtkToolItem *open_button = gtk_menu_tool_button_new_from_stock (GTK_STOCK_OPEN); - gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), - data->recent_menu); + /* test */ + /* add the custom Open button to the toolbar */ + GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_OPEN, GTK_ICON_SIZE_BUTTON); - gtk_tool_item_set_tooltip_text (open_button, _("Open a file")); - gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), - _("Open a recently used file")); + GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open")); + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), data->recent_menu); + gtk_tool_item_set_tooltip_text (open_button, _("Open a file")); + gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), _("Open a recently used file")); action = gtk_action_group_get_action (data->actions, "Open"); - g_object_set (action, - "short_label", _("Open"), - NULL); + g_object_set (action, "short_label", _("Open"), NULL); //gtk_action_connect_proxy (action, GTK_WIDGET (open_button)); gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button), action); - gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), - open_button, - 1); - /* end testing */ + gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), open_button, 1); + /* end test */ } static GtkWidget *ui_mainwindow_create_youraccounts(struct hbfile_data *data) { - GtkWidget *mainvbox, *align, *label, *widget, *sw; + GtkWidget *mainvbox, *label, *widget, *sw; - mainvbox = gtk_vbox_new (FALSE, 0); + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - label = make_label(_("Your accounts"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2); + label = make_label_group(_("Your accounts")); + gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL); gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0); - align = gtk_alignment_new(0, 0, 1.0, 1.0); - // top, bottom, left, right - gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING); - gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0); - sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (align), sw); - + //gtk_widget_set_margin_top(GTK_WIDGET(sw), 0); + gtk_widget_set_margin_bottom(GTK_WIDGET(sw), SPACING_SMALL); + gtk_widget_set_margin_start(GTK_WIDGET(sw), 2*SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(sw), SPACING_SMALL); + gtk_box_pack_start (GTK_BOX (mainvbox), sw, TRUE, TRUE, 0); + widget = (GtkWidget *)create_list_account(); data->LV_acc = widget; gtk_container_add (GTK_CONTAINER (sw), widget); @@@ -2586,59 -2677,65 +2708,65 @@@ static GtkWidget *ui_mainwindow_create_topspending(struct hbfile_data *data) { GtkWidget *mainvbox, *hbox, *vbox; - GtkWidget *label, *align, *widget; + GtkWidget *label, *widget; - mainvbox = gtk_vbox_new (FALSE, 0); - data->GR_top = mainvbox; + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + data->GR_top = mainvbox; - label = make_label(_("Where your money goes"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2); - gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0); + label = make_label_group(_("Where your money goes")); + gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL); + gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0); - align = gtk_alignment_new(0, 0, 1.0, 1.0); - // top, bottom, left, right - gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING); - gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0); - vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING); - gtk_container_add (GTK_CONTAINER (align), vbox); - - /* total + date range */ - hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - - label = make_label(_("Top 5 spending"), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - - label = make_label(NULL, 0.0, 0.5); - data->TX_topamount = label; - gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_SMALL); + //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0); + gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL); + gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL); + gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0); + + /* total + date range */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - data->CY_range = make_daterange(label, FALSE); - gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0); + label = make_label(_("Top spending"), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + label = make_label(NULL, 0.0, 0.5); + data->TX_topamount = label; + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); - /* pie + listview */ - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); + data->CY_range = make_daterange(label, FALSE); + gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0); - widget = gtk_chart_new(CHART_TYPE_PIE); - data->RE_pie = widget; - gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol); - gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); + widget = make_radio(CYA_CATSUBCAT, TRUE, GTK_ORIENTATION_HORIZONTAL); + data->RA_type = widget; + gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - /* - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0); - */ - - widget = (GtkWidget *)create_list_topspending(); - data->LV_top = widget; + /* pie + listview */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); - gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE); + widget = gtk_chart_new(CHART_TYPE_PIE); + data->RE_pie = widget; + gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol); + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); + + /* + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0); + */ + widget = (GtkWidget *)create_list_topspending(); + data->LV_top = widget; + + gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE); + // gtk_container_add (GTK_CONTAINER (sw), widget); return mainvbox; @@@ -2647,20 -2744,21 +2775,21 @@@ static GtkWidget *ui_mainwindow_scheduled_create(struct hbfile_data *data) { - GtkWidget *mainvbox, *hbox, *vbox, *sw, *tbar; - GtkWidget *label, *image, *align, *widget; + GtkWidget *mainvbox, *hbox, *vbox, *bbox, *sw, *tbar; + GtkWidget *label, *widget; GtkToolItem *toolitem; - mainvbox = gtk_vbox_new (FALSE, 0); + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); data->GR_upc = mainvbox; - hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL); gtk_box_pack_start (GTK_BOX (mainvbox), hbox, FALSE, FALSE, 0); - label = make_label(_("Scheduled transactions"), 0.0, 0.5); - //gtk_label_set_angle(GTK_LABEL(label), 90.0); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2); + label = make_label_group(_("Scheduled transactions")); + gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2); + gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); label = make_label(_("maximum post date"), 0.0, 0.7); @@@ -2672,13 -2770,12 +2801,12 @@@ gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - align = gtk_alignment_new(0, 0, 1.0, 1.0); - // top, bottom, left, right - gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING); - gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (align), vbox); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0); + gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL); + gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL); + gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL); + gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0); sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); @@@ -2692,25 -2789,41 +2820,41 @@@ tbar = gtk_toolbar_new(); gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU); gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS); + gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR); gtk_box_pack_start (GTK_BOX (vbox), tbar, FALSE, FALSE, 0); - /*widget = gtk_tool_item_new (); - label = gtk_label_new("test"); - gtk_container_add(GTK_CONTAINER(widget), label); - gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(widget), -1);*/ - - image = gtk_image_new_from_icon_name ("media-skip-forward", GTK_ICON_SIZE_MENU); + bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); + toolitem = gtk_tool_item_new(); + gtk_container_add (GTK_CONTAINER(toolitem), bbox); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + widget = gtk_button_new_with_label(_("Skip")); + data->BT_sched_skip = widget; + gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0); + + widget = gtk_button_new_with_label(_("Edit & Post")); + data->BT_sched_editpost = widget; + gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0); + + //TRANSLATORS: Posting a scheduled transaction is the action to materialize it into its target account. + //TRANSLATORS: Before that action the automated transaction occurrence is pending and not yet really existing. + widget = gtk_button_new_with_label (_("Post")); + data->BT_sched_post = widget; + gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0); + + + /* image = gtk_image_new_from_icon_name (ICONNAME_HB_SCHED_SKIP, GTK_ICON_SIZE_MENU); toolitem = gtk_tool_button_new(image, NULL); data->BT_sched_skip = toolitem; gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); gtk_widget_set_tooltip_text(GTK_WIDGET(toolitem), _("Skip")); - image = gtk_image_new_from_icon_name ("media-playback-start", GTK_ICON_SIZE_MENU); + image = gtk_image_new_from_icon_name (ICONNAME_HB_SCHED_POST, GTK_ICON_SIZE_MENU); toolitem = gtk_tool_button_new(image, NULL); data->BT_sched_post = toolitem; gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); gtk_widget_set_tooltip_text(GTK_WIDGET(toolitem), _("Post")); - + */ return mainvbox; @@@ -2743,19 -2856,7 +2887,7 @@@ GtkAction *action data->window = window; GLOBALS->mainwindow = window; - //setup, init and show window - wg = &PREFS->wal_wg; - if(wg->s == 0) - { - gtk_window_move(GTK_WINDOW(window), wg->l, wg->t); - gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h); - } - else - gtk_window_maximize(GTK_WINDOW(window)); - - gtk_widget_show (window); - - mainvbox = gtk_vbox_new (FALSE, 0); + mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), mainvbox); ui_mainwindow_create_menu_bar_and_toolbar (data, mainvbox); @@@ -2772,15 -2873,15 +2904,15 @@@ GtkWidget *bar, *label #endif /* Add the main area */ - vbox = gtk_vbox_new (FALSE, 0); - //gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + //gtk_container_set_border_width (GTK_CONTAINER(vbox), SPACING_MEDIUM); gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0); - vpaned = gtk_vpaned_new(); + vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); data->vpaned = vpaned; gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0); - hpaned = gtk_hpaned_new(); + hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); data->hpaned = hpaned; gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE); @@@ -2801,6 -2902,16 +2933,16 @@@ if(PREFS->wal_vpaned > 0) gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned); + //setup, init and show window + wg = &PREFS->wal_wg; + if(wg->s == 0) + { + gtk_window_move(GTK_WINDOW(window), wg->l, wg->t); + gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h); + } + else + gtk_window_maximize(GTK_WINDOW(window)); + gtk_widget_show_all (window); //todo: move this elsewhere @@@ -2842,9 -2953,15 +2984,15 @@@ g_signal_connect (GTK_TREE_VIEW(data->LV_acc), "row-activated", G_CALLBACK (ui_mainwindow_onRowActivated), GINT_TO_POINTER(2)); g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_upc)), "changed", G_CALLBACK (ui_mainwindow_scheduled_selection_cb), NULL); - g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data); + g_signal_connect (GTK_TREE_VIEW(data->LV_upc), "row-activated", G_CALLBACK (ui_mainwindow_scheduled_onRowActivated), NULL); g_signal_connect (G_OBJECT (data->BT_sched_skip), "clicked", G_CALLBACK (ui_mainwindow_scheduled_skip_cb), data); + g_signal_connect (G_OBJECT (data->BT_sched_editpost), "clicked", G_CALLBACK (ui_mainwindow_scheduled_editpost_cb), data); + g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data); + widget = radio_get_nth_widget(GTK_CONTAINER(data->RA_type), 1); + if(widget) + g_signal_connect (widget, "toggled", G_CALLBACK (ui_mainwindow_populate_topspending), &data); + g_signal_connect (data->CY_range, "changed", G_CALLBACK (ui_mainwindow_populate_topspending), NULL); @@@ -2859,9 -2976,7 +3007,7 @@@ //gtk_action_group_set_sensitive(data->actions, FALSE); - - return window; + return window; } - diff --combined src/ext-perl.xs index 8002047,0000000..5aa56b0 mode 100644,000000..100644 --- a/src/ext-perl.xs +++ b/src/ext-perl.xs @@@ -1,1042 -1,0 +1,1043 @@@ + +#include +#include +#include + +#include + +#undef _ +#include "homebank.h" +#include "ext.h" +#include "refcount.h" + +extern struct HomeBank *GLOBALS; +#include "dsp_mainwindow.h" +#include "dsp_account.h" +#include "ui-transaction.h" + + +static gint ext_perl_init(int* argc, char** argv[], char** env[]); +static void ext_perl_term(void); +static gboolean ext_perl_check_file(const gchar* plugin_filepath); +static GHashTable* ext_perl_read_plugin_metadata(const gchar* plugin_filepath); +static gint ext_perl_load_plugin(const gchar* plugin_filepath); +static void ext_perl_unload_plugin(const gchar* plugin_filepath); +static void ext_perl_execute_action(const gchar* plugin_filepath); +static void ext_perl_call_hook(const gchar* hook_id, GList* args); + +static SV* val_to_sv(GValue* val); +static GValue* sv_to_val(SV* sv); + +static gboolean gperl_value_from_sv(GValue* value, SV* sv); +static SV* gperl_sv_from_value(const GValue* value, gboolean copy_boxed); + + +static inline GValue* EXT_SV(GValue* v, SV* sv, GType type) +{ + g_value_init(v, type); + gperl_value_from_sv(v, sv); + return v; +} + + +#define EXT_P2C_OBJECT(PKG, ARG, VAR, TYP) \ +if (sv_derived_from(ARG, PKG)) { \ + IV iv = SvIV((SV*)SvRV(ARG)); \ + VAR = INT2PTR(TYP, iv); \ +} else { \ + croak(#VAR" is not of type "PKG); \ +} + +#define EXT_C2P_OBJECT(PKG, ARG, VAR) \ +sv_setref_pv(ARG, PKG, (void*)VAR) + + +static inline GPtrArray* SvGptrarray(const SV* sv) +{ + if (SvROK(sv)) { + sv = MUTABLE_SV(SvRV(sv)); + } + if (SvTYPE(sv) == SVt_PVAV) { + AV* av = (AV*)sv; + int i; + int top = av_len(av); + GPtrArray* array = g_ptr_array_new(); + for (i = 0; i <= top; ++i) { + SV** item = av_fetch(av, i, 0); + if (!item) continue; + g_ptr_array_add(array, sv_to_val(*item)); + } + return array; + // TODO- leaking + } else { + croak("var is not an array"); + } +} + +static inline SV* newSVgptrarray(const GPtrArray* a) +{ + if (a) { + AV* av = newAV(); + int i; + for (i = 0; i < a->len; ++i) { + GValue* item = g_ptr_array_index(a, i); + av_push(av, val_to_sv(item)); + } + return newRV((SV*)av); + } + return &PL_sv_undef; +} + + +static inline GHashTable* SvGhashtable(const SV* sv) +{ + if (SvROK(sv)) { + sv = MUTABLE_SV(SvRV(sv)); + } + if (SvTYPE(sv) == SVt_PVHV) { + HV* hv = (HV*)sv; + hv_iterinit(hv); + gchar* key; + I32 len; + SV* item; + GHashTable* hash = g_hash_table_new(g_str_hash, g_str_equal); + while ((item = hv_iternextsv(hv, &key, &len))) { + g_hash_table_insert(hash, key, sv_to_val(item)); + } + return hash; + // TODO- leaking + } else { + croak("var is not a hash"); + } +} + +static inline SV* newSVghashtable(GHashTable* h) +{ + if (h) { + HV* hv = newHV(); + GHashTableIter it; + g_hash_table_iter_init(&it, h); + gchar* key = NULL; + GValue* item = NULL; + while (g_hash_table_iter_next(&it, (gpointer*)&key, (gpointer*)&item)) { + hv_store(hv, key, -g_utf8_strlen(key, -1), val_to_sv(item), 0); + } + return newRV((SV*)hv); + } + return &PL_sv_undef; +} + + +static inline gboolean SvGboolean(SV* sv) +{ + if (!sv) { + return FALSE; + } + if (SvROK(sv)) { + return !!SvIV(SvRV(sv)); + } else { + return SvTRUE(sv); + } +} + +static inline SV* newSVgboolean(gboolean b) +{ + return sv_setref_iv(newSV(0), "HomeBank::Boolean", !!b); +} + + +static inline gchar* SvGchar_ptr(SV* sv) +{ + return SvPVutf8_nolen(sv); +} + +static inline SV* newSVgchar_ptr(const gchar* str) +{ + if (!str) return &PL_sv_undef; + + SV* sv = newSVpv(str, 0); + SvUTF8_on(sv); + return sv; +} + + +static inline GObject* SvGobject(const SV* sv) +{ + GObject* (*func)(const SV*) = ext_symbol_lookup("gperl_get_object"); + if (func) { + return func(sv); + } + return NULL; +} + +static inline SV* newSVgobject(const GObject* o) +{ + SV* (*func)(const GObject*, gboolean) = ext_symbol_lookup("gperl_new_object"); + if (func) { + return func(o, FALSE); + } + return &PL_sv_undef; +} + + +static PerlInterpreter* context = NULL; + + +static gint ext_perl_init(int* argc, char** argv[], char** env[]) +{ + int ret = 0; + + PERL_SYS_INIT3(argc, argv, env); + context = perl_alloc(); + perl_construct(context); + + PL_exit_flags |= PERL_EXIT_DESTRUCT_END; + PL_origalen = 1; + PL_perl_destruct_level = 1; + + gchar* bootstrap = g_strdup_printf("-e" + "use lib '%s';" + "use HomeBank;" + "HomeBank->bootstrap;", + homebank_app_get_pkglib_dir()); + char *args[] = { "", bootstrap }; + + EXTERN_C void xs_init(pTHX); + if (perl_parse(context, xs_init, 2, args, NULL) || perl_run(context)) { + ext_perl_term(); + ret = -1; + } + + g_free(bootstrap); + return ret; +} + +static void ext_perl_term(void) +{ + if (context) { + perl_destruct(context); + perl_free(context); + context = NULL; + } + PERL_SYS_TERM(); +} + +static gboolean ext_perl_check_file(const gchar* plugin_filepath) +{ + if (g_str_has_suffix(plugin_filepath, ".pl")) { + return TRUE; + } + return FALSE; +} + +static GHashTable* ext_perl_read_plugin_metadata(const gchar* plugin_filepath) +{ + GHashTable* table = NULL; + + if (!context) return NULL; + PERL_SET_CONTEXT(context); + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + mXPUSHs(newSVgchar_ptr(plugin_filepath)); + PUTBACK; + + int ret = call_pv("HomeBank::read_metadata", G_SCALAR | G_EVAL); + + SPAGAIN; + + if (ret == 1) { + table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + SV* sv = POPs; + if (SvROK(sv)) { + sv = MUTABLE_SV(SvRV(sv)); + } + if (SvTYPE(sv) == SVt_PVHV) { + HV* hv = (HV*)sv; + hv_iterinit(hv); + gchar* key; + I32 len; + SV* item; + while ((item = hv_iternextsv(hv, &key, &len))) { + if (SvPOK(item)) { + gchar* val = SvPVutf8_nolen(item); + g_hash_table_insert(table, g_strdup(key), g_strdup(val)); + } + } + } + } + + PUTBACK; + FREETMPS; + LEAVE; + + return table; +} + +static gint ext_perl_load_plugin(const gchar* plugin_filepath) +{ + if (!context) return -1; + PERL_SET_CONTEXT(context); + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + mXPUSHs(newSVgchar_ptr(plugin_filepath)); + PUTBACK; + call_pv("HomeBank::load_plugin", G_DISCARD | G_EVAL); + SPAGAIN; + + gint ret = 0; + if (SvTRUE(ERRSV)) { + g_printerr("%s", SvPV_nolen(ERRSV)); + ret = -1; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return ret; +} + +static void ext_perl_unload_plugin(const gchar* plugin_filepath) +{ + if (!context) return; + PERL_SET_CONTEXT(context); + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + mXPUSHs(newSVgchar_ptr(plugin_filepath)); + PUTBACK; + call_pv("HomeBank::unload_plugin", G_DISCARD | G_EVAL); + SPAGAIN; + + if (SvTRUE(ERRSV)) { + g_printerr("%s", SvPV_nolen(ERRSV)); + } + + PUTBACK; + FREETMPS; + LEAVE; +} + +static void ext_perl_execute_action(const gchar* plugin_filepath) +{ + if (!context) return; + PERL_SET_CONTEXT(context); + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + mXPUSHs(newSVgchar_ptr(plugin_filepath)); + PUTBACK; + call_pv("HomeBank::execute_action", G_DISCARD | G_EVAL); + SPAGAIN; + + if (SvTRUE(ERRSV)) { + g_printerr("%s", SvPV_nolen(ERRSV)); + } + + PUTBACK; + FREETMPS; + LEAVE; +} + +static void ext_perl_call_hook(const gchar* hook_id, GList* args) +{ + if (!context) return; + PERL_SET_CONTEXT(context); + + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + mXPUSHs(newSVgchar_ptr(hook_id)); + + GList *list = g_list_first(args); + while (list) { + GValue* val = list->data; + XPUSHs(sv_2mortal(val_to_sv(val))); + list = g_list_next(list); + } + + PUTBACK; + call_pv("HomeBank::call_hook", G_ARRAY); + SPAGAIN; + POPi; + PUTBACK; + FREETMPS; + LEAVE; +} + + +static SV* val_to_sv(GValue* val) +{ + if (!val || !G_IS_VALUE(val) || G_VALUE_TYPE(val) == G_TYPE_NONE) { + return &PL_sv_undef; + } + if (G_VALUE_TYPE(val) == G_TYPE_BOOLEAN) { + return newSVgboolean(g_value_get_boolean(val)); + } + if (G_VALUE_TYPE(val) == G_TYPE_PTR_ARRAY) { + return newSVgptrarray((GPtrArray*)g_value_get_boxed(val)); + } + if (G_VALUE_TYPE(val) == G_TYPE_HASH_TABLE) { + return newSVghashtable((GHashTable*)g_value_get_boxed(val)); + } +#define obj(CTYPE, _2, PART, GTYPE, _5) \ + if (G_VALUE_TYPE(val) == GTYPE) { \ + SV* sv = newSV(0); \ + CTYPE* ptr = (CTYPE*)g_value_get_##PART(val); \ + EXT_C2P_OBJECT("HomeBank::"#CTYPE, sv, rc_ref(ptr)); \ + return sv; \ + } +#include "ext-value.h" +#undef obj + return gperl_sv_from_value(val, FALSE); +} + +static GValue* sv_to_val(SV* sv) +{ + GValue* val = g_new0(GValue, 1); + + if (SvUOK(sv)) return EXT_SV(val, sv, G_TYPE_UINT); + if (SvIOK(sv)) return EXT_SV(val, sv, G_TYPE_INT); + if (SvNOK(sv)) return EXT_SV(val, sv, G_TYPE_DOUBLE); + if (SvPOK(sv)) return EXT_SV(val, sv, G_TYPE_STRING); + if (sv_isobject(sv)) { + if (sv_derived_from(sv, "HomeBank::Boolean")) { + return EXT_BOOLEAN(val, SvGboolean(sv)); + } +#define obj(CTYPE, NAME, _3, _4, _5) \ + if (sv_derived_from(sv, "HomeBank::"#CTYPE)) { \ + CTYPE* ptr; \ + EXT_P2C_OBJECT("HomeBank::"#CTYPE, sv, ptr, CTYPE*); \ + return EXT_##NAME(val, ptr); \ + } +#include "ext-value.h" +#undef obj + return EXT_SV(val, sv, G_TYPE_OBJECT); + } + if (SvROK(sv)) { + sv = SvRV(sv); + switch (SvTYPE(sv)) { + case SVt_IV: + return EXT_BOOLEAN(val, SvGboolean(sv)); + case SVt_PVAV: + return EXT_ARRAY(val, SvGptrarray(sv)); + case SVt_PVHV: + return EXT_HASH_TABLE(val, SvGhashtable(sv)); + default: + break; + } + } + switch (SvTYPE(sv)) { + case SVt_PVAV: + return EXT_ARRAY(val, SvGptrarray(sv)); + case SVt_PVHV: + return EXT_HASH_TABLE(val, SvGhashtable(sv)); + default: + break; + } + + g_free(val); + return NULL; +} + + +static gboolean gperl_value_from_sv(GValue* value, SV* sv) +{ + gboolean (*func)(GValue*, SV*) = ext_symbol_lookup("gperl_value_from_sv"); + if (func) return func(value, sv); + + GType type = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value)); + if (!SvOK(sv)) return TRUE; + switch (type) { + case G_TYPE_CHAR: + { + gchar *tmp = SvGchar_ptr(sv); + g_value_set_schar(value, (gint8)(tmp ? tmp[0] : 0)); + break; + } + case G_TYPE_UCHAR: + { + char *tmp = SvPV_nolen(sv); + g_value_set_uchar(value, (guchar)(tmp ? tmp[0] : 0)); + break; + } + case G_TYPE_BOOLEAN: + g_value_set_boolean(value, SvTRUE(sv)); + break; + case G_TYPE_INT: + g_value_set_int(value, SvIV(sv)); + break; + case G_TYPE_UINT: + g_value_set_uint(value, SvIV(sv)); + break; + case G_TYPE_LONG: + g_value_set_long(value, SvIV(sv)); + break; + case G_TYPE_ULONG: + g_value_set_ulong(value, SvIV(sv)); + break; + case G_TYPE_FLOAT: + g_value_set_float(value, (gfloat)SvNV(sv)); + break; + case G_TYPE_DOUBLE: + g_value_set_double(value, SvNV(sv)); + break; + case G_TYPE_STRING: + g_value_set_string(value, SvGchar_ptr(sv)); + break; + } + return TRUE; +} + +static SV* gperl_sv_from_value(const GValue* value, gboolean copy_boxed) +{ + SV* (*func)(const GValue*, gboolean) = ext_symbol_lookup("gperl_sv_from_value"); + if (func) return func(value, copy_boxed); + + GType type = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value)); + switch (type) { + case G_TYPE_CHAR: + return newSViv(g_value_get_schar(value)); + case G_TYPE_UCHAR: + return newSVuv(g_value_get_uchar(value)); + case G_TYPE_BOOLEAN: + return newSViv(g_value_get_boolean(value)); + case G_TYPE_INT: + return newSViv(g_value_get_int(value)); + case G_TYPE_UINT: + return newSVuv(g_value_get_uint(value)); + case G_TYPE_LONG: + return newSViv(g_value_get_long(value)); + case G_TYPE_ULONG: + return newSVuv(g_value_get_ulong(value)); + case G_TYPE_FLOAT: + return newSVnv(g_value_get_float(value)); + case G_TYPE_DOUBLE: + return newSVnv(g_value_get_double(value)); + case G_TYPE_STRING: + return newSVgchar_ptr(g_value_get_string(value)); + } + return &PL_sv_undef; +} + + +static void _register(void) __attribute__((constructor)); +static void _register() +{ + ext_register("perl", + ext_perl_init, + ext_perl_term, + ext_perl_check_file, + ext_perl_read_plugin_metadata, + ext_perl_load_plugin, + ext_perl_unload_plugin, + ext_perl_execute_action, + ext_perl_call_hook); +} + + +MODULE = HomeBank PACKAGE = HomeBank + +PROTOTYPES: ENABLE + +const gchar* +version(void) + CODE: + RETVAL = VERSION; + OUTPUT: + RETVAL + +const gchar* +config_dir(void) + CODE: + RETVAL = homebank_app_get_config_dir(); + OUTPUT: + RETVAL + +gboolean +has(const gchar* CLASS, ...) + PREINIT: + int i; + CODE: + PERL_UNUSED_ARG(CLASS); + RETVAL = TRUE; + for (i = 1; i < items; ++i) { + gchar* feature = SvGchar_ptr(ST(i)); + if (!feature || !ext_has(feature)) { + RETVAL = FALSE; + break; + } + } + OUTPUT: + RETVAL + +GObject* +main_window(void) + CODE: + RETVAL = G_OBJECT(GLOBALS->mainwindow); + OUTPUT: + RETVAL + +GObject* +main_ui_manager(void) + PREINIT: + struct hbfile_data *data; + CODE: + RETVAL = NULL; + if (GLOBALS->mainwindow) { + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GLOBALS->mainwindow, GTK_TYPE_WINDOW)), "inst_data"); + if (data) { + RETVAL = G_OBJECT(data->manager); + } + } + OUTPUT: + RETVAL + +void +info(const gchar* CLASS, const gchar* title, const gchar* text) + CODE: + PERL_UNUSED_ARG(CLASS); + ext_run_modal(title, text, "info"); + +void +warn(const gchar* CLASS, const gchar* title, const gchar* text) + CODE: + PERL_UNUSED_ARG(CLASS); + ext_run_modal(title, text, "warn"); + +void +error(const gchar* CLASS, const gchar* title, const gchar* text) + CODE: + PERL_UNUSED_ARG(CLASS); + ext_run_modal(title, text, "error"); + +void +hook(const gchar* CLASS, const gchar* hook_name, ...) + PREINIT: + int i; + GList* list = NULL; + CODE: + PERL_UNUSED_ARG(CLASS); + for (i = 2; i < items; ++i) { + SV* sv = ST(i); + GValue *val = sv_to_val(sv); + list = g_list_append(list, val); + } + CLEANUP: + ext_vhook(hook_name, list); + g_list_free(list); + // TODO free all the things + +GObject* +open_prefs(const gchar* CLASS) + CODE: + PERL_UNUSED_ARG(CLASS); + RETVAL = G_OBJECT(defpref_dialog_new(PREF_GENERAL)); + OUTPUT: + RETVAL + + +MODULE = HomeBank PACKAGE = HomeBank::File + +const gchar* +owner(const gchar* CLASS, ...) + CODE: + PERL_UNUSED_ARG(CLASS); + if (1 < items) { + hbfile_change_owner(g_strdup(SvGchar_ptr(ST(1)))); + } + RETVAL = GLOBALS->owner; + OUTPUT: + RETVAL + +void +transactions(const gchar* CLASS) + PPCODE: + PERL_UNUSED_ARG(CLASS); - GList* list = g_list_first(GLOBALS->ope_list); - for (; list; list = g_list_next(list)) { - GValue val = G_VALUE_INIT; - SV* sv = val_to_sv(EXT_TRANSACTION(&val, list->data)); - mXPUSHs(sv); ++ ++ GList* acc_list = g_hash_table_get_values(GLOBALS->h_acc); ++ GList* acc_link = g_list_first(acc_list); ++ for (; acc_link; acc_link = g_list_next(acc_link)) { ++ Account *acc = acc_link->data; ++ ++ GList* txn_link = g_queue_peek_head_link(acc->txn_queue); ++ for (; txn_link; txn_link = g_list_next(txn_link)) { ++ Transaction* txn = txn_link->data; ++ ++ GValue val = G_VALUE_INIT; ++ SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn)); ++ mXPUSHs(sv); ++ } + } + ++ g_list_free(acc_list); ++ +void +anonymize(void) + CODE: + hbfile_anonymize(); + +void +baz(const gchar* CLASS, Account* account) + CODE: + PERL_UNUSED_ARG(CLASS); + g_print("hello: %s\n", account->name); + +GPtrArray* +meh(const gchar* CLASS, GPtrArray* asdf) + CODE: + PERL_UNUSED_ARG(CLASS); + g_print("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n"); + if (asdf) { + ; + } else { + g_print("the array is nil\n"); + } + RETVAL = asdf; + OUTPUT: + RETVAL + CLEANUP: + g_ptr_array_unref(asdf); + +GHashTable* +foo(const gchar* CLASS, GHashTable* asdf) + CODE: + PERL_UNUSED_ARG(CLASS); + g_print("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n"); + if (asdf) { + GHashTableIter it; + g_hash_table_iter_init(&it, asdf); + gchar* key = NULL; + GValue* item = NULL; + while (g_hash_table_iter_next(&it, (gpointer*)&key, (gpointer*)&item)) { + g_print("hash with key: %s\n", key); + } + } else { + g_print("the hash is nil\n"); + } + RETVAL = asdf; + OUTPUT: + RETVAL + CLEANUP: + g_hash_table_unref(asdf); + + +MODULE = HomeBank PACKAGE = HomeBank::Account + +void +compute_balances(const gchar* CLASS) + CODE: + PERL_UNUSED_ARG(CLASS); + account_compute_balances(); + +Account* +new(void) + CODE: + RETVAL = da_acc_malloc(); + OUTPUT: + RETVAL + - Account* - clone(Account* SELF) - CODE: - RETVAL = da_acc_clone(SELF); - RETVAL->key = 0; - OUTPUT: - RETVAL - +void +DESTROY(Account* SELF) + CODE: + da_acc_free(SELF); + +Account* +get(const gchar* CLASS, guint key) + CODE: + PERL_UNUSED_ARG(CLASS); + RETVAL = rc_ref(da_acc_get(key)); + OUTPUT: + RETVAL + +Account* +get_by_name(const gchar* CLASS, const gchar* name) + CODE: + PERL_UNUSED_ARG(CLASS); + RETVAL = rc_ref(da_acc_get_by_name((gchar*)name)); + OUTPUT: + RETVAL + +const gchar* +name(Account* SELF, ...) + CODE: + if (1 < items) { + account_rename(SELF, SvGchar_ptr(ST(1))); + } + RETVAL = SELF->name; + OUTPUT: + RETVAL + +const gchar* +number(Account* SELF, ...) + CODE: + if (1 < items) { + g_free(SELF->number); + SELF->number = g_strdup(SvGchar_ptr(ST(1))); + } + RETVAL = SELF->number; + OUTPUT: + RETVAL + +const gchar* +bankname(Account* SELF, ...) + CODE: + if (1 < items) { + g_free(SELF->bankname); + SELF->bankname = g_strdup(SvGchar_ptr(ST(1))); + } + RETVAL = SELF->bankname; + OUTPUT: + RETVAL + +gdouble +initial(Account* SELF, ...) + CODE: + if (1 < items) { + SELF->initial = SvNV(ST(1)); + } + RETVAL = SELF->initial; + OUTPUT: + RETVAL + +gdouble +minimum(Account* SELF, ...) + CODE: + if (1 < items) { + SELF->minimum = SvNV(ST(1)); + } + RETVAL = SELF->minimum; + OUTPUT: + RETVAL + +guint +cheque1(Account* SELF, ...) + ALIAS: + check1 = 1 + CODE: + PERL_UNUSED_VAR(ix); + if (1 < items) { + SELF->cheque1 = SvUV(ST(1)); + } + RETVAL = SELF->cheque1; + OUTPUT: + RETVAL + +guint +cheque2(Account* SELF, ...) + ALIAS: + check2 = 1 + CODE: + PERL_UNUSED_VAR(ix); + if (1 < items) { + SELF->cheque2 = SvUV(ST(1)); + } + RETVAL = SELF->cheque2; + OUTPUT: + RETVAL + +gdouble +balance(Account* SELF) + ALIAS: + bank_balance = 1 + future_balance = 2 + CODE: + switch (ix) { + case 1: + RETVAL = SELF->bal_bank; + break; + case 2: + RETVAL = SELF->bal_future; + break; + default: + RETVAL = SELF->bal_today; + break; + } + OUTPUT: + RETVAL + +gboolean +is_inserted(Account* SELF) + CODE: + RETVAL = da_acc_get(SELF->key) == SELF; + OUTPUT: + RETVAL + +gboolean +is_used(Account* SELF) + CODE: + RETVAL = account_is_used(SELF->key); + OUTPUT: + RETVAL + +gboolean +insert(Account* SELF) + CODE: + if (SELF->key == 0 || account_is_used(SELF->key)) + RETVAL = da_acc_append(rc_ref(SELF)); + else + RETVAL = da_acc_insert(rc_ref(SELF)); + OUTPUT: + RETVAL + +void +remove(Account* SELF) + CODE: + da_acc_remove(SELF->key); + +void +transactions(Account* SELF) + PPCODE: - GList* list = g_list_first(GLOBALS->ope_list); ++ GList* list = g_queue_peek_head_link(SELF->txn_queue); + for (; list; list = g_list_next(list)) { + Transaction* txn = list->data; - if (txn->kacc == SELF->key) { - GValue val = G_VALUE_INIT; - SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn)); - mXPUSHs(sv); - } ++ GValue val = G_VALUE_INIT; ++ SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn)); ++ mXPUSHs(sv); + } + +GObject* +open(Account* SELF) + CODE: + RETVAL = G_OBJECT(register_panel_window_new(SELF->key, SELF)); + OUTPUT: + RETVAL + + +MODULE = HomeBank PACKAGE = HomeBank::Transaction + +Transaction* +new(void) + CODE: + RETVAL = da_transaction_malloc(); + OUTPUT: + RETVAL + +void +DESTROY(Transaction* SELF) + CODE: + da_transaction_free(SELF); + +gdouble +amount(Transaction* SELF, ...) + CODE: + if (1 < items) { + SELF->amount = SvNV(ST(1)); + } + RETVAL = SELF->amount; + OUTPUT: + RETVAL + +guint +account_num(Transaction* SELF, ...) + CODE: + if (1 < items) { + SELF->kacc = SvIV(ST(1)); + } + RETVAL = SELF->kacc; + OUTPUT: + RETVAL + +guint +paired_account_num(Transaction* SELF, ...) + CODE: + if (1 < items) { + SELF->kxferacc = SvIV(ST(1)); + } + RETVAL = SELF->kxferacc; + OUTPUT: + RETVAL + +void +date(Transaction* SELF, ...) + PPCODE: + if (1 < items) { + SELF->date = SvIV(ST(1)); + } + if (GIMME_V == G_ARRAY) { + GDate* d = g_date_new_julian(SELF->date); + mXPUSHp("day", 3); + mXPUSHi(g_date_get_day(d)); + mXPUSHp("month", 5); + mXPUSHi(g_date_get_month(d)); + mXPUSHp("year", 4); + mXPUSHi(g_date_get_year(d)); + g_date_free(d); + XSRETURN(6); + } else { + XSRETURN_IV(SELF->date); + } + +const gchar* +wording(Transaction* SELF, ...) + CODE: + if (1 < items) { + if (SELF->wording) g_free(SELF->wording); + SELF->wording = g_strdup(SvGchar_ptr(ST(1))); + } + RETVAL = SELF->wording ? SELF->wording : ""; + OUTPUT: + RETVAL + +const gchar* +info(Transaction* SELF, ...) + CODE: + if (1 < items) { + if (SELF->info) g_free(SELF->info); + SELF->info = g_strdup(SvGchar_ptr(ST(1))); + } + RETVAL = SELF->info ? SELF->info : ""; + OUTPUT: + RETVAL + +GObject* +open(Transaction* SELF) + CODE: - RETVAL = G_OBJECT(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY)); ++ RETVAL = G_OBJECT(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY, FALSE)); + deftransaction_set_transaction(GTK_WIDGET(RETVAL), SELF); + OUTPUT: + RETVAL + +Transaction* +pair_with(Transaction* SELF, Transaction* other, ...) + PREINIT: + int i; + GList* list = NULL; + CODE: + if (2 < items) { + list = g_list_append(list, other); + for (i = 2; i < items; ++i) { + Transaction* ptr = NULL; + SV* sv = ST(i); + EXT_P2C_OBJECT("HomeBank::Transaction", sv, ptr, Transaction*); + list = g_list_append(list, ptr); + } - other = ui_dialog_transaction_xfer_select_child(list); ++ other = ui_dialog_transaction_xfer_select_child(SELF, list); + } + if (other) { + transaction_xfer_change_to_child(SELF, other); + SELF->paymode = PAYMODE_INTXFER; + } + RETVAL = other; + OUTPUT: + RETVAL + CLEANUP: + g_list_free(list); + +void +dump(Transaction* SELF) + CODE: + g_print("txn: %p (%s) at %u (%d/%d) flags:%d, paymode:%d, kpay:%d, kcat:%d", SELF, + SELF->wording, SELF->date, SELF->kacc, SELF->kxferacc, SELF->flags, SELF->paymode, SELF->kpay, SELF->kcat); + diff --combined src/hb-account.c index c3366e7,56b5339..9064868 --- a/src/hb-account.c +++ b/src/hb-account.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,9 -20,6 +20,9 @@@ #include "homebank.h" #include "hb-account.h" +#include "ext.h" +#include "refcount.h" + /****************************************************************************/ /* Debug macros */ /****************************************************************************/ @@@ -38,31 -35,11 +38,11 @@@ extern struct HomeBank *GLOBALS; - - - - Account * - da_acc_clone(Account *src_item) - { - Account *new_item = rc_dup(src_item, sizeof(Account)); - - DB( g_print("da_acc_clone\n") ); - if(new_item) - { - //duplicate the string - new_item->name = g_strdup(src_item->name); - new_item->number = g_strdup(src_item->number); - new_item->bankname = g_strdup(src_item->bankname); - } - return new_item; - } - - void da_acc_free(Account *item) { DB( g_print("da_acc_free\n") ); - if(item != NULL) + if(rc_unref(item)) { DB( g_print(" => %d, %s\n", item->key, item->name) ); @@@ -70,7 -47,11 +50,11 @@@ g_free(item->name); g_free(item->number); g_free(item->bankname); + g_free(item->notes); + + g_queue_free (item->txn_queue); + - g_free(item); + rc_free(item); } } @@@ -78,8 -59,12 +62,12 @@@ Account * da_acc_malloc(void) { + Account *item; + DB( g_print("da_acc_malloc\n") ); - return rc_alloc(sizeof(Account)); - item = g_malloc0(sizeof(Account)); ++ item = rc_alloc(sizeof(Account)); + item->txn_queue = g_queue_new (); + return item; } @@@ -140,9 -125,9 +128,9 @@@ da_acc_length(void /** * da_acc_remove: * - * remove an account from the GHashTable + * delete an account from the GHashTable * - * Return value: TRUE if the key was found and removed + * Return value: TRUE if the key was found and deleted * */ gboolean @@@ -172,9 -157,6 +160,9 @@@ guint32 *new_key *new_key = item->key; g_hash_table_insert(GLOBALS->h_acc, new_key, item); + GValue item_val = G_VALUE_INIT; + ext_hook("account_inserted", EXT_ACCOUNT(&item_val, item), NULL); + return TRUE; } @@@ -210,10 -192,6 +198,10 @@@ guint32 *new_key DB( g_print(" -> insert id: %d\n", *new_key) ); g_hash_table_insert(GLOBALS->h_acc, new_key, item); + + GValue item_val = G_VALUE_INIT; + ext_hook("account_inserted", EXT_ACCOUNT(&item_val, item), NULL); + return TRUE; } } @@@ -360,57 -338,68 +348,68 @@@ GList *list = g_hash_table_get_values(G gboolean account_is_used(guint32 key) { + Account *acc; GList *list; + GList *lst_acc, *lnk_acc; + GList *lnk_txn; + gboolean retval; - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) - { - Transaction *entry = list->data; - if( key == entry->kacc || key == entry->kxferacc) - return TRUE; - list = g_list_next(list); - } + retval = FALSE; + lst_acc = NULL; - list = g_list_first(GLOBALS->arc_list); - while (list != NULL) + acc = da_acc_get(key); + if( g_queue_get_length(acc->txn_queue) > 0 ) { - Archive *entry = list->data; - if( key == entry->kacc || key == entry->kxferacc) - return TRUE; - list = g_list_next(list); + retval = TRUE; + goto end; } - return FALSE; - } - - void - account_move(guint32 key1, guint32 key2) - { - GList *list; - - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - Transaction *entry = list->data; - if(entry->kacc == key1) - entry->kacc = key2; - if(entry->kxferacc == key1) - entry->kxferacc = key2; - list = g_list_next(list); + Account *acc = lnk_acc->data; + + if(acc->key != key) + { + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) + { + Transaction *entry = lnk_txn->data; + + if( key == entry->kxferacc) + { + retval = TRUE; + goto end; + } + + lnk_txn = g_list_next(lnk_txn); + } + } + lnk_acc = g_list_next(lnk_acc); } list = g_list_first(GLOBALS->arc_list); while (list != NULL) { Archive *entry = list->data; - if(entry->kacc == key1) - entry->kacc = key2; - if(entry->kxferacc == key1) - entry->kxferacc = key2; + + if( key == entry->kacc || key == entry->kxferacc) + { + retval = TRUE; + goto end; + } + list = g_list_next(list); } + + end: + g_list_free(lst_acc); + + return retval; } + static gchar * account_get_stripname(gchar *name) { @@@ -453,46 -442,62 +452,62 @@@ gchar *stripname = account_get_stripnam return FALSE; } - /* when we change the currency of an account, we must ensure - * xfer transaction account will be set to same currency + + /* + * change the account currency + * change every txn to currency + * ensure dst xfer transaction account will be set to same currency */ - /* - void account_set_currency(Account *item, guint32 kcur) + void account_set_currency(Account *acc, guint32 kcur) { GList *list; - Account *acc; + Account *dstacc; + gboolean *xfer_list; + guint32 maxkey, i; - if(item->kcur != kcur) + DB( g_print("\n[account] set currency\n") ); + + if(acc->kcur == kcur) { - item->kcur = kcur; - - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + DB( g_print(" - already ok, return\n") ); + return; + } + + DB( g_print(" - set for '%s'\n", acc->name) ); + + maxkey = da_acc_get_max_key () + 1; + xfer_list = g_malloc0(sizeof(gboolean) * maxkey ); + DB( g_print(" - alloc for %d account\n", da_acc_length() ) ); + + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *txn = list->data; + + txn->kcur = kcur; + if( (txn->paymode == PAYMODE_INTXFER) && (txn->kxferacc > 0) && (txn->kxfer > 0) ) { - Transaction *entry = list->data; - if(entry->paymode == PAYMODE_INTXFER) - { - if(entry->kacc == item->key) - { - // change target account - acc = da_acc_get (entry->kxferacc); - acc->kcur = kcur; - } - if(entry->kxferacc == item->key) - { - // change source account - acc = da_acc_get (entry->kacc); - acc->kcur = kcur; - } - } - - list = g_list_next(list); + xfer_list[txn->kxferacc] = TRUE; } + list = g_list_next(list); } + + acc->kcur = kcur; + DB( g_print(" - '%s'\n", acc->name) ); - } - */ + for(i=1;idate <= GLOBALS->today) acc->bal_today -= trn->amount; - if(trn->flags & OF_VALID) + if(trn->status == TXN_STATUS_RECONCILED) + //if(trn->flags & OF_VALID) acc->bal_bank -= trn->amount; } @@@ -519,7 -525,8 +535,8 @@@ static void account_balances_add_intern if(trn->date <= GLOBALS->today) acc->bal_today += trn->amount; - if(trn->flags & OF_VALID) + if(trn->status == TXN_STATUS_RECONCILED) + //if(trn->flags & OF_VALID) acc->bal_bank += trn->amount; } @@@ -529,7 -536,9 +546,9 @@@ */ gboolean account_balances_sub(Transaction *trn) { - if(!(trn->flags & OF_REMIND)) + + if(!(trn->status == TXN_STATUS_REMIND)) + //if(!(trn->flags & OF_REMIND)) { Account *acc = da_acc_get(trn->kacc); if(acc == NULL) return FALSE; @@@ -545,7 -554,8 +564,8 @@@ */ gboolean account_balances_add(Transaction *trn) { - if(!(trn->flags & OF_REMIND)) + if(!(trn->status == TXN_STATUS_REMIND)) + //if(!(trn->flags & OF_REMIND)) { Account *acc = da_acc_get(trn->kacc); if(acc == NULL) return FALSE; @@@ -556,49 -566,60 +576,60 @@@ } - - - - + //todo: optim called 2 times from dsp_mainwindow void account_compute_balances(void) { - GList *lacc, *list; - Account *acc; - Transaction *trn; + GList *lst_acc, *lnk_acc; + GList *lnk_txn; DB( g_print("\naccount_compute_balances start\n") ); - /* set initial amount */ - lacc = list = g_hash_table_get_values(GLOBALS->h_acc); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - acc = list->data; + Account *acc = lnk_acc->data; + + /* set initial amount */ acc->bal_bank = acc->initial; acc->bal_today = acc->initial; acc->bal_future = acc->initial; - list = g_list_next(list); - } - g_list_free(lacc); - - - /* compute every transaction */ - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) - { - trn = list->data; - - if(!(trn->flags & OF_REMIND)) + + /* add every txn */ + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) { - account_balances_add(trn); + account_balances_add_internal(acc, lnk_txn->data); + lnk_txn = g_list_next(lnk_txn); } - list = g_list_next(list); + + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); DB( g_print("\naccount_compute_balances end\n") ); } + void account_convert_euro(Account *acc) + { + GList *lnk_txn; + + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) + { + Transaction *txn = lnk_txn->data; + gdouble oldamount = txn->amount; + txn->amount = hb_amount_to_euro(oldamount); + DB( g_print("%10.6f => %10.6f, %s\n", oldamount, txn->amount, txn->wording) ); + //todo: sync child xfer + lnk_txn = g_list_next(lnk_txn); + } + acc->initial = hb_amount_to_euro(acc->initial); + acc->warning = hb_amount_to_euro(acc->warning); + acc->minimum = hb_amount_to_euro(acc->minimum); + } diff --combined src/hb-archive.c index e3faf5d,c552f85..d815703 --- a/src/hb-archive.c +++ b/src/hb-archive.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -19,10 -19,8 +19,11 @@@ #include "homebank.h" #include "hb-archive.h" + #include "hb-split.h" +#include "ext.h" +#include "refcount.h" + /****************************************************************************/ /* Debug macros */ /****************************************************************************/ @@@ -43,29 -41,35 +44,35 @@@ extern struct HomeBank *GLOBALS Archive *da_archive_malloc(void) { - return g_malloc0(sizeof(Archive)); + return rc_alloc(sizeof(Archive)); } Archive *da_archive_clone(Archive *src_item) { -Archive *new_item = g_memdup(src_item, sizeof(Archive)); +Archive *new_item = rc_dup(src_item, sizeof(Archive)); if(new_item) { //duplicate the string new_item->wording = g_strdup(src_item->wording); + + if( da_splits_clone(src_item->splits, new_item->splits) > 0) + new_item->flags |= OF_SPLIT; //Flag that Splits are active } return new_item; } void da_archive_free(Archive *item) { - if(item != NULL) + if(rc_unref(item)) { if(item->wording != NULL) g_free(item->wording); + da_splits_free(item->splits); + //item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared + - g_free(item); + rc_free(item); } } @@@ -110,27 -114,31 +117,31 @@@ Payee *pay { g_warning("arc consistency: fixed invalid cat %d", item->kcat); item->kcat = 0; + GLOBALS->changes_count++; } - + + split_cat_consistency(item->splits); + // check payee exists pay = da_pay_get(item->kpay); if(pay == NULL) { g_warning("arc consistency: fixed invalid pay %d", item->kpay); item->kpay = 0; + GLOBALS->changes_count++; } // reset dst acc for non xfer transaction if( item->paymode != PAYMODE_INTXFER ) item->kxferacc = 0; - // remove automation if dst_acc not exists + // delete automation if dst_acc not exists if(item->paymode == PAYMODE_INTXFER) { acc = da_acc_get(item->kxferacc); if(acc == NULL) { - item->flags &= ~(OF_AUTO); //remove flag + item->flags &= ~(OF_AUTO); //delete flag } } @@@ -138,11 -146,38 +149,38 @@@ /* = = = = = = = = = = = = = = = = = = = = */ + Archive *da_archive_init_from_transaction(Archive *arc, Transaction *txn) + { + //fill it + arc->amount = txn->amount; + arc->kacc = txn->kacc; + arc->kxferacc = txn->kxferacc; + arc->paymode = txn->paymode; + arc->flags = txn->flags & (OF_INCOME); + arc->status = txn->status; + arc->kpay = txn->kpay; + arc->kcat = txn->kcat; + if(txn->wording != NULL) + arc->wording = g_strdup(txn->wording); + else + arc->wording = g_strdup(_("(new archive)")); + + if( da_splits_clone(txn->splits, arc->splits) > 0) + arc->flags |= OF_SPLIT; //Flag that Splits are active + + return arc; + } + + + + static guint32 _sched_date_get_next_post(Archive *arc, guint32 nextdate) { GDate *tmpdate; guint32 nextpostdate = nextdate; - + + DB( g_print("\n[scheduled] _sched_date_get_next_post\n") ); + tmpdate = g_date_new_julian(nextpostdate); switch(arc->unit) { @@@ -164,17 -199,6 +202,6 @@@ nextpostdate = g_date_get_julian(tmpdate); g_date_free(tmpdate); - /* check limit, update and maybe break */ - if(arc->flags & OF_LIMIT) - { - arc->limit--; - if(arc->limit <= 0) - { - arc->flags ^= (OF_LIMIT | OF_AUTO); // invert flags - nextpostdate = 0; - } - } - return nextpostdate; } @@@ -183,7 -207,7 +210,7 @@@ gboolean scheduled_is_postable(Archive { gdouble value; - value = arrondi(arc->amount, 2); + value = hb_amount_round(arc->amount, 2); if( (arc->flags & OF_AUTO) && (arc->kacc > 0) && (value != 0.0) ) return TRUE; @@@ -198,6 -222,9 +225,9 @@@ GDateWeekday wday guint32 finalpostdate; gint shift; + DB( g_print("\n[scheduled] scheduled_get_postdate\n") ); + + finalpostdate = postdate; tmpdate = g_date_new_julian(finalpostdate); @@@ -235,24 -262,58 +265,58 @@@ } + guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate) + { + guint32 curdate = jrefdate - arc->nextdate; + guint32 nblate = 0; + /* + switch(arc->unit) + { + case AUTO_UNIT_DAY: + nbpost = (curdate / arc->every); + g_print("debug d: %d => %f\n", curdate, nbpost); + break; + case AUTO_UNIT_WEEK: + nbpost = (curdate / ( 7 * arc->every)); + g_print("debug w: %d => %f\n", curdate, nbpost); + break; - guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate) - { - guint32 nbpost = 0; - guint32 curdate = arc->nextdate; + case AUTO_UNIT_MONTH: + //approximate is sufficient + nbpost = (curdate / (( 365.2425 / 12) * arc->every)); + g_print("debug m: %d => %f\n", curdate, nbpost); + break; + + case AUTO_UNIT_YEAR: + //approximate is sufficient + nbpost = (curdate / ( 365.2425 * arc->every)); + g_print("debug y: %d => %f\n", curdate, nbpost); + break; + } + + nblate = floor(nbpost); + + if(arc->flags & OF_LIMIT) + nblate = MIN(nblate, arc->limit); + + nblate = MIN(nblate, 11); + */ + + // pre 5.1 way + curdate = arc->nextdate; while(curdate <= jrefdate) { curdate = _sched_date_get_next_post(arc, curdate); - nbpost++; - // break at 11 max (to display +10) - if(nbpost >= 11) + nblate++; + // break if over limit or at 11 max (to display +10) + if(nblate >= arc->limit || nblate >= 11) break; } - return nbpost; + return nblate; } @@@ -260,6 -321,19 +324,19 @@@ guint32 scheduled_date_advance(Archive *arc) { arc->nextdate = _sched_date_get_next_post(arc, arc->nextdate); + + //#1556289 + /* check limit, update and maybe break */ + if(arc->flags & OF_LIMIT) + { + arc->limit--; + if(arc->limit <= 0) + { + arc->flags ^= (OF_LIMIT | OF_AUTO); // invert flags + arc->nextdate = 0; + } + } + return arc->nextdate; } diff --combined src/hb-assign.c index 8303436,93fd2da..951cf92 --- a/src/hb-assign.c +++ b/src/hb-assign.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,9 -20,6 +20,9 @@@ #include "homebank.h" #include "hb-assign.h" +#include "ext.h" +#include "refcount.h" + #define MYDEBUG 0 #if MYDEBUG @@@ -41,12 -38,12 +41,12 @@@ voi da_asg_free(Assign *item) { DB( g_print("da_asg_free\n") ); - if(item != NULL) + if(rc_unref(item)) { - DB( g_print(" => %d, %s\n", item->key, item->name) ); + DB( g_print(" => %d, %s\n", item->key, item->text) ); - g_free(item->name); + g_free(item->text); - g_free(item); + rc_free(item); } } @@@ -55,7 -52,7 +55,7 @@@ Assign da_asg_malloc(void) { DB( g_print("da_asg_malloc\n") ); - return g_malloc0(sizeof(Assign)); + return rc_alloc(sizeof(Assign)); } @@@ -83,9 -80,9 +83,9 @@@ static void da_asg_max_key_ghfunc(gpoin static gboolean da_asg_name_grfunc(gpointer key, Assign *item, gchar *name) { - if( name && item->name ) + if( name && item->text ) { - if(!strcasecmp(name, item->name)) + if(!strcasecmp(name, item->text)) return TRUE; } return FALSE; @@@ -105,9 -102,9 +105,9 @@@ da_asg_length(void /** * da_asg_remove: * - * remove an rul from the GHashTable + * delete an rul from the GHashTable * - * Return value: TRUE if the key was found and removed + * Return value: TRUE if the key was found and deleted * */ gboolean @@@ -157,12 -154,12 +157,12 @@@ guint32 *new_key DB( g_print("da_asg_append\n") ); - DB( g_print(" -> try append: %s\n", item->name) ); + DB( g_print(" -> try append: %s\n", item->text) ); - if( item->name != NULL ) + if( item->text != NULL ) { /* ensure no duplicate */ - existitem = da_asg_get_by_name( item->name ); + existitem = da_asg_get_by_name( item->text ); if( existitem == NULL ) { new_key = g_new0(guint32, 1); @@@ -176,7 -173,7 +176,7 @@@ } } - DB( g_print(" -> %s already exist: %d\n", item->name, item->key) ); + DB( g_print(" -> %s already exist: %d\n", item->text, item->key) ); return FALSE; } @@@ -266,7 -263,7 +266,7 @@@ da_asg_debug_list_ghfunc(gpointer key, guint32 *id = key; Assign *item = value; - DB( g_print(" %d :: %s\n", *id, item->name) ); + DB( g_print(" %d :: %s\n", *id, item->text) ); } diff --combined src/hb-category.c index 3dad28b,ce14b3c..781598a --- a/src/hb-category.c +++ b/src/hb-category.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,9 -20,6 +20,9 @@@ #include "homebank.h" #include "hb-category.h" +#include "ext.h" +#include "refcount.h" + /****************************************************************************/ /* Debug macros */ @@@ -43,7 -40,7 +43,7 @@@ extern struct HomeBank *GLOBALS Category * da_cat_clone(Category *src_item) { -Category *new_item = g_memdup(src_item, sizeof(Category)); +Category *new_item = rc_dup(src_item, sizeof(Category)); DB( g_print("da_cat_clone\n") ); if(new_item) @@@ -59,12 -56,12 +59,12 @@@ voi da_cat_free(Category *item) { DB( g_print("da_cat_free\n") ); - if(item != NULL) + if(rc_unref(item)) { DB( g_print(" => %d, %s\n", item->key, item->name) ); g_free(item->name); - g_free(item); + rc_free(item); } } @@@ -73,7 -70,7 +73,7 @@@ Category da_cat_malloc(void) { DB( g_print("da_cat_malloc\n") ); - return g_malloc0(sizeof(Category)); + return rc_alloc(sizeof(Category)); } @@@ -120,7 -117,7 +120,7 @@@ da_cat_length(void * * GRFunc to get the max id * - * Return value: TRUE if the key/value must be removed + * Return value: TRUE if the key/value must be deleted * */ static gboolean @@@ -136,9 -133,9 +136,9 @@@ da_cat_remove_grfunc(gpointer key, Cate /** * da_cat_remove: * - * remove a category from the GHashTable + * delete a category from the GHashTable * - * Return value: TRUE if the key was found and removed + * Return value: TRUE if the key was found and deleted * */ guint @@@ -259,7 -256,7 +259,7 @@@ da_cat_get_fullname(Category *cat { Category *parent; - if( cat->parent == 0) + if( cat->parent == 0 ) return g_strdup(cat->name); else { @@@ -539,12 -536,30 +539,30 @@@ void da_cat_consistency(Category *item { gboolean isIncome; + if((item->flags & GF_SUB) && item->key > 0) + { + //check for existing parent + if( da_cat_get(item->parent) == NULL ) + { + Category *parent = da_cat_append_ifnew_by_fullname ("orphaned", FALSE); + + item->parent = parent->key; + + g_warning("category consistency: fixed missing parent %d", item->parent); + } + } + // ensure type equal for categories and its children if(!(item->flags & GF_SUB) && item->key > 0) { isIncome = (item->flags & GF_INCOME) ? TRUE : FALSE; - category_change_type(item, isIncome); + if( category_change_type(item, isIncome) > 0 ) + { + g_warning("category consistency: fixed type for child"); + GLOBALS->changes_count++; + } } + g_strstrip(item->name); } @@@ -582,88 -597,181 +600,181 @@@ da_cat_debug_list(void /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - gboolean - category_is_used(guint32 key) + guint32 category_report_id(guint32 key, gboolean subcat) { - GList *lrul, *list; - guint i, nbsplit; + Category *catentry = da_cat_get(key); + guint32 retval = 0; - list = g_list_first(GLOBALS->ope_list); + if(catentry) + { + if(subcat == FALSE) + { + retval = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key; + } + else + { + retval = catentry->key; + } + } + return retval; + } + + + void + category_delete_unused(void) + { + GList *lcat, *list; + + lcat = list = g_hash_table_get_values(GLOBALS->h_cat); while (list != NULL) { - Transaction *entry = list->data; - if( key == entry->kcat ) - return TRUE; + Category *entry = list->data; + + if(entry->usage_count <= 0 && entry->key > 0) + da_cat_remove (entry->key); + + list = g_list_next(list); + } + g_list_free(lcat); + } + + + static void + category_fill_usage_count(guint32 kcat) + { + Category *cat = da_cat_get (kcat); + Category *parent; - // check split category #1340142 - nbsplit = da_transaction_splits_count(entry); - for(i=0;iusage_count++; + if( cat->parent > 0 ) { - Split *split = entry->splits[i]; + parent = da_cat_get(cat->parent); + if( parent ) + { + parent->usage_count++; + } + } + } + } + + + void + category_fill_usage(void) + { + GList *lcat; + GList *lst_acc, *lnk_acc; + GList *lnk_txn; + GList *lpay, *lrul, *list; - if( key == split->kcat ) - return TRUE; + lcat = list = g_hash_table_get_values(GLOBALS->h_cat); + while (list != NULL) + { + Category *entry = list->data; + entry->usage_count = 0; + list = g_list_next(list); + } + g_list_free(lcat); + + + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) + { + Transaction *txn = lnk_txn->data; + + category_fill_usage_count(txn->kcat); + lnk_txn = g_list_next(lnk_txn); } + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); + + lpay = list = g_hash_table_get_values(GLOBALS->h_pay); + while (list != NULL) + { + Payee *entry = list->data; + category_fill_usage_count(entry->kcat); list = g_list_next(list); } + g_list_free(lpay); + list = g_list_first(GLOBALS->arc_list); while (list != NULL) { Archive *entry = list->data; - if( key == entry->kcat ) - return TRUE; + + category_fill_usage_count(entry->kcat); list = g_list_next(list); } - //todo: add budget use here - + lrul = list = g_hash_table_get_values(GLOBALS->h_rul); while (list != NULL) { Assign *entry = list->data; - if( key == entry->kcat) - return TRUE; + category_fill_usage_count(entry->kcat); list = g_list_next(list); } g_list_free(lrul); - return FALSE; } + void category_move(guint32 key1, guint32 key2) { + GList *lst_acc, *lnk_acc; + GList *lnk_txn; GList *lrul, *list; guint i, nbsplit; - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - Transaction *entry = list->data; - if(entry->kcat == key1) - { - entry->kcat = key2; - entry->flags |= OF_CHANGED; - } + Account *acc = lnk_acc->data; - // move split category #1340142 - nbsplit = da_transaction_splits_count(entry); - for(i=0;itxn_queue); + while (lnk_txn != NULL) { - Split *split = entry->splits[i]; + Transaction *txn = lnk_txn->data; + + if(txn->kcat == key1) + { + txn->kcat = key2; + txn->flags |= OF_CHANGED; + } - if( split->kcat == key1 ) + // move split category #1340142 + nbsplit = da_splits_count(txn->splits); + for(i=0;ikcat = key2; - entry->flags |= OF_CHANGED; + Split *split = txn->splits[i]; + + if( split->kcat == key1 ) + { + split->kcat = key2; + txn->flags |= OF_CHANGED; + } } - } - list = g_list_next(list); + lnk_txn = g_list_next(lnk_txn); + } + + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); + list = g_list_first(GLOBALS->arc_list); while (list != NULL) @@@ -868,7 -976,7 +979,7 @@@ const gchar *encoding if( g_strv_length (str_array) != 3 ) { - *error = _("invalid csv format"); + *error = _("invalid CSV format"); retval = FALSE; DB( g_print(" + error %s\n", *error) ); } @@@ -984,13 -1092,31 +1095,31 @@@ GList *lcat, *list return retval; } + gint category_type_get(Category *item) + { + if( (item->flags & (GF_INCOME)) ) + return 1; + return -1; + } + + + + static gint category_change_type_eval(Category *item, gboolean isIncome) + { + if( (item->flags & (GF_INCOME)) && !isIncome ) + return 1; + return 0; + } + gint category_change_type(Category *item, gboolean isIncome) { - gint changes = 1; + gint changes = 0; GList *lcat, *list; - item->flags &= ~(GF_INCOME); //remove flag + changes += category_change_type_eval(item, isIncome); + + item->flags &= ~(GF_INCOME); //delete flag if(isIncome == TRUE) item->flags |= GF_INCOME; @@@ -1002,10 -1128,10 +1131,10 @@@ if(child->parent == item->key) { - child->flags &= ~(GF_INCOME); //remove flag + changes += category_change_type_eval(child, isIncome); + child->flags &= ~(GF_INCOME); //delete flag if(isIncome == TRUE) child->flags |= GF_INCOME; - changes++; } list = g_list_next(list); } diff --combined src/hb-payee.c index 6a51cc7,5992a4d..419bdea --- a/src/hb-payee.c +++ b/src/hb-payee.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,9 -20,6 +20,9 @@@ #include "homebank.h" #include "hb-payee.h" +#include "ext.h" +#include "refcount.h" + /****************************************************************************/ /* Debug macros */ @@@ -44,12 -41,12 +44,12 @@@ voi da_pay_free(Payee *item) { DB( g_print("da_pay_free\n") ); - if(item != NULL) + if(rc_unref(item)) { DB( g_print(" => %d, %s\n", item->key, item->name) ); g_free(item->name); - g_free(item); + rc_free(item); } } @@@ -58,7 -55,7 +58,7 @@@ Payee da_pay_malloc(void) { DB( g_print("da_pay_malloc\n") ); - return g_malloc0(sizeof(Payee)); + return rc_alloc(sizeof(Payee)); } @@@ -140,9 -137,9 +140,9 @@@ guint32 *new_key /** * da_pay_remove: * - * remove an payee from the GHashTable + * delete an payee from the GHashTable * - * Return value: TRUE if the key was found and removed + * Return value: TRUE if the key was found and deleted * */ gboolean @@@ -305,33 -302,75 +305,75 @@@ da_pay_debug_list(void #endif - - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + void + payee_delete_unused(void) + { + GList *lpay, *list; + + lpay = list = g_hash_table_get_values(GLOBALS->h_pay); + while (list != NULL) + { + Payee *entry = list->data; + if(entry->usage_count <= 0 && entry->key > 0) + da_pay_remove (entry->key); + list = g_list_next(list); + } + g_list_free(lpay); + } - gboolean - payee_is_used(guint32 key) + void + payee_fill_usage(void) { + GList *lpay; + GList *lst_acc, *lnk_acc; + GList *lnk_txn; GList *lrul, *list; - list = g_list_first(GLOBALS->ope_list); + lpay = list = g_hash_table_get_values(GLOBALS->h_pay); while (list != NULL) { - Transaction *entry = list->data; - if( key == entry->kpay ) - return TRUE; + Payee *entry = list->data; + entry->usage_count = 0; list = g_list_next(list); } + g_list_free(lpay); + + + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) + { + Transaction *txn = lnk_txn->data; + Payee *pay = da_pay_get (txn->kpay); + + if(pay) + pay->usage_count++; + + lnk_txn = g_list_next(lnk_txn); + } + + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); + list = g_list_first(GLOBALS->arc_list); while (list != NULL) { Archive *entry = list->data; - if( key == entry->kpay ) - return TRUE; + Payee *pay = da_pay_get (entry->kpay); + + if(pay) + pay->usage_count++; list = g_list_next(list); } @@@ -339,33 -378,47 +381,47 @@@ while (list != NULL) { Assign *entry = list->data; + Payee *pay = da_pay_get (entry->kpay); + + if(pay) + pay->usage_count++; - if( key == entry->kpay) - return TRUE; list = g_list_next(list); } g_list_free(lrul); - - return FALSE; } + void payee_move(guint32 key1, guint32 key2) { + GList *lst_acc, *lnk_acc; + GList *lnk_txn; GList *lrul, *list; - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - Transaction *entry = list->data; - if(entry->kpay == key1) + Account *acc = lnk_acc->data; + + lnk_txn = g_queue_peek_head_link(acc->txn_queue); + while (lnk_txn != NULL) { - entry->kpay = key2; - entry->flags |= OF_CHANGED; + Transaction *txn = lnk_txn->data; + + if(txn->kpay == key1) + { + txn->kpay = key2; + txn->flags |= OF_CHANGED; + } + lnk_txn = g_list_next(lnk_txn); } - list = g_list_next(list); + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); + list = g_list_first(GLOBALS->arc_list); while (list != NULL) diff --combined src/hb-preferences.c index e7695bc,5bf8234..d257ca7 --- a/src/hb-preferences.c +++ b/src/hb-preferences.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -17,7 -17,9 +17,9 @@@ * along with this program. If not, see . */ + #include "homebank.h" + #include "hb-preferences.h" #include "hb-filter.h" #include "gtk-chart-colors.h" @@@ -41,7 -43,56 +43,56 @@@ extern struct HomeBank *GLOBALS; extern struct Preferences *PREFS; + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + + static void homebank_pref_init_monetary(void) + { + + DB( g_print("\n[system] get currency code\n") ); + + #ifdef G_OS_UNIX + struct lconv *lc = localeconv(); + + g_stpcpy (PREFS->IntCurrSymbol, lc->int_curr_symbol); + g_strstrip(PREFS->IntCurrSymbol); + + DB( g_print("- stored '%s' from linux system\n", PREFS->IntCurrSymbol) ); + #else + + #ifdef G_OS_WIN32 + #define BUFFER_SIZE 512 + char buffer[BUFFER_SIZE]; + //LPWSTR wcBuffer = buffer; + LPSTR wcBuffer = buffer; + int iResult; + + //https://msdn.microsoft.com/en-us/library/windows/desktop/dd464799%28v=vs.85%29.aspx + + //LOCALE_SINTLSYMBOL + iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SINTLSYMBOL, wcBuffer, BUFFER_SIZE); + if(iResult > 0) + { + DB( g_print("LOCALE_SINTLSYMBOL='%s'\n", buffer) ); + g_stpcpy (PREFS->IntCurrSymbol, buffer); + g_strstrip(PREFS->IntCurrSymbol); + + DB( g_print("- stored '%s' from windows system\n", PREFS->IntCurrSymbol) ); + } + #else + + g_stpcpy (PREFS->IntCurrSymbol, "USD"); + + DB( g_print("- stored '%s' as default\n", PREFS->IntCurrSymbol) ); + + #endif + + #endif + + + } + + /* static void homebank_pref_init_monetary(void) { DB( g_print("\n[preferences] monetary\n") ); @@@ -53,6 -104,8 +104,8 @@@ struct lconv *lc = localeconv() DB( g_print("\n[preferences] monetary unix\n") ); + DB( g_print("int_curr_symbol '%s'\n", lc->int_curr_symbol) ); + DB( g_print("mon_decimal_point is utf8: %d\n", g_utf8_validate(lc->mon_decimal_point, -1, NULL)) ); DB( g_print("mon_decimal_point '%s'\n", lc->mon_decimal_point) ); DB( g_print("mon_decimal_point %x %x %x %x\n", lc->mon_decimal_point[0], lc->mon_decimal_point[1], lc->mon_decimal_point[2], lc->mon_decimal_point[3]) ); @@@ -70,19 -123,18 +123,18 @@@ DB( g_print("n_cs_precedes '%d'\n", lc->n_cs_precedes) ); - /* ok assign */ - + //PREFS->base_cur.iso_code = g_strdup(g_strstrip(lc->int_curr_symbol)); if( lc->p_cs_precedes || lc->n_cs_precedes ) { PREFS->base_cur.symbol = g_strdup(lc->currency_symbol); - PREFS->base_cur.is_prefix = TRUE; + PREFS->base_cur.sym_prefix = TRUE; DB( g_print("locale mon cs is a prefix\n") ); } else { PREFS->base_cur.symbol = g_strdup(lc->currency_symbol); - PREFS->base_cur.is_prefix = FALSE; + PREFS->base_cur.sym_prefix = FALSE; } PREFS->base_cur.decimal_char = g_strdup(lc->mon_decimal_point); @@@ -107,7 -159,7 +159,7 @@@ #else #ifdef G_OS_WIN32 - //todo: to be really set by a win32 specialist from the registry... + #define BUFFER_SIZE 512 char buffer[BUFFER_SIZE]; //LPWSTR wcBuffer = buffer; @@@ -115,6 -167,11 +167,11 @@@ int iResult; gsize toto; + //https://msdn.microsoft.com/en-us/library/windows/desktop/dd464799%28v=vs.85%29.aspx + + //LOCALE_SINTLSYMBOL + + //see g_locale_to_utf8 here iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SCURRENCY, wcBuffer, BUFFER_SIZE); if(iResult > 0) @@@ -123,6 -180,9 +180,9 @@@ PREFS->base_cur.symbol = g_locale_to_utf8(buffer, -1, NULL, &toto, NULL); } + // LOCALE_ICURRENCY + //PREFS->base_cur.sym_prefix = + iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, wcBuffer, BUFFER_SIZE); if(iResult > 0) { @@@ -137,12 -197,14 +197,14 @@@ PREFS->base_cur.grouping_char = g_locale_to_utf8(buffer, -1, NULL, &toto, NULL); } + // LOCALE_ICURRDIGITS PREFS->base_cur.frac_digits = 2; #else - PREFS->base_cur.prefix_symbol = NULL; //g_strdup(""); - PREFS->base_cur.suffix_symbol = NULL; //g_strdup(""); + PREFS->base_cur.iso_code = g_strdup("USD"); + PREFS->base_cur.symbol = NULL; //g_strdup(""); + PREFS->base_cur.sym_prefix = FALSE; PREFS->base_cur.decimal_char = g_strdup("."); PREFS->base_cur.grouping_char = NULL; //g_strdup(""); PREFS->base_cur.frac_digits = 2; @@@ -151,6 -213,7 +213,7 @@@ #endif } + */ @@@ -164,57 -227,6 +227,6 @@@ static void homebank_pref_init_wingeome } - /* - ** create the format string for monetary strfmon (major/minor) - */ - static void _homebank_pref_createformat(void) - { - struct CurrencyFmt *cur; - - DB( g_print("\n[preferences] pref create format\n") ); - - /* - if(PREFS->base_cur.grouping_char != NULL) - g_snprintf(GLOBALS->fmt_maj_number, 15, "%%^.%dn", PREFS->base_cur.frac_digits); - else - g_snprintf(GLOBALS->fmt_maj_number, 15, "%%.%dn", PREFS->base_cur.frac_digits); - - DB( g_print("+ major is: '%s'\n", GLOBALS->fmt_maj_number) ); - - - if(PREFS->minor_cur.grouping_char != NULL) - g_snprintf(GLOBALS->fmt_min_number, 15, "%s %%!^.%dn %s", - PREFS->minor_cur.prefix_symbol, - PREFS->minor_cur.frac_digits, - PREFS->minor_cur.suffix_symbol - ); - else - g_snprintf(GLOBALS->fmt_min_number, 15, "%s %%!.%dn %s", - PREFS->minor_cur.prefix_symbol, - PREFS->minor_cur.frac_digits, - PREFS->minor_cur.suffix_symbol - ); - - DB( g_print("+ minor is: '%s'\n", GLOBALS->fmt_min_number) ); - */ - - /* base mon format */ - cur = &PREFS->base_cur; - g_snprintf(cur->format , 8-1, "%%.%df", cur->frac_digits); - g_snprintf(cur->monfmt, 32-1, (cur->is_prefix) ? "%s %%s" : "%%s %s", cur->symbol); - DB( g_print(" - format: '%s'\n", cur->format) ); - DB( g_print(" - monfmt: '%s'\n", cur->monfmt) ); - - /* minor mon format */ - cur = &PREFS->minor_cur; - g_snprintf(cur->format , 8-1, "%%.%df", cur->frac_digits); - g_snprintf(cur->monfmt, 32-1, (cur->is_prefix) ? "%s %%s" : "%%s %s", cur->symbol); - DB( g_print(" - format: '%s'\n", cur->format) ); - DB( g_print(" - monfmt: '%s'\n", cur->monfmt) ); - - } - - //vehicle_unit_100 //vehicle_unit_distbyvol //=> used for column title @@@ -230,27 -242,30 +242,30 @@@ static void _homebank_pref_init_measure // unit is miles else { - PREFS->vehicle_unit_dist = "%d m."; - PREFS->vehicle_unit_100 = "100 miles"; + PREFS->vehicle_unit_dist = "%d mi."; + PREFS->vehicle_unit_100 = "100 mi."; } // unit is Liters if(!PREFS->vehicle_unit_isgal) { - PREFS->vehicle_unit_vol = "%.2f L"; + //TRANSLATORS: format a liter number with l/L as abbreviation + PREFS->vehicle_unit_vol = _("%.2f l"); if(!PREFS->vehicle_unit_ismile) - PREFS->vehicle_unit_distbyvol = "km/L"; + //TRANSLATORS: kilometer per liter + PREFS->vehicle_unit_distbyvol = _("km/l"); else - PREFS->vehicle_unit_distbyvol = "miles/gal"; + //TRANSLATORS: miles per liter + PREFS->vehicle_unit_distbyvol = _("mi./l"); } // unit is gallon else { - PREFS->vehicle_unit_vol = "%.2f gal"; + PREFS->vehicle_unit_vol = "%.2f gal."; if(!PREFS->vehicle_unit_ismile) - PREFS->vehicle_unit_distbyvol = "km/gal"; + PREFS->vehicle_unit_distbyvol = "km/gal."; else - PREFS->vehicle_unit_distbyvol = "miles/gal"; + PREFS->vehicle_unit_distbyvol = "mi./gal."; } } @@@ -274,17 -289,11 +289,14 @@@ void homebank_pref_free(void g_free(PREFS->language); - g_free(PREFS->base_cur.symbol); - g_free(PREFS->base_cur.decimal_char); - g_free(PREFS->base_cur.grouping_char); g_free(PREFS->minor_cur.symbol); g_free(PREFS->minor_cur.decimal_char); g_free(PREFS->minor_cur.grouping_char); + g_strfreev(PREFS->ext_path); + g_list_free_full(PREFS->ext_whitelist, g_free); + memset(PREFS, 0, sizeof(struct Preferences)); } @@@ -309,16 -318,18 +321,18 @@@ gint i PREFS->showsplash = TRUE; PREFS->loadlast = TRUE; PREFS->appendscheduled = FALSE; + PREFS->do_update_currency = FALSE; PREFS->heritdate = FALSE; PREFS->hidereconciled = FALSE; + PREFS->showremind = TRUE; PREFS->toolbar_style = 4; //text beside icons PREFS->custom_colors = TRUE; PREFS->color_exp = g_strdup(DEFAULT_EXP_COLOR); PREFS->color_inc = g_strdup(DEFAULT_INC_COLOR); PREFS->color_warn = g_strdup(DEFAULT_WARN_COLOR); - PREFS->rules_hint = FALSE; + PREFS->grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE; /* fiscal year */ PREFS->fisc_year_day = 1; @@@ -333,6 -344,8 +347,8 @@@ homebank_pref_init_wingeometry(&PREFS->bud_wg, 0, 0, 800, 494); homebank_pref_init_wingeometry(&PREFS->cst_wg, 0, 0, 800, 494); + homebank_pref_init_wingeometry(&PREFS->txn_wg, 0, 0, -1, -1); + homebank_pref_init_monetary(); PREFS->wal_toolbar = TRUE; @@@ -362,6 -375,7 +378,7 @@@ PREFS->lst_ope_columns[i++] = LST_DSPOPE_PAYEE; PREFS->lst_ope_columns[i++] = LST_DSPOPE_CATEGORY; PREFS->lst_ope_columns[i++] = LST_DSPOPE_TAGS; + PREFS->lst_ope_columns[i++] = LST_DSPOPE_CLR; PREFS->lst_ope_columns[i++] = -LST_DSPOPE_AMOUNT; PREFS->lst_ope_columns[i++] = LST_DSPOPE_EXPENSE; PREFS->lst_ope_columns[i++] = LST_DSPOPE_INCOME; @@@ -371,20 -385,33 +388,33 @@@ PREFS->lst_ope_sort_id = LST_DSPOPE_DATE; PREFS->lst_ope_sort_order = GTK_SORT_ASCENDING; + for( i=0;ilst_ope_col_size[i] = -1; //PREFS->base_cur.nbdecimal = 2; //PREFS->base_cur.separator = TRUE; PREFS->date_range_wal = FLT_RANGE_LASTMONTH; PREFS->date_range_txn = FLT_RANGE_LAST12MONTHS; + PREFS->date_future_nbdays = 0; PREFS->date_range_rep = FLT_RANGE_THISYEAR; + //import/export + PREFS->dtex_nointro = TRUE; + //PREFS->dtex_datefmt + PREFS->dtex_ofxname = 1; + PREFS->dtex_ofxmemo = 2; + PREFS->dtex_qifmemo = TRUE; + PREFS->dtex_qifswap = FALSE; //todo: add intelligence here PREFS->euro_active = FALSE; PREFS->euro_country = 0; PREFS->euro_value = 1.0; + + da_cur_initformat(&PREFS->minor_cur); + //PREFS->euro_nbdec = 2; //PREFS->euro_thsep = TRUE; //PREFS->euro_symbol = g_strdup("??"); @@@ -395,29 -422,11 +425,28 @@@ PREFS->budg_showdetail = FALSE; PREFS->report_color_scheme = CHART_COLMAP_HOMEBANK; - PREFS->chart_legend = FALSE; + //PREFS->chart_legend = FALSE; PREFS->vehicle_unit_ismile = FALSE; PREFS->vehicle_unit_isgal = FALSE; + gchar** plugin_path = g_new0(gchar**, 4); + i = 0; + const gchar* env = g_getenv("HOMEBANK_PLUGINS"); + if (env) { + if (g_path_is_absolute(env)) { + plugin_path[i++] = g_strdup(env); + } else { + gchar* cur = g_get_current_dir(); + plugin_path[i++] = g_build_filename(cur, env, NULL); + g_free(cur); + } + } + plugin_path[i++] = g_build_filename(homebank_app_get_config_dir(), "plugins", NULL); + plugin_path[i++] = g_build_filename(homebank_app_get_pkglib_dir(), "plugins", NULL); + PREFS->ext_path = plugin_path; + PREFS->ext_whitelist = NULL; + - _homebank_pref_createformat(); _homebank_pref_init_measurement_units(); } @@@ -449,6 -458,9 +478,9 @@@ static void homebank_pref_get_wingeomet } } + + + static void homebank_pref_get_boolean( GKeyFile *key_file, const gchar *group_name, @@@ -548,18 -560,18 +580,18 @@@ gchar *string } - static void homebank_pref_currfmt_convert(struct CurrencyFmt *cur, gchar *prefix, gchar *suffix) + static void homebank_pref_currfmt_convert(Currency *cur, gchar *prefix, gchar *suffix) { if( (prefix != NULL) && (strlen(prefix) > 0) ) { cur->symbol = g_strdup(prefix); - cur->is_prefix = TRUE; + cur->sym_prefix = TRUE; } else if( (suffix != NULL) ) { cur->symbol = g_strdup(suffix); - cur->is_prefix = FALSE; + cur->sym_prefix = FALSE; } } @@@ -632,7 -644,16 +664,16 @@@ GError *error = NULL homebank_pref_get_string(keyfile, group, "ColorInc" , &PREFS->color_inc); homebank_pref_get_string(keyfile, group, "ColorWarn", &PREFS->color_warn); - homebank_pref_get_boolean(keyfile, group, "RulesHint", &PREFS->rules_hint); + if( version <= 500 ) + { + gboolean rules_hint; + homebank_pref_get_boolean(keyfile, group, "RulesHint", &rules_hint); + if( rules_hint == TRUE ) + PREFS->grid_lines = GTK_TREE_VIEW_GRID_LINES_HORIZONTAL; + + } + else + homebank_pref_get_short(keyfile, group, "GridLines", &PREFS->grid_lines); } DB( g_print(" - color exp: %s\n", PREFS->color_exp) ); @@@ -647,14 -668,16 +688,16 @@@ homebank_pref_get_boolean(keyfile, group, "ShowSplash", &PREFS->showsplash); homebank_pref_get_boolean(keyfile, group, "LoadLast", &PREFS->loadlast); homebank_pref_get_boolean(keyfile, group, "AppendScheduled", &PREFS->appendscheduled); + homebank_pref_get_boolean(keyfile, group, "UpdateCurrency", &PREFS->do_update_currency); homebank_pref_get_boolean(keyfile, group, "HeritDate", &PREFS->heritdate); homebank_pref_get_boolean(keyfile, group, "HideReconciled", &PREFS->hidereconciled); + homebank_pref_get_boolean(keyfile, group, "ShowRemind", &PREFS->showremind); if( g_key_file_has_key(keyfile, group, "ColumnsOpe", NULL) ) { gboolean *bsrc; - gint *src, i; + gint *src, i, j; gsize length; if(version <= 2) //retrieve old 0.1 or 0.2 visibility boolean @@@ -690,10 -713,33 +733,33 @@@ DB( g_print(" - upgrade from v7\n") ); DB( g_print(" - copying column order from pref file\n") ); memcpy(PREFS->lst_ope_columns, src, length*sizeof(gint)); + //append balance column PREFS->lst_ope_columns[10] = LST_DSPOPE_BALANCE; } } + if(version < 500) + { + if( length == NUM_LST_DSPOPE-2 ) //1 less column before v4.5.1 + { + DB( g_print(" - upgrade prior v5.0\n") ); + DB( g_print(" - copying column order from pref file\n") ); + gboolean added = FALSE; + for(i=0,j=0; ilst_ope_columns[j++] = LST_DSPOPE_CLR; + added = TRUE; + } + PREFS->lst_ope_columns[j++] = src[i]; + } + } + } + } g_free(src); @@@ -701,6 -747,22 +767,22 @@@ } + if( g_key_file_has_key(keyfile, group, "ColumnsOpeWidth", NULL) ) + { + gint *src; + gsize length; + + src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpeWidth", &length, &error); + + DB( g_print(" - length %d (max=%d)\n", length, NUM_LST_DSPOPE) ); + + if( length == NUM_LST_DSPOPE-1 ) + { + DB( g_print(" - copying column width from pref file\n") ); + memcpy(PREFS->lst_ope_col_size, src, length*sizeof(gint)); + } + } + homebank_pref_get_integer(keyfile, group, "OpeSortId", &PREFS->lst_ope_sort_id); homebank_pref_get_integer(keyfile, group, "OpeSortOrder", &PREFS->lst_ope_sort_order); @@@ -721,10 -783,14 +803,14 @@@ homebank_pref_get_wingeometry(keyfile, group, "Ove", &PREFS->ove_wg); homebank_pref_get_wingeometry(keyfile, group, "Bud", &PREFS->bud_wg); homebank_pref_get_wingeometry(keyfile, group, "Car", &PREFS->cst_wg); + + homebank_pref_get_wingeometry(keyfile, group, "Txn", &PREFS->txn_wg); + if(version <= 7) //set maximize to 0 { PREFS->wal_wg.s = 0; PREFS->acc_wg.s = 0; + PREFS->txn_wg.s = 0; PREFS->sta_wg.s = 0; PREFS->tme_wg.s = 0; PREFS->ove_wg.s = 0; @@@ -744,39 -810,6 +830,6 @@@ homebank_pref_get_string(keyfile, group, "DateFmt", &PREFS->date_format); - if(version <= 1) - { - //retrieve old 0.1 preferences - homebank_pref_get_short(keyfile, group, "NumNbDec", &PREFS->base_cur.frac_digits); - //PREFS->base_cur.separator = g_key_file_get_boolean (keyfile, group, "NumSep", NULL); - } - else - { - if(version < 460) - { - gchar *prefix = NULL; - gchar *suffix = NULL; - - homebank_pref_get_string(keyfile, group, "PreSymbol", &prefix); - homebank_pref_get_string(keyfile, group, "SufSymbol", &suffix); - homebank_pref_currfmt_convert(&PREFS->base_cur, prefix, suffix); - g_free(prefix); - g_free(suffix); - } - else - { - homebank_pref_get_string(keyfile, group, "Symbol", &PREFS->base_cur.symbol); - homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->base_cur.is_prefix); - } - homebank_pref_get_string(keyfile, group, "DecChar" , &PREFS->base_cur.decimal_char); - homebank_pref_get_string(keyfile, group, "GroupChar", &PREFS->base_cur.grouping_char); - homebank_pref_get_short(keyfile, group, "FracDigits", &PREFS->base_cur.frac_digits); - - //fix 378992/421228 - if( PREFS->base_cur.frac_digits > MAX_FRAC_DIGIT ) - PREFS->base_cur.frac_digits = MAX_FRAC_DIGIT; - } - if(version < 460) { gboolean useimperial; @@@ -799,6 -832,7 +852,7 @@@ homebank_pref_get_integer(keyfile, group, "DateRangeWal", &PREFS->date_range_wal); homebank_pref_get_integer(keyfile, group, "DateRangeTxn", &PREFS->date_range_txn); + homebank_pref_get_integer(keyfile, group, "DateFutureNbDays", &PREFS->date_future_nbdays); homebank_pref_get_integer(keyfile, group, "DateRangeRep", &PREFS->date_range_rep); if(version <= 7) @@@ -850,7 -884,7 +904,7 @@@ else { homebank_pref_get_string(keyfile, group, "Symbol", &PREFS->minor_cur.symbol); - homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->minor_cur.is_prefix); + homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->minor_cur.sym_prefix); } homebank_pref_get_string(keyfile, group, "DecChar" , &PREFS->minor_cur.decimal_char); homebank_pref_get_string(keyfile, group, "GroupChar", &PREFS->minor_cur.grouping_char); @@@ -860,6 -894,7 +914,7 @@@ if( PREFS->minor_cur.frac_digits > MAX_FRAC_DIGIT ) PREFS->minor_cur.frac_digits = MAX_FRAC_DIGIT; + da_cur_initformat(&PREFS->minor_cur); } //PREFS->euro_symbol = g_locale_to_utf8(tmpstr, -1, NULL, NULL, NULL); @@@ -878,35 -913,18 +933,39 @@@ DB( g_print(" -> ** Exchange\n") ); + //homebank_pref_get_boolean(keyfile, group, "DoIntro", &PREFS->dtex_nointro); homebank_pref_get_integer(keyfile, group, "DateFmt", &PREFS->dtex_datefmt); + homebank_pref_get_integer(keyfile, group, "OfxName", &PREFS->dtex_ofxname); homebank_pref_get_integer(keyfile, group, "OfxMemo", &PREFS->dtex_ofxmemo); + homebank_pref_get_boolean(keyfile, group, "QifMemo", &PREFS->dtex_qifmemo); + homebank_pref_get_boolean(keyfile, group, "QifSwap", &PREFS->dtex_qifswap); //group = "Chart"; //PREFS->chart_legend = g_key_file_get_boolean (keyfile, group, "Legend", NULL); + group = "Plugins"; + { + DB( g_print(" -> ** Plugins\n") ); + + gchar** strv = g_key_file_get_string_list(keyfile, group, "Path", NULL, NULL); + if (strv) { + g_strfreev(PREFS->ext_path); + PREFS->ext_path = strv; + } + + strv = g_key_file_get_string_list(keyfile, group, "Whitelist", NULL, NULL); + if (strv) { + gchar** it; + for (it = strv; it && *it; ++it) { + PREFS->ext_whitelist = g_list_append(PREFS->ext_whitelist, g_strdup(*it)); + } + g_strfreev(strv); + } + } + + /* #if MYDEBUG == 1 gsize length; @@@ -920,7 -938,6 +979,6 @@@ g_free(filename); g_key_file_free (keyfile); - _homebank_pref_createformat(); _homebank_pref_init_measurement_units(); } @@@ -976,8 -993,7 +1034,7 @@@ gsize length g_key_file_set_string (keyfile, group, "ColorInc" , PREFS->color_inc); g_key_file_set_string (keyfile, group, "ColorWarn", PREFS->color_warn); - g_key_file_set_boolean (keyfile, group, "RulesHint", PREFS->rules_hint); - + g_key_file_set_integer (keyfile, group, "GridLines", PREFS->grid_lines); homebank_pref_set_string (keyfile, group, "WalletPath" , PREFS->path_hbfile); homebank_pref_set_string (keyfile, group, "ImportPath" , PREFS->path_import); @@@ -987,11 -1003,14 +1044,14 @@@ g_key_file_set_boolean (keyfile, group, "ShowSplash", PREFS->showsplash); g_key_file_set_boolean (keyfile, group, "LoadLast", PREFS->loadlast); g_key_file_set_boolean (keyfile, group, "AppendScheduled", PREFS->appendscheduled); + g_key_file_set_boolean (keyfile, group, "UpdateCurrency", PREFS->do_update_currency); g_key_file_set_boolean (keyfile, group, "HeritDate", PREFS->heritdate); g_key_file_set_boolean (keyfile, group, "HideReconciled", PREFS->hidereconciled); + g_key_file_set_boolean (keyfile, group, "ShowRemind", PREFS->showremind); g_key_file_set_integer_list(keyfile, group, "ColumnsOpe", PREFS->lst_ope_columns, NUM_LST_DSPOPE-1); + g_key_file_set_integer_list(keyfile, group, "ColumnsOpeWidth", PREFS->lst_ope_col_size, NUM_LST_DSPOPE-1); g_key_file_set_integer (keyfile, group, "OpeSortId" , PREFS->lst_ope_sort_id); g_key_file_set_integer (keyfile, group, "OpeSortOrder" , PREFS->lst_ope_sort_order); @@@ -1010,6 -1029,8 +1070,8 @@@ g_key_file_set_integer_list(keyfile, group, "Bud", (gint *)&PREFS->bud_wg, 5); g_key_file_set_integer_list(keyfile, group, "Car", (gint *)&PREFS->cst_wg, 5); + g_key_file_set_integer_list(keyfile, group, "Txn", (gint *)&PREFS->txn_wg, 5); + g_key_file_set_integer (keyfile, group, "WalVPaned" , PREFS->wal_vpaned); g_key_file_set_integer (keyfile, group, "WalHPaned" , PREFS->wal_hpaned); g_key_file_set_boolean (keyfile, group, "WalToolbar", PREFS->wal_toolbar); @@@ -1022,12 -1043,6 +1084,6 @@@ group = "Format"; homebank_pref_set_string (keyfile, group, "DateFmt" , PREFS->date_format); - homebank_pref_set_string (keyfile, group, "Symbol" , PREFS->base_cur.symbol); - g_key_file_set_boolean (keyfile, group, "IsPrefix" , PREFS->base_cur.is_prefix); - homebank_pref_set_string (keyfile, group, "DecChar" , PREFS->base_cur.decimal_char); - homebank_pref_set_string (keyfile, group, "GroupChar" , PREFS->base_cur.grouping_char); - g_key_file_set_integer (keyfile, group, "FracDigits", PREFS->base_cur.frac_digits); - //g_key_file_set_boolean (keyfile, group, "UKUnits" , PREFS->imperial_unit); g_key_file_set_boolean (keyfile, group, "UnitIsMile" , PREFS->vehicle_unit_ismile); g_key_file_set_boolean (keyfile, group, "UnitIsGal" , PREFS->vehicle_unit_isgal); @@@ -1038,6 -1053,7 +1094,7 @@@ group = "Filter"; g_key_file_set_integer (keyfile, group, "DateRangeWal", PREFS->date_range_wal); g_key_file_set_integer (keyfile, group, "DateRangeTxn", PREFS->date_range_txn); + g_key_file_set_integer (keyfile, group, "DateFutureNbdays", PREFS->date_future_nbdays); g_key_file_set_integer (keyfile, group, "DateRangeRep", PREFS->date_range_rep); DB( g_print(" -> ** euro\n") ); @@@ -1055,7 -1071,7 +1112,7 @@@ g_ascii_dtostr(ratestr, 63, PREFS->euro_value); homebank_pref_set_string (keyfile, group, "ChangeRate", ratestr); homebank_pref_set_string (keyfile, group, "Symbol" , PREFS->minor_cur.symbol); - g_key_file_set_boolean (keyfile, group, "IsPrefix" , PREFS->minor_cur.is_prefix); + g_key_file_set_boolean (keyfile, group, "IsPrefix" , PREFS->minor_cur.sym_prefix); homebank_pref_set_string (keyfile, group, "DecChar" , PREFS->minor_cur.decimal_char); homebank_pref_set_string (keyfile, group, "GroupChar" , PREFS->minor_cur.grouping_char); g_key_file_set_integer (keyfile, group, "FracDigits", PREFS->minor_cur.frac_digits); @@@ -1073,27 -1089,17 +1130,32 @@@ group = "Exchange"; + //g_key_file_set_boolean (keyfile, group, "DoIntro", PREFS->dtex_nointro); g_key_file_set_integer (keyfile, group, "DateFmt", PREFS->dtex_datefmt); + g_key_file_set_integer (keyfile, group, "OfxName", PREFS->dtex_ofxname); g_key_file_set_integer (keyfile, group, "OfxMemo", PREFS->dtex_ofxmemo); + g_key_file_set_boolean (keyfile, group, "QifMemo", PREFS->dtex_qifmemo); + g_key_file_set_boolean (keyfile, group, "QifSwap", PREFS->dtex_qifswap); + //group = "Chart"; //g_key_file_set_boolean (keyfile, group, "Legend", PREFS->chart_legend); + group = "Plugins"; + { + g_key_file_set_string_list(keyfile, group, "Path", (const gchar* const*)PREFS->ext_path, g_strv_length(PREFS->ext_path)); + + gsize len = g_list_length(PREFS->ext_whitelist); + gchar** strv = g_new0(gchar*, len + 1); + guint i; + + for (i = 0; i < len; ++i) { + strv[i] = g_list_nth_data(PREFS->ext_whitelist, i); + } + g_key_file_set_string_list(keyfile, group, "Whitelist", (const gchar* const*)strv, len); + g_free(strv); + } + //g_key_file_set_string (keyfile, group, "", PREFS->); //g_key_file_set_boolean (keyfile, group, "", PREFS->); //g_key_file_set_integer (keyfile, group, "", PREFS->); @@@ -1124,7 -1130,6 +1186,6 @@@ g_key_file_free (keyfile); } - _homebank_pref_createformat(); _homebank_pref_init_measurement_units(); return retval; diff --combined src/hb-preferences.h index ae8d259,a9ac1e7..4b1cc72 --- a/src/hb-preferences.h +++ b/src/hb-preferences.h @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,6 -20,8 +20,8 @@@ #ifndef __HB_PREFERENCES_H__ #define __HB_PREFERENCES_H__ + #include "hb-currency.h" + #define DEFAULT_FORMAT_DATE "%x" #define MAX_FRAC_DIGIT 6 @@@ -42,18 -44,6 +44,6 @@@ /* ** Preference datas */ - struct CurrencyFmt - { - //gchar *prefix_symbol; /* max symbol is 3 digits in unicode */ - //gchar *suffix_symbol; /* but mostly is 1 digit, and most are prefix ~100 */ - gchar *symbol; - gboolean is_prefix; - gchar *decimal_char; - gchar *grouping_char; - gshort frac_digits; - gchar format[8]; /* hold decimal format: '%.xf' */ - gchar monfmt[32]; /* hold monetary format: 'prefix %s suffix' */ - }; struct WinGeometry { @@@ -67,82 -57,67 +57,67 @@@ struct Preference gboolean showsplash; gboolean loadlast; gboolean appendscheduled; - - gchar *language; - - gchar *path_hbfile; - gchar *path_import; - gchar *path_export; - - gboolean heritdate; - gboolean hidereconciled; - gint date_range_wal; - gint date_range_txn; - gint date_range_rep; - + gboolean do_update_currency; gshort fisc_year_day; gshort fisc_year_month; - + gint date_range_wal; + gchar *path_hbfile; + //interface + gchar *language; gshort toolbar_style; + //gboolean rules_hint; + gshort grid_lines; gboolean custom_colors; gchar *color_exp; gchar *color_inc; gchar *color_warn; - gboolean rules_hint; + + //transactions + gint date_range_txn; + gint date_future_nbdays; + gboolean hidereconciled; + gboolean showremind; + gboolean heritdate; + gint lst_ope_columns[NUM_LST_DSPOPE+1]; + gint lst_ope_col_size[NUM_LST_DSPOPE+1]; + gint lst_ope_sort_id; // -- implicit -- + gint lst_ope_sort_order; // -- implicit -- //display format gchar *date_format; + gchar IntCurrSymbol[8]; + gboolean vehicle_unit_ismile; // true if unit is mile, default Km + gboolean vehicle_unit_isgal; // true if unit is gallon, default Liter - struct CurrencyFmt base_cur; - - //gshort num_nbdecimal; - //gboolean num_separator; - //gboolean imperial_unit; - - //help system - //gboolean show_tooltips; - //gboolean show_help_button; - //gboolean show_tipofday; - //gchar *path_navigator; - - //currency - //gchar *curr_default; - - //euro zone - gboolean euro_active; - gint euro_country; - gdouble euro_value; - - struct CurrencyFmt minor_cur; - - //gshort euro_nbdec; - //gboolean euro_thsep; - //gchar *euro_symbol; + //data exchange options + gboolean dtex_nointro; + gint dtex_datefmt; + gint dtex_ofxname; + gint dtex_ofxmemo; + gboolean dtex_qifmemo; + gboolean dtex_qifswap; + gchar *path_import; + gchar *path_export; //report options + gint date_range_rep; + gint report_color_scheme; gboolean stat_byamount; gboolean stat_showrate; gboolean stat_showdetail; gboolean budg_showdetail; - gint report_color_scheme; - //data exchange options - gint dtex_ofxmemo; - gint dtex_datefmt; + //euro zone + gboolean euro_active; + gint euro_country; + gdouble euro_value; + Currency minor_cur; //chart options - gboolean chart_legend; - - - - /* internal : not saved*/ - - gint lst_ope_columns[NUM_LST_DSPOPE+1]; - gint lst_ope_sort_id; - gint lst_ope_sort_order; + //gboolean chart_legend; - /* windows size an position */ + /* windows/dialogs size an position */ struct WinGeometry wal_wg; struct WinGeometry acc_wg; struct WinGeometry sta_wg; @@@ -151,6 -126,8 +126,8 @@@ struct WinGeometry bud_wg; struct WinGeometry cst_wg; + struct WinGeometry txn_wg; + gboolean wal_toolbar; gboolean wal_spending; gboolean wal_upcoming; @@@ -159,18 -136,12 +136,16 @@@ gint wal_hpaned; //vehiclecost units (mile/gal or km/liters) - gboolean vehicle_unit_ismile; // true is unit is mile, default Km - gboolean vehicle_unit_isgal; // true is unit is gallon, default Liter gchar *vehicle_unit_dist; gchar *vehicle_unit_vol; gchar *vehicle_unit_100; gchar *vehicle_unit_distbyvol; + // plugins + gchar** ext_path; + GList* ext_whitelist; + }; diff --combined src/hb-tag.c index c8353a4,bf4ba69..42412c9 --- a/src/hb-tag.c +++ b/src/hb-tag.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -20,9 -20,6 +20,9 @@@ #include "homebank.h" #include "hb-tag.h" +#include "ext.h" +#include "refcount.h" + #define MYDEBUG 0 #if MYDEBUG @@@ -40,12 -37,12 +40,12 @@@ extern struct HomeBank *GLOBALS void da_tag_free(Tag *item) { DB( g_print("da_tag_free\n") ); - if(item != NULL) + if(rc_unref(item)) { DB( g_print(" => %d, %s\n", item->key, item->name) ); g_free(item->name); - g_free(item); + rc_free(item); } } @@@ -53,7 -50,7 +53,7 @@@ Tag *da_tag_malloc(void) { DB( g_print("da_tag_malloc\n") ); - return g_malloc0(sizeof(Tag)); + return rc_alloc(sizeof(Tag)); } @@@ -100,9 -97,9 +100,9 @@@ guint da_tag_length(void /** * da_tag_remove: * - * remove an tag from the GHashTable + * delete an tag from the GHashTable * - * Return value: TRUE if the key was found and removed + * Return value: TRUE if the key was found and deleted * */ gboolean da_tag_remove(guint32 key) diff --combined src/hb-transaction.c index 1d66998,2758da6..17fbad5 --- a/src/hb-transaction.c +++ b/src/hb-transaction.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -21,12 -21,10 +21,13 @@@ #include "hb-transaction.h" #include "hb-tag.h" + #include "hb-split.h" +#include "ext.h" +#include "refcount.h" + /****************************************************************************/ - /* Debug macros */ + /* Debug macros */ /****************************************************************************/ #define MYDEBUG 0 @@@ -41,131 -39,6 +42,6 @@@ extern struct HomeBank *GLOBALS extern struct Preferences *PREFS; - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - - - static void da_split_free(Split *item) - { - if(item != NULL) - { - if(item->memo != NULL) - g_free(item->memo); - - g_free(item); - } - } - - - static Split *da_split_malloc(void) - { - return g_malloc0(sizeof(Split)); - } - - - Split *da_split_new(guint32 kcat, gdouble amount, gchar *memo) - { - Split *split = da_split_malloc(); - - split->kcat = kcat; - split->amount = amount; - split->memo = g_strdup(memo); - return split; - } - - - - static Split *da_split_clone(Split *src_split) - { - Split *new_split = g_memdup(src_split, sizeof(Split)); - - DB( g_print("da_split_clone\n") ); - - if(new_split) - { - //duplicate the string - new_split->memo = g_strdup(src_split->memo); - DB( g_print(" clone %p -> %p\n", src_split, new_split) ); - - } - return new_split; - } - - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - - - guint da_transaction_splits_count(Transaction *txn) - { - guint i, count = 0; - - for(i=0;isplits[i] == NULL) - break; - count++; - } - return count; - } - - - void da_transaction_splits_free(Transaction *txn) - { - guint count, i=0; - - count = da_transaction_splits_count(txn); - if(count == 0) - return; - - DB( g_print("da_transaction_splits_free\n") ); - - for(;i<=count;i++) - { - DB( g_print("- freeing %d :: %p\n", i, txn->splits[i]) ); - - da_split_free(txn->splits[i]); - txn->splits[i] = NULL; - } - //remove the flag - txn->flags &= ~(OF_SPLIT); - - } - - - void da_transaction_splits_append(Transaction *txn, Split *split) - { - guint count = da_transaction_splits_count(txn); - - DB( g_print("da_transaction_splits_append\n") ); - - DB( g_print("- split[%d] at %p for ope %p\n", count, split, txn) ); - - txn->flags |= OF_SPLIT; - txn->splits[count] = split; - txn->splits[count + 1] = NULL; - - DB( g_print("- %d splits\n", da_transaction_splits_count(txn)) ); - } - - - void da_transaction_splits_clone(Transaction *stxn, Transaction *dtxn) - { - gint i, count; - - DB( g_print("da_transaction_splits_clone\n") ); - - count = da_transaction_splits_count(stxn); - for(i=0;isplits[i] = da_split_clone(stxn->splits[i]); - } - - if(count > 0) - dtxn->flags |= OF_SPLIT; - - DB( g_print(" clone %p -> %p, %d splits\n", stxn, dtxn, count) ); - } - - - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ void @@@ -190,7 -63,8 +66,8 @@@ da_transaction_clean(Transaction *item item->tags = NULL; } - da_transaction_splits_free(item); + da_splits_free(item->splits); + item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared if(item->same != NULL) { @@@ -205,10 -79,10 +82,10 @@@ void da_transaction_free(Transaction *item) { - if(item != NULL) + if(rc_unref(item)) { da_transaction_clean(item); - g_free(item); + rc_free(item); } } @@@ -216,14 -90,12 +93,12 @@@ Transaction * da_transaction_malloc(void) { - return g_malloc0(sizeof(Transaction)); + return rc_alloc(sizeof(Transaction)); } Transaction *da_transaction_copy(Transaction *src_txn, Transaction *dst_txn) { - guint count; - DB( g_print("da_transaction_copy\n") ); da_transaction_clean (dst_txn); @@@ -235,12 -107,10 +110,10 @@@ dst_txn->info = g_strdup(src_txn->info); //duplicate tags - dst_txn->tags = NULL; - count = transaction_tags_count(src_txn); - if(count > 0) - dst_txn->tags = g_memdup(src_txn->tags, count*sizeof(guint32)); + transaction_tags_clone(src_txn, dst_txn); - da_transaction_splits_clone(src_txn, dst_txn); + if (da_splits_clone(src_txn->splits, dst_txn->splits) > 0) + dst_txn->flags |= OF_SPLIT; //Flag that Splits are active return dst_txn; } @@@ -249,15 -119,20 +122,20 @@@ Transaction *da_transaction_init_from_template(Transaction *txn, Archive *arc) { //txn->date = 0; - txn->amount = arc->amount; - txn->kacc = arc->kacc; + txn->amount = arc->amount; + //#1258344 keep the current account if tpl is empty + if(arc->kacc) + txn->kacc = arc->kacc; txn->paymode = arc->paymode; txn->flags = arc->flags | OF_ADDED; + txn->status = arc->status; txn->kpay = arc->kpay; txn->kcat = arc->kcat; txn->kxferacc = arc->kxferacc; txn->wording = g_strdup(arc->wording); txn->info = NULL; + if( da_splits_clone(arc->splits, txn->splits) > 0) + txn->flags |= OF_SPLIT; //Flag that Splits are active return txn; } @@@ -265,8 -140,7 +143,7 @@@ Transaction *da_transaction_clone(Transaction *src_item) { -Transaction *new_item = g_memdup(src_item, sizeof(Transaction)); +Transaction *new_item = rc_dup(src_item, sizeof(Transaction)); - guint count; DB( g_print("da_transaction_clone\n") ); @@@ -277,17 -151,16 +154,16 @@@ new_item->info = g_strdup(src_item->info); //duplicate tags - new_item->tags = NULL; - count = transaction_tags_count(src_item); - if(count > 0) - new_item->tags = g_memdup(src_item->tags, count*sizeof(guint32)); - - da_transaction_splits_clone(src_item, new_item); + transaction_tags_clone(src_item, new_item); + + if( da_splits_clone(src_item->splits, new_item->splits) > 0) + new_item->flags |= OF_SPLIT; //Flag that Splits are active } return new_item; } + GList * da_transaction_new(void) { @@@ -295,17 -168,58 +171,58 @@@ } - void da_transaction_destroy(GList *list) + guint + da_transaction_length(void) + { + GList *lst_acc, *lnk_acc; + guint count = 0; + + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + + count += g_queue_get_length (acc->txn_queue); + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); + return count; + } + + + static void da_transaction_queue_free_ghfunc(Transaction *item, gpointer data) + { + da_transaction_free (item); + } + + + void da_transaction_destroy(void) { - GList *tmplist = g_list_first(list); + GList *lacc, *list; - while (tmplist != NULL) + lacc = g_hash_table_get_values(GLOBALS->h_acc); + list = g_list_first(lacc); + while (list != NULL) { - Transaction *item = tmplist->data; - da_transaction_free(item); - tmplist = g_list_next(tmplist); + Account *acc = list->data; + + g_queue_foreach(acc->txn_queue, (GFunc)da_transaction_queue_free_ghfunc, NULL); + list = g_list_next(list); } - g_list_free(list); + g_list_free(lacc); + } + + + static gint da_transaction_compare_datafunc(Transaction *a, Transaction *b, gpointer data) + { + return ((gint)a->date - b->date); + } + + + void da_transaction_queue_sort(GQueue *queue) + { + g_queue_sort(queue, (GCompareDataFunc)da_transaction_compare_datafunc, NULL); } @@@ -334,24 -248,28 +251,28 @@@ static void da_transaction_insert_memo( } - gboolean da_transaction_insert_sorted(Transaction *newitem) { - GList *tmplist = g_list_first(GLOBALS->ope_list); + Account *acc; + GList *lnk_txn; - // find the breaking date - while (tmplist != NULL) + acc = da_acc_get(newitem->kacc); + if(!acc) + return FALSE; + + lnk_txn = g_queue_peek_tail_link(acc->txn_queue); + while (lnk_txn != NULL) { - Transaction *item = tmplist->data; + Transaction *item = lnk_txn->data; - if(item->date > newitem->date) + if(item->date <= newitem->date) break; - - tmplist = g_list_next(tmplist); + + lnk_txn = g_list_previous(lnk_txn); } - // here we're at the insert point, let's insert our new txn just before - GLOBALS->ope_list = g_list_insert_before(GLOBALS->ope_list, tmplist, newitem); + // we're at insert point, insert after txn + g_queue_insert_after(acc->txn_queue, lnk_txn, newitem); da_transaction_insert_memo(newitem); return TRUE; @@@ -361,7 -279,12 +282,12 @@@ // nota: this is called only when loading xml file gboolean da_transaction_prepend(Transaction *item) { - GLOBALS->ope_list = g_list_prepend(GLOBALS->ope_list, item); + Account *acc; + + acc = da_acc_get(item->kacc); + if(acc) + item->kcur = acc->kcur; + g_queue_push_tail(acc->txn_queue, item); da_transaction_insert_memo(item); return TRUE; } @@@ -369,33 -292,43 +295,43 @@@ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - guint32 + static guint32 da_transaction_get_max_kxfer(void) { - guint32 max_key = 0; + GList *lst_acc, *lnk_acc; GList *list; - Transaction *item; + guint32 max_key = 0; DB( g_print("da_transaction_get_max_kxfer\n") ); - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - item = list->data; - if( item->paymode == PAYMODE_INTXFER) + Account *acc = lnk_acc->data; + + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) { - if( item->kxfer > max_key) - max_key = item->kxfer; + Transaction *item = list->data; + + if( item->paymode == PAYMODE_INTXFER ) + { + max_key = MAX(max_key, item->kxfer); + } + list = g_list_next(list); } - list = g_list_next(list); + + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); DB( g_print(" max_key : %d \n", max_key) ); - return max_key; } + static void da_transaction_goto_orphan(Transaction *txn) { const gchar *oatn = "orphaned transactions"; @@@ -417,7 -350,10 +353,10 @@@ void da_transaction_consistency(Transac Account *acc; Category *cat; Payee *pay; - guint i, nbsplit; + gint nbsplit; + + // ensure date is between range + item->date = CLAMP(item->date, HB_MINDATE, HB_MAXDATE); // check account exists acc = da_acc_get(item->kacc); @@@ -425,6 -361,7 +364,7 @@@ { g_warning("txn consistency: fixed invalid acc %d", item->kacc); da_transaction_goto_orphan(item); + GLOBALS->changes_count++; } // check category exists @@@ -433,19 -370,19 +373,19 @@@ { g_warning("txn consistency: fixed invalid cat %d", item->kcat); item->kcat = 0; + GLOBALS->changes_count++; } // check split category #1340142 - nbsplit = da_transaction_splits_count(item); - for(i=0;isplits); + + //# 1416624 empty category when split + nbsplit = da_splits_count(item->splits); + if(nbsplit > 0 && item->kcat > 0) { - Split *split = item->splits[i]; - cat = da_cat_get(split->kcat); - if(cat == NULL) - { - g_warning("txn consistency: fixed invalid split cat %d", split->kcat); - split->kcat = 0; - } + g_warning("txn consistency: fixed invalid cat on split txn"); + item->kcat = 0; + GLOBALS->changes_count++; } // check payee exists @@@ -454,20 -391,25 +394,25 @@@ { g_warning("txn consistency: fixed invalid pay %d", item->kpay); item->kpay = 0; + GLOBALS->changes_count++; } // reset dst acc for non xfer transaction if( item->paymode != PAYMODE_INTXFER ) item->kxferacc = 0; + //#1628678 tags for internal xfer should be checked as well + + //#1295877 ensure income flag is correctly set item->flags &= ~(OF_INCOME); if( item->amount > 0) item->flags |= (OF_INCOME); //#1308745 ensure remind flag unset if reconciled - if( item->flags & OF_VALID ) - item->flags &= ~(OF_REMIND); + //useless since 5.0 + //if( item->flags & OF_VALID ) + // item->flags &= ~(OF_REMIND); } @@@ -475,82 -417,151 +420,154 @@@ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* new transfer functions */ - Transaction *transaction_strong_get_child_transfer(Transaction *src) + static void transaction_xfer_create_child(Transaction *ope) { - GList *list; - - DB( g_print("\n[transaction] transaction_strong_get_child_transfer\n") ); + Transaction *child; + Account *acc; + gchar swap; - DB( g_print(" - search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->kacc, src->kxferacc) ); + DB( g_print("\n[transaction] transaction_xfer_create_child\n") ); - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + if( ope->kxferacc > 0 ) { - Transaction *item = list->data; - //#1252230 - //if( item->paymode == PAYMODE_INTXFER && item->kacc == src->kxferacc && item->kxfer == src->kxfer ) - if( item->paymode == PAYMODE_INTXFER && item->kxfer == src->kxfer && item != src ) + child = da_transaction_clone(ope); + + ope->flags |= OF_CHANGED; + child->flags |= OF_ADDED; + + child->amount = -child->amount; + child->flags ^= (OF_INCOME); // invert flag + //#1268026 + child->status = TXN_STATUS_NONE; + //child->flags &= ~(OF_VALID); // delete reconcile state + + swap = child->kacc; + child->kacc = child->kxferacc; + child->kxferacc = swap; + + /* update acc flags */ + acc = da_acc_get( child->kacc ); + if(acc != NULL) { - DB( g_print(" - found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->kacc, item->kxferacc) ); - return item; + acc->flags |= AF_ADDED; + + //strong link + guint maxkey = da_transaction_get_max_kxfer(); + + DB( g_print(" + maxkey is %d\n", maxkey) ); + + + ope->kxfer = maxkey+1; + child->kxfer = maxkey+1; + + DB( g_print(" + strong link to %d\n", ope->kxfer) ); + + + DB( g_print(" + add transfer, %p\n", child) ); + + da_transaction_insert_sorted(child); + + account_balances_add (child); + ++ GValue txn_value = G_VALUE_INIT; ++ ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL); ++ } - list = g_list_next(list); } - DB( g_print(" - not found...\n") ); - return NULL; + } - /* - * this function retrieve into a glist the potential child transfer - * for the source transaction - */ - GList *transaction_match_get_child_transfer(Transaction *src) + //todo: add strong control and extend to payee, maybe memo ? + static gboolean transaction_xfer_child_might(Transaction *stxn, Transaction *dtxn, gint daygap) { - GList *list; - GList *match = NULL; + gboolean retval = FALSE; - DB( g_print("\n[transaction] transaction_match_get_child_transfer\n") ); + if(stxn == dtxn) + return FALSE; - //DB( g_print(" - search : %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) ); + /*g_print("test\n"); - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) - { - Transaction *item = list->data; - if( src->date == item->date && - src->kxferacc == item->kacc && - ABS(src->amount) == ABS(item->amount) && - item->kxfer == 0) - { - //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) ); + g_print(" %d %d %d %f %d\n", + stxn->kcur, stxn->date, stxn->kacc, ABS(stxn->amount), stxn->kxfer ); - match = g_list_append(match, item); - } - list = g_list_next(list); - } - DB( g_print(" - found : %d\n", g_list_length(match)) ); + g_print(" %d %d %d %f %d\n", + dtxn->kcur, dtxn->date, dtxn->kacc, ABS(dtxn->amount), dtxn->kxfer ); + */ - return match; + if( stxn->kcur == dtxn->kcur && + stxn->date == dtxn->date && + //v5.1 make no sense: stxn->kxferacc == dtxn->kacc && + stxn->kacc != dtxn->kacc && + ABS(stxn->amount) == ABS(dtxn->amount) && + dtxn->kxfer == 0) + { + retval = TRUE; + } + + //g_print(" return %d\n", retval); + return retval; } - void transaction_xfer_search_or_add_child(Transaction *ope, GtkWidget *treeview) + static GList *transaction_xfer_child_might_list_get(Transaction *ope) { - GList *matchlist = transaction_match_get_child_transfer(ope); + GList *lst_acc, *lnk_acc; + GList *list, *matchlist = NULL; + + DB( g_print("\n[transaction]xfer_get_potential_child\n") ); - guint count = g_list_length(matchlist); + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + if( !(acc->flags & AF_CLOSED) && (acc->key != ope->kacc) ) + { + list = g_queue_peek_tail_link(acc->txn_queue); + while (list != NULL) + { + Transaction *item = list->data; + + // no need to go higher than src txn date + if(item->date < ope->date) + break; + + if( transaction_xfer_child_might(ope, item, 0) == TRUE ) + { + //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) ); + matchlist = g_list_append(matchlist, item); + } + list = g_list_previous(list); + } + } + + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); + + return matchlist; + } + + + void transaction_xfer_search_or_add_child(GtkWindow *parentwindow, Transaction *ope, gboolean manual) + { + GList *matchlist; + gint count; DB( g_print("\n[transaction] transaction_xfer_search_or_add_child\n") ); + matchlist = transaction_xfer_child_might_list_get(ope); + count = g_list_length(matchlist); + DB( g_print(" - found result is %d, switching\n", count) ); switch(count) { case 0: //we should create the child - transaction_xfer_create_child(ope, treeview); + transaction_xfer_create_child(ope); break; //todo: maybe with just 1 match the user must choose ? @@@ -566,99 -577,80 +583,80 @@@ default: //the user must choose himself { - Transaction *child; + Transaction *child; - child = ui_dialog_transaction_xfer_select_child(matchlist); - if(child == NULL) - transaction_xfer_create_child(ope, treeview); - else - transaction_xfer_change_to_child(ope, child); - break; + child = ui_dialog_transaction_xfer_select_child(ope, matchlist); + if(child == NULL) + transaction_xfer_create_child(ope); + else + transaction_xfer_change_to_child(ope, child); } } g_list_free(matchlist); - } - - - - - void transaction_xfer_create_child(Transaction *ope, GtkWidget *treeview) + Transaction *transaction_xfer_child_strong_get(Transaction *src) { - Transaction *child; - Account *acc; - gchar swap; + Account *dstacc; + GList *list; - DB( g_print("\n[transaction] transaction_xfer_create_child\n") ); + DB( g_print("\n[transaction] transaction_xfer_child_strong_get\n") ); - if( ope->kxferacc > 0 ) - { - child = da_transaction_clone(ope); + dstacc = da_acc_get(src->kxferacc); + if( !dstacc || src->kxfer <= 0 ) + return NULL; - child->amount = -child->amount; - child->flags ^= (OF_INCOME); // invert flag - child->flags &= ~(OF_REMIND); // remove flag - //#1268026 - child->flags &= ~(OF_VALID); // remove reconcile state - + DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src->date, src->wording, src->amount, src->kacc, src->kxferacc, src->kxfer) ); - swap = child->kacc; - child->kacc = child->kxferacc; - child->kxferacc = swap; + list = g_queue_peek_tail_link(dstacc->txn_queue); + while (list != NULL) + { + Transaction *item = list->data; - /* update acc flags */ - acc = da_acc_get( child->kacc ); - if(acc != NULL) + //#1252230 + //if( item->paymode == PAYMODE_INTXFER + // && item->kacc == src->kxferacc + // && item->kxfer == src->kxfer ) + if( item->paymode == PAYMODE_INTXFER + && item->kxfer == src->kxfer + && item != src ) { - acc->flags |= AF_ADDED; - - //strong link - guint maxkey = da_transaction_get_max_kxfer(); - - DB( g_print(" + maxkey is %d\n", maxkey) ); - - - ope->kxfer = maxkey+1; - child->kxfer = maxkey+1; - - DB( g_print(" + strong link to %d\n", ope->kxfer) ); - - - DB( g_print(" + add transfer, %p\n", child) ); - - da_transaction_insert_sorted(child); - - account_balances_add (child); - - if(treeview != NULL) - transaction_add_treeview(child, treeview, ope->kacc); - - GValue txn_value = G_VALUE_INIT; - ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL); + DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item->date, item->wording, item->amount, item->kacc, item->kxferacc, src->kxfer) ); + return item; } + list = g_list_previous(list); } - + + DB( g_print(" - not found...\n") ); + return NULL; } + + void transaction_xfer_change_to_child(Transaction *ope, Transaction *child) { - Account *acc; + Account *dstacc; DB( g_print("\n[transaction] transaction_xfer_change_to_child\n") ); + if(ope->kcur != child->kcur) + return; + + ope->flags |= OF_CHANGED; + child->flags |= OF_CHANGED; + child->paymode = PAYMODE_INTXFER; ope->kxferacc = child->kacc; child->kxferacc = ope->kacc; /* update acc flags */ - acc = da_acc_get( child->kacc); - if(acc != NULL) - acc->flags |= AF_CHANGED; + dstacc = da_acc_get( child->kacc); + if(dstacc != NULL) + dstacc->flags |= AF_CHANGED; //strong link guint maxkey = da_transaction_get_max_kxfer(); @@@ -697,45 -689,58 +695,58 @@@ void transaction_xfer_sync_child(Transa account_balances_add (child); - //todo: synchronise tags here also ? + //synchronise tags since 5.1 + if(child->tags) + g_free(child->tags); + transaction_tags_clone (s_txn, child); } - void transaction_xfer_delete_child(Transaction *src) + void transaction_xfer_remove_child(Transaction *src) { Transaction *dst; - DB( g_print("\n[transaction] transaction_xfer_delete_child\n") ); + DB( g_print("\n[transaction] transaction_xfer_remove_child\n") ); - dst = transaction_strong_get_child_transfer( src ); + dst = transaction_xfer_child_strong_get( src ); DB( g_print(" -> return is %s, %p\n", dst->wording, dst) ); if( dst != NULL ) { + Account *acc = da_acc_get(dst->kacc); + DB( g_print("deleting...") ); src->kxfer = 0; src->kxferacc = 0; account_balances_sub(dst); - GLOBALS->ope_list = g_list_remove(GLOBALS->ope_list, dst); + g_queue_remove(acc->txn_queue, dst); + da_transaction_free (dst); } } + // still useful for upgrade from < file v0.6 (hb v4.4 kxfer) Transaction *transaction_old_get_child_transfer(Transaction *src) { + Account *acc; GList *list; - Transaction *item; DB( g_print("\n[transaction] transaction_get_child_transfer\n") ); //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) ); + acc = da_acc_get(src->kxferacc); - list = g_list_first(GLOBALS->ope_list); + list = g_queue_peek_head_link(acc->txn_queue); while (list != NULL) { - item = list->data; + Transaction *item = list->data; + + // no need to go higher than src txn date + if(item->date > src->date) + break; + if( item->paymode == PAYMODE_INTXFER) { if( src->date == item->date && @@@ -757,8 -762,6 +768,6 @@@ } - - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ @@@ -773,13 -776,16 +782,16 @@@ Account *acc acc = da_acc_get(ope->kacc); if(acc == NULL) return; + ope->kcur = acc->kcur; + if(ope->paymode == PAYMODE_INTXFER) { acc = da_acc_get(ope->kxferacc); if(acc == NULL) return; - // remove any splits - da_transaction_splits_free(ope); + // delete any splits + da_splits_free(ope->splits); + ope->flags &= ~(OF_SPLIT); //Flag that Splits are cleared } //allocate a new entry and copy from our edited structure @@@ -831,17 -837,12 +843,15 @@@ if(newope->paymode == PAYMODE_INTXFER) { - transaction_xfer_search_or_add_child(newope, treeview); + transaction_xfer_search_or_add_child(NULL, newope, FALSE); } + + GValue txn_value = G_VALUE_INIT; + ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, newope), NULL); } } - - void transaction_add_treeview(Transaction *ope, GtkWidget *treeview, guint32 accnum) { GtkTreeModel *model; @@@ -873,7 -874,33 +883,33 @@@ GtkTreeIter iter } + gboolean transaction_acc_move(Transaction *txn, guint32 okacc, guint32 nkacc) + { + Account *oacc, *nacc; + + oacc = da_acc_get(okacc); + nacc = da_acc_get(nkacc); + if( oacc && nacc ) + { + if( g_queue_remove(oacc->txn_queue, txn) ) + { + g_queue_push_tail(nacc->txn_queue, txn); + txn->kacc = nacc->key; + txn->kcur = nacc->kcur; + nacc->flags |= AF_CHANGED; + return TRUE; + } + else + //ensure to keep txn into current account + txn->kacc = okacc; + } + return FALSE; + } + + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + + static gboolean misc_text_match(gchar *text, gchar *searchtext, gboolean exact) { gboolean match = FALSE; @@@ -910,6 -937,22 +946,22 @@@ return match; } + static gboolean misc_regex_match(gchar *text, gchar *searchtext, gboolean exact) + { + gboolean match = FALSE; + + if(text == NULL) + return FALSE; + + DB( g_print("match RE %s in %s\n", searchtext, text) ); + if( searchtext != NULL ) + { + match = g_regex_match_simple(searchtext, text, ((exact == TRUE)?0:G_REGEX_CASELESS) | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY ); + if (match == TRUE) { DB( g_print(" found pattern '%s'\n", searchtext) ); } + } + return match; + } + static Assign *transaction_auto_assign_eval_txn(GList *l_rul, Transaction *txn) { @@@ -931,8 -974,17 +983,17 @@@ GList *list if(pay) text = pay->name; } - if( misc_text_match(text, rul->name, rul->flags & ASGF_EXACT)) - rule = rul; + + if( !(rul->flags & ASGF_REGEX) ) + { + if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) ) + rule = rul; + } + else + { + if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) ) + rule = rul; + } list = g_list_next(list); } @@@ -955,8 -1007,16 +1016,16 @@@ GList *list if( rul->field == 0 ) //memo { - if( misc_text_match(text, rul->name, rul->flags & ASGF_EXACT)) - rule = rul; + if( !(rul->flags & ASGF_REGEX) ) + { + if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) ) + rule = rul; + } + else + { + if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) ) + rule = rul; + } } list = g_list_next(list); } @@@ -965,7 -1025,7 +1034,7 @@@ } - gint transaction_auto_assign(GList *ope_list, guint32 key) + gint transaction_auto_assign(GList *ope_list, guint32 kacc) { GList *l_ope; GList *l_rul; @@@ -973,73 -1033,79 +1042,79 @@@ gint changes = 0 DB( g_print("\n[transaction] transaction_auto_assign\n") ); - l_ope = g_list_first(ope_list); l_rul = g_hash_table_get_values(GLOBALS->h_rul); + l_ope = g_list_first(ope_list); while (l_ope != NULL) { Transaction *ope = l_ope->data; + gboolean changed = FALSE; DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope->wording, ope->kacc, ope->kpay, ope->kcat) ); - //#1215521: added key == 0 - if( (key == ope->kacc || key == 0) ) + //#1215521: added kacc == 0 + if( (kacc == ope->kacc || kacc == 0) ) { Assign *rul; - if( !(ope->flags & OF_SPLIT) && (ope->kpay == 0 || ope->kcat == 0) ) + rul = transaction_auto_assign_eval_txn(l_rul, ope); + if( rul != NULL ) { - rul = transaction_auto_assign_eval_txn(l_rul, ope); - if( rul != NULL ) + if( (ope->kpay == 0 && (rul->flags & ASGF_DOPAY)) || (rul->flags & ASGF_OVWPAY) ) + { + if(ope->kpay != rul->kpay) { changed = TRUE; } + ope->kpay = rul->kpay; + } + + if( !(ope->flags & OF_SPLIT) ) { - if( ope->kpay == 0 && (rul->flags & ASGF_DOPAY) ) + if( (ope->kcat == 0 && (rul->flags & ASGF_DOCAT)) || (rul->flags & ASGF_OVWCAT) ) { - ope->kpay = rul->kpay; - ope->flags |= OF_CHANGED; - changes++; + if(ope->kcat != rul->kcat) { changed = TRUE; } + ope->kcat = rul->kcat; } - if( ope->kcat == 0 && (rul->flags & ASGF_DOCAT) ) + } + + if( (ope->paymode == 0 && (rul->flags & ASGF_DOMOD)) || (rul->flags & ASGF_OVWMOD) ) + { + //ugly hack - don't allow modify intxfer + if(ope->paymode != PAYMODE_INTXFER && rul->paymode != PAYMODE_INTXFER) { - ope->kcat = rul->kcat; - ope->flags |= OF_CHANGED; - changes++; + if(ope->paymode != rul->paymode) { changed = TRUE; } + ope->paymode = rul->paymode; } - } + } - else if( ope->flags & OF_SPLIT ) + + if( ope->flags & OF_SPLIT ) { - guint i, nbsplit = da_transaction_splits_count(ope); - Split *split; - gboolean split_change = FALSE; + guint i, nbsplit = da_splits_count(ope->splits); for(i=0;isplits[i]; - + Split *split = ope->splits[i]; + DB( g_print("- eval split '%s'\n", split->memo) ); - if(split->kcat == 0) + rul = transaction_auto_assign_eval(l_rul, split->memo); + if( rul != NULL ) { - rul = transaction_auto_assign_eval(l_rul, split->memo); - if( rul != NULL ) + //#1501144: check if user wants to set category in rule + if( (split->kcat == 0 || (rul->flags & ASGF_OVWCAT)) && (rul->flags & ASGF_DOCAT) ) { - if( split->kcat == 0 && rul->kcat > 0 ) - { - split->kcat = rul->kcat; - ope->flags |= OF_CHANGED; - split_change = TRUE; - } + if(split->kcat != rul->kcat) { changed = TRUE; } + split->kcat = rul->kcat; } } - } + } - if(split_change == TRUE) - changes++; - + if(changed == TRUE) + { + ope->flags |= OF_CHANGED; + changes++; } - } l_ope = g_list_next(l_ope); @@@ -1060,6 -1126,8 +1135,8 @@@ transaction_tags_count(Transaction *ope guint count = 0; guint32 *ptr = ope->tags; + DB( g_print("(transaction_tags_count)\n") ); + if( ope->tags == NULL ) return 0; @@@ -1070,82 -1138,19 +1147,19 @@@ } - - - guint transaction_splits_parse(Transaction *ope, gchar *cats, gchar *amounts, gchar *memos) + void transaction_tags_clone(Transaction *src_txn, Transaction *dst_txn) { - gchar **cat_a, **amt_a, **mem_a; - guint count, i; - guint32 kcat; - gdouble amount; - Split *split; - - DB( g_print(" split parse %s :: %s :: %s\n", cats, amounts, memos) ); - - cat_a = g_strsplit (cats, "||", 0); - amt_a = g_strsplit (amounts, "||", 0); - mem_a = g_strsplit (memos, "||", 0); + guint count; - count = g_strv_length(amt_a); - if( (count == g_strv_length(cat_a)) && (count == g_strv_length(mem_a)) ) - { - for(i=0;iflags |= OF_SPLIT; - } - else + dst_txn->tags = NULL; + count = transaction_tags_count(src_txn); + if(count > 0) { - g_warning("invalid split parse"); + //1501962: we must also copy the final 0 + dst_txn->tags = g_memdup(src_txn->tags, (count+1)*sizeof(guint32)); } - - g_strfreev (mem_a); - g_strfreev (amt_a); - g_strfreev (cat_a); - - return count; } - - - guint transaction_splits_tostring(Transaction *ope, gchar **cats, gchar **amounts, gchar **memos) - { - guint count, i; - Split *split; - char buf[G_ASCII_DTOSTR_BUF_SIZE]; - GString *cat_a = g_string_new (NULL); - GString *amt_a = g_string_new (NULL); - GString *mem_a = g_string_new (NULL); - - count = da_transaction_splits_count(ope); - for(i=0;isplits[i]; - g_string_append_printf (cat_a, "%d", split->kcat); - g_string_append(amt_a, g_ascii_dtostr (buf, sizeof (buf), split->amount) ); - g_string_append(mem_a, split->memo); - - if((i+1) < count) - { - g_string_append(cat_a, "||"); - g_string_append(amt_a, "||"); - g_string_append(mem_a, "||"); - } - } - - *cats = g_string_free(cat_a, FALSE); - *amounts = g_string_free(amt_a, FALSE); - *memos = g_string_free(mem_a, FALSE); - - return count; - } - - guint transaction_tags_parse(Transaction *ope, const gchar *tagstring) { @@@ -1153,7 -1158,7 +1167,7 @@@ gchar **str_array guint count, i; Tag *tag; - DB( g_print("(transaction_set_tags)\n") ); + DB( g_print("(transaction_tags_parse)\n") ); DB( g_print(" - tagstring='%s'\n", tagstring) ); @@@ -1189,6 -1194,7 +1203,7 @@@ ope->tags[i] = tag->key; } + ope->tags[i] = 0; } //hex_dump(ope->tags, sizeof(guint32*)*count+1); @@@ -1206,7 -1212,7 +1221,7 @@@ gchar **str_array gchar *tagstring; Tag *tag; - DB( g_print("transaction_get_tagstring\n") ); + DB( g_print("transaction_tags_tostring\n") ); DB( g_print(" -> tags at=%p\n", ope->tags) ); diff --combined src/hb-xml.c index 9db1e30,2338e58..68768fa --- a/src/hb-xml.c +++ b/src/hb-xml.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -23,8 -23,8 +23,10 @@@ #include "hb-transaction.h" #include "hb-xml.h" +#include "ext.h" + + #include "ui-dialogs.h" + /****************************************************************************/ /* Debug macros */ /****************************************************************************/ @@@ -40,757 -40,916 +42,919 @@@ extern struct HomeBank *GLOBALS; extern struct Preferences *PREFS; - typedef struct _ParseContext ParseContext; - struct _ParseContext - { - gdouble version; - }; + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - static void homebank_upgrade_to_v02(void); - static void homebank_upgrade_to_v03(void); - static void homebank_upgrade_to_v04(void); - static void homebank_upgrade_to_v05(void); - static void homebank_upgrade_lower_v06(void); - static void homebank_upgrade_to_v06(void); - static void homebank_upgrade_to_v07(void); - static void homebank_upgrade_to_v08(void); - static void - start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) + // v0.1 to v0.2 : we must change account reference by making a +1 to its index references + static void homebank_upgrade_to_v02(void) { - ParseContext *ctx = user_data; - //GtkUIManager *self = ctx->self; - gint i, j; + GList *lst_acc, *lnk_acc; + GList *list; + GHashTable *h_old_acc; + - //DB( g_print("** start element: %s\n", element_name) ); + DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") ); - switch(element_name[0]) + //keep old hashtable with us + h_old_acc = GLOBALS->h_acc; + da_acc_new(); + + lst_acc = g_hash_table_get_values(h_old_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - //get file version - /* - case 'h': - { - if(!strcmp (element_name, "homebank")) - { - if(!strcmp (attribute_names[0], "v" )) - { - version = g_ascii_strtod(attribute_values[0], NULL); - DB( g_print(" version %f\n", version) ); - } + Account *acc = lnk_acc->data; - } - } - */ + acc->key++; + acc->pos++; + da_acc_insert (acc); - case 'a': + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) { - if(!strcmp (element_name, "account")) - { - Account *entry = da_acc_malloc(); + Transaction *entry = list->data; + entry->kacc++; + entry->kxferacc++; + list = g_list_next(list); + } + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "pos" )) { entry->pos = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "type" )) { entry->type = atoi(attribute_values[i]); } - //else if(!strcmp (attribute_names[i], "curr" )) { entry->kcur = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "number" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->number = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "bankname")) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->bankname = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "initial" )) { entry->initial = g_ascii_strtod(attribute_values[i], NULL); } - else if(!strcmp (attribute_names[i], "minimum" )) { entry->minimum = g_ascii_strtod(attribute_values[i], NULL); } - else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); } + //we loose some small memory here + g_hash_table_steal_all(h_old_acc); - } + list = g_list_first(GLOBALS->arc_list); + while (list != NULL) + { + Archive *entry = list->data; + entry->kacc++; + entry->kxferacc++; + list = g_list_next(list); + } + } - //version upgrade: type was added in 0.2 - //todo: for stock account - /* - if(version <= 0.1) - { - entry->type = ACC_TYPE_BANK; - DB( g_print(" acctype forced to BANK\n") ); - } - */ + // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738 + static void homebank_upgrade_to_v03(void) + { + GList *lst_acc, *lnk_acc; + GList *list; - DB( g_print(" version %f\n", ctx->version) ); + DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") ); - //upgrade to v0.2 file - // we must change account reference by making a +1 to its index references - if( ctx->version == 0.1 ) - { - entry->key++; - entry->pos = entry->key; - } + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; - //all attribute loaded: append - da_acc_insert(entry); - } + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *entry = list->data; - //assign - else if(!strcmp (element_name, "asg")) - { - Assign *entry = da_asg_malloc(); - gint exact = 0; + da_transaction_consistency(entry); + list = g_list_next(list); + } + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "field" )) { entry->field = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); } - //else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } - // prior v08 - else if(!strcmp (attribute_names[i], "exact" )) { exact = atoi(attribute_values[i]); } - } - /* in v08 exact moved to flag */ - if( ctx->version <= 0.7) - { - entry->flags = (ASGF_DOCAT|ASGF_DOPAY); - if( exact > 0 ) - entry->flags |= ASGF_EXACT; - } + list = g_list_first(GLOBALS->arc_list); + while (list != NULL) + { + Archive *entry = list->data; - //all attribute loaded: append - da_asg_append(entry); + da_archive_consistency(entry); + list = g_list_next(list); + } + } - } + static void homebank_upgrade_to_v04(void) + { + DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") ); - } - break; + GLOBALS->arc_list = da_archive_sort(GLOBALS->arc_list); + } - case 'p': - { - if(!strcmp (element_name, "pay")) - { - Payee *entry = da_pay_malloc(); - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); + // v0.4 to v0.5 : + // we must assume kxferacc exists in archives for internal xfer : bug 528923 + // if not, delete automation from the archive + static void homebank_upgrade_to_v05(void) + { + GList *list; - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } - } + DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") ); - //all attribute loaded: append - da_pay_insert(entry); + list = g_list_first(GLOBALS->arc_list); + while (list != NULL) + { + Archive *entry = list->data; - } - else if(!strcmp (element_name, "properties")) - { - for (i = 0; attribute_names[i] != NULL; i++) - { - if(!strcmp (attribute_names[i], "title" )) { g_free(GLOBALS->owner); GLOBALS->owner = g_strdup(attribute_values[i]); } - //else if(!strcmp (attribute_names[i], "curr" )) { GLOBALS->kcur = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "car_category")) { GLOBALS->vehicle_category = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "auto_smode" )) { GLOBALS->auto_smode = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "auto_weekday")) { GLOBALS->auto_weekday = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "auto_nbdays" )) { GLOBALS->auto_nbdays = atoi(attribute_values[i]); } - } - } - } - break; + da_archive_consistency(entry); + list = g_list_next(list); + } + } - case 'c': - { - if(!strcmp (element_name, "cat")) - { - Category *entry = da_cat_malloc(); - gboolean budget; - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); + // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions + //#677351 + static void homebank_upgrade_to_v06(void) + { + GList *lst_acc, *lnk_acc; + GList *list; - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "parent")) { entry->parent = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } + DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") ); - budget = FALSE; - for(j=0;j<=12;j++) - { - gchar *tmpname; + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; - tmpname = g_strdup_printf ("b%d", j); - if(!(strcmp (attribute_names[i], tmpname))) { entry->budget[j] = g_ascii_strtod(attribute_values[i], NULL); } - g_free(tmpname); + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *entry = list->data; + da_transaction_consistency(entry); + list = g_list_next(list); + } + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); - if(entry->budget[j]) budget = TRUE; - } - if(budget == TRUE) - entry->flags |= GF_BUDGET; - } + list = g_list_first(GLOBALS->arc_list); + while (list != NULL) + { + Archive *entry = list->data; + da_archive_consistency(entry); + list = g_list_next(list); + } + } - //all attribute loaded: append - da_cat_insert( entry); - } - /* else if(!strcmp (element_name, "cur")) - { - Currency *entry = da_cur_malloc (); - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "frac" )) { entry->frac_digits = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "rate" )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); } - else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); } + // v0.7 AF_BUDGET deleted instead of AF_NOBUDGET + static void homebank_upgrade_to_v07(void) + { + GList *lacc, *list; - } + DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") ); - //all attribute loaded: append - da_cur_insert (entry); - } - */ - } - break; + lacc = list = g_hash_table_get_values(GLOBALS->h_acc); + while (list != NULL) + { + Account *acc = list->data; - case 't': + if( acc->flags & AF_OLDBUDGET ) // budget include { - if(!strcmp (element_name, "tags")) - { - Tag *entry = da_tag_malloc(); - - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } - //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } - } - - //all attribute loaded: append - da_tag_insert(entry); - - } + acc->flags &= ~(AF_OLDBUDGET); } - - case 'f': + else { - if(!strcmp (element_name, "fav")) - { - Archive *entry = da_archive_malloc(); + acc->flags |= AF_NOBUDGET; + } - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); } - else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "nextdate" )) { entry->nextdate = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "every" )) { entry->every = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "unit" )) { entry->unit = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "limit" )) { entry->limit = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "weekend" )) { entry->weekend = atoi(attribute_values[i]); } + list = g_list_next(list); + } + g_list_free(lacc); - } + } - //all attribute loaded: append - GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry); + static void homebank_upgrade_to_v08(void) + { + GList *lst_acc, *lnk_acc; + GList *list; - } - } - break; + DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") ); + + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; - /* - case 'r': + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) { + Transaction *entry = list->data; + da_transaction_consistency(entry); + list = g_list_next(list); } - break; - */ + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); - case 'o': - { - if(!strcmp (element_name, "ope")) - { - Transaction *entry = da_transaction_malloc(); - gchar *scat = NULL; - gchar *samt = NULL; - gchar *smem = NULL; - gboolean split = FALSE; - for (i = 0; attribute_names[i] != NULL; i++) - { - //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) ); - - if(!strcmp (attribute_names[i], "date" )) { entry->date = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); } - else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "info" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->info = g_strdup(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "tags" )) - { - if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 ) - { - transaction_tags_parse(entry, attribute_values[i]); - } - } - else if(!strcmp (attribute_names[i], "kxfer" )) { entry->kxfer = atoi(attribute_values[i]); } - else if(!strcmp (attribute_names[i], "scat" )) { scat = (gchar *)attribute_values[i]; split = TRUE; } - else if(!strcmp (attribute_names[i], "samt" )) { samt = (gchar *)attribute_values[i]; split = TRUE; } - else if(!strcmp (attribute_names[i], "smem" )) { smem = (gchar *)attribute_values[i]; split = TRUE; } - } + } - //bugfix 303886 - //if(entry->kcat < 0) - // entry->kcat = 0; - if(split == TRUE) - { - transaction_splits_parse(entry, scat, samt, smem); - } + static void homebank_upgrade_to_v10(void) + { + GList *lst_acc, *lnk_acc; + GList *list; - //all attribute loaded: append - // we use prepend here, the list will be reversed later for perf reason - da_transaction_prepend(entry); - } - } - break; + DB( g_print("\n[hb-xml] homebank_upgrade_to_v10\n") ); + + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *entry = list->data; + entry->status = TXN_STATUS_NONE; + if(entry->flags & OF_OLDVALID) + entry->status = TXN_STATUS_RECONCILED; + else + if(entry->flags & OF_OLDREMIND) + entry->status = TXN_STATUS_REMIND; + //remove those flags + entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND); + list = g_list_next(list); + } + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); } - /* - static void - end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) - { - ParseContext *ctx = user_data; - - //DB( g_print("-- end element: %s\n", element_name) ); - - } - */ + static void homebank_upgrade_to_v11(void) + { + GList *list; - static GMarkupParser hb_parser = { - start_element_handler, - NULL, //end_element_handler, - NULL, //text_handler, - NULL, - NULL //cleanup - }; + DB( g_print("\n[hb-xml] homebank_upgrade_to_v11\n") ); - /* - ** XML load homebank file: hbfile - */ - gint homebank_load_xml(gchar *filename) - { - gint retval; - gchar *buffer; - gsize length; - GError *error = NULL; - ParseContext ctx = { 0 }; - GMarkupParseContext *context; - gboolean rc; + list = g_list_first(GLOBALS->arc_list); + while (list != NULL) + { + Archive *entry = list->data; - DB( g_print("\n[hb-xml] homebank_load_xml\n") ); + entry->status = TXN_STATUS_NONE; + if(entry->flags & OF_OLDVALID) + entry->status = TXN_STATUS_RECONCILED; + else + if(entry->flags & OF_OLDREMIND) + entry->status = TXN_STATUS_REMIND; - GValue filename_val = G_VALUE_INIT; - ext_hook("load_file", EXT_STRING(&filename_val, filename), NULL); + //remove those flags + entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND); - retval = XML_OK; - if (!g_file_get_contents (filename, &buffer, &length, &error)) - { - //g_message ("%s", error->message); - retval = XML_IO_ERROR; - g_error_free (error); + list = g_list_next(list); } - else - { - gchar *v_buffer; - gdouble version; - /* v3.4 add :: prevent load of future file version */ - v_buffer = g_strstr_len(buffer, 50, "kcur %d\n", GLOBALS->kcur) ); - ctx.version = version; + ui_dialog_upgrade_choose_currency(); + } - if( version > FILE_VERSION ) - { - DB( g_print("- failed: version %f is not supported (max is %f)\n", version, FILE_VERSION) ); - return XML_VERSION_ERROR; - } - else - { - DB( g_print("- ok : version=%.1f\n", version) ); - /* 1st: validate the file is well in utf-8 */ - DB( g_print("- ensure UTF-8\n") ); - buffer = homebank_utf8_ensure(buffer); - /* then process the buffer */ - #if MYDEBUG == 1 - GTimer *t = g_timer_new(); - g_print("- start parse\n"); - #endif - - context = g_markup_parse_context_new (&hb_parser, 0, &ctx, NULL); + // lower v0.6 : we must assume categories/payee exists + // and strong link to xfer + // #632496 + static void homebank_upgrade_lower_v06(void) + { + GList *lst_acc, *lnk_acc; + Category *cat; + Payee *pay; + GList *lrul, *list; - error = NULL; - rc = g_markup_parse_context_parse (context, buffer, length, &error); + DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") ); - if( error ) - g_print("failed: %s\n", error->message); + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) + { + Account *acc = lnk_acc->data; + + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *entry = list->data; - if( rc == FALSE ) + //also strong link internal xfer + if(entry->paymode == PAYMODE_INTXFER && entry->kxfer == 0) { - error = NULL; - g_markup_parse_context_end_parse(context, &error); - - if( error ) - g_print("failed: %s\n", error->message); + Transaction *child = transaction_old_get_child_transfer(entry); + if(child != NULL) + { + transaction_xfer_change_to_child(entry, child); + } } - g_markup_parse_context_free (context); - g_free (buffer); - - //reverse the glist (see g_list append idiom to perf for reason - // we use prepend and then reverse - GLOBALS->ope_list = g_list_reverse(GLOBALS->ope_list); + da_transaction_consistency(entry); - DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t, NULL)) ); - DB( g_timer_destroy (t) ); + list = g_list_next(list); + } + lnk_acc = g_list_next(lnk_acc); + } + g_list_free(lst_acc); - /* file upgrade / bugfix */ - if( version <= 0.1 ) - homebank_upgrade_to_v02(); - if( version <= 0.2 ) - homebank_upgrade_to_v03(); - if( version <= 0.3 ) - homebank_upgrade_to_v04(); - if( version <= 0.4 ) - homebank_upgrade_to_v05(); - if( version <= 0.5 ) - { - homebank_upgrade_to_v06(); - homebank_upgrade_lower_v06(); - } - if( version <= 0.6 ) - { - homebank_upgrade_to_v07(); - hbfile_sanity_check(); - } - if( version <= 0.7 ) - homebank_upgrade_to_v08(); - if( version <= 0.8 ) - hbfile_sanity_check(); - // next ? - + lrul = list = g_hash_table_get_values(GLOBALS->h_rul); + while (list != NULL) + { + Assign *entry = list->data; + + cat = da_cat_get(entry->kcat); + if(cat == NULL) + { + DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) ); + entry->kcat = 0; } - } - return retval; + pay = da_pay_get(entry->kpay); + if(pay == NULL) + { + DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) ); + entry->kpay = 0; + } + + + list = g_list_next(list); + } + g_list_free(lrul); } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ - // v0.1 to v0.2 : we must change account reference by making a +1 to its index references - static void homebank_upgrade_to_v02(void) + + static void homebank_load_xml_acc(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) { - GList *list; + Account *entry = da_acc_malloc(); + gint i; - DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") ); + for (i = 0; attribute_names[i] != NULL; i++) + { + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "pos" )) { entry->pos = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "type" )) { entry->type = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "curr" )) { entry->kcur = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "number" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->number = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "bankname")) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->bankname = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "initial" )) { entry->initial = g_ascii_strtod(attribute_values[i], NULL); } + + else if(!strcmp (attribute_names[i], "minimum" )) { entry->minimum = g_ascii_strtod(attribute_values[i], NULL); } + else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "notes" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->notes = g_strdup(attribute_values[i]); } + } - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + //all attribute loaded: append + da_acc_insert(entry); + } + + + static void homebank_load_xml_asg(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) + { + Assign *entry = da_asg_malloc(); + gint exact = 0; + gint i; + + for (i = 0; attribute_names[i] != NULL; i++) { - Transaction *entry = list->data; - entry->kacc++; - entry->kxferacc++; - list = g_list_next(list); + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "field" )) { entry->field = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->text = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } + // prior v08 + else if(!strcmp (attribute_names[i], "exact" )) { exact = atoi(attribute_values[i]); } } - list = g_list_first(GLOBALS->arc_list); - while (list != NULL) + /* in v08 exact moved to flag */ + if( ctx->file_version <= 0.7) { - Archive *entry = list->data; - entry->kacc++; - entry->kxferacc++; - list = g_list_next(list); + entry->flags = (ASGF_DOCAT|ASGF_DOPAY); + if( exact > 0 ) + entry->flags |= ASGF_EXACT; } + + //all attribute loaded: append + da_asg_append(entry); + } - // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738 - static void homebank_upgrade_to_v03(void) + + static void homebank_load_xml_pay(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) { - GList *list; + Payee *entry = da_pay_malloc(); + gint i; - DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") ); - - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + for (i = 0; attribute_names[i] != NULL; i++) { - Transaction *entry = list->data; + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); - da_transaction_consistency(entry); - list = g_list_next(list); + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } } - list = g_list_first(GLOBALS->arc_list); - while (list != NULL) - { - Archive *entry = list->data; + //all attribute loaded: append + da_pay_insert(entry); + } - da_archive_consistency(entry); - list = g_list_next(list); + + static void homebank_load_xml_prop(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) + { + gint i; + + for (i = 0; attribute_names[i] != NULL; i++) + { + if(!strcmp (attribute_names[i], "title" )) { g_free(GLOBALS->owner); GLOBALS->owner = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "curr" )) { GLOBALS->kcur = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "car_category")) { GLOBALS->vehicle_category = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "auto_smode" )) { GLOBALS->auto_smode = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "auto_weekday")) { GLOBALS->auto_weekday = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "auto_nbdays" )) { GLOBALS->auto_nbdays = atoi(attribute_values[i]); } } } - static void homebank_upgrade_to_v04(void) + + static void homebank_load_xml_cat(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) { - DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") ); + Category *entry = da_cat_malloc(); + gboolean budget; + gint i, j; - GLOBALS->arc_list = da_archive_sort(GLOBALS->arc_list); + for (i = 0; attribute_names[i] != NULL; i++) + { + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "parent")) { entry->parent = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } + + budget = FALSE; + for(j=0;j<=12;j++) + { + gchar *tmpname; + + tmpname = g_strdup_printf ("b%d", j); + if(!(strcmp (attribute_names[i], tmpname))) { entry->budget[j] = g_ascii_strtod(attribute_values[i], NULL); } + g_free(tmpname); + + if(entry->budget[j]) budget = TRUE; + } + if(budget == TRUE) + entry->flags |= GF_BUDGET; + + } + + //all attribute loaded: append + da_cat_insert( entry); } - // v0.4 to v0.5 : - // we must assume kxferacc exists in archives for internal xfer : bug 528923 - // if not, remove automation from the archive - static void homebank_upgrade_to_v05(void) + static void homebank_load_xml_cur(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) { - GList *list; + Currency *entry = da_cur_malloc (); + gint i; - DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") ); + for (i = 0; attribute_names[i] != NULL; i++) + { + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "frac" )) { entry->frac_digits = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "rate" )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); } + else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); } - list = g_list_first(GLOBALS->arc_list); - while (list != NULL) + } + + //all attribute loaded: append + da_cur_insert (entry); + } + + + static void homebank_load_xml_tag(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) + { + Tag *entry = da_tag_malloc(); + gint i; + + for (i = 0; attribute_names[i] != NULL; i++) { - Archive *entry = list->data; + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); - da_archive_consistency(entry); - list = g_list_next(list); + if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); } + //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); } } + + //all attribute loaded: append + da_tag_insert(entry); } - // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions - //#677351 - static void homebank_upgrade_to_v06(void) + static void homebank_load_xml_fav(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) { - GList *list; + Archive *entry = da_archive_malloc(); + gchar *scat = NULL; + gchar *samt = NULL; + gchar *smem = NULL; + gboolean split = FALSE; + gint i; + + for (i = 0; attribute_names[i] != NULL; i++) + { + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); } + else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "st" )) { entry->status = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "nextdate" )) { entry->nextdate = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "every" )) { entry->every = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "unit" )) { entry->unit = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "limit" )) { entry->limit = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "weekend" )) { entry->weekend = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "scat" )) { scat = (gchar *)attribute_values[i]; split = TRUE; } + else if(!strcmp (attribute_names[i], "samt" )) { samt = (gchar *)attribute_values[i]; split = TRUE; } + else if(!strcmp (attribute_names[i], "smem" )) { smem = (gchar *)attribute_values[i]; split = TRUE; } - DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") ); + } - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + if(split == TRUE) { - Transaction *entry = list->data; - da_transaction_consistency(entry); - list = g_list_next(list); + if (da_splits_parse(entry->splits, scat, samt, smem) > 0) + { + entry->flags |= OF_SPLIT; //Flag that Splits are active + } } - list = g_list_first(GLOBALS->arc_list); - while (list != NULL) + //all attribute loaded: append + GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry); + } + + + static void homebank_load_xml_ope(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values) + { + Transaction *entry = da_transaction_malloc(); + gchar *scat = NULL; + gchar *samt = NULL; + gchar *smem = NULL; + gboolean split = FALSE; + gint i; + + for (i = 0; attribute_names[i] != NULL; i++) { - Archive *entry = list->data; - da_archive_consistency(entry); - list = g_list_next(list); + //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) ); + + if(!strcmp (attribute_names[i], "date" )) { entry->date = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); } + else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "st" )) { entry->status = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "payee" )) { entry->kpay = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "category" )) { entry->kcat = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "info" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->info = g_strdup(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "tags" )) + { + if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 ) + { + transaction_tags_parse(entry, attribute_values[i]); + } + } + else if(!strcmp (attribute_names[i], "kxfer" )) { entry->kxfer = atoi(attribute_values[i]); } + else if(!strcmp (attribute_names[i], "scat" )) { scat = (gchar *)attribute_values[i]; split = TRUE; } + else if(!strcmp (attribute_names[i], "samt" )) { samt = (gchar *)attribute_values[i]; split = TRUE; } + else if(!strcmp (attribute_names[i], "smem" )) { smem = (gchar *)attribute_values[i]; split = TRUE; } + } + + //bugfix 303886 + //if(entry->kcat < 0) + // entry->kcat = 0; + + if(split == TRUE) + { + if (da_splits_parse(entry->splits, scat, samt, smem) > 0) + { + entry->flags |= OF_SPLIT; //Flag that Splits are active + } } + + //all attribute loaded: append + // we use prepend here, the list will be reversed later for perf reason + da_transaction_prepend(entry); } - // v0.7 AF_BUDGET removed instead of AF_NOBUDGET - static void homebank_upgrade_to_v07(void) + + + static void + start_element_handler (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) { - GList *lacc, *list; + ParseContext *ctx = user_data; + //GtkUIManager *self = ctx->self; - DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") ); + //DB( g_print("** start element: %s\n", element_name) ); - lacc = list = g_hash_table_get_values(GLOBALS->h_acc); - while (list != NULL) + switch(element_name[0]) { - Account *acc = list->data; + case 'a': + { + if(!strcmp (element_name, "account")) //account + { + homebank_load_xml_acc(ctx, attribute_names, attribute_values); + } + else if(!strcmp (element_name, "asg")) //assign + { + homebank_load_xml_asg(ctx, attribute_names, attribute_values); + } + } + break; - if( acc->flags & AF_OLDBUDGET ) // budget include + case 'p': { - acc->flags &= ~(AF_OLDBUDGET); + if(!strcmp (element_name, "pay")) + { + homebank_load_xml_pay(ctx, attribute_names, attribute_values); + } + else if(!strcmp (element_name, "properties")) + { + homebank_load_xml_prop(ctx, attribute_names, attribute_values); + } } - else + break; + + case 'c': { - acc->flags |= AF_NOBUDGET; + if(!strcmp (element_name, "cat")) + { + homebank_load_xml_cat(ctx, attribute_names, attribute_values); + } + else if(!strcmp (element_name, "cur")) + { + homebank_load_xml_cur(ctx, attribute_names, attribute_values); + } } + break; - list = g_list_next(list); + case 't': + { + if(!strcmp (element_name, "tags")) + { + homebank_load_xml_tag(ctx, attribute_names, attribute_values); + } + } + + case 'f': + { + if(!strcmp (element_name, "fav")) + { + homebank_load_xml_fav(ctx, attribute_names, attribute_values); + } + } + break; + + case 'o': + { + if(!strcmp (element_name, "ope")) + { + homebank_load_xml_ope(ctx, attribute_names, attribute_values); + } + } + break; } - g_list_free(lacc); + } + + + /* + static void + end_element_handler (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) + { + ParseContext *ctx = user_data; + + //DB( g_print("-- end element: %s\n", element_name) ); + } + */ - static void homebank_upgrade_to_v08(void) + static GMarkupParser hb_parser = { + start_element_handler, + NULL, //end_element_handler, + NULL, //text_handler, + NULL, + NULL //cleanup + }; + + + static gboolean hb_xml_get_version(ParseContext *ctx, gchar *buffer) { - GList *list; + gchar *v_buffer; - DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") ); + ctx->file_version = 0.0; + ctx->data_version = 0; - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) - { - Transaction *entry = list->data; - da_transaction_consistency(entry); - list = g_list_next(list); - } + /* v3.4 add :: prevent load of future file version */ + v_buffer = g_strstr_len(buffer, 50, "file_version = g_ascii_strtod(v_buffer+13, NULL); /* a little hacky, but works ! */ + if( ctx->file_version == 0.0 ) + ctx->file_version = 0.1; + else if( ctx->file_version == 5.0 ) //was a mistake + ctx->file_version = 1.0; + v_buffer = g_strstr_len(buffer+13, 50, "d="); + if( v_buffer ) + { + DB( g_print(" d=%s)\n\n", v_buffer) ); + + ctx->data_version = atoi(v_buffer+3); + } + return TRUE; } - // v0.6 to v0.7 : assign a default currency /* - static void homebank_upgrade_to_v08(void) + ** XML load homebank file: hbfile + */ + gint homebank_load_xml(gchar *filename) { + gint retval; + gchar *buffer; + gsize length; + GError *error = NULL; + ParseContext ctx; + GMarkupParseContext *context; + gboolean rc; + + DB( g_print("\n[hb-xml] homebank_load_xml\n") ); + ++ GValue filename_val = G_VALUE_INIT; ++ ext_hook("load_file", EXT_STRING(&filename_val, filename), NULL); ++ + retval = XML_OK; + if (!g_file_get_contents (filename, &buffer, &length, &error)) + { + //g_message ("%s", error->message); + retval = XML_IO_ERROR; + g_error_free (error); + } + else + { + if( hb_xml_get_version(&ctx, buffer) == FALSE ) + { + return XML_FILE_ERROR; + } - // set a base currency to the hbfile if not - g_print("GLOBALS->kcur %d\n", GLOBALS->kcur); + if( ctx.file_version > FILE_VERSION ) + { + DB( g_print("- failed: version %f is not supported (max is %f)\n", ctx.file_version, FILE_VERSION) ); + return XML_VERSION_ERROR; + } + else + { + DB( g_print("- file ok : v=%.1f data_v=%06d\n", ctx.file_version, ctx.data_version) ); - if(GLOBALS->kcur == 0) - { - //struct iso4217format *choice = ui_cur_select_dialog_new(GLOBALS->mainwindow); - struct iso4217format *curfmt = iso4217format_get(PREFS->curr_default); + /* 1st: validate the file is well in utf-8 */ + DB( g_print("- ensure UTF-8\n") ); + buffer = homebank_utf8_ensure(buffer); - if(curfmt == NULL) - curfmt = iso4217format_get_en_us(); - - - Currency *item = currency_add_from_user(curfmt); + /* then process the buffer */ + #if MYDEBUG == 1 + GTimer *t = g_timer_new(); + g_print("- start parse\n"); + #endif - GLOBALS->kcur = item->key; + context = g_markup_parse_context_new (&hb_parser, 0, &ctx, NULL); - g_print("GLOBALS->kcur %d\n", GLOBALS->kcur); + error = NULL; + rc = g_markup_parse_context_parse (context, buffer, length, &error); - // set every accounts to base currecny - GList *list = g_hash_table_get_values(GLOBALS->h_acc); - while (list != NULL) - { - Account *acc; - acc = list->data; + if( error ) + g_print("failed: %s\n", error->message); - acc->kcur = item->key; + if( rc == FALSE ) + { + error = NULL; + g_markup_parse_context_end_parse(context, &error); - list = g_list_next(list); + if( error ) + g_print("failed: %s\n", error->message); } - g_list_free(list); - - - } - } - */ - - - // lower v0.6 : we must assume categories/payee exists - // and strong link to xfer - // #632496 - static void homebank_upgrade_lower_v06(void) - { - Category *cat; - Payee *pay; - GList *lrul, *list; - DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") ); - - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) - { - Transaction *entry = list->data; + g_markup_parse_context_free (context); + g_free (buffer); - da_transaction_consistency(entry); + DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t, NULL)) ); + DB( g_timer_destroy (t) ); - //also strong link internal xfer - if(entry->paymode == PAYMODE_INTXFER) - { - Transaction *child = transaction_old_get_child_transfer(entry); - if(child != NULL) + /* file upgrade / bugfix */ + if( ctx.file_version <= 0.1 ) + homebank_upgrade_to_v02(); + if( ctx.file_version <= 0.2 ) + homebank_upgrade_to_v03(); + if( ctx.file_version <= 0.3 ) + homebank_upgrade_to_v04(); + if( ctx.file_version <= 0.4 ) + homebank_upgrade_to_v05(); + if( ctx.file_version <= 0.5 ) { - transaction_xfer_change_to_child(entry, child); + homebank_upgrade_to_v06(); + homebank_upgrade_lower_v06(); + } + if( ctx.file_version <= 0.6 ) + { + homebank_upgrade_to_v07(); + hbfile_sanity_check(); + } + if( ctx.file_version <= 0.7 ) // <= 4.5 + { + homebank_upgrade_to_v08(); + } + if( ctx.file_version <= 0.8 ) // <= 4.6 + { + hbfile_sanity_check(); + } + if( ctx.file_version <= 0.9 ) // <= 4.6.3 + { + hbfile_sanity_check(); + homebank_upgrade_to_v10(); + } + if( ctx.file_version <= 1.0 ) // <= 5.0.0 + { + hbfile_sanity_check(); + homebank_upgrade_to_v11(); + } + //starting 5.0.4 data upgrade is done without changing file_version + if( ctx.data_version < 050005 ) // <= 5.0.5 + { + hbfile_sanity_check(); + } + if( ctx.file_version <= 1.1 ) // <= 5.1.0 + { + hbfile_sanity_check(); + homebank_upgrade_to_v12(); } - } - - list = g_list_next(list); - } - - - lrul = list = g_hash_table_get_values(GLOBALS->h_rul); - while (list != NULL) - { - Assign *entry = list->data; - - cat = da_cat_get(entry->kcat); - if(cat == NULL) - { - DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) ); - entry->kcat = 0; - } - pay = da_pay_get(entry->kpay); - if(pay == NULL) - { - DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) ); - entry->kpay = 0; + // next ? + } - - - list = g_list_next(list); } - g_list_free(lrul); - + return retval; } + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* @@@ -806,6 -965,79 +970,79 @@@ static void hb_xml_append_txt(GString * } } + static void + append_escaped_text (GString *str, + const gchar *text, + gssize length) + { + const gchar *p; + const gchar *end; + gunichar c; + + p = text; + end = text + length; + + while (p < end) + { + const gchar *next; + next = g_utf8_next_char (p); + + switch (*p) + { + case '&': + g_string_append (str, "&"); + break; + + case '<': + g_string_append (str, "<"); + break; + + case '>': + g_string_append (str, ">"); + break; + + case '\'': + g_string_append (str, "'"); + break; + + case '"': + g_string_append (str, """); + break; + + default: + c = g_utf8_get_char (p); + if ((0x1 <= c && c <= 0x8) || + (0xa <= c && c <= 0xd) || //chnaged here from b<->c to a<->d + (0xe <= c && c <= 0x1f) || + (0x7f <= c && c <= 0x84) || + (0x86 <= c && c <= 0x9f)) + g_string_append_printf (str, "&#x%x;", c); + else + g_string_append_len (str, p, next - p); + break; + } + + p = next; + } + } + + // we override g_markup_escape_text from glib to encode \n (LF) & \r (CR) + static void hb_xml_append_txt_crlf(GString *gstring, gchar *attrname, gchar *value) + { + if(value != NULL && *value != 0) + { + gssize length; + GString *escaped; + + //gchar *escaped = g_markup_escape_text(value, -1); + length = strlen (value); + escaped = g_string_sized_new (length); + append_escaped_text (escaped, value, length); + g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped->str); + g_string_free (escaped, TRUE); + } + } + static void hb_xml_append_int0(GString *gstring, gchar *attrname, guint32 value) { g_string_append_printf(gstring, "%s=\"%d\" ", attrname, value); @@@ -829,13 -1061,18 +1066,18 @@@ char buf[G_ASCII_DTOSTR_BUF_SIZE] } + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + + /* ** XML properties save */ - static void homebank_save_xml_prop(GIOChannel *io) + static gint homebank_save_xml_prop(GIOChannel *io) { gchar *title; GString *node; + gint retval = XML_OK; + GError *error = NULL; title = GLOBALS->owner == NULL ? "" : GLOBALS->owner; @@@ -844,6 -1081,7 +1086,7 @@@ g_string_assign(node, "kcur); hb_xml_append_int(node, "car_category", GLOBALS->vehicle_category); hb_xml_append_int0(node, "auto_smode", GLOBALS->auto_smode); hb_xml_append_int(node, "auto_weekday", GLOBALS->auto_weekday); @@@ -851,61 -1089,67 +1094,67 @@@ g_string_append(node, "/>\n"); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } g_string_free(node, TRUE); + return retval; } /* ** XML currency save */ - /* - static void homebank_save_xml_cur(GIOChannel *io) + static gint homebank_save_xml_cur(GIOChannel *io) { GList *list; gchar *tmpstr; char buf1[G_ASCII_DTOSTR_BUF_SIZE]; + gint retval = XML_OK; list = g_hash_table_get_values(GLOBALS->h_cur); while (list != NULL) { Currency *item = list->data; - if(item->key != 0) - { - tmpstr = g_markup_printf_escaped( - "\n", - item->key, - item->iso_code, - item->name, - item->symbol, - item->sym_prefix, - item->decimal_char, - item->grouping_char, - item->frac_digits, - g_ascii_dtostr (buf1, sizeof (buf1), item->rate), - item->mdate - ); - - g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL); - g_free(tmpstr); + tmpstr = g_markup_printf_escaped( + "\n", + item->key, + item->iso_code, + item->name, + item->symbol, + item->sym_prefix, + item->decimal_char, + item->grouping_char, + item->frac_digits, + g_ascii_dtostr (buf1, sizeof (buf1), item->rate), + item->mdate + ); + + g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL); + g_free(tmpstr); - } list = g_list_next(list); } g_list_free(list); + return retval; } - */ /* ** XML account save */ - static void homebank_save_xml_acc(GIOChannel *io) + static gint homebank_save_xml_acc(GIOChannel *io) { GList *lacc, *list; GString *node; + gint retval = XML_OK; + GError *error = NULL; node = g_string_sized_new(255); @@@ -914,7 -1158,7 +1163,7 @@@ { Account *item = list->data; - item->flags &= ~(AF_ADDED|AF_CHANGED); //remove flag + item->flags &= ~(AF_ADDED|AF_CHANGED); //delete flag g_string_assign(node, "flags); hb_xml_append_int(node, "pos", item->pos); hb_xml_append_int(node, "type", item->type); - //hb_xml_append_int(node, "curr", item->kcur); + hb_xml_append_int(node, "curr", item->kcur); hb_xml_append_txt(node, "name", item->name); hb_xml_append_txt(node, "number", item->number); hb_xml_append_txt(node, "bankname", item->bankname); hb_xml_append_amt(node, "initial", item->initial); + hb_xml_append_amt(node, "minimum", item->minimum); hb_xml_append_int(node, "cheque1", item->cheque1); hb_xml_append_int(node, "cheque2", item->cheque2); + hb_xml_append_txt_crlf(node, "notes", item->notes); g_string_append(node, "/>\n"); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } + list = g_list_next(list); } g_list_free(lacc); g_string_free(node, TRUE); + return retval; } /* ** XML payee save */ - static void homebank_save_xml_pay(GIOChannel *io) + static gint homebank_save_xml_pay(GIOChannel *io) { GList *lpay, *list; - gchar *tmpstr; + GString *node; + gint retval = XML_OK; + GError *error = NULL; + + node = g_string_sized_new(255); lpay = list = payee_glist_sorted(0); while (list != NULL) @@@ -955,29 -1214,43 +1219,43 @@@ if(item->key != 0) { - tmpstr = g_markup_printf_escaped("\n", - item->key, - item->name - ); + g_string_assign(node, "key); + hb_xml_append_txt(node, "name", item->name); + hb_xml_append_int(node, "category", item->kcat); + hb_xml_append_int(node, "paymode" , item->paymode); + + g_string_append(node, "/>\n"); + + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } } list = g_list_next(list); } g_list_free(lpay); + g_string_free(node, TRUE); + return retval; } /* ** XML category save */ - static void homebank_save_xml_cat(GIOChannel *io) + static gint homebank_save_xml_cat(GIOChannel *io) { GList *lcat, *list; GString *node; char buf[G_ASCII_DTOSTR_BUF_SIZE]; guint i; + gint retval = XML_OK; + GError *error = NULL; node = g_string_sized_new(255); @@@ -1004,22 -1277,33 +1282,33 @@@ } g_string_append(node, "/>\n"); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); + + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } } list = g_list_next(list); } g_list_free(lcat); g_string_free(node, TRUE); + return retval; } /* ** XML tag save */ - static void homebank_save_xml_tag(GIOChannel *io) + static gint homebank_save_xml_tag(GIOChannel *io) { GList *ltag, *list; gchar *tmpstr; + gint retval = XML_OK; + GError *error = NULL; ltag = list = tag_glist_sorted(0); while (list != NULL) @@@ -1028,28 -1312,37 +1317,37 @@@ if(item->key != 0) { - tmpstr = g_markup_printf_escaped("\n", + tmpstr = g_markup_printf_escaped("\n", item->key, item->name ); - g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL); + error = NULL; + g_io_channel_write_chars(io, tmpstr, -1, NULL, &error); g_free(tmpstr); - + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } } list = g_list_next(list); } g_list_free(ltag); + return retval; } /* ** XML assign save */ - static void homebank_save_xml_asg(GIOChannel *io) + static gint homebank_save_xml_asg(GIOChannel *io) { GList *lasg, *list; GString *node; + gint retval = XML_OK; + GError *error = NULL; node = g_string_sized_new(255); @@@ -1063,19 -1356,27 +1361,27 @@@ hb_xml_append_int(node, "key" , item->key); hb_xml_append_int(node, "flags" , item->flags); hb_xml_append_int(node, "field" , item->field); - hb_xml_append_txt(node, "name" , item->name); + hb_xml_append_txt(node, "name" , item->text); hb_xml_append_int(node, "payee" , item->kpay); hb_xml_append_int(node, "category", item->kcat); - //hb_xml_append_int(node, "paymode" , item->paymode); + hb_xml_append_int(node, "paymode" , item->paymode); g_string_append(node, "/>\n"); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } list = g_list_next(list); } g_list_free(lasg); g_string_free(node, TRUE); + return retval; } @@@ -1083,10 -1384,12 +1389,12 @@@ /* ** XML archive save */ - static void homebank_save_xml_arc(GIOChannel *io) + static gint homebank_save_xml_arc(GIOChannel *io) { GList *list; GString *node; + gint retval = XML_OK; + GError *error = NULL; node = g_string_sized_new(255); @@@ -1101,6 -1404,7 +1409,7 @@@ hb_xml_append_int(node, "account", item->kacc); hb_xml_append_int(node, "dst_account", item->kxferacc); hb_xml_append_int(node, "paymode", item->paymode); + hb_xml_append_int(node, "st", item->status); hb_xml_append_int(node, "flags", item->flags); hb_xml_append_int(node, "payee", item->kpay); hb_xml_append_int(node, "category", item->kcat); @@@ -1111,74 -1415,125 +1420,125 @@@ hb_xml_append_int(node, "limit", item->limit); hb_xml_append_int(node, "weekend", item->weekend); + if(da_splits_count(item->splits) > 0) + { + gchar *cats, *amounts, *memos; + + da_splits_tostring(item->splits, &cats, &amounts, &memos); + g_string_append_printf(node, "scat=\"%s\" ", cats); + g_string_append_printf(node, "samt=\"%s\" ", amounts); + + //fix #1173910 + gchar *escaped = g_markup_escape_text(memos, -1); + g_string_append_printf(node, "smem=\"%s\" ", escaped); + g_free(escaped); + + g_free(cats); + g_free(amounts); + g_free(memos); + } + g_string_append(node, "/>\n"); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } + list = g_list_next(list); } g_string_free(node, TRUE); + return retval; } /* ** XML transaction save */ - static void homebank_save_xml_ope(GIOChannel *io) + static gint homebank_save_xml_ope(GIOChannel *io) { + GList *lst_acc, *lnk_acc; GList *list; GString *node; gchar *tagstr; + gint retval = XML_OK; + GError *error = NULL; node = g_string_sized_new(255); - list = g_list_first(GLOBALS->ope_list); - while (list != NULL) + lst_acc = g_hash_table_get_values(GLOBALS->h_acc); + lnk_acc = g_list_first(lst_acc); + while (lnk_acc != NULL) { - Transaction *item = list->data; + Account *acc = lnk_acc->data; - item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED); //remove flag - tagstr = transaction_tags_tostring(item); + list = g_queue_peek_head_link(acc->txn_queue); + while (list != NULL) + { + Transaction *item = list->data; - g_string_assign(node, "date); - hb_xml_append_amt(node, "amount", item->amount); - hb_xml_append_int(node, "account", item->kacc); - hb_xml_append_int(node, "dst_account", item->kxferacc); - hb_xml_append_int(node, "paymode", item->paymode); - hb_xml_append_int(node, "flags", item->flags); - hb_xml_append_int(node, "payee", item->kpay); - hb_xml_append_int(node, "category", item->kcat); - hb_xml_append_txt(node, "wording", item->wording); - hb_xml_append_txt(node, "info", item->info); - hb_xml_append_txt(node, "tags", tagstr); - hb_xml_append_int(node, "kxfer", item->kxfer); + item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED); //delete flag + tagstr = transaction_tags_tostring(item); - if(da_transaction_splits_count(item) > 0) + g_string_assign(node, "date); + hb_xml_append_amt(node, "amount", item->amount); + hb_xml_append_int(node, "account", item->kacc); + hb_xml_append_int(node, "dst_account", item->kxferacc); + hb_xml_append_int(node, "paymode", item->paymode); + hb_xml_append_int(node, "st", item->status); + hb_xml_append_int(node, "flags", item->flags); + hb_xml_append_int(node, "payee", item->kpay); + hb_xml_append_int(node, "category", item->kcat); + hb_xml_append_txt(node, "wording", item->wording); + hb_xml_append_txt(node, "info", item->info); + hb_xml_append_txt(node, "tags", tagstr); + hb_xml_append_int(node, "kxfer", item->kxfer); + + if(da_splits_count(item->splits) > 0) { - gchar *cats, *amounts, *memos; + gchar *cats, *amounts, *memos; - transaction_splits_tostring(item, &cats, &amounts, &memos); - g_string_append_printf(node, "scat=\"%s\" ", cats); - g_string_append_printf(node, "samt=\"%s\" ", amounts); - - //fix #1173910 - gchar *escaped = g_markup_escape_text(memos, -1); - g_string_append_printf(node, "smem=\"%s\" ", escaped); - g_free(escaped); + da_splits_tostring(item->splits, &cats, &amounts, &memos); + g_string_append_printf(node, "scat=\"%s\" ", cats); + g_string_append_printf(node, "samt=\"%s\" ", amounts); + + //fix #1173910 + gchar *escaped = g_markup_escape_text(memos, -1); + g_string_append_printf(node, "smem=\"%s\" ", escaped); + g_free(escaped); + + g_free(cats); + g_free(amounts); + g_free(memos); + } - g_free(cats); - g_free(amounts); - g_free(memos); - } + g_string_append(node, "/>\n"); - g_string_append(node, "/>\n"); + g_free(tagstr); + + error = NULL; + g_io_channel_write_chars(io, node->str, -1, NULL, &error); + + if(error) + { + retval = XML_IO_ERROR; + g_error_free(error); + } - g_free(tagstr); - g_io_channel_write_chars(io, node->str, -1, NULL, NULL); - list = g_list_next(list); + list = g_list_next(list); + } + + lnk_acc = g_list_next(lnk_acc); } + g_list_free(lst_acc); + g_string_free(node, TRUE); + return retval; } /* @@@ -1190,33 -1545,36 +1550,39 @@@ GIOChannel *io char buf1[G_ASCII_DTOSTR_BUF_SIZE]; gchar *outstr; gint retval = XML_OK; + GError *error = NULL; + GValue filename_val = G_VALUE_INIT; + ext_hook("save_file", EXT_STRING(&filename_val, filename), NULL); + - io = g_io_channel_new_file(filename, "w", NULL); + io = g_io_channel_new_file(filename, "w", &error); if(io == NULL) { g_message("file error on: %s", filename); retval = XML_IO_ERROR; + + if(error) + g_print("failed: %s\n", error->message); + + g_error_free(error); } else { g_io_channel_write_chars(io, "\n", -1, NULL, NULL); - outstr = g_strdup_printf("\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION)); + outstr = g_strdup_printf("\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION), HB_VERSION_NUM); g_io_channel_write_chars(io, outstr, -1, NULL, NULL); g_free(outstr); - homebank_save_xml_prop(io); - //homebank_save_xml_cur(io); - homebank_save_xml_acc(io); - homebank_save_xml_pay(io); - homebank_save_xml_cat(io); - homebank_save_xml_tag(io); - homebank_save_xml_asg(io); - homebank_save_xml_arc(io); - homebank_save_xml_ope(io); + retval = homebank_save_xml_prop(io); + retval = homebank_save_xml_cur(io); + retval = homebank_save_xml_acc(io); + retval = homebank_save_xml_pay(io); + retval = homebank_save_xml_cat(io); + retval = homebank_save_xml_tag(io); + retval = homebank_save_xml_asg(io); + retval = homebank_save_xml_arc(io); + retval = homebank_save_xml_ope(io); g_io_channel_write_chars(io, "\n", -1, NULL, NULL); diff --combined src/homebank.c index 106b8ec,421d0ef..c8a6895 --- a/src/homebank.c +++ b/src/homebank.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -18,12 -18,13 +18,14 @@@ */ #include "homebank.h" +#include "ext.h" #include "dsp_mainwindow.h" #include "hb-preferences.h" #include "language.h" + + #ifdef G_OS_WIN32 #include #endif @@@ -53,7 -54,6 +55,7 @@@ static gchar *pixmaps_dir = NULL static gchar *locale_dir = NULL; static gchar *help_dir = NULL; static gchar *datas_dir = NULL; +static gchar *pkglib_dir = NULL; //#define MARKUP_STRING "%s" @@@ -157,25 -157,26 +159,26 @@@ static gint csvtype[7] = /* is it csv homebank ? */ else { - gboolean hbcsv; + gchar **str_array; + gboolean isvalid = FALSE; - hbcsv = hb_string_csv_valid(tmpstr, 8, csvtype); + hb_string_strip_crlf(tmpstr); + str_array = hb_csv_row_get(tmpstr, ";", 8); + isvalid = hb_csv_row_valid(str_array, 8, csvtype); - DB( g_print(" hbcsv %d\n", hbcsv) ); + DB( g_print(" hbcsv %d\n", isvalid) ); - if( hbcsv == TRUE ) + if( isvalid == TRUE ) { DB( g_print(" type is CSV homebank\n") ); retval = FILETYPE_CSV_HB; } - + g_strfreev (str_array); } - g_free(tmpstr); } } - } g_io_channel_unref (io); } @@@ -187,21 -188,26 +190,26 @@@ /* = = = = = = = = = = = = = = = = = = = = */ - - /* ** ensure the filename ends with '.xhb' */ - void homebank_file_ensure_xhb(void) + void homebank_file_ensure_xhb(gchar *filename) { - gchar *newfilepath; - DB( g_print("\n[homebank] file_ensure_xhb\n") ); - - newfilepath = hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb"); - hbfile_change_filepath(newfilepath); - - DB( g_print("- out: %s\n", GLOBALS->xhb_filepath) ); + filename = (filename == NULL) ? g_strdup(GLOBALS->xhb_filepath) : filename; + if( g_str_has_suffix (filename, ".xhb") == FALSE ) + { + gchar *newfilename; + + newfilename = hb_util_filename_new_with_extension(filename, "xhb"); + hbfile_change_filepath(newfilename); + DB( g_print(" - changed to: '%s'\n", GLOBALS->xhb_filepath) ); + } + //#1460390 + else + { + hbfile_change_filepath(filename); + } } @@@ -218,51 -224,32 +226,32 @@@ gboolean retval = FALSE { retval = TRUE; } + g_free(buffer); } return retval; } - - void homebank_backup_current_file(gchar *pathname) + void homebank_backup_current_file(void) { - gchar *basename; - gchar *dirname; - gchar *filename; - gchar *newname; - gchar **str_array; + gchar *bakfilename; DB( g_print("\n[homebank] backup_current_file\n") ); - basename = g_path_get_basename(pathname); - dirname = g_path_get_dirname (pathname); - - if( g_str_has_suffix(basename, ".xhb") ) + bakfilename = hb_util_filename_new_with_extension (GLOBALS->xhb_filepath, "xhb~"); + if( g_file_test(bakfilename, G_FILE_TEST_EXISTS) ) { - str_array = g_strsplit(basename, ".", 0); - filename = g_strdup_printf("%s.xhb~", str_array[0]); - newname = g_build_filename(dirname, filename, NULL); - g_free(filename); - - if( g_file_test(newname, G_FILE_TEST_EXISTS) ) - { - DB( g_print("- remove existing: %s\n", newname) ); - g_remove(newname); - } - - DB( g_print("- copy %s => %s\n", pathname, newname) ); - - homebank_copy_file (pathname, newname); - //#512046 - //retval = g_rename(pathname, newname); + DB( g_print(" - delete existing: '%s'\n", bakfilename) ); + g_remove(bakfilename); + } - //DB( g_print("retval %d\n", retval) ); + DB( g_print(" - copy '%s' => '%s'\n", GLOBALS->xhb_filepath, bakfilename) ); - g_strfreev(str_array); - g_free(newname); - } - g_free(basename); - g_free(dirname); + //#512046 copy file not to broke potential links + //retval = g_rename(pathname, newname); + homebank_copy_file (GLOBALS->xhb_filepath, bakfilename); + + g_free(bakfilename); } /* = = = = = = = = = = = = = = = = = = = = */ @@@ -287,7 -274,7 +276,7 @@@ gchar *errmsg errmsg = g_win32_error_message(retval); DB( g_print ("%s\n", errmsg) ); g_free(errmsg); - + return FALSE; } @@@ -357,25 -344,25 +346,25 @@@ gchar *group, *filename, *lastfilename filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL ); - DB( g_print(" -> filename: %s\n", filename) ); + DB( g_print(" - filename: %s\n", filename) ); if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL)) { group = "HomeBank"; - DB( g_print(" -> load keyfile ok\n") ); + DB( g_print(" - load keyfile ok\n") ); if(g_key_file_has_key(keyfile, group, "LastOpenedFile", NULL)) { - DB( g_print(" -> keyfile has key ok\n") ); + DB( g_print(" - keyfile has key ok\n") ); lastfilename = g_key_file_get_string (keyfile, group, "LastOpenedFile", NULL); - DB( g_print(" -> lastfile loaded: %s\n", lastfilename ) ); + DB( g_print(" - lastfile loaded: %s\n", lastfilename ) ); // #593082 if (g_file_test (lastfilename, G_FILE_TEST_EXISTS) != FALSE) { - DB( g_print(" -> file exists\n") ); + DB( g_print(" - file exists\n") ); hbfile_change_filepath(lastfilename); @@@ -387,7 -374,7 +376,7 @@@ g_key_file_free (keyfile); } - DB( g_print(" -> return: %d\n", retval) ); + DB( g_print(" - return: %d\n", retval) ); return retval; } @@@ -407,10 -394,11 +396,11 @@@ gsize length if( GLOBALS->xhb_filepath != NULL ) { - keyfile = g_key_file_new(); if(keyfile ) { + DB( g_print(" - saving '%s'\n", GLOBALS->xhb_filepath) ); + group = "HomeBank"; g_key_file_set_string (keyfile, group, "LastOpenedFile", GLOBALS->xhb_filepath); @@@ -434,173 -422,106 +424,106 @@@ /* = = = = = = = = = = = = = = = = = = = = */ /* Main homebank */ + #ifdef G_OS_WIN32 + static GtkCssProvider *provider; + static void + homebank_theme_changed (GtkSettings *settings, GParamSpec *pspec, gpointer data) + { + if (pspec == NULL || g_str_equal (pspec->name, "gtk-theme-name")) + { + gchar *theme; + GdkScreen *screen; - static void free_list_pixbuf(void) - { - guint i; + g_object_get (settings, "gtk-theme-name", &theme, NULL); + screen = gdk_screen_get_default (); - DB( g_print("\n[homebank] free_list_pixbuf\n") ); + DB( g_print("theme %s\n", theme) ); - for(i=0;ilst_pixbuf[i] != NULL) + if (g_str_equal (theme, "gtk-win32")) { - g_object_unref(GLOBALS->lst_pixbuf[i]); - } - } - } + if (provider == NULL) + { + gchar *filename; - static void load_list_pixbuf(void) - { - GdkPixbuf *pixbuf; - guint i; - GtkWidget *cellview; - - DB( g_print("\n[homebank] load_list_pixbuf\n") ); - - cellview = gtk_cell_view_new (); - - /* list added (account/transaction list) */ - pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_NEW, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_ADD] = pixbuf; - - /* list scheduled (archive list) */ - pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_AUTO, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_AUTO] = pixbuf; - - /* list edited (account/transaction list) */ - pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_EDIT] = pixbuf; - - /* list remind (transaction list) */ - pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_REMIND, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_REMIND] = pixbuf; - - /* list reconciled (transaction list) */ - pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_VALID, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_VALID] = pixbuf; - - /* list warning (import transaction list) */ - pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU, NULL); - //g_object_unref(pixbuf); - GLOBALS->lst_pixbuf[LST_PIXBUF_WARNING] = pixbuf; - - GLOBALS->lst_pixbuf_maxwidth = 0; - for(i=0;ilst_pixbuf[i] != NULL ) - GLOBALS->lst_pixbuf_maxwidth = MAX(GLOBALS->lst_pixbuf_maxwidth, gdk_pixbuf_get_width(GLOBALS->lst_pixbuf[i]) ); + filename = g_build_filename(homebank_app_get_datas_dir(), "homebank-gtk-win32.css", NULL ); + DB( g_print("tweak file %s\n", filename) ); - } + if( g_file_test(filename, G_FILE_TEST_EXISTS) ) + { + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_path (provider, filename, NULL); + } + g_free (filename); + } - DB( g_print(" -> pixbuf list maxwidth: %d\n", GLOBALS->lst_pixbuf_maxwidth) ); + if(provider != NULL) + { + DB( g_print(" assign provider %p to screen %p\n", provider, screen) ); - gtk_widget_destroy (cellview); + gtk_style_context_add_provider_for_screen (screen, + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + } + else if (provider != NULL) + { + gtk_style_context_remove_provider_for_screen (screen, + GTK_STYLE_PROVIDER (provider)); + g_clear_object (&provider); + } + g_free (theme); + } } - static void - homebank_register_stock_icons() + homebank_setup_theme_extensions (void) { - DB( g_print("\n[homebank] register_stock_icons\n") ); + GtkSettings *settings; - GtkIconFactory *factory; - GtkIconSet *icon_set; - GtkIconSource *icon_source; - guint i; + settings = gtk_settings_get_default (); + provider = NULL; + g_signal_connect (settings, "notify", G_CALLBACK (homebank_theme_changed), NULL); + homebank_theme_changed (settings, NULL, NULL); + } + #endif - const char *icon_theme_items[] = - { - "hb-file-import", - "hb-file-export" - "pm-none", - "pm-ccard", - "pm-check", - "pm-cash" , - "pm-transfer", - "pm-intransfer", - "pm-dcard", - "pm-standingorder", - "pm-epayment", - "pm-deposit", - "pm-fifee", - "pm-directdebit", - "flt-inactive", - "flt-include", - "flt-exclude", - HB_STOCK_OPE_VALID, - HB_STOCK_OPE_REMIND, - HB_STOCK_OPE_AUTO, - "prf-general", - "prf-interface", - "prf-columns", - "prf-display", - "prf-euro", - "prf-report", - "prf-import", - "prf-plugins" - }; - - factory = gtk_icon_factory_new (); - - for (i = 0; i < G_N_ELEMENTS (icon_theme_items); i++) - { - icon_source = gtk_icon_source_new (); - gtk_icon_source_set_icon_name (icon_source, icon_theme_items[i]); - icon_set = gtk_icon_set_new (); - gtk_icon_set_add_source (icon_set, icon_source); - gtk_icon_source_free (icon_source); + static void + homebank_icon_theme_setup() + { + DB( g_print("\n[homebank] icon_theme_setup\n") ); - gtk_icon_factory_add (factory, icon_theme_items[i], icon_set); - gtk_icon_set_unref (icon_set); - } + GLOBALS->icontheme = gtk_icon_theme_get_default(); - //gtk_stock_add_static (icon_theme_items, G_N_ELEMENTS (icon_theme_items)); + DB( g_print(" - prepend theme search path: %s\n", homebank_app_get_pixmaps_dir()) ); + gtk_icon_theme_prepend_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir()); + //DB( g_print(" - append theme search path: %s\n", homebank_app_get_pixmaps_dir()) ); + //gtk_icon_theme_append_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir()); - gtk_icon_factory_add_default (factory); - g_object_unref (factory); #if MYDEBUG == 1 GtkIconTheme *ic = gtk_icon_theme_get_default(); + guint i; gchar **paths; - DB( g_print(" -> get default icon theme\n") ); - + DB( g_print(" - get default icon theme\n") ); + gtk_icon_theme_get_search_path(ic, &paths, NULL); for(i=0;i path %d: %s\n", i, paths[i]); + g_print(" - path %d: %s\n", i, paths[i]); } - + g_strfreev(paths); #endif - - DB( g_print(" -> adding theme search path: %s\n", homebank_app_get_pixmaps_dir()) ); - gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), homebank_app_get_pixmaps_dir()); } - /* - void homebank_window_set_icon_from_file(GtkWindow *window, gchar *filename) - { - gchar *pathfilename; - - pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), filename, NULL); - gtk_window_set_icon_from_file(GTK_WINDOW (window), pathfilename, NULL); - g_free(pathfilename); - } - */ const gchar * homebank_app_get_config_dir (void) @@@ -638,12 -559,6 +561,12 @@@ homebank_app_get_datas_dir (void return datas_dir; } +const gchar * +homebank_app_get_pkglib_dir (void) +{ + return pkglib_dir; +} + /* build package paths at runtime */ static void @@@ -660,13 -575,12 +583,13 @@@ build_package_paths (void pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "icons", NULL); help_dir = g_build_filename (prefix, "share", PACKAGE, "help", NULL); datas_dir = g_build_filename (prefix, "share", PACKAGE, "datas", NULL); + pkglib_dir = g_build_filename (prefix, "lib", PACKAGE, NULL); - #ifdef PORTABLE_APP - DB( g_print("- app is portable under windows\n") ); - config_dir = g_build_filename(prefix, "config", NULL); - #else - config_dir = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL); - #endif + #ifdef PORTABLE_APP + DB( g_print(" - app is portable under windows\n") ); + config_dir = g_build_filename(prefix, "config", NULL); + #else + config_dir = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL); + #endif g_free (prefix); #else locale_dir = g_build_filename (DATA_DIR, "locale", NULL); @@@ -674,8 -588,7 +597,8 @@@ pixmaps_dir = g_build_filename (DATA_DIR, PACKAGE, "icons", NULL); help_dir = g_build_filename (DATA_DIR, PACKAGE, "help", NULL); datas_dir = g_build_filename (DATA_DIR, PACKAGE, "datas", NULL); - config_dir = g_build_filename (g_get_user_config_dir(), HB_DATA_PATH, NULL); + pkglib_dir = g_build_filename (PKGLIB_DIR, NULL); + config_dir = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL); //#870023 Ubuntu packages the help files in "/usr/share/doc/homebank-data/help/" for some strange reason if(! g_file_test(help_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) @@@ -685,13 -598,12 +608,13 @@@ } #endif - DB( g_print("- config_dir : %s\n", config_dir) ); - DB( g_print("- images_dir : %s\n", images_dir) ); - DB( g_print("- pixmaps_dir: %s\n", pixmaps_dir) ); - DB( g_print("- locale_dir : %s\n", locale_dir) ); - DB( g_print("- help_dir : %s\n", help_dir) ); - DB( g_print("- datas_dir : %s\n", datas_dir) ); - DB( g_print("- pkglib_dir : %s\n", pkglib_dir) ); + DB( g_print(" - config_dir : %s\n", config_dir) ); + DB( g_print(" - images_dir : %s\n", images_dir) ); + DB( g_print(" - pixmaps_dir: %s\n", pixmaps_dir) ); + DB( g_print(" - locale_dir : %s\n", locale_dir) ); + DB( g_print(" - help_dir : %s\n", help_dir) ); + DB( g_print(" - datas_dir : %s\n", datas_dir) ); ++ DB( g_print(" - pkglib_dir : %s\n", pkglib_dir) ); } @@@ -726,7 -638,7 +649,7 @@@ gboolean retval = FALSE { if(g_file_set_contents(dstpath, buffer, length, NULL)) { - //g_print("sould remove %s\n", srcpath); + //g_print("sould delete %s\n", srcpath); g_remove(srcpath); retval = TRUE; } @@@ -752,47 -664,47 +675,47 @@@ gboolean exists /* check if /.config exist */ #ifndef G_OS_WIN32 configdir = g_get_user_config_dir(); - DB( g_print("- check '%s' exists\n", configdir) ); + DB( g_print(" - check '%s' exists\n", configdir) ); if(!g_file_test(configdir, G_FILE_TEST_IS_DIR)) { - DB( g_print("- creating dir\n") ); + DB( g_print(" - creating dir\n") ); g_mkdir(configdir, 0755); } #endif - + /* check for XDG .config/homebank */ configdir = homebank_app_get_config_dir(); - DB( g_print("- config_dir is: '%s'\n", configdir) ); + DB( g_print(" - config_dir is: '%s'\n", configdir) ); exists = g_file_test(configdir, G_FILE_TEST_IS_DIR); if(exists) { /* just update folder security */ - DB( g_print("- chmod 0700\n") ); + DB( g_print(" - chmod 0700\n") ); g_chmod(configdir, 0700); GLOBALS->first_run = FALSE; } else { /* create the config dir */ - DB( g_print("- create config_dir\n") ); + DB( g_print(" - create config_dir\n") ); g_mkdir(configdir, 0755); g_chmod(configdir, 0700); /* any old homedir configuration out there ? */ homedir = g_build_filename(g_get_home_dir (), ".homebank", NULL ); - DB( g_print("- homedir is: '%s'\n", homedir) ); + DB( g_print(" - homedir is: '%s'\n", homedir) ); exists = g_file_test(homedir, G_FILE_TEST_IS_DIR); if(exists) { gboolean f1, f2; /* we must do the migration properly */ - DB( g_print("- migrate old 2 files\n") ); + DB( g_print(" - migrate old 2 files\n") ); f1 = homebank_check_app_dir_migrate_file(homedir, config_dir, "preferences"); f2 = homebank_check_app_dir_migrate_file(homedir, config_dir, "lastopenedfiles"); if(f1 && f2) { - DB( g_print("- removing old dir\n") ); + DB( g_print(" - removing old dir\n") ); g_rmdir(homedir); } } @@@ -809,16 -721,11 +732,11 @@@ static void homebank_cleanup() { - DB( g_print("\n\n[homebank] cleanup\n") ); + DB( g_print("\n[homebank] cleanup\n") ); //v3.4 save windows size/position homebank_pref_save(); - free_list_pixbuf(); - free_paymode_icons(); - free_nainex_icons(); - free_pref_icons(); - hbfile_cleanup(TRUE); /* free our global datas */ @@@ -838,7 -745,6 +756,7 @@@ g_free (pixmaps_dir); g_free (locale_dir); g_free (help_dir); + g_free (pkglib_dir); } @@@ -865,29 -771,28 +783,28 @@@ static gboolean homebank_setup( hbfile_setup(TRUE); - homebank_register_stock_icons(); + homebank_icon_theme_setup(); - load_list_pixbuf(); - load_paymode_icons(); - load_nainex_icons(); - load_pref_icons(); + #ifdef G_OS_WIN32 + homebank_setup_theme_extensions(); + #endif homebank_app_date_get_julian(); #if MYDEBUG == 1 - g_print("- user_name: %s\n", g_get_user_name ()); - g_print("- real_name: %s\n", g_get_real_name ()); - g_print("- user_cache_dir: %s\n", g_get_user_cache_dir()); - g_print("- user_data_dir: %s\n", g_get_user_data_dir ()); - g_print("- user_config_dir: %s\n", g_get_user_config_dir ()); - //g_print("- system_data_dirs: %s\n", g_get_system_data_dirs ()); - //g_print("- system_config_dirs: %s\n", g_get_system_config_dirs ()); + g_print(" - user_name: %s\n", g_get_user_name ()); + g_print(" - real_name: %s\n", g_get_real_name ()); + g_print(" - user_cache_dir: %s\n", g_get_user_cache_dir()); + g_print(" - user_data_dir: %s\n", g_get_user_data_dir ()); + g_print(" - user_config_dir: %s\n", g_get_user_config_dir ()); + //g_print(" - system_data_dirs: %s\n", g_get_system_data_dirs ()); + //g_print(" - system_config_dirs: %s\n", g_get_system_config_dirs ()); - g_print("- home_dir: %s\n", g_get_home_dir ()); - g_print("- tmp_dir: %s\n", g_get_tmp_dir ()); - g_print("- current_dir: %s\n", g_get_current_dir ()); + g_print(" - home_dir: %s\n", g_get_home_dir ()); + g_print(" - tmp_dir: %s\n", g_get_tmp_dir ()); + g_print(" - current_dir: %s\n", g_get_current_dir ()); #endif @@@ -906,7 -811,7 +823,7 @@@ GtkWidget *frame, *vbox, *image //gchar *ver_string, *markup, *version; gchar *pathfilename; - DB( g_print("[homebank_construct_splash]\n") ); + DB( g_print("\n[homebank_construct_splash]\n") ); window = gtk_window_new(GTK_WINDOW_POPUP); //TOPLEVEL DONT WORK gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); @@@ -923,7 -828,7 +840,7 @@@ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add (GTK_CONTAINER (window), frame); - vbox = gtk_vbox_new (FALSE, 0); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (frame), vbox); /* @@@ -952,7 -857,7 +869,7 @@@ homebank_init_i18n (void */ setlocale (LC_ALL, ""); - + bindtextdomain (GETTEXT_PACKAGE, homebank_app_get_locale_dir ()); //#ifdef HAVE_BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); @@@ -962,7 -867,7 +879,7 @@@ /*#ifdef G_OS_WIN32 gchar *wl = g_win32_getlocale (); - DB( g_print(" -> win32 locale is '%s'\n", wl) ); + DB( g_print(" - win32 locale is '%s'\n", wl) ); g_free(wl); #endif*/ @@@ -970,7 -875,7 +887,7 @@@ int -main (int argc, char *argv[]) +main (int argc, char *argv[], char *env[]) { GOptionContext *option_context; GOptionGroup *option_group; @@@ -1042,22 -947,6 +959,22 @@@ gboolean openlast /* change the locale if a language is specified */ language_init (PREFS->language); - DB( g_print(" -> loading plugins\n") ); ++ DB( g_print(" - loading plugins\n") ); + ext_init(&argc, &argv, &env); + + GList* it; + for (it = PREFS->ext_whitelist; it; it = g_list_next(it)) { + ext_load_plugin(it->data); + } + + gchar** plugins = ext_list_plugins(); + gchar** plugins_it; + for (plugins_it = plugins; *plugins_it; ++plugins_it) { + gboolean loaded = ext_is_plugin_loaded(*plugins_it); + g_print("found plugin: %s, loaded: %d\n", *plugins_it, loaded); + } + g_strfreev(plugins); + if( PREFS->showsplash == TRUE ) { splash = homebank_construct_splash(); @@@ -1070,22 -959,12 +987,15 @@@ gtk_main_iteration (); } - /* - pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), "homebank.svg", NULL); - gtk_window_set_default_icon_from_file(pathfilename, NULL); - g_free(pathfilename); - */ - gtk_window_set_default_icon_name ("homebank"); - DB( g_print(" -> creating window\n" ) ); - + DB( g_print(" - creating window\n" ) ); mainwin = (GtkWidget *)create_hbfile_window (NULL); + GValue mainwin_val = G_VALUE_INIT; + ext_hook("create_main_window", EXT_OBJECT(&mainwin_val, mainwin), NULL); + if(mainwin) { @@@ -1132,7 -1011,7 +1042,7 @@@ gtk_main_iteration (); - DB( g_print(" -> open last file ?\n" ) ); + DB( g_print(" - open last file ?\n" ) ); // load a file ? /* load 1st file specified on commandline */ @@@ -1141,7 -1020,7 +1051,7 @@@ { if (g_file_test (files[0], G_FILE_TEST_EXISTS) != FALSE) { - DB( g_print(" -> should load %s\n", files[0] ) ); + DB( g_print(" - should load %s\n", files[0] ) ); hbfile_change_filepath(g_strdup(files[0])); ui_mainwindow_open_internal(mainwin, NULL); openlast = FALSE; @@@ -1155,7 -1034,7 +1065,7 @@@ } - DB( g_print(" -> GLOBALS->xhb_filepath: '%s'\n", GLOBALS->xhb_filepath ) ); + DB( g_print(" - GLOBALS->xhb_filepath: '%s'\n", GLOBALS->xhb_filepath ) ); if( openlast ) { @@@ -1163,20 -1042,17 +1073,24 @@@ ui_mainwindow_open_internal(mainwin, NULL); } + /* -- hack to generate a big file -- */ + + /* update the mainwin display */ ui_mainwindow_update(mainwin, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_VISUAL)); + ext_hook("enter_main_loop", NULL); + - DB( g_print(" -> gtk_main()\n" ) ); + DB( g_print(" - gtk_main()\n" ) ); + gtk_main (); + + ext_hook("exit_main_loop", NULL); } - DB( g_print(" -> unloading plugins\n") ); ++ DB( g_print(" - unloading plugins\n") ); + ext_term(); + } diff --combined src/homebank.h index 9acc5fc,de661f8..a89fc43 --- a/src/homebank.h +++ b/src/homebank.h @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -17,8 -17,8 +17,8 @@@ * along with this program. If not, see . */ - #ifndef __HOMEBANK_H__ - #define __HOMEBANK_H__ + #ifndef _HOMEBANK_H_ + #define _HOMEBANK_H_ #ifdef HAVE_CONFIG_H #include @@@ -41,6 -41,7 +41,7 @@@ #include "hb-preferences.h" #include "hb-transaction.h" + #include "hb-currency.h" #include "hb-account.h" #include "hb-archive.h" #include "hb-assign.h" @@@ -64,15 -65,20 +65,20 @@@ #define gettext_noop(str) (str) #define N_(str) gettext_noop (str) - /* = = = = = = = = */ /* = = = = = = = = = = = = = = = = */ - /* = = = = = = = = = = = = = = = = = = = = = = = = */ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ - #define HB_UNSTABLE FALSE - #define HB_VERSION "4.6.3" - #define FILE_VERSION 0.9 - #define PREF_VERSION 460 + #define HB_UNSTABLE FALSE + + #define HB_VERSION_MAJOR 5 + #define HB_VERSION_MINOR 1 + #define HB_VERSION_MICRO 2 + + #define HB_VERSION "5.1.2" + #define HB_VERSION_NUM (HB_VERSION_MAJOR*10000) + (HB_VERSION_MINOR*100) + HB_VERSION_MICRO + + #define FILE_VERSION 1.2 + #define PREF_VERSION 512 #if HB_UNSTABLE == FALSE #define PROGNAME "HomeBank" @@@ -82,6 -88,7 +88,7 @@@ #define HB_DATA_PATH "homebank_unstable" #endif + #ifdef G_OS_WIN32 #define GETTEXT_PACKAGE "homebank" #define LOCALE_DIR "locale" @@@ -97,64 -104,139 +104,139 @@@ #define ENABLE_NLS 1 #endif + /* container spacing */ - #define PHI 1.61803399 + #define SPACING_TINY 3 + #define SPACING_SMALL 6 + #define SPACING_MEDIUM 12 + #define SPACING_LARGE 18 - #define HB_MAINBOX_SPACING 12 - #define HB_BOX_SPACING 6 - #define HB_HSPACE_SPACING 18 /* used to separate dialog block */ - #define HB_TABROW_SPACING 6 - #define HB_TABCOL_SPACING 6 + #define HB_MINDATE 693596 //01/01/1900 + #define HB_MAXDATE 803533 //31/12/2200 /* widget minimum width */ #define HB_MINWIDTH_LIST 161 - #define HB_MINWIDTH_COMBO 80 + #define HB_MINHEIGHT_LIST 260 + + #define HB_MINWIDTH_SEARCH 240 + #define HB_MINWIDTH_COLUMN 48 - /* for transaction dialog */ - #define GTK_RESPONSE_ADD 1 + /* miscellaneous */ + #define PHI 1.61803399 + /* official GTK_RESPONSE are negative */ + #define GTK_RESPONSE_ADD 1 + #define GTK_RESPONSE_ADDKEEP 2 - #define HB_NUMBER_SAMPLE 20457.99 + #define HB_NUMBER_SAMPLE 1234567.89 - enum + typedef enum { FILETYPE_UNKNOW, FILETYPE_HOMEBANK, FILETYPE_OFX, FILETYPE_QIF, FILETYPE_CSV_HB, - FILETYPE_AMIGA_HB, + // FILETYPE_AMIGA_HB, NUM_FILETYPE - }; + } HbFileType; - /* - ** stock icons - */ - /* Custom HomeBank named icons */ - #define HB_STOCK_ACCOUNT "hb-account" - #define HB_STOCK_ARCHIVE "hb-archive" - #define HB_STOCK_ASSIGN "hb-assign" - #define HB_STOCK_BUDGET "hb-budget" - #define HB_STOCK_CATEGORY "hb-category" - #define HB_STOCK_PAYEE "hb-payee" - #define HB_STOCK_FILTER "hb-filter" - #define HB_STOCK_OPE_ADD "hb-ope-add" - #define HB_STOCK_OPE_HERIT "hb-ope-herit" - #define HB_STOCK_OPE_EDIT "hb-ope-edit" - #define HB_STOCK_OPE_SHOW "hb-ope-show" - #define HB_STOCK_OPE_DELETE "hb-ope-delete" - #define HB_STOCK_OPE_VALID "hb-ope-valid" - #define HB_STOCK_OPE_REMIND "hb-ope-remind" - #define HB_STOCK_OPE_AUTO "hb-ope-auto" - #define HB_STOCK_REP_STATS "hb-rep-stats" - #define HB_STOCK_REP_TIME "hb-rep-time" - #define HB_STOCK_REP_BALANCE "hb-rep-balance" - #define HB_STOCK_REP_BUDGET "hb-rep-budget" - #define HB_STOCK_REP_CAR "hb-rep-vehicle" + /* ---- icon size as defined into gtkiconfactory.c ---- */ + /* GTK_ICON_SIZE_MENU 16 + * GTK_ICON_SIZE_BUTTON 20 + * GTK_ICON_SIZE_SMALL_TOOLBAR 18 + * GTK_ICON_SIZE_LARGE_TOOLBAR 24 (default for toolbar) + * GTK_ICON_SIZE_DND 32 + * GTK_ICON_SIZE_DIALOG 48 + */ + + /* -------- named icons (Standard Icon Name) -------- */ + #define ICONNAME_NEW "document-new" + #define ICONNAME_OPEN "document-open" + #define ICONNAME_SAVE "document-save" + #define ICONNAME_SAVE_AS "document-save-as" //obsolete + #define ICONNAME_REVERT "document-revert" //obsolete + #define ICONNAME_PRINT "document-print" //unused + #define ICONNAME_PROPERTIES "document-properties" //obsolete + #define ICONNAME_CLOSE "window-close" //obsolete + #define ICONNAME_QUIT "application-exit" //obsolete + #define ICONNAME_FIND "edit-find" + #define ICONNAME_CLEAR "edit-clear" + #define ICONNAME_WARNING "dialog-warning" + #define ICONNAME_ERROR "dialog-error" + #define ICONNAME_INFO "dialog-information" + #define ICONNAME_HELP "help-browser" //obsolete + #define ICONNAME_ABOUT "help-about" //obsolete + #define ICONNAME_PREFERENCES "preferences-system" //obsolete + #define ICONNAME_REFRESH "view-refresh" + + #define ICONNAME_FOLDER "folder-symbolic" + + #define ICONNAME_LIST_ADD "list-add-symbolic" + #define ICONNAME_LIST_REMOVE "list-remove-symbolic" + + //#define ICONNAME_HB_SCHED_SKIP "media-skip-forward" + //#define ICONNAME_HB_SCHED_POST "media-playback-start" + + // custom or gnome not found + #define ICONNAME_HB_BUTTON_MENU "open-menu-symbolic" + #define ICONNAME_HB_TOGGLE_SIGN "toggle-sign-symbolic" + + + /* -------- named icons (Custom to homebank) -------- */ + #define ICONNAME_HB_CURRENCY "hb-currency" + #define ICONNAME_HB_ACCOUNT "hb-account" + #define ICONNAME_HB_ARCHIVE "hb-archive" + #define ICONNAME_HB_ASSIGN "hb-assign" + #define ICONNAME_HB_BUDGET "hb-budget" + #define ICONNAME_HB_CATEGORY "hb-category" + #define ICONNAME_HB_PAYEE "hb-payee" + #define ICONNAME_HB_OPE_SHOW "hb-ope-show" //? "view-register + #define ICONNAME_HB_REP_STATS "hb-rep-stats" + #define ICONNAME_HB_REP_TIME "hb-rep-time" + #define ICONNAME_HB_REP_BALANCE "hb-rep-balance" + #define ICONNAME_HB_REP_BUDGET "hb-rep-budget" + #define ICONNAME_HB_REP_CAR "hb-rep-vehicle" + + #define ICONNAME_HB_VIEW_LIST "hb-view-list" //"view-list-text" + #define ICONNAME_HB_VIEW_BAR "hb-view-bar" //"view-chart-bar" + #define ICONNAME_HB_VIEW_COLUMN "hb-view-column" //"view-chart-column" + #define ICONNAME_HB_VIEW_LINE "hb-view-line" //"view-chart-line" + #define ICONNAME_HB_VIEW_STACK "hb-view-stack" //"view-chart-stack" + #define ICONNAME_HB_VIEW_PIE "hb-view-pie" //"view-chart-pie" + #define ICONNAME_HB_VIEW_DONUT "hb-view-donut" //"view-chart-donut" + #define ICONNAME_HB_SHOW_LEGEND "hb-legend" //"view-legend" + #define ICONNAME_HB_SHOW_RATE "hb-rate" // obsolete ? + #define ICONNAME_HB_FILTER "hb-filter" //"edit-filter" + + #define ICONNAME_HB_FILE_IMPORT "hb-file-import" //document-import + #define ICONNAME_HB_FILE_EXPORT "hb-file-export" //document-export + #define ICONNAME_HB_FILE_VALID "hb-file-valid" + #define ICONNAME_HB_FILE_INVALID "hb-file-invalid" + + #define ICONNAME_HB_BUTTON_COLLAPSE "btn-collapse" + #define ICONNAME_HB_BUTTON_EXPAND "btn-expand" + #define ICONNAME_HB_BUTTON_SPLIT "btn-split" + + #define ICONNAME_HB_OPE_AUTO "hb-ope-auto" //? + #define ICONNAME_HB_OPE_BUDGET "hb-ope-budget" //? + #define ICONNAME_HB_OPE_ADD "hb-ope-add" //? "edit-add" + #define ICONNAME_HB_OPE_HERIT "hb-ope-herit" //? "edit-clone" + #define ICONNAME_HB_OPE_EDIT "hb-ope-edit" // + #define ICONNAME_HB_OPE_MULTIEDIT "hb-ope-multiedit" // + #define ICONNAME_HB_OPE_DELETE "hb-ope-delete" //? "edit-delete" + #define ICONNAME_CONVERT "hb-ope-convert" + #define ICONNAME_HB_ASSIGN_RUN "hb-assign-run" + + #define ICONNAME_HB_OPE_VALID "hb-ope-valid" // obsolete ? + #define ICONNAME_HB_OPE_CLEARED "hb-ope-cleared" + #define ICONNAME_HB_OPE_RECONCILED "hb-ope-reconciled" + #define ICONNAME_HB_OPE_REMIND "hb-ope-remind" + /* @@@ -163,50 -245,53 +245,53 @@@ struct HomeBank { // hbfile storage - GHashTable *h_cur; //currencies - GHashTable *h_acc; //accounts - GHashTable *h_pay; //payees - GHashTable *h_cat; //categories - GHashTable *h_tag; //tags - GHashTable *h_rul; //assign rules + GHashTable *h_cur; //currencies + GHashTable *h_acc; //accounts + GHashTable *h_pay; //payees + GHashTable *h_cat; //categories + GHashTable *h_tag; //tags + GHashTable *h_rul; //assign rules + + GHashTable *h_memo; //memo/description - GHashTable *h_memo; //memo/description + GList *arc_list; //archives - GList *arc_list; //archives - GList *ope_list; //transactions + //#1419304 we keep the deleted txn to a stack trash + GTrashStack *txn_stk; // hbfile (saved properties) - gchar *owner; - gshort auto_smode; - gshort auto_weekday; - gshort auto_nbdays; + gchar *owner; + gshort auto_smode; + gshort auto_weekday; + gshort auto_nbdays; - guint32 vehicle_category; - //guint32 kcur; // base currency + guint32 vehicle_category; + guint32 kcur; // base currency // hbfile (unsaved properties) - guint changes_count; - gboolean hbfile_is_new; - gchar *xhb_filepath; - gboolean xhb_hasbak; //file has backup (*.xhb~) used for revert menu sensitivity + guint changes_count; + gboolean hbfile_is_new; + gchar *xhb_filepath; + gboolean xhb_hasbak; //file has backup (*.xhb~) used for revert menu sensitivity // really global stuffs - gboolean first_run; - guint32 today; //today's date - gint define_off; //>0 when a stat, account window is opened - gboolean minor; + gboolean first_run; + guint32 today; //today's date + gint define_off; //>0 when a stat, account window is opened + gboolean minor; - GtkWidget *mainwindow; //should be global to access attached window data - GdkPixbuf *lst_pixbuf[NUM_LST_PIXBUF]; - gint lst_pixbuf_maxwidth; + GtkWidget *mainwindow; //should be global to access attached window data + GtkIconTheme *icontheme; + //GdkPixbuf *lst_pixbuf[NUM_LST_PIXBUF]; + //gint lst_pixbuf_maxwidth; }; gint homebank_alienfile_recognize(gchar *filename); gchar *homebank_filepath_with_extention(gchar *path, gchar *extension); gchar *homebank_filename_without_extention(gchar *path); - void homebank_file_ensure_xhb(void); - void homebank_backup_current_file(gchar *pathname); + void homebank_file_ensure_xhb(gchar *filename); + void homebank_backup_current_file(void); gboolean homebank_util_url_show (const gchar *url); gboolean homebank_lastopenedfiles_load(void); gboolean homebank_lastopenedfiles_save(void); @@@ -220,13 -305,11 +305,12 @@@ const gchar *homebank_app_get_pixmaps_d const gchar *homebank_app_get_locale_dir (void); const gchar *homebank_app_get_help_dir (void); const gchar *homebank_app_get_datas_dir (void); +const gchar *homebank_app_get_pkglib_dir (void); guint32 homebank_app_date_get_julian(void); /* - - - - obsolete things - - - - */ /* - typedef struct _budget Budget; struct _budget @@@ -254,7 -337,4 +338,4 @@@ struct _investmen }; */ - - - #endif diff --combined src/ui-pref.c index 4cc1eeb,5a63a49..fa7f906 --- a/src/ui-pref.c +++ b/src/ui-pref.c @@@ -1,5 -1,5 +1,5 @@@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2014 Maxime DOYEN + * Copyright (C) 1995-2016 Maxime DOYEN * * This file is part of HomeBank. * @@@ -24,8 -24,9 +24,11 @@@ #include "dsp_mainwindow.h" #include "gtk-chart-colors.h" +#include "ext.h" + + #include "ui-currency.h" + + /****************************************************************************/ /* Debug macros */ /****************************************************************************/ @@@ -43,8 -44,7 +46,7 @@@ extern struct Preferences *PREFS enum { - LST_PREF_SMALLPIXBUF, - LST_PREF_ICON, + LST_PREF_ICONNAME, LST_PREF_NAME, LST_PREF_PAGE, LST_PREF_MAX @@@ -60,17 -60,18 +62,15 @@@ enu enum { - PREF_GENERAL, - PREF_INTERFACE, - PREF_COLUMNS, - PREF_DISPLAY, - PREF_IMPORT, - PREF_REPORT, - PREF_EURO, - PREF_MAX + EXT_COLUMN_ENABLED = 0, + EXT_COLUMN_LABEL, + EXT_COLUMN_TOOLTIP, + EXT_COLUMN_PLUGIN_NAME, + EXT_NUM_COLUMNS }; - GdkPixbuf *pref_pixbuf[PREF_MAX]; - - static gchar *pref_pixname[PREF_MAX] = { + static gchar *pref_iconname[PREF_MAX] = { "prf-general", "prf-interface", "prf-columns", @@@ -78,7 -79,6 +78,7 @@@ "prf-import", "prf-report", "prf-euro", // to be renamed +"prf-plugins", //"prf_charts.svg" }; @@@ -89,8 -89,7 +89,8 @@@ N_("Transactions") N_("Display format"), N_("Import/Export"), N_("Report"), -N_("Euro minor") +N_("Euro minor"), +N_("Plugins") // }; @@@ -103,6 -102,15 +103,15 @@@ N_("Text beside icons") NULL }; + static gchar *CYA_GRID_LINES[] = { + N_("None"), + N_("Horizontal"), + N_("Vertical"), + N_("Both"), + NULL + }; + + gchar *CYA_TANGO_COLORS[] = { "----", N_("Tango light"), @@@ -119,6 -127,7 +128,7 @@@ NUL }; gchar *CYA_IMPORT_OFXNAME[] = { + N_("Ignore"), N_("Memo"), N_("Payee"), NULL @@@ -128,6 -137,7 +138,7 @@@ gchar *CYA_IMPORT_OFXMEMO[] = N_("Ignore"), N_("Append to Info"), N_("Append to Memo"), + N_("Append to Payee"), NULL }; @@@ -143,7 -153,7 +154,7 @@@ typedef struc //gchar *prefix_symbol; /* max symbol is 3 digits in unicode */ //gchar *suffix_symbol; /* but mostly is 1 digit */ gchar *symbol; - gboolean is_prefix; + gboolean sym_prefix; gchar *decimal_char; gchar *grouping_char; gshort frac_digits; @@@ -177,24 -187,25 +188,25 @@@ static EuroParams euro_params[] /* 2007 */ { "SIT", "Slovenia" , 239.640 , "tol" , TRUE , ",", ".", 2 }, // /* 2008 */ - { "CYP", "Cyprus" , 0.585274 , "" , TRUE , ",", "" , 2 }, // - { "MTL", "Malta" , 0.429300 , "" , TRUE , ",", "" , 2 }, // + { "CYP", "Cyprus" , 0.585274 , "£" , TRUE , ",", "" , 2 }, // + { "MTL", "Malta" , 0.429300 , "Lm" , TRUE , ",", "" , 2 }, // /* 2009 */ { "SKK", "Slovaquia" , 30.12600 , "Sk" , FALSE, ",", " ", 2 }, // /* 2011 */ { "EEK", "Estonia" , 15.6466 , "kr" , FALSE, ",", " ", 2 }, // /* 2014 */ - { "LVL", "Latvia" , 0.702804 , "lat.", FALSE, ",", "" , 2 }, // 2014 target for euro earliest - + { "LVL", "Latvia" , 0.702804 , "lat.", FALSE, ",", "" , 2 }, // jan. 2014 + /* 2016 */ + { "LTL", "Lithuania" , 3.45280 , "Lt." , TRUE , ",", "" , 2 }, // jan. 2015 + /* future */ - { "CZK", "Czech republic", 28.36 , "Kč" , FALSE, ",", " ", 2 }, // non-fixé - 2015 earliest - { "HUF", "Hungary" , 261.51 , "Ft" , TRUE , ",", " ", 2 }, // non-fixé - No current target for euro - { "LTL", "Lithuania" , 3.45280 , "Lt." , TRUE , ",", "" , 2 }, // 2014 target for euro earliest - { "PLN", "Poland" , 0.25 , "zł" , FALSE, ",", "" , 2 }, // non-fixé - No current target for euro { "BGN", "Bulgaria" , 1.95583 , "лв." , TRUE , ",", " ", 2 }, // non-fixé - 2014 target for euro + { "HUF", "Hungary" , 261.51 , "Ft" , TRUE , ",", " ", 2 }, // non-fixé - No current target for euro { "RON", "Romania" , 3.5155 , "Leu" , FALSE, ",", ".", 2 }, // non-fixé - 2015 target for euro earliest + { "CZK", "Czech republic", 28.36 , "Kč" , FALSE, ",", " ", 2 }, // non-fixé - 2015 earliest { "HRK", "Croatia" , 1.0000 , "kn" , FALSE, "" , ".", 0 }, // non-fixé - 2015 target for euro earliest - + { "PLN", "Poland" , 0.25 , "zł" , FALSE, ",", "" , 2 }, // non-fixé - No current target for euro + // { " ", "" , 1.00000 , "" , "" , FALSE, ",", "", 2 }, }; @@@ -205,7 -216,6 +217,7 @@@ GtkWidget *list_txn_colprefcreate(void) static void list_txn_colpref_get(GtkTreeView *treeview, gboolean *columns); +static void list_ext_colpref_get(GtkTreeView *treeview, GList **columns); @@@ -537,57 -547,6 +549,6 @@@ const gchar *dirname } - static gchar *ui_language_combobox_get_active_id(GtkComboBox *combobox) - { - GtkTreeModel *model; - GtkTreeIter iter; - gchar *id = 0; - - if( gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combobox), &iter) ) - { - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combobox)); - gtk_tree_model_get (GTK_TREE_MODEL(model), &iter, - 0, &id, - -1); - } - - return id; - } - - - static gint ui_language_combobox_set_active_id(GtkComboBox *combobox, gchar *id) - { - GtkTreeModel *model; - GtkTreeIter iter; - gboolean valid; - gchar *tmp_id; - gint i; - - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combobox)); - valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); - i = 0; - while (valid) - { - gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, - 0, &tmp_id, - -1); - - if( tmp_id != NULL) - { - if( g_ascii_strncasecmp(id, tmp_id, -1) == 0 ) - { - gtk_combo_box_set_active_iter(combobox, &iter); - return i; - } - } - - valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); - i++; - } - return i; - } - - static GtkWidget * ui_language_combobox_new(GtkWidget *label) @@@ -607,12 -566,13 +568,13 @@@ GtkCellRenderer *renderer gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, "text", 1, NULL); + gtk_combo_box_set_id_column( GTK_COMBO_BOX(combobox), 0); + g_object_unref(store); if(label) gtk_label_set_mnemonic_widget (GTK_LABEL(label), combobox); - //gtk_widget_set_size_request(comboboxentry, HB_MINWIDTH_COMBO, -1); ui_language_combobox_populate(combobox); gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0); @@@ -626,9 -586,6 +588,6 @@@ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ - - - /* ** */ @@@ -652,53 -609,6 +611,6 @@@ guint i return combobox; } - /* - static defpref_currency_display(GtkWidget *widget, gpointer user_data) - { - struct defpref_data *data; - struct iso4217format *curfmt; - - DB( g_print("\n[ui-pref] display default currency\n") ); - - data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - - curfmt = iso4217format_get(PREFS->curr_default); - if(curfmt != NULL) - { - gchar *name = g_strdup_printf("%s (%s)", curfmt->curr_iso_code, iso4217_get_name(curfmt->curr_iso_code)); - - gtk_label_set_label (data->LB_default, name); - g_free(name); - } - - } - - - static void defpref_currency_change(GtkWidget *widget, gpointer user_data) - { - struct defpref_data *data; - struct iso4217format *curfmt; - - DB( g_print("\n[ui-pref] chnage default currency\n") ); - - data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - - curfmt = ui_cur_select_dialog_new(data->window); - - DB( g_print("(cur) return %s\n", curfmt) ); - - if( curfmt != NULL ) - { - g_free(PREFS->curr_default); - PREFS->curr_default = g_strdup(curfmt->culture); - - defpref_currency_display(widget, NULL); - } - - } - */ - - static void defpref_pathselect(GtkWidget *widget, gpointer user_data) { @@@ -777,91 -687,33 +689,33 @@@ GDate *date } - - /* - ** update the number sample label - */ - static void defpref_numberbase_sample(GtkWidget *widget, gpointer user_data) - { - struct defpref_data *data; - struct CurrencyFmt cur; - gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE]; - gchar buf[128], *ptr; - - DB( g_print("\n[ui-pref] number sample\n") ); - - data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - - cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_symbol)); - cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix)); - cur.decimal_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_decimalchar)); - cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_groupingchar)); - cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits)); - g_snprintf(cur.format, 8-1, "%%.%df", cur.frac_digits); - - ptr = cur.monfmt; - if(cur.is_prefix) - { - ptr = g_stpcpy(ptr, cur.symbol); - ptr = g_stpcpy(ptr, " "); - } - ptr = g_stpcpy(ptr, "%s"); - if(!cur.is_prefix) - { - ptr = g_stpcpy(ptr, " "); - ptr = g_stpcpy(ptr, cur.symbol); - } - - DB( g_print("fmt: %s\n", cur.format) ); - DB( g_print("monfmt: %s\n", cur.monfmt) ); - - g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, 12345.67); - - real_mystrfmon(buf, 127, formatd_buf, &cur); - gtk_label_set_text(GTK_LABEL(data->LB_numberbase), buf); - - } - /* ** update the number sample label */ static void defpref_numbereuro_sample(GtkWidget *widget, gpointer user_data) { struct defpref_data *data; - struct CurrencyFmt cur; + Currency cur; gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE]; - gchar buf[128], *ptr; + gchar buf[128]; DB( g_print("\n[ui-pref] number sample\n") ); data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_symbol)); - cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix)); + cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix)); cur.decimal_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_decimalchar)); cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_groupingchar)); cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits)); - g_snprintf(cur.format, 8-1, "%%.%df", cur.frac_digits); - - ptr = cur.monfmt; - if(cur.is_prefix) - { - ptr = g_stpcpy(ptr, cur.symbol); - ptr = g_stpcpy(ptr, " "); - } - ptr = g_stpcpy(ptr, "%s"); - if(!cur.is_prefix) - { - ptr = g_stpcpy(ptr, " "); - ptr = g_stpcpy(ptr, cur.symbol); - } + + da_cur_initformat (&cur); DB( g_print("fmt: %s\n", cur.format) ); - DB( g_print("monfmt: %s\n", cur.monfmt) ); - - g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, 12345.67); - - real_mystrfmon(buf, 127, formatd_buf, &cur); + + g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, HB_NUMBER_SAMPLE); + hb_str_formatd(buf, 127, formatd_buf, &cur, TRUE); + gtk_label_set_text(GTK_LABEL(data->LB_numbereuro), buf); } @@@ -873,27 -725,39 +727,39 @@@ static void defpref_eurotoggle(GtkWidget *widget, gpointer user_data) { struct defpref_data *data; - gboolean bool; + gboolean sensitive; DB( g_print("\n[ui-pref] euro toggle\n") ); data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); - bool = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable)); + sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable)); + + gtk_widget_set_sensitive(data->GRP_currency , sensitive); + gtk_widget_set_sensitive(data->GRP_rate , sensitive); + gtk_widget_set_sensitive(data->GRP_format , sensitive); + } + /* + ** set euro value widget from a country + */ + static void defpref_eurosetcurrency(GtkWidget *widget, gpointer user_data) + { + struct defpref_data *data; + EuroParams *euro = user_data; + gchar *buf; + + + DB( g_print("\n[ui-pref] eurosetcurrency\n") ); - gtk_widget_set_sensitive(data->CY_euro_preset , bool); - gtk_widget_set_sensitive(data->ST_euro_country , bool); - gtk_widget_set_sensitive(data->NB_euro_value , bool); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + + buf = g_strdup_printf("%s - %s", euro->iso, euro->name); - gtk_widget_set_sensitive(data->ST_euro_symbol, bool); - gtk_widget_set_sensitive(data->CM_euro_isprefix, bool); - gtk_widget_set_sensitive(data->ST_euro_decimalchar, bool); - gtk_widget_set_sensitive(data->ST_euro_groupingchar, bool); - gtk_widget_set_sensitive(data->NB_euro_fracdigits, bool); - gtk_widget_set_sensitive(data->LB_numbereuro, bool); + gtk_label_set_markup(GTK_LABEL(data->ST_euro_country), buf); + g_free(buf); } @@@ -911,27 -775,45 +777,45 @@@ gint country data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); country = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_euro_preset)); + data->country = country; - gtk_label_set_text(GTK_LABEL(data->ST_euro_country), euro_params[country].name); + defpref_eurosetcurrency(widget, &euro_params[country]); gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_value), euro_params[country].value); gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits), euro_params[country].frac_digits); gtk_entry_set_text(GTK_ENTRY(data->ST_euro_symbol) , euro_params[country].symbol); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), euro_params[country].is_prefix); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), euro_params[country].sym_prefix); gtk_entry_set_text(GTK_ENTRY(data->ST_euro_decimalchar) , euro_params[country].decimal_char); gtk_entry_set_text(GTK_ENTRY(data->ST_euro_groupingchar), euro_params[country].grouping_char); } + + static void defpref_colortoggle(GtkWidget *widget, gpointer user_data) + { + struct defpref_data *data; + gboolean sensitive; + + DB( g_print("\n[ui-pref] color toggle\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + + sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors)); + + gtk_widget_set_sensitive(data->GR_colors , sensitive); + + } + + /* ** set preset colors for amount display */ static void defpref_colorpreset(GtkWidget *widget, gpointer user_data) { struct defpref_data *data; - GdkColor color; + GdkRGBA rgba; gint preset; gchar *expcol, *inccol, *wrncol; @@@ -964,19 -846,32 +848,32 @@@ } - gdk_color_parse(expcol, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color); + gdk_rgba_parse(&rgba, expcol); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba); - gdk_color_parse(inccol, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color); + gdk_rgba_parse(&rgba, inccol); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba); - gdk_color_parse(wrncol, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color); + gdk_rgba_parse(&rgba, wrncol); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba); } + static void defpref_color_scheme_changed(GtkWidget *widget, gpointer user_data) + { + struct defpref_data *data; + + DB( g_print("\n[ui-pref] color scheme chnaged\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + + gtk_widget_queue_draw (data->DA_colors); + + } + + /* @@@ -999,24 -894,15 +896,15 @@@ guint tmp /* ** set :: fill in widgets from PREFS structure */ - static void defpref_entry_set_text(GtkWidget *widget, gchar *text) - { - DB( g_print(" set text to '%s'\n", text) ); - - if( text != NULL ) - { - gtk_entry_set_text(GTK_ENTRY(widget), text); - } - } static void defpref_set(struct defpref_data *data) { - GdkColor color; + GdkRGBA rgba; DB( g_print("\n[ui-pref] set\n") ); if(PREFS->language != NULL) - ui_language_combobox_set_active_id(GTK_COMBO_BOX(data->CY_language), PREFS->language); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(data->CY_language), PREFS->language); else gtk_combo_box_set_active (GTK_COMBO_BOX(data->CY_language), 0); @@@ -1025,16 -911,17 +913,17 @@@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors), PREFS->custom_colors); - gdk_color_parse(PREFS->color_exp, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color); + gdk_rgba_parse(&rgba, PREFS->color_exp); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba); - gdk_color_parse(PREFS->color_inc, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color); + gdk_rgba_parse(&rgba, PREFS->color_inc); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba); - gdk_color_parse(PREFS->color_warn, &color); - gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color); + gdk_rgba_parse(&rgba, PREFS->color_warn); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint), PREFS->rules_hint); + //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint), PREFS->rules_hint); + gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_gridlines), PREFS->grid_lines); gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_fiscyearday), PREFS->fisc_year_day ); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_fiscyearmonth), PREFS->fisc_year_month - 1); @@@ -1046,45 -933,36 +935,36 @@@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_load_last), PREFS->loadlast); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_append_scheduled), PREFS->appendscheduled); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_do_update_currency), PREFS->do_update_currency); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_show_splash), PREFS->showsplash); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_herit_date), PREFS->heritdate); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_hide_reconciled), PREFS->hidereconciled); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_show_remind), PREFS->showremind); /* display */ gtk_entry_set_text(GTK_ENTRY(data->ST_datefmt), PREFS->date_format); - defpref_entry_set_text(data->ST_num_symbol, PREFS->base_cur.symbol); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix), PREFS->base_cur.is_prefix); - defpref_entry_set_text(data->ST_num_decimalchar, PREFS->base_cur.decimal_char); - defpref_entry_set_text(data->ST_num_groupingchar, PREFS->base_cur.grouping_char); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits), PREFS->base_cur.frac_digits); - - //gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_numnbdec), PREFS->num_nbdecimal); - //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_numseparator), PREFS->num_separator); - //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_imperial), PREFS->imperial_unit); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_unitismile), PREFS->vehicle_unit_ismile); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_unitisgal), PREFS->vehicle_unit_isgal); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_wal), PREFS->date_range_wal); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_txn), PREFS->date_range_txn); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_datefuture_nbdays), PREFS->date_future_nbdays); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_rep), PREFS->date_range_rep); - + /* euro */ - //defpref_currency_display(data->LB_default, NULL); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable), PREFS->euro_active); //gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_euro_preset), PREFS->euro_country); - gchar *buf; - buf = g_strdup_printf("%s", euro_params[PREFS->euro_country].name); - gtk_label_set_markup(GTK_LABEL(data->ST_euro_country), buf); - g_free(buf); + + data->country = PREFS->euro_country; + defpref_eurosetcurrency(data->window, &euro_params[PREFS->euro_country]); gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_value), PREFS->euro_value); - defpref_entry_set_text(data->ST_euro_symbol, PREFS->minor_cur.symbol); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), PREFS->minor_cur.is_prefix); - defpref_entry_set_text(data->ST_euro_decimalchar, PREFS->minor_cur.decimal_char); - defpref_entry_set_text(data->ST_euro_groupingchar, PREFS->minor_cur.grouping_char); + ui_gtk_entry_set_text(data->ST_euro_symbol, PREFS->minor_cur.symbol); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), PREFS->minor_cur.sym_prefix); + ui_gtk_entry_set_text(data->ST_euro_decimalchar, PREFS->minor_cur.decimal_char); + ui_gtk_entry_set_text(data->ST_euro_groupingchar, PREFS->minor_cur.grouping_char); gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits), PREFS->minor_cur.frac_digits); @@@ -1102,8 -980,10 +982,10 @@@ /* import */ gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_datefmt), PREFS->dtex_datefmt); + gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_ofxname), PREFS->dtex_ofxname); gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_ofxmemo), PREFS->dtex_ofxmemo); - + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifmemo), PREFS->dtex_qifmemo); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifswap), PREFS->dtex_qifswap); } @@@ -1113,45 -993,24 +995,24 @@@ ** get :: fill PREFS structure from widgets */ + #define RGBA_TO_INT(x) (int)(x*255) - static void defpref_entry_get_text(GtkWidget *widget, gchar **storage) + static gchar *gdk_rgba_to_hex(GdkRGBA *rgba) { - const gchar *text; - - - DB( g_print("defpref_entry_get_text\n") ); - - DB( g_print(" storage is '%p' at '%p'\n", *storage, storage) ); - - /* free any previous string */ - if( *storage != NULL ) - { - DB( g_print(" storage was not null, freeing\n") ); - - g_free(*storage); - - } - - *storage = NULL; - - text = gtk_entry_get_text(GTK_ENTRY(widget)); - *storage = g_strdup(text); - DB( g_print(" storing %s at %p\n", *storage, storage) ); - - DB( g_print(" get text to '%s' '%s'\n", text, *storage) ); + return g_strdup_printf("#%02x%02x%02x", RGBA_TO_INT(rgba->red), RGBA_TO_INT(rgba->green), RGBA_TO_INT(rgba->blue)); } static void defpref_get(struct defpref_data *data) { - GdkColor color; + GdkRGBA rgba; const gchar *lang; DB( g_print("\n[ui-pref] get\n") ); g_free(PREFS->language); PREFS->language = NULL; - lang = ui_language_combobox_get_active_id(GTK_COMBO_BOX(data->CY_language)); + lang = gtk_combo_box_get_active_id(GTK_COMBO_BOX(data->CY_language)); if(lang != NULL) { PREFS->language = g_strdup(lang); @@@ -1162,19 -1021,20 +1023,20 @@@ PREFS->custom_colors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors)); - gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color); + gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba); g_free(PREFS->color_exp); - PREFS->color_exp = gdk_color_to_string(&color); + PREFS->color_exp = gdk_rgba_to_hex(&rgba); - gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color); + gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba); g_free(PREFS->color_inc); - PREFS->color_inc = gdk_color_to_string(&color); + PREFS->color_inc = gdk_rgba_to_hex(&rgba); - gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color); + gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba); g_free(PREFS->color_warn); - PREFS->color_warn = gdk_color_to_string(&color); + PREFS->color_warn = gdk_rgba_to_hex(&rgba); - PREFS->rules_hint = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint)); + //PREFS->rules_hint = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint)); + PREFS->grid_lines = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_gridlines)); PREFS->fisc_year_day = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fiscyearday)); PREFS->fisc_year_month = 1 + gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_fiscyearmonth)); @@@ -1184,15 -1044,18 +1046,18 @@@ g_free(PREFS->path_hbfile); PREFS->path_hbfile = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_hbfile))); - defpref_entry_get_text(data->ST_path_import, &PREFS->path_import); + ui_gtk_entry_replace_text(data->ST_path_import, &PREFS->path_import); - defpref_entry_get_text(data->ST_path_export, &PREFS->path_export); + ui_gtk_entry_replace_text(data->ST_path_export, &PREFS->path_export); PREFS->loadlast = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_load_last)); PREFS->appendscheduled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_append_scheduled)); + PREFS->do_update_currency = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_do_update_currency)); + PREFS->showsplash = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_show_splash)); PREFS->heritdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_herit_date)); PREFS->hidereconciled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_hide_reconciled)); + PREFS->showremind = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_show_remind)); //g_free(PREFS->path_navigator); //PREFS->path_navigator = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_navigator))); @@@ -1200,37 -1063,26 +1065,26 @@@ g_free(PREFS->date_format); PREFS->date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_datefmt))); - defpref_entry_get_text(data->ST_num_symbol, &PREFS->base_cur.symbol); - PREFS->base_cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix)); - defpref_entry_get_text(data->ST_num_decimalchar, &PREFS->base_cur.decimal_char); - defpref_entry_get_text(data->ST_num_groupingchar, &PREFS->base_cur.grouping_char); - PREFS->base_cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits)); - - //PREFS->num_nbdecimal = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_numnbdec)); - //PREFS->num_separator = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_numseparator)); - //PREFS->imperial_unit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_imperial)); PREFS->vehicle_unit_ismile = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_unitismile)); PREFS->vehicle_unit_isgal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_unitisgal)); PREFS->date_range_wal = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_wal)); PREFS->date_range_txn = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_txn)); + PREFS->date_future_nbdays = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_datefuture_nbdays)); PREFS->date_range_rep = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_rep)); PREFS->euro_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable)); - PREFS->euro_country = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_euro_preset)); + + PREFS->euro_country = data->country; PREFS->euro_value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_value)); //strcpy(PREFS->euro_symbol, gtk_entry_get_text(GTK_ENTRY(data->ST_euro_symbol))); //PREFS->euro_nbdec = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_nbdec)); //PREFS->euro_thsep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_thsep)); - defpref_entry_get_text(data->ST_euro_symbol, &PREFS->minor_cur.symbol); - PREFS->minor_cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix)); - - g_free(PREFS->minor_cur.decimal_char); - PREFS->minor_cur.decimal_char = g_strdup( gtk_entry_get_text(GTK_ENTRY(data->ST_euro_decimalchar)) ); - - g_free(PREFS->minor_cur.grouping_char); - PREFS->minor_cur.grouping_char = g_strdup( gtk_entry_get_text(GTK_ENTRY(data->ST_euro_groupingchar)) ); + ui_gtk_entry_replace_text(data->ST_euro_symbol, &PREFS->minor_cur.symbol); + PREFS->minor_cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix)); + ui_gtk_entry_replace_text(data->ST_euro_decimalchar, &PREFS->minor_cur.decimal_char); + ui_gtk_entry_replace_text(data->ST_euro_groupingchar, &PREFS->minor_cur.grouping_char); PREFS->minor_cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits)); PREFS->stat_byamount = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_stat_byamount)); @@@ -1243,440 -1095,448 +1097,449 @@@ /* import */ PREFS->dtex_datefmt = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_datefmt)); + PREFS->dtex_ofxname = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_ofxname)); PREFS->dtex_ofxmemo = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_ofxmemo)); - + PREFS->dtex_qifmemo = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifmemo)); + PREFS->dtex_qifswap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifswap)); //PREFS->chart_legend = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_chartlegend)); + list_ext_colpref_get(GTK_TREE_VIEW(data->PI_plugin_columns), &(PREFS->ext_whitelist)); } - /* - GtkWidget *defpref_page_charts (struct defpref_data *data) - { - GtkWidget *container; - GtkWidget *table, *label, *widget; - gint row; - - container = gtk_hbox_new(FALSE, 0); - - table = gtk_table_new (2, 2, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - widget = gtk_check_button_new_with_mnemonic (_("Show legend")); - data->CM_chartlegend = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Bar width:"), 1.0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_numeric(label, 8.0, 32.0); - //data->NB_numnbdec = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - - - return(container); - } - */ - static GtkWidget *defpref_page_import (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *hbox, *label, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (5, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - label = make_label(_("Date options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label(_("Date order:"), 0, 0.5); + GtkWidget *content_grid, *group_grid, *hbox, *label, *widget; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: Date options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Date options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; + label = make_label_widget(_("Date order:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_cycle(label, CYA_IMPORT_DATEORDER); data->CY_dtex_datefmt = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); - row++; - label = make_label(_("OFX/QFX options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + // group :: OFX/QFX options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("OFX/QFX options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; + label = make_label_widget(_("_Name field:")); + //----------------------------------------- l, r, t, b + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_cycle(label, CYA_IMPORT_OFXNAME); + data->CY_dtex_ofxname = widget; + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("_Memo field:"), 0, 0.5); + label = make_label_widget(_("_Memo field:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_cycle(label, CYA_IMPORT_OFXMEMO); data->CY_dtex_ofxmemo = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - - row++; - label = make_label(_("Files folder"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - - row++; - label = make_label(_("_Import:"), 0, 0.5); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + + // group :: QIF options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("QIF options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; + label = make_label_widget(_("Memos:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = gtk_check_button_new_with_mnemonic (_("_Import")); + data->CM_dtex_qifmemo = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + widget = gtk_check_button_new_with_mnemonic (_("_Swap with payees")); + data->CM_dtex_qifswap = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1); + + + // group :: Files folder + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Files folder")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; + label = make_label_widget(_("_Import:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); - hbox = gtk_hbox_new(FALSE, 0); - gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_hexpand (hbox, TRUE); + gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1); widget = make_string(label); data->ST_path_import = widget; + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); - widget = gtk_button_new_with_label("..."); + //widget = gtk_button_new_with_label("..."); + widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON); data->BT_path_import = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); row++; - label = make_label(_("_Export:"), 0, 0.5); + label = make_label_widget(_("_Export:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); - hbox = gtk_hbox_new(FALSE, 0); - gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_hexpand (hbox, TRUE); + gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1); widget = make_string(label); data->ST_path_export = widget; + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); - widget = gtk_button_new_with_label("..."); + //widget = gtk_button_new_with_label("..."); + widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON); data->BT_path_export = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - - return(container); + return content_grid; } + #define cube_dim 16 - - - static GtkWidget *defpref_page_reports (struct defpref_data *data) + static gboolean + draw_callback (GtkWidget *widget, + cairo_t *cr, + gpointer user_data) { - GtkWidget *container; - GtkWidget *table, *label, *widget; - gint row; + struct defpref_data *data = user_data; + gint index; + GtkColorScheme scheme; + gint w, h; + gint i, x, y; - container = gtk_vbox_new(FALSE, 0); + index = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_color_scheme)); - table = gtk_table_new (5, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); + colorscheme_init(&scheme, index); + + gtk_widget_get_size_request (widget, &w, &h); + x = y = 0; + for(i=0;iCY_daterange_rep = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - - row++; - label = make_label(_("Charts options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label(_("Color Scheme:"), 0, 0.5); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + + // group ::Charts options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Charts options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; + label = make_label_widget(_("Color scheme:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_cycle(label, (gchar **)chart_colors); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_cycle(label, chart_colors); data->CY_color_scheme = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("Statistics options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + widget = gtk_drawing_area_new (); + data->DA_colors = widget; + gtk_widget_set_size_request (widget, (1+cube_dim)*16, (1+cube_dim)*2); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); - row++; + g_signal_connect (data->DA_colors, "draw", G_CALLBACK (draw_callback), data); + + // group :: Statistics options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Statistics options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Show by _amount")); data->CM_stat_byamount = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; widget = gtk_check_button_new_with_mnemonic (_("Show _rate column")); data->CM_stat_showrate = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; widget = gtk_check_button_new_with_mnemonic (_("Show _details")); data->CM_stat_showdetail = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Budget options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); - row++; + // group :: Budget options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Budget options")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Show _details")); data->CM_budg_showdetail = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); - return(container); + return content_grid; } static GtkWidget *defpref_page_euro (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *label, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (7, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - - /* - label = make_label(_("Default currency"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label(_("Code:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_label(NULL, 0.0, 0.0); - data->LB_default = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - - - row++; - widget = gtk_button_new_with_mnemonic (_("_Change")); - data->BT_default = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - - row++; - */ - - label = make_label(_("General"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + GtkWidget *content_grid, *group_grid, *label, *widget, *expander; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: General + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("General")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; + row=1; widget = gtk_check_button_new_with_mnemonic (_("_Enable")); data->CM_euro_enable = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); + + // group :: Currency + group_grid = gtk_grid_new (); + data->GRP_currency = group_grid; + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Currency")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 4, 1); - row++; - label = make_label(_("Fill from:"), 0, 0.5); + row=1; + widget = make_label(NULL, 0.0, 0.5); + data->ST_euro_country = widget; + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1); + + //row++; + label = make_label_widget(_("_Preset:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 2, row, 1, 1); widget = make_euro_presets(label); data->CY_euro_preset = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Country:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_label(NULL, 0.0, 0.0); - data->ST_euro_country = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_margin_left (label, 2*SPACING_LARGE); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1); - row++; - label = make_label(_("Value:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_euro(label); + + // group :: Exchange rate + group_grid = gtk_grid_new (); + data->GRP_rate = group_grid; + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Exchange rate")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row=1; + label = make_label_widget("1 EUR _="); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_exchange_rate(label); data->NB_euro_value = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + + // group :: Numbers format + group_grid = gtk_grid_new (); + data->GRP_format = group_grid; + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Format")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Numbers format"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + row = 1; + widget = make_label(NULL, 0, 0.0); + data->LB_numbereuro = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1); row++; - label = make_label(_("Symbol:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + expander = gtk_expander_new_with_mnemonic(_("_Customize")); + gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 1, 1); + + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_container_add (GTK_CONTAINER (expander), group_grid); + + row = 0; + label = make_label_widget(_("_Symbol:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_string_maxlength(label, 3); data->ST_euro_symbol = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - widget = gtk_check_button_new_with_mnemonic (_("Is prefix")); + widget = gtk_check_button_new_with_mnemonic (_("Is pre_fix")); data->CM_euro_isprefix = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("Decimal char:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + label = make_label_widget(_("_Decimal char:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_string_maxlength(label, 1); data->ST_euro_decimalchar = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Grouping char:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string_maxlength(label, 1); - data->ST_euro_groupingchar = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("_Frac digits:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + label = make_label_widget(_("_Frac digits:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_numeric(label, 0.0, 6.0); data->NB_euro_fracdigits = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(NULL, 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_label(NULL, 0, 0.5); - data->LB_numbereuro = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - /* - row++; - label = make_label(_("_Frac digits:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_numeric(label, 0.0, 6.0); - data->NB_euro_nbdec = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - row++; - widget = gtk_check_button_new_with_mnemonic (_("Thousand separator")); - data->CM_euro_thsep = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("Symbol:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string_maxlength(label, 8); - data->ST_euro_symbol = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - */ + label = make_label_widget(_("_Grouping char:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_string_maxlength(label, 1); + data->ST_euro_groupingchar = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); - return(container); + return content_grid; } - /* - GtkWidget *defpref_page_help (struct defpref_data *data) - { - GtkWidget *container; - GtkWidget *table, *label, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (2, 2, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - label = make_label(_("Web navigator"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label("", 0.0, 0.5); - gtk_misc_set_padding (GTK_MISC (label), HB_BOX_SPACING, 0); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - label = make_label(_("Web _navigator to use:"), 1.0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string(label); - data->ST_path_navigator = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - - - - return(container); - } - */ - static GtkWidget *defpref_page_display (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *label, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); + GtkWidget *content_grid, *group_grid, *label, *widget, *expander; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: Date options + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Date")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - table = gtk_table_new (7, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); + row = 1; + widget = make_label(NULL, 0, 0.5); + data->LB_date = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); + row++; + expander = gtk_expander_new_with_mnemonic(_("_Customize")); + gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 1, 1); - row = 0; - label = make_label(_("Date options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_container_add (GTK_CONTAINER (expander), group_grid); - row++; - label = make_label(_("_Date format:"), 0, 0.5); + row = 1; + label = make_label_widget(_("_Format:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_string(label); data->ST_datefmt = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + + widget = gtk_image_new_from_icon_name (ICONNAME_INFO, GTK_ICON_SIZE_BUTTON); + gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1); + gtk_widget_set_tooltip_text(widget, _("%a locale's abbreviated weekday name.\n" "%A locale's full weekday name. \n" @@@ -1694,331 -1554,280 +1557,280 @@@ "%Y year with century as a decimal number. \n") ); - - row++; - label = make_label(NULL, 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_label(NULL, 0, 0.5); - data->LB_date = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Numbers options"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label(_("Symbol:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string_maxlength(label, 3); - data->ST_num_symbol = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - widget = gtk_check_button_new_with_mnemonic (_("Is prefix")); - data->CM_num_isprefix = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Decimal char:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string_maxlength(label,1); - data->ST_num_decimalchar = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("Grouping char:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_string_maxlength(label, 1); - data->ST_num_groupingchar = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(_("_Frac digits:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - #if MYDEBUG - widget = make_numeric(label, 0.0, 15.0); - #else - widget = make_numeric(label, 0.0, 6.0); - #endif - data->NB_num_fracdigits = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - label = make_label(NULL, 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_label(NULL, 0, 0.5); - data->LB_numberbase = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - /* obsolete */ - - /* - row++; - label = make_label(_("_Frac digits:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - widget = make_numeric(label, 0.0, 6.0); - data->NB_numnbdec = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; - widget = gtk_check_button_new_with_mnemonic (_("_Thousand separator")); - data->CM_numseparator = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); - */ - row++; - label = make_label(_("Measurement units"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + widget = make_label(NULL, 0.0, 0.5); + gtk_label_set_markup (GTK_LABEL(widget), "online reference"); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); - /*row++; - widget = gtk_check_button_new_with_mnemonic (_("Use _Imperial units")); - data->CM_imperial = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);*/ + // group :: Measurement units + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Measurement units")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Use _miles for meter")); data->CM_unitismile = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; - widget = gtk_check_button_new_with_mnemonic (_("Use _galons for fuel")); + widget = gtk_check_button_new_with_mnemonic (_("Use _gallon for fuel")); data->CM_unitisgal = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); - return(container); + return content_grid; } static GtkWidget *defpref_page_transactions (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *label, *sw, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (3, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, TRUE, TRUE, 0); - - row = 0; - label = make_label(_("Transaction window"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + GtkWidget *content_grid, *group_grid, *sw, *label, *widget; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: Transaction window + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Transaction window")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Date _range:"), 0, 0.5); + row = 1; + label = make_label_widget(_("Date _range:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_daterange(label, FALSE); data->CY_daterange_txn = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - widget = gtk_check_button_new_with_mnemonic (_("Hide reconciled transactions")); - data->CM_hide_reconciled = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + label = make_label_widget(_("_Show:")); + //----------------------------------------- l, r, t, b + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_numeric(NULL, 0, 366); + + data->ST_datefuture_nbdays = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + //TRANSLATORS: there is a spinner on the left of this label, and so you have 0....x days in advance the current date + label = make_label(_("days in advance the current date"), 0, 0.5); + gtk_grid_attach (GTK_GRID (group_grid), label, 3, row, 1, 1); row++; - label = make_label(_("Multiple add"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + widget = gtk_check_button_new_with_mnemonic (_("Hide reconciled transactions")); + data->CM_hide_reconciled = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1); row++; + widget = gtk_check_button_new_with_mnemonic (_("Always show remind transactions")); + data->CM_show_remind = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1); + + // group :: Multiple add + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Multiple add")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Keep the last date")); data->CM_herit_date = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); + // group :: Column list + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Column list")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Column list"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - row++; + row = 1; sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); widget = (GtkWidget *)list_txn_colprefcreate(); data->LV_opecolumns = widget; + gtk_widget_set_size_request(data->LV_opecolumns, HB_MINWIDTH_LIST, -1); gtk_container_add (GTK_CONTAINER (sw), widget); + gtk_widget_set_vexpand (sw, TRUE); + gtk_grid_attach (GTK_GRID (group_grid), sw, 1, row, 2, 1); gtk_widget_set_tooltip_text(widget, _("Drag & drop to change the order")); - gtk_table_attach (GTK_TABLE (table), sw, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); - - return(container); + return content_grid; } static GtkWidget *defpref_page_interface (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *hbox, *label, *widget; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (6, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - label = make_label(_("Language"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + GtkWidget *content_grid, *group_grid, *hbox, *label, *widget; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: General + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("General")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("_Language:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + row = 1; + label = make_label_widget(_("_Language:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = ui_language_combobox_new(label); data->CY_language = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("General"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; - label = make_label(_("_Toolbar:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + label = make_label_widget(_("_Toolbar:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_cycle(label, CYA_TOOLBAR_STYLE); data->CY_toolbar = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); - /* - row++; - label = make_label(_("_Size:"), 0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING); - gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - - widget = make_numeric(label, 16.0, 48.0); - data->NB_image_size = widget; - gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - label = make_label(_("pixels"), 0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - */ - - row++; - label = make_label(_("Treeview"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); row++; - widget = gtk_check_button_new_with_mnemonic (_("Show rules hint")); - data->CM_ruleshint = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + //widget = gtk_check_button_new_with_mnemonic (_("Enable rows in alternating colors")); + //data->CM_ruleshint = widget; + label = make_label_widget(_("_Grid line:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + widget = make_cycle(label, CYA_GRID_LINES); + data->CY_gridlines = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + // group :: Amount colors + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Amount colors")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Amount colors"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); - - row++; + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Uses custom colors")); data->CM_custom_colors = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + + group_grid = gtk_grid_new (); + data->GR_colors = group_grid; + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); row++; - label = make_label(_("_Preset:"), 0, 0.5); + label = make_label_widget(_("_Preset:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_cycle(label, CYA_TANGO_COLORS); data->CY_colors = widget; - //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1); - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); row++; - label = make_label(_("_Expense:"), 0, 0.5); + label = make_label_widget(_("_Expense:")); //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING); - gtk_table_attach_defaults (GTK_TABLE (table), hbox, 2, 3, row, row+1); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL); + gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1); widget = gtk_color_button_new (); data->CP_exp_color = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - label = make_label(_("_Income:"), 0, 0.5); + label = make_label_widget(_("_Income:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); widget = gtk_color_button_new (); data->CP_inc_color = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - label = make_label(_("_Warning:"), 0, 0.5); + label = make_label_widget(_("_Warning:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); widget = gtk_color_button_new (); data->CP_warn_color = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - - return(container); + return content_grid; } + static GtkWidget *defpref_page_general (struct defpref_data *data) { - GtkWidget *container; - GtkWidget *table, *label, *widget, *hbox; - gint row; - - container = gtk_vbox_new(FALSE, 0); - - table = gtk_table_new (4, 3, FALSE); - //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING); - gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING); - gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING); - - gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0); - - row = 0; - label = make_label(_("Program start"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + GtkWidget *content_grid, *group_grid, *hbox, *label, *widget; + gint crow, row; + + content_grid = gtk_grid_new(); + gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE); + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL); + + crow = 0; + // group :: Program start + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Program start")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; + row = 1; widget = gtk_check_button_new_with_mnemonic (_("Show splash screen")); data->CM_show_splash = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; widget = gtk_check_button_new_with_mnemonic (_("Load last opened file")); data->CM_load_last = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; widget = gtk_check_button_new_with_mnemonic (_("Post pending scheduled transactions")); data->CM_append_scheduled = widget; - gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); - + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); row++; - label = make_label(_("Fiscal year"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + widget = gtk_check_button_new_with_mnemonic (_("Update currencies online")); + data->CM_do_update_currency = widget; + gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1); - row++; + // group :: Fiscal year + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Fiscal year")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); + + row = 1; //TRANSLATORS: (fiscal year) starts on - label = make_label(_("Starts _on:"), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + label = make_label_widget(_("Starts _on:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); - hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING); - gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL); + gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1); widget = make_numeric (label, 1, 28); data->NB_fiscyearday = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); @@@ -2026,241 -1835,52 +1838,248 @@@ data->CY_fiscyearmonth = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - row++; - label = make_label(_("Main window reports"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + // group :: Main window reports + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Main window reports")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Date _range:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + row = 1; + label = make_label_widget(_("Date _range:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); widget = make_daterange(label, FALSE); data->CY_daterange_wal = widget; - gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); + // group :: Files folder + group_grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL); + gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM); + gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1); + + label = make_label_group(_("Files folder")); + gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1); - row++; - label = make_label(_("Files folder"), 0.0, 0.5); - gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); - gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1); + row = 1; + label = make_label_widget(_("_Default:")); + gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); - row++; - label = make_label(_("_Default:"), 0, 0.5); - //----------------------------------------- l, r, t, b - gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - - hbox = gtk_hbox_new(FALSE, 0); - gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_hexpand (hbox, TRUE); + gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1); widget = make_string(label); data->ST_path_hbfile = widget; + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); - widget = gtk_button_new_with_label("..."); + //widget = gtk_button_new_with_label("..."); + widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON); data->BT_path_hbfile = widget; gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); - - return(container); + return content_grid; } + +void plugin_execute_action(GtkTreeView* treeview, GtkTreePath* path, GtkTreeViewColumn* col, gpointer userdata); + +static void +toggle_plugin(GtkCellRendererToggle *cell, gchar* path_str, gpointer data) +{ + GtkTreeModel *model = (GtkTreeModel*)data; + GtkTreeIter iter; + GtkTreePath *path = gtk_tree_path_new_from_string(path_str); + + const gchar* plugin; + + gtk_tree_model_get_iter(model, &iter, path); + gtk_tree_model_get(model, &iter, EXT_COLUMN_PLUGIN_NAME, &plugin, -1); + + gboolean enabled = ext_is_plugin_loaded(plugin); + if (enabled) { + ext_unload_plugin(plugin); + enabled = FALSE; + } else { + enabled = (ext_load_plugin(plugin) == 0); + if (!enabled) { + ext_run_modal(_("Plugin Error"), _("The plugin failed to load properly."), "error"); + } + } + + /* set new value */ + gtk_list_store_set(GTK_LIST_STORE (model), &iter, EXT_COLUMN_ENABLED, enabled, -1); + + /* clean up */ + gtk_tree_path_free(path); +} + + +void plugin_execute_action(GtkTreeView* treeview, GtkTreePath* path, GtkTreeViewColumn* col, gpointer userdata) +{ + GtkTreeModel* model = gtk_tree_view_get_model(treeview); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(model, &iter, path)) { + gchar* plugin_filename; + gtk_tree_model_get(model, &iter, EXT_COLUMN_PLUGIN_NAME, &plugin_filename, -1); + ext_execute_action(plugin_filename); + g_free(plugin_filename); + } +} + +static GtkWidget *defpref_page_plugins (struct defpref_data *data) +{ + GtkWidget *container; + GtkListStore *store; + GtkTreeIter it; + GtkWidget* view; + + container = gtk_vbox_new(FALSE, 0); + + store = gtk_list_store_new(EXT_NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + gchar** plugins = ext_list_plugins(); + gchar** plugins_it; + for (plugins_it = plugins; *plugins_it; ++plugins_it) { + + gboolean enabled = ext_is_plugin_loaded(*plugins_it); + GHashTable* metadata = ext_read_plugin_metadata(*plugins_it); + if (!metadata) { + metadata = g_hash_table_new(g_str_hash, g_str_equal); + } + + gchar* tmp = NULL; + + // NAME + gchar* name = g_hash_table_lookup(metadata, "name"); + if (!name || *name == '\0') { + name = *plugins_it; + } + name = g_markup_escape_text(name, -1); + gchar* label = g_strdup_printf("%s", name); + gchar* tooltip = g_strdup_printf("%s", name); + g_free(name); + + // VERSION + gchar* version = g_hash_table_lookup(metadata, "version"); + if (version) { + version = g_markup_escape_text(version, -1); + tmp = label; + label = g_strdup_printf("%s %s", tmp, version); + g_free(tmp); + tmp = tooltip; + tooltip = g_strdup_printf("%s %s", tmp, version); + g_free(tmp); + g_free(version); + } + + // ABSTRACT + gchar* abstract = g_hash_table_lookup(metadata, "abstract"); + if (abstract) { + abstract = g_markup_escape_text(abstract, -1); + tmp = label; + label = g_strdup_printf("%s\n%s", tmp, abstract); + g_free(tmp); + g_free(abstract); + } + + // AUTHOR + gchar* author = g_hash_table_lookup(metadata, "author"); + if (author) { + author = g_markup_escape_text(author, -1); + tmp = tooltip; + tooltip = g_strdup_printf("%s\n%s", tmp, author); + g_free(tmp); + g_free(author); + } + + // WEBSITE + gchar* website = g_hash_table_lookup(metadata, "website"); + if (website) { + website = g_markup_escape_text(website, -1); + tmp = tooltip; + tooltip = g_strdup_printf("%s\n%s: %s", tmp, _("Website"), website); + g_free(tmp); + g_free(website); + } + + // FILEPATH + tmp = ext_find_plugin(*plugins_it); + gchar* full = g_markup_escape_text(tmp, -1); + g_free(tmp); + tmp = tooltip; + tooltip = g_strdup_printf("%s\n%s: %s", tmp, _("File"), full); + g_free(tmp); + g_free(full); + + g_hash_table_unref(metadata); + + gtk_list_store_append(store, &it); + gtk_list_store_set(store, &it, + EXT_COLUMN_ENABLED, enabled, + EXT_COLUMN_LABEL, label, + EXT_COLUMN_TOOLTIP, tooltip, + EXT_COLUMN_PLUGIN_NAME, *plugins_it, + -1); + + g_free(label); + g_free(tooltip); + } + g_strfreev(plugins); + + view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + g_signal_connect(view, "row-activated", (GCallback)plugin_execute_action, NULL); + + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); + gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(view), EXT_COLUMN_TOOLTIP); + + + GtkTreeViewColumn *col; + GtkCellRenderer *renderer; + + + col = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(col, _("Enabled")); + gtk_tree_view_column_set_sort_column_id(col, EXT_COLUMN_ENABLED); + gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_add_attribute(col, renderer, "active", 0); + g_signal_connect(renderer, "toggled", G_CALLBACK(toggle_plugin), store); + + col = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(col, _("Plugin")); + gtk_tree_view_column_set_sort_column_id(col, EXT_COLUMN_LABEL); + gtk_tree_view_column_set_expand(col, TRUE); + /*gtk_tree_view_column_set_sort_order(col, GTK_SORT_ASCENDING);*/ + gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); + + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_add_attribute(col, renderer, "markup", EXT_COLUMN_LABEL); + + data->PI_plugin_columns = view; + + GtkWidget* sw = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(sw), view); + + gtk_box_pack_start(GTK_BOX(container), sw, TRUE, TRUE, 0); + + return(container); +} + + static void defpref_selection(GtkTreeSelection *treeselection, gpointer user_data) { struct defpref_data *data; @@@ -2291,9 -1911,9 +2110,9 @@@ gint page gtk_label_set_text (GTK_LABEL (data->label), g_value_get_string (&val)); g_value_unset (&val); - gtk_tree_model_get_value(model, &iter, LST_PREF_ICON, &val); - gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), - g_value_get_object (&val)); + gtk_tree_model_get_value(model, &iter, LST_PREF_ICONNAME, &val); + //gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), g_value_get_object (&val)); + gtk_image_set_from_icon_name(GTK_IMAGE (data->image), g_value_get_string (&val), GTK_ICON_SIZE_DIALOG); g_value_unset (&val); @@@ -2344,12 -1964,13 +2163,13 @@@ gint result data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); DB( g_print("\n(defpref_clear) (data=%p)\n", data) ); - result = ui_dialog_msg_question( + result = ui_dialog_msg_confirm_alert( GTK_WINDOW(data->window), - _("Clear every preferences ?"), - _("This will revert the preferences\nto its default values") + _("Reset all preferences"), + _("Do you really want to reset all\npreferences to default values?"), + _("Reset") ); - if( result == GTK_RESPONSE_YES ) + if( result == GTK_RESPONSE_OK ) { homebank_pref_setdefault(); defpref_set(data); @@@ -2359,19 -1980,18 +2179,18 @@@ // the window creation -GtkWidget *defpref_dialog_new (void) +GtkWidget *defpref_dialog_new (gint initial_selection) { struct defpref_data data; GtkWidget *window, *content, *mainvbox; - GtkWidget *hbox, *vbox, *sw, *widget, *notebook, *page, *ebox, *image, *label; window = gtk_dialog_new_with_buttons (_("Preferences"), GTK_WINDOW(GLOBALS->mainwindow), 0, - GTK_STOCK_CANCEL, + _("_Cancel"), GTK_RESPONSE_REJECT, - GTK_STOCK_OK, + _("_OK"), GTK_RESPONSE_ACCEPT, NULL); @@@ -2380,19 -2000,19 +2199,19 @@@ //store our window private data g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)&data); - gtk_window_set_icon_name(GTK_WINDOW (window), GTK_STOCK_PREFERENCES); + gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_PREFERENCES); - content = gtk_dialog_get_content_area(GTK_DIALOG (window)); - mainvbox = gtk_vbox_new (FALSE, 8); + content = gtk_dialog_get_content_area(GTK_DIALOG (window)); // return a vbox + mainvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM); gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0); - gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 8); + gtk_container_set_border_width(GTK_CONTAINER(mainvbox), SPACING_MEDIUM); - hbox = gtk_hbox_new (FALSE, 8); + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_MEDIUM); gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0); //left part - vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING); + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_SMALL); gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); //list @@@ -2405,30 -2025,44 +2224,44 @@@ gtk_container_add (GTK_CONTAINER (sw), widget); // clear button - data.BT_clear = gtk_button_new_from_stock(GTK_STOCK_CLEAR); + data.BT_clear = gtk_button_new_with_mnemonic(_("_Reset")); gtk_box_pack_start (GTK_BOX (vbox), data.BT_clear, FALSE, TRUE, 0); //right part : notebook - vbox = gtk_vbox_new (FALSE, 12); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); gtk_widget_show (vbox); ebox = gtk_event_box_new(); - gtk_widget_set_state (ebox, GTK_STATE_SELECTED); + gtk_widget_set_name(ebox, "hbebox"); + GtkStyleContext *context = gtk_widget_get_style_context (ebox); + #if GTK_MINOR_VERSION <= 18 + gtk_style_context_add_class (context, GTK_STYLE_CLASS_LIST_ROW); + gtk_widget_set_state_flags(ebox, GTK_STATE_FLAG_SELECTED, TRUE); + #else + GtkCssProvider *provider; + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, + "#hbebox { color: @theme_selected_fg_color; background-color: @theme_selected_bg_color; }" + , -1, NULL); + gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(provider), G_MAXUINT); + + // gtk_style_context_set_state(context, GTK_STATE_FLAG_SELECTED); + #endif + gtk_box_pack_start (GTK_BOX (vbox), ebox, FALSE, TRUE, 0); gtk_widget_show (ebox); - hbox = gtk_hbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); - gtk_container_add (GTK_CONTAINER (ebox), hbox); - gtk_widget_show (hbox); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL); + gtk_container_set_border_width (GTK_CONTAINER (hbox), SPACING_SMALL); + gtk_container_add (GTK_CONTAINER (ebox), hbox); + gtk_widget_show (hbox); - gimp_label_set_attributes (GTK_LABEL (label), - PANGO_ATTR_SCALE, PANGO_SCALE_LARGE, + label = gtk_label_new (NULL); + gtk_widget_set_margin_left(label, SPACING_MEDIUM); + gimp_label_set_attributes (GTK_LABEL (label), + PANGO_ATTR_SCALE, PANGO_SCALE_XX_LARGE, PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); @@@ -2488,10 -2122,6 +2321,10 @@@ page = defpref_page_euro(&data); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL); + //plugins + page = defpref_page_plugins(&data); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL); + //todo:should move this gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data.CM_euro_enable), PREFS->euro_active); @@@ -2506,9 -2136,11 +2339,11 @@@ g_signal_connect (data.BT_path_import, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(2)); g_signal_connect (data.BT_path_export, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(3)); + g_signal_connect (data.CM_custom_colors, "toggled", G_CALLBACK (defpref_colortoggle), NULL); g_signal_connect (data.CY_colors, "changed", G_CALLBACK (defpref_colorpreset), NULL); + g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_page)), "changed", G_CALLBACK (defpref_selection), notebook); g_signal_connect (data.CM_euro_enable, "toggled", G_CALLBACK (defpref_eurotoggle), NULL); @@@ -2518,12 -2150,9 +2353,9 @@@ //date g_signal_connect (data.ST_datefmt, "changed", G_CALLBACK (defpref_date_sample), NULL); - //base number - g_signal_connect (data.ST_num_symbol , "changed", G_CALLBACK (defpref_numberbase_sample), NULL); - g_signal_connect (data.CM_num_isprefix, "toggled", G_CALLBACK (defpref_numberbase_sample), NULL); - g_signal_connect (data.ST_num_decimalchar, "changed", G_CALLBACK (defpref_numberbase_sample), NULL); - g_signal_connect (data.ST_num_groupingchar, "changed", G_CALLBACK (defpref_numberbase_sample), NULL); - g_signal_connect (data.NB_num_fracdigits, "value-changed", G_CALLBACK (defpref_numberbase_sample), NULL); + //report + g_signal_connect (data.CY_color_scheme, "changed", G_CALLBACK (defpref_color_scheme_changed), NULL); + //euro number g_signal_connect (data.ST_euro_symbol , "changed", G_CALLBACK (defpref_numbereuro_sample), NULL); @@@ -2539,16 -2168,16 +2371,17 @@@ //defhbfile_setup(&data); //defhbfile_update(data.LV_arc, NULL); - defpref_eurotoggle(window, NULL); - defpref_set(&data); + defpref_colortoggle(window, NULL); + defpref_eurotoggle(window, NULL); + gtk_window_resize(GTK_WINDOW(window), 640, 256); //select first row - GtkTreePath *path = gtk_tree_path_new_first (); + GtkTreePath *path = gtk_tree_path_new_from_indices(initial_selection, -1); + gtk_tree_selection_select_path (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_page)), path); @@@ -2557,7 -2186,6 +2390,7 @@@ gtk_tree_path_free(path); gtk_widget_show_all (window); + gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), initial_selection); gint result; gchar *old_lang; @@@ -2607,14 -2235,12 +2440,12 @@@ GtkWidget *view GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeIter iter; - GtkWidget *cellview; gint i; /* create list store */ store = gtk_list_store_new( LST_PREF_MAX, - GDK_TYPE_PIXBUF, - GDK_TYPE_PIXBUF, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT ); @@@ -2623,15 -2249,15 +2454,15 @@@ view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); - //gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (view), FALSE); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_SINGLE); /* column 1: icon */ column = gtk_tree_view_column_new(); renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set(renderer, "stock-size", GTK_ICON_SIZE_DND, NULL); gtk_tree_view_column_pack_start(column, renderer, FALSE); - gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", LST_PREF_SMALLPIXBUF, NULL); + gtk_tree_view_column_set_attributes(column, renderer, "icon-name", LST_PREF_ICONNAME, NULL); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start(column, renderer, TRUE); @@@ -2639,86 -2265,26 +2470,26 @@@ gtk_tree_view_append_column (GTK_TREE_VIEW(view), column); - - cellview = gtk_cell_view_new (); - //populate our combobox model for(i=0;i