GnuCash c935c2f+
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions
dialog-print-check.c File Reference

Print Checks Dialog. More...

#include <config.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include <locale.h>
#include <math.h>
#include "qof.h"
#include "gnc-date.h"
#include "gnc-prefs.h"
#include "gnc-numeric.h"
#include "gnc-plugin-page-register.h"
#include "dialog-print-check.h"
#include "dialog-utils.h"
#include "print-session.h"
#include "gnc-ui.h"
#include "gnc-date-format.h"
#include "gnc-ui-util.h"
#include "gnc-path.h"
#include "gnc-filepath-utils.h"
#include "gnc-gkeyfile-utils.h"
#include "gnc-engine.h"
#include "engine-helpers.h"
#include "Split.h"
#include "Transaction.h"

Go to the source code of this file.

Data Structures

struct  check_item_t
 
struct  check_format_t
 
struct  PrintCheckDialog
 
struct  _trans_amount
 

Macros

#define G_LOG_DOMAIN   "gnc.printing.checks"
 
#define GNC_PREFS_GROUP   "dialogs.checkprinting"
 
#define GNC_PREF_CHECK_FORMAT_GUID   "check-format-guid"
 
#define GNC_PREF_CHECK_POSITION   "check-position"
 
#define GNC_PREF_FIRST_PAGE_COUNT   "first-page-count"
 
#define GNC_PREF_DATE_FORMAT_USER   "date-format-user"
 
#define GNC_PREF_CUSTOM_PAYEE   "custom-payee"
 
#define GNC_PREF_CUSTOM_DATE   "custom-date"
 
#define GNC_PREF_CUSTOM_WORDS   "custom-amount-words"
 
#define GNC_PREF_CUSTOM_NUMBER   "custom-amount-number"
 
#define GNC_PREF_CUSTOM_ADDRESS   "custom-address"
 
#define GNC_PREF_CUSTOM_NOTES   "custom-notes"
 
#define GNC_PREF_CUSTOM_MEMO   "custom-memo"
 
#define GNC_PREF_CUSTOM_TRANSLATION   "custom-translation"
 
#define GNC_PREF_CUSTOM_ROTATION   "custom-rotation"
 
#define GNC_PREF_CUSTOM_UNITS   "custom-units"
 
#define GNC_PREF_PRINT_DATE_FMT   "print-date-format"
 
#define GNC_PREF_DEFAULT_FONT   "default-font"
 
#define GNC_PREF_BLOCKING_CHARS   "blocking-chars"
 
#define GNC_PREF_SPLITS_AMOUNT   "splits-amount"
 
#define GNC_PREF_SPLITS_MEMO   "splits-memo"
 
#define GNC_PREF_SPLITS_ACCOUNT   "splits-account"
 
#define DEFAULT_FONT   "sans 12"
 
#define CHECK_FMT_DIR   "checks"
 
#define CHECK_NAME_EXTENSION   ".chk"
 
#define DEGREES_TO_RADIANS   (G_PI / 180.0)
 
#define BLOCKING_CHAR_OFF   0
 
#define BLOCKING_CHAR_ON   1
 
#define KF_GROUP_TOP   "Top"
 
#define KF_GROUP_POS   "Check Positions"
 
#define KF_GROUP_ITEMS   "Check Items"
 
#define KF_KEY_GUID   "Guid"
 
#define KF_KEY_TITLE   "Title"
 
#define KF_KEY_ROTATION   "Rotation"
 
#define KF_KEY_TRANSLATION   "Translation"
 
#define KF_KEY_FONT   "Font"
 
#define KF_KEY_ALIGN   "Align"
 
#define KF_KEY_BLOCKING   "Blocking_Chars"
 
#define KF_KEY_SHOW_GRID   "Show_Grid"
 
#define KF_KEY_SHOW_BOXES   "Show_Boxes"
 
#define KF_KEY_NAMES   "Names"
 
#define KF_KEY_HEIGHT   "Height"
 
#define KF_KEY_TYPE   "Type"
 
#define KF_KEY_COORDS   "Coords"
 
#define KF_KEY_TEXT   "Text"
 
#define KF_KEY_FILENAME   "Filename"
 
#define KF_KEY_DATE_FORMAT   "DateFormat"
 
#define KF_KEY_SPLITS_AMOUNT   "SplitsAmount"
 
#define KF_KEY_SPLITS_MEMO   "SplitsMemo"
 
#define KF_KEY_SPLITS_ACCOUNT   "SplitsAccount"
 
#define ENUM_CHECK_ITEM_TYPE(_)
 

Enumerations

enum  format_combo_col { COL_NAME = 0 , COL_DATA , COL_SEP }
 
enum  CheckItemType { ENUM_CHECK_ITEM_TYPE =(ENUM_BODY) }
 

Functions

gchar * get_check_address (PrintCheckDialog *pcd)
 

Split printing functions

#define DATE_FMT_HEIGHT   8
 
#define DATE_FMT_SLOP   2
 
void gnc_ui_print_check_response_cb (GtkDialog *dialog, gint response, PrintCheckDialog *pcd)
 
void gnc_print_check_format_changed (GtkComboBox *widget, PrintCheckDialog *pcd)
 
void gnc_print_check_position_changed (GtkComboBox *widget, PrintCheckDialog *pcd)
 
void gnc_print_check_save_button_clicked (GtkButton *button, PrintCheckDialog *pcd)
 
void gnc_check_format_title_changed (GtkEditable *editable, GtkWidget *ok_button)
 
gchar * get_check_splits_amount (PrintCheckDialog *pcd)
 
gchar * get_check_splits_memo (PrintCheckDialog *pcd)
 
gchar * get_check_splits_account (PrintCheckDialog *pcd)
 
void gnc_ui_print_check_dialog_create (GtkWidget *parent, GList *splits, Account *account)
 

Detailed Description

Print Checks Dialog.

Author
Copyright (C) 2000 Bill Gribble grib@.nosp@m.bill.nosp@m.gribb.nosp@m.le.c.nosp@m.om
Copyright (C) 2006,2007 David Hampton hampt.nosp@m.on@e.nosp@m.mploy.nosp@m.ees..nosp@m.org

Definition in file dialog-print-check.c.

Macro Definition Documentation

◆ BLOCKING_CHAR_OFF

#define BLOCKING_CHAR_OFF   0

Definition at line 94 of file dialog-print-check.c.

◆ BLOCKING_CHAR_ON

#define BLOCKING_CHAR_ON   1

Definition at line 95 of file dialog-print-check.c.

◆ CHECK_FMT_DIR

#define CHECK_FMT_DIR   "checks"

Definition at line 90 of file dialog-print-check.c.

◆ CHECK_NAME_EXTENSION

#define CHECK_NAME_EXTENSION   ".chk"

Definition at line 91 of file dialog-print-check.c.

◆ DATE_FMT_HEIGHT

#define DATE_FMT_HEIGHT   8

Definition at line 2051 of file dialog-print-check.c.

◆ DATE_FMT_SLOP

#define DATE_FMT_SLOP   2

Definition at line 2052 of file dialog-print-check.c.

◆ DEFAULT_FONT

#define DEFAULT_FONT   "sans 12"

Definition at line 89 of file dialog-print-check.c.

◆ DEGREES_TO_RADIANS

#define DEGREES_TO_RADIANS   (G_PI / 180.0)

Definition at line 92 of file dialog-print-check.c.

◆ ENUM_CHECK_ITEM_TYPE

#define ENUM_CHECK_ITEM_TYPE (   _)
Value:
_(NONE,) \
_(PAYEE,) \
_(DATE,) \
_(NOTES,) \
_(CHECK_NUMBER,) \
\
_(MEMO,) \
_(ACTION,) \
_(AMOUNT_NUMBER,) \
_(AMOUNT_WORDS,) \
\
_(TEXT,) \
_(ADDRESS,) \
_(DATE_FORMAT,) \
_(SPLITS_AMOUNT,) \
_(SPLITS_MEMO,) \
_(SPLITS_ACCOUNT,) \
_(PICTURE,)

Definition at line 154 of file dialog-print-check.c.

