# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.52)
- AC_INIT([homebank], [5.1.7])
+ AC_INIT([homebank], [5.2.4])
#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.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)
CFLAGS="${CFLAGS} -Wno-deprecated-declarations"
# extended flags
- #CFLAGS="${CFLAGS} -Wextra -Wno-unused-parameter"
+ #CFLAGS="${CFLAGS} -Wextra -Wno-unused-parameter -Wno-cast-function-type"
# profiling valgrind/gprof flags
#CFLAGS="${CFLAGS} -g -O0 -pg"
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])
AC_CHECK_FUNCS([floor localeconv memset modf pow setlocale sqrt strcasecmp strtoul])
# International support
- ALL_LINGUAS="af ar ast be bg br ca cs cy da de el en_AU en_CA en_GB es et eu fa fi fr gl he hr hu id is it ja ko lt lv mr ms nb nds nl oc pl pt_BR pt pt_PT ro ru si sk sl sr sv tr uk vi zh_CN zh_TW"
+ ALL_LINGUAS="af ar ast be bg br ca ckb cs cy da de el en_AU en_CA en_GB es et eu fa fi fr gl he hr hu id is it ja 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"
AM_GLIB_GNU_GETTEXT
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
common_defines = \
-DSHARE_DIR=\""$(pkgdatadir)"\" \
- -DDATA_DIR=\""$(datadir)"\"
+ -DDATA_DIR=\""$(datadir)"\" \
+ -DPKGLIB_DIR=\""$(pkglibdir)"\"
bin_PROGRAMS = homebank
homebank_SOURCES = \
- dsp_account.c \
- dsp_account.h \
- dsp_mainwindow.c \
- dsp_mainwindow.h \
+ dsp-account.c \
+ dsp-account.h \
+ dsp-mainwindow.c \
+ dsp-mainwindow.h \
enums.h \
gtk-chart.c \
gtk-chart.h \
gtk-chart-colors.c \
gtk-chart-colors.h \
- gtk-chart-stack.c \
- gtk-chart-stack.h \
+ gtk-chart-progress.c \
+ gtk-chart-progress.h \
gtk-dateentry.c \
gtk-dateentry.h \
hb-account.c \
hb-xml.h \
homebank.c \
homebank.h \
+ hub-account.c \
+ hub-account.h \
+ hub-scheduled.c \
+ hub-scheduled.h \
+ hub-spending.c \
+ hub-spending.h \
+ hub-transaction.c \
+ hub-transaction.h \
language.c \
language.h \
- list_account.c \
- list_account.h \
- list_operation.c \
- list_operation.h \
- list_topspending.c \
- list_topspending.h \
- list_upcoming.c \
- list_upcoming.h \
- rep_balance.c \
- rep_balance.h \
- rep_budget.c \
- rep_budget.h \
- rep_stats.c \
- rep_stats.h \
- rep_time.c \
- rep_time.h \
- rep_vehicle.c \
- rep_vehicle.h \
+ list-account.c \
+ list-account.h \
+ list-operation.c \
+ list-operation.h \
+ list-scheduled.c \
+ list-scheduled.h \
+ rep-balance.c \
+ rep-balance.h \
+ rep-budget.c \
+ rep-budget.h \
+ rep-stats.c \
+ rep-stats.h \
+ rep-time.c \
+ rep-time.h \
+ rep-vehicle.c \
+ rep-vehicle.h \
ui-account.c \
ui-account.h \
ui-archive.c \
ui-pref.h \
ui-split.c \
ui-split.h \
+ ui-tag.c \
+ ui-tag.h \
ui-transaction.c \
ui-transaction.h \
ui-txn-multi.c \
ui-txn-multi.h \
+ ui-widgets-data.c \
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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
- #include "dsp_mainwindow.h"
+ #include "dsp-mainwindow.h"
- #include "list_account.h"
- #include "list_upcoming.h"
- #include "list_topspending.h"
+#include "ext.h"
+
+ #include "list-account.h"
- #include "dsp_account.h"
+ #include "hub-account.h"
+ #include "hub-scheduled.h"
+ #include "hub-spending.h"
+ #include "hub-transaction.h"
+
+ #include "dsp-account.h"
#include "ui-assist-import.h"
#include "ui-assist-start.h"
#include "ui-account.h"
#include "ui-pref.h"
#include "ui-hbfile.h"
#include "ui-transaction.h"
+ #include "ui-tag.h"
- #include "rep_balance.h"
- #include "rep_budget.h"
- #include "rep_stats.h"
- #include "rep_time.h"
- #include "rep_vehicle.h"
+ #include "rep-balance.h"
+ #include "rep-budget.h"
+ #include "rep-stats.h"
+ #include "rep-time.h"
+ #include "rep-vehicle.h"
#include "gtk-chart.h"
- //old url prior 2018
+ //old url prior 2019
//#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"
static void ui_mainwindow_action_save(void);
static void ui_mainwindow_action_saveas(void);
static void ui_mainwindow_action_revert(void);
+ static void ui_mainwindow_action_openbak(void);
static void ui_mainwindow_action_properties(void);
static void ui_mainwindow_action_close(void);
static void ui_mainwindow_action_quit(void);
static void ui_mainwindow_action_defarchive(void);
static void ui_mainwindow_action_defbudget(void);
static void ui_mainwindow_action_defassign(void);
+ static void ui_mainwindow_action_deftag(void);
static void ui_mainwindow_action_preferences(void);
static void ui_mainwindow_action_toggle_toolbar(GtkToggleAction *action);
static void ui_mainwindow_action_toggle_minor(GtkToggleAction *action);
static void ui_mainwindow_action_showtransactions(void);
+ static void ui_mainwindow_action_showalltransactions(void);
+
static void ui_mainwindow_action_addtransactions(void);
static void ui_mainwindow_action_checkscheduled(void);
static void ui_mainwindow_action_anonymize(void);
static void ui_mainwindow_action_file_statistics(void);
+static void ui_mainwindow_action_pluginprefs(void);
+
static void ui_mainwindow_action_help(void);
void ui_mainwindow_action_help_welcome(void);
static void ui_mainwindow_action_help_online(void);
static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager);
- static void ui_mainwindow_populate_topspending(GtkWidget *widget, gpointer user_data);
-
void ui_mainwindow_open(GtkWidget *widget, gpointer user_data);
void ui_mainwindow_save(GtkWidget *widget, gpointer user_data);
void ui_mainwindow_toggle_minor(GtkWidget *widget, gpointer user_data);
void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data);
- gboolean ui_dialog_msg_savechanges(GtkWidget *widget, gpointer user_data);
-
void ui_mainwindow_update(GtkWidget *widget, gpointer user_data);
void ui_mainwindow_addtransactions(GtkWidget *widget, gpointer user_data);
void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
- static void ui_panel_topspending_update(GtkWidget *widget, gpointer user_data);
-
- static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data);
- void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data);
-
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[] = {
- N_("Category"),
- N_("Subcategory"),
- NULL
- };
-
-
static GtkActionEntry entries[] = {
/* name, icon-name, label */
{ "FileMenu" , NULL, N_("_File"), NULL, NULL, NULL },
- { "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL },
+ //{ "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL },
+ { "RecentMenu" , NULL, N_("Open _Recent"), NULL, NULL, NULL },
{ "EditMenu" , NULL, N_("_Edit"), NULL, NULL, NULL },
{ "ViewMenu" , NULL, N_("_View"), NULL, NULL, NULL },
{ "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL },
{ "TxnMenu" , NULL, N_("_Transactions"), NULL, NULL, NULL },
{ "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL },
{ "ToolsMenu" , NULL, N_("_Tools"), NULL, NULL, NULL },
+ { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL },
{ "HelpMenu" , NULL, N_("_Help"), NULL, NULL, NULL },
// { "Import" , NULL, N_("Import") },
/* name, icon-name, label, accelerator, tooltip */
/* FileMenu */
- { "New" , ICONNAME_NEW , N_("_New") , "<control>N", N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) },
- { "Open" , ICONNAME_OPEN , N_("_Open...") , "<control>O", N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) },
- { "Save" , ICONNAME_SAVE , N_("_Save") , "<control>S", N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) },
+ { "New" , ICONNAME_HB_FILE_NEW , N_("_New") , "<control>N", N_("Create a new file"), G_CALLBACK (ui_mainwindow_action_new) },
+ { "Open" , ICONNAME_HB_FILE_OPEN , N_("_Open...") , "<control>O", N_("Open a file"), G_CALLBACK (ui_mainwindow_action_open) },
+ { "Save" , ICONNAME_HB_FILE_SAVE , N_("_Save") , "<control>S", N_("Save the current file"), G_CALLBACK (ui_mainwindow_action_save) },
{ "SaveAs" , ICONNAME_SAVE_AS , N_("Save _As...") , "<shift><control>S", N_("Save the current file with a different name"), G_CALLBACK (ui_mainwindow_action_saveas) },
+
{ "Revert" , ICONNAME_REVERT , N_("Revert") , NULL, N_("Revert to a saved version of this file"), G_CALLBACK (ui_mainwindow_action_revert) },
+ { "OpenBak" , NULL , N_("Restore backup") , NULL, N_("Restore from a backup file"), G_CALLBACK (ui_mainwindow_action_openbak) },
{ "Properties" , ICONNAME_PROPERTIES , N_("Properties..."), NULL, N_("Configure the file"), G_CALLBACK (ui_mainwindow_action_properties) },
{ "Close" , ICONNAME_CLOSE , N_("_Close") , "<control>W", N_("Close the current file"), G_CALLBACK (ui_mainwindow_action_close) },
{ "Quit" , ICONNAME_QUIT , N_("_Quit") , "<control>Q", N_("Quit HomeBank"), G_CALLBACK (ui_mainwindow_action_quit) },
/* Exchange */
- { "ImportQIF" , ICONNAME_HB_FILE_IMPORT , N_("QIF file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
- { "ImportOFX" , ICONNAME_HB_FILE_IMPORT , N_("OFX/QFX file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
- { "ImportCSV" , ICONNAME_HB_FILE_IMPORT , N_("CSV file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
-
- { "ExportQIF" , ICONNAME_HB_FILE_EXPORT , N_("Export QIF file...") , NULL, N_("Export all account in a QIF file"), G_CALLBACK (ui_mainwindow_action_export) },
+ { "Import" , ICONNAME_HB_FILE_IMPORT , N_("Import...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
+ //{ "ImportQIF" , ICONNAME_HB_FILE_IMPORT , N_("QIF file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
+ //{ "ImportOFX" , ICONNAME_HB_FILE_IMPORT , N_("OFX/QFX file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
+ //{ "ImportCSV" , ICONNAME_HB_FILE_IMPORT , N_("CSV file...") , NULL, N_("Open the import assistant"), G_CALLBACK (ui_mainwindow_action_import) },
-
++
+ { "ExportQIF" , ICONNAME_HB_FILE_EXPORT , N_("Export as QIF...") , NULL, N_("Export all account in a QIF file"), G_CALLBACK (ui_mainwindow_action_export) },
/* EditMenu */
{ "Preferences", ICONNAME_PREFERENCES , N_("Preferences..."), NULL, N_("Configure HomeBank"), G_CALLBACK (ui_mainwindow_action_preferences) },
{ "Archive" , ICONNAME_HB_ARCHIVE , N_("Scheduled/Template...") , NULL, N_("Configure the scheduled/template transactions"), G_CALLBACK (ui_mainwindow_action_defarchive) },
{ "Budget" , ICONNAME_HB_BUDGET , N_("Budget...") , NULL, N_("Configure the budget"), G_CALLBACK (ui_mainwindow_action_defbudget) },
{ "Assign" , ICONNAME_HB_ASSIGN , N_("Assignments..."), NULL, N_("Configure the automatic assignments"), G_CALLBACK (ui_mainwindow_action_defassign) },
+ { "Tag" , NULL , N_("Tags..."), NULL, N_("Configure the tags"), G_CALLBACK (ui_mainwindow_action_deftag) },
/* TxnMenu */
- { "ShowOpe" , ICONNAME_HB_OPE_SHOW , N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) },
- { "AddOpe" , ICONNAME_HB_OPE_ADD , N_("Add...") , NULL, N_("Add transactions"), G_CALLBACK (ui_mainwindow_action_addtransactions) },
+ { "AddTxn" , ICONNAME_HB_OPE_ADD , N_("Add...") , NULL, N_("Add transactions"), G_CALLBACK (ui_mainwindow_action_addtransactions) },
+ { "ShowTxn" , ICONNAME_HB_OPE_SHOW , N_("Show...") , NULL, N_("Shows selected account transactions"), G_CALLBACK (ui_mainwindow_action_showtransactions) },
+ { "ShowAllTxn" , ICONNAME_HB_OPE_SHOW , N_("Show all...") , NULL, N_("Shows all account transactions"), G_CALLBACK (ui_mainwindow_action_showalltransactions) },
{ "Scheduler" , NULL , N_("Set scheduler...") , NULL, N_("Configure the transaction scheduler"), G_CALLBACK (ui_mainwindow_action_properties) },
{ "AddScheduled", NULL , N_("Post scheduled"), NULL, N_("Post pending scheduled transactions"), G_CALLBACK (ui_mainwindow_action_checkscheduled) },
{ "Welcome" , NULL , N_("Show welcome dialog...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_help_welcome) },
{ "FileStats" , NULL , N_("File statistics...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_file_statistics) },
{ "Anonymize" , NULL , N_("Anonymize...") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_anonymize) },
--
++
+ /* Plugins */
+ { "PluginPreferences", "prf-plugins", N_("_Plugins..."), "<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) },
/* name , icon-name, label, accelerator, tooltip, callback, is_active */
{ "Toolbar" , NULL , N_("_Toolbar") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_toolbar), TRUE },
{ "Spending" , NULL , N_("_Top spending") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_topspending), TRUE },
- { "Upcoming" , NULL , N_("_Scheduled list") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE },
+ { "BottomLists", NULL , N_("_Bottom Lists") , NULL, NULL, G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE },
{ "AsMinor" , NULL , N_("Euro minor"), "<control>M", NULL, G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE },
};
" <menu action='FileMenu'>"
" <menuitem action='New'/>"
" <menuitem action='Open'/>"
+ " <menuitem action='RecentMenu'/>"
" <separator/>"
" <menuitem action='Save'/>"
" <menuitem action='SaveAs'/>"
- " <menuitem action='Revert'/>"
- " <separator/>"
- " <menuitem action='Properties'/>"
" <separator/>"
- " <menu action='ImportMenu'>"
+ " <menuitem action='Import'/>"
+ /*" <menu action='ImportMenu'>"
" <menuitem action='ImportQIF'/>"
" <menuitem action='ImportOFX'/>"
" <menuitem action='ImportCSV'/>"
- " </menu>"
+ " </menu>"*/
" <menuitem action='ExportQIF'/>"
- //" <separator/>"
- // print to come here
+ // future: print to come here
+ " <separator/>"
+ " <menuitem action='Revert'/>"
+ " <menuitem action='OpenBak'/>"
+ " <separator/>"
+ " <menuitem action='Properties'/>"
" <separator/>"
" <menuitem action='Close'/>"
" <menuitem action='Quit'/>"
" <menuitem action='Toolbar'/>"
" <separator/>"
" <menuitem action='Spending'/>"
- " <menuitem action='Upcoming'/>"
+ " <menuitem action='BottomLists'/>"
" <separator/>"
" <menuitem action='AsMinor'/>"
" </menu>"
" <menuitem action='Budget'/>"
" <menuitem action='Assign'/>"
" <menuitem action='Currency'/>"
+ " <menuitem action='Tag'/>"
" </menu>"
" <menu action='TxnMenu'>"
- " <menuitem action='ShowOpe'/>"
- " <menuitem action='AddOpe'/>"
+ " <menuitem action='AddTxn'/>"
+ " <menuitem action='ShowTxn'/>"
+ " <menuitem action='ShowAllTxn'/>"
" <separator/>"
" <menuitem action='Scheduler'/>"
" <menuitem action='AddScheduled'/>"
" <separator/>"
" <menuitem action='Anonymize'/>"
" </menu>"
+" <menu action='PluginMenu'>"
+" <separator/>"
+" <menuitem action='PluginPreferences'/>"
+" <separator/>"
+" </menu>"
" <menu action='HelpMenu'>"
" <menuitem action='Contents'/>"
" <menuitem action='Online'/>"
" <toolitem action='Assign'/>"
" <toolitem action='Currency'/>"
" <separator/>"
- " <toolitem action='ShowOpe'/>"
- " <toolitem action='AddOpe'/>"
+ " <toolitem action='ShowTxn'/>"
+ " <toolitem action='AddTxn'/>"
" <separator/>"
" <toolitem action='RStatistics'/>"
" <toolitem action='RTrendTime'/>"
" <toolitem action='RBalance'/>"
" <toolitem action='RBudget'/>"
" <toolitem action='RVehiculeCost'/>"
+" <separator/>"
" </toolbar>"
"</ui>";
title = g_strdup_printf (
_("Revert unsaved changes to file '%s'?"), basename);
-- secondtext =
++ secondtext =
_("- Changes made to the file will be permanently lost\n"
"- File will be reloaded from the last save (.xhb~)");
if( result == GTK_RESPONSE_OK )
{
DB( g_print(" - should revert\n") );
--
++
hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
ui_mainwindow_open_internal(widget, NULL);
hbfile_change_filepath(hb_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
gpointer data)
{
DB( g_print("activate url %s\n", link) );
--
++
homebank_util_url_show (link);
}
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-2018 - Maxime DOYEN";
+ static const gchar *copyright = "Copyright \xc2\xa9 1995-2019 - Maxime DOYEN";
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
--
++
dialog = gtk_about_dialog_new();
gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(GLOBALS->mainwindow));
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
--
++
gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(dialog), g_get_application_name ());
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), version);
gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), copyright);
gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("Free, easy, personal accounting for everyone"));
gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0);
--
++
//gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), );
gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr");
gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf);
g_object_unref (pixbuf);
}
--
++
gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists);
//gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), );
gtk_widget_destroy (dialog);
g_free(version);
--
++
}
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_hub_account_populate(GLOBALS->mainwindow, NULL);
+ //ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
+ //ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
}
}
static void ui_mainwindow_action_open(void)
{
- ui_mainwindow_open(GLOBALS->mainwindow, NULL);
+ ui_mainwindow_open(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
+ }
+
+ static void ui_mainwindow_action_openbak(void)
+ {
+ ui_mainwindow_open(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
}
static void ui_mainwindow_action_save(void)
}
+static void ui_mainwindow_action_pluginprefs(void)
+{
+ ui_mainwindow_showprefs(PREF_PLUGINS);
+}
+
+
static void ui_mainwindow_action_properties(void)
{
create_defhbfile_dialog();
title = _("Are you sure you want to anonymize the file?");
-- secondtext =
++ secondtext =
_("Proceeding will anonymize any text, \n"
"like 'account x', 'payee y', 'memo z', ...");
//#1707201
//if( result == GTK_RESPONSE_CANCEL )
-- // return;
++ // return;
if( result == GTK_RESPONSE_OK )
{
hbfile_anonymize();
//our global list has changed, so update the treeview
//todo: optimize this, should not call compute balance here
account_compute_balances ();
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
+ ui_hub_account_populate(GLOBALS->mainwindow, NULL);
ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE));
}
ui_cat_manage_dialog();
//todo:why refresh upcoming here??
//ui_mainwindow_populate_upcoming(GLOBALS->mainwindow, NULL);
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
+ ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
}
- static void ui_mainwindow_defarchive(Archive *arc)
+ //TODO: not ideal to do this
+ void ui_mainwindow_defarchive(Archive *arc)
{
struct hbfile_data *data;
GtkTreeModel *model;
data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
- // upcoming list have direct pointer to the arc (which may have changed)
+ // upcoming list have direct pointer to the arc (which may change during edit)
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
gtk_list_store_clear (GTK_LIST_STORE(model));
ui_arc_manage_dialog(arc);
- ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
}
}
+ static void ui_mainwindow_action_deftag(void)
+ {
+
+ ui_tag_manage_dialog();
+
+ //ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
+ }
+
+
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");
// top spending
gtk_chart_show_minor(GTK_CHART(data->RE_pie), GLOBALS->minor);
--
- ui_panel_topspending_update(data->window, data);
++
+ ui_hub_spending_update(data->window, data);
}
{
if( data->acc->window == NULL )
{
- window = register_panel_window_new(data->acc->key, data->acc);
+ window = register_panel_window_new(data->acc);
register_panel_window_init(window, NULL);
}
else
{
if(GTK_IS_WINDOW(data->acc->window))
- gtk_window_present(data->acc->window);
+ gtk_window_present(GTK_WINDOW(data->acc->window));
}
}
}
+ static void ui_mainwindow_action_showalltransactions(void)
+ {
+ GtkWidget *window;
+
+ if( GLOBALS->alltxnwindow == NULL )
+ {
+ window = register_panel_window_new(NULL);
+ register_panel_window_init(window, NULL);
+ }
+ else
+ {
+ if(GTK_IS_WINDOW(GLOBALS->alltxnwindow))
+ gtk_window_present(GTK_WINDOW(GLOBALS->alltxnwindow));
+ }
+
+ }
+
+
static void ui_mainwindow_action_addtransactions(void)
{
ui_mainwindow_addtransactions(GLOBALS->mainwindow, NULL);
static void ui_mainwindow_action_checkscheduled(void)
{
- ui_mainwindow_scheduled_postall(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
+ ui_hub_scheduled_postall(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
}
static void ui_mainwindow_action_statistic(void)
static void ui_mainwindow_action_trendtime(void)
{
struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
--
++
ui_reptime_window_new(data->acc != NULL ? data->acc->key : 0);
}
static void ui_mainwindow_action_import(GtkAction *action)
{
- const gchar *name;
- gint filetype = FILETYPE_UNKNOW;
+ /*const gchar *name;
+ gint filetype = FILETYPE_UNKNOWN;
name = gtk_action_get_name(action);
filetype= FILETYPE_OFX;
else
if( g_str_has_suffix (name, "CSV"))
- filetype= FILETYPE_CSV_HB;
+ filetype= FILETYPE_CSV_HB;*/
- DB( g_print("action %s type=%d\n", name, filetype) );
+ //DB( g_print("action %s type=%d\n", name, filetype) );
- ui_import_assistant_new(filetype);
+ ui_import_assistant_new(NULL);
}
NULL);
content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
--
++
mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (content_area), mainvbox, FALSE, FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
widget = gtk_button_new_with_mnemonic(_("Read HomeBank _Manual"));
gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog);
--
++
widget = gtk_button_new_with_mnemonic(_("Configure _preferences"));
gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog);
--
++
widget = gtk_button_new_with_mnemonic(_("Create a _new file"));
gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome3), dialog);
gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc))));
gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
--
++
data->showall = FALSE;
- ui_panel_accounts_setup(data);
-
+ ui_hub_account_setup(data);
-
++
hbfile_cleanup(file_clear);
hbfile_setup(file_clear);
if(data->acc != NULL)
account = data->acc->key;
- window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE);
+ window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE, account);
count = 0;
- while(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP)
+ while(result == HB_RESPONSE_ADD || result == HB_RESPONSE_ADDKEEP)
{
Transaction *ope;
/* fill in the transaction */
- if( result == GTK_RESPONSE_ADD )
+ if( result == HB_RESPONSE_ADD )
{
ope = da_transaction_malloc();
ope->date = date;
if( PREFS->heritdate == FALSE ) //fix: 318733
ope->date = GLOBALS->today;
-
++
+ da_transaction_set_default_template(ope);
}
// normally we can't be in addkeep without initialized ope with add
DB( g_print(" - dialog result is %d\n", result) );
- if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
+ if(result == HB_RESPONSE_ADD || result == HB_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
{
deftransaction_get(window, NULL);
- transaction_add(ope);
+ transaction_add(GTK_WINDOW(GLOBALS->mainwindow), ope);
DB( g_print(" - added 1 transaction to %d\n", ope->kacc) );
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
-
+ ui_hub_account_populate(GLOBALS->mainwindow, NULL);
-
++
count++;
//todo: still usefull ? store last date
date = ope->date;
}
- if( result == GTK_RESPONSE_ADD )
+ if( result == HB_RESPONSE_ADD )
{
da_transaction_free(ope);
ope = NULL;
}
}
- struct tmptop
- {
- guint32 key;
- gdouble value;
- };
-
-
- #define MAX_TOPSPENDING 10
-
-
- static gint tmptop_compare_func(struct tmptop *tt1, struct tmptop *tt2)
- {
- return tt1->value > tt2->value ? 1 : -1;
- }
-
- static void ui_panel_topspending_update(GtkWidget *widget, gpointer user_data)
+ gboolean ui_mainwindow_open_backup_check_confirm(gchar *filepath)
{
- struct hbfile_data *data;
- GtkTreeModel *model;
- gchar *title;
- gchar strbuffer[G_ASCII_DTOSTR_BUF_SIZE];
-
- DB( g_print("\n[ui-mainwindow] topspending_update\n") );
+ gboolean retval = FALSE;
+ gchar *basename, *secondtext;
+ gboolean result;
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+ 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);
++ _("Your are about to open the backup file '%s'.\n\nAre you sure you want to do this ?"), basename);
- hb_strfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, data->toptotal, GLOBALS->kcur, GLOBALS->minor);
- //hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->kcur, GLOBALS->minor);
- title = g_strdup_printf("%s %s", _("Top spending"), strbuffer);
+ result = ui_dialog_msg_confirm_alert(
+ GTK_WINDOW(GLOBALS->mainwindow),
+ _("Open the backup file ?"),
+ secondtext,
+ _("_Open backup")
- );
++ );
- model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top));
-
- gtk_chart_set_color_scheme(GTK_CHART(data->RE_pie), PREFS->report_color_scheme);
- gtk_chart_set_currency(GTK_CHART(data->RE_pie), GLOBALS->kcur);
- gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, title, NULL);
+ g_free(secondtext);
+ g_free(basename);
- g_free(title);
+ if( result == GTK_RESPONSE_OK )
+ retval = TRUE;
-
+
- //future usage
- gchar *fu = _("Top %d spending"); title = fu;
+ return retval;
}
- static void ui_mainwindow_populate_topspending(GtkWidget *widget, gpointer user_data)
+ /*
+ **
+ */
+ void ui_mainwindow_open(GtkWidget *widget, gpointer user_data)
{
- struct hbfile_data *data;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GList *list;
- gint type, range;
- guint n_result, i, n_items;
- GArray *garray;
- gdouble total, other;
- Account *acc;
-
-
- DB( g_print("\n[ui-mainwindow] populate_topspending\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- type = radio_get_active(GTK_CONTAINER(data->RA_type));
- range = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range));
-
- DB( g_print(" - type=%d, range=%d\n", type, range) );
- DB( g_print(" - pref range=%d\n", PREFS->date_range_wal) );
+ //struct hbfile_data *data;
+ gboolean bakmode = GPOINTER_TO_INT(user_data);;
+ gboolean doopen = TRUE;
+ gchar *filename = NULL;
- if(range == FLT_RANGE_OTHER)
- return;
-
- filter_preset_daterange_set(data->filter, range, 0);
-
-
- n_result = da_cat_get_max_key() + 1;
- total = 0.0;
+ DB( g_print("\n[ui-mainwindow] open\n") );
- DB( g_print(" - max key is %d\n", n_result) );
+ //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
- /* allocate some memory */
- garray = g_array_sized_new(FALSE, FALSE, sizeof(struct tmptop), n_result);
+ //#1791554 do ask for save confirm
+ if( bakmode != TRUE )
+ doopen = ui_dialog_msg_savechanges(widget,NULL);
- if(garray)
+ if( doopen == TRUE )
{
- struct tmptop zero = { .key=0, .value=0.0 };
- GQueue *txn_queue;
-
- //DB( g_print(" - array length=%d\n", garray->len) );
-
- for(i=0 ; i<n_result ; i++)
- {
- g_array_append_vals(garray, &zero, 1);
- //g_array_insert_vals(garray, i, &zero, 1);
-
- //struct tmptop *tt = &g_array_index (garray, struct tmptop, i);
- //DB( g_print("%4d, %4d %f\n", i, tt->key, tt->value) );
- }
-
- //DB( g_print("\n - end array length=%d\n", garray->len) );
-
- //todo: not ideal, has ot force to get_acc for each txn below
- txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
-
- /* compute the results */
- list = g_queue_peek_head_link(txn_queue);
- while (list != NULL)
+ if( ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename, bakmode) == TRUE )
{
- Transaction *ope = list->data;
-
- //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) )
+ //#1710955 test for backup open
+ if( hbfile_file_isbackup(filename) )
{
- guint32 pos = 0;
- gdouble trn_amount;
-
- //todo: optimize here
- trn_amount = ope->amount;
- acc = da_acc_get(ope->kacc);
- if(acc)
- trn_amount = hb_amount_base(ope->amount, acc->kcur);
-
- if( ope->flags & OF_SPLIT )
+ if( ui_mainwindow_open_backup_check_confirm(filename) == TRUE )
{
- guint nbsplit = da_splits_count(ope->splits);
- Split *split;
- struct tmptop *item;
-
- for(i=0;i<nbsplit;i++)
- {
- split = ope->splits[i];
- pos = category_report_id(split->kcat, type);
-
- trn_amount = hb_amount_base(split->amount, acc->kcur);
- //trn_amount = split->amount;
- //#1297054 if( trn_amount < 0 ) {
- item = &g_array_index (garray, struct tmptop, pos);
- item->key = pos;
- item->value += trn_amount;
- //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) );
- //}
- }
+ GLOBALS->hbfile_is_bak = TRUE;
}
else
{
- struct tmptop *item;
-
- pos = category_report_id(ope->kcat, type);
-
- //#1297054 if( trn_amount < 0 ) {
- item = &g_array_index (garray, struct tmptop, pos);
- item->key = pos;
- item->value += trn_amount;
- //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos) );
- //}
+ g_free(filename);
+ return;
}
-
-
- }
-
- list = g_list_next(list);
- }
-
- g_queue_free (txn_queue);
-
- // we need to sort this and limit before
- g_array_sort(garray, (GCompareFunc)tmptop_compare_func);
-
- n_items = MIN(garray->len,MAX_TOPSPENDING);
- other = 0;
- for(i=0 ; i<garray->len ; i++)
- {
- struct tmptop *item;
-
- item = &g_array_index (garray, struct tmptop, i);
- if(item->value < 0)
- {
- total += item->value;
-
- if(i >= n_items)
- other += item->value;
-
- DB( g_print(" - %d : k='%d' v='%f' t='%f'\n", i, item->key, item->value, total) );
-
- }
+ }
- }
- model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top));
- gtk_list_store_clear (GTK_LIST_STORE(model));
- g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
- gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_top), NULL); /* Detach model from view */
-
- /* insert into the treeview */
- for(i=0 ; i<MIN(garray->len,MAX_TOPSPENDING) ; i++)
- {
- gchar *name;
- Category *entry;
- struct tmptop *item;
- gdouble value;
-
- item = &g_array_index (garray, struct tmptop, i);
-
- if(!item->value) continue;
-
- value = hb_amount_round(item->value, 2);
- entry = da_cat_get(item->key);
- if(entry == NULL) continue;
-
- name = entry->key == 0 ? _("(no category)") : da_cat_get_fullname(entry);
-
- // append test
- gtk_list_store_append (GTK_LIST_STORE(model), &iter);
- gtk_list_store_set (GTK_LIST_STORE(model), &iter,
- LST_TOPSPEND_ID, i,
- LST_TOPSPEND_KEY, 0,
- LST_TOPSPEND_NAME, name,
- LST_TOPSPEND_AMOUNT, value,
- //LST_TOPSPEND_RATE, (gint)(((ABS(value)*100)/ABS(total)) + 0.5),
- -1);
-
- }
-
- // append test
- if(ABS(other) > 0)
- {
- gtk_list_store_append (GTK_LIST_STORE(model), &iter);
- gtk_list_store_set (GTK_LIST_STORE(model), &iter,
- LST_TOPSPEND_ID, n_items,
- LST_TOPSPEND_KEY, 0,
- LST_TOPSPEND_NAME, _("Other"),
- LST_TOPSPEND_AMOUNT, other,
- //LST_TOPSPEND_RATE, (gint)(((ABS(other)*100)/ABS(total)) + 0.5),
- -1);
- }
-
- /* Re-attach model to view */
- gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_top), model);
- g_object_unref(model);
-
-
- // update chart and widgets
- {
- gchar *daterange;
-
- data->toptotal = total;
- ui_panel_topspending_update(widget, data);
-
- daterange = filter_daterange_text_get(data->filter);
- gtk_widget_set_tooltip_markup(GTK_WIDGET(data->CY_range), daterange);
- g_free(daterange);
+ hbfile_change_filepath(filename);
+ ui_mainwindow_open_internal(widget, NULL);
}
}
-
- /* free our memory */
- g_array_free (garray, TRUE);
-
}
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- /* scheduled */
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- static Archive *
- ui_mainwindow_scheduled_get_selected_item(GtkTreeView *treeview)
+ /*
+ * open the file stored in GLOBALS->xhb_filepath
+ */
+ void ui_mainwindow_open_internal(GtkWidget *widget, gpointer user_data)
{
- GtkTreeSelection *treeselection;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- treeselection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
- if( gtk_tree_selection_get_selected(treeselection, &model, &iter) )
- {
- Archive *arc;
+ struct hbfile_data *data;
+ gint r;
- gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPUPC_DATAS, &arc, -1);
- return arc;
- }
+ DB( g_print("\n[ui-mainwindow] open internal\n") );
- return NULL;
- }
+ data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+ if( GLOBALS->xhb_filepath != NULL )
+ {
+ DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) );
- static void ui_mainwindow_scheduled_onRowActivated (GtkTreeView *treeview,
- GtkTreePath *path,
- GtkTreeViewColumn *col,
- gpointer userdata)
- {
- //struct hbfile_data *data;
- Archive *arc;
+ ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(FALSE));
+ GLOBALS->hbfile_is_new = FALSE;
- DB( g_print ("\n[ui-mainwindow] A scheduled row has been double-clicked!\n") );
+ r = homebank_load_xml(GLOBALS->xhb_filepath);
+ if( r == XML_OK )
+ {
+ DB( g_print(" - file loaded ok : rcode=%d\n", r) );
- //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(treeview, GTK_TYPE_WINDOW)), "inst_data");
+ GLOBALS->xhb_timemodified = hbfile_file_get_time_modified(GLOBALS->xhb_filepath);
+ hbfile_file_hasrevert(GLOBALS->xhb_filepath);
-
+
- arc = ui_mainwindow_scheduled_get_selected_item(treeview);
- ui_mainwindow_defarchive(arc);
- }
+ if(PREFS->appendscheduled)
+ scheduled_post_all_pending();
+ if(PREFS->do_update_currency)
+ ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow));
- static void ui_mainwindow_scheduled_do_post(Archive *arc, gboolean doedit, gpointer user_data)
- {
- struct hbfile_data *data = user_data;
- GtkWidget *window;
- gint result;
- Transaction *txn;
+ homebank_lastopenedfiles_save();
- window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, TRUE);
+ //todo: delete this after computing done at xml read
+ account_compute_balances();
- /* fill in the transaction */
- txn = da_transaction_malloc();
- da_transaction_init_from_template(txn, arc);
- txn->date = scheduled_get_postdate(arc, arc->nextdate);
+ ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath);
+ }
+ else
+ {
+ gchar *msg = _("Unknown error");
- deftransaction_set_transaction(window, txn);
+ switch(r)
+ {
+ case XML_IO_ERROR:
+ msg = _("I/O error for file '%s'.");
+ break;
+ case XML_FILE_ERROR:
+ msg = _("The file '%s' is not a valid HomeBank file.");
+ break;
- case XML_VERSION_ERROR:
++ case XML_VERSION_ERROR:
+ msg = _("The file '%s' was saved with a higher version of HomeBank\nand cannot be loaded by the current version.");
+ break;
+ }
- result = gtk_dialog_run (GTK_DIALOG (window));
+ ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
+ _("File error"),
+ msg,
+ GLOBALS->xhb_filepath
+ );
- DB( g_print(" - dialog result is %d\n", result) );
+ ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
- if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
- {
- deftransaction_get(window, NULL);
- transaction_add(txn);
- GLOBALS->changes_count++;
+ }
- scheduled_date_advance(arc);
+ ui_hub_account_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_transaction_populate(data);
-
+
- DB( g_print(" - added 1 transaction to %d\n", txn->kacc) );
+ ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
}
- da_transaction_free(txn);
-
- deftransaction_dispose(window, NULL);
- gtk_widget_destroy (window);
}
- static void ui_mainwindow_scheduled_editpost_cb(GtkWidget *widget, gpointer user_data)
+ /*
+ **
+ */
+ void ui_mainwindow_save(GtkWidget *widget, gpointer user_data)
{
- struct hbfile_data *data = user_data;
-
- Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
-
- if( (arc != NULL) )
- {
- ui_mainwindow_scheduled_do_post(arc, TRUE, data);
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
- }
- }
+ struct hbfile_data *data;
+ gboolean saveas = GPOINTER_TO_INT(user_data);
+ gchar *filename = NULL;
+ gint r = XML_UNSET;
+ DB( g_print("\n[ui-mainwindow] save\n") );
- static void ui_mainwindow_scheduled_post_cb(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data = user_data;
+ data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
- DB( g_print("\n[ui-mainwindow] scheduled post\n") );
+ if( GLOBALS->hbfile_is_new == TRUE )
+ saveas = 1;
- Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
+ //#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( (arc != NULL) )
+ if(saveas == 1)
{
- if( scheduled_is_postable(arc) )
+ if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename, FALSE) == TRUE)
{
- Transaction *txn = da_transaction_malloc ();
-
- da_transaction_init_from_template(txn, arc);
- txn->date = scheduled_get_postdate(arc, arc->nextdate);
- transaction_add(txn);
-
- GLOBALS->changes_count++;
- scheduled_date_advance(arc);
-
- da_transaction_free (txn);
+ DB( g_print(" + should save as '%s'\n", filename) );
+ homebank_file_ensure_xhb(filename);
+ homebank_backup_current_file();
+ r = homebank_save_xml(GLOBALS->xhb_filepath);
+ GLOBALS->hbfile_is_new = FALSE;
+ GLOBALS->hbfile_is_bak = FALSE;
}
else
- {
- ui_mainwindow_scheduled_do_post(arc, FALSE, data);
- }
-
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
+ return;
}
- }
+ else
+ {
+ guint64 time_modified = hbfile_file_get_time_modified (GLOBALS->xhb_filepath);
+ gint result = GTK_RESPONSE_OK;
+ DB( g_print(" + should quick save '%s'\n + time: open=%lu :: now=%lu\n", GLOBALS->xhb_filepath, GLOBALS->xhb_timemodified, time_modified) );
- static void ui_mainwindow_scheduled_skip_cb(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data = user_data;
-
- Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
- if( (arc != NULL) && (arc->flags & OF_AUTO) )
- {
- GLOBALS->changes_count++;
- scheduled_date_advance(arc);
-
- ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
- }
- }
-
-
-
- static void ui_mainwindow_scheduled_update(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
- //gint filter;
-
- DB( g_print("\n[ui-mainwindow] scheduled update\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- //filter = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_sched_filter));
-
- Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
-
- if(arc)
- {
- 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);
- gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), TRUE);
- }
- else
- {
- gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), FALSE);
- }
-
- }
-
-
-
- static void ui_mainwindow_scheduled_selection_cb(GtkTreeSelection *treeselection, gpointer user_data)
- {
-
-
- ui_mainwindow_scheduled_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(UF_SENSITIVE));
- }
-
-
-
- /*
- ** called after load, importamiga, on demand
- */
- void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data)
- {
- //struct hbfile_data *data;
- gint count;
- gint usermode = GPOINTER_TO_INT(user_data);
-
- DB( g_print("\n[ui-mainwindow] check scheduled\n") );
-
- //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- count = scheduled_post_all_pending();
-
- //inform the user
- if(usermode == TRUE)
- {
- gchar *txt;
-
- //#125534
- if( count > 0 )
- {
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_REFRESHALL));
- }
-
- if(count == 0)
- txt = _("No transaction to add");
- else
- txt = _("transaction added: %d");
-
- ui_dialog_msg_infoerror(GTK_WINDOW(GLOBALS->mainwindow), GTK_MESSAGE_INFO,
- _("Check scheduled transactions result"),
- txt,
- count);
- }
-
- }
-
-
- static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GList *list;
- gdouble totexp = 0;
- gdouble totinc = 0;
- gint count = 0;
- gchar buffer[256];
- guint32 maxpostdate;
- GDate *date;
- //Account *acc;
-
- DB( g_print("\n[ui-mainwindow] scheduled populate list\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
- gtk_list_store_clear (GTK_LIST_STORE(model));
-
- homebank_app_date_get_julian();
-
- maxpostdate = scheduled_date_get_post_max();
-
- date = g_date_new_julian (maxpostdate);
- g_date_strftime (buffer, 256-1, PREFS->date_format, date);
- g_date_free(date);
-
- gtk_label_set_text(GTK_LABEL(data->LB_maxpostdate), buffer);
-
-
- list = g_list_first(GLOBALS->arc_list);
- while (list != NULL)
- {
- Archive *arc = list->data;
- Account *acc;
- gdouble inc, exp;
- guint nbdays, nblate;
-
- if((arc->flags & OF_AUTO) ) //&& arc->kacc > 0)
- {
- count++;
- nbdays = arc->nextdate - maxpostdate;
- nblate = scheduled_get_latepost_count(arc, GLOBALS->today);
-
- DB( g_print(" - append '%s' : %d\n", arc->memo, nbdays) );
-
- if(arc->flags & OF_INCOME)
- {
- inc = arc->amount;
- exp = 0.0;
- }
- else
- {
- exp = arc->amount;
- inc = 0.0;
- }
-
- /* insert normal txn */
- acc = da_acc_get(arc->kacc);
- if( acc)
- {
- totinc += hb_amount_base(inc, acc->kcur);
- totexp += hb_amount_base(exp, acc->kcur);
- }
- gtk_list_store_append (GTK_LIST_STORE(model), &iter);
- gtk_list_store_set (GTK_LIST_STORE(model), &iter,
- LST_DSPUPC_DATAS, arc,
- LST_DSPUPC_ACCOUNT, acc,
- LST_DSPUPC_MEMO, arc->memo,
- LST_DSPUPC_EXPENSE, exp,
- LST_DSPUPC_INCOME, inc,
- LST_DSPUPC_REMAINING, nbdays,
- LST_DSPUPC_NB_LATE, nblate,
- -1);
-
- /* insert internal xfer txn : 1378836 */
- if(arc->paymode == PAYMODE_INTXFER)
- {
- acc = da_acc_get(arc->kxferacc);
- if( acc)
- {
- totinc += hb_amount_base(-inc, acc->kcur);
- totexp += hb_amount_base(-exp, acc->kcur);
- }
- gtk_list_store_append (GTK_LIST_STORE(model), &iter);
- gtk_list_store_set (GTK_LIST_STORE(model), &iter,
- LST_DSPUPC_DATAS, arc,
- LST_DSPUPC_ACCOUNT, acc,
- LST_DSPUPC_MEMO, arc->memo,
- LST_DSPUPC_EXPENSE, -inc,
- LST_DSPUPC_INCOME, -exp,
- LST_DSPUPC_REMAINING, nbdays,
- LST_DSPUPC_NB_LATE, nblate,
- -1);
- }
-
- }
- list = g_list_next(list);
- }
-
- // insert total
- if(count > 0 )
- {
- gtk_list_store_append (GTK_LIST_STORE(model), &iter);
- gtk_list_store_set (GTK_LIST_STORE(model), &iter,
- LST_DSPUPC_DATAS, NULL,
- LST_DSPUPC_ACCOUNT, NULL,
- LST_DSPUPC_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;
- }
-
-
- /*
- **
- */
- void ui_mainwindow_open(GtkWidget *widget, gpointer user_data)
- {
- //struct hbfile_data *data;
- gchar *filename = NULL;
-
- DB( g_print("\n[ui-mainwindow] open\n") );
-
- //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- if( ui_dialog_msg_savechanges(widget,NULL) == TRUE )
- {
- if( ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_OPEN, &filename) == TRUE )
- {
- //#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
- */
- void ui_mainwindow_open_internal(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
- gint r;
-
- DB( g_print("\n[ui-mainwindow] open internal\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- 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;
-
- r = homebank_load_xml(GLOBALS->xhb_filepath);
- if( r == XML_OK )
- {
- DB( g_print(" - file loaded ok : rcode=%d\n", r) );
-
- hbfile_file_hasbackup(GLOBALS->xhb_filepath);
-
- if(PREFS->appendscheduled)
- scheduled_post_all_pending();
-
- if(PREFS->do_update_currency)
- ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow));
-
- homebank_lastopenedfiles_save();
-
- //todo: delete this after computing done at xml read
- account_compute_balances();
-
- ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath);
- }
- else
- {
- gchar *msg = _("Unknow error");
-
- switch(r)
- {
- case XML_IO_ERROR:
- msg = _("I/O error for file '%s'.");
- break;
- case XML_FILE_ERROR:
- msg = _("The file '%s' is not a valid HomeBank file.");
- break;
- case XML_VERSION_ERROR:
- msg = _("The file '%s' was saved with a higher version of HomeBank\nand cannot be loaded by the current version.");
- break;
- }
-
- ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
- _("File error"),
- msg,
- GLOBALS->xhb_filepath
- );
-
- ui_mainwindow_clear(GLOBALS->mainwindow, GINT_TO_POINTER(TRUE));
-
- }
-
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
- ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
- ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
- }
-
-
- }
-
-
- /*
- **
- */
- void ui_mainwindow_save(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
- gboolean saveas = GPOINTER_TO_INT(user_data);
- gchar *filename = NULL;
- gint r = XML_UNSET;
-
- DB( g_print("\n[ui-mainwindow] save\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- 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)
- {
- DB( g_print(" + should save as '%s'\n", filename) );
- homebank_file_ensure_xhb(filename);
- homebank_backup_current_file();
- r = homebank_save_xml(GLOBALS->xhb_filepath);
- GLOBALS->hbfile_is_new = FALSE;
- GLOBALS->hbfile_is_bak = FALSE;
- }
- else
- return;
- }
- else
- {
- DB( g_print(" + should quick save %s\n", GLOBALS->xhb_filepath) );
- homebank_file_ensure_xhb(NULL);
- homebank_backup_current_file();
- r = homebank_save_xml(GLOBALS->xhb_filepath);
- }
-
-
- if(r == XML_OK)
- {
- GLOBALS->changes_count = 0;
- ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
- }
- else
- {
- gchar *msg = _("I/O error for file '%s'.");
-
- ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
- _("File error"),
- msg,
- GLOBALS->xhb_filepath
- );
-
- }
-
-
- }
-
-
- static void ui_panel_accounts_expand_all(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
- gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
- }
-
-
- static void ui_panel_accounts_collapse_all(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
- gtk_tree_view_collapse_all(GTK_TREE_VIEW(data->LV_acc));
- }
-
-
-
- static GHashTable *ui_panel_accounts_groups_get(GList *lacc, gint groupby, gboolean showall)
- {
- GHashTable *hash;
- GList *elt;
- 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;
-
- //#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 )
- {
- groupname = _("(no institution)");
- if( (acc->bankname != NULL) && strlen(acc->bankname) > 0 )
- groupname = acc->bankname;
- }
- else
- {
- //pre 5.1.3 historical by type display
- groupname = _(CYA_ACC_TYPE[acc->type]);
- }
-
- if( g_hash_table_contains(hash, groupname) == FALSE )
- {
- g_hash_table_insert(hash, g_strdup(groupname), g_ptr_array_sized_new(nballoc) );
- //DB( g_print(" - type hash insert '%s' = %d\n", groupname, inserted) );
- }
-
- group = g_hash_table_lookup(hash, groupname);
- if( group != NULL )
- {
- g_ptr_array_add(group, (gpointer)acc);
- DB( g_print(" -- add '%s' to group '%s'\n", acc->name, groupname) );
- }
- }
- elt = g_list_next(elt);
- }
-
- return hash;
- }
-
-
-
-
-
-
- void ui_mainwindow_populate_accounts(GtkWidget *widget, gpointer user_data)
- {
- struct hbfile_data *data;
- GtkTreeModel *model;
- GtkTreeIter iter1, child_iter;
- GList *lacc, *elt;
- Account *acc;
- guint j, nbtype;
- gdouble gtbank, gttoday, gtfuture;
-
- GHashTable *h_group;
- GHashTableIter grp_iter;
- gpointer key, value;
-
- DB( g_print("\n[ui-mainwindow] populate accounts\n") );
-
- data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-
- /* here we create a count and a list of every account pointer by type */
- lacc = elt = g_hash_table_get_values(GLOBALS->h_acc);
-
- h_group = ui_panel_accounts_groups_get(lacc, PREFS->pnl_acc_show_by, data->showall);
- g_list_free(lacc);
-
-
- gtbank = gttoday = gtfuture = 0;
-
- 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));
-
- nbtype = 0;
- g_hash_table_iter_init (&grp_iter, h_group);
- while (g_hash_table_iter_next (&grp_iter, &key, &value))
- {
- GPtrArray *gpa = value;
- gdouble tbank, ttoday, tfuture;
- gint position;
-
- if(gpa != NULL)
+ if( GLOBALS->xhb_timemodified != time_modified )
{
- nbtype++;
- //1: Header: Bank, Cash, ...
- 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);
-
- tbank = ttoday = tfuture = 0;
-
- //2: Accounts for real
- for(j=0;j<gpa->len;j++)
- {
- acc = g_ptr_array_index(gpa, j);
-
- //tbank += acc->bal_bank;
- //ttoday += acc->bal_today;
- //tfuture += acc->bal_future;
- tbank += hb_amount_base(acc->bal_bank, acc->kcur);
- ttoday += hb_amount_base(acc->bal_today, acc->kcur);
- tfuture += hb_amount_base(acc->bal_future, acc->kcur);
-
- DB( g_print(" - 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,
- LST_DSPACC_DATAS, acc,
- LST_DSPACC_DATATYPE, DSPACC_TYPE_NORMAL,
- LST_DSPACC_BANK, acc->bal_bank,
- LST_DSPACC_TODAY, acc->bal_today,
- LST_DSPACC_FUTURE, acc->bal_future,
- -1);
- }
-
- if(gpa->len > 1)
- {
- 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);
- gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter,
- LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL,
- LST_DSPACC_NAME, _("Total"),
- LST_DSPACC_BANK, tbank,
- LST_DSPACC_TODAY, ttoday,
- LST_DSPACC_FUTURE, tfuture,
- -1);
- }
-
- /* set balance to header to display when collasped */
- 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,
- LST_DSPACC_FUTURE, tfuture,
- -1);
-
- /* add to grand total */
- gtbank += tbank;
- gttoday += ttoday;
- gtfuture += tfuture;
+ result = ui_dialog_msg_confirm_alert(
+ GTK_WINDOW(GLOBALS->mainwindow),
+ _("The file has been modified since reading it."),
+ _("If you save it, all the external changes could be lost. Save it anyway?"),
+ _("S_ave Anyway")
+ );
-
+
+ if( result != GTK_RESPONSE_OK )
+ return;
}
+ DB( g_print(" + saving...\n") );
+ homebank_file_ensure_xhb(NULL);
+ homebank_backup_current_file();
+ r = homebank_save_xml(GLOBALS->xhb_filepath);
}
- DB( g_print(" - grand total :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) );
-
- // Grand total
- if( nbtype > 1 )
+ if(r == XML_OK)
{
- gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL);
- gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
- LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL,
- LST_DSPACC_NAME, _("Grand total"),
- LST_DSPACC_BANK, gtbank,
- LST_DSPACC_TODAY, gttoday,
- LST_DSPACC_FUTURE, gtfuture,
- -1);
+ DB( g_print(" + OK...\n") );
+ GLOBALS->changes_count = 0;
+ GLOBALS->xhb_timemodified = hbfile_file_get_time_modified (GLOBALS->xhb_filepath);
+ ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
}
-
-
- gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
-
- DB( g_print(" - free ressources\n") );
-
- g_hash_table_iter_init (&grp_iter, h_group);
- while (g_hash_table_iter_next (&grp_iter, &key, &value))
+ else
{
- g_ptr_array_free (value, TRUE);
- }
- g_hash_table_destroy (h_group);
+ gchar *msg = _("I/O error for file '%s'.");
+ ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
+ _("File error"),
+ msg,
+ GLOBALS->xhb_filepath
+ );
+ }
}
changed = (GLOBALS->changes_count > 0) ? "*" : "";
+ #if MYDEBUG == 1
+ data->wintitle = g_strdup_printf("%s%s (%d)- %s - " PROGNAME, changed, basename, GLOBALS->changes_count, GLOBALS->owner);
+ #else
data->wintitle = g_strdup_printf("%s%s - %s - " PROGNAME, changed, basename, GLOBALS->owner);
-
+ #endif
+
gtk_window_set_title (GTK_WINDOW (gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), data->wintitle);
g_free(basename);
active = FALSE;
}
-
- // no change: disable save
DB( g_print(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) );
-
+ // save
sensitive = (GLOBALS->changes_count != 0 ) ? TRUE : FALSE;
- //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/SaveAs"), sensitive);
- //if(sensitive == TRUE && GLOBALS->hbfile_is_new == TRUE) sensitive = FALSE;
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Save"), sensitive);
- gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Revert"), GLOBALS->xhb_hasbak);
+ // backup
+ sensitive = ( (GLOBALS->changes_count != 0) && GLOBALS->xhb_hasrevert ) ? TRUE : FALSE;
+ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Revert"), sensitive);
+ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/OpenBak"), sensitive);
// define off ?
sensitive = GLOBALS->define_off == 0 ? TRUE : FALSE;
-
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Account"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Payee"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Category"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/EditMenu/Preferences"), sensitive);
- // empty account list: disable Import, Archives, Edit, Filter, Add, Statistics, Overdrawn, Car Cost
+ // empty account list: disable Archives, Edit, Filter, Add, Statistics, Overdrawn, Car Cost
sensitive = da_acc_length() > 0 ? TRUE : FALSE;
-
- //gtk_action_set_sensitive(gtk_ui_manager_get_action(data-data->manager, "/MenuBar/FileMenu/Import"), sensitive);
-
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Close"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Archive"), sensitive);
- gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddOpe"), sensitive);
- gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
+ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddTxn"), sensitive);
+ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowTxn"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RStatistics"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RTrendTime"), sensitive);
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBudget"), sensitive);
// empty archive list: disable scheduled check
sensitive = g_list_length(GLOBALS->arc_list) > 0 ? TRUE : FALSE;
-
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddScheduled"), sensitive);
// no active account: disable Edit, Over
sensitive = (active == TRUE ) ? TRUE : FALSE;
if(data->acc && data->acc->window != NULL)
sensitive = FALSE;
-
- gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
-
+ gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowTxn"), sensitive);
}
/* update toolbar, list */
gtk_widget_hide(GTK_WIDGET(data->GR_top));
--
++
DB( g_print(" - show upcoming=%d\n", PREFS->wal_upcoming) );
if(PREFS->wal_upcoming)
gtk_widget_show(GTK_WIDGET(data->GR_upc));
{
DB( g_print(" 16: refreshall\n") );
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
- ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
- ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_account_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_spending_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_scheduled_populate(GLOBALS->mainwindow, NULL);
+ ui_hub_transaction_populate(data);
}
struct WinGeometry *wg;
gboolean retval = FALSE;
+ GValue widget_value = G_VALUE_INIT;
+ ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL);
+
DB( g_print("\n[ui-mainwindow] delete-event\n") );
//store position and size
GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(widget));
GdkWindowState state = gdk_window_get_state(gdk_window);
wg->s = (state & GDK_WINDOW_STATE_MAXIMIZED) ? 1 : 0;
-
DB( g_print(" window: l=%d, t=%d, w=%d, h=%d s=%d, state=%d\n", wg->l, wg->t, wg->w, wg->h, wg->s, state & GDK_WINDOW_STATE_MAXIMIZED) );
PREFS->wal_vpaned = gtk_paned_get_position(GTK_PANED(data->vpaned));
PREFS->wal_hpaned = gtk_paned_get_position(GTK_PANED(data->hpaned));
-
DB( g_print(" - vpaned=%d hpaned=%d\n", PREFS->wal_vpaned, PREFS->wal_hpaned) );
-
+ if(PREFS->pnl_list_tab)
+ g_free(PREFS->pnl_list_tab);
+ PREFS->pnl_list_tab = g_strdup(gtk_stack_get_visible_child_name(GTK_STACK(data->stack)));
++
//todo
if(ui_dialog_msg_savechanges(widget, NULL) == FALSE)
{
gtk_widget_destroy(data->LV_top);
g_free(data->wintitle);
- da_filter_free(data->filter);
+ da_flt_free(data->filter);
g_free(user_data);
--
++
gtk_main_quit();
}
}
- static void ui_mainwindow_window_screen_changed_cb (GtkWidget *widget,
- GdkScreen *old_screen,
- struct hbfile_data *data)
- {
-
- DB( g_print("\n[ui-mainwindow] screen_changed_cb\n") );
-
-
- data->recent_manager = gtk_recent_manager_get_default ();
-
- gtk_menu_detach (GTK_MENU (data->recent_menu));
- g_object_unref (G_OBJECT (data->recent_menu));
-
- data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
-
- g_signal_connect (data->recent_menu,
- "item-activated",
- G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
- data);
-
- //menu_item = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/OpenRecent");
- //gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), data->recent_menu);
- }
-
-
void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path)
{
GtkRecentData *recent_data;
{
gchar **uris, **str;
gchar *newseldata;
- gint filetype, slen;
+ gint n_uris, filetype, slen;
+ GError *error = NULL;
-
+
if (info != TARGET_URI_LIST)
return;
newseldata = g_new (gchar, slen + 1);
memcpy (newseldata, gtk_selection_data_get_data(selection_data), slen);
newseldata[slen] = 0;
-
+ //DB( g_print(" - seldata ='%s'\n", gtk_selection_data_get_data(selection_data) ) );
+ //DB( g_print(" - newseldata ='%s'\n", newseldata ) );
+
uris = g_uri_list_extract_uris (newseldata);
+ n_uris = g_strv_length(uris);
+ DB( g_print(" - dragged %d files (len=%d)\n", n_uris, slen ) );
- DB( g_print(" - dragged %d %d files\n", slen, g_strv_length(uris) ) );
+ g_free(newseldata);
- str = uris;
- //for (str = uris; *str; str++)
- if( *str )
+ //single file: check for xhb
+ if(n_uris == 1)
- {
+ {
- GError *error = NULL;
- gchar *path = g_filename_from_uri (*str, NULL, &error);
+ filetype = hb_filename_type_get_by_extension(*uris);
- if (path)
- {
- filetype = homebank_alienfile_recognize(path);
+ DB( g_print(" - filetype is homebank (%d)\n", filetype) );
- DB( g_print(" - dragged %s, type is %d\n", path, filetype ) );
+ if( filetype == FILETYPE_HOMEBANK )
+ {
+ gchar *path = g_filename_from_uri (*uris, NULL, &error);
- if( filetype == FILETYPE_HOMEBANK)
+ if( path != NULL )
{
+ DB( g_print(" - path is '%s'\n", path) );
hbfile_change_filepath(g_strdup(path));
ui_mainwindow_open_internal(GTK_WIDGET(window), NULL);
+ goto end_drop;
}
else
{
- //todo: future here to implement import for other filetype
- // ui_import_assistant_new();
- // + write a method into assistant to catch other filename
-
-
- ui_dialog_msg_infoerror(GTK_WINDOW(window), GTK_MESSAGE_ERROR,
+ g_warning ("Could not convert uri to local path: %s", error->message);
+ g_error_free (error);
+ }
+ g_free (path);
+ }
+ /* we no more manage error here
+ ui_dialog_msg_infoerror(GTK_WINDOW(window), GTK_MESSAGE_ERROR,
_("File error"),
_("The file %s is not a valid HomeBank file."),
- path
- );
-
+ path);
+ */
+ }
- }
+ //collect known filetype to import
+ DB( g_print(" - collect %d files\n", n_uris) );
-
+
- }
- else
+ gchar **paths = g_new (gchar *, n_uris + 1);
+ slen = 0;
+ for (str = uris; *str; str++)
+ {
+ filetype = hb_filename_type_get_by_extension(*str);
+ if( filetype != FILETYPE_HOMEBANK && filetype != FILETYPE_UNKNOWN )
{
- g_warning ("Could not convert uri to local path: %s", error->message);
+ gchar *path = g_filename_from_uri (*str, NULL, NULL);
- g_error_free (error);
+ if( path != NULL )
+ {
+ DB( g_print(" - append %d '%s'\n", slen, path ) );
+ paths[slen++] = path;
+ }
- }
+ }
- g_free (path);
}
-
-
+ paths[slen] = NULL;
+
+ if( slen > 0 )
+ {
+ ui_import_assistant_new( paths );
+ }
++
++
+ end_drop:
g_strfreev (uris);
-
- g_free(newseldata);
}
static GtkWidget *ui_mainwindow_create_recent_chooser_menu (GtkRecentManager *manager)
{
- GtkWidget *toolbar_recent_menu;
+ GtkWidget *recent_menu;
GtkRecentFilter *filter;
- toolbar_recent_menu = gtk_recent_chooser_menu_new_for_manager (manager);
-
- gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (toolbar_recent_menu),
- FALSE);
- gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (toolbar_recent_menu),
- GTK_RECENT_SORT_MRU);
+ recent_menu = gtk_recent_chooser_menu_new_for_manager (manager);
+ gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (recent_menu), FALSE);
+ gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (recent_menu), GTK_RECENT_SORT_MRU);
//todo: add a user pref for this
- gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (toolbar_recent_menu),
- 10);
-
-
- //gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (toolbar_recent_menu), FALSE);
-
- //gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (toolbar_recent_menu), TRUE);
+ gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (recent_menu), 10);
+ gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (recent_menu), FALSE);
+ //gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (recent_menu), TRUE);
filter = gtk_recent_filter_new ();
//gtk_recent_filter_add_application (filter, g_get_application_name());
gtk_recent_filter_add_pattern (filter, "*.[Xx][Hh][Bb]");
- gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (toolbar_recent_menu), filter);
+ gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (recent_menu), filter);
- return toolbar_recent_menu;
+ return recent_menu;
}
action = gtk_action_group_get_action(actions, "Budget");
g_object_set(action, "short_label", _("Budget"), NULL);
- action = gtk_action_group_get_action(actions, "ShowOpe");
+ action = gtk_action_group_get_action(actions, "ShowTxn");
g_object_set(action, "short_label", _("Show"), NULL);
- action = gtk_action_group_get_action(actions, "AddOpe");
+ action = gtk_action_group_get_action(actions, "AddTxn");
g_object_set(action, "is_important", TRUE, "short_label", _("Add"), NULL);
action = gtk_action_group_get_action(actions, "RStatistics");
g_error_free (error);
}
- //todo: this generate a warning
+
+ data->recent_manager = gtk_recent_manager_get_default ();
+
data->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
gtk_box_pack_start (GTK_BOX (mainvbox),
data->menubar,
FALSE,
0);
- data->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
- gtk_box_pack_start (GTK_BOX (mainvbox),
- data->toolbar,
- FALSE,
- FALSE,
- 0);
-
/* recent files menu */
-
- data->recent_manager = gtk_recent_manager_get_default ();
-
data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
g_signal_connect (data->recent_menu,
G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
data);
- /*
- widget = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/OpenRecent");
+ GtkWidget *widget = gtk_ui_manager_get_widget (data->manager, "/MenuBar/FileMenu/RecentMenu");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), data->recent_menu);
- */
- /* test */
- /* add the custom Open button to the toolbar */
- GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_OPEN, GTK_ICON_SIZE_BUTTON);
- GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open"));
- gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), data->recent_menu);
+ data->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
+ gtk_box_pack_start (GTK_BOX (mainvbox),
+ data->toolbar,
+ FALSE,
+ FALSE,
+ 0);
+ /* add the custom Open button to the toolbar */
+ GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_HB_FILE_OPEN, GTK_ICON_SIZE_BUTTON);
+ GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open"));
gtk_tool_item_set_tooltip_text (open_button, _("Open a file"));
+
+ GtkWidget *recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
+ gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), recent_menu);
gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), _("Open a recently used file"));
+ g_signal_connect (recent_menu,
+ "item-activated",
+ G_CALLBACK (ui_mainwindow_recent_chooser_item_activated_cb),
+ data);
+
action = gtk_action_group_get_action (data->actions, "Open");
g_object_set (action, "short_label", _("Open"), NULL);
//gtk_action_connect_proxy (action, GTK_WIDGET (open_button));
gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button), action);
gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), open_button, 1);
- /* end test */
-
- }
-
- /* Callback function for the undo action */
- /*static void
- activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
- {
- g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)));
- }*/
-
- static void
- activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
- {
- struct hbfile_data *data = user_data;
- GVariant *old_state, *new_state;
-
- old_state = g_action_get_state (G_ACTION (action));
- new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
-
- DB( g_print ("Toggle action %s activated, state changes from %d to %d\n",
- g_action_get_name (G_ACTION (action)),
- g_variant_get_boolean (old_state),
- g_variant_get_boolean (new_state)) );
-
- data->showall = g_variant_get_boolean (new_state);
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
-
- g_simple_action_set_state (action, new_state);
- g_variant_unref (old_state);
- }
-
- static void
- activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
- {
- //struct hbfile_data *data = user_data;
- GVariant *old_state, *new_state;
-
- old_state = g_action_get_state (G_ACTION (action));
- new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
-
- DB( g_print ("Radio action %s activated, state changes from %s to %s\n",
- g_action_get_name (G_ACTION (action)),
- g_variant_get_string (old_state, NULL),
- g_variant_get_string (new_state, NULL)) );
-
- PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_TYPE;
- if( !strcmp("bank", g_variant_get_string(new_state, NULL)) )
- PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_BANK;
-
- ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
-
- g_simple_action_set_state (action, new_state);
- g_variant_unref (old_state);
- }
-
-
- 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} }
- };
-
-
- 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;
- GtkToolItem *toolitem;
-
- panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
-
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0);
- widget = (GtkWidget *)create_list_account();
- data->LV_acc = widget;
- gtk_container_add (GTK_CONTAINER (sw), widget);
-
- //list toolbar
- tbar = gtk_toolbar_new();
- gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
- gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
- gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
- gtk_box_pack_start (GTK_BOX (panel), tbar, FALSE, FALSE, 0);
-
- label = make_label_group(_("Your accounts"));
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), label);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- toolitem = gtk_separator_tool_item_new ();
- gtk_tool_item_set_expand (toolitem, TRUE);
- gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), hbox);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- widget = make_image_button(ICONNAME_HB_BUTTON_EXPAND, _("Expand all"));
- data->BT_expandall = widget;
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-
- widget = make_image_button(ICONNAME_HB_BUTTON_COLLAPSE, _("Collapse all"));
- data->BT_collapseall = widget;
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-
- toolitem = gtk_separator_tool_item_new ();
- gtk_tool_item_set_expand (toolitem, FALSE);
- gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
-
- //gmenu test (see test folder into gtk)
- GMenu *menu, *section;
-
- menu = g_menu_new ();
- //g_menu_append (menumodel, "About", "actions.undo");
- //g_menu_append (menumodel, "Test", "actions.redo");
- section = g_menu_new ();
- g_menu_append (section, _("Show all"), "actions.showall");
- g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
- g_object_unref (section);
-
- section = g_menu_new ();
- g_menu_append (section, _("By type"), "actions.groupby::type");
- g_menu_append (section, _("By institition"), "actions.groupby::bank");
- g_menu_append_section(menu, NULL, G_MENU_MODEL(section));
- g_object_unref (section);
-
-
- 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);
-
-
- 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;
- }
-
-
- static GtkWidget *ui_mainwindow_create_topspending(struct hbfile_data *data)
- {
- GtkWidget *panel, *hbox, *tbar;
- GtkWidget *label, *widget;
- GtkToolItem *toolitem;
-
- widget = (GtkWidget *)create_list_topspending();
- data->LV_top = widget;
-
- panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
- data->GR_top = panel;
- /* chart + listview */
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_box_pack_start (GTK_BOX (panel), hbox, TRUE, TRUE, 0);
-
- widget = gtk_chart_new(CHART_TYPE_PIE);
- data->RE_pie = widget;
- gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol);
- gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE);
- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
-
- //list toolbar
- tbar = gtk_toolbar_new();
- gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
- gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
- gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
- gtk_box_pack_start (GTK_BOX (panel), tbar, FALSE, FALSE, 0);
-
- label = make_label_group(_("Where your money goes"));
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), label);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- toolitem = gtk_separator_tool_item_new ();
- gtk_tool_item_set_expand (toolitem, TRUE);
- gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- /* total + date range */
- hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), hbox);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- data->CY_range = make_daterange(label, FALSE);
- gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0);
-
- widget = make_radio(CYA_CATSUBCAT, TRUE, GTK_ORIENTATION_HORIZONTAL);
- data->RA_type = widget;
- gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-
- return panel;
- }
-
-
- static GtkWidget *ui_mainwindow_scheduled_create(struct hbfile_data *data)
- {
- GtkWidget *panel, *hbox, *vbox, *bbox, *sw, *tbar;
- GtkWidget *label, *widget;
- GtkToolItem *toolitem;
-
- panel = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_container_set_border_width(GTK_CONTAINER(panel), SPACING_SMALL);
- data->GR_upc = panel;
-
- vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0);
- //gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL);
- //gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL);
- //gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL);
- gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0);
-
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
-
- widget = (GtkWidget *)create_list_upcoming();
- data->LV_upc = widget;
- gtk_container_add (GTK_CONTAINER (sw), widget);
-
- tbar = gtk_toolbar_new();
- gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
- gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
- gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
- gtk_box_pack_start (GTK_BOX (vbox), tbar, FALSE, FALSE, 0);
-
- label = make_label_group(_("Scheduled transactions"));
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), label);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- toolitem = gtk_separator_tool_item_new ();
- gtk_tool_item_set_expand (toolitem, FALSE);
- gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
-
- bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), bbox);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- widget = gtk_button_new_with_label(_("Skip"));
- data->BT_sched_skip = widget;
- gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
-
- widget = gtk_button_new_with_label(_("Edit & Post"));
- data->BT_sched_editpost = widget;
- gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
-
- //TRANSLATORS: Posting a scheduled transaction is the action to materialize it into its target account.
- //TRANSLATORS: Before that action the automated transaction occurrence is pending and not yet really existing.
- widget = gtk_button_new_with_label (_("Post"));
- data->BT_sched_post = widget;
- gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
-
- toolitem = gtk_separator_tool_item_new ();
- gtk_tool_item_set_expand (toolitem, FALSE);
- gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_widget_set_valign (hbox, GTK_ALIGN_CENTER);
- toolitem = gtk_tool_item_new();
- gtk_container_add (GTK_CONTAINER(toolitem), hbox);
- gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
-
- label = make_label(_("maximum post date"), 0.0, 0.7);
- gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
- gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- label = make_label(NULL, 0.0, 0.7);
- data->LB_maxpostdate = label;
- gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
- gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- return panel;
}
{
struct hbfile_data *data;
struct WinGeometry *wg;
- GtkWidget *mainvbox, *vbox, *vpaned, *hpaned;
- GtkWidget *widget;
+ GtkWidget *mainvbox, *vbox, *box, *vpaned, *hpaned, *sidebar, *stack;
+ GtkWidget *widget, *page;
GtkWidget *window;
GtkAction *action;
gtk_label_set_markup (GTK_LABEL(label), "Unstable Development Version");
gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label, FALSE, FALSE, 0);
#endif
--
++
/* Add the main area */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
//gtk_container_set_border_width (GTK_CONTAINER(vbox), SPACING_MEDIUM);
data->vpaned = vpaned;
gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
- hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
- data->hpaned = hpaned;
- gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
-
- widget = ui_mainwindow_scheduled_create(data);
- gtk_paned_pack2 (GTK_PANED(vpaned), widget, TRUE, FALSE);
+ hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
+ data->hpaned = hpaned;
+ gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
- widget = ui_mainwindow_create_youraccounts(data);
+ widget = ui_hub_account_create(data);
//gtk_widget_set_size_request (widget, 100, -1);
gtk_paned_pack1 (GTK_PANED(hpaned), widget, FALSE, FALSE);
- widget = ui_mainwindow_create_topspending(data);
+ widget = ui_hub_spending_create(data);
//gtk_widget_set_size_request (widget, -1, 100);
gtk_paned_pack2 (GTK_PANED(hpaned), widget, TRUE, FALSE);
-
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ data->GR_upc = box;
+ gtk_paned_pack2 (GTK_PANED(vpaned), box, TRUE, FALSE);
+
+ sidebar = gtk_stack_sidebar_new ();
+ gtk_box_pack_start (GTK_BOX (box), sidebar, FALSE, FALSE, 0);
+
+ stack = gtk_stack_new ();
+ //gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
+ gtk_stack_sidebar_set_stack (GTK_STACK_SIDEBAR (sidebar), GTK_STACK (stack));
+ data->stack = stack;
+ gtk_box_pack_start (GTK_BOX (box), stack, TRUE, TRUE, 0);
-
++
+ page = ui_hub_scheduled_create(data);
+ gtk_stack_add_titled (GTK_STACK (stack), page, "sched", _("Scheduled"));
+ //gtk_paned_pack2 (GTK_PANED(vpaned), widget, TRUE, FALSE);
+
+ page = ui_hub_transaction_create(data, HUB_TXN_TYPE_FUTURE);
+ gtk_stack_add_titled (GTK_STACK (stack), page, "futur", _("Future"));
+
+ page = ui_hub_transaction_create(data, HUB_TXN_TYPE_REMIND);
+ gtk_stack_add_titled (GTK_STACK (stack), page, "remin", _("Remind"));
++
//setup, init and show window
wg = &PREFS->wal_wg;
if(PREFS->wal_vpaned > 0)
gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned);
-
+ if( PREFS->pnl_list_tab != NULL )
+ gtk_stack_set_visible_child_name (GTK_STACK(data->stack), PREFS->pnl_list_tab);
+
++
//todo: move this elsewhere
DB( g_print(" - setup stuff\n") );
- data->filter = da_filter_malloc();
- filter_default_all_set(data->filter);
+ data->filter = da_flt_malloc();
+ filter_reset(data->filter);
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_wal);
action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Toolbar");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_toolbar);
action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Spending");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_spending);
- action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/Upcoming");
+ action = gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/BottomLists");
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), PREFS->wal_upcoming);
/* Drag and drop support, set targets to NULL because we add the
g_signal_connect (G_OBJECT (window), "drag-data-received",
G_CALLBACK (ui_mainwindow_drag_data_received), window);
-
-
//connect all our signals
DB( g_print(" - connect signals\n") );
-
g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc)), "changed", G_CALLBACK (ui_mainwindow_selection), NULL);
g_signal_connect (GTK_TREE_VIEW(data->LV_acc ), "row-activated", G_CALLBACK (ui_mainwindow_onRowActivated), GINT_TO_POINTER(2));
- g_signal_connect (G_OBJECT (data->BT_expandall ), "clicked" , G_CALLBACK (ui_panel_accounts_expand_all), NULL);
- g_signal_connect (G_OBJECT (data->BT_collapseall), "clicked" , G_CALLBACK (ui_panel_accounts_collapse_all), NULL);
-
- g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_upc)), "changed", G_CALLBACK (ui_mainwindow_scheduled_selection_cb), NULL);
- g_signal_connect (GTK_TREE_VIEW(data->LV_upc), "row-activated", G_CALLBACK (ui_mainwindow_scheduled_onRowActivated), NULL);
- g_signal_connect (G_OBJECT (data->BT_sched_skip), "clicked", G_CALLBACK (ui_mainwindow_scheduled_skip_cb), data);
- g_signal_connect (G_OBJECT (data->BT_sched_editpost), "clicked", G_CALLBACK (ui_mainwindow_scheduled_editpost_cb), data);
- g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data);
-
- widget = radio_get_nth_widget(GTK_CONTAINER(data->RA_type), 1);
- if(widget)
- g_signal_connect (widget, "toggled", G_CALLBACK (ui_mainwindow_populate_topspending), &data);
-
- g_signal_connect (data->CY_range, "changed", G_CALLBACK (ui_mainwindow_populate_topspending), NULL);
-
/* 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",
- G_CALLBACK (ui_mainwindow_window_screen_changed_cb),
- data);
-
-
//gtk_action_group_set_sensitive(data->actions, FALSE);
-
return window;
}
--- /dev/null
- #include "dsp_mainwindow.h"
- #include "dsp_account.h"
+
+#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;
- RETVAL = G_OBJECT(register_panel_window_new(SELF->key, SELF));
++#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(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY, FALSE));
++ RETVAL = G_OBJECT(register_panel_window_new(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*
+memo(Transaction* SELF, ...)
+ CODE:
+ if (1 < items) {
+ if (SELF->memo) g_free(SELF->memo);
+ SELF->memo = g_strdup(SvGchar_ptr(ST(1)));
+ }
+ 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:
- other = ui_dialog_transaction_xfer_select_child(SELF, list);
++ RETVAL = G_OBJECT(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY, FALSE, 0));
+ 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);
+ }
++ ui_dialog_transaction_xfer_select_child(NULL, SELF, list, &other);
+ }
+ 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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 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_free(item->imp_name);
g_free(item->name);
g_free(item->number);
g_free(item->bankname);
g_free(item->notes);
--
++
g_queue_free (item->txn_queue);
--
- g_free(item);
++
+ rc_free(item);
}
}
Account *item;
DB( g_print("da_acc_malloc\n") );
- item = g_malloc0(sizeof(Account));
+ item = rc_alloc(sizeof(Account));
+ item->kcur = GLOBALS->kcur;
item->txn_queue = g_queue_new ();
return item;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- static void da_acc_max_key_ghfunc(gpointer key, Account *item, guint32 *max_key)
- {
- *max_key = MAX(*max_key, item->key);
- }
- static gboolean da_acc_name_grfunc(gpointer key, Account *item, gchar *name)
- {
- if( name && item->name )
- {
- if(!strcasecmp(name, item->name))
- return TRUE;
- }
- return FALSE;
- }
-
- static gboolean da_acc_imp_name_grfunc(gpointer key, Account *item, gchar *name)
- {
- if( name && item->imp_name )
- {
- if(!strcasecmp(name, item->imp_name))
- return TRUE;
- }
- return FALSE;
- }
/**
* da_acc_length:
}
+ static void da_acc_max_key_ghfunc(gpointer key, Account *item, guint32 *max_key)
+ {
+ *max_key = MAX(*max_key, item->key);
+ }
+
+
+ /**
+ * da_acc_get_max_key:
+ *
+ * Get the biggest key from the GHashTable
+ *
+ * Return value: the biggest key value
+ *
+ */
+ guint32
+ da_acc_get_max_key(void)
+ {
+ guint32 max_key = 0;
+
+ g_hash_table_foreach(GLOBALS->h_acc, (GHFunc)da_acc_max_key_ghfunc, &max_key);
+ return max_key;
+ }
+
+
/**
* da_acc_remove:
*
*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;
}
da_acc_append(Account *item)
{
Account *existitem;
- guint32 *new_key;
DB( g_print("da_acc_append\n") );
- /* ensure no duplicate */
- g_strstrip(item->name);
- if(item->name != NULL)
+ existitem = da_acc_get_by_name( item->name );
+ if( existitem == NULL )
{
- existitem = da_acc_get_by_name( item->name );
- if( existitem == NULL )
- {
- new_key = g_new0(guint32, 1);
- *new_key = da_acc_get_max_key() + 1;
- item->key = *new_key;
- item->pos = da_acc_length() + 1;
+ item->key = da_acc_get_max_key() + 1;
+ item->pos = da_acc_length() + 1;
+ da_acc_insert(item);
+
- DB( g_print(" -> insert id: %d\n", *new_key) );
++ GValue item_val = G_VALUE_INIT;
++ ext_hook("account_inserted", EXT_ACCOUNT(&item_val, item), NULL);
+
- 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;
- }
+ return TRUE;
}
DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
return FALSE;
}
- /**
- * da_acc_get_max_key:
- *
- * Get the biggest key from the GHashTable
- *
- * Return value: the biggest key value
- *
- */
- guint32
- da_acc_get_max_key(void)
- {
- guint32 max_key = 0;
- g_hash_table_foreach(GLOBALS->h_acc, (GHFunc)da_acc_max_key_ghfunc, &max_key);
- return max_key;
+ static gboolean da_acc_name_grfunc(gpointer key, Account *item, gchar *name)
+ {
+ if( name && item->name )
+ {
+ if(!strcasecmp(name, item->name))
+ return TRUE;
+ }
+ return FALSE;
}
-
-
-
/**
* da_acc_get_by_name:
*
*
*/
Account *
- da_acc_get_by_name(gchar *name)
+ da_acc_get_by_name(gchar *rawname)
{
+ Account *retval = NULL;
+ gchar *stripname;
+
DB( g_print("da_acc_get_by_name\n") );
- return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_name_grfunc, name);
- }
+ if( rawname )
+ {
+ stripname = g_strdup(rawname);
+ g_strstrip(stripname);
+ if( strlen(stripname) > 0 )
+ retval = g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_name_grfunc, stripname);
- Account *
- da_acc_get_by_imp_name(gchar *name)
- {
- DB( g_print("da_acc_get_by_imp_name\n") );
+ g_free(stripname);
+ }
- return g_hash_table_find(GLOBALS->h_acc, (GHRFunc)da_acc_imp_name_grfunc, name);
- return retval;
++ return retval;
}
while (lnk_acc != NULL)
{
Account *acc = lnk_acc->data;
--
++
if(acc->key != key)
{
lnk_txn = g_queue_peek_head_link(acc->txn_queue);
while (lnk_txn != NULL)
{
Transaction *entry = lnk_txn->data;
--
++
if( key == entry->kxferacc)
{
retval = TRUE;
Account *existitem;
gchar *stripname = account_get_stripname(newname);
- existitem = da_acc_get_by_name(stripname);
- if( existitem == NULL )
+ if( strlen(stripname) > 0 )
{
- g_free(item->name);
- item->name = g_strdup(stripname);
- return TRUE;
- }
+ existitem = da_acc_get_by_name(stripname);
+ if( existitem == NULL )
+ {
+ g_free(item->name);
+ item->name = g_strdup(stripname);
+ return TRUE;
+ }
- g_free(stripname);
+ g_free(stripname);
+ }
-
+
return FALSE;
}
--/*
++/*
* change the account currency
* change every txn to currency
* ensure dst xfer transaction account will be set to same currency
}
DB( g_print(" - set for '%s'\n", acc->name) );
-
+
maxkey = da_acc_get_max_key () + 1;
xfer_list = g_malloc0(sizeof(gboolean) * maxkey );
DB( g_print(" - alloc for %d account\n", da_acc_length() ) );
acc->kcur = kcur;
DB( g_print(" - '%s'\n", acc->name) );
--
++
for(i=1;i<maxkey;i++)
{
DB( g_print(" - %d '%d'\n", i, xfer_list[i]) );
while (lnk_acc != NULL)
{
Account *acc = lnk_acc->data;
--
++
/* set initial amount */
acc->bal_bank = acc->initial;
acc->bal_today = acc->initial;
acc->bal_future = acc->initial;
--
++
/* add every txn */
lnk_txn = g_queue_peek_head_link(acc->txn_queue);
while (lnk_txn != NULL)
{
Transaction *txn = lnk_txn->data;
--
++
if(!(txn->status == TXN_STATUS_REMIND))
{
account_balances_add_internal(acc, txn);
}
lnk_txn = g_list_next(lnk_txn);
}
--
++
lnk_acc = g_list_next(lnk_acc);
}
g_list_free(lst_acc);
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-archive.h"
#include "hb-split.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
Archive *da_archive_malloc(void)
{
- return rc_alloc(sizeof(Archive));
+ Archive *item;
+
- item = g_malloc0(sizeof(Archive));
++ item = rc_alloc(sizeof(Archive));
+ item->key = 1;
+ return item;
}
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->memo = g_strdup(src_item->memo);
- if( da_splits_clone(src_item->splits, new_item->splits) > 0)
+ //duplicate tags
+ //no g_free here to avoid free the src tags (memdup copie dthe ptr)
+ new_item->tags = tags_clone(src_item->tags);
+
+ //duplicate splits
+ //no g_free here to avoid free the src tags (memdup copie dthe ptr)
+ new_item->splits = da_splits_clone(src_item->splits);
+ if( da_splits_length (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->memo != NULL)
g_free(item->memo);
-
- da_splits_free(item->splits);
- //item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
-
+ if(item->splits != NULL)
+ da_split_destroy(item->splits);
- g_free(item);
+ rc_free(item);
}
}
}
- max_key = MAX(item->key, max_key);
+ /* append a fav with an existing key (from xml file only) */
+ gboolean
+ da_archive_append(Archive *item)
+ {
+ GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, item);
+ return TRUE;
+ }
+
+
+ gboolean
+ da_archive_append_new(Archive *item)
+ {
+ item->key = da_archive_get_max_key() + 1;
+ GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, item);
+ return TRUE;
+ }
+
+
+ guint32
+ da_archive_get_max_key(void)
+ {
+ GList *tmplist = g_list_first(GLOBALS->arc_list);
+ guint32 max_key = 0;
+
+ while (tmplist != NULL)
+ {
+ Archive *item = tmplist->data;
+
-
++ max_key = MAX(item->key, max_key);
+ tmplist = g_list_next(tmplist);
+ }
++
+ return max_key;
+ }
+
+
+ Archive *
+ da_archive_get(guint32 key)
+ {
+ GList *tmplist;
+ Archive *retval = NULL;
+
+ tmplist = g_list_first(GLOBALS->arc_list);
+ while (tmplist != NULL)
+ {
+ Archive *item = tmplist->data;
+
+ if(item->key == key)
+ {
+ retval = item;
+ break;
+ }
+ tmplist = g_list_next(tmplist);
+ }
+ return retval;
+ }
+
+
void da_archive_consistency(Archive *item)
{
Account *acc;
Category *cat;
Payee *pay;
+ guint nbsplit;
// check category exists
cat = da_cat_get(item->kcat);
item->kcat = 0;
GLOBALS->changes_count++;
}
-
- split_cat_consistency(item->splits);
-
+
- //#1340142 check split category
++ //#1340142 check split category
+ if( item->splits != NULL )
+ {
+ nbsplit = da_splits_consistency(item->splits);
+ //# 1416624 empty category when split
+ if(nbsplit > 0 && item->kcat > 0)
+ {
+ g_warning("txn consistency: fixed invalid cat on split txn");
+ item->kcat = 0;
+ GLOBALS->changes_count++;
+ }
+ }
-
++
// check payee exists
pay = da_pay_get(item->kpay);
if(pay == NULL)
arc->kpay = txn->kpay;
arc->kcat = txn->kcat;
if(txn->memo != NULL)
- arc->memo = g_strdup(txn->memo);
+ arc->memo = g_strdup(txn->memo);
else
- arc->memo = g_strdup(_("(new archive)"));
+ arc->memo = g_strdup(_("(new archive)"));
- if( da_splits_clone(txn->splits, arc->splits) > 0)
+ arc->tags = tags_clone(txn->tags);
+ arc->splits = da_splits_clone(txn->splits);
+ if( da_splits_length (arc->splits) > 0 )
arc->flags |= OF_SPLIT; //Flag that Splits are active
--
++
return arc;
}
/* get the final post date and free */
nextpostdate = g_date_get_julian(tmpdate);
--
++
return nextpostdate;
}
finalpostdate = postdate;
--
++
tmpdate = g_date_new_julian(finalpostdate);
/* manage weekend exception */
if( arc->weekend > 0 )
}
}
}
--
++
/* get the final post date and free */
finalpostdate = g_date_get_julian(tmpdate);
g_date_free(tmpdate);
--
++
return finalpostdate;
}
if(arc->flags & OF_LIMIT)
nblate = MIN(nblate, arc->limit);
--
++
nblate = MIN(nblate, 11);
*/
--
++
// pre 5.1 way
post_date = g_date_new();
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)
+ if( nblate >= 11 || ( (arc->flags & OF_LIMIT) && (nblate >= arc->limit) ) )
break;
}
}
arc->daygap = CLAMP(lastday - g_date_get_day(post_date), 0, 3);
--
++
DB( g_print(" daygap is %d\n", arc->daygap) );
}
else
DB( g_print("\n[scheduled] date_get_post_max\n") );
//add until xx of the next month (excluded)
-- if(GLOBALS->auto_smode == 0)
++ if(GLOBALS->auto_smode == 0)
{
DB( g_print(" - max is %d of next month\n", GLOBALS->auto_weekday) );
--
++
today = g_date_new_julian(GLOBALS->today);
//we compute user xx weekday of next month
g_date_set_day(maxdate, GLOBALS->auto_weekday);
if(g_date_get_day (today) >= GLOBALS->auto_weekday)
g_date_add_months(maxdate, 1);
--
++
nbdays = g_date_days_between(today, maxdate);
--
++
g_date_free(maxdate);
g_date_free(today);
}
maxpostdate = scheduled_date_get_post_max();
txn = da_transaction_malloc();
--
++
list = g_list_first(GLOBALS->arc_list);
while (list != NULL)
{
while(mydate < maxpostdate)
{
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);
+ transaction_add(NULL, txn);
GLOBALS->changes_count++;
count++;
}
da_transaction_free (txn);
--
++
return count;
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 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)
{
//duplicate the string
- new_item->name = g_strdup(src_item->name);
+ new_item->name = g_strdup(src_item->name);
+ new_item->fullname = g_strdup(src_item->fullname);
}
return 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);
+ g_free(item->fullname);
+ rc_free(item);
}
}
da_cat_malloc(void)
{
DB( g_print("da_cat_malloc\n") );
- return g_malloc0(sizeof(Category));
+ return rc_alloc(sizeof(Category));
}
// insert our 'no category'
item = da_cat_malloc();
+ item->key = 0;
item->name = g_strdup("");
+ item->fullname = g_strdup("");
da_cat_insert(item);
}
}
+ static void
+ da_cat_max_key_ghfunc(gpointer key, Category *cat, guint32 *max_key)
+ {
+ *max_key = MAX(*max_key, cat->key);
+ }
/**
- * da_cat_remove_grfunc:
+ * da_cat_get_max_key:
*
- * GRFunc to get the max id
+ * Get the biggest key from the GHashTable
*
- * Return value: TRUE if the key/value must be deleted
+ * Return value: the biggest key value
*
*/
+ guint32
+ da_cat_get_max_key(void)
+ {
+ guint32 max_key = 0;
+
+ g_hash_table_foreach(GLOBALS->h_cat, (GHFunc)da_cat_max_key_ghfunc, &max_key);
+ return max_key;
+ }
+
+
static gboolean
da_cat_remove_grfunc(gpointer key, Category *cat, guint32 *remkey)
{
guint
da_cat_remove(guint32 key)
{
- DB( g_print("da_cat_remove %d\n", key) );
+ DB( g_print("\nda_cat_remove %d\n", key) );
return g_hash_table_foreach_remove(GLOBALS->h_cat, (GHRFunc)da_cat_remove_grfunc, &key);
}
-
+
+ static void
+ da_cat_build_fullname(Category *item)
+ {
+ Category *parent;
+
+ g_free(item->fullname);
+ if( item->parent == 0 )
+ item->fullname = g_strdup(item->name);
+ else
+ {
+ parent = da_cat_get(item->parent);
+ if( parent != NULL )
+ item->fullname = g_strconcat(parent->name, ":", item->name, NULL);
+ }
-
++
+ DB( g_print("- updated %d:'%s' fullname='%s'\n", item->key, item->name, item->fullname) );
+
+ }
+
+
+ static void
+ da_cat_rename(Category *item, gchar *newname)
+ {
+
+ DB( g_print("- renaming %s' => '%s'\n", item->name, newname) );
-
++
+ g_free(item->name);
+ item->name = g_strdup(newname);
+ da_cat_build_fullname(item);
-
++
+ if( item->parent == 0 )
+ {
+ GHashTableIter iter;
+ gpointer value;
+
+ DB( g_print("- updating subcat fullname\n") );
-
++
+ g_hash_table_iter_init (&iter, GLOBALS->h_cat);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ Category *subcat = value;
++
+ if( subcat->parent == item->key )
+ da_cat_build_fullname(subcat);
+ }
+
+ }
+ }
+
+
/**
* da_cat_insert:
*
{
guint32 *new_key;
- DB( g_print("da_cat_insert\n") );
+ DB( g_print("\nda_cat_insert\n") );
+
+ DB( g_print("- '%s'\n", item->name) );
-
+
new_key = g_new0(guint32, 1);
*new_key = item->key;
g_hash_table_insert(GLOBALS->h_cat, new_key, item);
-
+ da_cat_build_fullname(item);
++
return TRUE;
}
* Return value: TRUE if inserted
*
*/
+ // used only to add cat/subcat from ui_category with the 2 inputs
gboolean
da_cat_append(Category *cat)
{
Category *existitem;
- guint32 *new_key;
- gchar *fullname;
-
- DB( g_print("da_cat_append\n") );
-
- if( cat->name != NULL)
- {
-
- fullname = da_cat_get_fullname(cat);
- existitem = da_cat_get_by_fullname( fullname );
- g_free(fullname);
- if( existitem == NULL )
- {
- new_key = g_new0(guint32, 1);
- *new_key = da_cat_get_max_key() + 1;
- cat->key = *new_key;
-
- DB( g_print(" -> insert id: %d\n", *new_key) );
+ DB( g_print("\nda_cat_append\n") );
- g_hash_table_insert(GLOBALS->h_cat, new_key, cat);
- return TRUE;
- }
+ if( !cat->fullname )
+ da_cat_build_fullname(cat);
-
+
+ existitem = da_cat_get_by_fullname( cat->fullname );
+ if( existitem == NULL )
+ {
+ cat->key = da_cat_get_max_key() + 1;
+ da_cat_insert(cat);
+ return TRUE;
}
DB( g_print(" -> %s already exist\n", cat->name) );
-
return FALSE;
}
- /**
- * da_cat_max_key_ghfunc:
- *
- * GHFunc for biggest key
- *
- */
- static void
- da_cat_max_key_ghfunc(gpointer key, Category *cat, guint32 *max_key)
- {
-
- *max_key = MAX(*max_key, cat->key);
- }
-
- /**
- * da_cat_get_max_key:
- *
- * Get the biggest key from the GHashTable
- *
- * Return value: the biggest key value
- *
- */
- guint32
- da_cat_get_max_key(void)
- {
- guint32 max_key = 0;
- g_hash_table_foreach(GLOBALS->h_cat, (GHFunc)da_cat_max_key_ghfunc, &max_key);
- return max_key;
- }
- /**
- * da_cat_get_fullname:
- *
- * Get category the fullname 'xxxx:yyyyy'
- *
- * Return value: the category fullname (free it with g_free)
- *
- */
- gchar *
- da_cat_get_fullname(Category *cat)
+ /* fullname i.e. car:refuel */
+ struct fullcatcontext
{
- Category *parent;
-
- if( cat->parent == 0 )
- return g_strdup(cat->name);
- else
- {
- parent = da_cat_get(cat->parent);
- if( parent )
- {
- return g_strdup_printf("%s:%s", parent->name, cat->name);
- }
- }
-
- return NULL;
- }
+ guint32 parent;
+ gchar *name;
+ };
- /**
- * da_cat_name_grfunc:
- *
- * GRFunc to get the max id
- *
- * Return value: TRUE if the key/value pair match our name
- *
- */
static gboolean
- da_cat_name_grfunc(gpointer key, Category *cat, gchar *name)
+ da_cat_fullname_grfunc(gpointer key, Category *item, struct fullcatcontext *ctx)
{
- // DB( g_print("%s == %s\n", name, cat->name) );
- if( name && cat->name)
+ //DB( g_print("'%s' == '%s'\n", ctx->name, item->name) );
+ if( item->parent == ctx->parent )
{
- if(!strcasecmp(name, cat->name))
- return TRUE;
+ if( ctx->name && item->name )
+ if(!strcasecmp(ctx->name, item->name))
+ return TRUE;
}
return FALSE;
}
- /**
- * da_cat_get_key_by_name:
- *
- * Get a category key by its name
- *
- * Return value: the category key or -1 if not found
- *
- */
- guint32
- da_cat_get_key_by_name(gchar *name)
- {
- Category *cat;
-
- DB( g_print("da_cat_get_key_by_name\n") );
-
- cat = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_name_grfunc, name);
- if( cat == NULL)
- return -1;
-
- return cat->key;
- }
- /**
- * da_cat_get_by_name:
- *
- * Get a category structure by its name
- *
- * Return value: Category * or NULL if not found
- *
- */
- Category *
- da_cat_get_by_name(gchar *name)
+ static Category *da_cat_get_by_name_find_internal(guint32 parent, gchar *name)
{
- DB( g_print("da_cat_get_by_name\n") );
+ struct fullcatcontext ctx;
- return g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_name_grfunc, name);
+ ctx.parent = parent;
+ ctx.name = name;
+ DB( g_print("- searching %s %d '%s'\n", (parent == 0) ? "lv1cat" : "lv2cat", parent, name) );
+ return g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
}
- /* fullname i.e. car:refuel */
- struct fullcatcontext
+ static gchar **da_cat_get_by_fullname_split_clean(gchar *rawfullname, guint *outlen)
{
- guint parent;
- gchar *name;
- };
+ gchar **partstr = g_strsplit(rawfullname, ":", 2);
+ guint len = g_strv_length(partstr);
+ gboolean valid = TRUE;
+ DB( g_print("- spliclean '%s' - %d parts\n", rawfullname, g_strv_length(partstr)) );
- static gboolean
- da_cat_fullname_grfunc(gpointer key, Category *item, struct fullcatcontext *ctx)
- {
+ if( outlen != NULL )
+ *outlen = len;
-
+
- //DB( g_print("'%s' == '%s'\n", ctx->name, item->name) );
- if( item->parent == ctx->parent )
+ if(len >= 1)
{
- if(!strcasecmp(ctx->name, item->name))
- return TRUE;
+ g_strstrip(partstr[0]);
+ if( strlen(partstr[0]) == 0 )
+ valid = FALSE;
+
+ if(len == 2)
+ {
+ g_strstrip(partstr[1]);
+ if( strlen(partstr[1]) == 0 )
+ valid = FALSE;
+ }
}
- return FALSE;
+
+ if(valid == TRUE)
+ return partstr;
+
+ DB( g_print("- is invalid\n") );
+
+ g_strfreev(partstr);
+ return NULL;
}
+
Category *
- da_cat_get_by_fullname(gchar *fullname)
+ da_cat_get_by_fullname(gchar *rawfullname)
{
- struct fullcatcontext ctx;
- gchar **typestr;
- Category *item = NULL;
+ gchar **partstr;
+ Category *parent = NULL;
+ Category *retval = NULL;
+ guint len;
-
+
- DB( g_print("da_cat_get_by_fullname\n") );
+ DB( g_print("\nda_cat_get_by_fullname\n") );
- typestr = g_strsplit(fullname, ":", 2);
- if( g_strv_length(typestr) == 2 )
+ if( rawfullname )
{
- ctx.parent = 0;
- ctx.name = typestr[0];
- DB( g_print(" [x:x] try to find the parent : '%s'\n", typestr[0]) );
-
- Category *parent = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
- if( parent != NULL )
+ if( (partstr = da_cat_get_by_fullname_split_clean(rawfullname, &len)) != NULL )
{
- ctx.parent = parent->key;
- ctx.name = typestr[1];
+ if( len >= 1 )
+ {
+ parent = da_cat_get_by_name_find_internal(0, partstr[0]);
+ retval = parent;
+ }
-
+
- DB( g_print(" [x:x] and searching sub %d '%s'\n", ctx.parent, ctx.name) );
+ if( len == 2 && parent != NULL )
+ {
+ retval = da_cat_get_by_name_find_internal(parent->key, partstr[1]);
+ }
- item = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
+ g_strfreev(partstr);
}
}
- else
- {
- ctx.parent = 0;
- ctx.name = fullname;
-
- DB( g_print(" [x] try to '%s'\n", fullname) );
-
- item = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
- }
-
- g_strfreev(typestr);
-
+
- DB( g_print(" return value %p\n", item) );
-
- return item;
+ return retval;
}
*
*/
Category *
- da_cat_append_ifnew_by_fullname(gchar *fullname, gboolean imported)
+ da_cat_append_ifnew_by_fullname(gchar *rawfullname)
{
- struct fullcatcontext ctx;
- gchar **typestr;
- Category *newcat, *item, *retval = NULL;
- guint32 *new_key;
+ gchar **partstr;
+ Category *parent = NULL;
+ Category *newcat = NULL;
+ Category *retval = NULL;
+ guint len;
- DB( g_print("da_cat_append_ifnew_by_fullname\n") );
+ DB( g_print("\nda_cat_append_ifnew_by_fullname\n") );
- DB( g_print(" -> fullname: '%s' %d\n", fullname, strlen(fullname)) );
-
- if( strlen(fullname) > 0 )
+ if( rawfullname )
{
- typestr = g_strsplit(fullname, ":", 2);
-
- /* if we have a subcategory : aaaa:bbb */
- if( g_strv_length(typestr) == 2 )
+ if( (partstr = da_cat_get_by_fullname_split_clean(rawfullname, &len)) != NULL )
{
- ctx.parent = 0;
- ctx.name = typestr[0];
- DB( g_print(" try to find the parent:'%s'\n", typestr[0]) );
-
- Category *parent = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
- if( parent == NULL )
- {
- DB( g_print(" -> not found\n") );
-
- // append a new category
- new_key = g_new0(guint32, 1);
- *new_key = da_cat_get_max_key() + 1;
-
- newcat = da_cat_malloc();
- newcat->key = *new_key;
- newcat->name = g_strdup(typestr[0]);
- newcat->imported = imported;
-
- parent = newcat;
-
- DB( g_print(" -> insert cat '%s' id: %d\n", newcat->name, newcat->key) );
-
- g_hash_table_insert(GLOBALS->h_cat, new_key, newcat);
- }
-
- ctx.parent = parent->key;
- ctx.name = typestr[1];
- DB( g_print(" searching %d '%s'\n", ctx.parent, ctx.name) );
-
- item = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
- if( item == NULL )
+ if( len >= 1 )
{
- // append a new subcategory
- new_key = g_new0(guint32, 1);
- *new_key = da_cat_get_max_key() + 1;
-
- newcat = da_cat_malloc();
- newcat->key = *new_key;
- newcat->parent = parent->key;
- newcat->name = g_strdup(typestr[1]);
- 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) );
-
- g_hash_table_insert(GLOBALS->h_cat, new_key, newcat);
-
- retval = newcat;
+ parent = da_cat_get_by_name_find_internal(0, partstr[0]);
+ if( parent == NULL )
+ {
+ parent = da_cat_malloc();
+ parent->key = da_cat_get_max_key() + 1;
+ parent->name = g_strdup(partstr[0]);
+ da_cat_insert(parent);
+ }
+ retval = parent;
}
- else
- retval = item;
- }
- /* this a single category : aaaa */
- else
- {
- ctx.parent = 0;
- ctx.name = typestr[0];
- DB( g_print(" searching %d '%s'\n", ctx.parent, ctx.name) );
-
+
- item = g_hash_table_find(GLOBALS->h_cat, (GHRFunc)da_cat_fullname_grfunc, &ctx);
- if( item == NULL )
+ /* if we have a subcategory - xxx:xxx */
+ if( len == 2 && parent != NULL )
{
- // append a new category
- new_key = g_new0(guint32, 1);
- *new_key = da_cat_get_max_key() + 1;
-
- newcat = da_cat_malloc();
- newcat->key = *new_key;
- newcat->name = g_strdup(typestr[0]);
- newcat->imported = imported;
-
- DB( g_print(" -> insert cat '%s' id: %d\n", newcat->name, newcat->key) );
-
- g_hash_table_insert(GLOBALS->h_cat, new_key, newcat);
-
+ newcat = da_cat_get_by_name_find_internal(parent->key, partstr[1]);
+ if( newcat == NULL )
+ {
+ newcat = da_cat_malloc();
+ newcat->key = da_cat_get_max_key() + 1;
+ newcat->parent = parent->key;
+ newcat->name = g_strdup(partstr[1]);
+ newcat->flags |= GF_SUB;
+ //#1713413 take parent type into account
+ if(parent->flags & GF_INCOME)
+ newcat->flags |= GF_INCOME;
+ da_cat_insert(newcat);
+ }
retval = newcat;
}
- else
- retval = item;
-
+
+ g_strfreev(partstr);
}
-
- g_strfreev(typestr);
}
return retval;
}
-
/**
* da_cat_get:
*
}
+ gchar *da_cat_get_name(Category *item)
+ {
+ gchar *name = NULL;
+
+ if(item != NULL)
+ {
+ name = item->key == 0 ? _("(no category)") : item->fullname;
+ }
+ return name;
+ }
+
+
void da_cat_consistency(Category *item)
{
gboolean isIncome;
//check for existing parent
if( da_cat_get(item->parent) == NULL )
{
- Category *parent = da_cat_append_ifnew_by_fullname ("orphaned", FALSE);
+ Category *parent = da_cat_append_ifnew_by_fullname ("orphaned");
item->parent = parent->key;
-
+ da_cat_build_fullname(item);
g_warning("category consistency: fixed missing parent %d", item->parent);
}
}
GLOBALS->changes_count++;
}
}
-
- g_strstrip(item->name);
+
+ if( item->name != NULL )
+ g_strstrip(item->name);
+ else
+ {
+ item->name = g_strdup("void");
+ da_cat_build_fullname(item);
+ g_warning("category consistency: fixed null name");
+ GLOBALS->changes_count++;
+ }
-
++
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
guint32 category_report_id(guint32 key, gboolean subcat)
{
- Category *catentry = da_cat_get(key);
guint32 retval = 0;
- if(catentry)
+ if(subcat == FALSE)
{
- if(subcat == FALSE)
- {
+ Category *catentry = da_cat_get(key);
+ if(catentry)
retval = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
- }
- else
- {
- retval = catentry->key;
- }
}
+ else
+ {
+ retval = key;
+ }
+ //DB( g_print("- cat '%s' reportid = %d\n", catentry->name, retval) );
return retval;
}
--void
++void
category_delete_unused(void)
{
GList *lcat, *list;
--
++
lcat = list = g_hash_table_get_values(GLOBALS->h_cat);
while (list != NULL)
{
}
--static void
++static void
category_fill_usage_count(guint32 kcat)
{
Category *cat = da_cat_get (kcat);
//#1689308 count split as well
if( txn->flags & OF_SPLIT )
{
- nbsplit = da_splits_count(txn->splits);
+ nbsplit = da_splits_length(txn->splits);
for(i=0;i<nbsplit;i++)
{
- Split *split = txn->splits[i];
-
+ Split *split = da_splits_get(txn->splits, i);
-
++
category_fill_usage_count(split->kcat);
}
}
else
-- category_fill_usage_count(txn->kcat);
++ category_fill_usage_count(txn->kcat);
lnk_txn = g_list_next(lnk_txn);
}
//#1689308 count split as well
if( entry->flags & OF_SPLIT )
{
- nbsplit = da_splits_count(entry->splits);
+ nbsplit = da_splits_length(entry->splits);
for(i=0;i<nbsplit;i++)
{
- Split *split = entry->splits[i];
-
+ Split *split = da_splits_get(entry->splits, i);
-
++
category_fill_usage_count(split->kcat);
}
}
while (lnk_txn != NULL)
{
Transaction *txn = lnk_txn->data;
--
++
if(txn->kcat == key1)
{
txn->kcat = key2;
}
// move split category #1340142
- nbsplit = da_splits_count(txn->splits);
+ nbsplit = da_splits_length(txn->splits);
for(i=0;i<nbsplit;i++)
{
- Split *split = txn->splits[i];
+ Split *split = da_splits_get(txn->splits, i);
if( split->kcat == key1 )
{
lnk_txn = g_list_next(lnk_txn);
}
--
++
lnk_acc = g_list_next(lnk_acc);
}
g_list_free(lst_acc);
gchar *stripname;
gboolean retval;
- DB( g_print("(category) rename\n") );
+ DB( g_print("\n(category) rename\n") );
stripname = g_strdup(newname);
g_strstrip(stripname);
if( existitem != NULL && existitem->key != item->key)
{
- DB( g_print("error, same name already exist with other key %d <> %d\n",existitem->key, item->key) );
+ DB( g_print("- error, same name already exist with other key %d <> %d\n",existitem->key, item->key) );
retval = FALSE;
}
else
{
- DB( g_print(" -renaming\n") );
+ DB( g_print("- renaming\n") );
- g_free(item->name);
- item->name = g_strdup(stripname);
+ da_cat_rename (item, stripname);
retval = TRUE;
}
}
- static gint category_glist_name_compare_func(Category *c1, Category *c2)
+ static gint
+ category_glist_name_compare_func(Category *c1, Category *c2)
{
- gchar *name1, *name2;
gint retval = 0;
if( c1 != NULL && c2 != NULL )
{
- name1 = da_cat_get_fullname(c1);
- name2 = da_cat_get_fullname(c2);
-
- retval = hb_string_utf8_compare(name1, name2);
-
- g_free(name2);
- g_free(name1);
+ retval = hb_string_utf8_compare(c1->fullname, c2->fullname);
}
return retval;
}
- static gint category_glist_key_compare_func(Category *a, Category *b)
+ static gint
+ category_glist_key_compare_func(Category *a, Category *b)
{
gint ka, kb, retval = 0;
}
- GList *category_glist_sorted(gint column)
+ GList *
+ category_glist_sorted(gint column)
{
GList *list = g_hash_table_get_values(GLOBALS->h_cat);
const gchar *encoding;
encoding = homebank_file_getencoding(filename);
-
- DB( g_print(" -> encoding should be %s\n", encoding) );
-
+ DB( g_print(" -> encoding should be %s\n", encoding) );
retval = TRUE;
*error = NULL;
io = g_io_channel_new_file(filename, "r", NULL);
if(io != NULL)
{
-
if( encoding != NULL )
{
g_io_channel_set_encoding(io, encoding, NULL);
fullcatname = g_strdup_printf("%s:%s", lastcatname, str_array[2]);
}
- DB( g_print(" + fullcatname %s\n", fullcatname) );
-
- item = da_cat_append_ifnew_by_fullname(fullcatname, FALSE);
-
+ item = da_cat_append_ifnew_by_fullname(fullcatname);
DB( g_print(" + item %p\n", item) );
if( item != NULL)
g_strfreev (str_array);
}
}
-
}
g_free(tmpstr);
-
}
g_io_channel_unref (io);
-
-
}
g_free(lastcatname);
}
-
gboolean
category_save_csv(gchar *filename, gchar **error)
{
gchar *outstr;
GList *lcat, *list;
-
io = g_io_channel_new_file(filename, "w", NULL);
if(io != NULL)
{
g_io_channel_unref (io);
}
-
return retval;
}
- gint category_type_get(Category *item)
+
+ gint
+ category_type_get(Category *item)
{
if( (item->flags & (GF_INCOME)) )
return 1;
}
+ gchar
+ category_get_type_char(Category *item)
+ {
+ return (item->flags & GF_INCOME) ? '+' : '-';
+ }
+
- static gint category_change_type_eval(Category *item, gboolean isIncome)
-static gint
++static gint
+ category_change_type_eval(Category *item, gboolean isIncome)
{
if( (item->flags & (GF_INCOME)) && !isIncome )
return 1;
}
- gint category_change_type(Category *item, gboolean isIncome)
-gint
++gint
+ category_change_type(Category *item, gboolean isIncome)
{
gint changes = 0;
GList *lcat, *list;
changes += category_change_type_eval(item, isIncome);
--
++
item->flags &= ~(GF_INCOME); //delete flag
if(isIncome == TRUE)
item->flags |= GF_INCOME;
}
-
-
-
/**
* category_find_preset:
*
* Return value: a pathname to the file or NULL
*
*/
- gchar *category_find_preset(gchar **lang)
+ gchar *
+ category_find_preset(gchar **lang)
{
gchar **langs;
gchar *filename;
return NULL;
}
-
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "hb-payee.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
/* Debug macros */
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+ //Payee *
+ //da_pay_clone
+
+
void
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));
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- static void da_pay_max_key_ghfunc(gpointer key, Payee *item, guint32 *max_key)
- {
- *max_key = MAX(*max_key, item->key);
- }
-
- static gboolean da_pay_name_grfunc(gpointer key, Payee *item, gchar *name)
- {
- if( name && item->name )
- {
- if(!strcasecmp(name, item->name))
- return TRUE;
- }
- return FALSE;
- }
/**
* da_pay_length:
return g_hash_table_size(GLOBALS->h_pay);
}
- /*
- gboolean
- da_pay_create_none(void)
- {
- Payee *pay;
- guint32 *new_key;
-
- DB( g_print("da_pay_insert none\n") );
- pay = da_pay_malloc();
- new_key = g_new0(guint32, 1);
- *new_key = 0;
- pay->key = 0;
- pay->name = g_strdup("");
-
- DB( g_print(" -> insert id: %d\n", *new_key) );
+ static void
+ da_pay_max_key_ghfunc(gpointer key, Payee *item, guint32 *max_key)
+ {
+ *max_key = MAX(*max_key, item->key);
+ }
- g_hash_table_insert(GLOBALS->h_pay, new_key, pay);
+ /**
+ * da_pay_get_max_key:
+ *
+ * Get the biggest key from the GHashTable
+ *
+ * Return value: the biggest key value
+ *
+ */
+ guint32
+ da_pay_get_max_key(void)
+ {
+ guint32 max_key = 0;
- return TRUE;
+ g_hash_table_foreach(GLOBALS->h_pay, (GHFunc)da_pay_max_key_ghfunc, &max_key);
+ return max_key;
}
- */
/**
return g_hash_table_remove(GLOBALS->h_pay, &key);
}
+
/**
* da_pay_insert:
*
da_pay_append(Payee *item)
{
Payee *existitem;
- guint32 *new_key;
DB( g_print("da_pay_append\n") );
- /* ensure no duplicate */
- //g_strstrip(item->name);
- if( item->name != NULL )
+ existitem = da_pay_get_by_name( item->name );
+ if( existitem == NULL )
{
- existitem = da_pay_get_by_name( item->name );
- if( existitem == NULL )
- {
- new_key = g_new0(guint32, 1);
- *new_key = da_pay_get_max_key() + 1;
- item->key = *new_key;
-
- DB( g_print(" -> append id: %d\n", *new_key) );
-
- g_hash_table_insert(GLOBALS->h_pay, new_key, item);
- return TRUE;
- }
+ item->key = da_pay_get_max_key() + 1;
+ da_pay_insert(item);
+ return TRUE;
}
DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
-
return FALSE;
}
+
/**
- * da_pay_get_max_key:
+ * da_pay_append_if_new:
*
- * Get the biggest key from the GHashTable
+ * append a new payee into the GHashTable
*
- * Return value: the biggest key value
+ * Return value: existing or new payee
*
*/
- guint32
- da_pay_get_max_key(void)
+ Payee *
+ da_pay_append_if_new(gchar *rawname)
{
- guint32 max_key = 0;
+ Payee *retval = NULL;
- g_hash_table_foreach(GLOBALS->h_pay, (GHFunc)da_pay_max_key_ghfunc, &max_key);
- return max_key;
+ retval = da_pay_get_by_name(rawname);
+ if(retval == NULL)
+ {
+ retval = da_pay_malloc();
+ retval->key = da_pay_get_max_key() + 1;
+ retval->name = g_strdup(rawname);
+ g_strstrip(retval->name);
+ da_pay_insert(retval);
+ }
+
+ return retval;
}
+ static gboolean
+ da_pay_name_grfunc(gpointer key, Payee *item, gchar *name)
+ {
+ if( name && item->name )
+ {
+ if(!strcasecmp(name, item->name))
+ return TRUE;
+ }
+ return FALSE;
+ }
/**
*
*/
Payee *
- da_pay_get_by_name(gchar *name)
+ da_pay_get_by_name(gchar *rawname)
{
+ Payee *retval = NULL;
+ gchar *stripname;
+
DB( g_print("da_pay_get_by_name\n") );
- return g_hash_table_find(GLOBALS->h_pay, (GHRFunc)da_pay_name_grfunc, name);
+ if( rawname )
+ {
+ stripname = g_strdup(rawname);
+ g_strstrip(stripname);
+ if( strlen(stripname) == 0 )
+ retval = da_pay_get(0);
+ else
+ retval = g_hash_table_find(GLOBALS->h_pay, (GHRFunc)da_pay_name_grfunc, stripname);
+ g_free(stripname);
+ }
+ return retval;
}
-
/**
* da_pay_get:
*
void da_pay_consistency(Payee *item)
{
g_strstrip(item->name);
+ //5.2.4 we drop internal xfer here as it will disapear
+ if( item->paymode == PAYMODE_INTXFER )
+ item->paymode = PAYMODE_XFER;
}
{
Payee *existitem;
gchar *stripname;
+ gboolean retval = FALSE;
stripname = g_strdup(newname);
g_strstrip(stripname);
existitem = da_pay_get_by_name(stripname);
- if( existitem != NULL )
+ if( existitem != NULL && existitem->key != item->key)
{
- if( existitem->key == item->key )
- return TRUE;
+ DB( g_print("- error, same name already exist with other key %d <> %d\n",existitem->key, item->key) );
+ g_free(stripname);
}
else
{
+ DB( g_print("- renaming\n") );
g_free(item->name);
- item->name = g_strdup(stripname);
- return TRUE;
- }
-
- g_free(stripname);
-
- return FALSE;
- }
-
-
- /**
- * payee_append_if_new:
- *
- * append a new payee into the GHashTable
- *
- * Return value: true/false + new payee
- *
- */
- gboolean
- payee_append_if_new(gchar *name, Payee **newpayee)
- {
- gboolean retval = FALSE;
- gchar *stripname = g_strdup(name);
- Payee *item;
-
- g_strstrip(stripname);
- item = da_pay_get_by_name(stripname);
- if(item == NULL)
- {
- item = da_pay_malloc();
- item->name = g_strdup(stripname);
- da_pay_append(item);
+ item->name = stripname;
retval = TRUE;
}
- if( newpayee != NULL )
- *newpayee = item;
-
- g_free(stripname);
return retval;
}
+
static gint
payee_glist_name_compare_func(Payee *a, Payee *b)
{
}
- GList *payee_glist_sorted(gint column)
+ GList *
+ payee_glist_sorted(gint column)
{
GList *list = g_hash_table_get_values(GLOBALS->h_pay);
}
-
gboolean
payee_load_csv(gchar *filename, gchar **error)
{
gint nbcol;
encoding = homebank_file_getencoding(filename);
+ DB( g_print(" -> encoding should be %s\n", encoding) );
retval = TRUE;
*error = NULL;
io = g_io_channel_new_file(filename, "r", NULL);
if(io != NULL)
{
- DB( g_print(" -> encoding should be %s\n", encoding) );
if( encoding != NULL )
{
g_io_channel_set_encoding(io, encoding, NULL);
}
else
{
- gboolean added;
Payee *pay = NULL;
-
+ Category *cat = NULL;
+
if( nbcol >= 1 )
{
DB( g_print(" add pay:'%s' ?\n", str_array[0]) );
- added = payee_append_if_new(str_array[0], &pay);
- if( added )
+ pay = da_pay_append_if_new(str_array[0]);
+ DB( g_print(" pay: %p\n", pay) );
+ if( pay != NULL )
{
- DB( g_print(" added: %p\n", pay) );
GLOBALS->changes_count++;
}
}
if( nbcol == 2 )
{
- Category *cat;
-
DB( g_print(" add cat:'%s'\n", str_array[1]) );
- cat = da_cat_append_ifnew_by_fullname(str_array[1], FALSE);
+ cat = da_cat_append_ifnew_by_fullname(str_array[1]);
DB( g_print(" cat: %p %p\n", cat, pay) );
if( cat != NULL )
if( cat != NULL )
{
- fullcatname = da_cat_get_fullname (cat);
+ fullcatname = cat->fullname;
}
}
g_io_channel_unref (io);
}
-
}
-
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
g_free(PREFS->language);
+ g_free(PREFS->pnl_list_tab);
g_free(PREFS->minor_cur.symbol);
g_free(PREFS->minor_cur.decimal_char);
g_free(PREFS->minor_cur.grouping_char);
+ g_strfreev(PREFS->ext_path);
+ g_list_free_full(PREFS->ext_whitelist, g_free);
+
memset(PREFS, 0, sizeof(struct Preferences));
}
PREFS->appendscheduled = FALSE;
PREFS->do_update_currency = FALSE;
+ PREFS->bak_is_automatic = TRUE;
+ PREFS->bak_max_num_copies = 5;
+
PREFS->heritdate = FALSE;
PREFS->hidereconciled = FALSE;
PREFS->showremind = TRUE;
+ //#1673048
+ PREFS->txn_memoacp = TRUE;
+ PREFS->txn_memoacp_days = 365;
PREFS->toolbar_style = 4; //text beside icons
PREFS->custom_colors = TRUE;
PREFS->pnl_upc_col_pay_width = -1;
PREFS->pnl_upc_col_mem_width = -1;
+ i = 0;
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_DATE; //always displayed
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_MEMO;
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_AMOUNT;
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_INFO;
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_PAYEE;
+ PREFS->lst_impope_columns[i++] = LST_DSPOPE_CATEGORY;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_TAGS;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_CLR;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_STATUS; //always displayed
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_EXPENSE;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_INCOME;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_BALANCE;
+ PREFS->lst_impope_columns[i++] = -LST_DSPOPE_ACCOUNT;
i = 0;
- /* prior v4.5
- PREFS->lst_ope_columns[i++] = LST_DSPOPE_STATUS;
- 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_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_CATEGORY;
- PREFS->lst_ope_columns[i++] = LST_DSPOPE_TAGS;
- */
PREFS->lst_ope_columns[i++] = LST_DSPOPE_STATUS; //always displayed
PREFS->lst_ope_columns[i++] = LST_DSPOPE_DATE; //always displayed
PREFS->lst_ope_columns[i++] = LST_DSPOPE_INFO;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_INCOME;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_BALANCE;
PREFS->lst_ope_columns[i++] = LST_DSPOPE_MEMO;
+ PREFS->lst_ope_columns[i++] = -LST_DSPOPE_ACCOUNT;
PREFS->lst_ope_sort_id = LST_DSPOPE_DATE;
PREFS->lst_ope_sort_order = GTK_SORT_ASCENDING;
for( i=0;i<NUM_LST_DSPOPE;i++)
- PREFS->lst_ope_col_size[i] = -1;
+ PREFS->lst_ope_col_width[i] = -1;
//PREFS->base_cur.nbdecimal = 2;
//PREFS->base_cur.separator = TRUE;
- PREFS->date_range_wal = FLT_RANGE_LASTMONTH;
- PREFS->date_range_txn = FLT_RANGE_LAST12MONTHS;
+ //PREFS->date_range_wal = FLT_RANGE_LASTMONTH;
+ //PREFS->date_range_txn = FLT_RANGE_LAST12MONTHS;
+ //PREFS->date_range_rep = FLT_RANGE_THISYEAR;
+
+ //v5.2 change to let the example file show things
+ PREFS->date_range_wal = FLT_RANGE_ALLDATE;
+ PREFS->date_range_txn = FLT_RANGE_ALLDATE;
+ PREFS->date_range_rep = FLT_RANGE_ALLDATE;
PREFS->date_future_nbdays = 0;
- PREFS->date_range_rep = FLT_RANGE_THISYEAR;
//import/export
PREFS->dtex_nointro = TRUE;
+ PREFS->dtex_ucfirst = FALSE;
//PREFS->dtex_datefmt
PREFS->dtex_ofxname = 1;
PREFS->dtex_ofxmemo = 2;
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();
}
const gchar *key,
gboolean *storage)
{
+ DB( g_print(" search %s in %s\n", key, group_name) );
if( g_key_file_has_key(key_file, group_name, key, NULL) )
{
*storage = g_key_file_get_boolean(key_file, group_name, key, NULL);
+ DB( g_print(" stored boolean %d for %s at %x\n", *storage, key, *storage) );
}
}
const gchar *key,
gint *storage)
{
-
DB( g_print(" search %s in %s\n", key, group_name) );
-
if( g_key_file_has_key(key_file, group_name, key, NULL) )
{
*storage = g_key_file_get_integer(key_file, group_name, key, NULL);
-
- DB( g_print(" store integer %d for %s at %x\n", *storage, key, *storage) );
+ DB( g_print(" stored integer %d for %s at %x\n", *storage, key, *storage) );
}
}
const gchar *key,
guint32 *storage)
{
+ DB( g_print(" search %s in %s\n", key, group_name) );
if( g_key_file_has_key(key_file, group_name, key, NULL) )
{
*storage = g_key_file_get_integer(key_file, group_name, key, NULL);
+ DB( g_print(" stored guint32 %d for %s at %x\n", *storage, key, *storage) );
}
}
const gchar *key,
gshort *storage)
{
+ DB( g_print(" search %s in %s\n", key, group_name) );
if( g_key_file_has_key(key_file, group_name, key, NULL) )
{
*storage = (gshort)g_key_file_get_integer(key_file, group_name, key, NULL);
+ DB( g_print(" stored short %d for %s at %x\n", *storage, key, *storage) );
}
}
gboolean retval = FALSE;
gchar *group, *filename;
guint32 version;
+ gboolean loaded;
GError *error = NULL;
DB( g_print("\n[preferences] pref load\n") );
DB( g_print(" - filename: %s\n", filename) );
-
- if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
+ error = NULL;
+ loaded = g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error);
+ if( error )
+ {
+ g_warning("unable to load file %s: %s", filename, error->message);
+ g_error_free (error);
+ }
+
+ if( loaded == TRUE )
{
group = "General";
homebank_pref_get_boolean(keyfile, group, "AppendScheduled", &PREFS->appendscheduled);
homebank_pref_get_boolean(keyfile, group, "UpdateCurrency", &PREFS->do_update_currency);
+ homebank_pref_get_boolean(keyfile, group, "BakIsAutomatic", &PREFS->bak_is_automatic);
+ homebank_pref_get_short(keyfile, group, "BakMaxNumCopies", &PREFS->bak_max_num_copies);
+
homebank_pref_get_boolean(keyfile, group, "HeritDate", &PREFS->heritdate);
homebank_pref_get_boolean(keyfile, group, "HideReconciled", &PREFS->hidereconciled);
homebank_pref_get_boolean(keyfile, group, "ShowRemind", &PREFS->showremind);
+ homebank_pref_get_boolean(keyfile, group, "TxnMemoAcp", &PREFS->txn_memoacp);
+ homebank_pref_get_short(keyfile, group, "TxnMemoAcpDays", &PREFS->txn_memoacp_days);
+
if( g_key_file_has_key(keyfile, group, "ColumnsOpe", NULL) )
{
if(version <= 2) //retrieve old 0.1 or 0.2 visibility boolean
{
- bsrc = g_key_file_get_boolean_list(keyfile, group, "ColumnsOpe", &length, &error);
+ bsrc = g_key_file_get_boolean_list(keyfile, group, "ColumnsOpe", &length, NULL);
if( length == NUM_LST_DSPOPE-1 )
{
//and convert
}
else
{
- src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpe", &length, &error);
+ src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpe", &length, NULL);
DB( g_print(" - length %d (max=%d)\n", length, NUM_LST_DSPOPE) );
- if( length == NUM_LST_DSPOPE-1 )
+ if( length == NUM_LST_DSPOPE )
{
DB( g_print(" - copying column order from pref file\n") );
memcpy(PREFS->lst_ope_columns, src, length*sizeof(gint));
gint *src;
gsize length;
- src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpeWidth", &length, &error);
+ src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpeWidth", &length, NULL);
DB( g_print(" - length %d (max=%d)\n", length, NUM_LST_DSPOPE) );
- if( length == NUM_LST_DSPOPE-1 )
+ if( length == NUM_LST_DSPOPE )
{
DB( g_print(" - copying column width from pref file\n") );
- memcpy(PREFS->lst_ope_col_size, src, length*sizeof(gint));
+ memcpy(PREFS->lst_ope_col_width, src, length*sizeof(gint));
}
//leak
homebank_pref_get_short(keyfile, group, "UpcColPayW", &PREFS->pnl_upc_col_pay_width);
homebank_pref_get_short(keyfile, group, "UpcColMemW", &PREFS->pnl_upc_col_mem_width);
+ homebank_pref_get_string(keyfile, group, "PnlLstTab", &PREFS->pnl_list_tab);
group = "Format";
DB( g_print(" -> ** Exchange\n") );
- //homebank_pref_get_boolean(keyfile, group, "DoIntro", &PREFS->dtex_nointro);
-
+ homebank_pref_get_boolean(keyfile, group, "DoIntro", &PREFS->dtex_nointro);
+ homebank_pref_get_boolean(keyfile, group, "UcFirst", &PREFS->dtex_ucfirst);
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;
return retval;
}
+
static void homebank_pref_set_string(
GKeyFile *key_file,
const gchar *group_name,
gboolean retval = FALSE;
gchar *group, *filename;
gsize length;
+ GError *error = NULL;
DB( g_print("\n[preferences] pref save\n") );
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, "BakIsAutomatic", PREFS->bak_is_automatic);
+ g_key_file_set_integer (keyfile, group, "BakMaxNumCopies", PREFS->bak_max_num_copies);
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, "HeritDate", PREFS->heritdate);
g_key_file_set_boolean (keyfile, group, "HideReconciled", PREFS->hidereconciled);
g_key_file_set_boolean (keyfile, group, "ShowRemind", PREFS->showremind);
+ g_key_file_set_boolean (keyfile, group, "TxnMemoAcp", PREFS->txn_memoacp);
+ g_key_file_set_integer (keyfile, group, "TxnMemoAcpDays" , PREFS->txn_memoacp_days);
- g_key_file_set_integer_list(keyfile, group, "ColumnsOpe", PREFS->lst_ope_columns, NUM_LST_DSPOPE-1);
- g_key_file_set_integer_list(keyfile, group, "ColumnsOpeWidth", PREFS->lst_ope_col_size, NUM_LST_DSPOPE-1);
+ g_key_file_set_integer_list(keyfile, group, "ColumnsOpe", PREFS->lst_ope_columns, NUM_LST_DSPOPE);
+ g_key_file_set_integer_list(keyfile, group, "ColumnsOpeWidth", PREFS->lst_ope_col_width, NUM_LST_DSPOPE);
g_key_file_set_integer (keyfile, group, "OpeSortId" , PREFS->lst_ope_sort_id);
g_key_file_set_integer (keyfile, group, "OpeSortOrder" , PREFS->lst_ope_sort_order);
g_key_file_set_integer(keyfile, group, "UpcColPayW", PREFS->pnl_upc_col_pay_width);
g_key_file_set_integer(keyfile, group, "UpcColMemW", PREFS->pnl_upc_col_mem_width);
+ homebank_pref_set_string (keyfile, group, "PnlLstTab", PREFS->pnl_list_tab);
DB( g_print(" -> ** format\n") );
group = "Exchange";
- //g_key_file_set_boolean (keyfile, group, "DoIntro", PREFS->dtex_nointro);
-
+ g_key_file_set_boolean (keyfile, group, "DoIntro", PREFS->dtex_nointro);
+ g_key_file_set_boolean (keyfile, group, "UcFirst", PREFS->dtex_ucfirst);
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->);
DB( g_print(" -> filename: %s\n", filename) );
- g_file_set_contents(filename, contents, length, NULL);
-
+ g_file_set_contents(filename, contents, length, &error);
+ if( error )
+ {
+ g_warning("unable to save file %s: %s", filename, error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
DB( g_print(" -> contents: %s\n", contents) );
DB( g_print(" -> freeing filename\n") );
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-currency.h"
+
#define DEFAULT_FORMAT_DATE "%x"
#define MAX_FRAC_DIGIT 6
gboolean loadlast;
gboolean appendscheduled;
gboolean do_update_currency;
- gshort fisc_year_day;
- gshort fisc_year_month;
gint date_range_wal;
- gchar *path_hbfile;
//interface
- gchar *language;
gshort toolbar_style;
- //gboolean rules_hint;
+
+ gboolean icon_symbolic;
gshort grid_lines;
gboolean custom_colors;
gchar *color_exp;
gchar *color_inc;
gchar *color_warn;
+ //locale
+ gchar *language;
+ gchar *date_format;
+ gshort fisc_year_day;
+ gshort fisc_year_month;
+ gboolean vehicle_unit_ismile; // true if unit is mile, default Km
+ gboolean vehicle_unit_isgal; // true if unit is gallon, default Liter
+
//transactions
gint date_range_txn;
gint date_future_nbdays;
gboolean hidereconciled;
gboolean showremind;
gboolean heritdate;
- gint lst_ope_columns[NUM_LST_DSPOPE+1];
- gint lst_ope_col_size[NUM_LST_DSPOPE+1];
- gint lst_ope_sort_id; // -- implicit --
- gint lst_ope_sort_order; // -- implicit --
+ gboolean txn_memoacp;
+ gshort txn_memoacp_days;
- //display format
- gchar *date_format;
- gchar IntCurrSymbol[8];
- gboolean vehicle_unit_ismile; // true if unit is mile, default Km
- gboolean vehicle_unit_isgal; // true if unit is gallon, default Liter
-
- //data exchange options
- gboolean dtex_nointro;
+ //import/export
gint dtex_datefmt;
gint dtex_ofxname;
gint dtex_ofxmemo;
gboolean dtex_qifmemo;
gboolean dtex_qifswap;
- gchar *path_import;
- gchar *path_export;
+ gboolean dtex_ucfirst;
//report options
gint date_range_rep;
gboolean stat_byamount;
gboolean stat_showrate;
gboolean stat_showdetail;
- gboolean budg_showdetail;
+ gboolean budg_showdetail;
+
+ //backup option
+ gboolean bak_is_automatic;
+ gshort bak_max_num_copies;
+
+ //folders
+ gchar *path_hbfile;
+
+ gchar *path_import;
+ gchar *path_export;
+ gchar *path_attach;
//euro zone
gboolean euro_active;
gdouble euro_value;
Currency minor_cur;
- //chart options
- //gboolean chart_legend;
+ //---- others data -----
+ gboolean dtex_nointro;
+ gchar IntCurrSymbol[8];
+ gint lst_impope_columns[NUM_LST_DSPOPE+1];
+ gint lst_ope_columns[NUM_LST_DSPOPE+1];
+ gint lst_ope_col_width[NUM_LST_DSPOPE+1];
+ gint lst_ope_sort_id; // -- implicit --
+ gint lst_ope_sort_order; // -- implicit --
+
/* windows/dialogs size an position */
struct WinGeometry wal_wg;
struct WinGeometry acc_wg;
gshort pnl_acc_show_by;
gshort pnl_upc_col_pay_width;
gshort pnl_upc_col_mem_width;
-
+ gchar *pnl_list_tab;
//vehiclecost units (mile/gal or km/liters)
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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 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));
}
}
-
-
/**
* da_tag_get_by_name:
*
}
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+ guint
+ tags_count(guint32 *tags)
+ {
+ guint count = 0;
+
+ DB( g_print("\n[tags] count\n") );
+
+ if( tags == NULL )
+ return 0;
+
+ while(*tags++ != 0 && count < 32)
+ count++;
+
+ return count;
+ }
+
+
+ guint32 *tags_clone(guint32 *tags)
+ {
+ guint32 *newtags = NULL;
+ guint count;
+
+ count = tags_count(tags);
+ if(count > 0)
+ {
+ //1501962: we must also copy the final 0
+ newtags = g_memdup(tags, (count+1)*sizeof(guint32));
+ }
+
+ return newtags;
+ }
+
+
+ static gboolean
+ tags_key_exists(guint32 *tags, guint32 key)
+ {
+ guint count = 0;
+ while(*tags != 0 && count < 32)
+ {
+ if( *tags == key )
+ return TRUE;
+ tags++;
+ count++;
+ }
+ return FALSE;
+ }
+
+
+ guint32 *
+ tags_parse(const gchar *tagstring)
+ {
+ gchar **str_array;
+ guint32 *tags = NULL;
+ guint32 *ptags;
+ guint count, i;
+ Tag *tag;
+
+ DB( g_print("\n[tags] parse\n") );
+
+ if( tagstring )
+ {
+ str_array = g_strsplit (tagstring, " ", 0);
+ count = g_strv_length( str_array );
+ DB( g_print("- %d tags '%s'\n", count, tagstring) );
+ if( count > 0 )
+ {
+ tags = g_new0(guint32, count + 1);
+ ptags = tags;
+ for(i=0;i<count;i++)
+ {
+ //5.2.3 fixed empty tag
+ if( strlen(str_array[i]) == 0 )
+ continue;
+
+ DB( g_print("- %d search '%s'\n", i, str_array[i]) );
+ tag = da_tag_get_by_name(str_array[i]);
+ if(tag == NULL)
+ {
+ Tag *newtag = da_tag_malloc();
+
+ newtag->name = g_strdup(str_array[i]);
+ da_tag_append(newtag);
+ tag = da_tag_get_by_name(str_array[i]);
+ }
+ DB( g_print("- array add %d '%s'\n", tag->key, tag->name) );
+
+ //5.3 fixed duplicate tag in same tags
+ if( tags_key_exists(tags, tag->key) == FALSE )
+ *ptags++ = tag->key;
+ }
+ *ptags = 0;
+ }
+
+ g_strfreev (str_array);
+ }
+ return tags;
+ }
+
+
+
+ gchar *
+ tags_tostring(guint32 *tags)
+ {
+ guint count, i;
+ gchar **str_array, **tptr;
+ gchar *tagstring;
+ Tag *tag;
+ DB( g_print("\n[tags] tostring\n") );
+ if( tags == NULL )
+ {
+ return NULL;
+ }
+ else
+ {
+ count = tags_count(tags);
+ str_array = g_new0(gchar*, count+1);
+ tptr = str_array;
+ for(i=0;i<count;i++)
+ {
+ tag = da_tag_get(tags[i]);
+ if( tag )
+ {
+ *tptr++ = tag->name;
+ }
+ }
+ *tptr = NULL;
+
+ tagstring = g_strjoinv(" ", str_array);
+ g_free (str_array);
+ }
+ return tagstring;
+ }
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
#if MYDEBUG
static void
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+ gboolean
+ tag_rename(Tag *item, const gchar *newname)
+ {
+ Tag *existitem;
+ gchar *stripname;
+ gboolean retval = FALSE;
+
+ stripname = g_strdup(newname);
+ g_strstrip(stripname);
+
+ existitem = da_tag_get_by_name(stripname);
+
+ if( existitem != NULL && existitem->key != item->key)
+ {
+ DB( g_print("- error, same name already exist with other key %d <> %d\n",existitem->key, item->key) );
+ g_free(stripname);
+ }
+ else
+ {
+ DB( g_print("- renaming\n") );
+ g_free(item->name);
+ item->name = stripname;
+ retval = TRUE;
+ }
+
+ return retval;
+ }
+
static gint
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-tag.h"
#include "hb-split.h"
+#include "ext.h"
+#include "refcount.h"
+
/****************************************************************************/
- /* Debug macros */
+ /* Debug macro */
/****************************************************************************/
#define MYDEBUG 0
item->tags = NULL;
}
- da_splits_free(item->splits);
- item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
+ if(item->splits != NULL)
+ {
+ da_split_destroy(item->splits);
+ item->splits = NULL;
+ item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
+ }
if(item->same != 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));
}
- Transaction *da_transaction_copy(Transaction *src_txn, Transaction *dst_txn)
- {
- DB( g_print("da_transaction_copy\n") );
-
- da_transaction_clean (dst_txn);
-
- memmove(dst_txn, src_txn, sizeof(Transaction));
-
- //duplicate the string
- dst_txn->memo = g_strdup(src_txn->memo);
- dst_txn->info = g_strdup(src_txn->info);
-
- //duplicate tags
- transaction_tags_clone(src_txn, dst_txn);
-
- if (da_splits_clone(src_txn->splits, dst_txn->splits) > 0)
- dst_txn->flags |= OF_SPLIT; //Flag that Splits are active
-
- return dst_txn;
- }
-
-
Transaction *da_transaction_init_from_template(Transaction *txn, Archive *arc)
{
+ DB( g_print("da_transaction_init_from_template\n") );
+
//txn->date = 0;
txn->amount = arc->amount;
//#1258344 keep the current account if tpl is empty
txn->kpay = arc->kpay;
txn->kcat = arc->kcat;
txn->kxferacc = arc->kxferacc;
- txn->memo = g_strdup(arc->memo);
+ txn->memo = g_strdup(arc->memo);
txn->info = NULL;
- if( da_splits_clone(arc->splits, txn->splits) > 0)
+
+ //copy tags (with free previous here)
+ g_free(txn->tags);
+ txn->tags = tags_clone(arc->tags);
+
+ da_split_destroy (txn->splits);
+ txn->splits = da_splits_clone(arc->splits);
+ if( da_splits_length (txn->splits) > 0 )
txn->flags |= OF_SPLIT; //Flag that Splits are active
return txn;
}
+ Transaction *da_transaction_set_default_template(Transaction *txn)
+ {
+ Account *acc;
+ Archive *arc;
+
+ DB( g_print("da_transaction_set_default_template\n") );
+
+ acc = da_acc_get(txn->kacc);
+ if(acc != NULL && acc->karc > 0)
+ {
+ arc = da_archive_get(acc->karc);
+ if( arc )
+ {
+ DB( g_print(" - init with default template\n") );
+ da_transaction_init_from_template(txn, arc);
+ }
+ }
+
+ return txn;
+ }
+
+
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") );
new_item->memo = g_strdup(src_item->memo);
new_item->info = g_strdup(src_item->info);
- //duplicate tags
- transaction_tags_clone(src_item, new_item);
+ //duplicate tags/splits
+ //no g_free here to avoid free the src tags (memdup copied the ptr)
+ new_item->tags = tags_clone(src_item->tags);
- if( da_splits_clone(src_item->splits, new_item->splits) > 0)
+ new_item->splits = da_splits_clone(src_item->splits);
+ if( da_splits_length (new_item->splits) > 0 )
new_item->flags |= OF_SPLIT; //Flag that Splits are active
}
{
gboolean retval = FALSE;
- // append the memo if new
if( item->memo != NULL )
{
- if( g_hash_table_lookup(GLOBALS->h_memo, item->memo) == NULL )
+ //# 1673048 add filter on status and date obsolete
+ if( (PREFS->txn_memoacp == TRUE) && (item->date >= (GLOBALS->today - PREFS->txn_memoacp_days)) )
{
- retval = g_hash_table_insert(GLOBALS->h_memo, g_strdup(item->memo), NULL);
+ if( g_hash_table_lookup(GLOBALS->h_memo, item->memo) == NULL )
+ {
+ retval = g_hash_table_insert(GLOBALS->h_memo, g_strdup(item->memo), NULL);
+ }
}
}
return retval;
Account *acc;
Category *cat;
Payee *pay;
- gint nbsplit;
+ guint nbsplit;
DB( g_print("\n[transaction] consistency\n") );
GLOBALS->changes_count++;
}
- // check split category #1340142
- split_cat_consistency(item->splits);
-
- //# 1416624 empty category when split
- nbsplit = da_splits_count(item->splits);
- if(nbsplit > 0 && item->kcat > 0)
+ //#1340142 check split category
+ if( item->splits != NULL )
{
- g_warning("txn consistency: fixed invalid cat on split txn");
- item->kcat = 0;
- GLOBALS->changes_count++;
+ nbsplit = da_splits_consistency(item->splits);
+ //# 1416624 empty category when split
+ if(nbsplit > 0 && item->kcat > 0)
+ {
+ g_warning("txn consistency: fixed invalid cat on split txn");
+ item->kcat = 0;
+ GLOBALS->changes_count++;
+ }
}
// check payee exists
}
//#1628678 tags for internal xfer should be checked as well
-
+ //#1787826 intxfer should not have split
//#1295877 ensure income flag is correctly set
item->flags &= ~(OF_INCOME);
account_balances_add (child);
+ GValue txn_value = G_VALUE_INIT;
+ ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL);
+
}
}
}
- static GList *transaction_xfer_child_might_list_get(Transaction *ope)
+ static GList *transaction_xfer_child_might_list_get(Transaction *ope, guint32 kdstacc)
{
GList *lst_acc, *lnk_acc;
GList *list, *matchlist = NULL;
- //DB( g_print("\n[transaction] xfer_child_might_list_get\n") );
+ DB( g_print("\n[transaction] xfer_child_might_list_get\n") );
+
+ DB( g_print(" - kdstacc:%d\n", kdstacc) );
lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
lnk_acc = g_list_first(lst_acc);
{
Account *acc = lnk_acc->data;
- if( !(acc->flags & AF_CLOSED) && (acc->key != ope->kacc) )
+ if( !(acc->flags & AF_CLOSED) && (acc->key != ope->kacc) && ( (acc->key == kdstacc) || kdstacc == 0 ) )
{
list = g_queue_peek_tail_link(acc->txn_queue);
while (list != NULL)
if( transaction_xfer_child_might(ope, item, 0) == TRUE )
{
- //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->memo, item->amount, item->account, item->kxferacc) );
+ DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->memo, item->amount, item->kacc, item->kxferacc) );
matchlist = g_list_append(matchlist, item);
}
list = g_list_previous(list);
}
- void transaction_xfer_search_or_add_child(GtkWindow *parentwindow, Transaction *ope, gboolean manual)
+ void transaction_xfer_search_or_add_child(GtkWindow *parent, Transaction *ope, guint32 kdstacc)
{
GList *matchlist;
gint count;
DB( g_print("\n[transaction] xfer_search_or_add_child\n") );
- matchlist = transaction_xfer_child_might_list_get(ope);
+ matchlist = transaction_xfer_child_might_list_get(ope, kdstacc);
count = g_list_length(matchlist);
DB( g_print(" - found %d might match, switching\n", count) );
break;
//todo: maybe with just 1 match the user must choose ?
- //#942346: bad idea so to no let the user confirm, so let hil confirm
+ //#942346: bad idea so to no let the user confirm, so let him confirm
/*
case 1: //transform the transaction to a child transfer
{
default: //the user must choose himself
{
+ gint result;
Transaction *child;
- child = ui_dialog_transaction_xfer_select_child(ope, matchlist);
- if(child == NULL)
- transaction_xfer_create_child(ope);
- else
+ result = ui_dialog_transaction_xfer_select_child(parent, ope, matchlist, &child);
+ if( result == GTK_RESPONSE_ACCEPT )
+ {
transaction_xfer_change_to_child(ope, child);
+ }
+ else //GTK_RESPONSE_CANCEL
+ {
+ ope->paymode = PAYMODE_NONE;
+ ope->kxfer = 0;
+ ope->kxferacc = 0;
+ }
}
}
}
//synchronise tags since 5.1
- if(child->tags)
- g_free(child->tags);
- transaction_tags_clone (s_txn, child);
+ g_free(child->tags);
+ child->tags = tags_clone (s_txn->tags);
}
}
- Transaction *transaction_add(Transaction *ope)
+ void transaction_changed(Transaction *txn)
+ {
+ Account *acc;
+
+ if( txn == NULL )
+ return;
+
+ acc = da_acc_get(txn->kacc);
+ if(acc == NULL)
+ return;
+
+ acc->flags |= AF_CHANGED;
+ }
+
+
+ Transaction *transaction_add(GtkWindow *parent, Transaction *ope)
{
Transaction *newope;
Account *acc;
if(acc == NULL) return NULL;
// delete any splits
- da_splits_free(ope->splits);
+ da_split_destroy(ope->splits);
+ ope->splits = NULL;
ope->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
}
if(newope->paymode == PAYMODE_INTXFER)
{
- transaction_xfer_search_or_add_child(NULL, newope, FALSE);
+ transaction_xfer_search_or_add_child(parent, newope, newope->kxferacc);
}
+
+ GValue txn_value = G_VALUE_INIT;
+ ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, newope), NULL);
}
return newope;
{
if( g_strrstr(text, searchtext) != NULL )
{
- DB( g_print(" found case '%s'\n", searchtext) );
+ DB( g_print("-- found case '%s'\n", searchtext) );
match = TRUE;
}
}
if( g_strrstr(word, needle) != NULL )
{
- DB( g_print(" found nocase '%s'\n", searchtext) );
+ DB( g_print("-- found nocase '%s'\n", searchtext) );
match = TRUE;
}
g_free(word);
if(text == NULL)
return FALSE;
- DB( g_print("- match RE %s in %s\n", searchtext, text) );
+ DB( g_print("-- match RE %s in %s\n", searchtext, text) );
if( searchtext != NULL )
{
match = g_regex_match_simple(searchtext, text, ((exact == TRUE)?0:G_REGEX_CASELESS) | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY );
- if (match == TRUE) { DB( g_print(" found pattern '%s'\n", searchtext) ); }
+ if (match == TRUE) { DB( g_print("-- found pattern '%s'\n", searchtext) ); }
}
return match;
}
- static Assign *transaction_auto_assign_eval_txn(GList *l_rul, Transaction *txn)
+ static GList *transaction_auto_assign_eval_txn(GList *l_rul, Transaction *txn)
{
- Assign *rule = NULL;
+ GList *ret_list = NULL;
GList *list;
-
- DB( g_print("\n[transaction] auto_assign_eval_txn\n") );
-
- DB( g_print("- eval every rules, and return the last that match\n") );
+ gchar *text;
list = g_list_first(l_rul);
while (list != NULL)
{
Assign *rul = list->data;
- gchar *text;
text = txn->memo;
if(rul->field == 1) //payee
if( !(rul->flags & ASGF_REGEX) )
{
if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) )
- rule = rul;
+ ret_list = g_list_append(ret_list, rul);
}
else
{
if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) )
- rule = rul;
+ ret_list = g_list_append(ret_list, rul);
}
list = g_list_next(list);
}
- return rule;
+ DB( g_print("- evaluated txn '%s'=> %d match\n", text, g_list_length (ret_list)) );
+
+ return ret_list;
}
- static Assign *transaction_auto_assign_eval(GList *l_rul, gchar *text)
+ static GList *transaction_auto_assign_eval(GList *l_rul, gchar *text)
{
- Assign *rule = NULL;
+ GList *ret_list = NULL;
GList *list;
- DB( g_print("\n[transaction] auto_assign_eval\n") );
-
- DB( g_print("- eval every rules, and return the last that match\n") );
-
list = g_list_first(l_rul);
while (list != NULL)
{
if( !(rul->flags & ASGF_REGEX) )
{
if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) )
- rule = rul;
+ ret_list = g_list_append(ret_list, rul);
}
else
{
if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) )
- rule = rul;
+ ret_list = g_list_append(ret_list, rul);
}
}
list = g_list_next(list);
}
- return rule;
+ DB( g_print("- evaluated split '%s' => %d match\n", text, g_list_length (ret_list)) );
+
+ return ret_list;
}
- gint transaction_auto_assign(GList *ope_list, guint32 kacc)
+ guint transaction_auto_assign(GList *ope_list, guint32 kacc)
{
GList *l_ope;
GList *l_rul;
- gint changes = 0;
+ GList *l_match, *l_tmp;
+ guint changes = 0;
DB( g_print("\n[transaction] auto_assign\n") );
Transaction *ope = l_ope->data;
gboolean changed = FALSE;
- DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope->memo, ope->kacc, ope->kpay, ope->kcat) );
+ DB( g_print("\n- work on txn '%s' : acc=%d, pay=%d, cat=%d, %s\n", ope->memo, ope->kacc, ope->kpay, ope->kcat, (ope->flags & OF_SPLIT) ? "is_split" : "" ) );
//#1215521: added kacc == 0
if( (kacc == ope->kacc || kacc == 0) )
{
- Assign *rul;
-
- rul = transaction_auto_assign_eval_txn(l_rul, ope);
- if( rul != NULL )
+ if( !(ope->flags & OF_SPLIT) )
{
- if( (ope->kpay == 0 && (rul->flags & ASGF_DOPAY)) || (rul->flags & ASGF_OVWPAY) )
+ l_match = l_tmp = transaction_auto_assign_eval_txn(l_rul, ope);
+ while( l_tmp != NULL )
{
- if(ope->kpay != rul->kpay) { changed = TRUE; }
- ope->kpay = rul->kpay;
- }
+ Assign *rul = l_tmp->data;
+
+ if( (ope->kpay == 0 && (rul->flags & ASGF_DOPAY)) || (rul->flags & ASGF_OVWPAY) )
+ {
+ if(ope->kpay != rul->kpay) { changed = TRUE; }
+ ope->kpay = rul->kpay;
+ }
- if( !(ope->flags & OF_SPLIT) )
- {
if( (ope->kcat == 0 && (rul->flags & ASGF_DOCAT)) || (rul->flags & ASGF_OVWCAT) )
{
if(ope->kcat != rul->kcat) { changed = TRUE; }
ope->kcat = rul->kcat;
}
- }
- if( (ope->paymode == 0 && (rul->flags & ASGF_DOMOD)) || (rul->flags & ASGF_OVWMOD) )
- {
- //ugly hack - don't allow modify intxfer
- if(ope->paymode != PAYMODE_INTXFER && rul->paymode != PAYMODE_INTXFER)
+ if( (ope->paymode == 0 && (rul->flags & ASGF_DOMOD)) || (rul->flags & ASGF_OVWMOD) )
{
- if(ope->paymode != rul->paymode) { changed = TRUE; }
- ope->paymode = rul->paymode;
+ //ugly hack - don't allow modify intxfer
+ if(ope->paymode != PAYMODE_INTXFER && rul->paymode != PAYMODE_INTXFER)
+ {
+ if(ope->paymode != rul->paymode) { changed = TRUE; }
+ ope->paymode = rul->paymode;
+ }
}
+ l_tmp = g_list_next(l_tmp);
}
-
+ g_list_free(l_match);
}
-
- if( ope->flags & OF_SPLIT )
+ else
{
- guint i, nbsplit = da_splits_count(ope->splits);
-
+ guint i, nbsplit = da_splits_length(ope->splits);
+
for(i=0;i<nbsplit;i++)
{
- Split *split = ope->splits[i];
+ Split *split = da_splits_get(ope->splits, i);
DB( g_print("- eval split '%s'\n", split->memo) );
- rul = transaction_auto_assign_eval(l_rul, split->memo);
- if( rul != NULL )
+ l_match = l_tmp = transaction_auto_assign_eval(l_rul, split->memo);
+ while( l_tmp != NULL )
{
+ Assign *rul = l_tmp->data;
+
//#1501144: check if user wants to set category in rule
if( (split->kcat == 0 || (rul->flags & ASGF_OVWCAT)) && (rul->flags & ASGF_DOCAT) )
{
if(split->kcat != rul->kcat) { changed = TRUE; }
split->kcat = rul->kcat;
}
- }
+ l_tmp = g_list_next(l_tmp);
+ }
+ g_list_free(l_match);
}
}
}
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
-
- guint
- transaction_tags_count(Transaction *ope)
+ static gboolean transaction_similar_match(Transaction *stxn, Transaction *dtxn, guint32 daygap)
{
- guint count = 0;
- guint32 *ptr = ope->tags;
-
- //DB( g_print("\n[transaction] tags_count\n") );
-
- if( ope->tags == NULL )
- return 0;
+ gboolean retval = FALSE;
- while(*ptr++ != 0 && count < 32)
- count++;
+ if(stxn == dtxn)
+ return FALSE;
- return count;
+ DB( g_print(" date: %d - %d = %d\n", stxn->date, dtxn->date, stxn->date - dtxn->date) );
+
+ if( stxn->kcur == dtxn->kcur
+ && stxn->amount == dtxn->amount
+ && ( (stxn->date - dtxn->date) <= daygap )
+ //todo: at import we also check payee, but maybe too strict here
+ && (hb_string_compare(stxn->memo, dtxn->memo) == 0)
+ )
+ {
+ retval = TRUE;
+ }
+ return retval;
}
- void transaction_tags_clone(Transaction *src_txn, Transaction *dst_txn)
+ void transaction_similar_unmark(Account *acc)
{
- guint count;
+ GList *lnk_txn;
- dst_txn->tags = NULL;
- count = transaction_tags_count(src_txn);
- if(count > 0)
+ lnk_txn = g_queue_peek_tail_link(acc->txn_queue);
+ while (lnk_txn != NULL)
{
- //1501962: we must also copy the final 0
- dst_txn->tags = g_memdup(src_txn->tags, (count+1)*sizeof(guint32));
+ Transaction *stxn = lnk_txn->data;
+ stxn->marker = TXN_MARK_NONE;
+ lnk_txn = g_list_previous(lnk_txn);
}
}
- guint
- transaction_tags_parse(Transaction *ope, const gchar *tagstring)
+
+ gint transaction_similar_mark(Account *acc, guint32 daygap)
{
- gchar **str_array;
- guint count, i;
- Tag *tag;
+ GList *lnk_txn, *list2;
+ gint nball = 0;
+ gint nbdup = 0;
- DB( g_print("\n[transaction] tags_parse\n") );
+ //warning the list must be sorted by date then amount
+ //ideally (easier to parse) we shoudl get a list sorted by amount, then date
+ DB( g_print("\n[transaction] check duplicate\n") );
- DB( g_print(" - tagstring='%s'\n", tagstring) );
+ DB( g_print("\n - account:'%s' gap:%d\n", acc->name, daygap) );
- str_array = g_strsplit (tagstring, " ", 0);
- count = g_strv_length( str_array );
+ #if MYDEBUG == 1
+ GTimer *t = g_timer_new();
+ g_print(" - start parse\n");
+ #endif
- g_free(ope->tags);
- ope->tags = NULL;
- DB( g_print(" -> reset storage %p\n", ope->tags) );
+ /*
+ llast = g_list_last(old ope list);
+ DB( g_print("- end last : %f sec\n", g_timer_elapsed(t, NULL)) );
+ g_timer_reset(t);
+ ltxn = llast->data;
+ g_date_clear(&gd, 1);
+ g_date_set_julian(&gd, ltxn->date);
+ g_print(" - last julian=%u %02d-%02d-%04d\n", ltxn->date, g_date_get_day (&gd), g_date_get_month (&gd), g_date_get_year(&gd));
- if( count > 0 )
- {
+ minjulian = ltxn->date - (366*2);
+ g_date_clear(&gd, 1);
+ g_date_set_julian(&gd, minjulian);
+ g_print(" - min julian=%u %02d-%02d-%04d\n", minjulian, g_date_get_day (&gd), g_date_get_month (&gd), g_date_get_year(&gd));
+ */
+
+ transaction_similar_unmark(acc);
- ope->tags = g_new0(guint32, count + 1);
+ //mark duplicate
+ lnk_txn = g_queue_peek_tail_link(acc->txn_queue);
+ while (lnk_txn != NULL)
+ {
+ Transaction *stxn = lnk_txn->data;
- DB( g_print(" -> storage %p\n", ope->tags) );
+ //if(stxn->date < minjulian)
+ // break;
+ DB( g_print("------\n eval src: %d, '%s', '%s', %.2f\n", stxn->date, stxn->info, stxn->memo, stxn->amount) );
- for(i=0;i<count;i++)
+ list2 = g_list_previous(lnk_txn);
+ while (list2 != NULL)
{
- tag = da_tag_get_by_name(str_array[i]);
- if(tag == NULL)
- {
- Tag *newtag = da_tag_malloc();
+ Transaction *dtxn = list2->data;
- newtag->name = g_strdup(str_array[i]);
- da_tag_append(newtag);
- tag = da_tag_get_by_name(str_array[i]);
- }
+ DB( g_print(" + with dst: %d, '%s', '%s', %.2f\n", dtxn->date, dtxn->info, dtxn->memo, dtxn->amount) );
- DB( g_print(" -> storing %d=>%s at tags pos %d\n", tag->key, tag->name, i) );
+ if( (stxn->date - dtxn->date) > daygap )
+ {
+ DB( g_print(" break %d %d\n", (dtxn->date - daygap) , (stxn->date - daygap)) );
+ break;
+ }
+
+ if( dtxn->marker == TXN_MARK_NONE )
+ {
+ if( transaction_similar_match(stxn, dtxn, daygap) )
+ {
+ stxn->marker = TXN_MARK_DUPSRC;
+ dtxn->marker = TXN_MARK_DUPDST;
+ DB( g_print(" = dtxn marker=%d\n", dtxn->marker) );
+ nball++;
+ }
+ }
+ else
+ {
+ DB( g_print(" already marked %d\n", dtxn->marker) );
+ }
- ope->tags[i] = tag->key;
+
+ list2 = g_list_previous(list2);
}
- ope->tags[i] = 0;
+
+ DB( g_print(" = stxn marker=%d\n", stxn->marker) );
+ if( stxn->marker == TXN_MARK_DUPSRC )
+ nbdup++;
+
+ lnk_txn = g_list_previous(lnk_txn);
}
- //hex_dump(ope->tags, sizeof(guint32*)*count+1);
+ DB( g_print(" - end parse : %f sec\n", g_timer_elapsed(t, NULL)) );
+ DB( g_timer_destroy (t) );
- g_strfreev (str_array);
+ DB( g_print(" - found: %d/%d dup\n", nbdup, nball ) );
- return count;
+ return nbdup;
}
- gchar *
- transaction_tags_tostring(Transaction *ope)
+
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+ /* = = experimental = = */
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+
+ /*
+ probably add a structure hosted into a glist here
+ with kind of problem: duplicate, child xfer, orphan xfer
+ and collect all that with target txn
+ */
+
+
+ /*void future_transaction_test_account(Account *acc)
{
- guint count, i;
- gchar **str_array;
- gchar *tagstring;
- Tag *tag;
+ GList *lnk_txn, *list2;
+ gint nball = 0;
+ gint nbdup = 0;
+ gint nbxfer = 0;
+ GPtrArray *array;
- DB( g_print("\n[transaction] tags_tostring\n") );
+ //future
+ gint gapday = 0, i;
- DB( g_print(" -> tags at=%p\n", ope->tags) );
+ //warning the list must be sorted by date then amount
+ //ideally (easier to parse) we shoudl get a list sorted by amount, then date
- if( ope->tags == NULL )
- {
+ DB( g_print("\n[transaction] check duplicate\n") );
- return NULL;
- }
- else
- {
- count = transaction_tags_count(ope);
- DB( g_print(" -> tags at=%p, nbtags=%d\n", ope->tags, count) );
- str_array = g_new0(gchar*, count+1);
+ DB( g_print("\n - account:'%s'\n", acc->name) );
+
+ GTimer *t = g_timer_new();
+ g_print(" - start parse\n");
+
- DB( g_print(" -> str_array at %p\n", str_array) );
+ llast = g_list_last(old ope list);
+ DB( g_print("- end last : %f sec\n", g_timer_elapsed(t, NULL)) );
+ g_timer_reset(t);
- //hex_dump(ope->tags, sizeof(guint32*)*(count+1));
+ ltxn = llast->data;
+ g_date_clear(&gd, 1);
+ g_date_set_julian(&gd, ltxn->date);
+ g_print(" - last julian=%u %02d-%02d-%04d\n", ltxn->date, g_date_get_day (&gd), g_date_get_month (&gd), g_date_get_year(&gd));
- for(i=0;i<count;i++)
+ minjulian = ltxn->date - (366*2);
+ g_date_clear(&gd, 1);
+ g_date_set_julian(&gd, minjulian);
+ g_print(" - min julian=%u %02d-%02d-%04d\n", minjulian, g_date_get_day (&gd), g_date_get_month (&gd), g_date_get_year(&gd));
+
+ array = g_ptr_array_sized_new (25);
+
+ lnk_txn = g_queue_peek_tail_link(acc->txn_queue);
+ while (lnk_txn != NULL)
+ {
+ Transaction *stxn = lnk_txn->data;
+
+ //if(stxn->date < minjulian)
+ // break;
+ DB( g_print("------\n eval src: %d, '%s', '%s', %2.f\n", stxn->date, stxn->info, stxn->memo, stxn->amount) );
+
+ stxn->marker = 0;
+ list2 = g_list_previous(lnk_txn);
+ while (list2 != NULL)
{
- DB( g_print(" -> try to get tag %d\n", ope->tags[i]) );
+ Transaction *dtxn = list2->data;
+
+ stxn->marker = 0;
+ if( (dtxn->date + gapday) < (stxn->date + gapday) )
+ break;
+
+ DB( g_print(" + with dst: %d, '%s', '%s', %2.f\n", dtxn->date, dtxn->info, dtxn->memo, dtxn->amount) );
- tag = da_tag_get(ope->tags[i]);
- if( tag )
+ if( transaction_similar_match(stxn, dtxn, gapday) )
{
- DB( g_print(" -> get %s at %d\n", tag->name, i) );
- str_array[i] = tag->name;
+ g_ptr_array_add (array, stxn);
+ g_ptr_array_add (array, dtxn);
+ nbdup++;
+ DB( g_print(" + dst=1 src=1\n") );
}
- else
- str_array[i] = NULL;
-
+ nball++;
+ list2 = g_list_previous(list2);
}
- tagstring = g_strjoinv(" ", str_array);
+ lnk_txn = g_list_previous(lnk_txn);
+ }
- g_free (str_array);
+ DB( g_print(" - end parse : %f sec\n", g_timer_elapsed(t, NULL)) );
+ DB( g_timer_destroy (t) );
+ for(i=0;i<array->len;i++)
+ {
+ Transaction *txn = g_ptr_array_index(array, i);
+ txn->marker = 1;
}
- return tagstring;
+ g_ptr_array_free(array, TRUE);
+
+ DB( g_print(" - found: %d/%d dup, %d xfer\n", nbdup, nball, nbxfer ) );
+
}
+
+
+
+
+ //todo: add a limitation, no need to go through all txn
+ // 1 year in th past, or abolute number ?
+ gint future_transaction_test_notification(void)
+ {
+ GList *lst_acc, *lnk_acc;
+
+ DB( g_print("\ntransaction_test_notification\n") );
+
+ lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+ lnk_acc = g_list_first(lst_acc);
+ while (lnk_acc != NULL)
+ {
+ Account *acc = lnk_acc->data;
+
+ transaction_similar_mark(acc);
+
+ lnk_acc = g_list_next(lnk_acc);
+ }
+ g_list_free(lst_acc);
+
+ return 0;
+ }
+ */
+
+
+
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "hb-transaction.h"
#include "hb-xml.h"
+#include "ext.h"
+
#include "ui-dialogs.h"
/****************************************************************************/
}
+ static void homebank_upgrade_to_v13(void)
+ {
+ GList *tmplist;
+ guint32 newkey;
+
+ DB( g_print("\n[hb-xml] homebank_upgrade_to_v13\n") );
+
+ //#1008629 assign a key to each archive
+ newkey = 1;
+ tmplist = g_list_first(GLOBALS->arc_list);
+ while (tmplist != NULL)
+ {
+ Archive *item = tmplist->data;
+
+ item->key = newkey++;
+ tmplist = g_list_next(tmplist);
+ }
+
+ }
+
+
// lower v0.6 : we must assume categories/payee exists
// and strong link to xfer
// #632496
cat = da_cat_get(entry->kcat);
if(cat == NULL)
{
- DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) );
+ DB( g_print(" !! fixing cat for rul: %d is unknown\n", entry->kcat) );
entry->kcat = 0;
}
pay = da_pay_get(entry->kpay);
if(pay == NULL)
{
- DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) );
+ DB( g_print(" !! fixing pay for rul: %d is unknown\n", entry->kpay) );
entry->kpay = 0;
}
else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "notes" )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->notes = g_strdup(attribute_values[i]); }
+ else if(!strcmp (attribute_names[i], "tpl" )) { entry->karc = atoi(attribute_values[i]); }
}
//all attribute loaded: append
}
- static void homebank_load_xml_tag(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
+ /*static void homebank_load_xml_tag(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
{
Tag *entry = da_tag_malloc();
gint i;
//all attribute loaded: append
da_tag_insert(entry);
- }
+ }*/
static void homebank_load_xml_fav(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
{
//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); }
+ if(!strcmp (attribute_names[i], "key" )) { entry->key = atoi(attribute_values[i]); }
+ else if(!strcmp (attribute_names[i], "amount" )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
else if(!strcmp (attribute_names[i], "account" )) { entry->kacc = atoi(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
else if(!strcmp (attribute_names[i], "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->memo = g_strdup(attribute_values[i]); }
-
-
-
-
-
-
-
+ else if(!strcmp (attribute_names[i], "tags" ))
+ {
+ if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 )
+ {
+ entry->tags = tags_parse(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]); }
if(split == TRUE)
{
+ entry->splits = da_split_new ();
if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
{
entry->flags |= OF_SPLIT; //Flag that Splits are active
}
//all attribute loaded: append
- GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry);
+ //GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry);
+ da_archive_append(entry);
}
{
if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 )
{
- transaction_tags_parse(entry, attribute_values[i]);
+ entry->tags = tags_parse(attribute_values[i]);
}
}
else if(!strcmp (attribute_names[i], "kxfer" )) { entry->kxfer = atoi(attribute_values[i]); }
if(split == TRUE)
{
+ entry->splits = da_split_new ();
if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
{
entry->flags |= OF_SPLIT; //Flag that Splits are active
ParseContext *ctx = user_data;
//GtkUIManager *self = ctx->self;
- //DB( g_print("** start element: %s\n", element_name) );
+ //DB( g_print("** start element: '%s'\n", element_name) );
switch(element_name[0])
{
}
break;
+
+
+
+
+
+
+
+
+
case 'c':
{
if(!strcmp (element_name, "cat"))
}
break;
- case 't':
+ //TODO: < 5.2 misstyped here, should be tag without a s
+ //commented > 5.2 useless not loaded, but no side effect
+ /*case 't':
{
if(!strcmp (element_name, "tags"))
{
homebank_load_xml_tag(ctx, attribute_names, attribute_values);
}
}
- break;
+ 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))
{
- //g_message ("%s", error->message);
- retval = XML_IO_ERROR;
- g_error_free (error);
+ if(error)
+ {
+ g_warning("unable to load file %s: %s", filename, error->message);
+ g_error_free(error);
+ retval = XML_IO_ERROR;
+ }
}
else
{
rc = g_markup_parse_context_parse (context, buffer, length, &error);
if( error )
+ {
g_print("failed: %s\n", error->message);
+ g_error_free (error);
+ }
+
if( rc == FALSE )
{
error = NULL;
g_markup_parse_context_end_parse(context, &error);
if( error )
+ {
g_print("failed: %s\n", error->message);
+ g_error_free (error);
+ }
}
g_markup_parse_context_free (context);
{
homebank_upgrade_to_v12_7();
}
+ if( ctx.file_version < 1.3 ) // <= 5.2
+ {
+ hbfile_sanity_check();
+ homebank_upgrade_to_v13();
+ }
+ if( ctx.data_version <= 50203 )
+ {
+ hbfile_sanity_check();
+ }
// next ?
if(value != NULL && *value != 0)
{
gchar *escaped = g_markup_escape_text(value, -1);
- g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped);
+ g_string_append_printf(gstring, " %s=\"%s\"", attrname, escaped);
g_free(escaped);
}
}
length = strlen (value);
escaped = g_string_sized_new (length);
append_escaped_text (escaped, value, length);
- g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped->str);
+ g_string_append_printf(gstring, " %s=\"%s\"", attrname, escaped->str);
g_string_free (escaped, TRUE);
}
}
static void hb_xml_append_int0(GString *gstring, gchar *attrname, guint32 value)
{
- g_string_append_printf(gstring, "%s=\"%d\" ", attrname, value);
+ g_string_append_printf(gstring, " %s=\"%d\"", attrname, value);
}
static void hb_xml_append_int(GString *gstring, gchar *attrname, guint32 value)
//we must use this, as fprintf use locale decimal settings and not '.'
g_ascii_dtostr (buf, sizeof (buf), amount);
- g_string_append_printf(gstring, "%s=\"%s\" ", attrname, buf);
+ g_string_append_printf(gstring, " %s=\"%s\"", attrname, buf);
}
node = g_string_sized_new(255);
- g_string_assign(node, "<properties ");
+ g_string_assign(node, "<properties");
hb_xml_append_txt(node, "title", title);
hb_xml_append_int(node, "curr", GLOBALS->kcur);
item->flags &= ~(AF_ADDED|AF_CHANGED); //delete flag
- g_string_assign(node, "<account ");
+ g_string_assign(node, "<account");
hb_xml_append_int(node, "key", item->key);
hb_xml_append_int(node, "flags", item->flags);
hb_xml_append_int(node, "cheque1", item->cheque1);
hb_xml_append_int(node, "cheque2", item->cheque2);
hb_xml_append_txt_crlf(node, "notes", item->notes);
+ hb_xml_append_int(node, "tpl", item->karc);
+
g_string_append(node, "/>\n");
if(item->key != 0)
{
- g_string_assign(node, "<pay ");
+ g_string_assign(node, "<pay");
hb_xml_append_int(node, "key", item->key);
hb_xml_append_txt(node, "name", item->name);
if(item->key != 0)
{
- g_string_assign(node, "<cat ");
+ g_string_assign(node, "<cat");
hb_xml_append_int(node, "key", item->key);
hb_xml_append_int(node, "parent", item->parent);
{
if(item->budget[i] != 0)
{
- g_string_append_printf(node,"b%d=\"%s\" ", i, g_ascii_dtostr (buf, sizeof (buf), item->budget[i]));
+ g_string_append_printf(node," b%d=\"%s\"", i, g_ascii_dtostr (buf, sizeof (buf), item->budget[i]));
}
}
/*
** XML tag save
*/
- static gint homebank_save_xml_tag(GIOChannel *io)
+ /*static gint homebank_save_xml_tag(GIOChannel *io)
{
GList *ltag, *list;
gchar *tmpstr;
}
g_list_free(ltag);
return retval;
- }
+ }*/
/*
{
Assign *item = list->data;
- g_string_assign(node, "<asg ");
+ g_string_assign(node, "<asg");
hb_xml_append_int(node, "key" , item->key);
hb_xml_append_int(node, "flags" , item->flags);
{
GList *list;
GString *node;
+ gchar *tagstr;
gint retval = XML_OK;
GError *error = NULL;
{
Archive *item = list->data;
- g_string_assign(node, "<fav ");
+ tagstr = tags_tostring(item->tags);
+
+ g_string_assign(node, "<fav");
+ hb_xml_append_int(node, "key", item->key);
hb_xml_append_amt(node, "amount", item->amount);
hb_xml_append_int(node, "account", item->kacc);
hb_xml_append_int(node, "dst_account", item->kxferacc);
hb_xml_append_int(node, "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->memo);
+ hb_xml_append_txt(node, "wording", item->memo);
+ hb_xml_append_txt(node, "tags", tagstr);
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, "weekend", item->weekend);
hb_xml_append_int(node, "gap", item->daygap);
- if(da_splits_count(item->splits) > 0)
+ if(da_splits_length(item->splits) > 0)
{
- gchar *cats, *amounts, *memos;
+ gchar *cats, *amounts, *memos;
da_splits_tostring(item->splits, &cats, &amounts, &memos);
- g_string_append_printf(node, "scat=\"%s\" ", cats);
- g_string_append_printf(node, "samt=\"%s\" ", amounts);
+ g_string_append_printf(node, " scat=\"%s\"", cats);
+ g_string_append_printf(node, " samt=\"%s\"", amounts);
//fix #1173910
gchar *escaped = g_markup_escape_text(memos, -1);
- g_string_append_printf(node, "smem=\"%s\" ", escaped);
+ g_string_append_printf(node, " smem=\"%s\"", escaped);
g_free(escaped);
g_free(cats);
}
g_string_append(node, "/>\n");
+
+ g_free(tagstr);
error = NULL;
g_io_channel_write_chars(io, node->str, -1, NULL, &error);
Transaction *item = list->data;
item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED); //delete flag
- tagstr = transaction_tags_tostring(item);
+ tagstr = tags_tostring(item->tags);
- g_string_assign(node, "<ope ");
+ g_string_assign(node, "<ope");
hb_xml_append_int(node, "date", item->date);
hb_xml_append_amt(node, "amount", item->amount);
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_length(item->splits) > 0)
{
gchar *cats, *amounts, *memos;
da_splits_tostring(item->splits, &cats, &amounts, &memos);
- g_string_append_printf(node, "scat=\"%s\" ", cats);
- g_string_append_printf(node, "samt=\"%s\" ", amounts);
+ g_string_append_printf(node, " scat=\"%s\"", cats);
+ g_string_append_printf(node, " samt=\"%s\"", amounts);
//fix #1173910
gchar *escaped = g_markup_escape_text(memos, -1);
- g_string_append_printf(node, "smem=\"%s\" ", escaped);
+ g_string_append_printf(node, " smem=\"%s\"", escaped);
g_free(escaped);
g_free(cats);
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)
+ if(error)
{
- g_message("file error on: %s", filename);
- retval = XML_IO_ERROR;
-
- if(error)
- g_print("failed: %s\n", error->message);
-
+ g_warning("unable to save file %s: %s", filename, error->message);
g_error_free(error);
+ return(XML_IO_ERROR);
}
- else
- {
- g_io_channel_write_chars(io, "<?xml version=\"1.0\"?>\n", -1, NULL, NULL);
- outstr = g_strdup_printf("<homebank v=\"%s\" d=\"%06d\">\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION), HB_VERSION_NUM);
- g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
- g_free(outstr);
+ g_io_channel_write_chars(io, "<?xml version=\"1.0\"?>\n", -1, NULL, NULL);
- retval = homebank_save_xml_prop(io);
- retval = homebank_save_xml_cur(io);
- retval = homebank_save_xml_acc(io);
- retval = homebank_save_xml_pay(io);
- retval = homebank_save_xml_cat(io);
- retval = homebank_save_xml_tag(io);
- retval = homebank_save_xml_asg(io);
- retval = homebank_save_xml_arc(io);
- retval = homebank_save_xml_ope(io);
+ outstr = g_strdup_printf("<homebank v=\"%s\" d=\"%06d\">\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION), HB_VERSION_NUM);
+ g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
+ g_free(outstr);
- g_io_channel_write_chars(io, "</homebank>\n", -1, NULL, NULL);
+ retval = homebank_save_xml_prop(io);
+ retval = homebank_save_xml_cur(io);
+ retval = homebank_save_xml_acc(io);
+ retval = homebank_save_xml_pay(io);
+ retval = homebank_save_xml_cat(io);
+ //retval = homebank_save_xml_tag(io);
+ retval = homebank_save_xml_asg(io);
+ retval = homebank_save_xml_arc(io);
+
+ retval = homebank_save_xml_ope(io);
+
+ g_io_channel_write_chars(io, "</homebank>\n", -1, NULL, NULL);
+
+ g_io_channel_unref (io);
- g_io_channel_unref (io);
- }
return retval;
}
/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
+#include "ext.h"
- #include "dsp_mainwindow.h"
+ #include "dsp-mainwindow.h"
#include "hb-preferences.h"
#include "language.h"
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>"
gint homebank_alienfile_recognize(gchar *filename)
{
GIOChannel *io;
- gint i, retval = FILETYPE_UNKNOW;
+ gint i, retval = FILETYPE_UNKNOWN;
gchar *tmpstr;
gint io_stat;
GError *err = NULL;
for(i=0;i<25;i++)
{
- if( retval != FILETYPE_UNKNOW )
+ if( retval != FILETYPE_UNKNOWN )
break;
io_stat = g_io_channel_read_line(io, &tmpstr, NULL, NULL, &err);
if( g_file_test(filepath, G_FILE_TEST_EXISTS) )
{
+ DB( g_print(" - deleting: '%s'\n", filepath) );
g_remove(filepath);
retval = TRUE;
}
-
- DB( g_print(" - deleted: '%s' :: %d\n", filepath, retval) );
+ else
+ {
+ DB( g_print(" - cannot delete: '%s'\n", filepath) );
+ }
+
return retval;
}
void homebank_backup_current_file(void)
{
gchar *bakfilename;
+ GPtrArray *array;
+ gint i;
DB( g_print("\n[homebank] backup_current_file\n") );
//retval = g_rename(pathname, newname);
homebank_file_copy (GLOBALS->xhb_filepath, bakfilename);
g_free(bakfilename);
+
+ //do safe backup according to user preferences
+ DB( g_print(" user pref backup\n") );
+ if( PREFS->bak_is_automatic == TRUE )
+ {
+ bakfilename = hb_filename_new_for_backup(GLOBALS->xhb_filepath);
+ if( g_file_test(bakfilename, G_FILE_TEST_EXISTS) == FALSE )
+ {
+ homebank_file_copy (GLOBALS->xhb_filepath, bakfilename);
+ }
+ g_free(bakfilename);
+
+ //delete any offscale backup
+ DB( g_print(" clean old backup\n") );
+ array = hb_filename_backup_list(GLOBALS->xhb_filepath);
+
+ DB( g_print(" found %d match\n", array->len) );
+
+ gchar *dirname = g_path_get_dirname(GLOBALS->xhb_filepath);
+
+ for(i=0;i<(gint)array->len;i++)
+ {
+ gchar *offscalefilename = g_ptr_array_index(array, i);
+
+ DB( g_print(" %d : '%s'\n", i, offscalefilename) );
+ if( i >= PREFS->bak_max_num_copies )
+ {
+ gchar *bakdelfilepath = g_build_filename(dirname, offscalefilename, NULL);
+
+ DB( g_print(" - should delete '%s'\n", bakdelfilepath) );
+
+ homebank_file_delete_existing(bakdelfilepath);
+
+ g_free(bakdelfilepath);
+ }
+ }
+ g_ptr_array_free(array, TRUE);
+
+ g_free(dirname);
+ }
+
}
GKeyFile *keyfile;
gchar *group, *filename, *tmpfilename;
gchar *lastfilename = NULL;
+ GError *error = NULL;
DB( g_print("\n[homebank] lastopenedfiles load\n") );
if(keyfile)
{
filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
- if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
+ if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error))
{
group = "HomeBank";
}
}
}
+
+ if( error )
+ {
+ g_print("failed: %s\n", error->message);
+ g_error_free (error);
+ }
+
g_free(filename);
g_key_file_free (keyfile);
}
gboolean retval = FALSE;
gchar *group, *filename;
gsize length;
+ GError *error = NULL;
DB( g_print("\n[homebank] lastopenedfiles save\n") );
if( GLOBALS->xhb_filepath != NULL )
{
- keyfile = g_key_file_new();
- if(keyfile )
+ //don't save bakup files
+ if( hbfile_file_isbackup(GLOBALS->xhb_filepath) == FALSE )
{
- DB( g_print(" - saving '%s'\n", GLOBALS->xhb_filepath) );
+ keyfile = g_key_file_new();
+ if(keyfile )
+ {
+ DB( g_print(" - saving '%s'\n", GLOBALS->xhb_filepath) );
- group = "HomeBank";
- g_key_file_set_string (keyfile, group, "LastOpenedFile", GLOBALS->xhb_filepath);
+ group = "HomeBank";
+ g_key_file_set_string (keyfile, group, "LastOpenedFile", GLOBALS->xhb_filepath);
- gchar *contents = g_key_file_to_data( keyfile, &length, NULL);
+ gchar *contents = g_key_file_to_data( keyfile, &length, NULL);
- //DB( g_print(" keyfile:\n%s\nlen=%d\n", contents, length) );
+ //DB( g_print(" keyfile:\n%s\nlen=%d\n", contents, length) );
- filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
- g_file_set_contents(filename, contents, length, NULL);
- g_free(filename);
+ filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
- g_free(contents);
- g_key_file_free (keyfile);
+ g_file_set_contents(filename, contents, length, &error);
+ g_free(filename);
+
+ if( error )
+ {
+ g_print("failed: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_free(contents);
+ g_key_file_free (keyfile);
+ }
}
}
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)
{
/* update the mainwin display */
ui_mainwindow_update(mainwin, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_VISUAL));
+ ext_hook("enter_main_loop", NULL);
+
DB( g_print(" - gtk_main()\n" ) );
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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#define N_(str) gettext_noop (str)
/* = = = = = = = = = = = = = = = = */
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define HB_UNSTABLE FALSE
#define HB_UNSTABLE_SHOW FALSE
#define HB_VERSION_MAJOR 5
- #define HB_VERSION_MINOR 1
- #define HB_VERSION_MICRO 7
+ #define HB_VERSION_MINOR 2
+ #define HB_VERSION_MICRO 4
- #define HB_VERSION "5.1.7"
+ #define HB_VERSION "5.2.4"
#define HB_VERSION_NUM (HB_VERSION_MAJOR*10000) + (HB_VERSION_MINOR*100) + HB_VERSION_MICRO
- #define FILE_VERSION 1.2
- #define PREF_VERSION 517
+ #define FILE_VERSION 1.3
+ #define PREF_VERSION 524
#if HB_UNSTABLE == FALSE
#define PROGNAME "HomeBank"
#define SPACING_MEDIUM 12
#define SPACING_LARGE 18
+ #define HB_DATE_MAX_GAP 7
+ // those 2 line are duplicated into dateentry
#define HB_MINDATE 693596 //01/01/1900
#define HB_MAXDATE 803533 //31/12/2200
/* miscellaneous */
#define PHI 1.61803399
- /* official GTK_RESPONSE are negative */
- #define GTK_RESPONSE_ADD 1
- #define GTK_RESPONSE_ADDKEEP 2
+
#define HB_NUMBER_SAMPLE 1234567.89
typedef enum
{
- FILETYPE_UNKNOW,
+ FILETYPE_UNKNOWN,
FILETYPE_HOMEBANK,
FILETYPE_OFX,
FILETYPE_QIF,
/* -------- named icons (Standard Icon Name) -------- */
- #define ICONNAME_NEW "document-new"
- #define ICONNAME_OPEN "document-open"
- #define ICONNAME_SAVE "document-save"
+
+
+ //obsolete, as since since gtk3.10 : no more icons for dialogs and menu
#define ICONNAME_SAVE_AS "document-save-as" //obsolete
- #define ICONNAME_REVERT "document-revert" //obsolete
- #define ICONNAME_PRINT "document-print" //unused
+ #define ICONNAME_REVERT "document-revert" //obsolete
#define ICONNAME_PROPERTIES "document-properties" //obsolete
#define ICONNAME_CLOSE "window-close" //obsolete
#define ICONNAME_QUIT "application-exit" //obsolete
- #define ICONNAME_FIND "edit-find"
- #define ICONNAME_CLEAR "edit-clear"
- #define ICONNAME_WARNING "dialog-warning"
- #define ICONNAME_ERROR "dialog-error"
- #define ICONNAME_INFO "dialog-information"
#define ICONNAME_HELP "help-browser" //obsolete
#define ICONNAME_ABOUT "help-about" //obsolete
#define ICONNAME_PREFERENCES "preferences-system" //obsolete
- #define ICONNAME_REFRESH "view-refresh"
- #define ICONNAME_FOLDER "folder-symbolic"
- #define ICONNAME_EMBLEM_SYSTEM "emblem-system-symbolic"
+ //#define ICONNAME_FIND "edit-find" //unused
+ //#define ICONNAME_CLEAR "edit-clear" //unused
+ //#define ICONNAME_HB_SCHED_SKIP "media-skip-forward"
+ //#define ICONNAME_HB_SCHED_POST "media-playback-start"
+
+ //in 5.2 no themeable icon to keep a consistent iconset
+
+ #define ICONNAME_WARNING "dialog-warning"
+ #define ICONNAME_ERROR "dialog-error"
+ #define ICONNAME_INFO "dialog-information"
+
+ #define ICONNAME_FOLDER "folder-symbolic"
+ #define ICONNAME_EMBLEM_OK "emblem-ok-symbolic"
+ #define ICONNAME_EMBLEM_SYSTEM "emblem-system-symbolic"
+ #define ICONNAME_WINDOW_CLOSE "window-close-symbolic"
#define ICONNAME_LIST_ADD "list-add-symbolic"
#define ICONNAME_LIST_REMOVE "list-remove-symbolic"
-
+ #define ICONNAME_LIST_REMOVE_ALL "list-remove-all-symbolic"
#define ICONNAME_CHANGES_PREVENT "changes-prevent-symbolic"
+ #define ICONNAME_SYSTEM_SEARCH "system-search-symbolic"
// custom or gnome not found
#define ICONNAME_HB_BUTTON_MENU "open-menu-symbolic"
+ #define ICONNAME_HB_BUTTON_COLLAPSE "list-collapse-all-symbolic"
+ #define ICONNAME_HB_BUTTON_EXPAND "list-expand-all-symbolic"
+ #define ICONNAME_HB_BUTTON_SPLIT "edit-split-symbolic"
#define ICONNAME_HB_TOGGLE_SIGN "toggle-sign-symbolic"
/* -------- named icons (Custom to homebank) -------- */
+
+
#define ICONNAME_HB_CURRENCY "hb-currency"
#define ICONNAME_HB_ACCOUNT "hb-account"
#define ICONNAME_HB_ARCHIVE "hb-archive"
#define ICONNAME_HB_VIEW_STACK "hb-view-stack" //"view-chart-stack"
#define ICONNAME_HB_VIEW_PIE "hb-view-pie" //"view-chart-pie"
#define ICONNAME_HB_VIEW_DONUT "hb-view-donut" //"view-chart-donut"
- #define ICONNAME_HB_SHOW_LEGEND "hb-legend" //"view-legend"
- #define ICONNAME_HB_SHOW_RATE "hb-rate" // obsolete ?
- #define ICONNAME_HB_FILTER "hb-filter" //"edit-filter"
-
- #define ICONNAME_HB_FILE_IMPORT "hb-file-import" //document-import
- #define ICONNAME_HB_FILE_EXPORT "hb-file-export" //document-export
+ #define ICONNAME_HB_SHOW_LEGEND "hb-legend" //"view-legend"
+ #define ICONNAME_HB_SHOW_RATE "hb-rate" // obsolete ?
+ #define ICONNAME_HB_REFRESH "hb-view-refresh" //"view-refresh"
+ #define ICONNAME_HB_FILTER "hb-filter" //"edit-filter"
+
+ #define ICONNAME_HB_FILE_NEW "hb-document-new" //document-new
+ #define ICONNAME_HB_FILE_OPEN "hb-document-open" //document-open
+ #define ICONNAME_HB_FILE_SAVE "hb-document-save" //document-save
+ //#define ICONNAME_PRINT "document-print"
+ #define ICONNAME_HB_FILE_IMPORT "hb-file-import" //document-import
+ #define ICONNAME_HB_FILE_EXPORT "hb-file-export" //document-export
#define ICONNAME_HB_FILE_VALID "hb-file-valid"
#define ICONNAME_HB_FILE_INVALID "hb-file-invalid"
- #define ICONNAME_HB_BUTTON_COLLAPSE "btn-collapse-symbolic"
- #define ICONNAME_HB_BUTTON_EXPAND "btn-expand-symbolic"
- #define ICONNAME_HB_BUTTON_SPLIT "btn-split"
-
#define ICONNAME_HB_OPE_AUTO "hb-ope-auto" //?
#define ICONNAME_HB_OPE_BUDGET "hb-ope-budget" //?
#define ICONNAME_HB_OPE_ADD "hb-ope-add" //? "edit-add"
#define ICONNAME_HB_OPE_EDIT "hb-ope-edit" //
#define ICONNAME_HB_OPE_MULTIEDIT "hb-ope-multiedit" //
#define ICONNAME_HB_OPE_DELETE "hb-ope-delete" //? "edit-delete"
- #define ICONNAME_CONVERT "hb-ope-convert"
+ #define ICONNAME_CONVERT "hb-ope-convert" // obsolete ?
#define ICONNAME_HB_ASSIGN_RUN "hb-assign-run"
- #define ICONNAME_HB_OPE_VALID "hb-ope-valid" // obsolete ?
- #define ICONNAME_HB_OPE_CLEARED "hb-ope-cleared"
- #define ICONNAME_HB_OPE_RECONCILED "hb-ope-reconciled"
+ #define ICONNAME_HB_OPE_NEW "hb-ope-new"
+ // edit is defined above
#define ICONNAME_HB_OPE_REMIND "hb-ope-remind"
+ #define ICONNAME_HB_OPE_SIMILAR "hb-ope-similar"
+ #define ICONNAME_HB_OPE_CLEARED "hb-ope-cleared"
+ #define ICONNAME_HB_OPE_RECONCILED "hb-ope-reconciled"
+ #define ICONNAME_HB_OPE_FUTURE "hb-ope-future"
/*
gboolean hbfile_is_new;
gboolean hbfile_is_bak;
gchar *xhb_filepath;
- gboolean xhb_hasbak; //file has backup (*.xhb~) used for revert menu sensitivity
+ gboolean xhb_hasrevert; //file has backup (*.xhb~) used for revert menu sensitivity
+ guint64 xhb_timemodified;
// really global stuffs
gboolean first_run;
gboolean minor;
GtkWidget *mainwindow; //should be global to access attached window data
+ GtkWidget *alltxnwindow; //window to mutex all txn show
GtkIconTheme *icontheme;
//GdkPixbuf *lst_pixbuf[NUM_LST_PIXBUF];
//gint lst_pixbuf_maxwidth;
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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
#include "homebank.h"
#include "ui-pref.h"
- #include "dsp_mainwindow.h"
+ #include "dsp-mainwindow.h"
#include "gtk-chart-colors.h"
+#include "ext.h"
+
#include "ui-currency.h"
enum
{
- PREF_GENERAL,
- PREF_INTERFACE,
- PREF_LOCALE, //old DISPLAY
- PREF_TXN, //old COLUMNS
- PREF_IMPORT,
- PREF_REPORT,
- PREF_BACKUP,
- PREF_FOLDERS,
- PREF_EURO,
- PREF_MAX
+ EXT_COLUMN_ENABLED = 0,
+ EXT_COLUMN_LABEL,
+ EXT_COLUMN_TOOLTIP,
+ EXT_COLUMN_PLUGIN_NAME,
+ EXT_NUM_COLUMNS
};
static gchar *pref_iconname[PREF_MAX] = {
"prf-general",
"prf-interface",
+ "prf-locale",
"prf-columns",
- "prf-display",
-//"prf-display",
++//"prf-display",
"prf-import",
"prf-report",
+ "prf-backup",
+ "prf-folder",
"prf-euro", // to be renamed
+"prf-plugins",
//"prf_charts.svg"
};
static gchar *pref_name[PREF_MAX] = {
N_("General"),
N_("Interface"),
+ N_("Locale"),
N_("Transactions"),
- N_("Display format"),
N_("Import/Export"),
N_("Report"),
-N_("Euro minor")
+ N_("Backup"),
+ N_("Folders"),
+N_("Euro minor"),
+N_("Plugins")
//
};
N_("Ignore"),
N_("Memo"),
N_("Payee"),
+ N_("Info"),
NULL
};
};
+static void list_ext_colpref_get(GtkTreeView *treeview, GList **columns);
+
+
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
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" },
//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;
}
switch( type )
{
- case 1:
+ case PRF_PATH_WALLET:
path = &PREFS->path_hbfile;
entry = data->ST_path_hbfile;
title = _("Choose a default HomeBank files folder");
break;
- case 2:
+ case PRF_PATH_IMPORT:
path = &PREFS->path_import;
entry = data->ST_path_import;
title = _("Choose a default import folder");
break;
- case 3:
+ case PRF_PATH_EXPORT:
path = &PREFS->path_export;
entry = data->ST_path_export;
title = _("Choose a default export folder");
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);
sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors));
+ gtk_widget_set_sensitive(data->LB_colors , sensitive);
+ gtk_widget_set_sensitive(data->CY_colors , sensitive);
+ gtk_widget_set_sensitive(data->LB_exp_color , sensitive);
gtk_widget_set_sensitive(data->GR_colors , sensitive);
+ }
+
+
+ static void defpref_backuptoggle(GtkWidget *widget, gpointer user_data)
+ {
+ struct defpref_data *data;
+ gboolean sensitive;
+
+ DB( g_print("\n[ui-pref] backup toggle\n") );
+ data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+ sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_bak_is_automatic));
+ gtk_widget_set_sensitive(data->LB_bak_max_num_copies, sensitive);
+ gtk_widget_set_sensitive(data->NB_bak_max_num_copies, sensitive);
+ gtk_widget_set_sensitive(data->GR_bak_freq , sensitive);
}
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
gtk_widget_queue_draw (data->DA_colors);
-
+
}
// files/backup
gtk_entry_set_text(GTK_ENTRY(data->ST_path_hbfile), PREFS->path_hbfile);
-
-
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_bak_is_automatic), PREFS->bak_is_automatic);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_bak_max_num_copies), PREFS->bak_max_num_copies);
// interface
if(PREFS->language != NULL)
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);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_memoacp), PREFS->txn_memoacp);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_memoacp_days), PREFS->txn_memoacp_days);
// display format
gtk_entry_set_text(GTK_ENTRY(data->ST_datefmt), PREFS->date_format);
// import/export
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_datefmt), PREFS->dtex_datefmt);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_dtex_ucfirst), PREFS->dtex_ucfirst);
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);
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)));
-
+ ui_gtk_entry_replace_text(data->ST_path_hbfile, &PREFS->path_hbfile);
+ PREFS->bak_is_automatic = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_bak_is_automatic));
+ PREFS->bak_max_num_copies = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_bak_max_num_copies));
g_free(PREFS->language);
PREFS->language = NULL;
{
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->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);
- // 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));
+ PREFS->txn_memoacp = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_memoacp));
+ PREFS->txn_memoacp_days = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_memoacp_days));
// display format
g_free(PREFS->date_format);
// import/export
PREFS->dtex_datefmt = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_datefmt));
+ PREFS->dtex_ucfirst = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_dtex_ucfirst));
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));
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->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));
}
static GtkWidget *defpref_page_import (struct defpref_data *data)
{
- GtkWidget *content_grid, *group_grid, *hbox, *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(_("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:"));
+ label = make_label_widget(_("OFX _Name:"));
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_IMPORT_OFXNAME);
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
row++;
- label = make_label_widget(_("_Memo field:"));
+ label = make_label_widget(_("OFX _Memo:"));
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_IMPORT_OFXMEMO);
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("QIF options"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
-
+
row = 1;
- label = make_label_widget(_("Memos:"));
- gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
- widget = gtk_check_button_new_with_mnemonic (_("_Import"));
+ widget = gtk_check_button_new_with_mnemonic (_("_Import memos"));
data->CM_dtex_qifmemo = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
- widget = gtk_check_button_new_with_mnemonic (_("_Swap with payees"));
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
+ widget = gtk_check_button_new_with_mnemonic (_("_Swap memos with payees"));
data->CM_dtex_qifswap = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1);
-
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
- // group :: Files folder
+ // group :: other options
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
- label = make_label_group(_("Files folder"));
+ label = make_label_group(_("Other options"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
- label = make_label_widget(_("_Import:"));
- //----------------------------------------- l, r, t, b
- gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_hexpand (hbox, TRUE);
- gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
-
- widget = make_string(label);
- data->ST_path_import = widget;
- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
-
- //widget = gtk_button_new_with_label("...");
- widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
- data->BT_path_import = widget;
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-
- row++;
- label = make_label_widget(_("_Export:"));
- //----------------------------------------- l, r, t, b
- gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_hexpand (hbox, TRUE);
- gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
-
- widget = make_string(label);
- data->ST_path_export = widget;
- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+ widget = gtk_check_button_new_with_mnemonic (_("Sentence _case memo/payee"));
+ data->CM_dtex_ucfirst = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
-
+
- //widget = gtk_button_new_with_label("...");
- widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
- data->BT_path_export = widget;
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
return content_grid;
}
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:"));
+ label = make_label_widget(_("_Range:"));
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_daterange(label, FALSE);
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);
static GtkWidget *defpref_page_display (struct defpref_data *data)
{
- GtkWidget *content_grid, *group_grid, *label, *widget, *expander;
+ GtkWidget *content_grid, *group_grid, *label, *widget, *expander, *hbox;
gint crow, row;
content_grid = gtk_grid_new();
gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
crow = 0;
- // group :: Date options
+ // group :: General
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
- label = make_label_group(_("Date"));
+ label = make_label_group(_("User interface"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
+ label = make_label(_("_Language:"), 0, 0.5);
+ gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+ widget = ui_language_combobox_new(label);
+ data->CY_language = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+ row++;
+ row++;
+ label = make_label(_("_Date display:"), 0, 0.5);
+ gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_label(NULL, 0, 0.5);
data->LB_date = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
row++;
expander = gtk_expander_new_with_mnemonic(_("_Customize"));
- gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 1, 1);
+ gtk_grid_attach (GTK_GRID (group_grid), expander, 2, row, 1, 1);
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_container_add (GTK_CONTAINER (expander), group_grid);
- row = 1;
+ row++;
label = make_label_widget(_("_Format:"));
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = gtk_image_new_from_icon_name (ICONNAME_INFO, GTK_ICON_SIZE_BUTTON);
gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1);
-
+
gtk_widget_set_tooltip_text(widget,
_("%a locale's abbreviated weekday name.\n"
"%A locale's full weekday name. \n"
"%m month as a decimal number [01,12]. \n"
"%p locale's appropriate date representation. \n"
"%y year without century as a decimal number [00,99]. \n"
- "%Y year with century as a decimal number. \n")
+ "%Y year with century as a decimal number.")
);
row++;
gtk_label_set_markup (GTK_LABEL(widget), "<small><a href=\"http://man7.org/linux/man-pages/man3/strftime.3.html\">online reference</a></small>");
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+
+
+ // group :: Fiscal year
+ group_grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+ gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+ gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+
+ label = make_label_group(_("Fiscal year"));
+ gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+
+ row = 1;
+ //TRANSLATORS: (fiscal year) starts on
+ label = make_label_widget(_("Starts _on:"));
+ 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 = make_numeric (label, 1, 28);
+ data->NB_fiscyearday = widget;
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ widget = make_cycle (NULL, CYA_MONTHS);
+ data->CY_fiscyearmonth = widget;
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+
+
+
// group :: Measurement units
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("Measurement units"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("Transaction window"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
- label = make_label_widget(_("Date _range:"));
+ label = make_label(_("_Range:"), 0, 0.5);
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_daterange(label, FALSE);
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
row++;
- label = make_label_widget(_("_Show:"));
+ label = make_label(_("_Show future:"), 0, 0.5);
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_numeric(NULL, 0, 366);
-
+
data->ST_datefuture_nbdays = widget;
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
//TRANSLATORS: there is a spinner on the left of this label, and so you have 0....x days in advance the current date
- label = make_label(_("days in advance the current date"), 0, 0.5);
+ label = make_label(_("days ahead"), 0, 0.5);
gtk_grid_attach (GTK_GRID (group_grid), label, 3, row, 1, 1);
row++;
widget = gtk_check_button_new_with_mnemonic (_("Hide reconciled transactions"));
data->CM_hide_reconciled = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1);
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 3, 1);
row++;
widget = gtk_check_button_new_with_mnemonic (_("Always show remind transactions"));
data->CM_show_remind = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1);
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 3, 1);
// group :: Multiple add
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("Multiple add"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
data->CM_herit_date = widget;
gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
-
+ // group :: Memo autocomplete
+ 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(_("Memo autocomplete"));
+ gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+
+ row = 1;
+ widget = gtk_check_button_new_with_mnemonic (_("Active"));
+ data->CM_memoacp = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+ row++;
+ widget = make_numeric(NULL, 0, 1460);
+ data->ST_memoacp_days = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+ label = make_label(_("rolling days"), 0, 0.5);
+ gtk_grid_attach (GTK_GRID (group_grid), label, 3, row, 1, 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_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("General"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
- label = make_label_widget(_("_Language:"));
- gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
- widget = ui_language_combobox_new(label);
- data->CY_language = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
-
- row++;
- label = make_label_widget(_("_Toolbar:"));
+ label = make_label(_("_Toolbar:"), 0, 0.5);
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_TOOLBAR_STYLE);
data->CY_toolbar = widget;
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+
+
+
+
+
+
+
+
+
+
+
row++;
//widget = gtk_check_button_new_with_mnemonic (_("Enable rows in alternating colors"));
//data->CM_ruleshint = widget;
- label = make_label_widget(_("_Grid line:"));
+ label = make_label(_("_Grid line:"), 0, 0.5);
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_GRID_LINES);
data->CY_gridlines = widget;
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
label = make_label_group(_("Amount colors"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
widget = gtk_check_button_new_with_mnemonic (_("Uses custom colors"));
data->CM_custom_colors = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
-
- group_grid = gtk_grid_new ();
- data->GR_colors = group_grid;
- gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
- gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
- gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
row++;
- label = make_label_widget(_("_Preset:"));
+ label = make_label(_("_Preset:"), 0, 0.5);
+ data->LB_colors = label;
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
widget = make_cycle(label, CYA_TANGO_COLORS);
gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
row++;
- label = make_label_widget(_("_Expense:"));
+ label = make_label(_("_Expense:"), 0, 0.5);
+ data->LB_exp_color = label;
//----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+ data->GR_colors = hbox;
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);
}
- static GtkWidget *defpref_page_general (struct defpref_data *data)
+ static GtkWidget *defpref_page_filebackup (struct defpref_data *data)
{
GtkWidget *content_grid, *group_grid, *hbox, *label, *widget;
gint crow, row;
gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
crow = 0;
- // group :: Program start
+ // group :: Backup
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
- label = make_label_group(_("Program start"));
+ label = make_label_group(_("Backup"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
- widget = gtk_check_button_new_with_mnemonic (_("Show splash screen"));
- data->CM_show_splash = widget;
+ widget = gtk_check_button_new_with_mnemonic (_("_Enable automatic backups"));
+ data->CM_bak_is_automatic = widget;
gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
row++;
- widget = gtk_check_button_new_with_mnemonic (_("Load last opened file"));
- data->CM_load_last = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+ label = make_label_widget(_("_Number of backups to keep:"));
+ data->LB_bak_max_num_copies = label;
+ gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+ widget = make_numeric (label, 1, 99);
+ data->NB_bak_max_num_copies = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
row++;
- widget = gtk_check_button_new_with_mnemonic (_("Post pending scheduled transactions"));
- data->CM_append_scheduled = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+ data->GR_bak_freq = hbox;
+ //gtk_widget_set_hexpand (hbox, TRUE);
+ gtk_grid_attach (GTK_GRID (group_grid), hbox, 1, row, 2, 1);
- row++;
- widget = gtk_check_button_new_with_mnemonic (_("Update currencies online"));
- data->CM_do_update_currency = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+ widget = gtk_image_new_from_icon_name (ICONNAME_INFO, GTK_ICON_SIZE_BUTTON);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+ label = make_label_widget(_("Backup frequency is once a day"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- // group :: Fiscal year
+
+ return content_grid;
+ }
+
+
+ static GtkWidget *defpref_page_folders (struct defpref_data *data)
+ {
+ GtkWidget *content_grid, *group_grid, *hbox, *label, *widget;
+ gint crow, row;
+
+ content_grid = gtk_grid_new();
+ gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+
+ crow = 0;
+ // group :: Files folder
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
- label = make_label_group(_("Fiscal year"));
+ label = make_label_group(_("HomeBank files"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
row = 1;
- //TRANSLATORS: (fiscal year) starts on
- label = make_label_widget(_("Starts _on:"));
+ label = make_label_widget(_("_Wallets:"));
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_hexpand (hbox, TRUE);
gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
- widget = make_numeric (label, 1, 28);
- data->NB_fiscyearday = widget;
- gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
- widget = make_cycle (NULL, CYA_MONTHS);
- data->CY_fiscyearmonth = widget;
+
+ widget = make_string(label);
+ data->ST_path_hbfile = widget;
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+
+ //widget = gtk_button_new_with_label("...");
+ widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
+ data->BT_path_hbfile = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
- // group :: Main window reports
+
+ // group :: Files folder
group_grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
+
- label = make_label_group(_("Main window reports"));
+ label = make_label_group(_("Exchange files"));
gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
-
+
row = 1;
- label = make_label_widget(_("Date _range:"));
+ label = make_label_widget(_("_Import:"));
+ //----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
- widget = make_daterange(label, FALSE);
- data->CY_daterange_wal = widget;
- gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
- // group :: Files folder
- group_grid = gtk_grid_new ();
- gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
- gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
- gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_hexpand (hbox, TRUE);
+ gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
- label = make_label_group(_("Files folder"));
- gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+ widget = make_string(label);
+ data->ST_path_import = widget;
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
- row = 1;
- label = make_label_widget(_("_Default:"));
+ //widget = gtk_button_new_with_label("...");
+ widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
+ data->BT_path_import = widget;
+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
+
+ row++;
+ label = make_label_widget(_("_Export:"));
+ //----------------------------------------- l, r, t, b
gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
widget = make_string(label);
- data->ST_path_hbfile = widget;
+ data->ST_path_export = widget;
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
//widget = gtk_button_new_with_label("...");
widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
- data->BT_path_hbfile = widget;
+ data->BT_path_export = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-
+
+
+ return content_grid;
+ }
+
+
+ static GtkWidget *defpref_page_general (struct defpref_data *data)
+ {
+ GtkWidget *content_grid, *group_grid, *label, *widget;
+ gint crow, row;
+
+ content_grid = gtk_grid_new();
+ gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+
+ crow = 0;
+ // group :: Program start
+ group_grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+ gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+ gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
-
++
+ label = make_label_group(_("Program start"));
+ gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+
+ row = 1;
+ widget = gtk_check_button_new_with_mnemonic (_("Show splash screen"));
+ data->CM_show_splash = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+ row++;
+ widget = gtk_check_button_new_with_mnemonic (_("Load last opened file"));
+ data->CM_load_last = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+ row++;
+ widget = gtk_check_button_new_with_mnemonic (_("Post pending scheduled transactions"));
+ data->CM_append_scheduled = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+ row++;
+ widget = gtk_check_button_new_with_mnemonic (_("Update currencies online"));
+ data->CM_do_update_currency = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+
+ // group :: Main window reports
+ group_grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+ gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+ gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
++
+ label = make_label_group(_("Main window reports"));
+ gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+
+ row = 1;
+ label = make_label(_("_Range:"), 0, 0.5);
+ gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+ widget = make_daterange(label, FALSE);
+ data->CY_daterange_wal = widget;
+ gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 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;
/*
** add an empty new account to our temp GList and treeview
*/
- static void defpref_clear(GtkWidget *widget, gpointer user_data)
+ static void defpref_reset(GtkWidget *widget, gpointer user_data)
{
struct defpref_data *data;
gint result;
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
- DB( g_print("\n(defpref_clear) (data=%p)\n", data) );
+ DB( g_print("\n(defpref_reset) (data=%p)\n", data) );
result = ui_dialog_msg_confirm_alert(
GTK_WINDOW(data->window),
- _("Reset all preferences"),
- _("Do you really want to reset all\npreferences to default values?"),
- _("Reset")
+ _("Reset All Preferences"),
+ _("Do you really want to reset\nall preferences to default\nvalues?"),
+ _("_Reset")
);
if( result == GTK_RESPONSE_OK )
{
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;
window = gtk_dialog_new_with_buttons (_("Preferences"),
GTK_WINDOW(GLOBALS->mainwindow),
0,
+ _("_Reset"),
+ 55,
_("_Cancel"),
GTK_RESPONSE_REJECT,
_("_OK"),
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.LV_page = widget;
gtk_container_add (GTK_CONTAINER (sw), widget);
- // clear button
- 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);
#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
gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
/*
- "general",
- "interface",
- "display",
- "help",
- "euro",
- "report"
+ PREF_GENERAL,
+ PREF_INTERFACE,
+ PREF_LOCALE, //old DISPLAY
+ PREF_TXN, //old COLUMNS
+ PREF_IMPORT,
+ PREF_REPORT,
+ PREF_BACKUP,
+ PREF_FOLDERS,
+ PREF_EURO,
+ PREF_MAX
*/
//general
page = defpref_page_interface(&data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
- //columns
- page = defpref_page_transactions(&data);
+ //locale
+ page = defpref_page_display(&data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
- //display
- page = defpref_page_display(&data);
+ //transaction
+ page = defpref_page_transactions(&data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
//import
page = defpref_page_reports(&data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
+ //backup
+ page = defpref_page_filebackup(&data);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
+
+ //folders
+ page = defpref_page_folders(&data);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
+
//euro
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);
//connect all our signals
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);
+ g_signal_connect (data.CM_bak_is_automatic, "toggled", G_CALLBACK (defpref_backuptoggle), 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.BT_path_export, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(3));
+ g_signal_connect (data.BT_path_hbfile, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(PRF_PATH_WALLET));
+ g_signal_connect (data.BT_path_import, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(PRF_PATH_IMPORT));
+ g_signal_connect (data.BT_path_export, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(PRF_PATH_EXPORT));
g_signal_connect (data.CM_custom_colors, "toggled", G_CALLBACK (defpref_colortoggle), NULL);
g_signal_connect (data.CY_colors, "changed", G_CALLBACK (defpref_colorpreset), NULL);
-
+
g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_page)), "changed", G_CALLBACK (defpref_selection), notebook);
g_signal_connect (data.CM_euro_enable, "toggled", G_CALLBACK (defpref_eurotoggle), NULL);
//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;
+
+ case 55:
+ defpref_reset (window, NULL);
+ break;
}
-
+
// cleanup and destroy
//defhbfile_cleanup(&data, result);
GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
gboolean fixed;
- // get toggled iter
+ // get toggled iter
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, COLUMN_VISIBLE, &fixed, -1);
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;
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,
}
*/
+
+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-2018 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
struct defpref_data
{
+ // common
GtkWidget *window;
-
GtkWidget *LV_page;
GtkWidget *GR_page;
-
GtkWidget *label;
GtkWidget *image;
GtkWidget *BT_clear;
+ // general
+ GtkWidget *CM_show_splash;
+ GtkWidget *CM_load_last;
+ GtkWidget *CM_append_scheduled;
+ GtkWidget *CM_do_update_currency;
+ GtkWidget *ST_path_hbfile, *BT_path_hbfile;
+ GtkWidget *CM_bak_is_automatic;
+ GtkWidget *GR_bak_freq;
+ GtkWidget *LB_bak_max_num_copies, *NB_bak_max_num_copies;
+ GtkWidget *CY_daterange_wal;
+ GtkWidget *NB_fiscyearday;
+ GtkWidget *CY_fiscyearmonth;
+
+
+
GtkWidget *CY_language;
GtkWidget *CY_toolbar;
+
+
+
+
+ GtkWidget *LB_colors, *CY_colors;
+
GtkWidget *GR_colors;
- GtkWidget *CY_colors;
GtkWidget *CM_custom_colors;
- GtkWidget *CP_exp_color;
+ GtkWidget *LB_exp_color, *CP_exp_color;
GtkWidget *CP_inc_color;
GtkWidget *CP_warn_color;
//GtkWidget *CM_ruleshint;
GtkWidget *CY_gridlines;
- GtkWidget *LV_opecolumns;
+ //GtkWidget *LV_opecolumns;
GtkWidget *BT_go_up;
GtkWidget *BT_go_down;
- GtkWidget *NB_fiscyearday;
- GtkWidget *CY_fiscyearmonth;
--
++
GtkWidget *CM_runwizard;
- GtkWidget *ST_path_hbfile, *BT_path_hbfile;
GtkWidget *ST_path_import, *BT_path_import;
GtkWidget *ST_path_export, *BT_path_export;
- GtkWidget *CM_load_last;
- GtkWidget *CM_show_splash;
- GtkWidget *CM_append_scheduled;
- GtkWidget *CM_do_update_currency;
GtkWidget *CM_herit_date;
GtkWidget *CM_hide_reconciled;
GtkWidget *CM_show_remind;
+ GtkWidget *CM_memoacp;
+ GtkWidget *ST_memoacp_days;
GtkWidget *ST_datefmt;
GtkWidget *LB_date;
GtkWidget *CM_unitismile;
GtkWidget *CM_unitisgal;
- GtkWidget *CY_daterange_wal;
GtkWidget *CY_daterange_txn;
GtkWidget *ST_datefuture_nbdays;
GtkWidget *CY_daterange_rep;
--
++
/* currencies */
GtkWidget *LB_default;
-- GtkWidget *BT_default;
--
++ GtkWidget *BT_default;
++
GtkWidget *CM_euro_enable;
GtkWidget *GRP_currency;
GtkWidget *GRP_rate;
GtkWidget *GRP_format;
--
++
GtkWidget *CY_euro_preset;
GtkWidget *ST_euro_country;
GtkWidget *NB_euro_value;
GtkWidget *ST_euro_symbol;
GtkWidget *CM_euro_isprefix;
-- GtkWidget *ST_euro_decimalchar;
-- GtkWidget *ST_euro_groupingchar;
++ GtkWidget *ST_euro_decimalchar;
++ GtkWidget *ST_euro_groupingchar;
GtkWidget *NB_euro_fracdigits;
GtkWidget *LB_numbereuro;
GtkWidget *CY_dtex_ofxmemo;
GtkWidget *CM_dtex_qifmemo;
GtkWidget *CM_dtex_qifswap;
+ GtkWidget *CM_dtex_ucfirst;
gint country;
+ GtkWidget *PI_plugin_columns;
};
- PREF_TRANSACTIONS,
- PREF_DISPLAY_FORMAT,
- PREF_IMPORT_EXPORT,
+enum
+{
+ PREF_GENERAL,
+ PREF_INTERFACE,
- PREF_EURO_MINOR,
++ PREF_LOCALE, //old DISPLAY
++ PREF_TXN, //old COLUMNS
++ PREF_IMPORT,
+ PREF_REPORT,
++ PREF_BACKUP,
++ PREF_FOLDERS,
++ PREF_EURO,
+ PREF_PLUGINS,
+ PREF_MAX
+};
-typedef struct
+
- typedef struct
++typedef struct
{
gchar *locale;
gchar *name;
} EuroParams;
+ enum {
+ PRF_PATH_WALLET,
+ PRF_PATH_IMPORT,
+ PRF_PATH_EXPORT,
+ };
void free_pref_icons(void);
void load_pref_icons(void);
-GtkWidget *defpref_dialog_new (void);
+GtkWidget *defpref_dialog_new (gint initial_selection);
#endif
$(NULL)
private_icons = \
- hicolor_actions_16x16_btn-collapse.png \
- hicolor_actions_16x16_btn-expand.png \
- hicolor_status_16x16_btn-split.png \
- hicolor_status_16x16_flt-exclude.png \
- hicolor_status_16x16_flt-inactive.png \
- hicolor_status_16x16_flt-include.png \
- hicolor_actions_16x16_hb-ope-auto.png \
- hicolor_actions_16x16_hb-ope-budget.png \
- hicolor_actions_16x16_hb-ope-edit.png \
- hicolor_actions_16x16_hb-ope-cleared.png \
- hicolor_actions_16x16_hb-ope-remind.png \
- hicolor_actions_16x16_hb-ope-reconciled.png \
+ hicolor_actions_16x16_hb-ope-future.png \
+ hicolor_actions_24x24_hb-document-new.png \
+ hicolor_actions_24x24_hb-document-open.png \
+ hicolor_actions_24x24_hb-document-save.png \
+ hicolor_actions_24x24_hb-document-save-as.png \
hicolor_actions_24x24_hb-account.png \
hicolor_actions_24x24_hb-archive.png \
hicolor_actions_24x24_hb-assign.png \
hicolor_actions_24x24_hb-view-list.png \
hicolor_actions_24x24_hb-view-pie.png \
hicolor_actions_24x24_hb-view-stack.png \
+ hicolor_actions_24x24_hb-view-refresh.png \
+ hicolor_status_16x16_flt-exclude.png \
+ hicolor_status_16x16_flt-inactive.png \
+ hicolor_status_16x16_flt-include.png \
+ hicolor_status_16x16_hb-ope-new.png \
+ hicolor_status_16x16_hb-ope-similar.png \
+ hicolor_status_16x16_hb-ope-auto.png \
+ hicolor_status_16x16_hb-ope-budget.png \
+ hicolor_status_16x16_hb-ope-edit.png \
+ hicolor_status_16x16_hb-ope-cleared.png \
+ hicolor_status_16x16_hb-ope-remind.png \
+ hicolor_status_16x16_hb-ope-reconciled.png \
hicolor_status_16x16_pm-none.png \
hicolor_status_16x16_pm-ccard.png \
hicolor_status_16x16_pm-dcard.png \
hicolor_status_16x16_pm-deposit.png \
hicolor_status_16x16_pm-fifee.png \
hicolor_status_16x16_pm-directdebit.png \
+ hicolor_status_48x48_prf-backup.png \
hicolor_status_48x48_prf-columns.png \
- hicolor_status_48x48_prf-display.png \
hicolor_status_48x48_prf-euro.png \
+ hicolor_status_48x48_prf-folder.png \
hicolor_status_48x48_prf-general.png \
hicolor_status_48x48_prf-import.png \
hicolor_status_48x48_prf-interface.png \
+ hicolor_status_48x48_prf-locale.png \
hicolor_status_48x48_prf-report.png \
+ hicolor_status_48x48_prf-plugins.png \
+ hicolor_actions_scalable_edit-split-symbolic.svg \
hicolor_actions_scalable_toggle-sign-symbolic.svg \
- hicolor_actions_scalable_btn-collapse-symbolic.svg \
- hicolor_actions_scalable_btn-expand-symbolic.svg \
+ hicolor_actions_scalable_list-collapse-all-symbolic.svg \
+ hicolor_actions_scalable_list-expand-all-symbolic.svg \
$(NULL)