]>
Dogcows Code - chaz/homebank/blob - src/hb-export.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2018 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "hb-export.h"
23 /****************************************************************************/
25 /****************************************************************************/
34 /* our global datas */
35 extern struct HomeBank
*GLOBALS
;
36 extern struct Preferences
*PREFS
;
38 /* = = = = = = = = = = = = = = = = = = = = */
40 static void hb_export_qif_elt_txn(GIOChannel
*io
, Account
*acc
)
45 char amountbuf
[G_ASCII_DTOSTR_BUF_SIZE
];
49 elt
= g_string_sized_new(255);
53 list
= g_queue_peek_head_link(acc
->txn_queue
);
56 Transaction
*txn
= list
->data
;
61 g_date_set_julian (date
, txn
->date
);
63 switch(PREFS
->dtex_datefmt
)
66 g_string_append_printf (elt
, "D%02d/%02d/%04d\n",
67 g_date_get_month(date
),
73 g_string_append_printf (elt
, "D%02d/%02d/%04d\n",
75 g_date_get_month(date
),
80 g_string_append_printf (elt
, "D%04d/%02d/%02d\n",
81 g_date_get_year(date
),
82 g_date_get_month(date
),
88 //g_ascii_dtostr (amountbuf, sizeof (amountbuf), txn->amount);
89 g_ascii_formatd (amountbuf
, sizeof (amountbuf
), "%.2f", txn
->amount
);
90 g_string_append_printf (elt
, "T%s\n", amountbuf
);
93 if(txn
->status
== TXN_STATUS_CLEARED
)
96 if(txn
->status
== TXN_STATUS_RECONCILED
)
99 g_string_append_printf (elt
, "C%s\n", sbuf
);
101 if( txn
->paymode
== PAYMODE_CHECK
)
102 g_string_append_printf (elt
, "N%s\n", txn
->info
);
105 payee
= da_pay_get(txn
->kpay
);
107 g_string_append_printf (elt
, "P%s\n", payee
->name
);
110 g_string_append_printf (elt
, "M%s\n", txn
->memo
);
112 // LCategory of transaction
113 // L[Transfer account name]
114 // LCategory of transaction/Class of transaction
115 // L[Transfer account]/Class of transaction
116 if( txn
->paymode
== PAYMODE_INTXFER
&& txn
->kacc
== acc
->key
)
119 Account
*dstacc
= da_acc_get(txn
->kxferacc
);
121 g_string_append_printf (elt
, "L[%s]\n", dstacc
->name
);
125 cat
= da_cat_get(txn
->kcat
);
128 txt
= da_cat_get_fullname(cat
);
129 g_string_append_printf (elt
, "L%s\n", txt
);
135 count
= da_splits_count(txn
->splits
);
138 Split
*s
= txn
->splits
[i
];
140 cat
= da_cat_get(s
->kcat
);
143 txt
= da_cat_get_fullname(cat
);
144 g_string_append_printf (elt
, "S%s\n", txt
);
148 g_string_append_printf (elt
, "E%s\n", s
->memo
);
150 g_ascii_formatd (amountbuf
, sizeof (amountbuf
), "%.2f", s
->amount
);
151 g_string_append_printf (elt
, "$%s\n", amountbuf
);
154 g_string_append (elt
, "^\n");
157 list
= g_list_next(list
);
160 g_io_channel_write_chars(io
, elt
->str
, -1, NULL
, NULL
);
162 g_string_free(elt
, TRUE
);
170 static void hb_export_qif_elt_acc(GIOChannel
*io
, Account
*acc
)
175 elt
= g_string_sized_new(255);
178 //#987144 fixed account type
181 case ACC_TYPE_BANK
: type
= "Bank"; break;
182 case ACC_TYPE_CASH
: type
= "Cash"; break;
183 case ACC_TYPE_ASSET
: type
= "Oth A"; break;
184 case ACC_TYPE_CREDITCARD
: type
= "CCard"; break;
185 case ACC_TYPE_LIABILITY
: type
= "Oth L"; break;
186 default : type
= "Bank"; break;
189 g_string_assign(elt
, "!Account\n");
190 g_string_append_printf (elt
, "N%s\n", acc
->name
);
191 g_string_append_printf (elt
, "T%s\n", type
);
192 g_string_append (elt
, "^\n");
193 g_string_append_printf (elt
, "!Type:%s\n", type
);
195 g_io_channel_write_chars(io
, elt
->str
, -1, NULL
, NULL
);
197 g_string_free(elt
, TRUE
);
201 void hb_export_qif_account_single(gchar
*filename
, Account
*acc
)
205 io
= g_io_channel_new_file(filename
, "w", NULL
);
208 g_message("file error on: %s", filename
);
209 //retval = XML_IO_ERROR;
213 hb_export_qif_elt_acc(io
, acc
);
214 hb_export_qif_elt_txn(io
, acc
);
215 g_io_channel_unref (io
);
220 void hb_export_qif_account_all(gchar
*filename
)
225 io
= g_io_channel_new_file(filename
, "w", NULL
);
228 g_message("file error on: %s", filename
);
229 //retval = XML_IO_ERROR;
233 //todo: save accounts in order
234 //todo: save transfer transaction once
236 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
239 Account
*item
= list
->data
;
241 hb_export_qif_elt_acc(io
, item
);
242 hb_export_qif_elt_txn(io
, item
);
244 list
= g_list_next(list
);
248 g_io_channel_unref (io
);
254 /* = = = = = = = = beta feature version = = = = = = = = */
256 //static GtkPrintSettings *settings = NULL;
257 //static GtkPageSetup *page_setup = NULL;
260 static void papersize(PdfPrintContext
*ppc
)
262 //GList *list, *item;
266 DB( g_print("[papersize]\n") );
268 name
= gtk_paper_size_get_default();
270 DB( g_print("- def paper is %s\n", name
) );
272 ps
= gtk_paper_size_new(name
);
276 /*GtkPageSetup *new_page_setup;
278 if (settings == NULL)
279 settings = gtk_print_settings_new ();
281 new_page_setup = gtk_print_run_page_setup_dialog (NULL,
282 page_setup, settings);
285 g_object_unref (page_setup);
287 page_setup = new_page_setup;
291 gdouble w
, h
, mt
, mb
, ml
, mr
;
292 w
= gtk_paper_size_get_width(ps
, GTK_UNIT_MM
);
293 h
= gtk_paper_size_get_height(ps
, GTK_UNIT_MM
);
294 mt
= gtk_paper_size_get_default_top_margin(ps
, GTK_UNIT_MM
);
295 mr
= gtk_paper_size_get_default_right_margin(ps
, GTK_UNIT_MM
);
296 mb
= gtk_paper_size_get_default_bottom_margin(ps
, GTK_UNIT_MM
);
297 ml
= gtk_paper_size_get_default_left_margin(ps
, GTK_UNIT_MM
);
299 DB( g_print("- name: %s\n", gtk_paper_size_get_display_name(ps
)) );
300 DB( g_print("- w: %f (%f)\n- h: %f (%f)\n", w
, w
/PANGO_SCALE
, h
, h
/PANGO_SCALE
) );
301 DB( g_print("- margin: %f %f %f %f\n", mt
, mr
, mb
, ml
) );
312 gtk_paper_size_free(ps
);
314 /* list all paper size */
316 list = gtk_paper_size_get_paper_sizes (FALSE);
317 item = g_list_first(list);
323 g_print("- name: %s\n", gtk_paper_size_get_display_name(ps));
324 gtk_paper_size_free(ps);
326 item = g_list_next(item);
333 #define FONT "Helvetica 9px"
335 //#define PDF_MARGIN 24
336 #define PDF_COL_MARGIN 8
337 #define PDF_LINE_MARGIN 2
338 #define PDF_FONT_NORMAL 9
339 #define PDF_FONT_TITLE 12
345 #define HEX_R(xcol) (((xcol>>24) & 0xFF)/255)
346 #define HEX_G(xcol) (((xcol>>16) & 0xFF)/255)
347 #define HEX_B(xcol) (((xcol>> 8) & 0xFF)/255)
351 static void hb_pdf_draw_help_rect(cairo_t
*cr
, gint32 xcol
, double x
, double y
, double w
, double h
)
355 cairo_set_line_width(cr
, 1.0);
356 cairo_set_source_rgba(cr
, HEX_R(xcol
), HEX_G(xcol
), HEX_B(xcol
), 1.0); //alpha is unused for now
357 cairo_rectangle (cr
, x
, y
, w
, h
);
367 static void hb_pdf_draw_line(PdfPrintContext
*ppc
, cairo_t
*cr
, gdouble y
, gboolean bold
, gboolean rulehint
)
373 /* Create a PangoLayout, set the font and text */
374 layout
= pango_cairo_create_layout (cr
);
376 //desc = pango_font_description_from_string (FONT);
378 pango_font_description_set_weight(ppc
->desc
, PANGO_WEIGHT_BOLD
);
380 pango_font_description_set_weight(ppc
->desc
, PANGO_WEIGHT_NORMAL
);
382 pango_layout_set_font_description (layout
, ppc
->desc
);
391 cairo_set_source_rgb(cr
, 0.9, 0.9, 0.9);
392 cairo_rectangle (cr
, x
, y
, ppc
->w
- ppc
->ml
- ppc
->mr
, PDF_FONT_NORMAL
);
398 cairo_set_source_rgb(cr
, 0.0, 0.0, 0.0);
399 cairo_move_to(cr
, x
, y
);
401 for(i
=0;i
<PDF_NUMCOL
;i
++)
403 if(ppc
->column_txt
[i
] != NULL
)
407 pango_layout_set_text (layout
, ppc
->column_txt
[i
], -1);
408 pango_layout_get_size (layout
, &width
, &height
);
409 if( i
==1 || i
==2 || i
==3 )
411 pango_layout_set_width(layout
, ppc
->column_width
[i
]*PANGO_SCALE
);
412 pango_layout_set_ellipsize (layout
, PANGO_ELLIPSIZE_END
);
415 //cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
417 if( i
==0 || i
==4 || i
==6 ) // pad right: date/amount/balance
419 //if(*ppc->column_txt[i] != '-')
420 //cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.66); //grey
421 cairo_move_to(cr
, x
+ ppc
->column_width
[i
] - (width
/PANGO_SCALE
) , y
);
424 cairo_move_to(cr
, x
, y
);
426 pango_cairo_show_layout (cr
, layout
);
429 /*cairo_set_line_width(cr, 1.0);
430 cairo_move_to(cr, x, y + .5);
431 cairo_line_to(cr, x + ppc->column_width[i], y+.5);
436 x
+= ppc
->column_width
[i
] + PDF_COL_MARGIN
;
439 g_object_unref (layout
);
444 static void hb_pdf_set_col_title(PdfPrintContext
*ppc
)
446 ppc
->column_txt
[0] = _("Date");
447 ppc
->column_txt
[1] = _("Info");
448 ppc
->column_txt
[2] = _("Payee");
449 ppc
->column_txt
[3] = _("Memo");
450 ppc
->column_txt
[4] = _("Amount");
451 ppc
->column_txt
[5] = "C";
452 ppc
->column_txt
[6] = _("Balance");
456 void hb_export_pdf_listview(GtkTreeView
*treeview
, gchar
*filepath
, gchar
*accname
)
458 cairo_surface_t
*surf
;
461 PangoFontDescription
*desc
;
469 DB( g_print("[gtk-chart] export to pdf\n") );
471 model
= gtk_tree_view_get_model(treeview
);
475 //gchar *filename = "/home/max/Desktop/hb-txn-export.pdf";
476 double width
; //=210 * 2.83;
477 double height
; //=297 * 2.83;
482 surf
= cairo_pdf_surface_create (filepath
, width
, height
);
484 if( cairo_surface_status(surf
) != CAIRO_STATUS_SUCCESS
)
485 //todo: manage error later on
489 cr
= cairo_create (surf
);
490 //cairo_pdf_surface_set_size(surf, width * 2.83, height * 2.83);
492 //g_print("width=%d\n", cairo_image_surface_get_width( surf));
493 double x1
, x2
, y1
, y2
;
494 cairo_clip_extents (cr
, &x1
, &y1
, &x2
, &y2
);
496 DB( g_print("surface w=%f, h=%f\n", x2
- x1
, y2
- y1
) );
497 double pwidth
= x2
- x1
;
500 /* Create a PangoLayout, set the font and text */
501 layout
= pango_cairo_create_layout (cr
);
503 /* get and copy the font from the treeview widget */
504 gtk_style_context_get(gtk_widget_get_style_context(GTK_WIDGET(treeview
)), GTK_STATE_FLAG_NORMAL
, "font", &desc
, NULL
);
505 ppc
.desc
= pango_font_description_copy(desc
);
507 DB( g_print("family: %s\n", pango_font_description_get_family(desc
)) );
508 DB( g_print("size: %d (%d)\n", pango_font_description_get_size (desc
), pango_font_description_get_size (desc
)/PANGO_SCALE
) );
512 /* header is 1 line for date page number at top, then a title in bold, then 2 empty lines */
513 gint header_height
= PDF_FONT_NORMAL
* 2 + PDF_FONT_TITLE
;
514 gint nb_lines
= gtk_tree_model_iter_n_children(model
, NULL
);
516 /* should include here the headertitle line */
518 gint lpp
= floor ((height
-header_height
-ppc
.mt
-ppc
.mb
) / (PDF_FONT_NORMAL
+ PDF_LINE_MARGIN
));
519 gint page
, num_pages
= (nb_lines
- 1) / lpp
+ 1;
521 DB( g_print("\n - should pdf %d lines, lpp=%d, num_pages=%d\n", nb_lines
, lpp
, num_pages
) );
525 gint cur_page_line
= 1;
528 gchar amtbuf
[G_ASCII_DTOSTR_BUF_SIZE
];
529 gchar balbuf
[G_ASCII_DTOSTR_BUF_SIZE
];
531 GDate
*date
= g_date_new ();
533 //cairo_set_font_size(cr, PDF_FONT_NORMAL);
534 pango_font_description_set_absolute_size(ppc
.desc
, PDF_FONT_NORMAL
* PANGO_SCALE
);
535 pango_layout_set_font_description (layout
, ppc
.desc
);
538 hb_pdf_set_col_title(&ppc
);
540 for(col
=0;col
<PDF_NUMCOL
;col
++)
544 ppc
.column_width
[col
] = 0;
545 pango_layout_set_text (layout
, ppc
.column_txt
[col
], -1);
546 pango_layout_get_size (layout
, &tw
, &th
);
547 ppc
.column_width
[col
] = MAX(ppc
.column_width
[col
], tw
/ PANGO_SCALE
);
551 DB( g_print(" - compute width\n") );
553 /* first pass to get max width */
554 valid
= gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model
), &iter
);
560 gtk_tree_model_get (model
, &iter
, LST_DSPOPE_DATAS
, &txn
, -1);
563 g_date_set_julian (date
, txn
->date
);
564 g_date_strftime (dbuffer
, 255-1, "%x", date
);
565 pango_layout_set_text (layout
, dbuffer
, -1);
566 pango_layout_get_size (layout
, &tw
, &th
);
567 ppc
.column_width
[i
] = MAX(ppc
.column_width
[i
], tw
/ PANGO_SCALE
);
570 if(txn
->info
!= NULL
&& strlen(txn
->info
) > 0)
572 pango_layout_set_text (layout
, txn
->info
, -1);
573 pango_layout_get_size (layout
, &tw
, &th
);
574 ppc
.column_width
[i
] = MAX(ppc
.column_width
[i
], tw
/ PANGO_SCALE
);
578 hb_strfnum(amtbuf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->amount
, txn
->kcur
, GLOBALS
->minor
);
579 pango_layout_set_text (layout
, amtbuf
, -1);
580 pango_layout_get_size (layout
, &tw
, &th
);
581 ppc
.column_width
[i
] = MAX(ppc
.column_width
[i
], tw
/ PANGO_SCALE
);
584 pango_layout_set_text (layout
, "R", -1);
585 pango_layout_get_size (layout
, &tw
, &th
);
586 ppc
.column_width
[i
] = MAX(ppc
.column_width
[i
], tw
/ PANGO_SCALE
);
589 hb_strfnum(balbuf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->balance
, txn
->kcur
, GLOBALS
->minor
);
590 pango_layout_set_text (layout
, balbuf
, -1);
591 pango_layout_get_size (layout
, &tw
, &th
);
592 ppc
.column_width
[i
] = MAX(ppc
.column_width
[i
], tw
/ PANGO_SCALE
);
594 valid
= gtk_tree_model_iter_next(GTK_TREE_MODEL(model
), &iter
);
597 /* distribute remaining size */
598 gdouble tmp
= pwidth
- ppc
.ml
- ppc
.mr
- (PDF_COL_MARGIN
*PDF_NUMCOL
);
601 DB( g_print(" page width=%f, remain width=%f\n", pwidth
, tmp
) );
603 tmp
-= ppc
.column_width
[0];
604 tmp
-= ppc
.column_width
[4];
605 tmp
-= ppc
.column_width
[5];
606 tmp
-= ppc
.column_width
[6];
608 /* info=1/4 payee=1/4 memo=2/4 */
609 ppc
.column_width
[1] = tmp
/ 4;;
610 ppc
.column_width
[2] = tmp
/ 4;
611 ppc
.column_width
[3] = 2*tmp
/ 4;
613 DB( g_print(" page width=%f, remain width=%f\n", width
, tmp
) );
616 for(i
=0;i
<PDF_NUMCOL
;i
++)
617 g_print(" col%d=%g ", i
, ppc
.column_width
[i
]);
622 DB( g_print("\n - start printing\n") );
626 valid
= gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model
), &iter
);
632 gtk_tree_model_get (model
, &iter
, LST_DSPOPE_DATAS
, &txn
, -1);
634 //DB( g_print(" - %d, %d, %s\n", x, y, txn->memo) );
635 if(cur_page_line
== 1)
640 hb_pdf_draw_help_rect(cr
, 0xFF0000FF, ppc
.ml
+0.5, ppc
.mt
+0.5, width
-(ppc
.ml
+ppc
.mr
), height
- (ppc
.mt
+ppc
.mb
));
641 hb_pdf_draw_help_rect(cr
, 0xFF00FFFF, ppc
.ml
+0.5, ppc
.mt
+0.5, width
-(ppc
.ml
+ppc
.mr
), header_height
);
644 cairo_set_source_rgb(cr
, 0.0, 0.0, 0.0);
646 // draw account title
647 pango_font_description_set_absolute_size(ppc
.desc
, PDF_FONT_TITLE
* PANGO_SCALE
);
648 pango_layout_set_font_description (layout
, ppc
.desc
);
650 pango_layout_set_text (layout
, accname
, -1);
651 pango_layout_get_pixel_size (layout
, &tw
, &th
);
652 cairo_move_to(cr
, pwidth
/2 - (tw
/2), ppc
.mt
);
653 pango_cairo_show_layout (cr
, layout
);
655 // draw column titles
656 pango_font_description_set_absolute_size(ppc
.desc
, PDF_FONT_NORMAL
* PANGO_SCALE
);
657 pango_layout_set_font_description (layout
, ppc
.desc
);
659 g_sprintf(dbuffer
, "Page %d/%d", page
, num_pages
);
660 pango_layout_set_text (layout
, dbuffer
, -1);
661 pango_layout_get_pixel_size (layout
, &tw
, &th
);
662 cairo_move_to(cr
, pwidth
- ppc
.mr
- tw
, ppc
.mt
);
663 pango_cairo_show_layout (cr
, layout
);
666 y
= ppc
.mt
+ header_height
- (PDF_FONT_NORMAL
+ PDF_LINE_MARGIN
);
667 hb_pdf_set_col_title(&ppc
);
669 hb_pdf_draw_line(&ppc
, cr
, y
, TRUE
, FALSE
);
672 /* print a single line */
674 y
= ppc
.mt
+ header_height
+ (cur_page_line
* (PDF_FONT_NORMAL
+ PDF_LINE_MARGIN
));
679 for(i
=0;i
<PDF_NUMCOL
;i
++)
681 ppc
.column_txt
[i
] = NULL
;
685 g_date_set_julian (date
, txn
->date
);
686 g_date_strftime (dbuffer
, 255-1, "%x", date
);
687 ppc
.column_txt
[i
] = dbuffer
;
690 ppc
.column_txt
[i
] = txn
->info
;
693 Payee
*p
= da_pay_get(txn
->kpay
);
695 ppc
.column_txt
[i
] = p
->name
;
698 /*Category *c = da_cat_get(txn->kcat);
700 ppc.column_txt[i] = da_cat_get_fullname(c);*/
701 ppc
.column_txt
[i
] = txn
->memo
;
704 hb_strfnum(amtbuf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->amount
, txn
->kcur
, GLOBALS
->minor
);
705 ppc
.column_txt
[i
] = amtbuf
;
708 ppc
.column_txt
[i
] = "";
709 if(txn
->status
== TXN_STATUS_CLEARED
)
710 ppc
.column_txt
[i
] = "c";
712 if(txn
->status
== TXN_STATUS_RECONCILED
)
713 ppc
.column_txt
[i
] = "R";
716 hb_strfnum(balbuf
, G_ASCII_DTOSTR_BUF_SIZE
-1, txn
->balance
, txn
->kcur
, GLOBALS
->minor
);
717 ppc
.column_txt
[i
] = balbuf
;
719 hb_pdf_draw_line(&ppc
, cr
, y
, FALSE
, (cur_page_line
% 2));
721 /* free any fullcat name */
722 /*if(ppc.column_txt[3] != NULL)
723 g_free(ppc.column_txt[3]);*/
726 if(cur_page_line
>= lpp
)
728 DB( g_print("\n - next page %d\n", page
) );
737 valid
= gtk_tree_model_iter_next(GTK_TREE_MODEL(model
), &iter
);
742 g_object_unref (layout
);
743 pango_font_description_free (ppc
.desc
);
746 cairo_surface_destroy (surf
);
This page took 0.064577 seconds and 4 git commands to generate.