183{
184
185 CheckItemType type;
187 gdouble x, y;
192 gdouble w, h;
197 gchar *filename;
200 gchar *text;
203 gchar *font;
207 gboolean blocking;
212 gboolean print_date_format;
216 PangoAlignment align;
220
221/* This data structure describes an entire page of checks. Depending
222 * upon the check format, the page may contain multiple checks or
223 * only a single check. The data structure is built from a
224 * description in a text file.
225 */
226typedef struct _check_format
227{
228
229 gchar *guid;
231 const gchar *group;
233 gchar *filename;
236 gchar *title;
239 gboolean blocking;
242 gboolean print_date_format;
245 gboolean show_grid;
247 gboolean show_boxes;
250 gdouble rotation;
252 gdouble trans_x;
254 gdouble trans_y;
256 gchar *font;
258 gdouble height;
260 GSList *positions;
262 GSList *items;
264
265
266/* This data structure is used to manage the print check dialog, and
267 * the overall check printing process. It contains pointers to many
268 * of the widgets in the dialog, pointers to the check descriptions
269 * that have been read, and also contains the data from the gnucash
270 * transaction/split that is to be printed.
271 */
273{
274 GtkBuilder *builder;
275 GtkWidget *dialog;
276 GtkWindow *caller_window;
277
278 Split *split;
279 GList *splits;
280 Account* account;
281
282 GtkWidget *format_combobox;
283 gint format_max;
284 GtkWidget *position_combobox;
285 gint position_max;
286 GtkSpinButton *first_page_count;
287 GtkWidget *custom_table;
288 GtkSpinButton *payee_x, *payee_y;
289 GtkSpinButton *date_x, *date_y;
290 GtkSpinButton *words_x, *words_y;
291 GtkSpinButton *number_x, *number_y;
292 GtkSpinButton *address_x, *address_y;
293 GtkSpinButton *notes_x, *notes_y;
294 GtkSpinButton *memo_x, *memo_y;
295 GtkSpinButton *splits_amount_x, *splits_amount_y;
296 GtkSpinButton *splits_memo_x, *splits_memo_y;
297 GtkSpinButton *splits_account_x, *splits_account_y;
298 GtkSpinButton *translation_x, *translation_y;
299 GtkSpinButton *check_rotation;
300 GtkWidget *translation_label;
301
302 GtkWidget *units_combobox;
303
304 GtkWidget *date_format;
305
306 GtkWidget *check_address_name;
307 GtkWidget *check_address_1;
308 GtkWidget *check_address_2;
309 GtkWidget *check_address_3;
310 GtkWidget *check_address_4;
311
312 gchar *default_font;
313
314 check_format_t *selected_format;
315};
316
317
318/* This function walks the list of available check formats looking for a
319 * specific format as specified by guid number. If found, a pointer to it is
320 * returned to the caller. Additionally, if the caller passed a pointer to a
321 * GtkTreeIter, then the iter for that entry will also be returned.
322 */
323static check_format_t *
324find_existing_format (GtkListStore *store, gchar *guid, GtkTreeIter *iter_out)
325{
326 GtkTreeIter iter;
327 check_format_t *format;
328
329 g_return_val_if_fail(store, NULL);
330 g_return_val_if_fail(guid, NULL);
331
332 if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
333 return NULL;
334
335 do
336 {
337 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
338 COL_DATA, &format, -1);
339 if (format == NULL)
340 continue;
341 if (strcmp(format->guid, guid) != 0)
342 continue;
343
344 if (iter_out)
345 *iter_out = iter;
346 return format;
347 }
348 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
349
350 return NULL;
351}
352
353
354/* This function returns a string containing the check address in a five-line
355 * format.
356 *
357 * Note that the string needs to be freed with g_free.
358 */
359gchar *
360get_check_address( PrintCheckDialog *pcd)
361{
362 gchar *address;
363 address = g_strconcat(gtk_entry_get_text(GTK_ENTRY(pcd->check_address_name)), "\n",
364 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_1)), "\n",
365 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_2)), "\n",
366 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_3)), "\n",
367 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_4)),
368 NULL);
369 return address;
370}
371
372struct _trans_amount
373{
374 const Transaction* trans;
375 gnc_numeric amount;
376};
377
378static void
379subtotal_subaccount(const Account *account, struct _trans_amount* trans_amount)
380{
381 /* Get the amount of this account in the transaction.*/
382 gnc_numeric amount = xaccTransGetAccountAmount(trans_amount->trans, account);
383 /* Accumulate. */
384 trans_amount->amount = gnc_numeric_add_fixed(trans_amount->amount, amount);
385}
386
387/* This function returns the amount of the check.
388 */
389static gnc_numeric
390get_check_amount(PrintCheckDialog *pcd)
391{
392 gnc_numeric amount;
393 if (pcd->account)
394 {
395 /* A parent account, e.g. from a subaccount register plugin page.
396 * Subtotal the amount of all splits from descendant accounts. */
397 struct _trans_amount trans_amount;
398 trans_amount.trans = xaccSplitGetParent(pcd->split);
399 trans_amount.amount = gnc_numeric_zero();
400 gnc_account_foreach_descendant(pcd->account, (AccountCb)subtotal_subaccount, &trans_amount);
401 amount = trans_amount.amount;
402 }
403 else
404 {
405 /* Print just the amount of the split. */
406 amount = xaccSplitGetAmount(pcd->split);
407 }
408 return gnc_numeric_abs(amount);
409}
410
412
414/* This function formats the splits amounts for printing.
415 */
416gchar *
417get_check_splits_amount(PrintCheckDialog *pcd)
418{
419 gchar* amount = NULL;
420 Transaction *trans;
421 GList *node;
422 SplitList* s_list;
423
424 trans = xaccSplitGetParent(pcd->split);
425 s_list = xaccTransGetSplitList(trans);
426 if ( !s_list ) return NULL;
427
428 amount = g_strconcat("", NULL);
429 node = s_list;
430 while ( node )
431 {
432 Split *split = node->data;
433 /* Include all splits except the main split for the check */
434 if (split != pcd->split)
435 {
436 const gchar* split_amount;
437 gchar* amt_temp;
438 split_amount = xaccPrintAmount(xaccSplitGetAmount(split), gnc_split_amount_print_info(split, TRUE));
439 amt_temp = amount;
440 if (amount && *amount)
441 amount = g_strconcat(amt_temp, "\n", split_amount, NULL);
442 else
443 amount = g_strconcat(amt_temp, split_amount, NULL);
444 g_free(amt_temp);
445 }
446 node = node->next;
447 }
448 return amount;
449}
450
451
452/* This function formats the splits memo fields for printing.
453 */
454gchar *
455get_check_splits_memo(PrintCheckDialog *pcd)
456{
457 gchar* memo = NULL;
458 const gchar* split_memo;
459 Transaction *trans;
460 GList *node;
461 SplitList* s_list;
462
463 trans = xaccSplitGetParent(pcd->split);
464 s_list = xaccTransGetSplitList(trans);
465 if ( !s_list ) return NULL;
466
467 memo = g_strconcat("", NULL);
468 node = s_list;
469 while ( node )
470 {
471 Split *split = node->data;
472 /* Include all splits except the main split for the check */
473 if (split != pcd->split)
474 {
475 gchar* memo_temp;
476 split_memo = xaccSplitGetMemo(split);
477 memo_temp = memo;
478 if (memo && *memo)
479 memo = g_strconcat(memo_temp, "\n", split_memo, NULL);
480 else
481 memo = g_strconcat(memo_temp, split_memo, NULL);
482 g_free(memo_temp);
483 }
484 node = node->next;
485 }
486 return memo;
487}
488
489
490/* This function formats the splits accounts for printing.
491 */
492gchar *
493get_check_splits_account(PrintCheckDialog *pcd)
494{
495 gchar* account = NULL;
496 Transaction *trans;
497 GList *node;
498 SplitList* s_list;
499
500 trans = xaccSplitGetParent(pcd->split);
501 s_list = xaccTransGetSplitList(trans);
502 if ( !s_list ) return NULL;
503
504 account = g_strconcat("", NULL);
505 node = s_list;
506 while ( node )
507 {
508 Split *split = node->data;
509 /* Include all splits except the main split for the check */
510 if (split != pcd->split)
511 {
512 gchar* account_temp;
513 const gchar* aName = NULL;
514 Account *pAccount;
515 pAccount = xaccSplitGetAccount(split);
516 aName = gnc_get_account_name_for_register(pAccount);
517 account_temp = account;
518 if (account && *account)
519 account = g_strconcat(account_temp, "\n", aName, NULL);
520 else
521 account = g_strconcat(account_temp, aName, NULL);
522 g_free(account_temp);
523 }
524 node = node->next;
525 }
526 return account;
527}
529
530
531/* This function determines if an address item is present in the check format.
532 */
533static gboolean
534check_format_has_address ( PrintCheckDialog *pcd )
535{
536 /* check format for an ADDRESS item */
537 check_item_t *item = NULL;
538 GSList *elem;
539 check_format_t *format = NULL;
540
541 if ( !pcd ) return FALSE;
542
543 /* If we're printing more than one check no addresses are allowed */
544 if (g_list_length(pcd->splits) != 1)
545 return FALSE;
546
547 /* if format is NULL, then the custom format is being used
548 * which has an ADDRESS item by definition */
549 format = pcd->selected_format;
550 if ( !format ) return TRUE;
551
552 for (elem = pcd->selected_format->items; elem; elem = g_slist_next(elem))
553 {
554 item = elem->data;
555 if ( item->type == ADDRESS ) return TRUE;
556 }
557 return FALSE;
558}
559
560
561static void
562gnc_ui_print_save_dialog(PrintCheckDialog *pcd)
563{
564 GtkTreeModel *model;
565 GtkTreeIter iter;
566 check_format_t *check;
567 const gchar *format;
568 gint active;
569
570 /* Options page */
571 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pcd->format_combobox),
572 &iter))
573 {
574 model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
575 gtk_tree_model_get(model, &iter, COL_DATA, &check, -1);
576 gnc_prefs_set_string (GNC_PREFS_GROUP, GNC_PREF_CHECK_FORMAT_GUID,
577 check ? check->guid : "custom");
578 }
579 active = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
580 gnc_prefs_set_int(GNC_PREFS_GROUP, GNC_PREF_CHECK_POSITION, active);
581 active = gtk_spin_button_get_value_as_int(pcd->first_page_count);
582 gnc_prefs_set_int(GNC_PREFS_GROUP, GNC_PREF_FIRST_PAGE_COUNT, active);
583 active = gnc_date_format_get_format (GNC_DATE_FORMAT(pcd->date_format));
584 gnc_prefs_set_int(GNC_PREFS_GROUP, GNC_PREF_DATE_FORMAT, active);
585 if (active == QOF_DATE_FORMAT_CUSTOM)
586 {
587 format = gnc_date_format_get_custom (GNC_DATE_FORMAT(pcd->date_format));
588 gnc_prefs_set_string (GNC_PREFS_GROUP, GNC_PREF_DATE_FORMAT_USER, format);
589 }
590 else
591 {
592 gnc_prefs_reset (GNC_PREFS_GROUP, GNC_PREF_DATE_FORMAT_USER);
593 }
594
595 /* Custom format page */
596 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_PAYEE,
597 gtk_spin_button_get_value(pcd->payee_x),
598 gtk_spin_button_get_value(pcd->payee_y));
599 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_DATE,
600 gtk_spin_button_get_value(pcd->date_x),
601 gtk_spin_button_get_value(pcd->date_y));
602 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_WORDS,
603 gtk_spin_button_get_value(pcd->words_x),
604 gtk_spin_button_get_value(pcd->words_y));
605 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_NUMBER,
606 gtk_spin_button_get_value(pcd->number_x),
607 gtk_spin_button_get_value(pcd->number_y));
608 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_NOTES,
609 gtk_spin_button_get_value(pcd->notes_x),
610 gtk_spin_button_get_value(pcd->notes_y));
611 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_MEMO,
612 gtk_spin_button_get_value(pcd->memo_x),
613 gtk_spin_button_get_value(pcd->memo_y));
614 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_ADDRESS,
615 gtk_spin_button_get_value(pcd->address_x),
616 gtk_spin_button_get_value(pcd->address_y));
617 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_AMOUNT,
618 gtk_spin_button_get_value(pcd->splits_amount_x),
619 gtk_spin_button_get_value(pcd->splits_amount_y));
620 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_MEMO,
621 gtk_spin_button_get_value(pcd->splits_memo_x),
622 gtk_spin_button_get_value(pcd->splits_memo_y));
623 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_ACCOUNT,
624 gtk_spin_button_get_value(pcd->splits_account_x),
625 gtk_spin_button_get_value(pcd->splits_account_y));
626 gnc_prefs_set_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_TRANSLATION,
627 gtk_spin_button_get_value(pcd->translation_x),
628 gtk_spin_button_get_value(pcd->translation_y));
629 gnc_prefs_set_float(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_ROTATION,
630 gtk_spin_button_get_value(pcd->check_rotation));
631 active = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->units_combobox));
632 gnc_prefs_set_int(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_UNITS, active);
633}
634
635
636static void
637gnc_ui_print_restore_dialog(PrintCheckDialog *pcd)
638{
639 GtkTreeModel *model;
640 GtkTreeIter iter;
641 gchar *format, *guid;
642 gdouble x, y;
643 gint active;
644
645 /* Options page */
646 guid = gnc_prefs_get_string (GNC_PREFS_GROUP, GNC_PREF_CHECK_FORMAT_GUID);
647 if (!(guid && *guid))
648 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox), 0);
649 else if (strcmp(guid, "custom") == 0)
650 {
651 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox),
652 pcd->format_max - 1);
653 }
654 else
655 {
656 model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
657 if (find_existing_format(GTK_LIST_STORE(model), guid, &iter))
658 {
659 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pcd->format_combobox), &iter);
660 }
661 else
662 {
663 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox), 0);
664 }
665 }
666 g_free (guid);
667
668 active = gnc_prefs_get_int(GNC_PREFS_GROUP, GNC_PREF_CHECK_POSITION);
669
670 /* If the check format used last time no longer exists, then the saved check
671 position may be invalid. If so set it to the first position. */
672 if (active < 0 || active > pcd->position_max)
673 active = 0;
674 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->position_combobox), active);
675 active = gnc_prefs_get_int(GNC_PREFS_GROUP, GNC_PREF_FIRST_PAGE_COUNT);
676 gtk_spin_button_set_value(pcd->first_page_count, (gdouble) active);
677 active = gnc_prefs_get_int(GNC_PREFS_GROUP, GNC_PREF_DATE_FORMAT);
678 gnc_date_format_set_format(GNC_DATE_FORMAT(pcd->date_format), active);
679 if (active == QOF_DATE_FORMAT_CUSTOM)
680 {
681 format = gnc_prefs_get_string (GNC_PREFS_GROUP, GNC_PREF_DATE_FORMAT_USER);
682 if (format && *format)
683 {
684 gnc_date_format_set_custom(GNC_DATE_FORMAT(pcd->date_format), format);
685 g_free(format);
686 }
687 }
688
689 /* Custom format page */
690 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_PAYEE, &x, &y);
691 gtk_spin_button_set_value(pcd->payee_x, x);
692 gtk_spin_button_set_value(pcd->payee_y, y);
693
694 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_DATE, &x, &y);
695 gtk_spin_button_set_value(pcd->date_x, x);
696 gtk_spin_button_set_value(pcd->date_y, y);
697 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_WORDS, &x, &y);
698 gtk_spin_button_set_value(pcd->words_x, x);
699 gtk_spin_button_set_value(pcd->words_y, y);
700 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_NUMBER, &x, &y);
701 gtk_spin_button_set_value(pcd->number_x, x);
702 gtk_spin_button_set_value(pcd->number_y, y);
703 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_ADDRESS, &x, &y);
704 gtk_spin_button_set_value(pcd->address_x, x);
705 gtk_spin_button_set_value(pcd->address_y, y);
706 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_NOTES, &x, &y);
707 gtk_spin_button_set_value(pcd->notes_x, x);
708 gtk_spin_button_set_value(pcd->notes_y, y);
709 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_MEMO, &x, &y);
710 gtk_spin_button_set_value(pcd->memo_x, x);
711 gtk_spin_button_set_value(pcd->memo_y, y);
712 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_AMOUNT, &x, &y);
713 gtk_spin_button_set_value(pcd->splits_amount_x, x);
714 gtk_spin_button_set_value(pcd->splits_amount_y, y);
715 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_MEMO, &x, &y);
716 gtk_spin_button_set_value(pcd->splits_memo_x, x);
717 gtk_spin_button_set_value(pcd->splits_memo_y, y);
718 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_SPLITS_ACCOUNT, &x, &y);
719 gtk_spin_button_set_value(pcd->splits_account_x, x);
720 gtk_spin_button_set_value(pcd->splits_account_y, y);
721 gnc_prefs_get_coords(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_TRANSLATION, &x, &y);
722 gtk_spin_button_set_value(pcd->translation_x, x);
723 gtk_spin_button_set_value(pcd->translation_y, y);
724 x = gnc_prefs_get_float(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_ROTATION);
725 gtk_spin_button_set_value(pcd->check_rotation, x);
726 active = gnc_prefs_get_int(GNC_PREFS_GROUP, GNC_PREF_CUSTOM_UNITS);
727 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->units_combobox), active);
728}
729
730
731static gdouble
732pcd_get_custom_multip(PrintCheckDialog *pcd)
733{
734 gint selected;
735
736 selected = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->units_combobox));
737 switch (selected)
738 {
739 default:
740 return 72.0; /* inches */
741 case 1:
742 return 28.346; /* cm */
743 case 2:
744 return 2.8346; /* mm */
745 case 3:
746 return 1.0; /* points */
747 }
748}
749
750
751/* This function saves a coordinate pair into a check description file. It
752 * extracts the values from the spin buttons, adjusts them according to the
753 * unit multiplier (inches, pixels, etc), then adds them to the gKeyFile.
754 */
755static void
756pcd_key_file_save_xy (GKeyFile *key_file, const gchar *group_name,
757 const gchar *key_name, gdouble multip,
758 GtkSpinButton *spin0, GtkSpinButton *spin1)
759{
760 gdouble dd[2];
761
762 dd[0] = multip * gtk_spin_button_get_value(spin0);
763 dd[1] = multip * gtk_spin_button_get_value(spin1);
764
765 /* Clip the numbers to three decimal places. */
766 dd[0] = round(dd[0] * 1000) / 1000;
767 dd[1] = round(dd[1] * 1000) / 1000;
768 g_key_file_set_double_list(key_file, group_name, key_name, dd, 2);
769}
770
771
772/* This function saves the information about a single printed item into a
773 * check description file. It uses a helper function to extracts and save the
774 * item coordinates.
775 */
776static void
777pcd_key_file_save_item_xy (GKeyFile *key_file, int index,
778 CheckItemType type, gdouble multip,
779 GtkSpinButton *spin0, GtkSpinButton *spin1)
780{
781 gchar *key;
782 key = g_strdup_printf("Type_%d", index);
783 g_key_file_set_string(key_file, KF_GROUP_ITEMS, key,
784 CheckItemTypeasString(type));
785 g_free(key);
786 key = g_strdup_printf("Coords_%d", index);
787 pcd_key_file_save_xy(key_file, KF_GROUP_ITEMS, key, multip, spin0, spin1);
788 g_free(key);
789}
790
791
792/* This function saves all of the information from the custom check dialog
793 * into a check description file.
794 */
795static void
796pcd_save_custom_data(PrintCheckDialog *pcd, const gchar *title)
797{
798 GKeyFile *key_file;
799 GError *error = NULL;
800 GtkWidget *dialog;
801 gdouble multip;
802 gint i = 1;
803 GncGUID guid;
804 char buf[GUID_ENCODING_LENGTH+1];
805 gchar *filename, *pathname;
806
807 multip = pcd_get_custom_multip(pcd);
808
809 key_file = g_key_file_new();
810 guid_replace(&guid);
811 guid_to_string_buff(&guid, buf);
812 g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, buf);
813 g_key_file_set_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, title);
814 g_key_file_set_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, FALSE);
815 g_key_file_set_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, FALSE);
816 g_key_file_set_double(key_file, KF_GROUP_TOP, KF_KEY_ROTATION,
817 gtk_spin_button_get_value(pcd->check_rotation));
818 pcd_key_file_save_xy(key_file, KF_GROUP_TOP, KF_KEY_TRANSLATION, multip,
819 pcd->translation_x, pcd->translation_y);
820
821 pcd_key_file_save_item_xy(key_file, i++, PAYEE, multip,
822 pcd->payee_x, pcd->payee_y);
823 pcd_key_file_save_item_xy(key_file, i++, DATE, multip,
824 pcd->date_x, pcd->date_y);
825 pcd_key_file_save_item_xy(key_file, i++, AMOUNT_WORDS, multip,
826 pcd->words_x, pcd->words_y);
827 pcd_key_file_save_item_xy(key_file, i++, AMOUNT_NUMBER, multip,
828 pcd->number_x, pcd->number_y);
829 pcd_key_file_save_item_xy(key_file, i++, ADDRESS, multip,
830 pcd->address_x, pcd->address_y);
831 pcd_key_file_save_item_xy(key_file, i++, NOTES, multip,
832 pcd->notes_x, pcd->notes_y);
833 pcd_key_file_save_item_xy(key_file, i++, MEMO, multip,
834 pcd->memo_x, pcd->memo_y);
835 pcd_key_file_save_item_xy(key_file, i++, SPLITS_AMOUNT, multip,
836 pcd->splits_amount_x, pcd->splits_amount_y);
837 pcd_key_file_save_item_xy(key_file, i++, SPLITS_MEMO, multip,
838 pcd->splits_memo_x, pcd->splits_memo_y);
839 pcd_key_file_save_item_xy(key_file, i++, SPLITS_ACCOUNT, multip,
840 pcd->splits_account_x, pcd->splits_account_y);
841
842 filename = g_strconcat(title, CHECK_NAME_EXTENSION, NULL);
843 pathname = g_build_filename(gnc_userdata_dir(), CHECK_FMT_DIR,
844 filename, NULL);
845
846 if (gnc_key_file_save_to_file(pathname, key_file, &error))
847 {
848 if (!gnc_prefs_get_bool(GNC_PREFS_GROUP, GNC_PREF_PRINT_DATE_FMT))
849 /* Reload the format combo box and reselect the "custom" entry */
850 initialize_format_combobox(pcd);
851
852 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->format_combobox),
853 pcd->format_max - 1);
854 }
855 else
856 {
857 dialog = gtk_message_dialog_new(GTK_WINDOW(pcd->dialog),
858 GTK_DIALOG_DESTROY_WITH_PARENT,
859 GTK_MESSAGE_ERROR,
860 GTK_BUTTONS_CLOSE, "%s",
861 _("Cannot save check format file."));
862 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
863 _("Cannot open file %s"),
864 _(error->message));
865 gtk_dialog_run(GTK_DIALOG(dialog));
866 gtk_widget_destroy(dialog);
867 g_error_free(error);
868 }
869 g_free(pathname);
870 g_free(filename);
871}
872
873
874/* This function makes the OK button active iff a title has been entered.
875 */
876void
877gnc_check_format_title_changed (GtkEditable *editable, GtkWidget *ok_button)
878{
879 const gchar *text;
880 gboolean sensitive;
881
882 text = gtk_entry_get_text(GTK_ENTRY(editable));
883 sensitive = text && *text;
884 gtk_widget_set_sensitive(ok_button, sensitive);
885}
886
887
888/* This function is called when the user clicks the "save format" button in
889 * the check printing dialog. It presents another dialog to the user to get
890 * the filename for saving the data.
891 */
892void
893gnc_print_check_save_button_clicked(GtkButton *unused, PrintCheckDialog *pcd)
894{
895 GtkWidget *dialog, *entry, *button;
896 GtkBuilder *builder;
897 gchar *title;
898
899 builder = gtk_builder_new();
900 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "format_title_dialog");
901
902 /* Get a title for the new check format. */
903 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "format_title_dialog"));
904 entry = GTK_WIDGET(gtk_builder_get_object (builder, "format_title"));
905 button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
906 gnc_check_format_title_changed(GTK_EDITABLE(entry), button);
907 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
908
909 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pcd->dialog));
910 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
911 {
912 gtk_widget_destroy(dialog);
913 g_object_unref(G_OBJECT(builder));
914 return;
915 }
916
917 title = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
918 gtk_widget_destroy (dialog);
919
920 g_object_unref(G_OBJECT(builder));
921
922 pcd_save_custom_data(pcd, title);
923 g_free(title);
924}
925
926
927/* This function is an auxiliary debugging function for converting an array of
928 * doubles into a printable string.
929 */
930static gchar *
931doubles_to_string(gdouble *dd, gint len)
932{
933 GString *str;
934 gint i;
935
936 str = g_string_new_len(NULL, 50);
937 for (i = 0; i < len; i++)
938 g_string_append_printf(str, "%f ", dd[i]);
939 return g_string_free(str, FALSE);
940}
941
942
943/* This function reads in the information describing the placement for each
944 * item to be printed on a check. This information is all relative to the
945 * upper left hand corner of a "check". See the format_read_multicheck_info()
946 * function for determining if there are multiple checks on a single page of
947 * paper. This data is build into a linked list and saved as part of the check
948 * format information. These items will be printed in the same order they are
949 * read, meaning that items listed later in the date file can be printed over
950 * top of items that appear earlier in the file.
951 */
952static GSList *
953format_read_item_placement(const gchar *file,
954 GKeyFile *key_file, check_format_t *format)
955{
956 check_item_t *data = NULL;
957 GError *error = NULL;
958 GSList *list = NULL;
959 gchar *key, *value, *name;
960 int item_num;
961 gboolean bval;
962 gdouble *dd;
963 gsize dd_len;
964
965 /* Read until failure. */
966 for (item_num = 1;; item_num++)
967 {
968
969 /* Create the per-item data structure */
970 data = g_new0(check_item_t, 1);
971 if (NULL == data)
972 return list;
973
974 /* Get the item type */
975 key = g_strdup_printf("%s_%d", KF_KEY_TYPE, item_num);
976 value = g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
977 if (error)
978 {
979 if ((error->domain == G_KEY_FILE_ERROR)
980 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND))
981 {
982 /* This is the expected exit from this function. */
983 goto cleanup;
984 }
985 goto failed;
986 }
987 DEBUG("Check file %s, group %s, key %s, value: %s",
988 file, KF_GROUP_ITEMS, key, value);
989 g_free(key);
990
991 /* Convert the type from a string to an enum, ignoring case. */
992 name = g_utf8_strup(value, -1);
993 data->type = CheckItemTypefromString(name);
994 g_free(name);
995 g_free(value);
996
997
998 /* Get the item location */
999 key = g_strdup_printf("%s_%d", KF_KEY_COORDS, item_num);
1000 dd = g_key_file_get_double_list(key_file, KF_GROUP_ITEMS,
1001 key, &dd_len, &error);
1002 if (error)
1003 goto failed;
1004 value = doubles_to_string(dd, dd_len);
1005 DEBUG("Check file %s, group %s, key %s, length %"G_GSIZE_FORMAT"; values: %s",
1006 file, KF_GROUP_ITEMS, key, dd_len, value);
1007 g_free(value);
1008
1009 /* Must have "x;y" or "x;y;w;h". */
1010 switch (dd_len)
1011 {
1012 case 4:
1013 data->w = dd[2];
1014 data->h = dd[3];
1015 /* fall through */
1016 case 2:
1017 data->x = dd[0];
1018 data->y = dd[1];
1019 break;
1020 default:
1021 g_warning
1022 ("Check file %s, group %s, key %s, error: 2 or 4 values only",
1023 file, KF_GROUP_ITEMS, key);
1024 goto cleanup;
1025 }
1026 g_free(dd);
1027 g_free(key);
1028
1029 /* Any text item can specify:
1030 * a font FONT_n
1031 * an alignment if a width was provided for the item ALIGN_n
1032 * blocking chars flag BLOCKING_CHARS_n
1033 * These values are optional and do not cause a failure if they are missing. */
1034
1035 if (data->type != PICTURE)
1036 {
1037 key = g_strdup_printf("%s_%d", KF_KEY_FONT, item_num);
1038 data->font =
1039 g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
1040 if (!error)
1041 {
1042 DEBUG("Check file %s, group %s, key %s, value: %s",
1043 file, KF_GROUP_ITEMS, key, data->font);
1044 }
1045 else
1046 {
1047 if (!((error->domain == G_KEY_FILE_ERROR)
1048 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1049 g_warning("Check file %s, group %s, key %s, error: %s",
1050 file, KF_GROUP_ITEMS, key, error->message);
1051 g_clear_error(&error);
1052 }
1053 g_free(key);
1054
1055 key = g_strdup_printf("%s_%d", KF_KEY_ALIGN, item_num);
1056 value =
1057 g_key_file_get_string(key_file, KF_GROUP_ITEMS, key, &error);
1058 if (!error)
1059 {
1060 DEBUG("Check file %s, group %s, key %s, value: %s",
1061 file, KF_GROUP_ITEMS, key, value);
1062 name = g_utf8_strdown(value, -1);
1063 if (strcmp(name, "right") == 0)
1064 data->align = PANGO_ALIGN_RIGHT;
1065 else if (strcmp(name, "center") == 0)
1066 data->align = PANGO_ALIGN_CENTER;
1067 else
1068 data->align = PANGO_ALIGN_LEFT;
1069 g_free(name);
1070 g_free(value);
1071 }
1072 else
1073 {
1074 if (!((error->domain == G_KEY_FILE_ERROR)
1075 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1076 g_warning("Check file %s, group %s, key %s, error: %s",
1077 file, KF_GROUP_ITEMS, key, error->message);
1078 data->align = PANGO_ALIGN_LEFT;
1079 g_clear_error(&error);
1080 }
1081 g_free(key);
1082
1083 key = g_strdup_printf("%s_%d", KF_KEY_BLOCKING, item_num);
1084 bval =
1085 g_key_file_get_boolean(key_file, KF_GROUP_ITEMS, key, &error);
1086 if (!error)
1087 {
1088 DEBUG("Check file %s, group %s, key %s, value: %d",
1089 file, KF_GROUP_ITEMS, key, bval);
1090 data->blocking = bval;
1091 }
1092 else
1093 {
1094 if (!((error->domain == G_KEY_FILE_ERROR)
1095 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1096 g_warning("Check file %s, group %s, key %s, error: %s",
1097 file, KF_GROUP_ITEMS, key, error->message);
1098 data->blocking = format->blocking;
1099 g_clear_error(&error);
1100 }
1101 g_free(key);
1102 }
1103 /* Get any extra data for specific items. */
1104 switch (data->type)
1105 {
1106 case PICTURE:
1107 key = g_strdup_printf("%s_%d", KF_KEY_FILENAME, item_num);
1108 data->filename =
1109 g_key_file_get_string(key_file, KF_GROUP_ITEMS, key,
1110 &error);
1111 if (error)
1112 goto failed;
1113 DEBUG("Check file %s, group %s, key %s, value: %s",
1114 file, KF_GROUP_ITEMS, key, data->filename);
1115 g_free(key);
1116 break;
1117 case TEXT:
1118 key = g_strdup_printf("%s_%d", KF_KEY_TEXT, item_num);
1119 data->text =
1120 g_key_file_get_string(key_file, KF_GROUP_ITEMS, key,
1121 &error);
1122 if (error)
1123 goto failed;
1124 DEBUG("Check file %s, group %s, key %s, value: %s",
1125 file, KF_GROUP_ITEMS, key, data->text);
1126 g_free(key);
1127 break;
1128 case DATE:
1129 /* no error if the date_format is not present */
1130 key = g_strdup_printf("%s_%d", KF_KEY_DATE_FORMAT, item_num);
1131 bval = g_key_file_get_boolean(key_file, KF_GROUP_ITEMS, key, &error);
1132 if (!error)
1133 {
1134 DEBUG("Check file %s, group %s, key %s, value: %d",
1135 file, KF_GROUP_ITEMS, key, bval);
1136 data->print_date_format = bval;
1137 }
1138 else
1139 {
1140 if (!((error->domain == G_KEY_FILE_ERROR)
1141 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1142 g_warning("Check file %s, group %s, key %s, error: %s",
1143 file, KF_GROUP_ITEMS, key, error->message);
1144 data->print_date_format = format->print_date_format;
1145 g_clear_error(&error);
1146 }
1147 g_free(key);
1148 break;
1149 default:
1150 break;
1151 }
1152
1153 list = g_slist_append(list, data);
1154 data = NULL;
1155 }
1156
1157 /* Should never be reached. */
1158 return list;
1159
1160failed:
1161 g_warning("Check file %s, group %s, key %s, error: %s",
1162 file, KF_GROUP_ITEMS, key, error->message);
1163cleanup:
1164 if (error)
1165 g_error_free(error);
1166 if (data)
1167 g_free(data);
1168 if (key)
1169 g_free(key);
1170 return list;
1171}
1172
1173
1174/* Free the data describing the placement of a single item on a check.
1175 */
1176static void
1177format_free_item_placement(check_item_t *data)
1178{
1179 if (data->font)
1180 g_free(data->font);
1181 if (data->text)
1182 g_free(data->text);
1183 if (data->filename)
1184 g_free(data->filename);
1185 g_free(data);
1186}
1187
1188
1189/* Read the information describing whether a page contains multiple checks or
1190 * a single check. If there are multiple checks on a page, this functions
1191 * builds a linked list of the position names and their offsets (from the
1192 * upper left corner of the page).
1193 */
1194static GSList *
1195format_read_multicheck_info(const gchar *file,
1196 GKeyFile *key_file, check_format_t *format)
1197{
1198 GError *error = NULL;
1199 GSList *list = NULL;
1200 gchar *key, **names;
1201 gsize length;
1202 gint i;
1203
1204 key = g_strdup_printf("%s", KF_KEY_HEIGHT);
1205 format->height = g_key_file_get_double(key_file, KF_GROUP_POS, key, &error);
1206 if (error)
1207 {
1208 if ((error->domain == G_KEY_FILE_ERROR)
1209 && ((error->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND)
1210 || (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1211 {
1212 g_clear_error(&error);
1213 format->height = 0.0;
1214 }
1215 else
1216 {
1217 g_warning("Check file %s, error reading group %s, key %s: %s",
1218 file, KF_GROUP_POS, key, error->message);
1219 g_free(key);
1220 return NULL;
1221 }
1222 }
1223
1224 names = g_key_file_get_string_list(key_file, KF_GROUP_POS, KF_KEY_NAMES,
1225 &length, &error);
1226 if (error)
1227 {
1228 if ((error->domain == G_KEY_FILE_ERROR)
1229 && ((error->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND)
1230 || (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1231 {
1232 /* This is the expected exit from this function. */
1233 g_free(key);
1234 return NULL;
1235 }
1236 g_warning("Check file %s, error reading group %s, key %s: %s",
1237 file, KF_GROUP_POS, key, error->message);
1238 g_free(key);
1239 return list;
1240 }
1241
1242 for (i = 0; i < length; i++)
1243 list = g_slist_append(list, g_strdup(names[i]));
1244
1245 g_strfreev(names);
1246 return list;
1247}
1248
1249
1250/* Free the data describing the placement of multiple checks on a page.
1251 */
1252static void
1253free_check_position(gchar *name)
1254{
1255 g_free(name);
1256}
1257
1258
1259/* Read the information describing the general layout of a page of checks.
1260 * All items in this section are optional except or the name of the check
1261 * style.
1262 */
1263static gboolean
1264format_read_general_info(const gchar *file,
1265 GKeyFile *key_file, check_format_t *format)
1266{
1267 GError *error = NULL;
1268 gchar **parts;
1269 gchar *value;
1270 double *dd;
1271 gsize dd_len;
1272
1273 value = g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_GUID, &error);
1274 if (error)
1275 {
1276 g_warning("Check file %s, group %s, key %s, error: %s",
1277 file, KF_GROUP_TOP, KF_KEY_GUID, error->message);
1278 g_error_free(error);
1279 return FALSE;
1280 }
1281 parts = g_strsplit(value, "-", -1);
1282 format->guid = g_strjoinv("", parts);
1283 g_strfreev(parts);
1284 DEBUG("Check file %s, group %s, key %s, value: %s",
1285 file, KF_GROUP_TOP, KF_KEY_GUID, format->guid);
1286
1287 format->title =
1288 g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_TITLE, &error);
1289 if (!error)
1290 {
1291 DEBUG("Check file %s, group %s, key %s, value: %s",
1292 file, KF_GROUP_TOP, KF_KEY_TITLE, format->title);
1293 }
1294 else
1295 {
1296 g_warning("Check file %s, group %s, key %s, error: %s",
1297 file, KF_GROUP_TOP, KF_KEY_TITLE, error->message);
1298 return FALSE;
1299 }
1300
1301 format->blocking =
1302 g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_BLOCKING,
1303 &error);
1304 if (!error)
1305 {
1306 DEBUG("Check file %s, group %s, key %s, value: %d",
1307 file, KF_GROUP_TOP, KF_KEY_BLOCKING, format->blocking);
1308 }
1309 else
1310 {
1311 if (!((error->domain == G_KEY_FILE_ERROR)
1312 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1313 g_warning("Check file %s, group %s, key %s, error: %s",
1314 file, KF_GROUP_TOP, KF_KEY_BLOCKING, error->message);
1315 if ( gnc_prefs_get_bool(GNC_PREFS_GROUP, GNC_PREF_BLOCKING_CHARS) )
1316 {
1317 format->blocking = TRUE;
1318 }
1319 else
1320 {
1321 format->blocking = FALSE;
1322 }
1323 g_clear_error(&error);
1324 }
1325
1326 format->print_date_format =
1327 g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT,
1328 &error);
1329 if (!error)
1330 {
1331 DEBUG("Check file %s, group %s, key %s, value: %d",
1332 file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT, format->print_date_format);
1333 }
1334 else
1335 {
1336 if (!((error->domain == G_KEY_FILE_ERROR)
1337 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1338 g_warning("Check file %s, group %s, key %s, error: %s",
1339 file, KF_GROUP_TOP, KF_KEY_DATE_FORMAT, error->message);
1340 if ( gnc_prefs_get_bool(GNC_PREFS_GROUP, GNC_PREF_PRINT_DATE_FMT) )
1341 {
1342 format->print_date_format = TRUE;
1343 }
1344 else
1345 {
1346 format->print_date_format = FALSE;
1347 }
1348 g_clear_error(&error);
1349 }
1350
1351 format->show_grid =
1352 g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_GRID,
1353 &error);
1354 if (!error)
1355 {
1356 DEBUG("Check file %s, group %s, key %s, value: %d",
1357 file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, format->show_grid);
1358 }
1359 else
1360 {
1361 if (!((error->domain == G_KEY_FILE_ERROR)
1362 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1363 g_warning("Check file %s, group %s, key %s, error: %s",
1364 file, KF_GROUP_TOP, KF_KEY_SHOW_GRID, error->message);
1365 format->show_grid = FALSE;
1366 g_clear_error(&error);
1367 }
1368
1369 format->show_boxes =
1370 g_key_file_get_boolean(key_file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES,
1371 &error);
1372 if (!error)
1373 {
1374 DEBUG("Check file %s, group %s, key %s, value: %d",
1375 file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, format->show_boxes);
1376 }
1377 else
1378 {
1379 if (!((error->domain == G_KEY_FILE_ERROR)
1380 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1381 g_warning("Check file %s, group %s, key %s, error: %s",
1382 file, KF_GROUP_TOP, KF_KEY_SHOW_BOXES, error->message);
1383 format->show_boxes = FALSE;
1384 g_clear_error(&error);
1385 }
1386
1387 format->font =
1388 g_key_file_get_string(key_file, KF_GROUP_TOP, KF_KEY_FONT, &error);
1389 if (!error)
1390 {
1391 DEBUG("Check file %s, group %s, key %s, value: %s",
1392 file, KF_GROUP_TOP, KF_KEY_FONT, format->font);
1393 }
1394 else
1395 {
1396 if (!((error->domain == G_KEY_FILE_ERROR)
1397 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1398 g_warning("Check file %s, group %s, key %s, error: %s",
1399 file, KF_GROUP_TOP, KF_KEY_FONT, error->message);
1400 g_clear_error(&error);
1401 }
1402
1403 format->rotation =
1404 g_key_file_get_double(key_file, KF_GROUP_TOP, KF_KEY_ROTATION, &error);
1405 if (!error)
1406 {
1407 DEBUG("Check file %s, group %s, key %s, value: %f",
1408 file, KF_GROUP_TOP, KF_KEY_ROTATION, format->rotation);
1409 }
1410 else
1411 {
1412 if (!((error->domain == G_KEY_FILE_ERROR)
1413 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1414 g_warning("Check file %s, group %s, key %s, error: %s",
1415 file, KF_GROUP_TOP, KF_KEY_ROTATION, error->message);
1416 format->rotation = 0.0;
1417 g_clear_error(&error);
1418 }
1419
1420 dd = g_key_file_get_double_list(key_file, KF_GROUP_TOP, KF_KEY_TRANSLATION,
1421 &dd_len, &error);
1422 if (!error)
1423 {
1424 value = doubles_to_string(dd, dd_len);
1425 DEBUG("Check file %s, group %s, key %s, length %"G_GSIZE_FORMAT"; values: %s",
1426 file, KF_GROUP_TOP, KF_KEY_TRANSLATION, dd_len, value);
1427 g_free(value);
1428
1429 if (dd_len == 2)
1430 {
1431 format->trans_x = dd[0];
1432 format->trans_y = dd[1];
1433 }
1434 else
1435 {
1436 g_warning("Check file %s, error top %s, key %s: 2 values only",
1437 file, KF_GROUP_TOP, KF_KEY_TRANSLATION);
1438 }
1439 g_free(dd);
1440 }
1441 else
1442 {
1443 if (!((error->domain == G_KEY_FILE_ERROR)
1444 && (error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)))
1445 g_warning("Check file %s, group top %s, key %s: %s",
1446 file, KF_GROUP_ITEMS, KF_KEY_TRANSLATION, error->message);
1447 g_clear_error(&error);
1448 }
1449
1450 return TRUE;
1451}
1452
1453
1454/* Free all of the information describing a page of checks.
1455 */
1456static void
1457free_check_format(check_format_t *data)
1458{
1459 g_return_if_fail(data);
1460 g_free(data->guid);
1461 g_free(data->filename);
1462 g_free(data->title);
1463 g_free(data->font);
1464 g_slist_foreach(data->positions, (GFunc) free_check_position, NULL);
1465 g_slist_free(data->positions);
1466 g_slist_foreach(data->items, (GFunc) format_free_item_placement, NULL);
1467 g_slist_free(data->items);
1468 g_free(data);
1469}
1470
1471
1472/* Read a single check format file and append the resulting format to the
1473 * list of all known formats. This function calls other functions to read
1474 * each section of the data file.
1475 */
1476static check_format_t *
1477read_one_check_format(PrintCheckDialog *pcd, const gchar *groupname,
1478 const gchar *dirname, const gchar *file)
1479{
1480 gchar *pathname;
1481 GKeyFile *key_file;
1482 check_format_t *format;
1483
1484 pathname = g_build_filename(dirname, file, (char *)NULL);
1485 key_file = gnc_key_file_load_from_file(pathname, FALSE, FALSE, NULL);
1486 g_free(pathname);
1487 if (!key_file)
1488 {
1489 g_warning("Check file %s, cannot load file", file);
1490 return NULL;
1491 }
1492
1493 format = g_new0(check_format_t, 1);
1494 format->group = groupname;
1495 format->filename = g_strdup(file);
1496 if (format_read_general_info(file, key_file, format))
1497 {
1498 format->positions = format_read_multicheck_info(file, key_file, format);
1499 format->items = format_read_item_placement(file, key_file, format);
1500 }
1501
1502 g_key_file_free(key_file);
1503 if ((NULL == format->title) || (NULL == format->items))
1504 {
1505 g_warning("Check file %s, no items read. Dropping file.", file);
1506 free_check_format(format);
1507 return NULL;
1508 }
1509
1510 return format;
1511}
1512
1513
1514/* Iterate over a single check directory, throwing out any backup files and
1515 * then calling a helper function to read and parse the check format within
1516 * the file.
1517 */
1518static void
1519read_one_check_directory(PrintCheckDialog *pcd, GtkListStore *store,
1520 const gchar *groupname, const gchar *dirname)
1521{
1522 check_format_t *format = NULL, *existing;
1523 GDir *dir;
1524 const gchar *filename;
1525 GtkTreeIter iter;
1526 GtkWidget *dialog;
1527 gboolean found = FALSE;
1528
1529 dir = g_dir_open(dirname, 0, NULL);
1530 if (dir == NULL)
1531 return;
1532
1533 while ((filename = g_dir_read_name(dir)) != NULL)
1534 {
1535 if (g_str_has_prefix(filename, "#"))
1536 continue;
1537 if (!g_str_has_suffix(filename, ".chk"))
1538 continue;
1539
1540 format = read_one_check_format(pcd, groupname, dirname, filename);
1541 if (NULL == format)
1542 continue;
1543
1544 existing = find_existing_format(store, format->guid, NULL);
1545 if (existing)
1546 {
1547 dialog = gtk_message_dialog_new
1548 (GTK_WINDOW(pcd->dialog),
1549 GTK_DIALOG_DESTROY_WITH_PARENT,
1550 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s",
1551 _("There is a duplicate check format file."));
1552 gtk_message_dialog_format_secondary_text
1553 (GTK_MESSAGE_DIALOG(dialog),
1554 /* Translators:
1555 %1$s is the type of the first check format
1556 (user defined or application defined);
1557 %2$s is the filename of that format;
1558 %3$s the type of the other check format; and
1559 %4$s the filename of that other format. */
1560 _("The GUIDs in the %s check format file '%s' and "
1561 "the %s check format file '%s' match."),
1562 existing->group, existing->filename,
1563 format->group, format->filename);
1564 gtk_dialog_run(GTK_DIALOG(dialog));
1565 gtk_widget_destroy(dialog);
1566 free_check_format (format);
1567 }
1568 else
1569 {
1570 gtk_list_store_append(store, &iter);
1571 gtk_list_store_set(store, &iter, COL_NAME, format->title,
1572 COL_DATA, format, -1);
1573 found = TRUE;
1574 }
1575 }
1576 g_dir_close(dir);
1577
1578 /* If any files were added to the list, add a separator between
1579 * this group and the next. */
1580 if (found)
1581 {
1582 gtk_list_store_append(store, &iter);
1583 gtk_list_store_set(store, &iter, COL_SEP, TRUE, -1);
1584 }
1585}
1586
1587
1588/* Read all check formats. This function first looks in the system directory
1589 * for check files, and then looks in the user's .gnucash directory for any
1590 * custom check files.
1591 */
1592static void
1593read_formats(PrintCheckDialog *pcd, GtkListStore *store)
1594{
1595 gchar *dirname, *pkgdatadir;
1596
1597 pkgdatadir = gnc_path_get_pkgdatadir();
1598 dirname = g_build_filename(pkgdatadir, CHECK_FMT_DIR, (char *)NULL);
1599 /* Translators: This is a directory name. It may be presented to
1600 * the user to indicate that some data file was defined by the
1601 * gnucash application. */
1602 read_one_check_directory(pcd, store, _("application"), dirname);
1603 g_free(dirname);
1604 g_free(pkgdatadir);
1605
1606 dirname = gnc_build_userdata_path(CHECK_FMT_DIR);
1607 /* Translators: This is a directory name. It may be presented to
1608 * the user to indicate that some data file was defined by a
1609 * user herself. */
1610 read_one_check_directory(pcd, store, _("user"), dirname);
1611 g_free(dirname);
1612}
1613
1614
1615static gboolean
1616format_is_a_separator (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
1617{
1618 gboolean separator;
1619
1620 gtk_tree_model_get(model, iter, COL_SEP, &separator, -1);
1621 return separator;
1622}
1623
1624
1625static void
1626initialize_format_combobox (PrintCheckDialog *pcd)
1627{
1628 GtkListStore *store;
1629 GtkTreeIter iter;
1630
1631 store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
1632 read_formats(pcd, store);
1633 gtk_list_store_append(store, &iter);
1634 gtk_list_store_set(store, &iter, COL_NAME, _("Custom"), -1);
1635 pcd->format_max = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1636 gtk_combo_box_set_model(GTK_COMBO_BOX(pcd->format_combobox),
1637 GTK_TREE_MODEL(store));
1638 gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(pcd->format_combobox),
1639 format_is_a_separator, NULL, NULL);
1640 g_object_unref (store);
1641}
1642
1643
1644/*****************************************************
1645 * gnc_ui_print_check_dialog_create *
1646 * make a new print check dialog and wait for it. *
1647 * If account is given, this is a parent account to *
1648 * subtotal the amount of all splits under it. *
1649 *****************************************************/
1650void
1651gnc_ui_print_check_dialog_create(GtkWidget *parent,
1652 GList *splits,
1653 Account* account)
1654{
1655 PrintCheckDialog *pcd;
1656 GtkBuilder *builder;
1657 GtkWidget *table;
1658 gchar *font;
1659 Transaction *trans = NULL;
1660
1661 pcd = g_new0(PrintCheckDialog, 1);
1662 pcd->caller_window = GTK_WINDOW(parent);
1663 pcd->splits = g_list_copy(splits);
1664 pcd->account = account;
1665
1666 builder = gtk_builder_new();
1667 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment1");
1668 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment2");
1669 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment3");
1670 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment4");
1671 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment5");
1672 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment6");
1673 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment7");
1674 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment8");
1675 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment9");
1676 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment10");
1677 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment11");
1678 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment12");
1679 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment13");
1680 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment14");
1681 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment15");
1682 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment16");
1683 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment17");
1684 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment18");
1685 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment19");
1686 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment20");
1687 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment21");
1688 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment22");
1689 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment23");
1690 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment24");
1691 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore1");
1692 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore2");
1693 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore3");
1694 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "print_check_dialog");
1695
1696 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
1697
1698 pcd->builder = builder;
1699 pcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "print_check_dialog"));
1700
1701 // Set the name for this dialog so it can be easily manipulated with css
1702 gtk_widget_set_name (GTK_WIDGET(pcd->dialog), "gnc-id-print-check");
1703
1704 /* now pick out the relevant child widgets */
1705 pcd->format_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_format_combobox"));
1706 pcd->position_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_position_combobox"));
1707 pcd->first_page_count = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "first_page_count_entry"));
1708
1709 pcd->custom_table = GTK_WIDGET(gtk_builder_get_object (builder, "custom_table"));
1710 pcd->payee_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_x_entry"));
1711 pcd->payee_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_y_entry"));
1712 pcd->date_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_x_entry"));
1713 pcd->date_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_y_entry"));
1714 pcd->words_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_x_entry"));
1715 pcd->words_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_y_entry"));
1716 pcd->number_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_x_entry"));
1717 pcd->number_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_y_entry"));
1718 pcd->notes_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_x_entry"));
1719 pcd->notes_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_y_entry"));
1720 pcd->memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_x_entry"));
1721 pcd->memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_y_entry"));
1722 pcd->address_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_x_entry"));
1723 pcd->address_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_y_entry"));
1724 pcd->splits_amount_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_x_entry"));
1725 pcd->splits_amount_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_y_entry"));
1726 pcd->splits_memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_x_entry"));
1727 pcd->splits_memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_y_entry"));
1728 pcd->splits_account_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_x_entry"));
1729 pcd->splits_account_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_y_entry"));
1730 pcd->translation_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_x_entry"));
1731 pcd->translation_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_y_entry"));
1732 pcd->translation_label = GTK_WIDGET(gtk_builder_get_object (builder, "translation_label"));
1733 pcd->check_rotation = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "check_rotation_entry"));
1734 pcd->units_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "units_combobox"));
1735
1736 gtk_window_set_transient_for(GTK_WINDOW(pcd->dialog), pcd->caller_window);
1737
1738 /* Create and attach the date-format chooser */
1739 table = GTK_WIDGET(gtk_builder_get_object (builder, "options_table"));
1740 pcd->date_format = gnc_date_format_new_without_label();
1741 gtk_grid_attach (GTK_GRID(table), pcd->date_format, 1, 4, 1, 1);
1742
1743 /* Default font (set in preferences) */
1744 font = gnc_prefs_get_string(GNC_PREFS_GROUP, GNC_PREF_DEFAULT_FONT);
1745 pcd->default_font = font && *font ? font : g_strdup(DEFAULT_FONT);
1746
1747 /* Update the combo boxes bases on the available check formats */
1748 initialize_format_combobox(pcd);
1749
1750 /* address */
1751 pcd->check_address_name = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_name"));
1752 pcd->check_address_1 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_1"));
1753 pcd->check_address_2 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_2"));
1754 pcd->check_address_3 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_3"));
1755 pcd->check_address_4 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_4"));
1756 /* fill in any available address data */
1757 /* Can't access business objects e.g. Customer,Vendor,Employee because
1758 * it would create build problems */
1759 if (g_list_length(pcd->splits) == 1)
1760 {
1761 GncOwner txn_owner;
1762
1763 trans = xaccSplitGetParent((Split *)(pcd->splits->data));
1764 if (gncOwnerGetOwnerFromTxn (trans, &txn_owner))
1765 {
1766 GncOwner owner;
1767 gncOwnerCopy (gncOwnerGetEndOwner (&txn_owner), &owner);
1768
1769 /* Got a business owner, get the address */
1770 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_name), gncOwnerGetName(&owner));
1771 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_1), gncAddressGetAddr1 (gncOwnerGetAddr(&owner)));
1772 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_2), gncAddressGetAddr2 (gncOwnerGetAddr(&owner)));
1773 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_3), gncAddressGetAddr3 (gncOwnerGetAddr(&owner)));
1774 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_4), gncAddressGetAddr4 (gncOwnerGetAddr(&owner)));
1775 }
1776 }
1777
1778 /* Use transaction description as address name if no better address has been found */
1779 if ( trans && (0 == gtk_entry_get_text_length (GTK_ENTRY(pcd->check_address_name))) )
1780 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_name), xaccTransGetDescription(trans));
1781
1782 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "lower_left")));
1783
1784 gnc_ui_print_restore_dialog(pcd);
1785 gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(pcd->dialog), GTK_WINDOW (parent));
1786
1787 g_object_unref(G_OBJECT(builder));
1788 gtk_widget_show_all(pcd->dialog);
1789}
1790
1791
1792/**************************************
1793 * Print check contents to the page. *
1794 **************************************/
1795
1796/* Draw a grid pattern on the page to be printed. This grid is helpful when
1797 * figuring out the offsets for where to print various items on the page.
1798 */
1799static void
1800draw_grid(GtkPrintContext *context, gint width, gint height, const gchar *font)
1801{
1802 const double dash_pattern[2] = { 1.0, 5.0 };
1803 PangoFontDescription *desc;
1804 PangoLayout *layout;
1805 cairo_t *cr;
1806 gchar *text;
1807 gint i;
1808
1809 /* Initialize for printing text */
1810 layout = gtk_print_context_create_pango_layout(context);
1811 desc = pango_font_description_from_string(font);
1812 pango_layout_set_font_description(layout, desc);
1813 pango_font_description_free(desc);
1814 pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
1815 pango_layout_set_width(layout, -1);
1816
1817 /* Set up the line to draw with. */
1818 cr = gtk_print_context_get_cairo_context(context);
1819 cairo_save(cr);
1820 cairo_set_line_width(cr, 1.0);
1821 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
1822 cairo_set_dash(cr, dash_pattern, 2, 0);
1823
1824 /* Draw horizontal lines */
1825 for (i = -200; i < (height + 200); i += 50)
1826 {
1827 text = g_strdup_printf("%d", (int)i);
1828 cairo_move_to(cr, -200, i);
1829 cairo_line_to(cr, width + 200, i);
1830 cairo_stroke(cr);
1831 pango_layout_set_text(layout, text, -1);
1832 cairo_move_to(cr, 0, i);
1833 pango_cairo_show_layout(cr, layout);
1834 g_free(text);
1835 }
1836
1837 /* Draw vertical lines */
1838 for (i = -200; i < (width + 200); i += 50)
1839 {
1840 text = g_strdup_printf("%d", (int)i);
1841 cairo_move_to(cr, i, -200);
1842 cairo_line_to(cr, i, height + 200);
1843 cairo_stroke(cr);
1844 pango_layout_set_text(layout, text, -1);
1845 cairo_move_to(cr, i, 0);
1846 pango_cairo_show_layout(cr, layout);
1847 g_free(text);
1848 }
1849
1850 /* Clean up after ourselves */
1851 cairo_restore(cr);
1852 g_object_unref(layout);
1853}
1854
1855
1856/* Print a single line of text to the printed page. If a width and height
1857 * are specified, the line will be wrapped at the specified width, and the
1858 * resulting text will be clipped if it does not fit in the space
1859 * available.
1860 */
1861static gdouble
1862draw_text(GtkPrintContext *context, const gchar *text, check_item_t *data,
1863 PangoFontDescription *default_desc)
1864{
1865 PangoFontDescription *desc;
1866 PangoLayout *layout;
1867 cairo_t *cr;
1868 gint layout_height, layout_width;
1869 gdouble width, height;
1870 gchar *new_text;
1871
1872 if ((NULL == text) || (strlen(text) == 0))
1873 return 0.0;
1874
1875 /* Initialize for printing text */
1876 layout = gtk_print_context_create_pango_layout(context);
1877 if (data->font)
1878 {
1879 desc = pango_font_description_from_string(data->font);
1880 pango_layout_set_font_description(layout, desc);
1881 pango_font_description_free(desc);
1882 }
1883 else
1884 {
1885 pango_layout_set_font_description(layout, default_desc);
1886 }
1887 pango_layout_set_alignment(layout,
1888 data->w ? data->align : PANGO_ALIGN_LEFT);
1889 pango_layout_set_width(layout, data->w ? data->w * PANGO_SCALE : -1);
1890 pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
1891 if ( data->blocking )
1892 {
1893 new_text = g_strdup_printf("***%s***", text);
1894 pango_layout_set_text(layout, new_text, -1);
1895 g_free(new_text);
1896 }
1897 else
1898 {
1899 pango_layout_set_text(layout, text, -1);
1900 }
1901 pango_layout_get_size(layout, &layout_width, &layout_height);
1902 width = (gdouble) layout_width / PANGO_SCALE;
1903 height = (gdouble) layout_height / PANGO_SCALE;
1904
1905 cr = gtk_print_context_get_cairo_context(context);
1906 cairo_save(cr);
1907
1908 /* Clip text to the enclosing rectangle */
1909 if (data->w && data->h)
1910 {
1911 DEBUG("Text clip rectangle, coords %f,%f, size %f,%f",
1912 data->x, data->y - data->h, data->w, data->h);
1913 cairo_rectangle(cr, data->x, data->y - data->h, data->w, data->h);
1914 cairo_clip_preserve(cr);
1915 }
1916
1917 /* Draw the text */
1918 DEBUG("Text move to %f,%f, print '%s'", data->x, data->y,
1919 text ? text : "(null)");
1920 cairo_move_to(cr, data->x, data->y - height);
1921 pango_cairo_show_layout(cr, layout);
1922
1923 /* Clean up after ourselves */
1924 cairo_restore(cr);
1925 g_object_unref(layout);
1926 return width;
1927
1928}
1929
1930
1931/* Find and load the specified image. If the specified filename isn't an
1932 * absolute path name, this code will also look in the gnucash system check
1933 * format directory, and then in the user's private check format
1934 * directory.
1935 *
1936 * NOTE: The gtk_image_new_from_file() function never fails. If it can't
1937 * find the specified file, it returns the "broken image" icon. This function
1938 * takes advantage of that.
1939*/
1940static GtkWidget *
1941read_image (const gchar *filename)
1942{
1943 GtkWidget *image;
1944 gchar *pkgdatadir, *dirname, *tmp_name;
1945
1946 if (g_path_is_absolute(filename))
1947 return gtk_image_new_from_file(filename);
1948
1949 pkgdatadir = gnc_path_get_pkgdatadir();
1950 tmp_name = g_build_filename(pkgdatadir, CHECK_FMT_DIR, filename, (char *)NULL);
1951 if (!g_file_test(tmp_name, G_FILE_TEST_EXISTS))
1952 {
1953 g_free(tmp_name);
1954 dirname = gnc_build_userdata_path(CHECK_FMT_DIR);
1955 tmp_name = g_build_filename(dirname, filename, (char *)NULL);
1956 g_free(dirname);
1957 }
1958 image = gtk_image_new_from_file(tmp_name);
1959 g_free(tmp_name);
1960 return image;
1961}
1962
1963
1964/* Print a single image to the printed page. This picture will be scaled
1965 * down to fit in the specified size rectangle. Scaling is done with the
1966 * proportions locked 1:1 so as not to distort the image.
1967 */
1968static void
1969draw_picture(GtkPrintContext *context, check_item_t *data)
1970{
1971 cairo_t *cr;
1972 GdkPixbuf *pixbuf, *scaled_pixbuf;
1973 GtkImage *image;
1974 gint pix_w, pix_h;
1975 gdouble scale_w, scale_h, scale;
1976
1977 cr = gtk_print_context_get_cairo_context(context);
1978 cairo_save(cr);
1979
1980 /* Get the picture. */
1981 image = GTK_IMAGE(read_image(data->filename));
1982 pixbuf = gtk_image_get_pixbuf(image);
1983 if (pixbuf)
1984 {
1985 g_object_ref(pixbuf);
1986 }
1987 else
1988 {
1989 GtkIconTheme *def_theme = gtk_icon_theme_get_default ();
1990
1991 g_warning("Filename '%s' cannot be read or understood.",
1992 data->filename);
1993
1994 pixbuf = gtk_icon_theme_load_icon (def_theme,
1995 "image-missing",
1996 16,
1997 GTK_ICON_LOOKUP_USE_BUILTIN,
1998 NULL);
1999 }
2000 pix_w = gdk_pixbuf_get_width(pixbuf);
2001 pix_h = gdk_pixbuf_get_height(pixbuf);
2002
2003 /* Draw the enclosing rectangle */
2004 if (data->w && data->h)
2005 {
2006 cairo_rectangle(cr, data->x, data->y - data->h, data->w, data->h);
2007 DEBUG("Picture clip rectangle, user coords %f,%f, user size %f,%f",
2008 data->x, data->y - data->h, data->w, data->h);
2009 }
2010 else
2011 {
2012 cairo_rectangle(cr, data->x, data->y - pix_h, pix_w, pix_h);
2013 DEBUG("Picture clip rectangle, user coords %f,%f, pic size %d,%d",
2014 data->x, data->y - data->h, pix_w, pix_h);
2015 }
2016 cairo_clip_preserve(cr);
2017
2018 /* Scale down to fit. Never scale up. */
2019 scale_w = scale_h = 1;
2020 if (data->w && (pix_w > data->w))
2021 scale_w = data->w / pix_w;
2022 if (data->h && (pix_h > data->h))
2023 scale_h = data->h / pix_h;
2024 scale = MIN(scale_w, scale_h);
2025
2026 if (scale != 1)
2027 {
2028 scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, pix_w * scale,
2029 pix_h * scale,
2030 GDK_INTERP_BILINEAR);
2031 pix_h = gdk_pixbuf_get_height(scaled_pixbuf);
2032 gdk_cairo_set_source_pixbuf(cr, scaled_pixbuf, data->x,
2033 data->y - pix_h);
2034
2035 g_object_unref(scaled_pixbuf);
2036 }
2037 else
2038 {
2039 gdk_cairo_set_source_pixbuf(cr, pixbuf, data->x, data->y - pix_h);
2040 }
2041 g_object_unref(pixbuf);
2042 cairo_paint(cr);
2043
2044 /* Clean up after ourselves */
2045 cairo_restore(cr);
2046 gtk_widget_destroy(GTK_WIDGET(image));
2047}
2048
2049
2050#define DATE_FMT_HEIGHT 8
2051#define DATE_FMT_SLOP 2
2052
2053/* There is a new Canadian requirement that all software that prints the date
2054 * on a check must also print the format of that date underneath using a 6-8
2055 * point font. This function implements that requirement. It requires the
2056 * font description used in printing the date so that it can print in the same
2057 * font using a smaller point size. It also requires width of the printed
2058 * date as an argument, allowing it to center the format string under the
2059 * date.
2060 *
2061 * Note: This code only prints a date if the user has explicitly requested it
2062 * via a preference setting. This is because gnucash has no way of
2063 * knowing if the user's checks already have a date format printed on them.
2064 */
2065static void
2066draw_date_format(GtkPrintContext *context, const gchar *date_format,
2067 check_item_t *data, PangoFontDescription *default_desc,
2068 gdouble width)
2069{
2070 PangoFontDescription *date_desc;
2071 check_item_t date_item;
2072 gchar *text = NULL, *expanded = NULL;
2073 const gchar *c;
2074 GString *cdn_fmt;
2075
2076 if ( !data->print_date_format ) return;
2077
2078 date_desc = pango_font_description_copy_static(default_desc);
2079 pango_font_description_set_size(date_desc, DATE_FMT_HEIGHT * PANGO_SCALE);
2080 date_item = *data;
2081 date_item.y += (DATE_FMT_HEIGHT + DATE_FMT_SLOP);
2082 date_item.w = width;
2083 date_item.h = DATE_FMT_HEIGHT + DATE_FMT_SLOP;
2084 date_item.align = PANGO_ALIGN_CENTER;
2085
2086 /* This is a date format string. It should only contain ascii. */
2087 cdn_fmt = g_string_new_len(NULL, 50);
2088 for (c = date_format; c && *c; )
2089 {
2090 if ((c[0] != '%') || (c[1] == '\0'))
2091 {
2092 c += 1;
2093 continue;
2094 }
2095 switch (c[1])
2096 {
2097 case 'F':
2098 cdn_fmt = g_string_append(cdn_fmt, "YYYYMMDD");
2099 break;
2100 case 'Y':
2101 cdn_fmt = g_string_append(cdn_fmt, "YYYY");
2102 break;
2103 case 'y':
2104 cdn_fmt = g_string_append(cdn_fmt, "YY");
2105 break;
2106 case 'm':
2107 cdn_fmt = g_string_append(cdn_fmt, "MM");
2108 break;
2109 case 'd':
2110 case 'e':
2111 cdn_fmt = g_string_append(cdn_fmt, "DD");
2112 break;
2113 case 'x':
2114 expanded = g_strdup_printf("%s%s",
2116 c + 2);
2117 c = expanded;
2118 continue;
2119 default:
2120 break;
2121 }
2122 c += 2;
2123 }
2124
2125 text = g_string_free(cdn_fmt, FALSE);
2126 draw_text(context, text, &date_item, date_desc);
2127 g_free(text);
2128 if (expanded)
2129 g_free(expanded);
2130 pango_font_description_free(date_desc);
2131}
2132
2133
2134/* Print each of the items that in the description of a single check. This
2135 * function uses helper functions to print text based and picture based items.
2136 */
2137static void
2138draw_page_items(GtkPrintContext *context,
2139 check_format_t *format, gpointer user_data)
2140{
2141 PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
2142 PangoFontDescription *default_desc;
2143 Transaction *trans;
2144 gnc_numeric amount;
2145 GNCPrintAmountInfo info;
2146 const gchar *date_format;
2147 gchar *text = NULL, buf[100];
2148 GSList *elem;
2149 check_item_t *item;
2150 gdouble width;
2151 gchar *address = NULL;
2152
2153 trans = xaccSplitGetParent(pcd->split);
2154 /* This was valid when the check printing dialog was instantiated. */
2155 g_return_if_fail(trans);
2156 amount = get_check_amount(pcd);
2157
2158 if (format->font)
2159 default_desc = pango_font_description_from_string(format->font);
2160 else
2161 default_desc = pango_font_description_from_string(pcd->default_font);
2162
2163 /* Now put the actual data onto the page. */
2164 for (elem = format->items; elem; elem = g_slist_next(elem))
2165 {
2166 item = elem->data;
2167
2168 switch (item->type)
2169 {
2170 case DATE:
2171 {
2172 GDate date;
2173 g_date_clear (&date, 1);
2174 gnc_gdate_set_time64 (&date, xaccTransGetDate(trans));
2175 date_format =
2176 gnc_date_format_get_custom(GNC_DATE_FORMAT
2177 (pcd->date_format));
2178 g_date_strftime(buf, 100, date_format, &date);
2179 width = draw_text(context, buf, item, default_desc);
2180 draw_date_format(context, date_format, item, default_desc, width);
2181 break;
2182 }
2183
2184 case PAYEE:
2185 draw_text(context, xaccTransGetDescription(trans), item, default_desc);
2186 break;
2187
2188 case NOTES:
2189 draw_text(context, xaccTransGetNotes(trans), item, default_desc);
2190 break;
2191
2192 case MEMO:
2193 draw_text(context, xaccSplitGetMemo(pcd->split), item, default_desc);
2194 break;
2195
2196 case ACTION:
2197 draw_text(context, gnc_get_action_num(trans, pcd->split), item,
2198 default_desc);
2199 break;
2200
2201 case CHECK_NUMBER:
2202 draw_text(context, gnc_get_num_action(trans, pcd->split), item,
2203 default_desc);
2204 break;
2205
2206 case AMOUNT_NUMBER:
2207 info = gnc_default_print_info(FALSE);
2208 draw_text(context, xaccPrintAmount(amount, info),
2209 item, default_desc);
2210 break;
2211
2212 case AMOUNT_WORDS:
2213 text = numeric_to_words(amount);
2214 draw_text(context, text, item, default_desc);
2215 g_free(text);
2216 break;
2217
2218 case TEXT:
2219 draw_text(context, item->text, item, default_desc);
2220 break;
2221
2222 case ADDRESS:
2223 address = get_check_address(pcd);
2224 draw_text(context, address, item, default_desc);
2225 g_free(address);
2226 break;
2227
2228 case SPLITS_AMOUNT:
2229 text = get_check_splits_amount(pcd);
2230 draw_text(context, text, item, default_desc);
2231 g_free(text);
2232 break;
2233
2234 case SPLITS_MEMO:
2235 text = get_check_splits_memo(pcd);
2236 draw_text(context, text, item, default_desc);
2237 g_free(text);
2238 break;
2239
2240 case SPLITS_ACCOUNT:
2241 text = get_check_splits_account(pcd);
2242 draw_text(context, text, item, default_desc);
2243 g_free(text);
2244 break;
2245
2246 case PICTURE:
2247 draw_picture(context, item);
2248 break;
2249
2250 default:
2251 text = g_strdup_printf("(unknown check field, type %d)", item->type);
2252 draw_text(context, text, item, default_desc);
2253 g_free(text);
2254 break;
2255 }
2256 }
2257
2258 pango_font_description_free(default_desc);
2259}
2260
2261
2262/* Print each of the items that in the description of a single check. This
2263 * function uses helper functions to print text based and picture based items.
2264 */
2265static void
2266draw_page_boxes(GtkPrintContext *context,
2267 check_format_t *format, gpointer user_data)
2268{
2269 cairo_t *cr;
2270 GSList *elem;
2271 check_item_t *item;
2272
2273 cr = gtk_print_context_get_cairo_context(context);
2274
2275 /* Now put the actual data onto the page. */
2276 for (elem = format->items; elem; elem = g_slist_next(elem))
2277 {
2278 item = elem->data;
2279 if (!item->w || !item->h)
2280 continue;
2281 cairo_rectangle(cr, item->x, item->y - item->h, item->w, item->h);
2282 cairo_stroke(cr);
2283 }
2284}
2285
2286
2287/* Print an entire page based upon the layout in a check description file. This
2288 * function takes care of translating/rotating the page, calling the function to
2289 * print the grid pattern (if requested), and calls a helper function to print
2290 * all check items.
2291 */
2292static void
2293draw_check_format(GtkPrintContext *context, gint position,
2294 check_format_t *format, gpointer user_data)
2295{
2296 PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
2297 gdouble x, y, r, multip;
2298 cairo_t *cr = gtk_print_context_get_cairo_context(context);
2299
2300 /* Translate all subsequent check items if required. */
2301 if ((position > 0) && (position < pcd->position_max))
2302 {
2303 /* Standard positioning is used.
2304 * Note that the first check on the page (position 0) doesn't
2305 * need to be moved (hence the test for position > 0 above. */
2306 cairo_translate(cr, 0, format->height); /* Translation is relative to previous
2307 check translation, not to page border ! */
2308 DEBUG("Position %d translated by %f relative to previous check (pre-defined)", position, format->height);
2309 DEBUG(" by %f relative to page (pre-defined)", position * format->height);
2310 }
2311 else if (position == pcd->position_max)
2312 {
2313 /* Custom positioning is used. */
2314 multip = pcd_get_custom_multip(pcd);
2315 x = multip * gtk_spin_button_get_value(pcd->translation_x);
2316 y = multip * gtk_spin_button_get_value(pcd->translation_y);
2317 cairo_translate(cr, x, y);
2318 DEBUG("Position translated by %f,%f (custom)", x, y);
2319 r = gtk_spin_button_get_value(pcd->check_rotation);
2320 cairo_rotate(cr, r * DEGREES_TO_RADIANS);
2321 DEBUG("Position rotated by %f degrees (custom)", r);
2322 }
2323
2324 /* Draw layout boxes if requested. Also useful when determining check
2325 * layouts. */
2326 if (format->show_boxes)
2327 draw_page_boxes(context, format, user_data);
2328
2329 /* Draw the actual check data. */
2330 draw_page_items(context, format, user_data);
2331}
2332
2333
2334static void
2335draw_check_custom(GtkPrintContext *context, gpointer user_data)
2336{
2337 PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
2338 GNCPrintAmountInfo info;
2339 PangoFontDescription *desc;
2340 Transaction *trans;
2341 gnc_numeric amount;
2342 cairo_t *cr;
2343 const gchar *date_format;
2344 gchar *text = NULL, buf[100];
2345 check_item_t item = { 0 };
2346 gdouble x, y, multip, degrees;
2347 GDate date;
2348 gchar *address;
2349
2350 trans = xaccSplitGetParent(pcd->split);
2351 /* This was valid when the check printing dialog was instantiated. */
2352 g_return_if_fail(trans);
2353
2354 desc = pango_font_description_from_string(pcd->default_font);
2355
2356 multip = pcd_get_custom_multip(pcd);
2357 degrees = gtk_spin_button_get_value(pcd->check_rotation);
2358 cr = gtk_print_context_get_cairo_context(context);
2359 cairo_rotate(cr, degrees * DEGREES_TO_RADIANS);
2360 DEBUG("Page rotated by %f degrees", degrees);
2361
2362 x = multip * gtk_spin_button_get_value(pcd->translation_x);
2363 y = multip * gtk_spin_button_get_value(pcd->translation_y);
2364 cairo_translate(cr, x, y);
2365 DEBUG("Page translated by %f,%f", x, y);
2366
2367 item.x = multip * gtk_spin_button_get_value(pcd->payee_x);
2368 item.y = multip * gtk_spin_button_get_value(pcd->payee_y);
2369 draw_text(context, xaccTransGetDescription(trans), &item, desc);
2370
2371 item.x = multip * gtk_spin_button_get_value(pcd->date_x);
2372 item.y = multip * gtk_spin_button_get_value(pcd->date_y);
2373 g_date_clear (&date, 1);
2374 gnc_gdate_set_time64 (&date, xaccTransGetDate(trans));
2375 date_format = gnc_date_format_get_custom(GNC_DATE_FORMAT(pcd->date_format));
2376 g_date_strftime(buf, 100, date_format, &date);
2377 draw_text(context, buf, &item, desc);
2378
2379 item.x = multip * gtk_spin_button_get_value(pcd->number_x);
2380 item.y = multip * gtk_spin_button_get_value(pcd->number_y);
2381 info = gnc_default_print_info(FALSE);
2382 amount = gnc_numeric_abs(xaccSplitGetAmount(pcd->split));
2383 draw_text(context, xaccPrintAmount(amount, info), &item, desc);
2384
2385 item.x = multip * gtk_spin_button_get_value(pcd->words_x);
2386 item.y = multip * gtk_spin_button_get_value(pcd->words_y);
2387 text = numeric_to_words(amount);
2388 draw_text(context, text, &item, desc);
2389 g_free(text);
2390
2391 item.x = multip * gtk_spin_button_get_value(pcd->address_x);
2392 item.y = multip * gtk_spin_button_get_value(pcd->address_y);
2393 address = get_check_address(pcd);
2394 draw_text(context, address, &item, desc);
2395 g_free(address);
2396
2397 item.x = multip * gtk_spin_button_get_value(pcd->splits_amount_x);
2398 item.y = multip * gtk_spin_button_get_value(pcd->splits_amount_y);
2399 text = get_check_splits_amount(pcd);
2400 draw_text(context, text, &item, desc);
2401 g_free(text);
2402
2403 item.x = multip * gtk_spin_button_get_value(pcd->splits_memo_x);
2404 item.y = multip * gtk_spin_button_get_value(pcd->splits_memo_y);
2405 text = get_check_splits_memo(pcd);
2406 draw_text(context, text, &item, desc);
2407 g_free(text);
2408
2409 item.x = multip * gtk_spin_button_get_value(pcd->splits_account_x);
2410 item.y = multip * gtk_spin_button_get_value(pcd->splits_account_y);
2411 text = get_check_splits_account(pcd);
2412 draw_text(context, text, &item, desc);
2413 g_free(text);
2414
2415 item.x = multip * gtk_spin_button_get_value(pcd->notes_x);
2416 item.y = multip * gtk_spin_button_get_value(pcd->notes_y);
2417 draw_text(context, xaccTransGetNotes(trans), &item, desc);
2418
2419 item.x = multip * gtk_spin_button_get_value(pcd->memo_x);
2420 item.y = multip * gtk_spin_button_get_value(pcd->memo_y);
2421 draw_text(context, xaccSplitGetMemo(pcd->split), &item, desc);
2422
2423 pango_font_description_free(desc);
2424}
2425
2426
2427/* Print a page of checks. This takes into account the number of checks to print,
2428 * the number of checks on a page, and the starting check position on the page.
2429 * This function is called once by the GtkPrint code once for each page to be printed.
2430 */
2431static void
2432draw_page(GtkPrintOperation *operation,
2433 GtkPrintContext *context, gint page_nr, gpointer user_data)
2434{
2435 PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
2436 check_format_t *format;
2437 cairo_t *cr = gtk_print_context_get_cairo_context(context);
2438
2439 format = pcd->selected_format;
2440 if (format)
2441 {
2442 gint first_check, last_check;
2443 gint first_page_count;
2444 guint check_count = g_list_length(pcd->splits);
2445 gint check_number;
2446 gint position = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2447 gint last_blank_check_pos;
2448 gint checks_per_page;
2449 GList *next_split;
2450
2451 if (position == pcd->position_max)
2452 {
2453 /* Custom position, one check per page */
2454 checks_per_page = 1;
2455 first_page_count = 1;
2456 }
2457 else
2458 {
2459 checks_per_page = pcd->position_max;
2460 first_page_count = gtk_spin_button_get_value_as_int(pcd->first_page_count);
2461 }
2462
2463 if (page_nr == 0)
2464 {
2465 first_check = 0;
2466 last_check = first_page_count - 1;
2467 next_split = pcd->splits;
2468 }
2469 else
2470 {
2471 first_check = first_page_count + (page_nr - 1) * checks_per_page;
2472 last_check = MIN(check_count - 1, first_check + checks_per_page - 1);
2473 next_split = g_list_nth(pcd->splits, first_check);
2474 /* If position is not "custom" reset it to top */
2475 if (position < pcd->position_max)
2476 position = 0;
2477 }
2478
2479 /* Do page level translations/rotations */
2480 cairo_translate(cr, format->trans_x, format->trans_y);
2481 DEBUG("Page translated by %f,%f", format->trans_x, format->trans_y);
2482 cairo_rotate(cr, format->rotation * DEGREES_TO_RADIANS);
2483 DEBUG("Page rotated by %f degrees", format->rotation);
2484
2485 /* The grid is useful when determining check layouts */
2486 if (format->show_grid)
2487 {
2488 draw_grid(context,
2489 gtk_print_context_get_width(context),
2490 gtk_print_context_get_height(context),
2491 pcd->default_font);
2492 }
2493
2494 last_blank_check_pos = position - 1;
2495 /* Optionally skip blank check positions if */
2496 if ((page_nr == 0) /* on first page AND */
2497 && (last_blank_check_pos > 0) /* there's more than one blank check */
2498 && (position < pcd->position_max)) /* but don't skip for custom positioning */
2499 cairo_translate(cr, 0, format->height * last_blank_check_pos);
2500
2501 for (check_number = first_check; check_number <= last_check;
2502 check_number++, position++)
2503 {
2504 pcd->split = (Split *) next_split->data;
2505 next_split = g_list_next(next_split);
2506 draw_check_format(context, position, format, user_data);
2507 }
2508 }
2509 else
2510 {
2511 /* Custom check format */
2512 pcd->split = (Split *) g_list_nth_data(pcd->splits, page_nr);
2513 g_return_if_fail(pcd->split);
2514 draw_check_custom(context, user_data);
2515 }
2516}
2517
2518
2519/* Compute the number of pages required to complete this print operation.
2520 * This function is called once by the GtkPrint code to determine the number
2521 * of pages required to complete the print operation.
2522 */
2523static void
2524begin_print(GtkPrintOperation *operation,
2525 GtkPrintContext *context, gpointer user_data)
2526{
2527 PrintCheckDialog *pcd = (PrintCheckDialog *) user_data;
2528 guint check_count = g_list_length(pcd->splits);
2529 gint pages;
2530 gint position = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2531
2532 if (pcd->selected_format /* User selected a format other than custom */
2533 && pcd->position_max > 1 /* The format has more than one check per page
2534 (position_max is equivalent to custom
2535 positioning, and there need to be at least two
2536 other check defined positions (0 and 1), so
2537 custom positioning should be at least
2538 at position 2, i.e. >1) */
2539 && position < pcd->position_max) /* User chose a check position other
2540 then custom (which is always at
2541 position_max in the list) */
2542 {
2543 gint first_page_count, remaining_count;
2544
2545 first_page_count = gtk_spin_button_get_value_as_int(pcd->first_page_count);
2546 remaining_count = check_count - first_page_count;
2547 pages = 1 /* First page, will have first_page_count checks */
2548 + remaining_count / pcd->position_max;
2549 /* Subsequent pages with all positions filled */
2550 if ((remaining_count % pcd->position_max) > 0)
2551 pages++; /* Last page, not all positions are filled. Needs to be added
2552 separately because integer division rounds towards 0 and
2553 would omit the last checks if they didn't fill a full page */
2554 }
2555 else
2556 pages = check_count;
2557 gtk_print_operation_set_n_pages(operation, pages);
2558}
2559
2560
2561/************************************
2562 * gnc_ui_print_check_dialog_ok_cb *
2563 ************************************/
2564static void
2565gnc_ui_print_check_dialog_ok_cb(PrintCheckDialog *pcd)
2566{
2567 GtkPrintOperation *print;
2568 GtkPrintOperationResult res;
2569
2570 print = gtk_print_operation_new();
2571
2572 gnc_print_operation_init(print, "GnuCash-Checks");
2573 gtk_print_operation_set_unit(print, GTK_UNIT_POINTS);
2574 gtk_print_operation_set_use_full_page(print, TRUE);
2575 g_signal_connect(print, "begin_print", G_CALLBACK(begin_print), pcd);
2576 g_signal_connect(print, "draw_page", G_CALLBACK(draw_page), pcd);
2577
2578 res = gtk_print_operation_run(print,
2579 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
2580 pcd->caller_window, NULL);
2581
2582 if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
2584
2585 g_object_unref(print);
2586}
2587
2588
2589static void
2590gnc_print_check_set_sensitive (GtkWidget *widget, gpointer data)
2591{
2592 gboolean sensitive;
2593 if (GTK_IS_LABEL(widget) || GTK_IS_SEPARATOR(widget))
2594 return;
2595 sensitive = GPOINTER_TO_INT(data);
2596 gtk_widget_set_sensitive(widget, sensitive);
2597}
2598
2599
2600void
2601gnc_print_check_format_changed (GtkComboBox *widget,
2602 PrintCheckDialog *pcd)
2603{
2604 GtkListStore *p_store;
2605 GtkTreeModel *f_model;
2606 GtkTreeIter f_iter, iter;
2607 gboolean sensitive;
2608 gint pnum;
2609 check_format_t *format;
2610 gboolean separator;
2611 GSList *elem;
2612
2613 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pcd->format_combobox), &f_iter))
2614 return;
2615 f_model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
2616 gtk_tree_model_get(f_model, &f_iter, COL_DATA, &format, COL_SEP, &separator, -1);
2617 if (separator)
2618 return;
2619
2620 pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2621
2622 /* Update the positions combobox */
2623 pcd->selected_format = format;
2624 p_store = gtk_list_store_new (1, G_TYPE_STRING);
2625 gtk_combo_box_set_model(GTK_COMBO_BOX(pcd->position_combobox),
2626 GTK_TREE_MODEL(p_store));
2627 if (format)
2628 {
2629 if (format->positions)
2630 {
2631 pcd->position_max = g_slist_length(format->positions); /* -1 for 0 base, +1 for custom entry */
2632 for (elem = format->positions; elem; elem = g_slist_next(elem))
2633 {
2634 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2635 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, elem->data, -1);
2636 }
2637 }
2638 else
2639 {
2640 /* Invent a "Top" position if format has no positions */
2641 pcd->position_max = 1;
2642 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2643 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Top"), -1);
2644 }
2645 }
2646 else
2647 {
2648 pcd->position_max = 0;
2649 }
2650 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2651 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Custom"), -1);
2652 g_object_unref (p_store);
2653
2654 /* If there's only one thing in the position combobox, make it insensitive */
2655 sensitive = (pcd->position_max > 0);
2656 gtk_widget_set_sensitive(GTK_WIDGET(pcd->position_combobox), sensitive);
2657
2658 /* Update the custom page, this must be done before setting the active
2659 entry in the position combo box since gnc_print_check_position_changed
2660 will adjust these settings in some cases. */
2661 sensitive = (!separator && !format);
2662 gtk_container_foreach(GTK_CONTAINER(pcd->custom_table),
2663 gnc_print_check_set_sensitive,
2664 GINT_TO_POINTER(sensitive));
2665
2666 /* Set the active entry in the position combo box, this will trigger a
2667 call to gnc_print_check_position_changed */
2668 pnum = MAX(MIN(pnum, pcd->position_max), 0);
2669 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->position_combobox), pnum);
2670
2671 /* Update address fields */
2672 sensitive = check_format_has_address(pcd);
2673 gtk_widget_set_sensitive(pcd->check_address_name, sensitive);
2674 gtk_widget_set_sensitive(pcd->check_address_1, sensitive);
2675 gtk_widget_set_sensitive(pcd->check_address_2, sensitive);
2676 gtk_widget_set_sensitive(pcd->check_address_3, sensitive);
2677 gtk_widget_set_sensitive(pcd->check_address_4, sensitive);
2678}
2679
2680
2681void
2682gnc_print_check_position_changed (GtkComboBox *widget,
2683 PrintCheckDialog *pcd)
2684{
2685 gboolean sensitive;
2686 gint pnum;
2687 guint check_count;
2688 gint first_page_max, first_page_min, first_page_value;
2689
2690 pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2691
2692 /* Make the translation and rotation fields active if the position is "custom" */
2693 sensitive = pnum == pcd->position_max;
2694 gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_x), sensitive);
2695 gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_y), sensitive);
2696 gtk_widget_set_sensitive(GTK_WIDGET(pcd->check_rotation), sensitive);
2697 gtk_widget_set_sensitive(GTK_WIDGET(pcd->units_combobox), sensitive);
2698
2699 /* Set up the first page check count spin box */
2700 check_count = g_list_length(pcd->splits);
2701 first_page_max = MAX(1, MIN(pcd->position_max - pnum, check_count));
2702 first_page_min = 1;
2703 pnum = gtk_spin_button_get_value_as_int(pcd->first_page_count);
2704 first_page_value = MAX(MIN(pnum, first_page_max), first_page_min);
2705 gtk_spin_button_set_range(pcd->first_page_count, (gdouble)first_page_min, (gdouble)first_page_max);
2706 gtk_spin_button_set_value(pcd->first_page_count, (gdouble)first_page_value);
2707 sensitive = first_page_max > 1;
2708 gtk_widget_set_sensitive(GTK_WIDGET(pcd->first_page_count), sensitive);
2709}
2710
2711
2712void
2713gnc_ui_print_check_response_cb(GtkDialog *dialog,
2714 gint response,
2715 PrintCheckDialog *pcd)
2716{
2717 switch (response)
2718 {
2719 case GTK_RESPONSE_HELP:
2720 gnc_gnome_help (GTK_WINDOW(dialog), DF_MANUAL, DL_PRINTCHECK);
2721 return;
2722
2723 case GTK_RESPONSE_OK:
2724 gnc_ui_print_check_dialog_ok_cb(pcd);
2725 gnc_ui_print_save_dialog(pcd);
2726 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(dialog));
2727 break;
2728
2729 case GTK_RESPONSE_CANCEL:
2730 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(dialog));
2731 break;
2732 }
2733
2734 gtk_widget_destroy(pcd->dialog);
2735 g_free(pcd->default_font);
2736 g_list_free(pcd->splits);
2737 g_free(pcd);
2738}
@ COL_NAME
This column holds a copy of the check format name and is what is displayed to the user in the combobo...
@ COL_DATA
This column holds a pointer to the check format data read in from a file.
@ COL_SEP
This column contains the value TRUE if this entry specifies a separator line.
void gnc_print_operation_init(GtkPrintOperation *op, const gchar *jobname)
If print settings have been saved by gnc_print_operation_save_print_settings(), then set them on the ...
void gnc_print_operation_save_print_settings(GtkPrintOperation *op)
Retrieve the print settings from the GtkPrintOperation op and save them in a static variable.
void gnc_gdate_set_time64(GDate *gd, time64 time)
Set a GDate to a time64.
const gchar * qof_date_format_get_string(QofDateFormat df)
This function returns a strftime formatting string for printing an all numeric date (e....
Definition gnc-date.cpp:502
@ QOF_DATE_FORMAT_LOCALE
Take from locale information.
Definition gnc-date.h:128
@ QOF_DATE_FORMAT_CUSTOM
Used by the check printing code.
Definition gnc-date.h:130
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
gnc_numeric xaccTransGetAccountAmount(const Transaction *trans, const Account *acc)
Same as xaccTransGetAccountValue, but uses the Account's commodity.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
GList SplitList
GList of Split.
Definition gnc-engine.h:207
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
gboolean gnc_key_file_save_to_file(const gchar *filename, GKeyFile *key_file, GError **error)
Write a key/value file from memory to disk.
GKeyFile * gnc_key_file_load_from_file(const gchar *filename, gboolean ignore_error, gboolean return_empty_struct, GError **caller_error)
Open and read a key/value file from disk into memory.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
Definition guid.h:84
void guid_replace(GncGUID *guid)
Generate a new guid.
Definition guid.cpp:178
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Definition guid.cpp:208
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome's yelp for linux, and open to a given link within a gi...
char * gnc_get_account_name_for_register(const Account *account)
Get either the full name of the account or the simple name, depending on the configuration parameter ...
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
const GncOwner * gncOwnerGetEndOwner(const GncOwner *owner)
Get the "parent" Owner or GncGUID thereof.
Definition gncOwner.c:572
gboolean gncOwnerGetOwnerFromTxn(Transaction *txn, GncOwner *owner)
Convenience function to get the owner from a transaction.
Definition gncOwner.c:674
gboolean gnc_prefs_set_float(const gchar *group, const gchar *pref_name, gdouble value)
Store a float value into the preferences backend.
gdouble gnc_prefs_get_float(const gchar *group, const gchar *pref_name)
Get an float value from the preferences backend.
gint gnc_prefs_get_int(const gchar *group, const gchar *pref_name)
Get an integer value from the preferences backend.
void gnc_prefs_get_coords(const gchar *group, const gchar *pref_name, gdouble *x, gdouble *y)
Get a pair of coordinates from the preferences backend.
void gnc_prefs_reset(const gchar *group, const gchar *pref_name)
Reset a preference to its default value in the preferences backend.
gboolean gnc_prefs_set_coords(const gchar *group, const gchar *pref_name, gdouble x, gdouble y)
Store coordinates into the preferences backend.
gchar * gnc_prefs_get_string(const gchar *group, const gchar *pref_name)
Get a string value from the preferences backend.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gboolean gnc_prefs_set_string(const gchar *group, const gchar *pref_name, const gchar *value)
Store a string into the preferences backend.
gboolean gnc_prefs_set_int(const gchar *group, const gchar *pref_name, gint value)
Store an integer value into the preferences backend.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
STRUCTS.
The type used to store guids in C.
Definition guid.h:75
gdouble trans_x
Move entire page left by this amount.
gboolean show_grid
Print a grid pattern on the page.
gboolean print_date_format
Default for printing date format characters for this page of checks.
const gchar * group
The group where this format was found.
gboolean show_boxes
Print boxes when width and height are known.
gchar * font
Default font for this page of checks.
gchar * filename
The name of the file from which this data was read.
gchar * title
Title of this check format.
gdouble rotation
Rotate the entire page by this amount.
gdouble height
Height of one check on a page.
gboolean blocking
Default for printing blocking characters for this page of checks.
GSList * items
List of items printed on each check.
gdouble trans_y
Move entire page down by this amount.
gchar * guid
Unique identifier for this format.
GSList * positions
Names of the checks on the page.
gdouble h
Optional.
gdouble y
The x/y coordinates where this item should be printed.
PangoAlignment align
The alignment of a text based item.
gchar * text
The text to be displayed (for text based items.) Otherwise unused.
CheckItemType type
What type of item is this?

◆ G_LOG_DOMAIN

#define G_LOG_DOMAIN   "gnc.printing.checks"

Definition at line 60 of file dialog-print-check.c.

◆ GNC_PREF_BLOCKING_CHARS

#define GNC_PREF_BLOCKING_CHARS   "blocking-chars"

Definition at line 83 of file dialog-print-check.c.

◆ GNC_PREF_CHECK_FORMAT_GUID

#define GNC_PREF_CHECK_FORMAT_GUID   "check-format-guid"

Definition at line 67 of file dialog-print-check.c.

◆ GNC_PREF_CHECK_POSITION

#define GNC_PREF_CHECK_POSITION   "check-position"

Definition at line 68 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_ADDRESS

#define GNC_PREF_CUSTOM_ADDRESS   "custom-address"

Definition at line 75 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_DATE

#define GNC_PREF_CUSTOM_DATE   "custom-date"

Definition at line 72 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_MEMO

#define GNC_PREF_CUSTOM_MEMO   "custom-memo"

Definition at line 77 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_NOTES

#define GNC_PREF_CUSTOM_NOTES   "custom-notes"

Definition at line 76 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_NUMBER

#define GNC_PREF_CUSTOM_NUMBER   "custom-amount-number"

Definition at line 74 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_PAYEE

#define GNC_PREF_CUSTOM_PAYEE   "custom-payee"

Definition at line 71 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_ROTATION

#define GNC_PREF_CUSTOM_ROTATION   "custom-rotation"

Definition at line 79 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_TRANSLATION

#define GNC_PREF_CUSTOM_TRANSLATION   "custom-translation"

Definition at line 78 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_UNITS

#define GNC_PREF_CUSTOM_UNITS   "custom-units"

Definition at line 80 of file dialog-print-check.c.

◆ GNC_PREF_CUSTOM_WORDS

#define GNC_PREF_CUSTOM_WORDS   "custom-amount-words"

Definition at line 73 of file dialog-print-check.c.

◆ GNC_PREF_DATE_FORMAT_USER

#define GNC_PREF_DATE_FORMAT_USER   "date-format-user"

Definition at line 70 of file dialog-print-check.c.

◆ GNC_PREF_DEFAULT_FONT

#define GNC_PREF_DEFAULT_FONT   "default-font"

Definition at line 82 of file dialog-print-check.c.

◆ GNC_PREF_FIRST_PAGE_COUNT

#define GNC_PREF_FIRST_PAGE_COUNT   "first-page-count"

Definition at line 69 of file dialog-print-check.c.

◆ GNC_PREF_PRINT_DATE_FMT

#define GNC_PREF_PRINT_DATE_FMT   "print-date-format"

Definition at line 81 of file dialog-print-check.c.

◆ GNC_PREF_SPLITS_ACCOUNT

#define GNC_PREF_SPLITS_ACCOUNT   "splits-account"

Definition at line 86 of file dialog-print-check.c.

◆ GNC_PREF_SPLITS_AMOUNT

#define GNC_PREF_SPLITS_AMOUNT   "splits-amount"

Definition at line 84 of file dialog-print-check.c.

◆ GNC_PREF_SPLITS_MEMO

#define GNC_PREF_SPLITS_MEMO   "splits-memo"

Definition at line 85 of file dialog-print-check.c.

◆ GNC_PREFS_GROUP

#define GNC_PREFS_GROUP   "dialogs.checkprinting"

Definition at line 66 of file dialog-print-check.c.

◆ KF_GROUP_ITEMS

#define KF_GROUP_ITEMS   "Check Items"

Definition at line 99 of file dialog-print-check.c.

◆ KF_GROUP_POS

#define KF_GROUP_POS   "Check Positions"

Definition at line 98 of file dialog-print-check.c.

◆ KF_GROUP_TOP

#define KF_GROUP_TOP   "Top"

Definition at line 97 of file dialog-print-check.c.

◆ KF_KEY_ALIGN

#define KF_KEY_ALIGN   "Align"

Definition at line 105 of file dialog-print-check.c.

◆ KF_KEY_BLOCKING

#define KF_KEY_BLOCKING   "Blocking_Chars"

Definition at line 106 of file dialog-print-check.c.

◆ KF_KEY_COORDS

#define KF_KEY_COORDS   "Coords"

Definition at line 112 of file dialog-print-check.c.

◆ KF_KEY_DATE_FORMAT

#define KF_KEY_DATE_FORMAT   "DateFormat"

Definition at line 115 of file dialog-print-check.c.

◆ KF_KEY_FILENAME

#define KF_KEY_FILENAME   "Filename"

Definition at line 114 of file dialog-print-check.c.

◆ KF_KEY_FONT

#define KF_KEY_FONT   "Font"

Definition at line 104 of file dialog-print-check.c.

◆ KF_KEY_GUID

#define KF_KEY_GUID   "Guid"

Definition at line 100 of file dialog-print-check.c.

◆ KF_KEY_HEIGHT

#define KF_KEY_HEIGHT   "Height"

Definition at line 110 of file dialog-print-check.c.

◆ KF_KEY_NAMES

#define KF_KEY_NAMES   "Names"

Definition at line 109 of file dialog-print-check.c.

◆ KF_KEY_ROTATION

#define KF_KEY_ROTATION   "Rotation"

Definition at line 102 of file dialog-print-check.c.

◆ KF_KEY_SHOW_BOXES

#define KF_KEY_SHOW_BOXES   "Show_Boxes"

Definition at line 108 of file dialog-print-check.c.

◆ KF_KEY_SHOW_GRID

#define KF_KEY_SHOW_GRID   "Show_Grid"

Definition at line 107 of file dialog-print-check.c.

◆ KF_KEY_SPLITS_ACCOUNT

#define KF_KEY_SPLITS_ACCOUNT   "SplitsAccount"

Definition at line 118 of file dialog-print-check.c.

◆ KF_KEY_SPLITS_AMOUNT

#define KF_KEY_SPLITS_AMOUNT   "SplitsAmount"

Definition at line 116 of file dialog-print-check.c.

◆ KF_KEY_SPLITS_MEMO

#define KF_KEY_SPLITS_MEMO   "SplitsMemo"

Definition at line 117 of file dialog-print-check.c.

◆ KF_KEY_TEXT

#define KF_KEY_TEXT   "Text"

Definition at line 113 of file dialog-print-check.c.

◆ KF_KEY_TITLE

#define KF_KEY_TITLE   "Title"

Definition at line 101 of file dialog-print-check.c.

◆ KF_KEY_TRANSLATION

#define KF_KEY_TRANSLATION   "Translation"

Definition at line 103 of file dialog-print-check.c.

◆ KF_KEY_TYPE

#define KF_KEY_TYPE   "Type"

Definition at line 111 of file dialog-print-check.c.

Enumeration Type Documentation

◆ CheckItemType

enum CheckItemType

Definition at line 174 of file dialog-print-check.c.

◆ format_combo_col

Enumerator
COL_NAME 

This column holds a copy of the check format name and is what is displayed to the user in the combobox.

It is NULL for separator lines.

COL_DATA 

This column holds a pointer to the check format data read in from a file.

It is NULL for the custom check format and for separator lines.

COL_SEP 

This column contains the value TRUE if this entry specifies a separator line.

Definition at line 122 of file dialog-print-check.c.

123{
124 COL_NAME = 0,
128 COL_DATA,
132 COL_SEP,
format_combo_col

Function Documentation

◆ get_check_address()

gchar * get_check_address ( PrintCheckDialog *  pcd)

Definition at line 361 of file dialog-print-check.c.

362{
363 gchar *address;
364 address = g_strconcat(gtk_entry_get_text(GTK_ENTRY(pcd->check_address_name)), "\n",
365 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_1)), "\n",
366 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_2)), "\n",
367 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_3)), "\n",
368 gtk_entry_get_text(GTK_ENTRY(pcd->check_address_4)),
369 NULL);
370 return address;
371}

