GnuCash  5.6-150-g038405b370+
datecell-gnome.c
1 /********************************************************************\
2  * datecell-gnome.c -- implement date cell handler in gnome *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA gnu@gnu.org *
20  * *
21 \********************************************************************/
22 
23 /*
24  * FILE: datecell-gnome.c
25  *
26  * FUNCTION: Implement gnome portion of datecell widget
27  * embedded in a table cell.
28  *
29  * HISTORY:
30  * Copyright (c) 2000 Dave Peticolas <dave@krondo.com>
31  * Copyright (c) 2017 Aaron Laws
32  */
33 
34 #include <config.h>
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40 #include <glib/gi18n.h>
41 #include <gdk/gdkkeysyms.h>
42 
43 #include "datecell.h"
44 #include "dialog-utils.h"
45 #include "gnc-ui.h"
46 #include "gnc-ui-util.h"
47 #include "gnucash-date-picker.h"
48 #include "gnucash-item-edit.h"
49 #include "gnucash-sheet.h"
50 #include "gnucash-sheetP.h"
51 
52 
53 #define DATE_BUF (MAX_DATE_LENGTH+1)
54 
55 typedef struct _PopBox
56 {
57  GnucashSheet *sheet;
58  GncItemEdit *item_edit;
59  GNCDatePicker *date_picker;
60 
61  gboolean signals_connected; /* date picker signals connected? */
62  gboolean calendar_popped; /* calendar is popped up? */
63  gboolean in_date_select;
64 
65  struct tm date;
66 } PopBox;
67 
68 
69 static void block_picker_signals (DateCell *cell);
70 static void unblock_picker_signals (DateCell *cell);
71 static void gnc_date_cell_realize (BasicCell *bcell, gpointer w);
72 static void gnc_date_cell_set_value_internal (BasicCell *bcell,
73  const char *value);
74 static void gnc_date_cell_move (BasicCell *bcell);
75 static void gnc_date_cell_gui_destroy (BasicCell *bcell);
76 static void gnc_date_cell_destroy (BasicCell *bcell);
77 static void gnc_date_cell_modify_verify (BasicCell *_cell,
78  const char *change,
79  int change_len,
80  const char *newval,
81  int newval_len,
82  int *cursor_position,
83  int *start_selection,
84  int *end_selection);
85 static gboolean gnc_date_cell_direct_update (BasicCell *bcell,
86  int *cursor_position,
87  int *start_selection,
88  int *end_selection,
89  void *gui_data);
90 static gboolean gnc_date_cell_enter (BasicCell *bcell,
91  int *cursor_position,
92  int *start_selection,
93  int *end_selection);
94 static void gnc_date_cell_leave (BasicCell *bcell);
95 
96 static gboolean
97 check_readonly_threshold (const gchar *datestr, GDate *d, gboolean warn)
98 {
99  GDate *readonly_threshold = qof_book_get_autoreadonly_gdate(gnc_get_current_book());
100  if (g_date_compare(d, readonly_threshold) < 0)
101  {
102  if (warn)
103  {
104  gchar *dialog_msg = _("The entered date of the transaction is "
105  "older than the \"Read-Only Threshold\" set for "
106  "this book. This setting can be changed in "
107  "File->Properties->Accounts, resetting to the threshold.");
108  gchar *dialog_title = _("Cannot store a transaction at this date");
109  GtkWidget *dialog = gtk_message_dialog_new(gnc_ui_get_main_window (NULL),
110  0,
111  GTK_MESSAGE_ERROR,
112  GTK_BUTTONS_OK,
113  "%s", dialog_title);
114  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
115  "%s", dialog_msg);
116  gtk_dialog_run (GTK_DIALOG(dialog));
117  gtk_widget_destroy (dialog);
118 
119 // g_warning("Entered date %s is before the \"auto-read-only threshold\";"
120 // " resetting to the threshold.", datestr);
121  }
122  // Reset the date to the threshold date
123  g_date_set_julian (d, g_date_get_julian (readonly_threshold));
124  g_date_free (readonly_threshold);
125  return TRUE;
126  }
127  g_date_free (readonly_threshold);
128  return FALSE;
129 }
130 
131 static void
132 gnc_parse_date (struct tm *parsed, const char * datestr, gboolean warn)
133 {
134  int day, month, year;
135  gboolean use_autoreadonly = qof_book_uses_autoreadonly(gnc_get_current_book());
136  GDate *test_date;
137 
138  if (!parsed) return;
139  if (!datestr) return;
140 
141  if (!qof_scan_date (datestr, &day, &month, &year))
142  {
143  // Couldn't parse date, use today
144  struct tm tm_today;
145 
146  memset (&tm_today, 0, sizeof (struct tm));
147  gnc_tm_get_today_start (&tm_today);
148  day = tm_today.tm_mday;
149  month = tm_today.tm_mon + 1;
150  year = tm_today.tm_year + 1900;
151  }
152 
153  test_date = g_date_new_dmy (day, month, year);
154 
155  if (!gnc_gdate_in_valid_range (test_date, warn))
156  {
157  struct tm tm_today;
158  memset (&tm_today, 0, sizeof (struct tm));
159  gnc_tm_get_today_start (&tm_today);
160  year = tm_today.tm_year + 1900;
161  }
162 
163  // If we have an auto-read-only threshold, do not accept a date that is
164  // older than the threshold.
165  if (use_autoreadonly)
166  {
167  g_date_set_dmy (test_date, day, month, year);
168  if (check_readonly_threshold (datestr, test_date, warn))
169  {
170  day = g_date_get_day (test_date);
171  month = g_date_get_month (test_date);
172  year = g_date_get_year (test_date);
173  }
174  }
175  g_date_free (test_date);
176 
177  parsed->tm_mday = day;
178  parsed->tm_mon = month - 1;
179  parsed->tm_year = year - 1900;
180 
181  gnc_tm_set_day_start(parsed);
182  /* Using gnc_mktime purely for its side effect of filling in the
183  * rest of parsed and to check that it's valid.
184  */
185  if (gnc_mktime (parsed) == -1)
186  gnc_tm_get_today_start (parsed);
187  gnc_mktime (parsed);
188 }
189 
190 static void
191 gnc_date_cell_print_date (DateCell *cell, char *buff)
192 {
193  PopBox *box = cell->cell.gui_private;
194 
196  box->date.tm_mday,
197  box->date.tm_mon + 1,
198  box->date.tm_year + 1900);
199 }
200 
201 static void
202 gnc_date_cell_init (DateCell *cell)
203 {
204  PopBox *box;
205  time64 secs;
206  char buff[DATE_BUF];
207 
208  gnc_basic_cell_init (&(cell->cell));
209 
210  cell->cell.is_popup = TRUE;
211 
212  cell->cell.destroy = gnc_date_cell_destroy;
213 
214  cell->cell.gui_realize = gnc_date_cell_realize;
215  cell->cell.gui_destroy = gnc_date_cell_gui_destroy;
216  cell->cell.modify_verify = gnc_date_cell_modify_verify;
217  cell->cell.direct_update = gnc_date_cell_direct_update;
218  cell->cell.set_value = gnc_date_cell_set_value_internal;
219 
220  box = g_new0 (PopBox, 1);
221 
222  box->sheet = NULL;
223  box->item_edit = NULL;
224  box->date_picker = NULL;
225 
226  box->signals_connected = FALSE;
227  box->calendar_popped = FALSE;
228  box->in_date_select = FALSE;
229 
230  cell->cell.gui_private = box;
231 
232  /* default value is today's date */
233  gnc_time (&secs);
234  gnc_localtime_r (&secs, &(box->date));
235  gnc_date_cell_print_date (cell, buff);
236 
237  gnc_basic_cell_set_value_internal (&cell->cell, buff);
238 }
239 
240 BasicCell *
242 {
243  DateCell *cell;
244 
245  cell = g_new0 (DateCell, 1);
246 
247  gnc_date_cell_init (cell);
248 
249  return &cell->cell;
250 }
251 
252 static void
253 date_picked_cb (GNCDatePicker *gdp, gpointer data)
254 {
255  DateCell *cell = data;
256  PopBox *box = cell->cell.gui_private;
257  guint day, month, year;
258  char buffer[DATE_BUF];
259 
260  gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
261 
262  qof_print_date_dmy_buff (buffer, MAX_DATE_LENGTH, day, month + 1, year);
263 
264  box->in_date_select = TRUE;
265  gnucash_sheet_modify_current_cell (box->sheet, buffer);
266  box->in_date_select = FALSE;
267 
268  gnc_item_edit_hide_popup (box->item_edit);
269  box->calendar_popped = FALSE;
270 }
271 
272 static void
273 date_selected_cb (GNCDatePicker *gdp, gpointer data)
274 {
275  DateCell *cell = data;
276  PopBox *box = cell->cell.gui_private;
277  guint day, month, year;
278  char buffer[DATE_BUF];
279 
280  gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
281 
282  qof_print_date_dmy_buff (buffer, MAX_DATE_LENGTH, day, month + 1, year);
283 
284  box->in_date_select = TRUE;
285  gnucash_sheet_modify_current_cell (box->sheet, buffer);
286  box->in_date_select = FALSE;
287 }
288 
289 static gboolean
290 key_press_item_cb (GNCDatePicker *gdp, GdkEventKey *event, gpointer data)
291 {
292  DateCell *cell = data;
293  PopBox *box = cell->cell.gui_private;
294 
295  switch (event->keyval)
296  {
297  case GDK_KEY_Escape:
298  gnc_item_edit_hide_popup (box->item_edit);
299  box->calendar_popped = FALSE;
300  break;
301 
302  default:
303  gtk_widget_event(GTK_WIDGET (box->sheet), (GdkEvent *) event);
304  break;
305  }
306  return TRUE;
307 }
308 
309 static void
310 date_picker_disconnect_signals (DateCell *cell)
311 {
312  PopBox *box = cell->cell.gui_private;
313 
314  if (!box->signals_connected)
315  return;
316 
317  g_signal_handlers_disconnect_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
318  0, 0, NULL, NULL, cell);
319 
320  box->signals_connected = FALSE;
321 }
322 
323 static void
324 date_picker_connect_signals (DateCell *cell)
325 {
326  PopBox *box = cell->cell.gui_private;
327 
328  if (box->signals_connected)
329  return;
330 
331  g_signal_connect (box->date_picker, "date_selected",
332  G_CALLBACK(date_selected_cb), cell);
333 
334  g_signal_connect(box->date_picker, "date_picked",
335  G_CALLBACK(date_picked_cb), cell);
336 
337  g_signal_connect(box->date_picker, "key_press_event",
338  G_CALLBACK(key_press_item_cb), cell);
339 
340  box->signals_connected = TRUE;
341 }
342 
343 static void
344 block_picker_signals (DateCell *cell)
345 {
346  PopBox *box = cell->cell.gui_private;
347 
348  if (!box->signals_connected)
349  return;
350 
351  g_signal_handlers_block_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
352  0, 0, NULL, NULL, cell);
353 }
354 
355 static void
356 unblock_picker_signals (DateCell *cell)
357 {
358  PopBox *box = cell->cell.gui_private;
359 
360  if (!box->signals_connected)
361  return;
362 
363  g_signal_handlers_unblock_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
364  0, 0, NULL, NULL, cell);
365 }
366 
367 static void
368 gnc_date_cell_gui_destroy (BasicCell *bcell)
369 {
370  PopBox *box = bcell->gui_private;
371  DateCell *cell = (DateCell *) bcell;
372 
373  if (cell->cell.gui_realize == NULL)
374  {
375  if (box != NULL && box->date_picker != NULL)
376  {
377  date_picker_disconnect_signals (cell);
378  g_object_unref (box->date_picker);
379  box->date_picker = NULL;
380  }
381 
382  /* allow the widget to be shown again */
383  cell->cell.gui_realize = gnc_date_cell_realize;
384  cell->cell.gui_move = NULL;
385  cell->cell.enter_cell = NULL;
386  cell->cell.leave_cell = NULL;
387  cell->cell.gui_destroy = NULL;
388  }
389 }
390 
391 static void
392 gnc_date_cell_destroy (BasicCell *bcell)
393 {
394  DateCell *cell = (DateCell *) bcell;
395  PopBox *box = cell->cell.gui_private;
396 
397  gnc_date_cell_gui_destroy (&(cell->cell));
398 
399  g_free (box);
400 
401  cell->cell.gui_private = NULL;
402  cell->cell.gui_realize = NULL;
403 }
404 
405 void
406 gnc_date_cell_set_value (DateCell *cell, int day, int mon, int year)
407 {
408  PopBox *box = cell->cell.gui_private;
409  struct tm dada;
410  char buff[DATE_BUF];
411 
412  dada.tm_mday = day;
413  dada.tm_mon = mon - 1;
414  dada.tm_year = year - 1900;
415 
416  gnc_tm_set_day_start(&dada);
417  gnc_mktime (&dada);
418 
419  box->date.tm_mday = dada.tm_mday;
420  box->date.tm_mon = dada.tm_mon;
421  box->date.tm_year = dada.tm_year;
422 
423  qof_print_date_dmy_buff (buff, MAX_DATE_LENGTH, dada.tm_mday, dada.tm_mon + 1, dada.tm_year + 1900);
424 
425  gnc_basic_cell_set_value_internal (&cell->cell, buff);
426 
427  if (!box->date_picker)
428  return;
429 
430  block_picker_signals (cell);
431  gnc_date_picker_set_date (box->date_picker, day, mon - 1, year);
432  unblock_picker_signals (cell);
433 }
434 
435 void
437 {
438  PopBox *box = cell->cell.gui_private;
439  char buff[DATE_BUF];
440 
441  gnc_localtime_r (&secs, &(box->date));
442 
444  box->date.tm_mday,
445  box->date.tm_mon + 1,
446  box->date.tm_year + 1900);
447 
448  gnc_basic_cell_set_value_internal (&cell->cell, buff);
449 
450  if (!box->date_picker)
451  return;
452 
453  block_picker_signals (cell);
454  gnc_date_picker_set_date (box->date_picker,
455  box->date.tm_mday,
456  box->date.tm_mon,
457  box->date.tm_year + 1900);
458  unblock_picker_signals (cell);
459 }
460 
461 void
463 {
464  PopBox *box = cell->cell.gui_private;
465  char buff[DATE_BUF];
466 
467  if (!cell)
468  return;
469 
470  gnc_parse_date (&(box->date), cell->cell.value, FALSE);
471 
473  box->date.tm_mday,
474  box->date.tm_mon + 1,
475  box->date.tm_year + 1900);
476 
477  gnc_basic_cell_set_value_internal (&cell->cell, buff);
478 
479  if (!box->date_picker)
480  return;
481 
482  block_picker_signals (cell);
483  gnc_date_picker_set_date (box->date_picker,
484  box->date.tm_mday,
485  box->date.tm_mon,
486  box->date.tm_year + 1900);
487  unblock_picker_signals (cell);
488 }
489 
490 static gboolean
491 gnc_date_cell_direct_update (BasicCell *bcell,
492  int *cursor_position,
493  int *start_selection,
494  int *end_selection,
495  void *gui_data)
496 {
497  DateCell *cell = (DateCell *) bcell;
498  PopBox *box = cell->cell.gui_private;
499  GdkEventKey *event = gui_data;
500  char buff[DATE_BUF];
501 
502  if (event->keyval == GDK_KEY_Escape)
503  {
504  if (bcell->changed)
505  {
506  const char *value = gnc_table_get_model_entry (box->sheet->table, bcell->cell_name);
507 
508  gnc_basic_cell_set_value_internal (bcell, value);
509  bcell->changed = FALSE;
510  *cursor_position = 0;
511  *start_selection = 0;
512  *end_selection = -1;
513  return TRUE;
514  }
515  return FALSE;
516  }
517 
518  if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
519  return FALSE;
520 
522  box->date.tm_mday,
523  box->date.tm_mon + 1,
524  box->date.tm_year + 1900);
525 
526  gnc_basic_cell_set_value_internal (&cell->cell, buff);
527 
528  *start_selection = 0;
529  *end_selection = -1;
530 
531  if (!box->date_picker)
532  return TRUE;
533 
534  block_picker_signals (cell);
535  gnc_date_picker_set_date (box->date_picker,
536  box->date.tm_mday,
537  box->date.tm_mon,
538  box->date.tm_year + 1900);
539  unblock_picker_signals (cell);
540 
541  return TRUE;
542 }
543 
544 static void
545 gnc_date_cell_modify_verify (BasicCell *_cell,
546  const char *change,
547  int change_len,
548  const char *newval,
549  int newval_len,
550  int *cursor_position,
551  int *start_selection,
552  int *end_selection)
553 {
554  DateCell *cell = (DateCell *) _cell;
555  PopBox *box = cell->cell.gui_private;
556  gboolean accept = FALSE;
557 
558  if (box->in_date_select)
559  {
560  gnc_basic_cell_set_value (_cell, newval);
561  return;
562  }
563 
564  /* if user hit backspace, accept the change */
565  if (change == NULL)
566  accept = TRUE;
567  else if (change_len == 0)
568  accept = TRUE;
569  else
570  {
571  int count = 0;
572  unsigned char separator = dateSeparator ();
573  gboolean ok = TRUE;
574  const gchar *c;
575  gunichar uc;
576 
577  /* accept only numbers or a date separator. Note that the
578  * separator of '-' (for DATE_FORMAT_ISO) takes precedence
579  * over the accelerator below! */
580  c = change;
581  while (*c)
582  {
583  uc = g_utf8_get_char (c);
584 
585  if (!g_unichar_isdigit (uc) && (separator != uc))
586  ok = FALSE;
587 
588  if (separator == uc)
589  count++;
590 
591  c = g_utf8_next_char (c);
592  }
593 
594  c = _cell->value;
595  while (*c)
596  {
597  uc = g_utf8_get_char (c);
598 
599  if (separator == uc)
600  count++;
601 
602  c = g_utf8_next_char (c);
603  }
604 
605  if (2 < count)
606  ok = FALSE;
607 
608  if (ok)
609  accept = TRUE;
610  }
611 
612  /* keep a copy of the new value */
613  if (accept)
614  {
615  gnc_basic_cell_set_value_internal (&cell->cell, newval);
616  gnc_parse_date (&(box->date), newval, FALSE);
617  *end_selection = *start_selection = *cursor_position;
618 
619  if (!box->date_picker)
620  return;
621 
622  block_picker_signals (cell);
623  gnc_date_picker_set_date (box->date_picker,
624  box->date.tm_mday,
625  box->date.tm_mon,
626  box->date.tm_year + 1900);
627  unblock_picker_signals (cell);
628  }
629 }
630 
631 static void
632 gnc_date_cell_realize (BasicCell *bcell, gpointer data)
633 {
634  GnucashSheet *sheet = data;
635  GncItemEdit *item_edit = gnucash_sheet_get_item_edit (sheet);
636  DateCell *cell = (DateCell *) bcell;
637  PopBox *box = cell->cell.gui_private;
638 
639  /* initialize gui-specific, private data */
640  box->sheet = sheet;
641  box->item_edit = item_edit;
642  box->date_picker = GNC_DATE_PICKER (gnc_date_picker_new ());
643  gtk_widget_show_all (GTK_WIDGET(box->date_picker));
644  g_object_ref_sink(box->date_picker);
645 
646  /* to mark cell as realized, remove the realize method */
647  cell->cell.gui_realize = NULL;
648  cell->cell.gui_move = gnc_date_cell_move;
649  cell->cell.enter_cell = gnc_date_cell_enter;
650  cell->cell.leave_cell = gnc_date_cell_leave;
651 }
652 
653 static void
654 gnc_date_cell_move (BasicCell *bcell)
655 {
656  PopBox *box = bcell->gui_private;
657 
658  date_picker_disconnect_signals ((DateCell *) bcell);
659 
660  gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
661  NULL, NULL, NULL, NULL, NULL);
662 
663  box->calendar_popped = FALSE;
664 }
665 
666 static int
667 popup_get_height (GtkWidget *widget,
668  G_GNUC_UNUSED int space_available,
669  G_GNUC_UNUSED int row_height,
670  G_GNUC_UNUSED gpointer user_data)
671 {
672  GtkWidget *cal = GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar);
673  GtkRequisition req;
674 
675  req.height = 0;
676  req.width = 0;
677 
678  gtk_widget_get_preferred_size (cal, &req, NULL);
679 
680  return req.height;
681 }
682 
683 static void
684 popup_set_focus (GtkWidget *widget,
685  G_GNUC_UNUSED gpointer user_data)
686 {
687  gtk_widget_grab_focus (GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar));
688 }
689 
690 static gboolean
691 gnc_date_cell_enter (BasicCell *bcell,
692  G_GNUC_UNUSED int *cursor_position,
693  int *start_selection,
694  int *end_selection)
695 {
696  DateCell *cell = (DateCell *) bcell;
697  PopBox *box = bcell->gui_private;
698 
699  gnc_item_edit_set_popup (box->item_edit, GTK_WIDGET (box->date_picker),
700  popup_get_height, NULL, popup_set_focus,
701  NULL, NULL, NULL);
702 
703  block_picker_signals (cell);
704  gnc_date_picker_set_date (box->date_picker,
705  box->date.tm_mday,
706  box->date.tm_mon,
707  box->date.tm_year + 1900);
708  unblock_picker_signals (cell);
709 
710  date_picker_connect_signals ((DateCell *) bcell);
711 
712  *start_selection = 0;
713  *end_selection = -1;
714 
715  return TRUE;
716 }
717 
718 static void
719 gnc_date_cell_leave (BasicCell *bcell)
720 {
721  time64 time;
722  PopBox *box = bcell->gui_private;
723 
724  date_picker_disconnect_signals ((DateCell *) bcell);
725 
726  gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
727  NULL, NULL, NULL, NULL, NULL);
728 
729  box->calendar_popped = FALSE;
730 
731  /* Refresh the date to expand any shortcuts. */
732  gnc_date_cell_get_date ((DateCell *)bcell, &time, TRUE);
733  gnc_date_cell_set_value_secs ((DateCell *)bcell, time);
734 }
735 
736 void
737 gnc_date_cell_get_date (DateCell *cell, time64 *time, gboolean warn)
738 {
739  PopBox *box = cell->cell.gui_private;
740  if (!cell || !time)
741  return;
742 
743  gnc_parse_date (&(box->date), cell->cell.value, warn);
744  *time = gnc_mktime (&box->date);
745 }
746 
747 static void
748 gnc_date_cell_set_value_internal (BasicCell *_cell, const char *str)
749 {
750  DateCell *cell = (DateCell *) _cell;
751  PopBox *box = cell->cell.gui_private;
752  char buff[DATE_BUF];
753 
754  gnc_parse_date (&(box->date), str, FALSE);
755 
757  box->date.tm_mday,
758  box->date.tm_mon + 1,
759  box->date.tm_year + 1900);
760 
761  gnc_basic_cell_set_value_internal (_cell, buff);
762 
763  if (!box->date_picker)
764  return;
765 
766  block_picker_signals (cell);
767  gnc_date_picker_set_date (box->date_picker,
768  box->date.tm_mday,
769  box->date.tm_mon,
770  box->date.tm_year + 1900);
771  unblock_picker_signals (cell);
772 }
size_t qof_print_date_dmy_buff(gchar *buff, size_t buflen, int day, int month, int year)
qof_print_date_dmy_buff Convert a date as day / month / year integers into a localized string represe...
gchar dateSeparator(void)
dateSeparator Return the field separator for the current date format
Definition: gnc-date.cpp:999
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
utility functions for the GnuCash UI
void gnc_date_cell_set_value_secs(DateCell *cell, time64 secs)
Sets the contents of the cell with seconds before or since the Unix epoch.
void gnc_tm_get_today_start(struct tm *tm)
The gnc_tm_get_today_start() routine takes a pointer to a struct tm and fills it in with the first se...
Definition: gnc-date.cpp:1399
void gnc_date_cell_set_value(DateCell *cell, int day, int mon, int year)
Accepts a numeric date and sets the contents of the date cell to that value.
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
Definition: gnc-date.cpp:115
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
Returns the GDate that is the threshold for auto-read-only.
Definition: qofbook.cpp:988
void gnc_date_cell_get_date(DateCell *cell, time64 *time, gboolean warn)
Set a time64 to the value in the DateCell.
BasicCell * gnc_date_cell_new(void)
installs a callback to handle date recording
void gnc_date_cell_commit(DateCell *cell)
Commits any pending changes to the value of the cell.
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
Definition: gnc-date.cpp:219
Public declarations of GnucashRegister class.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
Definition: gnc-date.h:108
Private declarations for GnucashSheet class.
Public declarations for GncDatePicker class.
Public declarations for GncItemEdit class.
gboolean qof_scan_date(const char *buff, int *day, int *month, int *year)
qof_scan_date Convert a string into day / month / year integers according to the current dateFormat v...
Definition: gnc-date.cpp:991
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:262
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
The DateCell object implements a date handling cell.
Definition: datecell.h:91
gboolean qof_book_uses_autoreadonly(const QofBook *book)
Returns TRUE if the auto-read-only feature should be used, otherwise FALSE.
Definition: qofbook.cpp:962