From: Charles McGarvey Date: Sun, 4 Feb 2018 17:16:29 +0000 (-0700) Subject: Merge branch 'master' into ext-perl X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fhomebank;a=commitdiff_plain;h=35b9973e4de7d69ad8841ead996a2e6cf1d85f08 Merge branch 'master' into ext-perl --- 35b9973e4de7d69ad8841ead996a2e6cf1d85f08 diff --cc Makefile.am index de75d0f,e5c6cfe..45d1f49 --- a/Makefile.am +++ b/Makefile.am @@@ -1,11 -1,16 +1,18 @@@ # HomeBank Makefile.am +ACLOCAL_AMFLAGS = -I m4 + #SUBDIRS = src -SUBDIRS = src data images mime pixmaps themes po doc +SUBDIRS = src data images mime pixmaps themes po doc plugins + datasdir = $(datadir)/homebank/datas/ + datas_DATA = \ + ChangeLog + + EXTRA_DIST = $(datas_DATA) + + # don't forget to do a 'make check' # to ensure all files are in po/POTFILES.in @@@ -21,8 -26,11 +28,17 @@@ DISTCLEANFILES = ... intltool-extract intltool-update \ po/.intltool-merge-cache - + # we clean every folder under /usr/share/homebank as well on uninstall + uninstall-hook: + -rm -rf $(datadir)/homebank/datas + -rm -rf $(datadir)/homebank/help + -rm -rf $(datadir)/homebank/icons + -rm -rf $(datadir)/homebank/images + #-rmdir $(datadir)/homebank ++ +run: all + PERL5LIB=src src/homebank + +debug: all + PERL5LIB=src gdb src/homebank ++ diff --cc configure.ac index 798e623,99db971..f1c2dfd --- a/configure.ac +++ b/configure.ac @@@ -26,7 -22,7 +26,7 @@@ AC_PROG_INSTAL AC_PROG_INTLTOOL # Checks for libraries. - PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.12 glib-2.0 >= 2.39 gmodule-2.0 >= 2.39) -PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.16 glib-2.0 >= 2.39) ++PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.16 glib-2.0 >= 2.39 gmodule-2.0 >= 2.39) AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) AC_CHECK_LIB(m, pow) diff --cc plugins/hello.pl index 9171bb2,0000000..25520b5 mode 100644,000000..100644 --- a/plugins/hello.pl +++ b/plugins/hello.pl @@@ -1,234 -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; +} + +sub on_create_main_window { + my $self = shift; + my $window = shift; + + if (!$window) { + 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); +} + +my $test_win; + +sub on_test { + my $self = shift; + require Gtk3; + + 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 { Gtk3->main_quit }); + $window->signal_connect(delete_event => sub { undef $test_win }); + + my $button = Gtk3::Button->new('Click Me!'); + Dump($button); + print Dumper($button); + $button->signal_connect(clicked => sub { + 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 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"; ++ print "transaction of amount: ", $xc->amount, "\t", $xc->memo, ", ", $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 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; +} + +sub EXECUTE { + print "the perl plugin is being configured.....\n"; + HomeBank->info("Hello Prefs", "YEEEEEARGGH!!!!!"); +} + +#__PACKAGE__->meta->make_immutable; diff --cc src/Makefile.am index 484ce27,9c7e193..20da8f1 --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -119,21 -118,13 +119,23 @@@ homebank_SOURCES = ui-split.h \ ui-transaction.c \ ui-transaction.h \ + ui-txn-multi.c \ + ui-txn-multi.h \ ui-widgets.c \ - ui-widgets.h + ui-widgets.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 = $(DEPS_LIBS) \ - $(LIBSOUP_LIBS) + $(LIBSOUP_LIBS) \ + $(PERL_OBJS) AM_CPPFLAGS = \ $(DEPS_CFLAGS) \ diff --cc src/dsp_mainwindow.c index e819137,2cb2ecd..c733f4c --- a/src/dsp_mainwindow.c +++ b/src/dsp_mainwindow.c @@@ -148,8 -152,8 +156,10 @@@ void ui_mainwindow_scheduled_postall(Gt void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path); +static void ui_mainwindow_showprefs(gint page); + + static void ui_panel_accounts_setup(struct hbfile_data *data); + extern gchar *CYA_ACC_TYPE[]; gchar *CYA_CATSUBCAT[] = { @@@ -318,17 -321,14 +331,19 @@@ static const gchar *ui_info " " " " " " +" " +" " +" " +" " +" " " " " " - " " " " - " " + " " + " " + " " " " + " " " " " " " " @@@ -2371,10 -2457,7 +2485,10 @@@ 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") ); + DB( g_print("\n[ui-mainwindow] delete-event\n") ); //store position and size wg = &PREFS->wal_wg; diff --cc src/ext-perl.xs index 5aa56b0,0000000..9c7bd8b mode 100644,000000..100644 --- a/src/ext-perl.xs +++ b/src/ext-perl.xs @@@ -1,1043 -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* 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 + +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_queue_peek_head_link(SELF->txn_queue); + for (; list; list = g_list_next(list)) { + Transaction* txn = list->data; + 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, ...) ++memo(Transaction* SELF, ...) + CODE: + if (1 < items) { - if (SELF->wording) g_free(SELF->wording); - SELF->wording = g_strdup(SvGchar_ptr(ST(1))); ++ if (SELF->memo) g_free(SELF->memo); ++ SELF->memo = g_strdup(SvGchar_ptr(ST(1))); + } - RETVAL = SELF->wording ? SELF->wording : ""; ++ RETVAL = SELF->memo ? SELF->memo : ""; + 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, 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(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); ++ SELF->memo, SELF->date, SELF->kacc, SELF->kxferacc, SELF->flags, SELF->paymode, SELF->kpay, SELF->kcat); + diff --cc src/hb-archive.c index e0789de,0e88c48..628e978 --- a/src/hb-archive.c +++ b/src/hb-archive.c @@@ -39,17 -36,15 +39,15 @@@ extern struct HomeBank *GLOBALS; - /* = = = = = = = = = = = = = = = = = = = = */ - /* Archive */ - 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) { @@@ -62,12 -57,13 +60,13 @@@ return new_item; } + void da_archive_free(Archive *item) { - if(item != NULL) + if(rc_unref(item)) { - if(item->wording != NULL) - g_free(item->wording); + if(item->memo != NULL) + g_free(item->memo); da_splits_free(item->splits); //item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared diff --cc src/hb-transaction.c index 5f77203,29812d9..eb82509 --- a/src/hb-transaction.c +++ b/src/hb-transaction.c @@@ -850,41 -946,9 +952,12 @@@ Account *acc { 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; - GtkTreeIter iter; - //GtkTreePath *path; - //GtkTreeSelection *sel; - - DB( g_print("\n[transaction] add_treeview\n") ); - - if(ope->kacc == accnum) - { - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); - gtk_list_store_append (GTK_LIST_STORE(model), &iter); - - gtk_list_store_set (GTK_LIST_STORE(model), &iter, - LST_DSPOPE_DATAS, ope, - -1); - - //activate that new line - //path = gtk_tree_model_get_path(model, &iter); - //gtk_tree_view_expand_to_path(GTK_TREE_VIEW(treeview), path); - - //sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - //gtk_tree_selection_select_iter(sel, &iter); - - //gtk_tree_path_free(path); - - } + + return newope; } diff --cc src/homebank.c index 9a9e915,3b65ca1..60e87c8 --- a/src/homebank.c +++ b/src/homebank.c @@@ -17,8 -17,8 +17,9 @@@ * along with this program. If not, see . */ + #include "homebank.h" +#include "ext.h" #include "dsp_mainwindow.h" #include "hb-preferences.h" @@@ -1079,18 -1073,13 +1104,20 @@@ nobak /* 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(" - call destroy mainwin\n" ) ); + gtk_widget_destroy(mainwin); } + DB( g_print(" - unloading plugins\n") ); + ext_term(); + } diff --cc src/ui-pref.c index 1597d68,7da069f..bcee6b1 --- a/src/ui-pref.c +++ b/src/ui-pref.c @@@ -206,29 -185,14 +186,17 @@@ static EuroParams euro_params[] }; - GtkWidget *pref_list_create(void); - 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); + + - - /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/ - typedef struct - { - gchar *locale; - gchar *name; - - } LangName; + static LangName languagenames[] = { --// af ar ast be bg 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 ++// af ar ast be bg 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 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 -- ++ { "aa", "Afar" }, { "ab", "Abkhazian" }, { "ae", "Avestan" }, @@@ -433,7 -400,7 +404,7 @@@ gchar *name1, *name2 //keep system laguage on top if(code1 == NULL) name1 = NULL; if(code2 == NULL) name2 = NULL; -- ++ retval = hb_string_utf8_compare(name1, name2); g_free(name2); @@@ -482,7 -449,7 +453,7 @@@ const gchar *lang g_warning(" locale name not found '%s'", locale); lang = locale; } -- ++ } return lang; @@@ -497,7 -464,7 +468,7 @@@ GtkTreeIter iter model = gtk_combo_box_get_model(GTK_COMBO_BOX(combobox)); gtk_list_store_append (GTK_LIST_STORE(model), &iter); -- gtk_list_store_set (GTK_LIST_STORE(model), &iter, ++ gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, NULL, 1, _("System Language"), -1); @@@ -520,13 -487,13 +491,13 @@@ const gchar *dirname { const gchar *lang; gchar *label; -- ++ gtk_list_store_append (GTK_LIST_STORE(model), &iter); lang = ui_language_combobox_get_name(dirname); label = g_strdup_printf ("%s [%s]", lang, dirname); -- gtk_list_store_set (GTK_LIST_STORE(model), &iter, ++ gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, dirname, 1, label, -1); @@@ -563,7 -530,7 +534,7 @@@ GtkCellRenderer *renderer 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) @@@ -572,7 -539,7 +543,7 @@@ ui_language_combobox_populate(combobox); gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0); -- ++ return combobox; } @@@ -740,7 -707,7 +711,7 @@@ gchar buf[128] cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits)); da_cur_initformat (&cur); -- ++ DB( g_print("fmt: %s\n", cur.format) ); g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, HB_NUMBER_SAMPLE); @@@ -780,11 -747,11 +751,11 @@@ struct defpref_data *data EuroParams *euro; gchar *buf; gint active; -- ++ DB( g_print("\n[ui-pref] eurosetcurrency\n") ); data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); -- ++ active = ui_euro_combobox_id_to_active(country); euro = &euro_params[active]; buf = g_strdup_printf("%s - %s", euro->iso, euro->name); @@@ -899,7 -866,7 +870,7 @@@ struct defpref_data *data data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); gtk_widget_queue_draw (data->DA_colors); -- ++ } @@@ -1047,7 -1018,7 +1022,7 @@@ const gchar *lang { PREFS->language = g_strdup(lang); } -- ++ PREFS->toolbar_style = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_toolbar)); //PREFS->image_size = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_image_size)); @@@ -1063,38 -1032,20 +1036,20 @@@ gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba); g_free(PREFS->color_warn); PREFS->color_warn = gdk_rgba_to_hex(&rgba); - //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)); + //list_txn_colpref_get(GTK_TREE_VIEW(data->LV_opecolumns), PREFS->lst_ope_columns); - 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)); - - list_txn_colpref_get(GTK_TREE_VIEW(data->LV_opecolumns), PREFS->lst_ope_columns); - - g_free(PREFS->path_hbfile); - PREFS->path_hbfile = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_hbfile))); - - ui_gtk_entry_replace_text(data->ST_path_import, &PREFS->path_import); - - 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)); - // transaction ++ // transaction + 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->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)); + PREFS->heritdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_herit_date)); - //g_free(PREFS->path_navigator); - //PREFS->path_navigator = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_navigator))); - + // display format g_free(PREFS->date_format); PREFS->date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_datefmt))); - 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)); @@@ -1116,25 -1078,7 +1082,9 @@@ 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)); - PREFS->stat_showrate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_stat_showrate)); - PREFS->stat_showdetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_stat_showdetail)); - - PREFS->budg_showdetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_budg_showdetail)); - - PREFS->report_color_scheme = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_color_scheme)); - - /* 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)); } @@@ -1153,10 -1097,10 +1103,10 @@@ gint crow, row 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 @@@ -1172,10 -1116,10 +1122,10 @@@ 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 @@@ -1199,10 -1143,10 +1149,10 @@@ 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); @@@ -1219,10 -1163,10 +1169,10 @@@ 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 @@@ -1280,7 -1224,7 +1230,7 @@@ gint i, x, y index = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_color_scheme)); colorscheme_init(&scheme, index); -- ++ gtk_widget_get_size_request (widget, &w, &h); x = y = 0; for(i=0;iCM_stat_byamount = widget; @@@ -1381,10 -1325,10 +1331,10 @@@ 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; @@@ -1409,7 -1353,7 +1359,7 @@@ gint crow, row 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); @@@ -1424,7 -1368,7 +1374,7 @@@ 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); @@@ -1444,7 -1388,7 +1394,7 @@@ //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); -- ++ // group :: Exchange rate group_grid = gtk_grid_new (); data->GRP_rate = group_grid; @@@ -1469,7 -1413,7 +1419,7 @@@ 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); @@@ -1486,7 -1430,7 +1436,7 @@@ 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); @@@ -1539,7 -1483,7 +1489,7 @@@ gint crow, row 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); @@@ -1569,7 -1513,7 +1519,7 @@@ 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" @@@ -1597,7 -1541,7 +1547,7 @@@ 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); @@@ -1630,7 -1574,7 +1580,7 @@@ gint crow, row 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); @@@ -1647,7 -1591,7 +1597,7 @@@ //----------------------------------------- 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); @@@ -1670,7 -1614,7 +1620,7 @@@ 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); @@@ -1684,7 -1629,7 +1635,7 @@@ 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); @@@ -1720,7 -1666,7 +1672,7 @@@ gint crow, row 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); @@@ -1730,7 -1676,7 +1682,7 @@@ widget = ui_language_combobox_new(label); data->CY_language = widget; gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1); -- ++ row++; label = make_label_widget(_("_Toolbar:")); gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1); @@@ -1753,7 -1699,7 +1705,7 @@@ 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); @@@ -1783,11 -1729,11 +1735,11 @@@ 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_widget(_("_Income:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); @@@ -1821,7 -1767,7 +1773,7 @@@ gint crow, row 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); @@@ -1873,7 -1819,7 +1825,7 @@@ 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); @@@ -1889,7 -1835,7 +1841,7 @@@ 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); @@@ -2204,7 -1954,7 +2156,7 @@@ gint result homebank_pref_setdefault(); defpref_set(data); } -- ++ } @@@ -2225,7 -1975,7 +2177,7 @@@ GtkWidget *hbox, *vbox, *sw, *widget, * NULL); data.window = window; -- ++ //store our window private data g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)&data); @@@ -2243,7 -1993,7 +2195,7 @@@ //left part vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_SMALL); gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); -- ++ //list sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); @@@ -2257,7 -2007,7 +2209,7 @@@ 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_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); @@@ -2272,11 -2022,11 +2224,11 @@@ #else GtkCssProvider *provider; provider = gtk_css_provider_new (); -- gtk_css_provider_load_from_data (provider, ++ 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 @@@ -2363,7 -2109,7 +2315,7 @@@ g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); g_signal_connect (G_OBJECT (data.BT_clear), "clicked", G_CALLBACK (defpref_clear), NULL); -- ++ //path selector g_signal_connect (data.BT_path_hbfile, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(1)); g_signal_connect (data.BT_path_import, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(2)); @@@ -2373,7 -2119,7 +2325,7 @@@ 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); @@@ -2438,20 -2182,20 +2390,20 @@@ ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_BALANCE+UF_VISUAL)); DB( g_print("old='%s' new='%s'\n", old_lang, PREFS->language) ); -- ++ if(g_ascii_strncasecmp(old_lang == NULL ? "" : old_lang, PREFS->language == NULL ? "" : PREFS->language, -1) != 0) { ui_dialog_msg_infoerror(GTK_WINDOW(window), GTK_MESSAGE_INFO, _("Info"), _("You will have to restart HomeBank\nfor the language change to take effect.") ); -- ++ } g_free(old_lang); break; } -- ++ // cleanup and destroy //defhbfile_cleanup(&data, result); @@@ -2532,7 -2276,7 +2484,7 @@@ GtkTreeIter iter GtkTreePath *path = gtk_tree_path_new_from_string (path_str); gboolean fixed; - /* get toggled iter */ - // get toggled iter ++ // get toggled iter gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, COLUMN_VISIBLE, &fixed, -1); @@@ -2556,8 -2300,7 +2508,7 @@@ gboolean visible gint i, id; DB( g_print("[lst_txn-colpref] store column order \n") ); - + - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); i = 0; @@@ -2609,16 -2349,16 +2557,16 @@@ gint i gboolean visible; DB( g_print("eval %d, %s\n", i, list_txn_column_label[i]) ); -- ++ if(i <= LST_DSPOPE_DATE) // status, date always displayed continue; //[i-1] here because lst_ope_columns[] do not store LST_DSPOPE_DATAS -- id = ABS(PREFS->lst_ope_columns[i-1]); ++ id = ABS(PREFS->lst_ope_columns[i-1]); if(id == 0) id = i; //if we pass here, new column or weird into pref file visible = (PREFS->lst_ope_columns[i-1] > 0) ? TRUE : FALSE; -- ++ DB( g_print(" - pos=%2d, id=%2d - %d '%s'\n", i, id, visible, list_txn_column_label[id]) ); gtk_list_store_append (store, &iter); @@@ -2627,7 -2367,7 +2575,7 @@@ COLUMN_NAME, _(list_txn_column_label[id]), COLUMN_ID , id, -1); -- ++ } //treeview @@@ -2646,7 -2386,7 +2594,7 @@@ g_signal_connect (renderer, "toggled", G_CALLBACK (list_txn_colpref_toggled_cell_data_function), store); -- ++ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Column"), renderer, @@@ -2659,33 -2399,5 +2607,34 @@@ return(view); } + */ + +static void list_ext_colpref_get(GtkTreeView *treeview, GList **columns) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + g_list_free_full(*columns, g_free); + *columns = NULL; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); + + gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); + while (valid) { + gboolean enabled = FALSE; + const gchar* name; + + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, + EXT_COLUMN_ENABLED, &enabled, + EXT_COLUMN_PLUGIN_NAME, &name, + -1); + + if (enabled) { + *columns = g_list_append(*columns, g_strdup(name)); + } + + valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + } +} +