◆ get_check_splits_account()

gchar * get_check_splits_account ( PrintCheckDialog *  pcd)

Definition at line 494 of file dialog-print-check.c.

495{
496 gchar* account = NULL;
497 Transaction *trans;
498 GList *node;
499 SplitList* s_list;
500
501 trans = xaccSplitGetParent(pcd->split);
502 s_list = xaccTransGetSplitList(trans);
503 if ( !s_list ) return NULL;
504
505 account = g_strconcat("", NULL);
506 node = s_list;
507 while ( node )
508 {
509 Split *split = node->data;
510 /* Include all splits except the main split for the check */
511 if (split != pcd->split)
512 {
513 gchar* account_temp;
514 const gchar* aName = NULL;
515 Account *pAccount;
516 pAccount = xaccSplitGetAccount(split);
517 aName = gnc_get_account_name_for_register(pAccount);
518 account_temp = account;
519 if (account && *account)
520 account = g_strconcat(account_temp, "\n", aName, NULL);
521 else
522 account = g_strconcat(account_temp, aName, NULL);
523 g_free(account_temp);
524 }
525 node = node->next;
526 }
527 return account;
528}

◆ get_check_splits_amount()

gchar * get_check_splits_amount ( PrintCheckDialog *  pcd)

Definition at line 418 of file dialog-print-check.c.

