plotting routines

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@605 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-03-08 20:56:38 +00:00
parent b4c00c97fa
commit 1903c5b9a2
3 changed files with 204 additions and 0 deletions

8
src/gnome/graph/Makefile Normal file
View 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

View 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
View 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);
}