Initial code for a new register.

This is very incomplete, but at the same time well isolated from the
rest of the code, so it is easy to disable should it not get functional
and stable before the next major release.
I decided to include it in trunk to give it more visibility and prevent
bitrot in the patch.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22289 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Geert Janssens committed 2012-08-07 17:24:33 +00:00
1 parent 1ef66b2ce0
commit a54e7149bf
28 files changed
+9595 -4

No files matched your search

+27
View File
@@ -659,6 +659,33 @@ xaccSplitEqual(const Split *sa, const Split *sb,
return TRUE;
}
/********************************************************************
* xaccSplitListGetUniqueTransactions
********************************************************************/
static void
add_keys_to_list(gpointer key, gpointer val, gpointer list)
{
*(GList **)list = g_list_prepend(*(GList **)list, key);
}
GList *
xaccSplitListGetUniqueTransactions(const GList *splits)
{
const GList *node;
GList *transList = NULL;
GHashTable *transHash = g_hash_table_new(g_direct_hash, g_direct_equal);
for(node = splits; node; node = node->next) {
Transaction *trans = xaccSplitGetParent((Split *)(node->data));
g_hash_table_insert(transHash, trans, trans);
}
g_hash_table_foreach(transHash, add_keys_to_list, &transList);
g_hash_table_destroy(transHash);
return transList;
}
/********************************************************************
* Account funcs
********************************************************************/
+3
View File
@@ -343,6 +343,9 @@ Split * xaccSplitLookup (const GncGUID *guid, QofBook *book);
#define xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
/* Get a GList of unique transactions containing the given list of Splits. */
GList *xaccSplitListGetUniqueTransactions(const GList *splits);
/**
* The xaccSplitGetOtherSplit() is a convenience routine that returns
* the other of a pair of splits. If there are more than two
+39
View File
@@ -954,6 +954,45 @@ xaccTransGetAccountAmount (const Transaction *trans, const Account *acc)
return total;
}
gboolean
xaccTransGetRateForCommodity(const Transaction *trans,
const gnc_commodity *split_com,
const Split *split_to_exclude, gnc_numeric *rate)
{
GList *splits;
gnc_commodity *trans_curr;
trans_curr = xaccTransGetCurrency(trans);
if (gnc_commodity_equal(trans_curr, split_com)) {
if (rate)
*rate = gnc_numeric_create(1, 1);
return TRUE;
}
for (splits = trans->splits; splits; splits = splits->next) {
Split *s = splits->data;
gnc_commodity *comm;
if (s == split_to_exclude) continue;
if (!xaccTransStillHasSplit(trans, s)) continue;
comm = xaccAccountGetCommodity(xaccSplitGetAccount(s));
if (gnc_commodity_equal(split_com, comm)) {
gnc_numeric amt = xaccSplitGetAmount(s);
gnc_numeric val = xaccSplitGetValue(s);
if (!gnc_numeric_zero_p(xaccSplitGetValue(s)) &&
!gnc_numeric_zero_p(xaccSplitGetValue(s))) {
if (rate)
*rate = gnc_numeric_div(amt, val, GNC_DENOM_AUTO,
GNC_HOW_DENOM_REDUCE);
return TRUE;
}
}
}
return FALSE;
}
gnc_numeric
xaccTransGetAccountConvRate(const Transaction *txn, const Account *acc)
{
+10 -3
View File
@@ -264,11 +264,12 @@ void xaccTransSetTxnType (Transaction *trans, char type);
* See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */
char xaccTransGetTxnType (const Transaction *trans);
/** Sets the transaction Number (or ID) field*/
void xaccTransSetNum (Transaction *trans, const char *num);
/** Sets the transaction Description */
void xaccTransSetDescription (Transaction *trans, const char *desc);
/** Sets the transaction Notes
*
The Notes field is only visible in the register in double-line mode */
@@ -318,8 +319,7 @@ int xaccTransGetSplitIndex(const Transaction *trans, const Split *split);
this list when you are done with it. */
/*@ dependent @*/
SplitList * xaccTransGetSplitList (const Transaction *trans);
gboolean xaccTransStillHasSplit(const Transaction *trans, const Split *s);
gboolean xaccTransStillHasSplit(const Transaction *trans, const Split *s);
/** Set the transaction to be ReadOnly by setting a non-NULL value as "reason".
*
@@ -410,6 +410,13 @@ gnc_numeric xaccTransGetAccountValue (const Transaction *trans,
gnc_numeric xaccTransGetAccountAmount (const Transaction *trans,
const Account *account);
/* Gets the amt/val rate, i.e. rate from the transaction currency to
the 'split_com' */
gboolean
xaccTransGetRateForCommodity(const Transaction *trans,
const gnc_commodity *split_com,
const Split *split_to_exclude, gnc_numeric *rate);
/* Compute the conversion rate for the transaction to this account.
* Any "split value" (which is in the transaction currency),
* multiplied by this conversion rate, will give you the value you
+10
View File
@@ -49,6 +49,9 @@ libgncmod_gnome_utils_la_SOURCES = \
gnc-account-sel.c \
gnc-amount-edit.c \
gnc-autosave.c \
gnc-cell-renderer-date.c \
gnc-cell-renderer-popup.c \
gnc-cell-renderer-popup-entry.c \
gnc-combott.c \
gnc-commodity-edit.c \
gnc-currency-edit.c \
@@ -87,11 +90,13 @@ libgncmod_gnome_utils_la_SOURCES = \
gnc-tree-model-budget.c \
gnc-tree-model-owner.c \
gnc-tree-model-commodity.c \
gnc-tree-model-split-reg.c \
gnc-tree-model-price.c \
gnc-tree-view-account.c \
gnc-tree-view-commodity.c \
gnc-tree-view-owner.c \
gnc-tree-view-price.c \
gnc-tree-view-split-reg.c \
gnc-tree-view-sx-list.c \
gnc-tree-view.c \
gnc-window.c \
@@ -123,6 +128,9 @@ gncinclude_HEADERS = \
dialog-utils.h \
gnc-account-sel.h \
gnc-amount-edit.h \
gnc-cell-renderer-date.h \
gnc-cell-renderer-popup.h \
gnc-cell-renderer-popup-entry.h \
gnc-combott.h \
gnc-commodity-edit.h \
gnc-currency-edit.h \
@@ -160,10 +168,12 @@ gncinclude_HEADERS = \
gnc-tree-model-owner.h \
gnc-tree-model-commodity.h \
gnc-tree-model-price.h \
gnc-tree-model-split-reg.h \
gnc-tree-view-account.h \
gnc-tree-view-commodity.h \
gnc-tree-view-owner.h \
gnc-tree-view-price.h \
gnc-tree-view-split-reg.h \
gnc-tree-view-sx-list.h \
gnc-tree-view.h \
gnc-ui.h \
+525
View File
@@ -0,0 +1,525 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
**************************************************************************/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <time.h>
#include "gnc-cell-renderer-date.h"
#include "gnc-cell-renderer-popup-entry.h"
#include "gnc-date.h"
enum {
PROP_0,
PROP_USE_BUTTONS,
};
static void gcrd_init (GncCellRendererDate *date);
static void gcrd_class_init (GncCellRendererDateClass *class);
static void gcrd_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gcrd_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
static void gcrd_today_clicked (GtkWidget *button,
GncCellRendererDate *cell);
static void gcrd_selected_double_click (GtkWidget *calendar,
GncCellRendererDate *cell);
static void gcrd_cancel_clicked (GtkWidget *popup_window,
GncCellRendererDate *cell);
static void gcrd_ok_clicked (GtkWidget *popup_window,
GncCellRendererDate *cell);
static void gcrd_day_selected (GtkWidget *popup_window,
GncCellRendererDate *cell);
GtkCellEditable *gcrd_start_editing (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
const gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GtkCellRendererState flags);
static void gcrd_show (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2);
static void gcrd_hide (GncCellRendererPopup *cell);
/* These two functions are used internally */
gboolean gcrd_time2dmy ( time_t raw_time, gint *day, gint *month, gint *year);
static time_t gcrd_dmy2time ( gint day, gint month, gint year);
/* These two functions convert string to date to string */
static gchar * gcrd_time2dmy_string ( time_t raw_time);
static time_t gcrd_string_dmy2time ( char *date_string);
static GncCellRendererPopupClass *parent_class;
GType
gnc_cell_renderer_date_get_type (void)
{
static GType cell_text_type = 0;
if (!cell_text_type) {
static const GTypeInfo cell_text_info = {
sizeof (GncCellRendererDateClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gcrd_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncCellRendererDate),
0, /* n_preallocs */
(GInstanceInitFunc) gcrd_init,
};
cell_text_type = g_type_register_static (GNC_TYPE_CELL_RENDERER_POPUP,
"GncCellRendererDate",
&cell_text_info,
0);
}
return cell_text_type;
}
static void
gcrd_init (GncCellRendererDate *date)
{
GncCellRendererPopup *popup;
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *bbox;
GtkWidget *button;
popup = GNC_CELL_RENDERER_POPUP (date);
frame = gtk_frame_new (NULL);
gtk_container_add (GTK_CONTAINER (popup->popup_window), frame);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
date->calendar = gtk_calendar_new ();
popup->focus_window = date->calendar;
gtk_box_pack_start (GTK_BOX (vbox), date->calendar, TRUE, TRUE, 0);
date->button_box = gtk_hbutton_box_new ();
gtk_box_set_spacing (GTK_BOX (date->button_box), 6);
gtk_box_pack_start (GTK_BOX (vbox), date->button_box, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("Cancel"));
gtk_container_add (GTK_CONTAINER (date->button_box), button);
g_signal_connect (button, "clicked",
G_CALLBACK (gcrd_cancel_clicked),
date);
date->today_button = gtk_button_new_with_label (_("Today"));
gtk_container_add (GTK_CONTAINER (date->button_box), date->today_button);
g_signal_connect (date->today_button, "clicked",
G_CALLBACK (gcrd_today_clicked),
date);
button = gtk_button_new_with_label (_("Select"));
gtk_container_add (GTK_CONTAINER (date->button_box), button);
g_signal_connect (button, "clicked",
G_CALLBACK (gcrd_ok_clicked),
date);
g_signal_connect (date->calendar, "day-selected",
G_CALLBACK (gcrd_day_selected),
date);
g_signal_connect (date->calendar, "day-selected-double-click",
G_CALLBACK (gcrd_selected_double_click),
date);
//Set calendar to show current date when displayed
date->time = time(NULL);
gtk_widget_show_all (frame);
}
static void
gcrd_class_init (GncCellRendererDateClass *class)
{
GncCellRendererPopupClass *popup_class;
GtkCellRendererClass *cell_class;
GObjectClass *gobject_class;
popup_class = GNC_CELL_RENDERER_POPUP_CLASS (class);
cell_class = GTK_CELL_RENDERER_CLASS (class);
parent_class = GNC_CELL_RENDERER_POPUP_CLASS (g_type_class_peek_parent (class));
gobject_class = G_OBJECT_CLASS (class);
gobject_class->set_property = gcrd_set_property;
gobject_class->get_property = gcrd_get_property;
cell_class->start_editing = gcrd_start_editing;
popup_class->show_popup = gcrd_show;
popup_class->hide_popup = gcrd_hide;
g_object_class_install_property (
gobject_class,
PROP_USE_BUTTONS,
g_param_spec_boolean ("use-buttons",
NULL,
NULL,
TRUE,
G_PARAM_READWRITE));
}
static void
gcrd_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
GncCellRendererDate *date;
date = GNC_CELL_RENDERER_DATE (object);
switch (param_id) {
case PROP_USE_BUTTONS:
date->use_buttons = g_value_get_boolean (value);
if (date->use_buttons)
gtk_widget_show (date->button_box);
else
gtk_widget_hide (date->button_box);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
static void
gcrd_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
GncCellRendererDate *date;
date = GNC_CELL_RENDERER_DATE (object);
switch (param_id) {
case PROP_USE_BUTTONS:
g_value_set_boolean (value, date->use_buttons);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
GtkCellEditable *
gcrd_start_editing (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
const gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GtkCellRendererState flags)
{
GNC_CELL_RENDERER_POPUP (cell)->editing_canceled = FALSE;
if (GTK_CELL_RENDERER_CLASS (parent_class)->start_editing) {
return GTK_CELL_RENDERER_CLASS (parent_class)->start_editing (
cell,
event,
widget,
path,
background_area,
cell_area,
flags);
}
return NULL;
}
static void
gcrd_hide (GncCellRendererPopup *cell)
{
if (parent_class->hide_popup) {
parent_class->hide_popup (cell);
}
}
static void
gcrd_show (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2)
{
GncCellRendererDate *date;
gint year;
gint month;
gint day;
gint index;
gchar *text;
if (parent_class->show_popup) {
parent_class->show_popup (cell,
path,
x1, y1,
x2, y2);
}
date = GNC_CELL_RENDERER_DATE (cell);
if (!(g_strcmp0(cell->cell_text, "")))
{
date->time = time(NULL);
gcrd_time2dmy ( date->time, &day, &month, &year);
}
else
{
date->time = gcrd_string_dmy2time (cell->cell_text);
gcrd_time2dmy ( date->time, &day, &month, &year);
}
gtk_calendar_clear_marks (GTK_CALENDAR (date->calendar));
gtk_calendar_select_month (GTK_CALENDAR (date->calendar), month - 1, year);
gtk_calendar_select_day (GTK_CALENDAR (date->calendar), day);
gtk_calendar_mark_day (GTK_CALENDAR (date->calendar), day);
}
GtkCellRenderer *
gnc_cell_renderer_date_new (gboolean use_buttons)
{
GObject *cell;
cell = g_object_new (GNC_TYPE_CELL_RENDERER_DATE,
"use-buttons", use_buttons,
NULL);
return GTK_CELL_RENDERER (cell);
}
static void
gcrd_today_clicked (GtkWidget *button, GncCellRendererDate *cell)
{
time_t today;
gint year, month, day;
today = time(NULL);
gcrd_time2dmy ( today, &day, &month, &year);
gtk_calendar_clear_marks (GTK_CALENDAR (cell->calendar));
gtk_calendar_select_month (GTK_CALENDAR (cell->calendar), month - 1, year);
gtk_calendar_select_day (GTK_CALENDAR (cell->calendar), day);
gtk_calendar_mark_day (GTK_CALENDAR (cell->calendar), day);
}
static void
gcrd_selected_double_click (GtkWidget *calendar, GncCellRendererDate *cell)
{
GncCellRendererPopup *popup;
popup = GNC_CELL_RENDERER_POPUP (cell);
gcrd_ok_clicked (popup->popup_window, cell);
}
static void
gcrd_cancel_clicked (GtkWidget *popup_window, GncCellRendererDate *cell)
{
GncCellRendererPopup *popup;
popup = GNC_CELL_RENDERER_POPUP (cell);
popup->editing_canceled = TRUE;
gnc_cell_renderer_popup_hide (popup);
}
static void
gcrd_ok_clicked (GtkWidget *popup_window, GncCellRendererDate *cell)
{
GncCellRendererPopup *popup;
popup = GNC_CELL_RENDERER_POPUP (cell);
gcrd_day_selected (popup_window, cell);
popup->editing_canceled = FALSE;
gnc_cell_renderer_popup_hide (popup);
}
static void
gcrd_day_selected (GtkWidget *popup_window, GncCellRendererDate *cell)
{
guint year;
guint month;
guint day;
time_t t;
gchar *str;
gtk_calendar_get_date (GTK_CALENDAR (cell->calendar),
&year,
&month,
&day);
t = gcrd_dmy2time ( day, month + 1, year);
cell->time = t;
str = gcrd_time2dmy_string (t);
gnc_popup_entry_set_text (
GNC_POPUP_ENTRY (GNC_CELL_RENDERER_POPUP (cell)->editable), str);
g_free (str);
}
static gboolean
gcrd_grab_on_window (GdkWindow *window,
guint32 activate_time)
{
if ((gdk_pointer_grab (window, TRUE,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK,
NULL, NULL, activate_time) == 0)) {
if (gdk_keyboard_grab (window, TRUE,
activate_time) == 0)
return TRUE;
else {
gdk_pointer_ungrab (activate_time);
return FALSE;
}
}
return FALSE;
}
/* This function converts a time_t value date to separate entities */
gboolean
gcrd_time2dmy ( time_t raw_time, gint *day, gint *month, gint *year)
{
struct tm * timeinfo;
timeinfo = localtime ( &raw_time );
*day = timeinfo->tm_mday;
*month = timeinfo->tm_mon + 1;
*year = timeinfo->tm_year + 1900;
return TRUE;
}
/* This function converts separate entities to a time_t value */
static time_t
gcrd_dmy2time ( gint day, gint month, gint year)
{
struct tm *when;
time_t raw_time;
time(&raw_time);
when = localtime ( &raw_time );
when->tm_year = year - 1900;
when->tm_mon = month - 1 ;
when->tm_mday = day;
return mktime(when);
}
/* This function converts a time_t value date to a string */
static gchar *
gcrd_time2dmy_string ( time_t raw_time)
{
return qof_print_date (raw_time);
}
/* This function converts a string date to a time_t value */
static time_t
gcrd_string_dmy2time ( char *date_string)
{
struct tm *when;
gint year = 0, month = 0, day = 0;
time_t raw_time;
if(qof_scan_date (date_string, &day, &month, &year))
{
time(&raw_time);
when = localtime ( &raw_time );
when->tm_year = year - 1900;
when->tm_mon = month - 1 ;
when->tm_mday = day;
return mktime(when);
}
else
{
raw_time = time(NULL);
return raw_time;
}
}
+71
View File
@@ -0,0 +1,71 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
**************************************************************************/
#ifndef __GNC_CELL_RENDERER_DATE_H__
#define __GNC_CELL_RENDERER_DATE_H__
#include <glib-object.h>
#include <gtk/gtkwidget.h>
#include <time.h>
#include "gnc-cell-renderer-popup.h"
#include "gnc-cell-renderer-popup-entry.h"
#define GNC_TYPE_CELL_RENDERER_DATE (gnc_cell_renderer_date_get_type ())
#define GNC_CELL_RENDERER_DATE(obj) (GTK_CHECK_CAST ((obj), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDate))
#define GNC_CELL_RENDERER_DATE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDateClass))
#define GNC_IS_CELL_RENDERER_DATE(obj) (GTK_CHECK_TYPE ((obj), GNC_TYPE_CELL_RENDERER_DATE))
#define GNC_IS_CELL_RENDERER_DATE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_CELL_RENDERER_DATE))
#define GNC_CELL_RENDERER_DATE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDateClass))
typedef struct _GncCellRendererDate GncCellRendererDate;
typedef struct _GncCellRendererDateClass GncCellRendererDateClass;
struct _GncCellRendererDate
{
GncCellRendererPopup parent;
GtkWidget *calendar;
GtkWidget *today_button;
time_t time;
gboolean use_buttons;
GtkWidget *button_box;
};
struct _GncCellRendererDateClass
{
GncCellRendererPopupClass parent_class;
};
GType gnc_cell_renderer_date_get_type (void) G_GNUC_CONST;
GtkCellRenderer *gnc_cell_renderer_date_new (gboolean use_buttons);
#endif /* __GNC_CELL_RENDERER_DATE_H__ */
@@ -0,0 +1,281 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*************************************************************************/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include "gnc-cell-renderer-popup-entry.h"
static void gnc_popup_entry_init (GncPopupEntry *entry);
static void gnc_popup_entry_class_init (GncPopupEntryClass *class);
static void gpw_cell_editable_init (GtkCellEditableIface *iface);
static gboolean gpw_key_press_event (GtkWidget *box,
GdkEventKey *key_event);
enum {
ARROW_CLICKED,
LAST_SIGNAL
};
enum {
ARG_0,
ARG_EDITING_CANCELED
};
static GtkEventBoxClass *parent_class;
static guint signals[LAST_SIGNAL];
GtkType
gnc_popup_entry_get_type (void)
{
static GtkType widget_type = 0;
if (!widget_type) {
static const GTypeInfo widget_info = {
sizeof (GncPopupEntryClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gnc_popup_entry_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncPopupEntry),
0, /* n_preallocs */
(GInstanceInitFunc) gnc_popup_entry_init,
};
static const GInterfaceInfo cell_editable_info = {
(GInterfaceInitFunc) gpw_cell_editable_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
widget_type = g_type_register_static (GTK_TYPE_EVENT_BOX,
"GncPopupEntry",
&widget_info,
0);
g_type_add_interface_static (widget_type,
GTK_TYPE_CELL_EDITABLE,
&cell_editable_info);
}
return widget_type;
}
static void
gnc_popup_entry_init (GncPopupEntry *widget)
{
GtkWidget *arrow;
widget->hbox = gtk_hbox_new (FALSE, 0);
gtk_widget_show (widget->hbox);
widget->entry = g_object_new (GTK_TYPE_ENTRY, "has_frame", FALSE, NULL);
GTK_ENTRY (widget->entry)->is_cell_renderer = TRUE;
gtk_widget_show (widget->entry);
widget->button = gtk_button_new ();
gtk_widget_show (widget->button);
arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
gtk_widget_show (arrow);
gtk_container_add (GTK_CONTAINER (widget->button), arrow);
gtk_box_pack_start (GTK_BOX (widget->hbox), widget->entry, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (widget->hbox), widget->button, FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (widget), widget->hbox);
GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_PRESS_MASK);
gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_RELEASE_MASK);
}
static void
gnc_popup_entry_class_init (GncPopupEntryClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->key_press_event = gpw_key_press_event;
gtk_object_add_arg_type ("GncPopupEntry::editing-canceled", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITING_CANCELED);
parent_class = GTK_EVENT_BOX_CLASS (g_type_class_peek_parent (klass));
signals[ARROW_CLICKED] = g_signal_new
("arrow-clicked",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
gpw_arrow_clicked (GtkWidget *button, GncPopupEntry *widget)
{
g_signal_emit (widget, signals[ARROW_CLICKED], 0);
}
/* GtkCellEditable method implementations
*/
static void
gtk_cell_editable_entry_activated (GtkEntry *entry, GncPopupEntry *widget)
{
gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
}
static gboolean
gtk_cell_editable_key_press_event (GtkEntry *entry,
GdkEventKey *key_event,
GncPopupEntry *widget)
{
if (key_event->keyval == GDK_Escape) {
widget->editing_canceled = TRUE;
gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
return TRUE;
}
return FALSE;
}
static gboolean
gpw_key_press_event (GtkWidget *box,
GdkEventKey *key_event)
{
GncPopupEntry *widget = GNC_POPUP_ENTRY (box);
GdkEvent tmp_event;
if (key_event->keyval == GDK_Escape) {
widget->editing_canceled = TRUE;
gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
return TRUE;
}
gtk_widget_grab_focus (widget->entry);
/* Hackish :/ Synthesize a key press event for the entry. */
memcpy (&tmp_event, key_event, sizeof (GdkEventKey));
tmp_event.key.window = widget->entry->window;
tmp_event.key.send_event = TRUE;
gtk_widget_event (widget->entry, &tmp_event);
return GTK_WIDGET_CLASS (parent_class)->key_press_event (GTK_WIDGET (widget),
key_event);
}
static void
gpw_start_editing (GtkCellEditable *cell_editable,
GdkEvent *event)
{
GncPopupEntry *widget = GNC_POPUP_ENTRY (cell_editable);
gtk_editable_select_region (GTK_EDITABLE (widget->entry), 0, -1);
g_signal_connect (G_OBJECT (widget->entry),
"activate",
G_CALLBACK (gtk_cell_editable_entry_activated),
widget);
g_signal_connect (G_OBJECT (widget->entry),
"key_press_event",
G_CALLBACK (gtk_cell_editable_key_press_event),
widget);
g_signal_connect (G_OBJECT (widget->button),
"clicked",
(GCallback) gpw_arrow_clicked,
widget);
}
static void
gpw_cell_editable_init (GtkCellEditableIface *iface)
{
iface->start_editing = gpw_start_editing;
}
void
gnc_popup_entry_set_text (GncPopupEntry *popup, const gchar *text)
{
g_return_if_fail (GNC_IS_POPUP_ENTRY (popup));
gtk_entry_set_text (GTK_ENTRY (popup->entry), text ? text : "");
}
const gchar *
gnc_popup_entry_get_text (GncPopupEntry *popup)
{
g_return_val_if_fail (GNC_IS_POPUP_ENTRY (popup), NULL);
return gtk_entry_get_text (GTK_ENTRY (popup->entry));
}
gint
gnc_popup_get_button_width (void)
{
GtkWidget *window, *button, *arrow;
gint width;
GtkRequisition req;
window = gtk_window_new (GTK_WINDOW_POPUP);
button = gtk_button_new ();
gtk_widget_show (button);
gtk_container_add (GTK_CONTAINER (window), button);
arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
gtk_widget_show (arrow);
gtk_container_add (GTK_CONTAINER (button), arrow);
gtk_window_move (GTK_WINDOW (window), -500, -500);
gtk_widget_show (window);
gtk_widget_size_request (window, &req);
width = req.width;
gtk_widget_destroy (window);
return width;
}
@@ -0,0 +1,74 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*************************************************************************/
#ifndef __GNC_POPUP_ENTRY_H__
#define __GNC_POPUP_ENTRY_H__
#include <pango/pango.h>
#include <gtk/gtkeventbox.h>
#define GNC_TYPE_POPUP_ENTRY (gnc_popup_entry_get_type ())
#define GNC_POPUP_ENTRY(obj) (GTK_CHECK_CAST ((obj), GNC_TYPE_POPUP_ENTRY, GncPopupEntry))
#define GNC_POPUP_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_POPUP_ENTRY, GncPopupEntryClass))
#define GNC_IS_POPUP_ENTRY(obj) (GTK_CHECK_TYPE ((obj), GNC_TYPE_POPUP_ENTRY))
#define GNC_IS_POPUP_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_POPUP_ENTRY))
#define GNC_POPUP_ENTRY_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_POPUP_ENTRY, GncPopupEntryClass))
typedef struct _GncPopupEntry GncPopupEntry;
typedef struct _GncPopupEntryClass GncPopupEntryClass;
struct _GncPopupEntry
{
GtkEventBox parent;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *entry;
gboolean editing_canceled;
};
struct _GncPopupEntryClass
{
GtkEventBoxClass parent_class;
};
GtkType gnc_popup_entry_get_type (void) G_GNUC_CONST;
GtkWidget *gnc_popup_entry_new (void);
void gnc_popup_entry_set_text (GncPopupEntry *popup,
const gchar *text);
const gchar *gnc_popup_entry_get_text (GncPopupEntry *popup);
gint gnc_popup_get_button_width (void);
#endif /* __GNC_POPUP_ENTRY_H__ */
+575
View File
@@ -0,0 +1,575 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*************************************************************************/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include "gnc-cell-renderer-popup.h"
#include "gnc-cell-renderer-popup-entry.h"
enum {
SHOW_POPUP,
HIDE_POPUP,
LAST_SIGNAL
};
static void gcrp_init (GncCellRendererPopup *popup);
static void gcrp_class_init (GncCellRendererPopupClass *class);
static GtkCellEditable *
gcrp_start_editing (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
const gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GtkCellRendererState flags);
static void gcrp_show_popup (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2);
static void gcrp_hide_popup (GncCellRendererPopup *cell);
static void gcrp_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height);
static void gcrp_style_set (GtkWidget *widget,
GtkStyle *old_style,
GncCellRendererPopup *popup);
static gboolean gcrp_key_press_event (GtkWidget *popup_window,
GdkEventKey *event,
GncCellRendererPopup *cell);
static gboolean gcrp_button_press_event (GtkWidget *widget,
GdkEventButton *event,
GncCellRendererPopup *popup);
void gnc_marshal_VOID__STRING_INT_INT_INT_INT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
static GtkCellRendererTextClass *parent_class;
static guint signals[LAST_SIGNAL];
#define GNC_CELL_RENDERER_POPUP_PATH "gnc-cell-renderer-popup-path"
GType
gnc_cell_renderer_popup_get_type (void)
{
static GType cell_text_type = 0;
if (!cell_text_type) {
static const GTypeInfo cell_text_info = {
sizeof (GncCellRendererPopupClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gcrp_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncCellRendererPopup),
0, /* n_preallocs */
(GInstanceInitFunc) gcrp_init,
};
cell_text_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT,
"GncCellRendererPopup",
&cell_text_info,
0);
}
return cell_text_type;
}
static void
gcrp_init (GncCellRendererPopup *popup)
{
popup->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
popup->button_width = -1;
g_signal_connect (popup->popup_window,
"button-press-event",
G_CALLBACK (gcrp_button_press_event),
popup);
g_signal_connect (popup->popup_window,
"key-press-event",
G_CALLBACK (gcrp_key_press_event),
popup);
g_signal_connect (popup->popup_window,
"style-set",
G_CALLBACK (gcrp_style_set),
popup);
}
static void
gcrp_class_init (GncCellRendererPopupClass *class)
{
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
parent_class = GTK_CELL_RENDERER_TEXT_CLASS (g_type_class_peek_parent (class));
cell_class->start_editing = gcrp_start_editing;
cell_class->get_size = gcrp_get_size;
class->show_popup = gcrp_show_popup;
class->hide_popup = gcrp_hide_popup;
signals[SHOW_POPUP] = g_signal_new (
"show-popup",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GncCellRendererPopupClass, show_popup),
NULL, NULL,
gnc_marshal_VOID__STRING_INT_INT_INT_INT,
G_TYPE_NONE, 5,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT);
signals[HIDE_POPUP] = g_signal_new (
"hide-popup",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GncCellRendererPopupClass, hide_popup),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
gcrp_editing_done (GtkCellEditable *editable,
GncCellRendererPopup *cell)
{
gchar *path;
const gchar *new_text;
if (GNC_POPUP_ENTRY (editable)->editing_canceled ||
cell->editing_canceled) {
gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (cell), TRUE);
return;
}
path = g_object_get_data (G_OBJECT (editable),
GNC_CELL_RENDERER_POPUP_PATH);
new_text = gnc_popup_entry_get_text (GNC_POPUP_ENTRY (editable));
g_signal_emit_by_name (cell,
"edited",
path,
new_text);
}
static void
gcrp_style_set (GtkWidget *widget,
GtkStyle *old_style,
GncCellRendererPopup *popup)
{
/* Invalidate the cache. */
popup->button_width = -1;
}
static gboolean
gcrp_grab_on_window (GdkWindow *window,
guint32 activate_time)
{
if ((gdk_pointer_grab (window, TRUE,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK,
NULL, NULL, activate_time) == 0)) {
if (gdk_keyboard_grab (window, TRUE,
activate_time) == 0)
return TRUE;
else {
gdk_pointer_ungrab (activate_time);
return FALSE;
}
}
return FALSE;
}
static void
gcrp_show_popup (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2)
{
GtkAllocation alloc;
gint x, y;
gint screen_height, screen_width;
gint button_height;
cell->shown = TRUE;
gtk_widget_realize (cell->popup_window);
/* I'm not sure this is ok to do, but we need to show the window to be
* able to get the allocation right.
*/
gtk_window_move (GTK_WINDOW (cell->popup_window), -500, -500);
gtk_widget_show (cell->popup_window);
alloc = cell->popup_window->allocation;
x = x2;
y = y2;
button_height = y2 - y1;
screen_height = gdk_screen_height () - y;
screen_width = gdk_screen_width ();
/* Check if it fits in the available height. */
if (alloc.height > screen_height) {
/* It doesn't fit, so we see if we have the minimum space needed. */
if (alloc.height > screen_height && y - button_height > screen_height) {
/* We don't, so we show the popup above the cell
instead of below it. */
screen_height = y - button_height;
y -= (alloc.height + button_height);
if (y < 0) {
y = 0;
}
}
}
/* We try to line it up with the right edge of the column, but we don't
* want it to go off the edges of the screen.
*/
if (x > screen_width) {
x = screen_width;
}
x -= alloc.width;
if (x < 0) {
x = 0;
}
gtk_grab_add (cell->popup_window);
gtk_window_move (GTK_WINDOW (cell->popup_window), x, y);
gtk_widget_show (cell->popup_window);
gtk_widget_grab_focus (cell->focus_window);
gcrp_grab_on_window (cell->popup_window->window,
gtk_get_current_event_time ());
}
static void
gcrp_hide_popup (GncCellRendererPopup *cell)
{
gtk_grab_remove (cell->popup_window);
gtk_widget_hide (cell->popup_window);
if (cell->editable) {
gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (cell->editable));
}
/* This may look weird (the test), but the weak pointer will actually be
* nulled out for some cells, like the date cell.
*/
if (cell->editable) {
gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (cell->editable));
}
cell->shown = FALSE;
cell->editing_canceled = FALSE;
}
static void
gcrp_arrow_clicked (GtkCellEditable *entry,
GncCellRendererPopup *cell)
{
GtkAllocation alloc;
gint x, y;
const gchar *path;
if (cell->shown) {
cell->editing_canceled = TRUE;
gnc_cell_renderer_popup_hide (cell);
return;
}
path = g_object_get_data (G_OBJECT (entry),
GNC_CELL_RENDERER_POPUP_PATH);
/* Temporarily grab pointer and keyboard on a window we know exists; we
* do this so that the grab (with owner events == TRUE) affects
* events generated when the window is mapped, such as enter
* notify events on subwidgets. If the grab fails, bail out.
*/
if (!gcrp_grab_on_window (GTK_WIDGET (entry)->window,
gtk_get_current_event_time ())) {
return;
}
gtk_editable_select_region (GTK_EDITABLE (GNC_POPUP_ENTRY (entry)->entry), 0, 0);
gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y);
alloc = GTK_WIDGET (entry)->allocation;
g_signal_emit (cell, signals[SHOW_POPUP], 0,
path,
x,
y,
x + alloc.width,
y + alloc.height);
}
static GtkCellEditable *
gcrp_start_editing (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
const gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GtkCellRendererState flags)
{
GncCellRendererPopup *popup;
GtkWidget *editable;
gchar *text;
popup = GNC_CELL_RENDERER_POPUP (cell);
/* If the cell isn't editable we return NULL. */
if (GTK_CELL_RENDERER_TEXT (popup)->editable == FALSE) {
return NULL;
}
editable = g_object_new (GNC_TYPE_POPUP_ENTRY, NULL);
text = GTK_CELL_RENDERER_TEXT (cell)->text;
popup->cell_text = g_strdup(text);
gnc_popup_entry_set_text (GNC_POPUP_ENTRY (editable), text ? text : "");
g_object_set_data_full (G_OBJECT (editable),
GNC_CELL_RENDERER_POPUP_PATH,
g_strdup (path),
g_free);
gtk_widget_show (editable);
g_signal_connect (editable,
"editing-done",
G_CALLBACK (gcrp_editing_done),
popup);
g_signal_connect (editable,
"arrow-clicked",
G_CALLBACK (gcrp_arrow_clicked),
popup);
popup->editable = editable;
g_object_add_weak_pointer (G_OBJECT (popup->editable),
(gpointer) &popup->editable);
return GTK_CELL_EDITABLE (editable);
}
GtkCellRenderer *
gnc_cell_renderer_popup_new (void)
{
return GTK_CELL_RENDERER (
g_object_new (gnc_cell_renderer_popup_get_type (), NULL));
}
void
gnc_cell_renderer_popup_hide (GncCellRendererPopup *cell)
{
g_return_if_fail (GNC_IS_CELL_RENDERER_POPUP (cell));
g_signal_emit (cell, signals[HIDE_POPUP], 0);
}
static void
gcrp_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height)
{
GncCellRendererPopup *popup;
popup = GNC_CELL_RENDERER_POPUP (cell);
if (GTK_CELL_RENDERER_CLASS (parent_class)->get_size) {
(* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell,
widget,
cell_area,
x_offset,
y_offset,
width,
height);
}
/* We cache this because it takes really long to get the width. */
if (popup->button_width == -1) {
popup->button_width = gnc_popup_get_button_width ();
}
*width += popup->button_width;
}
static gboolean
gcrp_key_press_event (GtkWidget *popup_window,
GdkEventKey *event,
GncCellRendererPopup *cell)
{
if (event->keyval != GDK_Escape &&
event->keyval != GDK_Return &&
event->keyval != GDK_KP_Enter &&
event->keyval != GDK_ISO_Enter &&
event->keyval != GDK_3270_Enter) {
return FALSE;
}
if (event->keyval == GDK_Escape) {
cell->editing_canceled = TRUE;
} else {
cell->editing_canceled = FALSE;
}
gnc_cell_renderer_popup_hide (cell);
return TRUE;
}
static gboolean
gcrp_button_press_event (GtkWidget *widget,
GdkEventButton *event,
GncCellRendererPopup *popup)
{
GtkAllocation alloc;
gdouble x, y;
gint xoffset, yoffset;
gint x1, y1;
gint x2, y2;
if (event->button != 1) {
return FALSE;
}
/* If the event happened outside the popup, cancel editing.
*/
/*gdk_event_get_root_coords ((GdkEvent *) event, &x, &y);*/
x = event->x_root;
y = event->y_root;
gdk_window_get_root_origin (widget->window,
&xoffset,
&yoffset);
xoffset += widget->allocation.x;
yoffset += widget->allocation.y;
alloc = popup->popup_window->allocation;
x1 = alloc.x + xoffset;
y1 = alloc.y + yoffset;
x2 = x1 + alloc.width;
y2 = y1 + alloc.height;
if (x > x1 && x < x2 && y > y1 && y < y2) {
return FALSE;
}
popup->editing_canceled = TRUE;
gnc_cell_renderer_popup_hide (popup);
return FALSE;
}
#define g_marshal_value_peek_int(v) (v)->data[0].v_int
#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
void
gnc_marshal_VOID__STRING_INT_INT_INT_INT (GClosure *closure,
GValue *return_value G_GNUC_UNUSED,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint G_GNUC_UNUSED,
gpointer marshal_data)
{
typedef void (*GMarshalFunc_VOID__STRING_INT_INT_INT_INT) (gpointer data1,
gpointer arg_1,
gint arg_2,
gint arg_3,
gint arg_4,
gint arg_5,
gpointer data2);
register GMarshalFunc_VOID__STRING_INT_INT_INT_INT callback;
register GCClosure *cc = (GCClosure*) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 6);
if (G_CCLOSURE_SWAP_DATA (closure))
{
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
}
else
{
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback = (GMarshalFunc_VOID__STRING_INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
callback (data1,
g_marshal_value_peek_string (param_values + 1),
g_marshal_value_peek_int (param_values + 2),
g_marshal_value_peek_int (param_values + 3),
g_marshal_value_peek_int (param_values + 4),
g_marshal_value_peek_int (param_values + 5),
data2);
}
+94
View File
@@ -0,0 +1,94 @@
/*************************************************************************
* The following code has come from Planner. This code implements a
* GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
*
* These files have been renamed and changed to remove code not required
* and to remove a dependency on libplanner.
*
* Copyright (C) 2012 Robert Fewell
*
* Copyright (C) 2001-2002 CodeFactory AB
* Copyright (C) 2001-2002 Richard Hult <richard@imendio.com>
* Copyright (C) 2001-2002 Mikael Hallendal <micke@imendio.com>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*************************************************************************/
#ifndef __GNC_CELL_RENDERER_POPUP_H__
#define __GNC_CELL_RENDERER_POPUP_H__
#include <pango/pango.h>
#include <gtk/gtkcellrenderertext.h>
#define GNC_TYPE_CELL_RENDERER_POPUP (gnc_cell_renderer_popup_get_type ())
#define GNC_CELL_RENDERER_POPUP(obj) (GTK_CHECK_CAST ((obj), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopup))
#define GNC_CELL_RENDERER_POPUP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopupClass))
#define GNC_IS_CELL_RENDERER_POPUP(obj) (GTK_CHECK_TYPE ((obj), GNC_TYPE_CELL_RENDERER_POPUP))
#define GNC_IS_CELL_RENDERER_POPUP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_CELL_RENDERER_POPUP))
#define GNC_CELL_RENDERER_POPUP_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopupClass))
typedef struct _GncCellRendererPopup GncCellRendererPopup;
typedef struct _GncCellRendererPopupClass GncCellRendererPopupClass;
struct _GncCellRendererPopup
{
GtkCellRendererText parent;
/* Cached width of the popup button. */
gint button_width;
/* The popup window. */
GtkWidget *popup_window;
/* The widget that should grab focus on popup. */
GtkWidget *focus_window;
/* The editable entry. */
GtkWidget *editable;
gboolean shown;
gboolean editing_canceled;
gchar *cell_text;
};
struct _GncCellRendererPopupClass
{
GtkCellRendererTextClass parent_class;
void (* show_popup) (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2);
void (* hide_popup) (GncCellRendererPopup *cell);
};
GtkType gnc_cell_renderer_popup_get_type (void) G_GNUC_CONST;
GtkCellRenderer *gnc_cell_renderer_popup_new (void);
void gnc_cell_renderer_popup_show (GncCellRendererPopup *cell,
const gchar *path,
gint x1,
gint y1,
gint x2,
gint y2);
void gnc_cell_renderer_popup_hide (GncCellRendererPopup *cell);
#endif /* __GNC_CELL_RENDERER_POPUP_H__ */
File diff suppressed because it is too large. Load diff
+196
View File
@@ -0,0 +1,196 @@
/********************************************************************\
* gnc-tree-model-split-reg.h -- GtkTreeView implementation to *
* display registers in a GtkTreeView. *
* *
* Copyright (C) 2012 Robert Fewell *
* Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker@cox.net> *
* *
* 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 *
* *
\********************************************************************/
#ifndef __GNC_TREE_MODEL_SPLIT_REG_H
#define __GNC_TREE_MODEL_SPLIT_REG_H
#include <gtk/gtk.h>
#include "gnc-tree-model.h"
#include "Query.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_TREE_MODEL_SPLIT_REG (gnc_tree_model_split_reg_get_type ())
#define GNC_TREE_MODEL_SPLIT_REG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitReg))
#define GNC_TREE_MODEL_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitRegClass))
#define GNC_IS_TREE_MODEL_SPLIT_REG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG))
#define GNC_IS_TREE_MODEL_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_MODEL_SPLIT_REG))
#define GNC_TREE_MODEL_SPLIT_REG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitRegClass))
#define GNC_TREE_MODEL_SPLIT_REG_NAME "GncTreeModelSplitReg"
/** @brief Register types
*
* "registers" are single-account display windows.
* "ledgers" are multiple-account display windows */
typedef enum
{
BANK_REGISTER2,
CASH_REGISTER2,
ASSET_REGISTER2,
CREDIT_REGISTER2,
LIABILITY_REGISTER2,
INCOME_REGISTER2,
EXPENSE_REGISTER2,
EQUITY_REGISTER2,
STOCK_REGISTER2,
CURRENCY_REGISTER2,
RECEIVABLE_REGISTER2,
PAYABLE_REGISTER2,
TRADING_REGISTER2,
NUM_SINGLE_REGISTER_TYPES2,
GENERAL_LEDGER2 = NUM_SINGLE_REGISTER_TYPES2,
INCOME_LEDGER2,
PORTFOLIO_LEDGER2,
SEARCH_LEDGER2,
NUM_REGISTER_TYPES2
} SplitRegisterType2;
/** Register styles */
typedef enum
{
REG_STYLE_LEDGER2,
REG_STYLE_AUTO_LEDGER2,
REG_STYLE_JOURNAL2
} SplitRegisterStyle2;
typedef enum
{
GNC_TREE_MODEL_SPLIT_REG_COL_GUID,
GNC_TREE_MODEL_SPLIT_REG_COL_DATE,
GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT,
GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES,
GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID,
GNC_TREE_MODEL_SPLIT_REG_COL_LAST_VISIBLE = GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID,
/* internal hidden columns */
GNC_TREE_MODEL_SPLIT_REG_COL_COLOR,
GNC_TREE_MODEL_SPLIT_REG_NUM_COLUMNS
} GncTreeModelSplitRegColumn;
/* typedefs & structures */
typedef struct GncTreeModelSplitRegPrivate GncTreeModelSplitRegPrivate;
/** The instance data structure for an account tree model. */
typedef struct
{
GncTreeModel gnc_tree_model; /**< The parent object data. */
GncTreeModelSplitRegPrivate *priv;
int stamp; /**< The state of the model. Any state
* change increments this number. */
SplitRegisterType2 type; /* This may be the wrong place for these, may be the view ? */
SplitRegisterStyle2 style;
} GncTreeModelSplitReg;
/** The class data structure for an account tree model. */
typedef struct
{
GncTreeModelClass gnc_tree_model; /**< The parent object data. */
} GncTreeModelSplitRegClass;
/** Get the type of split register tree plugin.
*
* @return A GType.
*/
GType gnc_tree_model_split_reg_get_type (void);
/** @name Split Register Tree Model Constructors
@{ */
/** Create a new GtkTreeModel for manipulating gnucash splits.
*
* @param The Query
*/
GncTreeModelSplitReg *gnc_tree_model_split_reg_new_from_account (Account *acc);
/** @} */
/** @name Split Register Tree Model Constructors
@{ */
/** Create a new GtkTreeModel for manipulating gnucash splits.
*
* @param The Query
*/
GncTreeModelSplitReg *gnc_tree_model_split_reg_new_from_query (Query *query);
/** @} */
/** Get the Account of GtkTreeModel.
*
* @param The model
*/
Account * gnc_tree_model_split_reg_get_anchor(GncTreeModelSplitReg *model);
/** @} */
GtkListStore *
gnc_tree_model_split_reg_get_description_list(GncTreeModelSplitReg *model);
GtkListStore *
gnc_tree_model_split_reg_get_notes_list(GncTreeModelSplitReg *model);
GtkListStore *
gnc_tree_model_split_reg_get_memo_list(GncTreeModelSplitReg *model);
GtkListStore *
gnc_tree_model_split_reg_get_numact_list(GncTreeModelSplitReg *model);
GtkListStore *
gnc_tree_model_split_reg_get_acct_list(GncTreeModelSplitReg *model);
void
gnc_tree_model_split_reg_get_num_list(GncTreeModelSplitReg *model);
void
gnc_tree_model_split_reg_get_action_list(GncTreeModelSplitReg *model);
gboolean
gnc_tree_model_split_reg_get_split_and_trans (
GncTreeModelSplitReg *model, GtkTreeIter *iter,
gboolean *is_trow1, gboolean *is_trow2, gboolean *is_split,
gboolean *is_blank, Split **split, Transaction **trans);
G_END_DECLS
#endif /* __GNC_TREE_MODEL_SPLIT_REG_H */
/** @} */
/** @} */
File diff suppressed because it is too large. Load diff
+69
View File
@@ -0,0 +1,69 @@
/********************************************************************\
* gnc-tree-view-split-reg.c -- GtkTreeView implementation to *
* display registers in a GtkTreeView. *
* *
* Copyright (C) 2012 Robert Fewell *
* Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker@cox.net> *
* *
* 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 *
* *
\********************************************************************/
#ifndef __GNC_TREE_VIEW_SPLIT_REG_H
#define __GNC_TREE_VIEW_SPLIT_REG_H
#include <gtk/gtk.h>
#include "gnc-tree-view.h"
#include "gnc-tree-model-split-reg.h"
#include "gnc-ui-util.h"
G_BEGIN_DECLS
#define GNC_TYPE_TREE_VIEW_SPLIT_REG (gnc_tree_view_split_reg_get_type ())
#define GNC_TREE_VIEW_SPLIT_REG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitReg))
#define GNC_TREE_VIEW_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitRegClass))
#define GNC_IS_TREE_VIEW_SPLIT_REG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG))
#define GNC_IS_TREE_VIEW_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_VIEW_SPLIT_REG))
#define GNC_TREE_VIEW_SPLIT_REG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitRegClass))
/* typedefs & structures */
typedef struct GncTreeViewSplitRegPrivate GncTreeViewSplitRegPrivate;
typedef struct
{
GncTreeView gnc_tree_view;
GncTreeViewSplitRegPrivate *priv;
int stamp;
} GncTreeViewSplitReg;
typedef struct
{
GncTreeViewClass gnc_tree_view;
} GncTreeViewSplitRegClass;
/* Standard g_object type */
GType gnc_tree_view_split_reg_get_type(void);
GncTreeViewSplitReg *gnc_tree_view_split_reg_new_with_model(GncTreeModelSplitReg *model);
G_END_DECLS
#endif /* __GNC_TREE_VIEW_SPLIT_REG_H */
+68
View File
@@ -43,6 +43,7 @@
#include "gnc-gconf-utils.h"
#include "gnc-gnome-utils.h"
#include "gnc-gobject-utils.h"
#include "gnc-cell-renderer-date.h"
/* The column id refers to a specific column in the tree model. It is
* also attached to the side of the tree column to allow lookup of a
@@ -1987,6 +1988,73 @@ gnc_tree_view_add_text_column (GncTreeView *view,
return column;
}
/** This function adds a new date column to a GncTreeView base view.
* It takes all the parameters necessary to hook a GtkTreeModel
* column to a GtkTreeViewColumn. If the tree has a gconf section
* associated with it, this function also wires up the column so that
* its visibility and width are remembered.
*
* Parameters are defined in gnc-tree-view.h
*/
GtkTreeViewColumn *
gnc_tree_view_add_date_column (GncTreeView *view,
const gchar *column_title,
const gchar *pref_name,
const gchar *stock_icon_name,
const gchar *sizing_text,
gint model_data_column,
gint model_visibility_column,
GtkTreeIterCompareFunc column_sort_fn)
{
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
PangoLayout* layout;
int default_width, title_width;
g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, column_title);
/* Set up an icon renderer if requested */
if (stock_icon_name) {
renderer = gtk_cell_renderer_pixbuf_new ();
g_object_set (renderer, "stock-id", stock_icon_name, NULL);
gtk_tree_view_column_pack_start (column, renderer, FALSE);
}
/* Set up a text renderer and attributes */
renderer = gnc_cell_renderer_date_new(TRUE);
gtk_tree_view_column_pack_start (column, renderer, TRUE);
/* Set renderer attributes controlled by the model */
if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
gtk_tree_view_column_add_attribute (column, renderer,
"text", model_data_column);
if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
gtk_tree_view_column_add_attribute (column, renderer,
"visible", model_visibility_column);
/* Default size is the larger of the column title and the sizing text */
layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
pango_layout_get_pixel_size(layout, &title_width, NULL);
g_object_unref(layout);
layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
pango_layout_get_pixel_size(layout, &default_width, NULL);
g_object_unref(layout);
default_width = MAX(default_width, title_width);
if (default_width)
default_width += 10; /* padding on either side */
gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
default_width, TRUE, column_sort_fn);
gnc_tree_view_append_column (view, column);
return column;
}
GtkTreeViewColumn *
gnc_tree_view_add_combo_column (GncTreeView *view,
const gchar *column_title,
+17
View File
@@ -33,6 +33,7 @@
#define __GNC_TREE_VIEW_H
#include <gtk/gtk.h>
#include "gnc-cell-renderer-date.h"
G_BEGIN_DECLS
@@ -208,6 +209,22 @@ gnc_tree_view_add_combo_column (GncTreeView *view,
gint combo_model_text_column,
GtkTreeIterCompareFunc column_sort_fn);
/** This function adds a new date column to a GncTreeView base
* view. The parameters it takes in common with
* gnc_tree_view_add_text_column() behave the same as there.
*/
GtkTreeViewColumn *
gnc_tree_view_add_date_column (GncTreeView *view,
const gchar *column_title,
const gchar *pref_name,
const gchar *stock_icon_name,
const gchar *sizing_text,
gint model_data_column,
gint model_visibility_column,
GtkTreeIterCompareFunc column_sort_fn);
/** This function adds a new numeric column to a GncTreeView base
* view. It takes all the parameters necessary to hook a
* GtkTreeModel column to a GtkTreeViewColumn. If the tree has a
+4
View File
@@ -45,10 +45,12 @@ libgnc_gnome_la_SOURCES = \
gnc-plugin-basic-commands.c \
gnc-plugin-budget.c \
gnc-plugin-register.c \
gnc-plugin-register2.c \
gnc-plugin-page-account-tree.c \
gnc-plugin-page-budget.c \
gnc-plugin-page-sx-list.c \
gnc-plugin-page-register.c \
gnc-plugin-page-register2.c \
gnc-split-reg.c \
reconcile-list.c \
top-level.c \
@@ -81,10 +83,12 @@ noinst_HEADERS = \
gnc-plugin-basic-commands.h \
gnc-plugin-budget.h \
gnc-plugin-register.h \
gnc-plugin-register2.h \
gnc-plugin-page-account-tree.h \
gnc-plugin-page-budget.h \
gnc-plugin-page-sx-list.h \
gnc-plugin-page-register.h \
gnc-plugin-page-register2.h \
gnc-split-reg.h \
reconcile-list.h \
top-level.h \
+46 -1
View File
@@ -38,6 +38,7 @@
#include <glib/gi18n.h>
#include "gnc-plugin-page-account-tree.h"
#include "gnc-plugin-page-register.h"
#include "gnc-plugin-page-register2.h"
#include "Scrub.h"
#include "Scrub3.h"
@@ -146,6 +147,8 @@ static void gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPlugin
static void gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page);
static void gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page);
/* Command callback for new Register Test */
static void gnc_plugin_page_account_tree_cmd_open2_account (GtkAction *action, GncPluginPageAccountTree *page);
static guint plugin_page_signals[LAST_SIGNAL] = { 0 };
@@ -171,6 +174,11 @@ static GtkActionEntry gnc_plugin_page_account_tree_actions [] =
N_("Open the selected account"),
G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_account)
},
{
"FileOpenAccount2Action", GNC_STOCK_OPEN_ACCOUNT, N_("Open New Register2 _Account"), NULL,
N_("Open the New Register2 selected account"),
G_CALLBACK (gnc_plugin_page_account_tree_cmd_open2_account)
},
{
"FileOpenSubaccountsAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Subaccounts"), NULL,
N_("Open the selected account and all its subaccounts"),
@@ -263,6 +271,7 @@ static const gchar *actions_requiring_account_rw[] =
static const gchar *actions_requiring_account_always[] =
{
"FileOpenAccountAction",
"FileOpenAccount2Action",
"FileOpenSubaccountsAction",
"ActionsLotsAction",
NULL
@@ -290,6 +299,7 @@ static const gchar* readonly_inactive_actions[] =
static action_toolbar_labels toolbar_labels[] =
{
{ "FileOpenAccountAction", N_("Open") },
{ "FileOpenAccount2Action", N_("Open2") },
{ "EditEditAccountAction", N_("Edit") },
{ "FileNewAccountAction", N_("New") },
{ "EditDeleteAccountAction", N_("Delete") },
@@ -775,8 +785,29 @@ gppat_open_account_common (GncPluginPageAccountTree *page,
gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
}
/*#####################################################################*/
/* New Register Common */
static void
gnc_plugin_page_account_tree_double_click_cb (GtkTreeView *treeview,
gppat_open2_account_common (GncPluginPageAccountTree *page,
Account *account,
gboolean include_subs)
{
GncPluginPageAccountTreePrivate *priv;
GtkWidget *window;
GncPluginPage *new_page;
if (account == NULL)
return;
priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
window = GNC_PLUGIN_PAGE (page)->window;
new_page = gnc_plugin_page_register2_new (account, include_subs);
gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
}
/*######################################################################*/
static void
gnc_plugin_page_account_tree_double_click_cb (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *col,
GncPluginPageAccountTree *page)
@@ -882,6 +913,20 @@ gnc_plugin_page_account_tree_cmd_open_account (GtkAction *action,
gppat_open_account_common (page, account, FALSE);
}
/*#####################################################################*/
/* Register Firing - Single Account to start with */
static void
gnc_plugin_page_account_tree_cmd_open2_account (GtkAction *action,
GncPluginPageAccountTree *page)
{
Account *account;
g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
account = gnc_plugin_page_account_tree_get_current_account (page);
gppat_open2_account_common (page, account, FALSE);
}
/*#####################################################################*/
static void
gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action,
GncPluginPageAccountTree *page)
File diff suppressed because it is too large. Load diff
+151
View File
@@ -0,0 +1,151 @@
/**********************************************************************
* gnc-plugin-page-register2.h -- register page functions *
* *
* Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de> *
* Copyright (C) 2003,2005,2006 David Hampton <hampton@employees.org> *
* *
* 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 *
**********************************************************************/
/** @addtogroup ContentPlugins
@{ */
/** @addtogroup Register2Plugin Register2 Page
@{ */
/** @file gnc-plugin-page-register.h
@brief Functions providing a register page for the GnuCash UI
@author Copyright (C) 2003 Jan Arne Petersen <jpetersen@uni-bonn.de>
@author Copyright (C) 2003 David Hampton <hampton@employees.org>
*/
#ifndef __GNC_PLUGIN_PAGE_REGISTER2_H
#define __GNC_PLUGIN_PAGE_REGISTER2_H
#include <gtk/gtk.h>
#include "Account.h"
#include "gnc-ledger-display.h"
#include "gnc-plugin-page.h"
#include "gnc-split-reg.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_PLUGIN_PAGE_REGISTER2 (gnc_plugin_page_register2_get_type ())
#define GNC_PLUGIN_PAGE_REGISTER2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2))
#define GNC_PLUGIN_PAGE_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2Class))
#define GNC_IS_PLUGIN_PAGE_REGISTER2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2))
#define GNC_IS_PLUGIN_PAGE_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_REGISTER2))
#define GNC_PLUGIN_PAGE_REGISTER2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2Class))
#define GNC_PLUGIN_PAGE_REGISTER2_NAME "GncPluginPageRegister2"
/* typedefs & structures */
typedef struct
{
GncPluginPage gnc_plugin_page;
} GncPluginPageRegister2;
typedef struct
{
GncPluginPageClass gnc_plugin_page;
} GncPluginPageRegister2Class;
/* function prototypes */
/** Retrieve the type number for the plugin page.
*
* @return The type number.
*/
GType gnc_plugin_page_register2_get_type (void);
/** Create a new "register" plugin page, given a pointer to an
* account.
*
* @param account The pointer to the account to embed in the
* register.
*
* @param subaccounts TRUE if all the sub-accounts of the specified
* account should be included in the register.
*
* @return The newly created plugin page.
*/
GncPluginPage *
gnc_plugin_page_register2_new (Account *account, gboolean subaccounts);
/** Create a new "register" plugin page, given a pointer to an already
* created ledger. This function should be used when the ledger
* already exists. (E.G. From the "find transaction" code, or from
* the scheduled transaction code.)
*
* @param ledger The pointer to the ledger to embed into the
* register.
*
* @return The newly created plugin page.
*/
GncPluginPage *
gnc_plugin_page_register2_new_ledger (GNCLedgerDisplay *ledger);
/** Create a new "register" plugin page containing a general ledger.
*
* @return The newly created plugin page.
*/
GncPluginPage *
gnc_plugin_page_register2_new_gl (void);
/** Set various register options on a newly created "register" plugin page.
*
* @param plugin_page The "register" page to modify.
*
* @param lines_default Used to calculate the minimum preferred height of
* the plugin page.
*
* @param read_only True if the register should be read-only.
*/
void
gnc_plugin_page_register2_set_options (GncPluginPage *plugin_page,
gint lines_default,
gboolean read_only);
/** Get the GNCSplitReg data structure associated with this register page.
*
* @param plugin_page A "register" page.
*/
GNCSplitReg *
gnc_plugin_page_register2_get_gsr (GncPluginPage *plugin_page);
/** Get the Account associated with this register page.
*
* @param page A "register" page.
*
* @return The account if the register contains only a single
* account, or an account and its sub-accounts. NULL otherwise.
*/
Account *
gnc_plugin_page_register2_get_account (GncPluginPageRegister2 *page);
G_END_DECLS
/** @} */
/** @} */
#endif /* __GNC_PLUGIN_PAGE_REGISTER2_H */
+202
View File
@@ -0,0 +1,202 @@
/*
* gnc-plugin-register2.c --
*
* Copyright (C) 2003 Jan Arne Petersen
* Author: Jan Arne Petersen <jpetersen@uni-bonn.de>
*
* 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
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <string.h>
#include "gnc-component-manager.h"
#include "gnc-plugin-register2.h"
#include "gnc-plugin-page-register2.h"
static void gnc_plugin_register2_class_init (GncPluginRegister2Class *klass);
static void gnc_plugin_register2_init (GncPluginRegister2 *plugin);
static void gnc_plugin_register2_finalize (GObject *object);
/* Command callbacks */
static void gnc_plugin_register2_cmd_general_ledger (GtkAction *action, GncMainWindowActionData *data);
#define PLUGIN_ACTIONS_NAME "gnc-plugin-register2-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-register2-ui.xml"
#define GCONF_REGISTER2_SECTION "general/register"
static GtkActionEntry gnc_plugin_actions [] =
{
{
"ToolsGeneralLedgerAction", NULL, N_("_General Ledger"), NULL,
N_("Open a general ledger window"),
G_CALLBACK (gnc_plugin_register2_cmd_general_ledger)
},
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
typedef struct GncPluginRegister2Private
{
gpointer dummy;
} GncPluginRegister2Private;
#define GNC_PLUGIN_REGISTER2_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Private))
static GObjectClass *parent_class = NULL;
static QofLogModule log_module = GNC_MOD_GUI;
/************************************************************
* Other Functions *
************************************************************/
/** This function is called whenever an entry in the general register
* section of gconf is changed. It does nothing more than kick off a
* gui refresh which should be delivered to any open register page.
* The register pages will then reread their settings from gconf and
* update the screen.
*
* @client Unused.
*
* @cnxn_id Unused.
*
* @entry Unused.
*
* @user_data Unused.
*/
static void
gnc_plugin_register2_gconf_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
gpointer user_data)
{
ENTER("");
gnc_gui_refresh_all ();
LEAVE("");
}
/************************************************************
* Object Implementation *
************************************************************/
GType
gnc_plugin_register2_get_type (void)
{
static GType gnc_plugin_register2_type = 0;
if (gnc_plugin_register2_type == 0)
{
static const GTypeInfo our_info =
{
sizeof (GncPluginRegister2Class),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gnc_plugin_register2_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncPluginRegister2),
0, /* n_preallocs */
(GInstanceInitFunc) gnc_plugin_register2_init
};
gnc_plugin_register2_type = g_type_register_static (GNC_TYPE_PLUGIN,
"GncPluginRegister2",
&our_info, 0);
}
return gnc_plugin_register2_type;
}
GncPlugin *
gnc_plugin_register2_new (void)
{
GncPluginRegister2 *plugin;
/* Reference the register page plugin to ensure it exists in
* the gtk type system. */
GNC_TYPE_PLUGIN_PAGE_REGISTER2;
plugin = g_object_new (GNC_TYPE_PLUGIN_REGISTER2,
NULL);
return GNC_PLUGIN (plugin);
}
static void
gnc_plugin_register2_class_init (GncPluginRegister2Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gnc_plugin_register2_finalize;
/* plugin info */
plugin_class->plugin_name = GNC_PLUGIN_REGISTER2_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->ui_filename = PLUGIN_UI_FILENAME;
plugin_class->gconf_section = GCONF_REGISTER2_SECTION;
plugin_class->gconf_notifications = gnc_plugin_register2_gconf_changed;
g_type_class_add_private(klass, sizeof(GncPluginRegister2Private));
}
static void
gnc_plugin_register2_init (GncPluginRegister2 *plugin)
{
}
static void
gnc_plugin_register2_finalize (GObject *object)
{
GncPluginRegister2 *plugin;
GncPluginRegister2Private *priv;
g_return_if_fail (GNC_IS_PLUGIN_REGISTER2 (object));
plugin = GNC_PLUGIN_REGISTER2 (object);
priv = GNC_PLUGIN_REGISTER2_GET_PRIVATE(plugin);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/************************************************************
* Command Callbacks *
************************************************************/
static void
gnc_plugin_register2_cmd_general_ledger (GtkAction *action,
GncMainWindowActionData *data)
{
GncPluginPage *page;
g_return_if_fail (data != NULL);
page = gnc_plugin_page_register2_new_gl ();
gnc_main_window_open_page (data->window, page);
}
+60
View File
@@ -0,0 +1,60 @@
/*
* gnc-plugin-register2.h --
*
* Copyright (C) 2003 Jan Arne Petersen
* Author: Jan Arne Petersen <jpetersen@uni-bonn.de>
*
* 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
*/
#ifndef __GNC_PLUGIN_REGISTER2_H
#define __GNC_PLUGIN_REGISTER2_H
#include "gnc-plugin.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_PLUGIN_REGISTER2 (gnc_plugin_register2_get_type ())
#define GNC_PLUGIN_REGISTER2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2))
#define GNC_PLUGIN_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Class))
#define GNC_IS_PLUGIN_REGISTER2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_REGISTER2))
#define GNC_IS_PLUGIN_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_REGISTER2))
#define GNC_PLUGIN_REGISTER2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Class))
#define GNC_PLUGIN_REGISTER2_NAME "gnc-plugin-register2"
/* typedefs & structures */
typedef struct
{
GncPlugin gnc_plugin;
} GncPluginRegister2;
typedef struct
{
GncPluginClass gnc_plugin;
} GncPluginRegister2Class;
/* function prototypes */
GType gnc_plugin_register2_get_type (void);
GncPlugin *gnc_plugin_register2_new (void);
G_END_DECLS
#endif /* __GNC_PLUGIN_REGISTER2_H */
+4
View File
@@ -51,8 +51,10 @@
#include "gnc-plugin-basic-commands.h" /* FIXME Remove this line*/
#include "gnc-plugin-file-history.h" /* FIXME Remove this line*/
#include "gnc-plugin-register.h" /* FIXME Remove this line*/
#include "gnc-plugin-register2.h" /* FIXME Remove this line*/
#include "gnc-plugin-budget.h"
#include "gnc-plugin-page-register.h"
#include "gnc-plugin-page-register2.h"
#include "gnc-plugin-manager.h" /* FIXME Remove this line*/
#include "gnc-html.h"
#include "gnc-gnome-utils.h"
@@ -417,6 +419,8 @@ gnc_main_gui_init (void)
gnc_plugin_manager_get (), gnc_plugin_menu_additions_new ());
gnc_plugin_manager_add_plugin (
gnc_plugin_manager_get (), gnc_plugin_register_new ());
gnc_plugin_manager_add_plugin (
gnc_plugin_manager_get (), gnc_plugin_register2_new ());
/* I'm not sure why the FIXME note says to remove this. Maybe
each module should be adding its own plugin to the manager?
Anyway... Oh, maybe... nah */
+2
View File
@@ -7,7 +7,9 @@ ui_DATA = \
gnc-plugin-page-account-tree-ui.xml \
gnc-plugin-file-history-ui.xml \
gnc-plugin-register-ui.xml \
gnc-plugin-register2-ui.xml \
gnc-plugin-page-register-ui.xml \
gnc-plugin-page-register2-ui.xml \
gnc-plugin-page-sx-list-ui.xml \
gnc-plugin-page-sxregister-ui.xml \
gnc-sxed-to-create-window-ui.xml \
@@ -7,6 +7,7 @@
<menuitem name="EditRenumberSubaccounts" action="EditRenumberSubaccountsAction"/>
<separator name="EditSep2"/>
<menuitem name="FileOpenAccount" action="FileOpenAccountAction"/>
<menuitem name="FileOpenAccount2" action="FileOpenAccount2Action"/>
<menuitem name="FileOpenSubaccounts" action="FileOpenSubaccountsAction"/>
</placeholder>
</menu>
@@ -34,6 +35,7 @@
<popup name="MainPopup" action="FakeToplevel">
<placeholder name="PopupPlaceholder2">
<menuitem name="AccountOpenAccount" action="FileOpenAccountAction"/>
<menuitem name="AccountOpenAccount2" action="FileOpenAccount2Action"/>
<menuitem name="AccountOpenSubaccounts" action="FileOpenSubaccountsAction"/>
<menuitem name="AccountEditAccount" action="EditEditAccountAction"/>
<separator name="AccountSep1"/>
@@ -60,6 +62,7 @@
<placeholder name="DefaultToolbarPlaceholder">
<separator name="ToolbarSep2"/>
<toolitem name="ToolbarOpenAccount" action="FileOpenAccountAction"/>
<toolitem name="ToolbarOpenAccount2" action="FileOpenAccount2Action"/>
<toolitem name="ToolbarEditAccount" action="EditEditAccountAction"/>
<separator name="ToolbarSep3"/>
<toolitem name="ToolbarNewAccount" action="FileNewAccountAction"/>
@@ -0,0 +1,104 @@
<ui>
<menubar>
<menu name="Edit" action="EditAction">
<placeholder name="EditAllSelectedPlaceholder">
<menuitem name="EditEditAccount" action="EditEditAccountAction"/>
</placeholder>
</menu>
<menu name="Transaction" action="TransactionAction">
<menuitem name="CutTransaction" action="CutTransactionAction"/>
<menuitem name="CopyTransaction" action="CopyTransactionAction"/>
<menuitem name="PasteTransaction" action="PasteTransactionAction"/>
<menuitem name="DuplicateTransaction" action="DuplicateTransactionAction"/>
<menuitem name="DeleteTransaction" action="DeleteTransactionAction"/>
<menuitem name="RemoveTransactionSplits" action="RemoveTransactionSplitsAction"/>
<!--menuitem name="ShiftTransactionForward" action="ShiftTransactionForwardAction"/-->
<separator name="TransactionSep1"/>
<menuitem name="RecordTransaction" action="RecordTransactionAction"/>
<menuitem name="CancelTransaction" action="CancelTransactionAction"/>
<separator name="TransactionSep2"/>
<menuitem name="VoidTransaction" action="VoidTransactionAction"/>
<menuitem name="UnvoidTransaction" action="UnvoidTransactionAction"/>
<menuitem name="ReverseTransaction" action="ReverseTransactionAction"/>
</menu>
<menu name="View" action="ViewAction">
<placeholder name="ViewContentPlaceholder">
<menuitem name="ViewStyleBasic" action="ViewStyleBasicAction"/>
<menuitem name="ViewStyleAutoSplit" action="ViewStyleAutoSplitAction"/>
<menuitem name="ViewStyleJournal" action="ViewStyleJournalAction"/>
<separator name="ViewSep44"/>
<menuitem name="ViewStyleDoubleLine" action="ViewStyleDoubleLineAction"/>
</placeholder>
</menu>
<menu name="Actions" action="ActionsAction">
<placeholder name="ActionsPlaceholder">
<separator name="ActionsSep1"/>
<menuitem name="ActionsTransfer" action="ActionsTransferAction"/>
<menuitem name="ActionsReconcile" action="ActionsReconcileAction"/>
<menuitem name="ActionsStockSplit" action="ActionsStockSplitAction"/>
<menuitem name="ActionLots" action="ActionsLotsAction"/>
<separator name="ActionsSep4"/>
<menuitem name="BlankTransaction" action="BlankTransactionAction"/>
<menuitem name="SplitTransaction" action="SplitTransactionAction"/>
<menuitem name="EditExchangeRate" action="EditExchangeRateAction"/>
<menuitem name="ScheduleTransaction" action="ScheduleTransactionAction"/>
<menuitem name="JumpTransaction" action="JumpTransactionAction"/>
<separator name="ActionsSep5"/>
</placeholder>
<menu name="ScrubMenu" action="ScrubMenuAction">
<menuitem name="ScrubAll" action="ScrubAllAction"/>
<menuitem name="ScrubCurrent" action="ScrubCurrentAction"/>
</menu>
</menu>
<menu name="Reports" action="ReportsAction">
<placeholder name="AccountReports">
<menuitem name="ReportsAccountReport" action="ReportsAccountReportAction"/>
<menuitem name="ReportsAcctTransReport" action="ReportsAcctTransReportAction"/>
</placeholder>
</menu>
</menubar>
<toolbar name="DefaultToolbar">
<placeholder name="DefaultToolbarPlaceholder">
<toolitem name="ToolbarDuplicateTransaction" action="DuplicateTransactionAction"/>
<toolitem name="ToolbarDeleteTransaction" action="DeleteTransactionAction"/>
<separator name="ToolbarSep66"/>
<toolitem name="ToolbarRecordTransaction" action="RecordTransactionAction"/>
<toolitem name="ToolbarCancelTransaction" action="CancelTransactionAction"/>
<separator name="ToolbarSep67"/>
<toolitem name="ToolbarBlankTransaction" action="BlankTransactionAction"/>
<toolitem name="ToolbarSplitTransaction" action="SplitTransactionAction"/>
<toolitem name="ToolbarJumpTransaction" action="JumpTransactionAction"/>
<toolitem name="ToolbarScheduleTransaction" action="ScheduleTransactionAction"/>
<separator name="ToolbarSep68"/>
<toolitem name="ToolbarTransfer" action="ActionsTransferAction"/>
<toolitem name="ActionsReconcile" action="ActionsReconcileAction"/>
</placeholder>
</toolbar>
<popup name="MainPopup" action="FakeToplevel">
<placeholder name="PopupPlaceholder1">
<menuitem name="ViewSortBy" action="ViewSortByAction"/>
<menuitem name="ViewFilterBy" action="ViewFilterByAction"/>
</placeholder>
<placeholder name="PopupPlaceholder2">
<menuitem name="DuplicateTransaction" action="DuplicateTransactionAction"/>
<menuitem name="DeleteTransaction" action="DeleteTransactionAction"/>
<menuitem name="RemoveTransactionSplits" action="RemoveTransactionSplitsAction"/>
<!--menuitem name="ShiftTransactionForward" action="ShiftTransactionForwardAction"/-->
<separator name="PopupSep2"/>
<menuitem name="RecordTransaction" action="RecordTransactionAction"/>
<menuitem name="CancelTransaction" action="CancelTransactionAction"/>
<separator name="PopupSep3"/>
<menuitem name="BlankTransaction" action="BlankTransactionAction"/>
<menuitem name="SplitTransaction" action="SplitTransactionAction"/>
<menuitem name="EditExchangeRate" action="EditExchangeRateAction"/>
<menuitem name="ScheduleTransaction" action="ScheduleTransactionAction"/>
<menuitem name="JumpTransaction" action="JumpTransactionAction"/>
</placeholder>
</popup>
</ui>
+9
View File
@@ -0,0 +1,9 @@
<ui>
<menubar>
<menu name="Tools" action="ToolsAction">
<placeholder name="ToolsPlaceholder">
<menuitem name="ToolsGeneralLedger" action="ToolsGeneralLedgerAction"/>
</placeholder>
</menu>
</menubar>
</ui>