419{
420 gchar* amount = NULL;
421 Transaction *trans;
422 GList *node;
423 SplitList* s_list;
424
425 trans = xaccSplitGetParent(pcd->split);
426 s_list = xaccTransGetSplitList(trans);
427 if ( !s_list ) return NULL;
428
429 amount = g_strconcat("", NULL);
430 node = s_list;
431 while ( node )
432 {
433 Split *split = node->data;
434 /* Include all splits except the main split for the check */
435 if (split != pcd->split)
436 {
437 const gchar* split_amount;
438 gchar* amt_temp;
439 split_amount = xaccPrintAmount(xaccSplitGetAmount(split), gnc_split_amount_print_info(split, TRUE));
440 amt_temp = amount;
441 if (amount && *amount)
442 amount = g_strconcat(amt_temp, "\n", split_amount, NULL);
443 else
444 amount = g_strconcat(amt_temp, split_amount, NULL);
445 g_free(amt_temp);
446 }
447 node = node->next;
448 }
449 return amount;
450}

◆ get_check_splits_memo()

gchar * get_check_splits_memo ( PrintCheckDialog *  pcd)

Definition at line 456 of file dialog-print-check.c.

457{
458 gchar* memo = NULL;
459 const gchar* split_memo;
460 Transaction *trans;
461 GList *node;
462 SplitList* s_list;
463
464 trans = xaccSplitGetParent(pcd->split);
465 s_list = xaccTransGetSplitList(trans);
466 if ( !s_list ) return NULL;
467
468 memo = g_strconcat("", NULL);
469 node = s_list;
470 while ( node )
471 {
472 Split *split = node->data;
473 /* Include all splits except the main split for the check */
474 if (split != pcd->split)
475 {
476 gchar* memo_temp;
477 split_memo = xaccSplitGetMemo(split);
478 memo_temp = memo;
479 if (memo && *memo)
480 memo = g_strconcat(memo_temp, "\n", split_memo, NULL);
481 else
482 memo = g_strconcat(memo_temp, split_memo, NULL);
483 g_free(memo_temp);
484 }
485 node = node->next;
486 }
487 return memo;
488}

