GnuCash  5.6-150-g038405b370+
gnucash-register.c
1 /********************************************************************\
2  * This program is free software; you can redistribute it and/or *
3  * modify it under the terms of the GNU General Public License as *
4  * published by the Free Software Foundation; either version 2 of *
5  * the License, or (at your option) any later version. *
6  * *
7  * This program is distributed in the hope that it will be useful, *
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
10  * GNU General Public License for more details. *
11  * *
12  * You should have received a copy of the GNU General Public License*
13  * along with this program; if not, contact: *
14  * *
15  * Free Software Foundation Voice: +1-617-542-5942 *
16  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
17  * Boston, MA 02110-1301, USA gnu@gnu.org *
18  * *
19 \********************************************************************/
20 
21 /*
22  * The Gnucash Register widget
23  *
24  * Based heavily on the Gnumeric Sheet widget.
25  *
26  * Authors:
27  * Heath Martin <martinh@pegasus.cc.ucf.edu>
28  * Dave Peticolas <dave@krondo.com>
29  */
30 
31 #include <config.h>
32 #include <glib.h>
33 #include <glib/gprintf.h>
34 #include <gdk/gdkkeysyms.h>
35 
36 #include "gnucash-register.h"
37 #include "gnucash-sheet.h"
38 #include "gnucash-sheetP.h"
39 
40 #include "gnucash-cursor.h"
41 #include "gnucash-style.h"
42 #include "gnucash-header.h"
43 #include "gnucash-item-edit.h"
44 #include "split-register.h"
45 #include "gnc-engine.h" // For debugging, e.g. ENTER(), LEAVE()
46 #include "gnc-prefs.h"
47 #include "gnc-state.h"
48 
49 #include "combocell.h"
50 #include "completioncell.h"
51 #include "datecell.h"
52 #include "formulacell-gnome.h"
53 #include "pricecell-gnome.h"
54 #include "quickfillcell-gnome.h"
55 #include "table-gnome.h"
56 
57 
58 /* Register signals */
59 enum
60 {
61  ACTIVATE_CURSOR,
62  REDRAW_ALL,
63  REDRAW_HELP,
64  SHOW_POPUP_MENU,
65  LAST_SIGNAL
66 };
67 
68 
71 /* This static indicates the debugging module that this .o belongs to. */
72 static QofLogModule log_module = GNC_MOD_REGISTER;
73 static guint register_signals[LAST_SIGNAL];
74 
75 
77 {
78  GtkGrid table;
79 
80  GtkWidget *hscrollbar;
81  GtkWidget *sheet;
82  gboolean hscrollbar_visible;
83 };
84 
85 
87 {
88  GtkGridClass parent_class;
89 
90  void (*activate_cursor) (GnucashRegister *reg);
91  void (*redraw_all) (GnucashRegister *reg);
92  void (*redraw_help) (GnucashRegister *reg);
93  void (*show_popup_menu) (GnucashRegister *reg);
94 };
95 
98 G_DEFINE_TYPE (GnucashRegister, gnucash_register, GTK_TYPE_GRID)
99 
100 void
102 {
103  gnc_register_add_cell_type (COMBO_CELL_TYPE_NAME, gnc_combo_cell_new);
104  gnc_register_add_cell_type (COMPLETION_CELL_TYPE_NAME, gnc_completion_cell_new);
105  gnc_register_add_cell_type (DATE_CELL_TYPE_NAME, gnc_date_cell_new);
106  gnc_register_add_cell_type (PRICE_CELL_TYPE_NAME,
107  gnc_price_cell_gnome_new);
108  gnc_register_add_cell_type (QUICKFILL_CELL_TYPE_NAME,
109  gnc_quickfill_cell_gnome_new);
110  gnc_register_add_cell_type( FORMULA_CELL_TYPE_NAME,
111  gnc_formula_cell_gnome_new );
112  gnc_table_gnome_init ();
113 }
114 
115 gboolean
116 gnucash_register_has_selection (GnucashRegister *reg)
117 {
118  GnucashSheet *sheet;
119  GncItemEdit *item_edit;
120 
121  g_return_val_if_fail((reg != NULL), FALSE);
122  g_return_val_if_fail(GNUCASH_IS_REGISTER(reg), FALSE);
123 
124  sheet = GNUCASH_SHEET(reg->sheet);
125  item_edit = GNC_ITEM_EDIT(sheet->item_editor);
126 
127  return gnc_item_edit_get_has_selection(item_edit);
128 }
129 
130 void
131 gnucash_register_cut_clipboard (GnucashRegister *reg)
132 {
133  GnucashSheet *sheet;
134  GncItemEdit *item_edit;
135 
136  g_return_if_fail(reg != NULL);
137  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
138 
139  sheet = GNUCASH_SHEET(reg->sheet);
140  item_edit = GNC_ITEM_EDIT(sheet->item_editor);
141 
142  gnc_item_edit_cut_clipboard(item_edit);
143 }
144 
145 void
146 gnucash_register_copy_clipboard (GnucashRegister *reg)
147 {
148  GnucashSheet *sheet;
149  GncItemEdit *item_edit;
150 
151  g_return_if_fail(reg != NULL);
152  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
153 
154  sheet = GNUCASH_SHEET(reg->sheet);
155  item_edit = GNC_ITEM_EDIT(sheet->item_editor);
156 
157  gnc_item_edit_copy_clipboard(item_edit);
158 }
159 
160 void
161 gnucash_register_paste_clipboard (GnucashRegister *reg)
162 {
163  GnucashSheet *sheet;
164  GncItemEdit *item_edit;
165 
166  g_return_if_fail(reg != NULL);
167  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
168 
169  sheet = GNUCASH_SHEET(reg->sheet);
170  item_edit = GNC_ITEM_EDIT(sheet->item_editor);
171 
172  gnc_item_edit_paste_clipboard (item_edit);
173 }
174 
175 void
176 gnucash_register_refresh_from_prefs (GnucashRegister *reg)
177 {
178  GnucashSheet *sheet;
179 
180  g_return_if_fail(reg != NULL);
181  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
182 
183  sheet = GNUCASH_SHEET(reg->sheet);
184  gnucash_sheet_refresh_from_prefs(sheet);
185  gnc_header_request_redraw (GNC_HEADER(sheet->header_item));
186 }
187 
188 void
189 gnucash_register_reset_sheet_layout (GnucashRegister *reg)
190 {
191  GNCHeaderWidths widths;
192  GnucashSheet *sheet;
193  gint current_width;
194 
195  g_return_if_fail (reg != NULL);
196 
197  sheet = GNUCASH_SHEET(reg->sheet);
198 
199  g_return_if_fail (sheet != NULL);
200  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
201 
202  current_width = sheet->window_width - 1;
203 
204  widths = gnc_header_widths_new ();
205  gnucash_sheet_set_header_widths (sheet, widths);
206 
207  gnucash_sheet_styles_set_dimensions (sheet, current_width);
208 
209  gnucash_sheet_compile_styles (sheet);
210  gnucash_sheet_table_load (sheet, TRUE);
211  gnucash_sheet_cursor_set_from_table (sheet, TRUE);
212  gnucash_sheet_redraw_all (sheet);
213  gnc_header_widths_destroy (widths);
214 }
215 
216 void
217 gnucash_register_goto_virt_cell (GnucashRegister *reg,
218  VirtualCellLocation vcell_loc)
219 {
220  GnucashSheet *sheet;
221  VirtualLocation virt_loc;
222 
223  g_return_if_fail(reg != NULL);
224  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
225 
226  sheet = GNUCASH_SHEET(reg->sheet);
227 
228  virt_loc.vcell_loc = vcell_loc;
229  virt_loc.phys_row_offset = 0;
230  virt_loc.phys_col_offset = 0;
231 
232  gnucash_sheet_goto_virt_loc(sheet, virt_loc);
233 }
234 
235 void
236 gnucash_register_goto_virt_loc (GnucashRegister *reg,
237  VirtualLocation virt_loc)
238 {
239  GnucashSheet *sheet;
240 
241  g_return_if_fail(reg != NULL);
242  g_return_if_fail(GNUCASH_IS_REGISTER(reg));
243 
244  sheet = GNUCASH_SHEET(reg->sheet);
245 
246  gnucash_sheet_goto_virt_loc(sheet, virt_loc);
247 }
248 
249 void
250 gnucash_register_goto_next_virt_row (GnucashRegister *reg)
251 {
252  GnucashSheet *sheet;
253  VirtualLocation virt_loc;
254  int start_virt_row;
255 
256  g_return_if_fail (reg != NULL);
257  g_return_if_fail (GNUCASH_IS_REGISTER(reg));
258 
259  sheet = GNUCASH_SHEET(reg->sheet);
260 
261  gnucash_cursor_get_virt (GNUCASH_CURSOR(sheet->cursor), &virt_loc);
262 
263  /* Move down one physical row at a time until we
264  * reach the next visible virtual cell. */
265  start_virt_row = virt_loc.vcell_loc.virt_row;
266  do
267  {
268  if (!gnc_table_move_vertical_position (sheet->table, &virt_loc, 1))
269  return;
270  }
271  while (start_virt_row == virt_loc.vcell_loc.virt_row);
272 
273  if (virt_loc.vcell_loc.virt_row >= sheet->num_virt_rows)
274  return;
275 
276  virt_loc.phys_row_offset = 0;
277  virt_loc.phys_col_offset = 0;
278 
279  gnucash_sheet_goto_virt_loc (sheet, virt_loc);
280 }
281 
282 void
283 gnucash_register_goto_next_matching_row (GnucashRegister *reg,
284  VirtualLocationMatchFunc match,
285  gpointer user_data)
286 {
287  GnucashSheet *sheet;
288  SheetBlockStyle *style;
289  VirtualLocation virt_loc;
290 
291  g_return_if_fail (reg != NULL);
292  g_return_if_fail (GNUCASH_IS_REGISTER(reg));
293  g_return_if_fail (match != NULL);
294 
295  sheet = GNUCASH_SHEET (reg->sheet);
296 
297  gnucash_cursor_get_virt (GNUCASH_CURSOR(sheet->cursor), &virt_loc);
298 
299  do
300  {
301  if (!gnc_table_move_vertical_position (sheet->table,
302  &virt_loc, 1))
303  return;
304 
305  if (virt_loc.vcell_loc.virt_row >= sheet->num_virt_rows)
306  return;
307 
308  style = gnucash_sheet_get_style (sheet, virt_loc.vcell_loc);
309  if (!style || !style->cursor)
310  return;
311  }
312  while (!match (virt_loc, user_data));
313 
314  virt_loc.phys_row_offset = 0;
315  virt_loc.phys_col_offset = 0;
316 
317  gnucash_sheet_goto_virt_loc (sheet, virt_loc);
318 }
319 
320 static gboolean
321 gnucash_register_sheet_resize (GnucashRegister *reg)
322 {
323  // Sometimes the space left by the horizontal scrollbar does
324  // not get filled on load, this makes sure it does
325  if (!reg->hscrollbar_visible)
326  gtk_widget_queue_resize (GTK_WIDGET (reg->sheet));
327 
328  return FALSE;
329 }
330 
331 static void
332 gnucash_register_update_hadjustment (GtkAdjustment *adj,
333  GnucashRegister *reg)
334 {
335  g_return_if_fail (reg != NULL);
336  g_return_if_fail (GNUCASH_IS_REGISTER(reg));
337 
338  if (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj)
339  > gtk_adjustment_get_page_size (adj))
340  {
341  if (!reg->hscrollbar_visible)
342  {
343  gtk_widget_show(reg->hscrollbar);
344  reg->hscrollbar_visible = TRUE;
345  }
346  }
347  else
348  {
349  if (reg->hscrollbar_visible)
350  {
351  gtk_widget_hide(reg->hscrollbar);
352  reg->hscrollbar_visible = FALSE;
353  // When sheet first loaded and the scrollbar is hidden, the space left
354  // is not always automatically taken up by the sheet so queue a resize
355  // when all is idle
356  g_idle_add ((GSourceFunc) gnucash_register_sheet_resize, reg);
357  }
358  }
359 }
360 
361 /*************************************************************/
362 
363 
364 static void
365 gnucash_register_class_init (GnucashRegisterClass *klass)
366 {
367  GObjectClass *gobject_class;
368 
369  gobject_class = G_OBJECT_CLASS (klass);
370 
371  gtk_widget_class_set_css_name (GTK_WIDGET_CLASS(klass), "gnc-id-register");
372 
373  register_signals[ACTIVATE_CURSOR] =
374  g_signal_new("activate_cursor",
375  G_TYPE_FROM_CLASS(gobject_class),
376  G_SIGNAL_RUN_LAST,
377  G_STRUCT_OFFSET(GnucashRegisterClass,
378  activate_cursor),
379  NULL, NULL,
380  g_cclosure_marshal_VOID__VOID,
381  G_TYPE_NONE, 0);
382 
383  register_signals[REDRAW_ALL] =
384  g_signal_new("redraw_all",
385  G_TYPE_FROM_CLASS(gobject_class),
386  G_SIGNAL_RUN_LAST,
387  G_STRUCT_OFFSET(GnucashRegisterClass,
388  redraw_all),
389  NULL, NULL,
390  g_cclosure_marshal_VOID__VOID,
391  G_TYPE_NONE, 0);
392 
393  register_signals[REDRAW_HELP] =
394  g_signal_new("redraw_help",
395  G_TYPE_FROM_CLASS(gobject_class),
396  G_SIGNAL_RUN_LAST,
397  G_STRUCT_OFFSET(GnucashRegisterClass,
398  redraw_help),
399  NULL, NULL,
400  g_cclosure_marshal_VOID__VOID,
401  G_TYPE_NONE, 0);
402 
403  register_signals[SHOW_POPUP_MENU] =
404  g_signal_new("show_popup_menu",
405  G_TYPE_FROM_CLASS(gobject_class),
406  G_SIGNAL_RUN_LAST,
407  G_STRUCT_OFFSET(GnucashRegisterClass,
408  show_popup_menu),
409  NULL, NULL,
410  g_cclosure_marshal_VOID__VOID,
411  G_TYPE_NONE, 0);
412 
413  klass->activate_cursor = NULL;
414  klass->redraw_all = NULL;
415  klass->redraw_help = NULL;
416  klass->show_popup_menu = NULL;
417 }
418 
419 
420 static void
421 gnucash_register_init (GnucashRegister *g_reg)
422 {
423  GtkGrid *table = GTK_GRID(g_reg);
424 
425  gtk_widget_set_can_focus (GTK_WIDGET(table), FALSE);
426  gtk_widget_set_can_default (GTK_WIDGET(table), FALSE);
427 
428  gtk_grid_set_row_homogeneous (GTK_GRID(table), FALSE);
429  gtk_grid_set_column_homogeneous (GTK_GRID(table), FALSE);
430 }
431 
432 void
433 gnucash_register_attach_popup (GnucashRegister *reg,
434  GtkWidget *popup,
435  gpointer data)
436 {
437  g_return_if_fail (GNUCASH_IS_REGISTER(reg));
438  g_return_if_fail (reg->sheet != NULL);
439  if (popup)
440  g_return_if_fail (GTK_IS_WIDGET(popup));
441 
442  gnucash_sheet_set_popup (GNUCASH_SHEET (reg->sheet), popup, data);
443 }
444 
445 
446 /* Um, this function checks that data is not null but never uses it.
447  * Weird. Also, since this function only works with a GnucashRegister
448  * widget, maybe some of it should be moved to gnucash-sheet.c. */
449 /* Adding to previous note: Since data doesn't appear do anything and to
450  * align the function with save_state() I've removed the check for
451  * NULL and changed two calls in dialog_order.c and dialog_invoice.c
452  * to pass NULL as second parameter. */
453 
454 static void
455 gnucash_register_configure (GnucashSheet *sheet, const gchar * state_section)
456 {
457  GNCHeaderWidths widths;
458  Table *table;
459  GList *node;
460  gchar *key;
461  guint value;
462  GKeyFile *state_file = gnc_state_get_current();
463 
464  // Stuff for per-register settings load.
465  g_return_if_fail (sheet != NULL);
466  g_return_if_fail (GNUCASH_IS_SHEET (sheet));
467 
468  PINFO("state_section=%s",state_section);
469 
470  ENTER("sheet=%p, data=%p", sheet, "");
471 
472  table = sheet->table;
474  table->ui_data = sheet;
475 
476  g_object_ref (sheet);
477 
478  /* config the cell-block styles */
479 
480  widths = gnc_header_widths_new ();
481 
482  if (state_section && gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY))
483  {
484  node = gnc_table_layout_get_cells (table->layout);
485  for (; node; node = node->next)
486  {
487  BasicCell *cell = node->data;
488 
489  if (cell->expandable)
490  continue;
491 
492  /* Remember whether the column is visible */
493  key = g_strdup_printf("%s_width", cell->cell_name);
494  value = g_key_file_get_integer (state_file, state_section, key, NULL);
495  if (value != 0)
496  gnc_header_widths_set_width (widths, cell->cell_name, value);
497  g_free(key);
498  }
499  }
500 
501  gnucash_sheet_create_styles (sheet);
502 
503  gnucash_sheet_set_header_widths (sheet, widths);
504 
505  gnucash_sheet_compile_styles (sheet);
506 
507  gnucash_sheet_table_load (sheet, TRUE);
508  gnucash_sheet_cursor_set_from_table (sheet, TRUE);
509  gnucash_sheet_redraw_all (sheet);
510 
511  gnc_header_widths_destroy (widths);
512 
513  LEAVE(" ");
514 }
515 
516 
517 static GtkWidget *
518 gnucash_register_create_widget (Table *table)
519 {
520  GnucashRegister *reg;
521  GtkWidget *header;
522  GtkWidget *widget;
523  GtkWidget *sheet;
524  GtkWidget *scrollbar;
525 
526  reg = g_object_new (GNUCASH_TYPE_REGISTER, NULL);
527  widget = GTK_WIDGET(reg);
528 
529  sheet = gnucash_sheet_new (table);
530  reg->sheet = sheet;
531  GNUCASH_SHEET(sheet)->reg = widget;
532 
533  header = gnc_header_new (GNUCASH_SHEET(sheet));
534 
535  gtk_grid_attach (GTK_GRID(widget), header, 0, 0, 1, 1);
536  gtk_widget_set_hexpand (header, TRUE);
537  gtk_widget_set_halign (header, GTK_ALIGN_FILL);
538  gtk_widget_set_vexpand (header, FALSE);
539  gtk_widget_set_valign (header, GTK_ALIGN_FILL);
540  g_object_set (header, "margin", 0, NULL);
541  gtk_widget_show (header);
542 
543  gtk_grid_attach (GTK_GRID(widget), sheet, 0, 1, 1, 1);
544  gtk_widget_set_hexpand (sheet, TRUE);
545  gtk_widget_set_halign (sheet, GTK_ALIGN_FILL);
546  gtk_widget_set_vexpand (sheet, TRUE);
547  gtk_widget_set_valign (sheet, GTK_ALIGN_FILL);
548  g_object_set (sheet, "margin", 0, NULL);
549  gtk_widget_show (sheet);
550 
551  scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, GNUCASH_SHEET(sheet)->vadj);
552  gtk_grid_attach (GTK_GRID(widget), GTK_WIDGET(scrollbar), 1, 0, 1, 2);
553  gtk_widget_set_hexpand (GTK_WIDGET(scrollbar), FALSE);
554  gtk_widget_set_halign (GTK_WIDGET(scrollbar), GTK_ALIGN_FILL);
555  gtk_widget_set_vexpand (GTK_WIDGET(scrollbar), TRUE);
556  gtk_widget_set_valign (GTK_WIDGET(scrollbar), GTK_ALIGN_FILL);
557  g_object_set (GTK_WIDGET(scrollbar), "margin", 0, NULL);
558  gtk_widget_show (scrollbar);
559  GNUCASH_SHEET(sheet)->vscrollbar = scrollbar;
560 
561  scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GNUCASH_SHEET(sheet)->hadj);
562  gtk_grid_attach (GTK_GRID(widget), GTK_WIDGET(scrollbar), 0, 2, 1, 1);
563  gtk_widget_set_hexpand (GTK_WIDGET(scrollbar), TRUE);
564  gtk_widget_set_halign (GTK_WIDGET(scrollbar), GTK_ALIGN_FILL);
565  gtk_widget_set_vexpand (GTK_WIDGET(scrollbar), FALSE);
566  gtk_widget_set_valign (GTK_WIDGET(scrollbar), GTK_ALIGN_FILL);
567  g_object_set (GTK_WIDGET(scrollbar), "margin", 0, NULL);
568  reg->hscrollbar = scrollbar;
569  gtk_widget_show (reg->hscrollbar);
570  reg->hscrollbar_visible = TRUE;
571  GNUCASH_SHEET(sheet)->hscrollbar = scrollbar;
572 
573  g_signal_connect (GNUCASH_SHEET(sheet)->hadj, "changed",
574  G_CALLBACK (gnucash_register_update_hadjustment), reg);
575 
576  return widget;
577 }
578 
579 
580 GtkWidget *
581 gnucash_register_new (Table *table, const gchar *state_section)
582 {
583  GnucashRegister *reg;
584  GtkWidget *widget;
585 
586  widget = gnucash_register_create_widget(table);
587  reg = GNUCASH_REGISTER(widget);
588 
589  gnucash_register_configure (GNUCASH_SHEET(reg->sheet), state_section);
590 
591  return widget;
592 }
593 
594 
595 void gnucash_register_set_moved_cb (GnucashRegister *reg,
596  GFunc cb, gpointer cb_data)
597 {
598  GnucashSheet *sheet;
599 
600  if (!reg || !reg->sheet)
601  return;
602  sheet = GNUCASH_SHEET(reg->sheet);
603  sheet->moved_cb = cb;
604  sheet->moved_cb_data = cb_data;
605 }
606 
607 
608 GnucashSheet *gnucash_register_get_sheet (GnucashRegister *reg)
609 {
610  g_return_val_if_fail (reg != NULL, NULL);
611  g_return_val_if_fail (GNUCASH_IS_REGISTER(reg), NULL);
612 
613  return GNUCASH_SHEET(reg->sheet);
614 }
615 
616 
617 void
618 gnucash_register_set_open_doclink_cb (GnucashRegister *reg,
619  GFunc cb, gpointer cb_data)
620 {
621  GnucashSheet *sheet;
622 
623  if (!reg || !reg->sheet)
624  return;
625  sheet = GNUCASH_SHEET(reg->sheet);
626  sheet->open_doclink_cb = cb;
627  sheet->open_doclink_cb_data = cb_data;
628 }
629 
630 
Functions to load, save and get gui state.
Implements gnome dependent formula cell functions.
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
GtkWidget * gnucash_register_new(Table *table, const gchar *state_section)
this already has scrollbars attached
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition: gnc-state.c:248
void gnc_table_init_gui(Table *table)
UI-specific functions.
Definition: table-gnome.c:158
Public declarations for GnucashCursor class.
BasicCell * gnc_date_cell_new(void)
installs a callback to handle date recording
Public declarations of GnucashRegister class.
Public declarations for GnucashHeader class.
Private declarations for GnucashSheet class.
gboolean gnc_table_move_vertical_position(Table *table, VirtualLocation *virt_loc, int phys_row_offset)
Moves away from virtual location virt_loc by phys_row_offset physical rows.
All type declarations for the whole Gnucash engine.
API for checkbook register display area.
Generic api to store and retrieve preferences.
Public declarations for GncItemEdit class.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
Styling functions for RegisterGnome.
void gnucash_register_add_cell_types(void)
Implementation.