# 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
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
++
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.52)
- AC_INIT([homebank], [5.1.3])
+ AC_INIT([homebank], [5.1.7])
#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.
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)
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
- # release flags
+ # general usage flags
CFLAGS="${CFLAGS} -Wall -Wmissing-prototypes"
# disable deprecated warnings
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])
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])
po/Makefile.in
doc/Makefile
doc/images/Makefile
+plugins/Makefile
])
AC_OUTPUT
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
--- /dev/null
- print "transaction of amount: ", $xc->amount, "\t", $xc->wording, ", ", $xc->info, ", $num, $date\n";
+
+# NAME: Hello World
+# VERSION: 0.01
+# ABSTRACT: This is the "hello world" of HomeBank plugins.
+# AUTHOR: Charles McGarvey <chazmcgarvey@brokenzipper.com>
+# 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->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;
common_defines = \
-DSHARE_DIR=\""$(pkgdatadir)"\" \
- -DDATA_DIR=\""$(datadir)"\"
+ -DDATA_DIR=\""$(datadir)"\" \
+ -DPKGLIB_DIR=\""$(pkglibdir)"\"
bin_PROGRAMS = homebank
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) \
$(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
+
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "dsp_mainwindow.h"
+#include "ext.h"
+
#include "list_account.h"
#include "list_upcoming.h"
#include "list_topspending.h"
#include "gtk-chart.h"
+ //old url prior 2018
//#define HOMEBANK_URL_HELP "http://homebank.free.fr/help/"
+ //#define HOMEBANK_URL_HELP_ONLINE "https://launchpad.net/homebank/+addquestion"
+ //#define HOMEBANK_URL_HELP_PROBLEM "https://launchpad.net/homebank/+filebug"
+ //#define HOMEBANK_URL_HELP_TRANSLATE "https://launchpad.net/homebank/+translations"
+
#define HOMEBANK_URL_HELP "index.html"
- #define HOMEBANK_URL_HELP_ONLINE "https://launchpad.net/homebank/+addquestion"
- #define HOMEBANK_URL_HELP_TRANSLATE "https://launchpad.net/homebank/+translations"
- #define HOMEBANK_URL_HELP_PROBLEM "https://launchpad.net/homebank/+filebug"
+ #define HOMEBANK_URL_HELP_ONLINE "http://homebank.free.fr/support.php"
+ #define HOMEBANK_URL_HELP_UPDATES "http://homebank.free.fr/downloads.php"
+ #define HOMEBANK_URL_HELP_PROBLEM "http://homebank.free.fr/development.php#bug"
+ #define HOMEBANK_URL_HELP_TRANSLATE "http://homebank.free.fr/development.php#translate"
/****************************************************************************/
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);
+ static void ui_mainwindow_action_help_updates(void);
+ static void ui_mainwindow_action_help_releasenotes(void);
static void ui_mainwindow_action_help_translate(void);
static void ui_mainwindow_action_help_problem(void);
static void ui_mainwindow_action_about(void);
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[] = {
{ "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") },
{ "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..."), "<control>U", N_("Configure plugin preferences"), G_CALLBACK(ui_mainwindow_action_pluginprefs) },
+
/* HelpMenu */
{ "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) },
+
+ { "Updates" , NULL , N_("Check for updates...") , NULL, N_("Visit HomeBank website to check for update"), G_CALLBACK (ui_mainwindow_action_help_updates) },
+ { "ReleaseNotes", NULL , N_("Release Notes") , NULL, N_("Display the release notes"), G_CALLBACK (ui_mainwindow_action_help_releasenotes) },
{ "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) },
+ { "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) },
{ "About" , ICONNAME_ABOUT , N_("_About") , NULL, N_("About HomeBank") ,G_CALLBACK (ui_mainwindow_action_about) },
" <separator/>"
" <menuitem action='Anonymize'/>"
" </menu>"
+" <menu action='PluginMenu'>"
+" <separator/>"
+" <menuitem action='PluginPreferences'/>"
+" <separator/>"
+" </menu>"
" <menu action='HelpMenu'>"
" <menuitem action='Contents'/>"
- " <separator/>"
" <menuitem action='Online'/>"
- " <menuitem action='Translate'/>"
+ " <separator/>"
+ " <menuitem action='Updates'/>"
+ " <menuitem action='ReleaseNotes'/>"
" <menuitem action='Problem'/>"
+ " <menuitem action='Translate'/>"
" <separator/>"
" <menuitem action='About'/>"
" </menu>"
" <toolitem action='RBalance'/>"
" <toolitem action='RBudget'/>"
" <toolitem action='RVehiculeCost'/>"
+" <separator/>"
" </toolbar>"
"</ui>";
{
DB( g_print(" - should revert\n") );
- hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
+ hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
ui_mainwindow_open_internal(widget, NULL);
- hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
+ hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
}
}
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
};
};
*/
- static const gchar *copyright = "Copyright \xc2\xa9 1995-2017 - Maxime DOYEN";
+ static const gchar *copyright = "Copyright \xc2\xa9 1995-2018 - Maxime DOYEN";
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);
+ //ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
+ //ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+ //ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
}
}
{
gboolean result;
- //gtk_widget_destroy(GLOBALS->mainwindow);
-
+ //emulate the wm close button
g_signal_emit_by_name(GLOBALS->mainwindow, "delete-event", NULL, &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();
_("_Anonymize")
);
- if( result == GTK_RESPONSE_CANCEL )
- return;
-
- hbfile_anonymize();
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
+ //#1707201
+ //if( result == GTK_RESPONSE_CANCEL )
+ // return;
+ if( result == GTK_RESPONSE_OK )
+ {
+ hbfile_anonymize();
+ ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
+ }
}
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");
}
+
static void ui_mainwindow_action_export(void)
{
gchar *filename;
}
}
+
static void ui_mainwindow_action_help(void)
{
gchar *link;
link = g_build_filename("file:///", homebank_app_get_help_dir(), HOMEBANK_URL_HELP, NULL );
homebank_util_url_show (link);
+ g_free(link);
+ }
+
+
+ static void ui_mainwindow_action_help_releasenotes(void)
+ {
+ gchar *link;
+ #ifdef G_OS_WIN32
+ link = g_build_filename("file:///", homebank_app_get_datas_dir(), "ChangeLog.txt", NULL );
+ #else
+ link = g_build_filename("file:///", homebank_app_get_datas_dir(), "ChangeLog", NULL );
+ #endif
+ homebank_util_url_show (link);
g_free(link);
}
}
+ static void ui_mainwindow_action_help_updates(void)
+ {
+ const gchar *link = HOMEBANK_URL_HELP_UPDATES;
+
+ homebank_util_url_show (link);
+ }
+
static void ui_mainwindow_action_help_online(void)
{
const gchar *link = HOMEBANK_URL_HELP_ONLINE;
homebank_util_url_show (link);
-
}
+
static void ui_mainwindow_action_help_translate(void)
{
const gchar *link = HOMEBANK_URL_HELP_TRANSLATE;
homebank_util_url_show (link);
-
}
+
static void ui_mainwindow_action_help_problem(void)
{
const gchar *link = HOMEBANK_URL_HELP_PROBLEM;
homebank_util_url_show (link);
-
}
-
-
/* hbfile functions -------------------- */
-
-
/*
**
*/
gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
data->showall = FALSE;
+ ui_panel_accounts_setup(data);
hbfile_cleanup(file_clear);
hbfile_setup(file_clear);
if( result == GTK_RESPONSE_ADD )
{
ope = da_transaction_malloc();
- ope->date = date;
+ ope->date = date;
ope->kacc = account;
if( PREFS->heritdate == FALSE ) //fix: 318733
if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
{
deftransaction_get(window, NULL);
- transaction_add(ope, NULL, ope->kacc);
+ transaction_add(ope);
DB( g_print(" - added 1 transaction to %d\n", ope->kacc) );
};
- #define MAX_TOPSPENDING 5
+ #define MAX_TOPSPENDING 10
static gint tmptop_compare_func(struct tmptop *tt1, struct tmptop *tt2)
{
Transaction *ope = list->data;
- //DB( g_print(" - eval txn: '%s', cat=%d ==> flt-test=%d\n", ope->wording, ope->kcat, filter_test(data->filter, ope)) );
+ //DB( g_print(" - eval txn: '%s', cat=%d ==> flt-test=%d\n", ope->memo, ope->kcat, filter_test(data->filter, ope)) );
if( !(ope->paymode == PAYMODE_INTXFER) )
{
if(acc)
trn_amount = hb_amount_base(ope->amount, acc->kcur);
- if( ope->flags & OF_SPLIT )
+ if( ope->flags & OF_SPLIT )
{
guint nbsplit = da_splits_count(ope->splits);
Split *split;
if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
{
deftransaction_get(window, NULL);
- transaction_add(txn, NULL, txn->kacc);
+ transaction_add(txn);
GLOBALS->changes_count++;
scheduled_date_advance(arc);
{
struct hbfile_data *data = user_data;
+ DB( g_print("\n[ui-mainwindow] scheduled post\n") );
+
Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
if( (arc != NULL) )
da_transaction_init_from_template(txn, arc);
txn->date = scheduled_get_postdate(arc, arc->nextdate);
- transaction_add(txn, NULL, 0);
+ transaction_add(txn);
GLOBALS->changes_count++;
scheduled_date_advance(arc);
if(arc)
{
- DB( g_print("archive is %s\n", arc->wording) );
+ DB( g_print("archive is %s\n", arc->memo) );
gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE);
nbdays = arc->nextdate - maxpostdate;
nblate = scheduled_get_latepost_count(arc, GLOBALS->today);
- DB( g_print(" - append '%s' : %d\n", arc->wording, nbdays) );
+ DB( g_print(" - append '%s' : %d\n", arc->memo, nbdays) );
if(arc->flags & OF_INCOME)
{
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
LST_DSPUPC_DATAS, arc,
LST_DSPUPC_ACCOUNT, acc,
- LST_DSPUPC_WORDING, arc->wording,
+ LST_DSPUPC_MEMO, arc->memo,
LST_DSPUPC_EXPENSE, exp,
LST_DSPUPC_INCOME, inc,
LST_DSPUPC_REMAINING, nbdays,
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
LST_DSPUPC_DATAS, arc,
LST_DSPUPC_ACCOUNT, acc,
- LST_DSPUPC_WORDING, arc->wording,
+ LST_DSPUPC_MEMO, arc->memo,
LST_DSPUPC_EXPENSE, -inc,
LST_DSPUPC_INCOME, -exp,
LST_DSPUPC_REMAINING, nbdays,
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
LST_DSPUPC_DATAS, NULL,
LST_DSPUPC_ACCOUNT, NULL,
- LST_DSPUPC_WORDING, _("Total"),
+ LST_DSPUPC_MEMO, _("Total"),
LST_DSPUPC_EXPENSE, totexp,
LST_DSPUPC_INCOME, totinc,
-1);
}
-
ui_mainwindow_scheduled_update(widget, NULL);
}
+ gboolean ui_mainwindow_open_backup_check_confirm(gchar *filepath)
+ {
+ gboolean retval = FALSE;
+ gchar *basename, *secondtext;
+ gboolean result;
+
+ basename = g_path_get_basename(filepath);
+ secondtext = g_strdup_printf (
+ _("Your are about to open the backup file '%s'.\n\nAre you sure you want to do this ?"), basename);
+
+ result = ui_dialog_msg_confirm_alert(
+ GTK_WINDOW(GLOBALS->mainwindow),
+ _("Open a backup file ?"),
+ secondtext,
+ _("_Open backup")
+ );
+
+ g_free(secondtext);
+ g_free(basename);
+
+ if( result == GTK_RESPONSE_OK )
+ retval = TRUE;
+
+ return retval;
+ }
/*
if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
{
- if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename) == TRUE)
+ if( ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename) == TRUE )
{
- hbfile_change_filepath(filename);
+ //#1710955 test for backup open
+ if( hbfile_file_isbackup(filename) )
+ {
+ if( ui_mainwindow_open_backup_check_confirm(filename) == TRUE )
+ {
+ GLOBALS->hbfile_is_bak = TRUE;
+ }
+ else
+ {
+ g_free(filename);
+ return;
+ }
+ }
+ hbfile_change_filepath(filename);
ui_mainwindow_open_internal(widget, NULL);
-
-
}
}
}
+
/*
* open the file stored in GLOBALS->xhb_filepath
*/
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) );
-
if( GLOBALS->xhb_filepath != NULL )
{
+ DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) );
+
ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
GLOBALS->hbfile_is_new = FALSE;
}
+
/*
**
*/
if( GLOBALS->hbfile_is_new == TRUE )
saveas = 1;
+ //#1710955 test for backup open
+ if( GLOBALS->hbfile_is_bak == TRUE )
+ {
+ //todo: later for backup, should also remove datetime and .bak
+ hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
+ saveas = 1;
+ }
+
if(saveas == 1)
{
if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename) == TRUE)
homebank_backup_current_file();
r = homebank_save_xml(GLOBALS->xhb_filepath);
GLOBALS->hbfile_is_new = FALSE;
+ GLOBALS->hbfile_is_bak = FALSE;
}
else
return;
gchar *groupname;
gint nballoc;
+ DB( g_print("\n[ui-mainwindow] accounts_groups_get\n") );
+
nballoc = da_acc_length ();
+
+ DB( g_print(" %d accounts\n", nballoc) );
+
hash = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
elt = g_list_first(lacc);
while (elt != NULL)
Account *acc = elt->data;
GPtrArray *group;
- if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
+ //#1674045 ony rely on nosummary
+ //if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
+ if( showall || !(acc->flags & AF_NOSUMMARY) )
{
if( groupby == DSPACC_GROUP_BY_BANK )
{
gtbank = gttoday = gtfuture = 0;
- DB( g_print(" populate listview\n") );
+ DB( g_print(" - populate listview, %d group(s)\n", g_hash_table_size(h_group)) );
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc));
gtk_tree_store_clear (GTK_TREE_STORE(model));
{
GPtrArray *gpa = value;
gdouble tbank, ttoday, tfuture;
+ gint position;
if(gpa != NULL)
{
nbtype++;
//1: Header: Bank, Cash, ...
- //DB( g_print(" - append type '%s'\n", CYA_ACC_TYPE[i]) );
- DB( g_print("\n - append type '%d'\n", key) );
+ DB( g_print(" - add group '%s'\n", (gchar *)key) );
+
+ //#1663399 keep type position like in dropdown
+ position = 0;
+ if( PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE )
+ {
+ gint t = 0;
+
+ while(CYA_ACC_TYPE[t] != NULL && t < 15)
+ {
+ if( !strcmp(CYA_ACC_TYPE[t], key) )
+ break;
+ t++;
+ }
+
+ position = t;
+ }
gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL);
gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
+ LST_DSPACC_POS, position,
LST_DSPACC_DATATYPE, DSPACC_TYPE_HEADER,
LST_DSPACC_NAME, key,
-1);
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) );
+ DB( g_print(" - add account '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) );
gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1);
gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter,
if(gpa->len > 1)
{
- DB( g_print(" - type totals :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
+ DB( g_print(" - group total :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
// insert the total line
gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1);
}
/* set balance to header to display when collasped */
- DB( g_print(" - enrich totals to header :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
+ DB( g_print(" - enrich group total header :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
LST_DSPACC_BANK, tbank,
LST_DSPACC_TODAY, ttoday,
}
- DB( g_print(" - grand totals :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) );
+ DB( g_print(" - grand total :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) );
// Grand total
if( nbtype > 1 )
struct hbfile_data *data;
gint flags;
- DB( g_print("\n[ui-mainwindow] refresh_display\n") );
+ DB( g_print("\n[ui-mainwindow] update %p\n", user_data) );
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
//data = INST_DATA(widget);
gchar *basename;
gchar *changed;
- DB( g_print(" + 1: wintitle %x\n", data->wintitle) );
+ DB( g_print(" 1: wintitle %p\n", data->wintitle) );
basename = g_path_get_basename(GLOBALS->xhb_filepath);
GtkTreePath *path;
gboolean active,sensitive;
- DB( g_print(" + 2: disabled, opelist count\n") );
+ DB( g_print(" 2: disabled, opelist count\n") );
//#1656531
data->acc = NULL;
/* update toolbar, list */
if(flags & UF_VISUAL)
{
- DB( g_print(" + 8: visual\n") );
+ DB( g_print(" 8: visual\n") );
if(PREFS->toolbar_style == 0)
gtk_toolbar_unset_style(GTK_TOOLBAR(data->toolbar));
if(flags & UF_BALANCE)
{
- DB( g_print(" + 4: balances\n") );
+ DB( g_print(" 4: balances\n") );
gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
if(flags & UF_REFRESHALL)
{
- DB( g_print(" + 8: refreshall\n") );
+ DB( g_print(" 16: refreshall\n") );
ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
}
}
+
+ static void ui_mainwindow_destroy(GtkTreeView *treeview, gpointer user_data)
+ {
+ DB( g_print("\n[ui-mainwindow] destroy\n") );
+
+ }
+
+
/*
**
*/
struct WinGeometry *wg;
gboolean retval = FALSE;
- DB( g_print("\n[ui-mainwindow] dispose\n") );
+ GValue widget_value = G_VALUE_INIT;
+ ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL);
+
+ DB( g_print("\n[ui-mainwindow] delete-event\n") );
//store position and size
wg = &PREFS->wal_wg;
}
else
{
- DB( g_print(" free wintitle %x\n", data->wintitle) );
-
+ //todo: retval is useless and below should move to destroy
+ retval = TRUE;
gtk_widget_destroy(data->LV_top);
g_free(data->wintitle);
da_filter_free(data->filter);
g_free(user_data);
+
gtk_main_quit();
}
-
-
- //delete-event TRUE abort/FALSE destroy
+ //TRUE:stop other handlers from being invoked for the event | FALSE: propagate
return retval;
}
static const GActionEntry actions[] = {
// { "paste", activate_action, NULL, NULL, NULL, {0,0,0} },
- { "showall" , activate_toggle, NULL, "false", NULL, {0,0,0} },
- { "groupby", activate_radio, "s", "'type'", NULL, {0,0,0} }
+ { "showall", activate_toggle, NULL, "false" , NULL, {0,0,0} },
+ { "groupby", activate_radio , "s", "'type'", NULL, {0,0,0} }
};
+ static void ui_panel_accounts_setup(struct hbfile_data *data)
+ {
+ GAction *action;
+ GVariant *new_state;
+
+ if( !G_IS_SIMPLE_ACTION_GROUP(data->action_group_acc) )
+ return;
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "showall");
+ if( action )
+ {
+ new_state = g_variant_new_boolean (data->showall);
+ g_simple_action_set_state (G_SIMPLE_ACTION(action), new_state);
+ }
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "groupby");
+ if( action )
+ {
+ const gchar *value = (PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE) ? "type" : "bank";
+ new_state = g_variant_new_string (value);
+ g_simple_action_set_state (G_SIMPLE_ACTION (action), new_state);
+ }
+
+ }
+
+
static GtkWidget *ui_mainwindow_create_youraccounts(struct hbfile_data *data)
{
GtkWidget *panel, *label, *widget, *sw, *tbar, *hbox, *image;
//gmenu test (see test folder into gtk)
- widget = gtk_menu_button_new();
- gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget), GTK_ARROW_UP);
- gtk_widget_set_halign (widget, GTK_ALIGN_END);
- image = gtk_image_new_from_icon_name (ICONNAME_EMBLEM_SYSTEM, GTK_ICON_SIZE_MENU);
- g_object_set (widget, "image", image, NULL);
-
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), widget);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
GMenu *menu, *section;
menu = g_menu_new ();
GSimpleActionGroup *group = g_simple_action_group_new ();
+ data->action_group_acc = group;
g_action_map_add_action_entries (G_ACTION_MAP (group), actions, G_N_ELEMENTS (actions), data);
- //init radio
- GAction *action = g_action_map_lookup_action (G_ACTION_MAP (group), "groupby");
- const gchar *value = (PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE) ? "type" : "bank";
- g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_string (value));
- gtk_widget_insert_action_group (widget, "actions", G_ACTION_GROUP(group));
+ widget = gtk_menu_button_new();
+ gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget), GTK_ARROW_UP);
+ gtk_widget_set_halign (widget, GTK_ALIGN_END);
+ image = gtk_image_new_from_icon_name (ICONNAME_EMBLEM_SYSTEM, GTK_ICON_SIZE_MENU);
+ g_object_set (widget, "image", image, NULL);
+ toolitem = gtk_tool_item_new();
+ gtk_container_add (GTK_CONTAINER(toolitem), widget);
+ gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
+
+ gtk_widget_insert_action_group (widget, "actions", G_ACTION_GROUP(group));
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (widget), G_MENU_MODEL (menu));
return panel;
//store our window private data
g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
- DB( g_print(" - new window=%x, inst_data=%0x\n", window, data) );
+ DB( g_print(" - new window=%p, inst_data=%p\n", window, data) );
// this is our mainwindow, so store it to GLOBALS data
data->window = window;
gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
widget = ui_mainwindow_scheduled_create(data);
- gtk_paned_pack2 (GTK_PANED(vpaned), widget, FALSE, FALSE);
+ gtk_paned_pack2 (GTK_PANED(vpaned), widget, TRUE, FALSE);
widget = ui_mainwindow_create_youraccounts(data);
+ //gtk_widget_set_size_request (widget, 100, -1);
gtk_paned_pack1 (GTK_PANED(hpaned), widget, FALSE, FALSE);
widget = ui_mainwindow_create_topspending(data);
- gtk_paned_pack2 (GTK_PANED(hpaned), widget, FALSE, FALSE);
-
-
- DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
+ //gtk_widget_set_size_request (widget, -1, 100);
+ gtk_paned_pack2 (GTK_PANED(hpaned), widget, TRUE, FALSE);
- if(PREFS->wal_hpaned > 0)
- gtk_paned_set_position(GTK_PANED(data->hpaned), PREFS->wal_hpaned);
- 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;
gtk_window_maximize(GTK_WINDOW(window));
gtk_widget_show_all (window);
-
+
+ //#1662197/1660910 moved after resize/show
+ DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
+
+ if(PREFS->wal_hpaned > 0)
+ gtk_paned_set_position(GTK_PANED(data->hpaned), PREFS->wal_hpaned);
+ if(PREFS->wal_vpaned > 0)
+ gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned);
+
//todo: move this elsewhere
DB( g_print(" - setup stuff\n") );
/* GtkWindow events */
g_signal_connect (window, "delete-event", G_CALLBACK (ui_mainwindow_dispose), (gpointer)data);
+ g_signal_connect (window, "destroy", G_CALLBACK (ui_mainwindow_destroy), NULL);
g_signal_connect (window, "screen-changed",
--- /dev/null
- wording(Transaction* SELF, ...)
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#include <string.h>
+
+#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*
- if (SELF->wording) g_free(SELF->wording);
- SELF->wording = g_strdup(SvGchar_ptr(ST(1)));
++memo(Transaction* SELF, ...)
+ CODE:
+ if (1 < items) {
- RETVAL = SELF->wording ? SELF->wording : "";
++ if (SELF->memo) g_free(SELF->memo);
++ SELF->memo = g_strdup(SvGchar_ptr(ST(1)));
+ }
- SELF->wording, SELF->date, SELF->kacc, SELF->kxferacc, SELF->flags, SELF->paymode, SELF->kpay, SELF->kcat);
++ 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->memo, SELF->date, SELF->kacc, SELF->kxferacc, SELF->flags, SELF->paymode, SELF->kpay, SELF->kcat);
+
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-account.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
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) );
g_queue_free (item->txn_queue);
- g_free(item);
+ rc_free(item);
}
}
Account *item;
DB( g_print("da_acc_malloc\n") );
- item = g_malloc0(sizeof(Account));
+ item = rc_alloc(sizeof(Account));
item->txn_queue = g_queue_new ();
return item;
}
*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;
}
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;
}
}
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) );
+ DB( g_print("%10.6f => %10.6f, %s\n", oldamount, txn->amount, txn->memo) );
//todo: sync child xfer
lnk_txn = g_list_next(lnk_txn);
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-archive.h"
#include "hb-split.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
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)
{
//duplicate the string
- new_item->wording = g_strdup(src_item->wording);
-
+ new_item->memo = g_strdup(src_item->memo);
+
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);
+ if(item->memo != NULL)
+ g_free(item->memo);
da_splits_free(item->splits);
//item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
- g_free(item);
+ rc_free(item);
}
}
+
void da_archive_destroy(GList *list)
{
GList *tmplist = g_list_first(list);
g_list_free(list);
}
+
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+
static gint da_archive_glist_compare_func(Archive *a, Archive *b)
{
- return hb_string_utf8_compare(a->wording, b->wording);
+ return hb_string_utf8_compare(a->memo, b->memo);
}
return g_list_sort(list, (GCompareFunc)da_archive_glist_compare_func);
}
+
guint da_archive_length(void)
{
return g_list_length(GLOBALS->arc_list);
}
+
void da_archive_consistency(Archive *item)
{
Account *acc;
Archive *da_archive_init_from_transaction(Archive *arc, Transaction *txn)
{
+ DB( g_print("\n[scheduled] init from txn\n") );
+
//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->paymode = txn->paymode;
+ arc->flags = txn->flags & (OF_INCOME);
arc->status = txn->status;
- arc->kpay = txn->kpay;
+ arc->kpay = txn->kpay;
arc->kcat = txn->kcat;
- if(txn->wording != NULL)
- arc->wording = g_strdup(txn->wording);
+ if(txn->memo != NULL)
+ arc->memo = g_strdup(txn->memo);
else
- arc->wording = g_strdup(_("(new archive)"));
+ arc->memo = g_strdup(_("(new archive)"));
if( da_splits_clone(txn->splits, arc->splits) > 0)
arc->flags |= OF_SPLIT; //Flag that Splits are active
}
-
-
- static guint32 _sched_date_get_next_post(Archive *arc, guint32 nextdate)
+ static guint32 _sched_date_get_next_post(GDate *tmpdate, Archive *arc, guint32 nextdate)
{
- GDate *tmpdate;
guint32 nextpostdate = nextdate;
- DB( g_print("\n[scheduled] _sched_date_get_next_post\n") );
+ //DB( g_print("\n[scheduled] date_get_next_post\n") );
+
+ g_date_set_julian(tmpdate, nextpostdate);
+
+ //DB( g_print("in : %2d-%2d-%4d\n", g_date_get_day(tmpdate), g_date_get_month (tmpdate), g_date_get_year(tmpdate) ) );
- tmpdate = g_date_new_julian(nextpostdate);
switch(arc->unit)
{
case AUTO_UNIT_DAY:
break;
}
+ //DB( g_print("out: %2d-%2d-%4d\n", g_date_get_day(tmpdate), g_date_get_month (tmpdate), g_date_get_year(tmpdate) ) );
+
+
/* get the final post date and free */
nextpostdate = g_date_get_julian(tmpdate);
- g_date_free(tmpdate);
return nextpostdate;
}
guint32 finalpostdate;
gint shift;
- DB( g_print("\n[scheduled] scheduled_get_postdate\n") );
+ DB( g_print("\n[scheduled] get_postdate\n") );
finalpostdate = postdate;
{
wday = g_date_get_weekday(tmpdate);
- DB( g_print(" %s wday=%d\n", arc->wording, wday) );
+ DB( g_print(" %s wday=%d\n", arc->memo, wday) );
if( wday >= G_DATE_SATURDAY )
{
guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate)
{
- guint32 curdate = jrefdate - arc->nextdate;
+ GDate *post_date;
+ guint32 curdate;
guint32 nblate = 0;
+ //DB( g_print("\n[scheduled] get_latepost_count\n") );
+
/*
+ curdate = jrefdate - arc->nextdate;
switch(arc->unit)
{
case AUTO_UNIT_DAY:
// pre 5.1 way
+ post_date = g_date_new();
curdate = arc->nextdate;
while(curdate <= jrefdate)
{
- curdate = _sched_date_get_next_post(arc, curdate);
+ curdate = _sched_date_get_next_post(post_date, arc, curdate);
nblate++;
// break if over limit or at 11 max (to display +10)
if(nblate >= arc->limit || nblate >= 11)
break;
}
+ //DB( g_print(" nblate=%d\n", nblate) );
+
+ g_date_free(post_date);
+
return nblate;
}
/* return 0 is max number of post is reached */
guint32 scheduled_date_advance(Archive *arc)
{
- arc->nextdate = _sched_date_get_next_post(arc, arc->nextdate);
-
+ GDate *post_date;
+ gushort lastday;
+
+ DB( g_print("\n[scheduled] date_advance\n") );
+
+ DB( g_print(" arc: '%s'\n", arc->memo ) );
+
+ post_date = g_date_new();
+ g_date_set_julian(post_date, arc->nextdate);
+ // saved the current day number
+ lastday = g_date_get_day(post_date);
+
+ arc->nextdate = _sched_date_get_next_post(post_date, arc, arc->nextdate);
+
+ DB( g_print(" raw next post date: %2d-%2d-%4d\n", g_date_get_day(post_date), g_date_get_month (post_date), g_date_get_year(post_date) ) );
+
+ //for day > 28 we might have a gap to compensate later
+ if( (arc->unit==AUTO_UNIT_MONTH) || (arc->unit==AUTO_UNIT_YEAR) )
+ {
+ if( lastday >= 28 )
+ {
+ DB( g_print(" lastday:%d, daygap:%d\n", lastday, arc->daygap) );
+ if( arc->daygap > 0 )
+ {
+ g_date_add_days (post_date, arc->daygap);
+ arc->nextdate = g_date_get_julian (post_date);
+ lastday += arc->daygap;
+ DB( g_print(" adjusted post date: %2d-%2d-%4d\n", g_date_get_day(post_date), g_date_get_month (post_date), g_date_get_year(post_date) ) );
+ }
+
+ arc->daygap = CLAMP(lastday - g_date_get_day(post_date), 0, 3);
+
+ DB( g_print(" daygap is %d\n", arc->daygap) );
+ }
+ else
+ arc->daygap = 0;
+ }
+
+
//#1556289
/* check limit, update and maybe break */
if(arc->flags & OF_LIMIT)
arc->nextdate = 0;
}
}
-
+
+ g_date_free(post_date);
+
return arc->nextdate;
}
{
Archive *arc = list->data;
- DB( g_print("\n eval %d for '%s'\n", scheduled_is_postable(arc), arc->wording) );
+ DB( g_print("\n eval %d for '%s'\n", scheduled_is_postable(arc), arc->memo) );
if(scheduled_is_postable(arc) == TRUE)
{
while(mydate < maxpostdate)
{
- DB( hb_print_date(mydate, arc->wording) );
+ DB( hb_print_date(mydate, arc->memo) );
da_transaction_init_from_template(txn, arc);
txn->date = scheduled_get_postdate(arc, mydate);
/* todo: ? fill in cheque number */
- transaction_add(txn, NULL, 0);
+ transaction_add(txn);
GLOBALS->changes_count++;
count++;
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-assign.h"
+#include "ext.h"
+#include "refcount.h"
+
#define MYDEBUG 0
#if MYDEBUG
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->text) );
g_free(item->text);
- g_free(item);
+ rc_free(item);
}
}
da_asg_malloc(void)
{
DB( g_print("da_asg_malloc\n") );
- return g_malloc0(sizeof(Assign));
+ return rc_alloc(sizeof(Assign));
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-category.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
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)
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);
}
}
da_cat_malloc(void)
{
DB( g_print("da_cat_malloc\n") );
- return g_malloc0(sizeof(Category));
+ return rc_alloc(sizeof(Category));
}
newcat->imported = imported;
newcat->flags |= GF_SUB;
+ //#1713413 take parent type into account
+ if(parent->flags & GF_INCOME)
+ newcat->flags |= GF_INCOME;
DB( g_print(" -> insert subcat '%s' id: %d\n", newcat->name, newcat->key) );
GList *lst_acc, *lnk_acc;
GList *lnk_txn;
GList *lpay, *lrul, *list;
+ guint i, nbsplit;
lcat = list = g_hash_table_get_values(GLOBALS->h_cat);
while (list != NULL)
{
Transaction *txn = lnk_txn->data;
- category_fill_usage_count(txn->kcat);
+ //#1689308 count split as well
+ if( txn->flags & OF_SPLIT )
+ {
+ nbsplit = da_splits_count(txn->splits);
+ for(i=0;i<nbsplit;i++)
+ {
+ Split *split = txn->splits[i];
+
+ category_fill_usage_count(split->kcat);
+ }
+ }
+ else
+ category_fill_usage_count(txn->kcat);
+
lnk_txn = g_list_next(lnk_txn);
}
lnk_acc = g_list_next(lnk_acc);
{
Archive *entry = list->data;
- category_fill_usage_count(entry->kcat);
+ //#1689308 count split as well
+ if( entry->flags & OF_SPLIT )
+ {
+ nbsplit = da_splits_count(entry->splits);
+ for(i=0;i<nbsplit;i++)
+ {
+ Split *split = entry->splits[i];
+
+ category_fill_usage_count(split->kcat);
+ }
+ }
+ else
+ category_fill_usage_count(entry->kcat);
+
list = g_list_next(list);
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-payee.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
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);
}
}
da_pay_malloc(void)
{
DB( g_print("da_pay_malloc\n") );
- return g_malloc0(sizeof(Payee));
+ return rc_alloc(sizeof(Payee));
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
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));
}
PREFS->lst_ope_columns[i++] = LST_DSPOPE_DATE;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_INFO;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_PAYEE;
- PREFS->lst_ope_columns[i++] = LST_DSPOPE_WORDING;
+ PREFS->lst_ope_columns[i++] = LST_DSPOPE_MEMO;
PREFS->lst_ope_columns[i++] = -LST_DSPOPE_AMOUNT;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_EXPENSE;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_INCOME;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_EXPENSE;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_INCOME;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_BALANCE;
- PREFS->lst_ope_columns[i++] = LST_DSPOPE_WORDING;
+ PREFS->lst_ope_columns[i++] = LST_DSPOPE_MEMO;
PREFS->lst_ope_sort_id = LST_DSPOPE_DATE;
PREFS->lst_ope_sort_order = GTK_SORT_ASCENDING;
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_init_measurement_units();
}
string = g_key_file_get_string(key_file, group_name, key, NULL);
if( string != NULL )
{
- *storage = g_strdup(string);
+ //*storage = g_strdup(string);
+ //leak
+ *storage = string; //already a new allocated string
//DB( g_print(" store '%s' for %s at %x\n", string, key, *storage) );
}
DB( g_print(" - copying column width from pref file\n") );
memcpy(PREFS->lst_ope_col_size, src, length*sizeof(gint));
}
+
+ //leak
+ g_free(src);
+
}
homebank_pref_get_integer(keyfile, group, "OpeSortId", &PREFS->lst_ope_sort_id);
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);
//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;
g_key_file_set_integer (keyfile, group, "BarStyle", PREFS->toolbar_style);
//g_key_file_set_integer (keyfile, group, "BarImageSize", PREFS->image_size);
+
+
g_key_file_set_boolean (keyfile, group, "CustomColors", PREFS->custom_colors);
g_key_file_set_string (keyfile, group, "ColorExp" , PREFS->color_exp);
g_key_file_set_string (keyfile, group, "ColorInc" , PREFS->color_inc);
homebank_pref_set_string (keyfile, group, "ExportPath" , PREFS->path_export);
//g_key_file_set_string (keyfile, group, "NavigatorPath", PREFS->path_navigator);
+
+
+
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);
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, "DateFutureNbDays", PREFS->date_future_nbdays);
g_key_file_set_integer (keyfile, group, "DateRangeRep", PREFS->date_range_rep);
DB( g_print(" -> ** euro\n") );
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);
//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->);
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
gchar *vehicle_unit_100;
gchar *vehicle_unit_distbyvol;
+ // plugins
+ gchar** ext_path;
+ GList* ext_whitelist;
+
};
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-tag.h"
+#include "ext.h"
+#include "refcount.h"
+
#define MYDEBUG 0
#if MYDEBUG
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);
}
}
Tag *da_tag_malloc(void)
{
DB( g_print("da_tag_malloc\n") );
- return g_malloc0(sizeof(Tag));
+ return rc_alloc(sizeof(Tag));
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-tag.h"
#include "hb-split.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
{
if(item != NULL)
{
- if(item->wording != NULL)
+ if(item->memo != NULL)
{
- g_free(item->wording);
- item->wording = NULL;
+ g_free(item->memo);
+ item->memo = NULL;
}
if(item->info != NULL)
{
}
-
void
da_transaction_free(Transaction *item)
{
- if(item != NULL)
+ if(rc_unref(item))
{
da_transaction_clean(item);
- g_free(item);
+ rc_free(item);
}
}
Transaction *
da_transaction_malloc(void)
{
- return g_malloc0(sizeof(Transaction));
+ return rc_alloc(sizeof(Transaction));
}
memmove(dst_txn, src_txn, sizeof(Transaction));
//duplicate the string
- dst_txn->wording = g_strdup(src_txn->wording);
+ dst_txn->memo = g_strdup(src_txn->memo);
dst_txn->info = g_strdup(src_txn->info);
//duplicate tags
txn->kpay = arc->kpay;
txn->kcat = arc->kcat;
txn->kxferacc = arc->kxferacc;
- txn->wording = g_strdup(arc->wording);
+ txn->memo = g_strdup(arc->memo);
txn->info = NULL;
if( da_splits_clone(arc->splits, txn->splits) > 0)
txn->flags |= OF_SPLIT; //Flag that Splits are active
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));
DB( g_print("da_transaction_clone\n") );
if(new_item)
{
//duplicate the string
- new_item->wording = g_strdup(src_item->wording);
+ new_item->memo = g_strdup(src_item->memo);
new_item->info = g_strdup(src_item->info);
//duplicate tags
}
- static void da_transaction_insert_memo(Transaction *item)
+ gboolean da_transaction_insert_memo(Transaction *item)
{
+ gboolean retval = FALSE;
+
// append the memo if new
- if( item->wording != NULL )
+ if( item->memo != NULL )
{
- if( g_hash_table_lookup(GLOBALS->h_memo, item->wording) == NULL )
+ if( g_hash_table_lookup(GLOBALS->h_memo, item->memo) == NULL )
{
- g_hash_table_insert(GLOBALS->h_memo, g_strdup(item->wording), NULL);
+ retval = g_hash_table_insert(GLOBALS->h_memo, g_strdup(item->memo), NULL);
}
}
+ return retval;
}
Account *acc;
acc = da_acc_get(item->kacc);
- if(acc)
- item->kcur = acc->kcur;
+ //#1661279
+ if(!acc)
+ return FALSE;
+
+ item->kcur = acc->kcur;
g_queue_push_tail(acc->txn_queue, item);
da_transaction_insert_memo(item);
return TRUE;
static void da_transaction_goto_orphan(Transaction *txn)
{
const gchar *oatn = "orphaned transactions";
- Account *acc;
+ Account *ori_acc, *acc;
+ gboolean found;
+
+ DB( g_print("\n[transaction] goto orphan\n") );
+
+ g_warning("txn consistency: moving to orphan %d '%s' %.2f", txn->date, txn->memo, txn->amount);
acc = da_acc_get_by_name((gchar *)oatn);
if(acc == NULL)
acc = da_acc_malloc();
acc->name = g_strdup(oatn);
da_acc_append(acc);
+ DB( g_print(" - created orphan acc %d\n", acc->key) );
+ }
+
+ ori_acc = da_acc_get(txn->kacc);
+ if( ori_acc )
+ {
+ found = g_queue_remove(ori_acc->txn_queue, txn);
+ DB( g_print(" - found in origin ? %d\n", found) );
+ if(found)
+ {
+ txn->kacc = acc->key;
+ da_transaction_insert_sorted (txn);
+ DB( g_print("moved txn to %d\n", txn->kacc) );
+ }
}
- txn->kacc = acc->key;
}
Payee *pay;
gint nbsplit;
+ DB( g_print("\n[transaction] consistency\n") );
+
// ensure date is between range
item->date = CLAMP(item->date, HB_MINDATE, HB_MAXDATE);
// reset dst acc for non xfer transaction
if( item->paymode != PAYMODE_INTXFER )
+ {
+ item->kxfer = 0;
item->kxferacc = 0;
+ }
+
+ // check dst account exists
+ if( item->paymode == PAYMODE_INTXFER )
+ {
+ gint tak = item->kxferacc;
+
+ item->kxferacc = ABS(tak); //I crossed negative here one day
+ acc = da_acc_get(item->kxferacc);
+ if(acc == NULL)
+ {
+ g_warning("txn consistency: fixed invalid dst_acc %d", item->kxferacc);
+ da_transaction_goto_orphan(item);
+ item->kxfer = 0;
+ item->paymode = PAYMODE_XFER;
+ GLOBALS->changes_count++;
+ }
+ }
//#1628678 tags for internal xfer should be checked as well
child->amount = -child->amount;
child->flags ^= (OF_INCOME); // invert flag
- //#1268026
- child->status = TXN_STATUS_NONE;
+ //#1268026 #1690555
+ if( child->status != TXN_STATUS_REMIND )
+ child->status = TXN_STATUS_NONE;
//child->flags &= ~(OF_VALID); // delete reconcile state
swap = child->kacc;
account_balances_add (child);
+ GValue txn_value = G_VALUE_INIT;
+ ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL);
+
}
}
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) );
+ //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->memo, item->amount, item->account, item->kxferacc) );
matchlist = g_list_append(matchlist, item);
}
list = g_list_previous(list);
if( !dstacc || src->kxfer <= 0 )
return NULL;
- DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src->date, src->wording, src->amount, src->kacc, src->kxferacc, src->kxfer) );
+ DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src->date, src->memo, src->amount, src->kacc, src->kxferacc, src->kxfer) );
list = g_queue_peek_tail_link(dstacc->txn_queue);
while (list != NULL)
&& item->kxfer == src->kxfer
&& item != src )
{
- DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item->date, item->wording, item->amount, item->kacc, item->kxferacc, src->kxfer) );
+ DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item->date, item->memo, item->amount, item->kacc, item->kxferacc, src->kxfer) );
return item;
}
list = g_list_previous(list);
}
- void transaction_xfer_sync_child(Transaction *s_txn, Transaction *child)
+ void transaction_xfer_child_sync(Transaction *s_txn, Transaction *child)
{
+ Account *acc;
- DB( g_print("\n[transaction] xfer_sync_child\n") );
+ DB( g_print("\n[transaction] xfer_child_sync\n") );
+
+ if( child == NULL )
+ {
+ DB( g_print(" - no child found\n") );
+ return;
+ }
+
+ DB( g_print(" - found do sync\n") );
+
+ /* update acc flags */
+ acc = da_acc_get( child->kacc);
+ if(acc != NULL)
+ acc->flags |= AF_CHANGED;
account_balances_sub (child);
child->flags |= (OF_INCOME);
child->kpay = s_txn->kpay;
child->kcat = s_txn->kcat;
- if(child->wording)
- g_free(child->wording);
- child->wording = g_strdup(s_txn->wording);
+ if(child->memo)
+ g_free(child->memo);
+ child->memo = g_strdup(s_txn->memo);
if(child->info)
g_free(child->info);
child->info = g_strdup(s_txn->info);
+ account_balances_add (child);
+
//#1252230 sync account also
- child->kacc = s_txn->kxferacc;
- child->kxferacc = s_txn->kacc;
+ //#1663789 idem after 5.1
+ //source changed: update child key (move of s_txn is done in external_edit)
+ if( s_txn->kacc != child->kxferacc )
+ {
+ child->kxferacc = s_txn->kacc;
+ }
+
+ //dest changed: move child & update child key
+ if( s_txn->kxferacc != child->kacc )
+ {
+ transaction_acc_move(child, child->kacc, s_txn->kxferacc);
+ }
- account_balances_add (child);
-
//synchronise tags since 5.1
if(child->tags)
g_free(child->tags);
DB( g_print("\n[transaction] xfer_remove_child\n") );
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);
- g_queue_remove(acc->txn_queue, dst);
- da_transaction_free (dst);
+ if( acc != NULL )
+ {
+ DB( g_print("deleting...") );
+ account_balances_sub(dst);
+ g_queue_remove(acc->txn_queue, dst);
+ //#1419304 we keep the deleted txn to a trash stack
+ //da_transaction_free (dst);
+ g_trash_stack_push(&GLOBALS->txn_stk, dst);
+
+ //#1691992
+ acc->flags |= AF_CHANGED;
+ }
}
+
+ src->kxfer = 0;
+ src->kxferacc = 0;
}
DB( g_print("\n[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) );
+ //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->memo, src->amount, src->account, src->kxferacc) );
acc = da_acc_get(src->kxferacc);
- list = g_queue_peek_head_link(acc->txn_queue);
- while (list != NULL)
+ if( acc != NULL )
{
- Transaction *item = list->data;
+ list = g_queue_peek_head_link(acc->txn_queue);
+ while (list != NULL)
+ {
+ Transaction *item = list->data;
- // no need to go higher than src txn date
- if(item->date > src->date)
- break;
+ // 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 &&
- src->kacc == item->kxferacc &&
- src->kxferacc == item->kacc &&
- ABS(src->amount) == ABS(item->amount) )
+ if( item->paymode == PAYMODE_INTXFER)
{
- //DB( g_print(" found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
+ if( src->date == item->date &&
+ src->kacc == item->kxferacc &&
+ src->kxferacc == item->kacc &&
+ ABS(src->amount) == ABS(item->amount) )
+ {
+ //DB( g_print(" found : %d %s %f %d=>%d\n", item->date, item->memo, item->amount, item->account, item->kxferacc) );
- return item;
+ return item;
+ }
}
+ list = g_list_next(list);
}
- list = g_list_next(list);
}
DB( g_print(" not found...\n") );
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- void transaction_add(Transaction *ope, GtkWidget *treeview, guint32 accnum)
+ void transaction_remove(Transaction *ope)
+ {
+ Account *acc;
+
+ //controls accounts valid (archive scheduled maybe bad)
+ acc = da_acc_get(ope->kacc);
+ if(acc == NULL) return;
+
+ account_balances_sub(ope);
+
+ if( ope->paymode == PAYMODE_INTXFER )
+ {
+ transaction_xfer_remove_child( ope );
+ }
+
+ g_queue_remove(acc->txn_queue, ope);
+ acc->flags |= AF_CHANGED;
+ //#1419304 we keep the deleted txn to a trash stack
+ //da_transaction_free(entry);
+ g_trash_stack_push(&GLOBALS->txn_stk, ope);
+ }
+
+
+ Transaction *transaction_add(Transaction *ope)
{
Transaction *newope;
Account *acc;
//controls accounts valid (archive scheduled maybe bad)
acc = da_acc_get(ope->kacc);
- if(acc == NULL) return;
+ if(acc == NULL) return NULL;
DB( g_print(" acc is '%s' %d\n", acc->name, acc->key) );
if(ope->paymode == PAYMODE_INTXFER)
{
acc = da_acc_get(ope->kxferacc);
- if(acc == NULL) return;
+ if(acc == NULL) return NULL;
// delete any splits
da_splits_free(ope->splits);
/* get the active account and the corresponding cheque number */
acc = da_acc_get( newope->kacc);
- cheque = atol(newope->info);
-
- //DB( g_print(" -> should store cheque number %d to %d", cheque, newope->account) );
- if( newope->flags & OF_CHEQ2 )
+ if( acc != NULL )
{
- acc->cheque2 = MAX(acc->cheque2, cheque);
- }
- else
- {
- acc->cheque1 = MAX(acc->cheque1, cheque);
+ cheque = atol(newope->info);
+
+ //DB( g_print(" -> should store cheque number %d to %d", cheque, newope->account) );
+ if( newope->flags & OF_CHEQ2 )
+ {
+ acc->cheque2 = MAX(acc->cheque2, cheque);
+ }
+ else
+ {
+ acc->cheque1 = MAX(acc->cheque1, cheque);
+ }
}
}
//da_transaction_append(newope);
da_transaction_insert_sorted(newope);
- if(treeview != NULL)
- transaction_add_treeview(newope, treeview, accnum);
-
account_balances_add(newope);
if(newope->paymode == PAYMODE_INTXFER)
{
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;
}
DB( g_print("\n[transaction] acc_move\n") );
+ if( okacc == nkacc )
+ return TRUE;
+
oacc = da_acc_get(okacc);
nacc = da_acc_get(nkacc);
if( oacc && nacc )
{
+ account_balances_sub(txn);
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;
+ account_balances_add(txn);
return TRUE;
}
else
+ {
//ensure to keep txn into current account
txn->kacc = okacc;
+ account_balances_add(txn);
+ }
}
return FALSE;
}
if(text == NULL)
return FALSE;
- //DB( g_print("search %s in %s\n", rul->name, ope->wording) );
+ //DB( g_print("search %s in %s\n", rul->name, ope->memo) );
if( searchtext != NULL )
{
if( exact == TRUE )
Assign *rul = list->data;
gchar *text;
- text = txn->wording;
+ text = txn->memo;
if(rul->field == 1) //payee
{
Payee *pay = da_pay_get(txn->kpay);
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) );
+ DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope->memo, ope->kacc, ope->kpay, ope->kcat) );
//#1215521: added kacc == 0
if( (kacc == ope->kacc || kacc == 0) )
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-transaction.h"
#include "hb-xml.h"
+#include "ext.h"
+
#include "ui-dialogs.h"
/****************************************************************************/
// v0.6 to v0.7 : assign a default currency
static void homebank_upgrade_to_v12(void)
{
+ DB( g_print("\n[hb-xml] homebank_upgrade_to_v12\n") );
+
// set a base currency to the hbfile if not
DB( g_print("GLOBALS->kcur %d\n", GLOBALS->kcur) );
}
+ static void homebank_upgrade_to_v12_7(void)
+ {
+ GList *lst_acc, *lnk_acc;
+
+ DB( g_print("\n[hb-xml] homebank_upgrade_to_v12\n") );
+
+ //#1674045 exclude closed account from everywhere to
+ //keep continuity for user that don't want to change this
+ 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 )
+ {
+ if( !(acc->flags & AF_NOSUMMARY) )
+ acc->flags |= AF_NOSUMMARY;
+ if( !(acc->flags & AF_NOBUDGET) )
+ acc->flags |= AF_NOBUDGET;
+ if( !(acc->flags & AF_NOREPORT) )
+ acc->flags |= AF_NOREPORT;
+ }
+ lnk_acc = g_list_next(lnk_acc);
+ }
+ g_list_free(lst_acc);
+ }
+
// lower v0.6 : we must assume categories/payee exists
// and strong link to xfer
{
//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]); }
+ 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], "iso" )) { entry->iso_code = g_strdup(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "symb" )) { entry->symbol = g_strdup(attribute_values[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], "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], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->memo = 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], "gap" )) { entry->daygap = 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; }
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], "wording" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->memo = 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" ))
{
}
//all attribute loaded: append
- // we use prepend here, the list will be reversed later for perf reason
+ // for perf reason we use prepend here, the list will be reversed later
da_transaction_prepend(entry);
}
homebank_load_xml_tag(ctx, attribute_names, attribute_values);
}
}
+ break;
case 'f':
{
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))
{
DB( g_timer_destroy (t) );
/* 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 )
- {
- homebank_upgrade_to_v06();
- homebank_upgrade_lower_v06();
- }
- if( ctx.file_version <= 0.6 )
+ // group a test for very old version
+ if( ctx.file_version <= 1.0 )
{
- 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();
- }
+ 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 )
+ {
+ 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
+ //file version is changed only when the structure change
+ //don't start number below with 0 to avoid octal interpretation
+ if( ctx.data_version <= 50005 ) // <= 5.0.5
{
hbfile_sanity_check();
}
- if( ctx.file_version <= 1.1 ) // <= 5.1.0
+ if( ctx.file_version <= 1.1 ) // <= 5.1.0
{
hbfile_sanity_check();
homebank_upgrade_to_v12();
}
+ if( ctx.data_version <= 50106 ) // < 5.1.6
+ {
+ homebank_upgrade_to_v12_7();
+ }
// next ?
}
-
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/*
Currency *item = list->data;
tmpstr = g_markup_printf_escaped(
- "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
+ "<cur key=\"%d\" flags=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\"/>\n",
item->key,
+ item->flags,
item->iso_code,
item->name,
item->symbol,
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, "wording", item->memo);
hb_xml_append_int(node, "nextdate", item->nextdate);
hb_xml_append_int(node, "every", item->every);
hb_xml_append_int(node, "unit", item->unit);
hb_xml_append_int(node, "limit", item->limit);
hb_xml_append_int(node, "weekend", item->weekend);
+ hb_xml_append_int(node, "gap", item->daygap);
if(da_splits_count(item->splits) > 0)
{
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, "wording", item->memo);
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)
- {
+ if(da_splits_count(item->splits) > 0)
+ {
gchar *cats, *amounts, *memos;
da_splits_tostring(item->splits, &cats, &amounts, &memos);
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", &error);
if(io == NULL)
{
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "homebank.h"
+#include "ext.h"
#include "dsp_mainwindow.h"
#include "hb-preferences.h"
#include "language.h"
-
#ifdef G_OS_WIN32
#include <windows.h>
#endif
#define APPLICATION_NAME "HomeBank"
+
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
static gchar *locale_dir = NULL;
static gchar *help_dir = NULL;
static gchar *datas_dir = NULL;
+static gchar *pkglib_dir = NULL;
//#define MARKUP_STRING "<span size='small'>%s</span>"
{
g_io_channel_set_encoding(io, NULL, NULL); /* set to binary mode */
- for(i=0;i<4;i++)
+ for(i=0;i<25;i++)
{
if( retval != FILETYPE_UNKNOW )
break;
g_str_has_prefix(tmpstr, "!option") ||
g_str_has_prefix(tmpstr, "!Account") ||
g_str_has_prefix(tmpstr, "!account")
- )
+ )
{
DB( g_print(" type is QIF\n") );
retval = FILETYPE_QIF;
else
/* is it OFX ? */
- if( g_strstr_len(tmpstr, 10, "OFX") != NULL)
+ if( g_strstr_len(tmpstr, -1, "<OFX>") != NULL
+ || g_strstr_len(tmpstr, -1, "<ofx>") != NULL
+ /*|| strcasestr(tmpstr, "<OFC>") != NULL*/
+ )
{
DB( g_print(" type is OFX\n") );
retval = FILETYPE_OFX;
{
gchar *newfilename;
- newfilename = hb_util_filename_new_with_extension(filename, "xhb");
+ newfilename = hb_filename_new_with_extension(filename, "xhb");
hbfile_change_filepath(newfilename);
DB( g_print(" - changed to: '%s'\n", GLOBALS->xhb_filepath) );
}
}
- static gboolean homebank_copy_file(gchar *srcfile, gchar *dstfile)
+ static gboolean homebank_file_copy(gchar *srcfile, gchar *dstfile)
{
gchar *buffer;
gsize length;
//GError *error = NULL;
gboolean retval = FALSE;
+ DB( g_print("\n[homebank] file copy\n") );
+
if (g_file_get_contents (srcfile, &buffer, &length, NULL))
{
if(g_file_set_contents(dstfile, buffer, length, NULL))
}
g_free(buffer);
}
+
+ DB( g_print(" - copied '%s' => '%s' :: %d\n", srcfile, dstfile, retval) );
return retval;
}
- void homebank_backup_current_file(void)
+ static gboolean homebank_file_delete_existing(gchar *filepath)
{
- gchar *bakfilename;
+ gboolean retval = FALSE;
- DB( g_print("\n[homebank] backup_current_file\n") );
+ DB( g_print("\n[homebank] file delete existing\n") );
- bakfilename = hb_util_filename_new_with_extension (GLOBALS->xhb_filepath, "xhb~");
- if( g_file_test(bakfilename, G_FILE_TEST_EXISTS) )
+ if( g_file_test(filepath, G_FILE_TEST_EXISTS) )
{
- DB( g_print(" - delete existing: '%s'\n", bakfilename) );
- g_remove(bakfilename);
+ g_remove(filepath);
+ retval = TRUE;
}
- DB( g_print(" - copy '%s' => '%s'\n", GLOBALS->xhb_filepath, bakfilename) );
+ DB( g_print(" - deleted: '%s' :: %d\n", filepath, retval) );
+ return retval;
+ }
+
+ void homebank_backup_current_file(void)
+ {
+ gchar *bakfilename;
+
+ DB( g_print("\n[homebank] backup_current_file\n") );
+
+ //do normal linux backup file
+ DB( g_print(" normal backup with ~\n") );
+ bakfilename = hb_filename_new_with_extension (GLOBALS->xhb_filepath, "xhb~");
+ homebank_file_delete_existing(bakfilename);
//#512046 copy file not to broke potential links
//retval = g_rename(pathname, newname);
- homebank_copy_file (GLOBALS->xhb_filepath, bakfilename);
-
+ homebank_file_copy (GLOBALS->xhb_filepath, bakfilename);
g_free(bakfilename);
}
+
/* = = = = = = = = = = = = = = = = = = = = */
/* url open */
/*
** load lastopenedfiles from homedir/.homebank
*/
- gboolean homebank_lastopenedfiles_load(void)
+ gchar *homebank_lastopenedfiles_load(void)
{
GKeyFile *keyfile;
- gboolean retval = FALSE;
- gchar *group, *filename, *lastfilename;
+ gchar *group, *filename, *tmpfilename;
+ gchar *lastfilename = NULL;
DB( g_print("\n[homebank] lastopenedfiles load\n") );
keyfile = g_key_file_new();
if(keyfile)
{
-
filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
-
- 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") );
-
if(g_key_file_has_key(keyfile, group, "LastOpenedFile", NULL))
{
- 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 ) );
+ tmpfilename = g_key_file_get_string (keyfile, group, "LastOpenedFile", NULL);
// #593082
- if (g_file_test (lastfilename, G_FILE_TEST_EXISTS) != FALSE)
+ if (g_file_test (tmpfilename, G_FILE_TEST_EXISTS) != FALSE)
{
- DB( g_print(" - file exists\n") );
-
- hbfile_change_filepath(lastfilename);
-
- retval = TRUE;
+ lastfilename = tmpfilename;
}
}
}
g_key_file_free (keyfile);
}
- DB( g_print(" - return: %d\n", retval) );
-
- return retval;
+ return lastfilename;
}
return datas_dir;
}
+const gchar *
+homebank_app_get_pkglib_dir (void)
+{
+ return pkglib_dir;
+}
+
/* build package paths at runtime */
static 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);
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);
+ 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
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) );
}
g_free (pixmaps_dir);
g_free (locale_dir);
g_free (help_dir);
+ g_free (pkglib_dir);
}
int
-main (int argc, char *argv[])
+main (int argc, char *argv[], char *env[])
{
GOptionContext *option_context;
GOptionGroup *option_group;
/* change the locale if a language is specified */
language_init (PREFS->language);
+ 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();
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)
{
if( openlast )
{
- if( homebank_lastopenedfiles_load() == TRUE )
+ gchar *lastfilepath;
+
+ lastfilepath = homebank_lastopenedfiles_load();
+ if( lastfilepath != NULL )
+ {
+ //#1710955 test for backup open
+ if( hbfile_file_isbackup(lastfilepath) )
+ {
+ if( ui_mainwindow_open_backup_check_confirm(lastfilepath) == TRUE )
+ {
+ GLOBALS->hbfile_is_bak = TRUE;
+ }
+ else
+ {
+ g_free(lastfilepath);
+ goto nobak;
+ }
+ }
+
+ hbfile_change_filepath(lastfilepath);
ui_mainwindow_open_internal(mainwin, NULL);
+
+ }
}
/* -- hack to generate a big file -- */
-
+ nobak:
/* update the mainwin display */
ui_mainwindow_update(mainwin, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_VISUAL));
- DB( g_print(" - gtk_main()\n" ) );
-
+ ext_hook("enter_main_loop", NULL);
+
+ 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();
+
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
/* = = = = = = = = = = = = = = = = */
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
- #define HB_UNSTABLE FALSE
+ #define HB_UNSTABLE FALSE
#define HB_UNSTABLE_SHOW FALSE
#define HB_VERSION_MAJOR 5
#define HB_VERSION_MINOR 1
- #define HB_VERSION_MICRO 3
+ #define HB_VERSION_MICRO 7
- #define HB_VERSION "5.1.3"
+ #define HB_VERSION "5.1.7"
#define HB_VERSION_NUM (HB_VERSION_MAJOR*10000) + (HB_VERSION_MINOR*100) + HB_VERSION_MICRO
#define FILE_VERSION 1.2
- #define PREF_VERSION 513
+ #define PREF_VERSION 517
#if HB_UNSTABLE == FALSE
#define PROGNAME "HomeBank"
* GTK_ICON_SIZE_DIALOG 48
*/
+
/* -------- named icons (Standard Icon Name) -------- */
#define ICONNAME_NEW "document-new"
#define ICONNAME_OPEN "document-open"
#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"
+ #define ICONNAME_CHANGES_PREVENT "changes-prevent-symbolic"
// custom or gnome not found
#define ICONNAME_HB_BUTTON_MENU "open-menu-symbolic"
// hbfile (unsaved properties)
guint changes_count;
gboolean hbfile_is_new;
+ gboolean hbfile_is_bak;
gchar *xhb_filepath;
gboolean xhb_hasbak; //file has backup (*.xhb~) used for revert menu sensitivity
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);
+ gchar *homebank_lastopenedfiles_load(void);
gboolean homebank_lastopenedfiles_save(void);
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 - - - - */
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "dsp_mainwindow.h"
#include "gtk-chart-colors.h"
+#include "ext.h"
+
#include "ui-currency.h"
LST_PREF_MAX
};
- enum
- {
- COLUMN_VISIBLE,
- COLUMN_NAME,
- COLUMN_ID,
- NUM_COLUMNS
- };
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
};
"prf-import",
"prf-report",
"prf-euro", // to be renamed
+"prf-plugins",
//"prf_charts.svg"
};
N_("Display format"),
N_("Import/Export"),
N_("Report"),
-N_("Euro minor")
+N_("Euro minor"),
+N_("Plugins")
//
};
extern gchar *CYA_CHART_COLORSCHEME[];
extern gchar *CYA_MONTHS[];
- typedef struct
- {
- gshort id;
- gchar *iso;
- gchar *name;
- gdouble value;
- //gchar *prefix_symbol; /* max symbol is 3 digits in unicode */
- //gchar *suffix_symbol; /* but mostly is 1 digit */
- gchar *symbol;
- gboolean sym_prefix;
- gchar *decimal_char;
- gchar *grouping_char;
- gshort frac_digits;
- } EuroParams;
+
/*
};
- 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" },
};
+ static GtkWidget *pref_list_create(void);
+
+
static gint
ui_language_combobox_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
{
//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);
g_warning(" locale name not found '%s'", locale);
lang = locale;
}
--
++
}
return lang;
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);
{
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);
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)
ui_language_combobox_populate(combobox);
gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
--
++
return combobox;
}
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);
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);
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
gtk_widget_queue_draw (data->DA_colors);
--
++
}
DB( g_print("\n[ui-pref] set\n") );
+ // general
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_show_splash), PREFS->showsplash);
+ 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_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_wal), PREFS->date_range_wal);
+ 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);
+
+ // files/backup
+ gtk_entry_set_text(GTK_ENTRY(data->ST_path_hbfile), PREFS->path_hbfile);
+
+
+
+ // interface
if(PREFS->language != NULL)
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);
-
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_toolbar), PREFS->toolbar_style);
//gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_image_size), PREFS->image_size);
-
-
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors), PREFS->custom_colors);
-
gdk_rgba_parse(&rgba, PREFS->color_exp);
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba);
-
gdk_rgba_parse(&rgba, PREFS->color_inc);
gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba);
-
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_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);
-
- gtk_entry_set_text(GTK_ENTRY(data->ST_path_hbfile), PREFS->path_hbfile);
- gtk_entry_set_text(GTK_ENTRY(data->ST_path_import), PREFS->path_import);
- gtk_entry_set_text(GTK_ENTRY(data->ST_path_export), PREFS->path_export);
- //gtk_entry_set_text(GTK_ENTRY(data->ST_path_navigator), PREFS->path_navigator);
-
- 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);
+ // transactions
+ 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_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);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_herit_date), PREFS->heritdate);
- /* display */
+ // display format
gtk_entry_set_text(GTK_ENTRY(data->ST_datefmt), PREFS->date_format);
-
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);
+ // import/export
+ 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);
+ gtk_entry_set_text(GTK_ENTRY(data->ST_path_import), PREFS->path_import);
+ gtk_entry_set_text(GTK_ENTRY(data->ST_path_export), PREFS->path_export);
+
+ // report
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_rep), PREFS->date_range_rep);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_color_scheme), PREFS->report_color_scheme);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_byamount), PREFS->stat_byamount);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_showrate), PREFS->stat_showrate);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_showdetail), PREFS->stat_showdetail);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_budg_showdetail), PREFS->budg_showdetail);
/* euro */
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);
data->country = PREFS->euro_country;
defpref_eurosetcurrency(data->window, data->country);
-
gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_value), PREFS->euro_value);
-
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);
-
//gtk_entry_set_text(GTK_ENTRY(data->ST_euro_symbol), PREFS->euro_symbol);
//gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_nbdec), PREFS->euro_nbdec);
//gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_thsep), PREFS->euro_thsep);
-
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_byamount), PREFS->stat_byamount);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_showrate), PREFS->stat_showrate);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_stat_showdetail), PREFS->stat_showdetail);
-
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_budg_showdetail), PREFS->budg_showdetail);
-
- gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_color_scheme), PREFS->report_color_scheme);
-
- /* 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);
-
-
}
/*
** get :: fill PREFS structure from widgets
*/
-
#define RGBA_TO_INT(x) (int)(x*255)
static gchar *gdk_rgba_to_hex(GdkRGBA *rgba)
DB( g_print("\n[ui-pref] get\n") );
+ // general
+ PREFS->showsplash = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_show_splash));
+ 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->date_range_wal = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_wal));
+ 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));
+
+ // files/backup
+ g_free(PREFS->path_hbfile);
+ PREFS->path_hbfile = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_hbfile)));
+
+
+
g_free(PREFS->language);
PREFS->language = NULL;
lang = gtk_combo_box_get_active_id(GTK_COMBO_BOX(data->CY_language));
{
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));
PREFS->custom_colors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors));
-
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba);
g_free(PREFS->color_exp);
PREFS->color_exp = gdk_rgba_to_hex(&rgba);
-
gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba);
g_free(PREFS->color_inc);
PREFS->color_inc = gdk_rgba_to_hex(&rgba);
-
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));
- 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));
+ // import/export
+ 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));
+ ui_gtk_entry_replace_text(data->ST_path_import, &PREFS->path_import);
+ ui_gtk_entry_replace_text(data->ST_path_export, &PREFS->path_export);
+
+ // report
PREFS->date_range_rep = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_rep));
+ PREFS->report_color_scheme = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_color_scheme));
+ 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));
+ // euro minor
PREFS->euro_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable));
-
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));
-
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));
- 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));
}
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_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_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);
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
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;i<scheme.nb_cols;i++)
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(_("Initial filter"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
--
++
row = 1;
label = make_label_widget(_("Date _range:"));
//----------------------------------------- l, r, t, b
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_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_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_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);
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);
//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;
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);
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);
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);
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"
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);
static GtkWidget *defpref_page_transactions (struct defpref_data *data)
{
- GtkWidget *content_grid, *group_grid, *sw, *label, *widget;
+ GtkWidget *content_grid, *group_grid, *label, *widget;
gint crow, row;
content_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);
//----------------------------------------- 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);
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);
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);
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"));
+ */
return content_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(_("General"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
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);
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);
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);
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);
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);
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);
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("<b>%s</b>", name);
+ gchar* tooltip = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>", 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<b>%s:</b> %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<b>%s:</b> %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;
homebank_pref_setdefault();
defpref_set(data);
}
--
++
}
// the window creation
-GtkWidget *defpref_dialog_new (void)
+GtkWidget *defpref_dialog_new (gint initial_selection)
{
struct defpref_data data;
GtkWidget *window, *content, *mainvbox;
NULL);
data.window = window;
--
++
//store our window private data
g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)&data);
//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);
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);
#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
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);
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));
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);
//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);
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;
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);
// -------------------------------
- GtkWidget *pref_list_create(void)
+ static GtkWidget *pref_list_create(void)
{
GtkListStore *store;
GtkWidget *view;
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
-
+ /*
extern gchar *list_txn_column_label[];
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);
- /* do something with the value */
+ // do something with the value
fixed ^= 1;
- /* set new value */
+ // set new value
gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_VISIBLE, fixed, -1);
- /* clean up */
+ // clean up
gtk_tree_path_free (path);
}
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;
// start at index 2 (status, date always displayed
columns[i+2] = visible == TRUE ? id : -id;
- /* Make iter point to the next row in the list store */
+ // Make iter point to the next row in the list store
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
i++;
}
-
-
-
}
DB( g_print("[lst_txn-colpref] create\n") );
- /* create list store */
+ // create list store
store = gtk_list_store_new(
3,
G_TYPE_BOOLEAN,
G_TYPE_UINT
);
- /* populate */
+ // populate
for(i=0 ; i < NUM_LST_DSPOPE-1; i++ ) //-1 cause account column avoid
{
gint id;
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);
COLUMN_NAME, _(list_txn_column_label[id]),
COLUMN_ID , id,
-1);
--
++
}
//treeview
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,
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);
+ }
+}
+
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2017 Maxime DOYEN
+ * Copyright (C) 1995-2018 Maxime DOYEN
*
* This file is part of HomeBank.
*
gint country;
+ GtkWidget *PI_plugin_columns;
+};
+
+enum
+{
+ PREF_GENERAL,
+ PREF_INTERFACE,
+ PREF_TRANSACTIONS,
+ PREF_DISPLAY_FORMAT,
+ PREF_IMPORT_EXPORT,
+ PREF_REPORT,
+ PREF_EURO_MINOR,
+ PREF_PLUGINS,
+ PREF_MAX
};
+ typedef struct
+ {
+ gchar *locale;
+ gchar *name;
+ } LangName;
+
+
+ typedef struct
+ {
+ gshort id;
+ gchar *iso;
+ gchar *name;
+ gdouble value;
+ //gchar *prefix_symbol; /* max symbol is 3 digits in unicode */
+ //gchar *suffix_symbol; /* but mostly is 1 digit */
+ gchar *symbol;
+ gboolean sym_prefix;
+ gchar *decimal_char;
+ gchar *grouping_char;
+ gshort frac_digits;
+ } EuroParams;
+
+
+
void free_pref_icons(void);
void load_pref_icons(void);
-GtkWidget *defpref_dialog_new (void);
+GtkWidget *defpref_dialog_new (gint initial_selection);
#endif