◆ gnc_check_format_title_changed()

void gnc_check_format_title_changed ( GtkEditable *  editable,
GtkWidget *  ok_button 
)

Definition at line 878 of file dialog-print-check.c.

879{
880 const gchar *text;
881 gboolean sensitive;
882
883 text = gtk_entry_get_text(GTK_ENTRY(editable));
884 sensitive = text && *text;
885 gtk_widget_set_sensitive(ok_button, sensitive);
886}

◆ gnc_print_check_format_changed()

void gnc_print_check_format_changed ( GtkComboBox *  widget,
PrintCheckDialog *  pcd 
)

Definition at line 2602 of file dialog-print-check.c.

2604{
2605 GtkListStore *p_store;
2606 GtkTreeModel *f_model;
2607 GtkTreeIter f_iter, iter;
2608 gboolean sensitive;
2609 gint pnum;
2610 check_format_t *format;
2611 gboolean separator;
2612 GSList *elem;
2613
2614 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pcd->format_combobox), &f_iter))
2615 return;
2616 f_model = gtk_combo_box_get_model(GTK_COMBO_BOX(pcd->format_combobox));
2617 gtk_tree_model_get(f_model, &f_iter, COL_DATA, &format, COL_SEP, &separator, -1);
2618 if (separator)
2619 return;
2620
2621 pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2622
2623 /* Update the positions combobox */
2624 pcd->selected_format = format;
2625 p_store = gtk_list_store_new (1, G_TYPE_STRING);
2626 gtk_combo_box_set_model(GTK_COMBO_BOX(pcd->position_combobox),
2627 GTK_TREE_MODEL(p_store));
2628 if (format)
2629 {
2630 if (format->positions)
2631 {
2632 pcd->position_max = g_slist_length(format->positions); /* -1 for 0 base, +1 for custom entry */
2633 for (elem = format->positions; elem; elem = g_slist_next(elem))
2634 {
2635 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2636 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, elem->data, -1);
2637 }
2638 }
2639 else
2640 {
2641 /* Invent a "Top" position if format has no positions */
2642 pcd->position_max = 1;
2643 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2644 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Top"), -1);
2645 }
2646 }
2647 else
2648 {
2649 pcd->position_max = 0;
2650 }
2651 gtk_list_store_append(GTK_LIST_STORE(p_store), &iter);
2652 gtk_list_store_set (GTK_LIST_STORE(p_store), &iter, 0, _("Custom"), -1);
2653 g_object_unref (p_store);
2654
2655 /* If there's only one thing in the position combobox, make it insensitive */
2656 sensitive = (pcd->position_max > 0);
2657 gtk_widget_set_sensitive(GTK_WIDGET(pcd->position_combobox), sensitive);
2658
2659 /* Update the custom page, this must be done before setting the active
2660 entry in the position combo box since gnc_print_check_position_changed
2661 will adjust these settings in some cases. */
2662 sensitive = (!separator && !format);
2663 gtk_container_foreach(GTK_CONTAINER(pcd->custom_table),
2664 gnc_print_check_set_sensitive,
2665 GINT_TO_POINTER(sensitive));
2666
2667 /* Set the active entry in the position combo box, this will trigger a
2668 call to gnc_print_check_position_changed */
2669 pnum = MAX(MIN(pnum, pcd->position_max), 0);
2670 gtk_combo_box_set_active(GTK_COMBO_BOX(pcd->position_combobox), pnum);
2671
2672 /* Update address fields */
2673 sensitive = check_format_has_address(pcd);
2674 gtk_widget_set_sensitive(pcd->check_address_name, sensitive);
2675 gtk_widget_set_sensitive(pcd->check_address_1, sensitive);
2676 gtk_widget_set_sensitive(pcd->check_address_2, sensitive);
2677 gtk_widget_set_sensitive(pcd->check_address_3, sensitive);
2678 gtk_widget_set_sensitive(pcd->check_address_4, sensitive);
2679}

