mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
plotting routines
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@605 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
b4c00c97fa
commit
1903c5b9a2
8
src/gnome/graph/Makefile
Normal file
8
src/gnome/graph/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
### Makefile
|
||||
|
||||
CFLAGS := -Wall -O2 -g -I../../engine -I ../../../
|
||||
|
||||
GTK_LIBS := -lgtk -lgdk -lglib
|
||||
LOADLIBES := -lplot -L/usr/X11R6/lib ${GTK_LIBS} -lXaw -lXt -lXext -lX11 -lm
|
||||
|
||||
plot-test: ../../libengine.a plot-test.o
|
49
src/gnome/graph/design.txt
Normal file
49
src/gnome/graph/design.txt
Normal file
@ -0,0 +1,49 @@
|
||||
* From: Rob Browning <rlb@cs.utexas.edu>
|
||||
|
||||
|
||||
For those of you interested, below is an extremely simple example of a
|
||||
tiny standalone program that can read an .xac file (specified as the
|
||||
first argument and then let you select accounts to plot from a Gtk
|
||||
window. The plot is just a per-transaction running balance, but it's
|
||||
a start. You need Gtk and plotutils 2.0 installed for this to work.
|
||||
I just put these files in a new directory src/graph. There's a
|
||||
Makefile and plot-test.c.
|
||||
|
||||
Issues:
|
||||
|
||||
This program is trivial, and it only works via a Gtk GUI, but I think
|
||||
that in the end we should support both interactive and non-interactive
|
||||
operation of our graphing and reporting tools. Whether this happens
|
||||
via special arguments to xacc, or by providing separate standalone
|
||||
programs that link to a common library (libxaccplot?) I don't know,
|
||||
but either way, I think we need both.
|
||||
|
||||
This little program generates the graph by launching a child "graph"
|
||||
process (graph is part of the plotutils package). I don't set any
|
||||
axis labels or anything. This could obviously be improved, but there
|
||||
are limits to how flexible the graph program is. It can't, for
|
||||
example, do pie or bar charts at the moment.
|
||||
|
||||
However, the lower level library (libplot) that it's based on will
|
||||
allow us to do whatever we want. In that case, though, we have to do
|
||||
the scaling, drawing, etc, ourselves, so I think we're better off to
|
||||
use "graph" for now, and go back and re-implement things in libplot,
|
||||
adding bells and whistles and other types of graphs later. I did
|
||||
create libplot code for simple bars in a bargraph just to make sure I
|
||||
though it would be feasible.
|
||||
|
||||
The other disadvantage to calling graph (as opposed to using libplot
|
||||
directly) is that it brings up it's own independent X window on each
|
||||
invocation. This can also be overcome by switching to the more
|
||||
primitive libplot, where you can specify your own X drawable as the
|
||||
output device.
|
||||
|
||||
I've actually contacted the plotutils author about providing the more
|
||||
sophisticated "graph" level plotting behaviors (autoscaling, etc.) as
|
||||
part of a library (libplotutils) rather than only as a standalone
|
||||
program. My guess is that this will happen, but I haven't heard back
|
||||
yet.
|
||||
|
||||
--
|
||||
Rob Browning <rlb@cs.utexas.edu>
|
||||
PGP fingerprint = E8 0E 0D 04 F5 21 A0 94 53 2B 97 F5 D6 4E 39 30
|
147
src/gnome/graph/plot-test.c
Normal file
147
src/gnome/graph/plot-test.c
Normal file
@ -0,0 +1,147 @@
|
||||
/* File: plot-test.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <plot.h>
|
||||
|
||||
#include <Account.h>
|
||||
#include <LedgerUtils.h>
|
||||
#include <FileIO.h>
|
||||
|
||||
static int
|
||||
graph_balance(Split **splits) {
|
||||
|
||||
FILE *child = popen("graph -T X", "w");
|
||||
int i = 0;
|
||||
|
||||
assert(child != NULL);
|
||||
|
||||
while(*splits) {
|
||||
const double split_balance = xaccGetBalance(*splits);
|
||||
fprintf(child, "%d %f\n", i, split_balance);
|
||||
i++;
|
||||
splits++;
|
||||
}
|
||||
pclose(child);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
destroy() {
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
static void
|
||||
graph_account_balance_per_transaction(gpointer item, gpointer user_data) {
|
||||
Account *acct = (Account *)
|
||||
gtk_object_get_data(GTK_OBJECT(item), "acct_ptr");
|
||||
|
||||
fprintf(stderr, "%s\n", acct->accountName);
|
||||
|
||||
xaccRecomputeBalance(acct);
|
||||
{
|
||||
Account *list[] = { acct, NULL };
|
||||
Split **splits = accListGetSortedSplits(list);
|
||||
graph_balance(splits);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
plot(GtkButton *button, gpointer data) {
|
||||
GtkWidget *list = GTK_WIDGET(data);
|
||||
GList *selection = GTK_LIST(list)->selection;
|
||||
g_list_foreach(selection, mangle_account, NULL);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
make_main_window(GtkWidget **list) {
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *quit_button;
|
||||
GtkWidget *plot_button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
*list = gtk_list_new();
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (window), "destroy",
|
||||
GTK_SIGNAL_FUNC (destroy), NULL);
|
||||
gtk_container_border_width (GTK_CONTAINER (window), 3);
|
||||
|
||||
quit_button = gtk_button_new_with_label ("Quit");
|
||||
|
||||
gtk_signal_connect_object (GTK_OBJECT (quit_button), "clicked",
|
||||
GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
GTK_OBJECT (window));
|
||||
|
||||
plot_button = gtk_button_new_with_label ("Plot");
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (plot_button), "clicked",
|
||||
GTK_SIGNAL_FUNC (plot), *list);
|
||||
|
||||
vbox = gtk_vbox_new(FALSE, 0);
|
||||
gtk_container_add (GTK_CONTAINER(window), vbox);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox), *list, FALSE, FALSE, 0);
|
||||
gtk_box_pack_end(GTK_BOX(vbox), quit_button, FALSE, FALSE, 0);
|
||||
gtk_box_pack_end(GTK_BOX(vbox), plot_button, FALSE, FALSE, 0);
|
||||
|
||||
gtk_widget_show (*list);
|
||||
gtk_widget_show (plot_button);
|
||||
gtk_widget_show (quit_button);
|
||||
gtk_widget_show(vbox);
|
||||
gtk_widget_show (window);
|
||||
|
||||
return(window);
|
||||
}
|
||||
|
||||
static void
|
||||
add_accounts_to_list(GtkWidget *list, const char *filename) {
|
||||
AccountGroup *db = xaccReadAccountGroup(filename);
|
||||
if(!db) {
|
||||
fprintf(stderr, "db: %p error: %d\n", db, xaccGetFileIOError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
{
|
||||
int count = xaccGetNumAccounts(db);
|
||||
int i;
|
||||
GtkWidget *item;
|
||||
|
||||
for(i=0; i<count; i++) {
|
||||
Account *acc = getAccount(db, i);
|
||||
item = gtk_list_item_new_with_label(acc->accountName);
|
||||
gtk_object_set_data(GTK_OBJECT(item), "acct_ptr", acc);
|
||||
gtk_container_add(GTK_CONTAINER(list), item);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
int handle;
|
||||
char *filename;
|
||||
GtkWidget *main_win;
|
||||
GtkWidget *display_area;
|
||||
GtkWidget *list = NULL;
|
||||
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr, "usage: plot-test filename\n");
|
||||
exit(1);
|
||||
}
|
||||
filename = argv[1];
|
||||
|
||||
main_win = make_main_window(&list);
|
||||
add_accounts_to_list(list, filename);
|
||||
|
||||
gtk_main();
|
||||
|
||||
return(0);
|
||||
}
|
Loading…
Reference in New Issue
Block a user