Files
gnucash/gnucash/import-export/aqb/gnc-plugin-aqbanking.c

717 lines
24 KiB
C

/*
* gnc-plugin-aqbanking.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-plugin-aqbanking.c
* @brief Plugin registration of the AqBanking module
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2003 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include <config.h>
#include <glib/gi18n.h>
#include "Account.h"
#include "dialog-ab-trans.h"
#include "assistant-ab-initial.h"
#include "gnc-ab-getbalance.h"
#include "gnc-ab-gettrans.h"
#include "gnc-ab-transfer.h"
#include "gnc-ab-utils.h"
#include "gnc-ab-kvp.h"
#include "gnc-gwen-gui.h"
#include "gnc-file-aqb-import.h"
#include "gnc-plugin-aqbanking.h"
#include "gnc-plugin-manager.h"
#include "gnc-plugin-page-account-tree.h"
#include "gnc-plugin-page-register.h"
#include "gnc-plugin-page-register2.h"
#include "gnc-main-window.h"
#include "gnc-prefs.h"
#include "gnc-ui-util.h" // for gnc_get_current_book
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
static void gnc_plugin_aqbanking_class_init(GncPluginAqBankingClass *klass);
static void gnc_plugin_aqbanking_init(GncPluginAqBanking *plugin);
static void gnc_plugin_aqbanking_add_to_window(GncPlugin *plugin, GncMainWindow *window, GQuark type);
static void gnc_plugin_aqbanking_remove_from_window(GncPlugin *plugin, GncMainWindow *window, GQuark type);
/* Object callbacks */
static void gnc_plugin_ab_main_window_page_added(GncMainWindow *window, GncPluginPage *page, gpointer user_data);
static void gnc_plugin_ab_main_window_page_changed(GncMainWindow *window, GncPluginPage *page, gpointer user_data);
static void gnc_plugin_ab_account_selected(GncPluginPage *plugin_page, Account *account, gpointer user_data);
/* Auxiliary functions */
static Account *main_window_to_account(GncMainWindow *window);
/* Command callbacks */
static void gnc_plugin_ab_cmd_setup(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_get_balance(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_get_transactions(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_transaction(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_sepatransaction(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_inttransaction(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_direct_debit(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_sepa_direct_debit(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_view_logwindow(GtkToggleAction *action, GncMainWindow *window);
static void gnc_plugin_ab_cmd_mt940_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_mt942_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_dtaus_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_dtaus_importsend(GtkAction *action, GncMainWindowActionData *data);
#define PLUGIN_ACTIONS_NAME "gnc-plugin-aqbanking-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-aqbanking-ui.xml"
#define MENU_TOGGLE_ACTION_AB_VIEW_LOGWINDOW "ABViewLogwindowAction"
static GtkActionEntry gnc_plugin_actions [] =
{
/* Menus */
{ "OnlineActionsAction", NULL, N_("_Online Actions"), NULL, NULL, NULL },
/* Menu Items */
{
"ABSetupAction", NULL, N_("_Online Banking Setup..."), NULL,
N_("Initial setup of Online Banking access (HBCI, or OFX DirectConnect, using AqBanking)"),
G_CALLBACK(gnc_plugin_ab_cmd_setup)
},
{
"ABGetBalanceAction", NULL, N_("Get _Balance"), NULL,
N_("Get the account balance online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_get_balance)
},
{
"ABGetTransAction", NULL, N_("Get _Transactions..."), NULL,
N_("Get the transactions online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_get_transactions)
},
{
"ABIssueTransAction", NULL, N_("_Issue Transaction..."), NULL,
N_("Issue a new transaction online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_transaction)
},
{
"ABIssueSepaTransAction", NULL, N_("_Issue SEPA Transaction..."), NULL,
N_("Issue a new international European (SEPA) transaction online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_sepatransaction)
},
{
"ABIssueIntTransAction", NULL, N_("I_nternal Transaction..."), NULL,
N_("Issue a new bank-internal transaction online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_inttransaction)
},
{
"ABIssueDirectDebitAction", NULL, N_("_Direct Debit..."), NULL,
N_("Issue a new direct debit note online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_direct_debit)
},
{
"ABIssueSepaDirectDebitAction", NULL, N_("_Issue SEPA Direct Debit..."), NULL,
N_("Issue a new international European (SEPA) direct debit note online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_sepa_direct_debit)
},
/* File -> Import menu item */
{
"Mt940ImportAction", "go-previous", N_("Import _MT940"), NULL,
N_("Import a MT940 file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_mt940_import)
},
{
"Mt942ImportAction", "go-previous", N_("Import MT94_2"), NULL,
N_("Import a MT942 file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_mt942_import)
},
{
"DtausImportAction", "go-previous", N_("Import _DTAUS"), NULL,
N_("Import a DTAUS file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_dtaus_import)
},
/* #ifdef CSV_IMPORT_FUNCTIONAL */
/* { "CsvImportAction", "go-previous", N_("Import _CSV"), NULL, */
/* N_("Import a CSV file into GnuCash"), */
/* G_CALLBACK(gnc_plugin_ab_cmd_csv_import) }, */
/* { "CsvImportSendAction", "go-previous", N_("Import CSV and s_end..."), NULL, */
/* N_("Import a CSV file into GnuCash and send the transfers online through Online Banking"), */
/* G_CALLBACK(gnc_plugin_ab_cmd_csv_importsend) }, */
/* #endif */
{
"DtausImportSendAction", "go-previous", N_("Import DTAUS and _send..."), NULL,
N_("Import a DTAUS file into GnuCash and send the transfers online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_dtaus_importsend)
},
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
static GtkToggleActionEntry gnc_plugin_toggle_actions [] =
{
{
MENU_TOGGLE_ACTION_AB_VIEW_LOGWINDOW, NULL,
N_("Show _log window"), NULL,
N_("Show the online banking log window."),
G_CALLBACK(gnc_plugin_ab_cmd_view_logwindow), TRUE
},
};
static guint gnc_plugin_n_toggle_actions = G_N_ELEMENTS(gnc_plugin_toggle_actions);
static const gchar *need_account_actions[] =
{
"ABGetBalanceAction",
"ABGetTransAction",
"ABIssueTransAction",
"ABIssueSepaTransAction",
"ABIssueIntTransAction",
"ABIssueDirectDebitAction",
"ABIssueSepaDirectDebitAction",
NULL
};
static const gchar *readonly_inactive_actions[] =
{
"OnlineActionsAction",
"ABSetupAction",
NULL
};
static GncMainWindow *gnc_main_window = NULL;
/************************************************************
* Object Implementation *
************************************************************/
G_DEFINE_TYPE(GncPluginAqBanking, gnc_plugin_aqbanking, GNC_TYPE_PLUGIN)
GncPlugin *
gnc_plugin_aqbanking_new(void)
{
return GNC_PLUGIN(g_object_new(GNC_TYPE_PLUGIN_AQBANKING, (gchar*) NULL));
}
static void
gnc_plugin_aqbanking_class_init(GncPluginAqBankingClass *klass)
{
GncPluginClass *plugin_class = GNC_PLUGIN_CLASS(klass);
/* plugin info */
plugin_class->plugin_name = GNC_PLUGIN_AQBANKING_NAME;
/* widget addition/removal */
plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
plugin_class->actions = gnc_plugin_actions;
plugin_class->n_actions = gnc_plugin_n_actions;
plugin_class->toggle_actions = gnc_plugin_toggle_actions;
plugin_class->n_toggle_actions = gnc_plugin_n_toggle_actions;
plugin_class->ui_filename = PLUGIN_UI_FILENAME;
plugin_class->add_to_window = gnc_plugin_aqbanking_add_to_window;
plugin_class->remove_from_window = gnc_plugin_aqbanking_remove_from_window;
}
static void
gnc_plugin_aqbanking_init(GncPluginAqBanking *plugin)
{
}
/**
* Called when this plugin is added to a main window. Connect a few callbacks
* here to track page changes.
*/
static void
gnc_plugin_aqbanking_add_to_window(GncPlugin *plugin, GncMainWindow *window,
GQuark type)
{
GtkAction *action;
gnc_main_window = window;
g_signal_connect(window, "page_added",
G_CALLBACK(gnc_plugin_ab_main_window_page_added),
plugin);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_ab_main_window_page_changed),
plugin);
action = gnc_main_window_find_action(window, MENU_TOGGLE_ACTION_AB_VIEW_LOGWINDOW);
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
}
static void
gnc_plugin_aqbanking_remove_from_window(GncPlugin *plugin, GncMainWindow *window,
GQuark type)
{
g_signal_handlers_disconnect_by_func(
window, G_CALLBACK(gnc_plugin_ab_main_window_page_changed), plugin);
g_signal_handlers_disconnect_by_func(
window, G_CALLBACK(gnc_plugin_ab_main_window_page_added), plugin);
}
/************************************************************
* Object Callbacks *
************************************************************/
/**
* A new page has been added to a main window. Connect a signal to it so that
* we can track when accounts are selected.
*/
static void
gnc_plugin_ab_main_window_page_added(GncMainWindow *window, GncPluginPage *page,
gpointer user_data)
{
const gchar *page_name;
ENTER("main window %p, page %p", window, page);
if (!GNC_IS_PLUGIN_PAGE(page))
{
LEAVE("no plugin_page");
return;
}
page_name = gnc_plugin_page_get_plugin_name(page);
if (!page_name)
{
LEAVE("no page_name of plugin_page");
return;
}
if (strcmp(page_name, GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME) == 0)
{
DEBUG("account tree page, adding signal");
g_signal_connect(page, "account_selected",
G_CALLBACK(gnc_plugin_ab_account_selected), NULL);
}
gnc_plugin_ab_main_window_page_changed(window, page, user_data);
LEAVE(" ");
}
/** Update the actions sensitivity
*/
static void update_inactive_actions(GncPluginPage *plugin_page)
{
GncMainWindow *window;
GtkActionGroup *action_group;
// We are readonly - so we have to switch particular actions to inactive.
gboolean is_readwrite = !qof_book_is_readonly(gnc_get_current_book());
// We continue only if the current page is a plugin page
if (!plugin_page || !GNC_IS_PLUGIN_PAGE(plugin_page))
return;
window = GNC_MAIN_WINDOW(plugin_page->window);
g_return_if_fail(GNC_IS_MAIN_WINDOW(window));
action_group = gnc_main_window_get_action_group(window, PLUGIN_ACTIONS_NAME);
g_return_if_fail(GTK_IS_ACTION_GROUP(action_group));
/* Set the action's sensitivity */
gnc_plugin_update_actions (action_group, readonly_inactive_actions,
"sensitive", is_readwrite);
}
/**
* Whenever the current page has changed, update the aqbanking menus based upon
* the page that is currently selected.
*/
static void
gnc_plugin_ab_main_window_page_changed(GncMainWindow *window,
GncPluginPage *page, gpointer user_data)
{
Account *account = main_window_to_account(window);
/* Make sure not to call this with a NULL GncPluginPage */
if (page)
{
// Update the menu items according to the selected account
gnc_plugin_ab_account_selected(page, account, user_data);
// Also update the action sensitivity due to read-only
update_inactive_actions(page);
}
}
/**
* An account had been (de)selected either in an "account tree" page or by
* selecting another register page. Update the aqbanking menus appropriately.
*/
static void
gnc_plugin_ab_account_selected(GncPluginPage *plugin_page, Account *account,
gpointer user_data)
{
GncMainWindow *window;
GtkActionGroup *action_group;
const gchar *bankcode = NULL;
const gchar *accountid = NULL;
g_return_if_fail(GNC_IS_PLUGIN_PAGE(plugin_page));
window = GNC_MAIN_WINDOW(plugin_page->window);
g_return_if_fail(GNC_IS_MAIN_WINDOW(window));
action_group = gnc_main_window_get_action_group(window, PLUGIN_ACTIONS_NAME);
g_return_if_fail(GTK_IS_ACTION_GROUP(action_group));
if (account)
{
bankcode = gnc_ab_get_account_bankcode(account);
accountid = gnc_ab_get_account_accountid(account);
gnc_plugin_update_actions(action_group, need_account_actions,
"sensitive",
(account && bankcode && *bankcode
&& accountid && *accountid));
gnc_plugin_update_actions(action_group, need_account_actions,
"visible", TRUE);
}
else
{
gnc_plugin_update_actions(action_group, need_account_actions,
"sensitive", FALSE);
gnc_plugin_update_actions(action_group, need_account_actions,
"visible", FALSE);
}
}
/************************************************************
* Auxiliary Functions *
************************************************************/
/**
* Given a pointer to a main window, try and extract an Account from it. If the
* current page is an "account tree" page, get the account corresponding to the
* selected account. (What if multiple accounts are selected?) If the current
* page is a "register" page, get the head account for the register. (Returns
* NULL for a general journal or search register.)
*
* @param window A pointer to a GncMainWindow object.
* @return A pointer to an account, if one can be determined from the current
* page. NULL otherwise.
*/
static Account *
main_window_to_account(GncMainWindow *window)
{
GncPluginPage *page;
const gchar *page_name;
Account *account = NULL;
const gchar *account_name;
ENTER("main window %p", window);
if (!GNC_IS_MAIN_WINDOW(window))
{
LEAVE("no main_window");
return NULL;
}
page = gnc_main_window_get_current_page(window);
if (!GNC_IS_PLUGIN_PAGE(page))
{
LEAVE("no plugin_page");
return NULL;
}
page_name = gnc_plugin_page_get_plugin_name(page);
if (!page_name)
{
LEAVE("no page_name of plugin_page");
return NULL;
}
if (strcmp(page_name, GNC_PLUGIN_PAGE_REGISTER_NAME) == 0)
{
DEBUG("register page");
account = gnc_plugin_page_register_get_account(
GNC_PLUGIN_PAGE_REGISTER(page));
}
else if (strcmp(page_name, GNC_PLUGIN_PAGE_REGISTER2_NAME) == 0)
{
DEBUG("register2 page");
account = gnc_plugin_page_register2_get_account(
GNC_PLUGIN_PAGE_REGISTER2(page));
}
else if (strcmp(page_name, GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME) == 0)
{
DEBUG("account tree page");
account = gnc_plugin_page_account_tree_get_current_account(
GNC_PLUGIN_PAGE_ACCOUNT_TREE(page));
}
else
{
account = NULL;
}
account_name = account ? xaccAccountGetName(account) : NULL;
LEAVE("account %s(%p)", account_name ? account_name : "(null)", account);
return account;
}
void
gnc_plugin_aqbanking_set_logwindow_visible(gboolean logwindow_visible)
{
GtkAction *action;
action = gnc_main_window_find_action(gnc_main_window,
MENU_TOGGLE_ACTION_AB_VIEW_LOGWINDOW);
if (action)
{
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
logwindow_visible);
}
}
/************************************************************
* Command Callbacks *
************************************************************/
static void
gnc_plugin_ab_cmd_setup(GtkAction *action, GncMainWindowActionData *data)
{
ENTER("action %p, main window data %p", action, data);
gnc_main_window = data->window;
gnc_ab_initial_assistant();
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_get_balance(GtkAction *action, GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_getbalance(GTK_WIDGET(data->window), account);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_get_transactions(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_gettrans(GTK_WIDGET(data->window), account);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_transaction(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SINGLE_TRANSFER);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_sepatransaction(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SEPA_TRANSFER);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_inttransaction(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_maketrans(GTK_WIDGET(data->window), account,
SINGLE_INTERNAL_TRANSFER);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_direct_debit(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SINGLE_DEBITNOTE);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_sepa_direct_debit(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL)
{
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_main_window = data->window;
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SEPA_DEBITNOTE);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_view_logwindow(GtkToggleAction *action, GncMainWindow *window)
{
if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
{
if (!gnc_GWEN_Gui_show_dialog())
{
/* Log window could not be made visible */
gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
}
}
else
{
gnc_GWEN_Gui_hide_dialog();
}
}
static void
gnc_plugin_ab_cmd_mt940_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_prefs_get_string(GNC_PREFS_GROUP_AQBANKING,
GNC_PREF_FORMAT_SWIFT940);
gnc_main_window = data->window;
gnc_file_aqbanking_import (GTK_WINDOW (gnc_main_window),
"swift", format ? format : "swift-mt940", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_mt942_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_prefs_get_string(GNC_PREFS_GROUP_AQBANKING,
GNC_PREF_FORMAT_SWIFT942);
gnc_main_window = data->window;
gnc_file_aqbanking_import (GTK_WINDOW (gnc_main_window),
"swift", format ? format : "swift-mt942", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_dtaus_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_prefs_get_string(GNC_PREFS_GROUP_AQBANKING,
GNC_PREF_FORMAT_DTAUS);
gnc_main_window = data->window;
gnc_file_aqbanking_import (GTK_WINDOW (gnc_main_window),
"dtaus", format ? format : "default", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_dtaus_importsend(GtkAction *action,
GncMainWindowActionData *data)
{
gchar *format = gnc_prefs_get_string(GNC_PREFS_GROUP_AQBANKING,
GNC_PREF_FORMAT_DTAUS);
gnc_main_window = data->window;
gnc_file_aqbanking_import (GTK_WINDOW (gnc_main_window),
"dtaus", format ? format : "default", TRUE);
g_free(format);
}
/************************************************************
* Plugin Bootstrapping *
************************************************************/
void
gnc_plugin_aqbanking_create_plugin(void)
{
GncPlugin *plugin = gnc_plugin_aqbanking_new();
gnc_plugin_manager_add_plugin(gnc_plugin_manager_get(), plugin);
}