◆ gnc_print_check_position_changed()

void gnc_print_check_position_changed ( GtkComboBox *  widget,
PrintCheckDialog *  pcd 
)

Definition at line 2683 of file dialog-print-check.c.

2685{
2686 gboolean sensitive;
2687 gint pnum;
2688 guint check_count;
2689 gint first_page_max, first_page_min, first_page_value;
2690
2691 pnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pcd->position_combobox));
2692
2693 /* Make the translation and rotation fields active if the position is "custom" */
2694 sensitive = pnum == pcd->position_max;
2695 gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_x), sensitive);
2696 gtk_widget_set_sensitive(GTK_WIDGET(pcd->translation_y), sensitive);
2697 gtk_widget_set_sensitive(GTK_WIDGET(pcd->check_rotation), sensitive);
2698 gtk_widget_set_sensitive(GTK_WIDGET(pcd->units_combobox), sensitive);
2699
2700 /* Set up the first page check count spin box */
2701 check_count = g_list_length(pcd->splits);
2702 first_page_max = MAX(1, MIN(pcd->position_max - pnum, check_count));
2703 first_page_min = 1;
2704 pnum = gtk_spin_button_get_value_as_int(pcd->first_page_count);
2705 first_page_value = MAX(MIN(pnum, first_page_max), first_page_min);
2706 gtk_spin_button_set_range(pcd->first_page_count, (gdouble)first_page_min, (gdouble)first_page_max);
2707 gtk_spin_button_set_value(pcd->first_page_count, (gdouble)first_page_value);
2708 sensitive = first_page_max > 1;
2709 gtk_widget_set_sensitive(GTK_WIDGET(pcd->first_page_count), sensitive);
2710}

◆ gnc_print_check_save_button_clicked()

void gnc_print_check_save_button_clicked ( GtkButton *  button,
PrintCheckDialog *  pcd 
)

Definition at line 894 of file dialog-print-check.c.

895{
896 GtkWidget *dialog, *entry, *button;
897 GtkBuilder *builder;
898 gchar *title;
899
900 builder = gtk_builder_new();
901 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "format_title_dialog");
902
903 /* Get a title for the new check format. */
904 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "format_title_dialog"));
905 entry = GTK_WIDGET(gtk_builder_get_object (builder, "format_title"));
906 button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
907 gnc_check_format_title_changed(GTK_EDITABLE(entry), button);
908 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
909
910 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pcd->dialog));
911 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
912 {
913 gtk_widget_destroy(dialog);
914 g_object_unref(G_OBJECT(builder));
915 return;
916 }
917
918 title = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
919 gtk_widget_destroy (dialog);
920
921 g_object_unref(G_OBJECT(builder));
922
923 pcd_save_custom_data(pcd, title);
924 g_free(title);
925}

◆ gnc_ui_print_check_dialog_create()

void gnc_ui_print_check_dialog_create ( GtkWidget *  parent,
GList *  splits,
Account account 
)

Definition at line 1652 of file dialog-print-check.c.

1655{
1656 PrintCheckDialog *pcd;
1657 GtkBuilder *builder;
1658 GtkWidget *table;
1659 gchar *font;
1660 Transaction *trans = NULL;
1661
1662 pcd = g_new0(PrintCheckDialog, 1);
1663 pcd->caller_window = GTK_WINDOW(parent);
1664 pcd->splits = g_list_copy(splits);
1665 pcd->account = account;
1666
1667 builder = gtk_builder_new();
1668 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment1");
1669 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment2");
1670 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment3");
1671 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment4");
1672 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment5");
1673 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment6");
1674 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment7");
1675 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment8");
1676 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment9");
1677 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment10");
1678 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment11");
1679 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment12");
1680 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment13");
1681 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment14");
1682 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment15");
1683 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment16");
1684 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment17");
1685 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment18");
1686 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment19");
1687 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment20");
1688 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment21");
1689 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment22");
1690 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment23");
1691 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "adjustment24");
1692 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore1");
1693 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore2");
1694 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "liststore3");
1695 gnc_builder_add_from_file (builder, "dialog-print-check.glade", "print_check_dialog");
1696
1697 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, pcd);
1698
1699 pcd->builder = builder;
1700 pcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "print_check_dialog"));
1701
1702 // Set the name for this dialog so it can be easily manipulated with css
1703 gtk_widget_set_name (GTK_WIDGET(pcd->dialog), "gnc-id-print-check");
1704
1705 /* now pick out the relevant child widgets */
1706 pcd->format_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_format_combobox"));
1707 pcd->position_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "check_position_combobox"));
1708 pcd->first_page_count = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "first_page_count_entry"));
1709
1710 pcd->custom_table = GTK_WIDGET(gtk_builder_get_object (builder, "custom_table"));
1711 pcd->payee_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_x_entry"));
1712 pcd->payee_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "payee_y_entry"));
1713 pcd->date_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_x_entry"));
1714 pcd->date_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "date_y_entry"));
1715 pcd->words_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_x_entry"));
1716 pcd->words_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_words_y_entry"));
1717 pcd->number_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_x_entry"));
1718 pcd->number_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "amount_numbers_y_entry"));
1719 pcd->notes_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_x_entry"));
1720 pcd->notes_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "notes_y_entry"));
1721 pcd->memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_x_entry"));
1722 pcd->memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "memo_y_entry"));
1723 pcd->address_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_x_entry"));
1724 pcd->address_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "address_y_entry"));
1725 pcd->splits_amount_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_x_entry"));
1726 pcd->splits_amount_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_amount_y_entry"));
1727 pcd->splits_memo_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_x_entry"));
1728 pcd->splits_memo_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_memo_y_entry"));
1729 pcd->splits_account_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_x_entry"));
1730 pcd->splits_account_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "splits_account_y_entry"));
1731 pcd->translation_x = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_x_entry"));
1732 pcd->translation_y = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "translation_y_entry"));
1733 pcd->translation_label = GTK_WIDGET(gtk_builder_get_object (builder, "translation_label"));
1734 pcd->check_rotation = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "check_rotation_entry"));
1735 pcd->units_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "units_combobox"));
1736
1737 gtk_window_set_transient_for(GTK_WINDOW(pcd->dialog), pcd->caller_window);
1738
1739 /* Create and attach the date-format chooser */
1740 table = GTK_WIDGET(gtk_builder_get_object (builder, "options_table"));
1741 pcd->date_format = gnc_date_format_new_without_label();
1742 gtk_grid_attach (GTK_GRID(table), pcd->date_format, 1, 4, 1, 1);
1743
1744 /* Default font (set in preferences) */
1745 font = gnc_prefs_get_string(GNC_PREFS_GROUP, GNC_PREF_DEFAULT_FONT);
1746 pcd->default_font = font && *font ? font : g_strdup(DEFAULT_FONT);
1747
1748 /* Update the combo boxes bases on the available check formats */
1749 initialize_format_combobox(pcd);
1750
1751 /* address */
1752 pcd->check_address_name = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_name"));
1753 pcd->check_address_1 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_1"));
1754 pcd->check_address_2 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_2"));
1755 pcd->check_address_3 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_3"));
1756 pcd->check_address_4 = GTK_WIDGET(gtk_builder_get_object (builder, "check_address_4"));
1757 /* fill in any available address data */
1758 /* Can't access business objects e.g. Customer,Vendor,Employee because
1759 * it would create build problems */
1760 if (g_list_length(pcd->splits) == 1)
1761 {
1762 GncOwner txn_owner;
1763
1764 trans = xaccSplitGetParent((Split *)(pcd->splits->data));
1765 if (gncOwnerGetOwnerFromTxn (trans, &txn_owner))
1766 {
1767 GncOwner owner;
1768 gncOwnerCopy (gncOwnerGetEndOwner (&txn_owner), &owner);
1769
1770 /* Got a business owner, get the address */
1771 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_name), gncOwnerGetName(&owner));
1772 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_1), gncAddressGetAddr1 (gncOwnerGetAddr(&owner)));
1773 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_2), gncAddressGetAddr2 (gncOwnerGetAddr(&owner)));
1774 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_3), gncAddressGetAddr3 (gncOwnerGetAddr(&owner)));
1775 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_4), gncAddressGetAddr4 (gncOwnerGetAddr(&owner)));
1776 }
1777 }
1778
1779 /* Use transaction description as address name if no better address has been found */
1780 if ( trans && (0 == gtk_entry_get_text_length (GTK_ENTRY(pcd->check_address_name))) )
1781 gtk_entry_set_text(GTK_ENTRY(pcd->check_address_name), xaccTransGetDescription(trans));
1782
1783 gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "lower_left")));
1784
1785 gnc_ui_print_restore_dialog(pcd);
1786 gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(pcd->dialog), GTK_WINDOW (parent));
1787
1788 g_object_unref(G_OBJECT(builder));
1789 gtk_widget_show_all(pcd->dialog);
1790}

◆ gnc_ui_print_check_response_cb()

void gnc_ui_print_check_response_cb ( GtkDialog *  dialog,
gint  response,
PrintCheckDialog *  pcd 
)

Definition at line 2714 of file dialog-print-check.c.

2717{
2718 switch (response)
2719 {
2720 case GTK_RESPONSE_HELP:
2721 gnc_gnome_help (GTK_WINDOW(dialog), DF_MANUAL, DL_PRINTCHECK);
2722 return;
2723
2724 case GTK_RESPONSE_OK:
2725 gnc_ui_print_check_dialog_ok_cb(pcd);
2726 gnc_ui_print_save_dialog(pcd);
2727 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(dialog));
2728 break;
2729
2730 case GTK_RESPONSE_CANCEL:
2731 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(dialog));
2732 break;
2733 }
2734
2735 gtk_widget_destroy(pcd->dialog);
2736 g_free(pcd->default_font);
2737 g_list_free(pcd->splits);
2738 g_free(pcd);
2739}