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 void
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 }
307 
308 static void
309 date_picker_disconnect_signals (DateCell *cell)
310 {
311  PopBox *box = cell->cell.gui_private;
312 
313  if (!box->signals_connected)
314  return;
315 
316  g_signal_handlers_disconnect_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
317  0, 0, NULL, NULL, cell);
318 
319  box->signals_connected = FALSE;
320 }
321 
322 static void
323 date_picker_connect_signals (DateCell *cell)
324 {
325  PopBox *box = cell->cell.gui_private;
326 
327  if (box->signals_connected)
328  return;
329 
330  g_signal_connect (box->date_picker, "date_selected",
331  G_CALLBACK(date_selected_cb), cell);
332 
333  g_signal_connect(box->date_picker, "date_picked",
334  G_CALLBACK(date_picked_cb), cell);
335 
336  g_signal_connect(box->date_picker, "key_press_event",
337  G_CALLBACK(key_press_item_cb), cell);
338 
339  box->signals_connected = TRUE;
340 }
341 
342 static void
343 block_picker_signals (DateCell *cell)
344 {
345  PopBox *box = cell->cell.gui_private;
346 
347  if (!box->signals_connected)
348  return;
349 
350  g_signal_handlers_block_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
351  0, 0, NULL, NULL, cell);
352 }
353 
354 static void
355 unblock_picker_signals (DateCell *cell)
356 {
357  PopBox *box = cell->cell.gui_private;
358 
359  if (!box->signals_connected)
360  return;
361 
362  g_signal_handlers_unblock_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
363  0, 0, NULL, NULL, cell);
364 }
365 
366 static void
367 gnc_date_cell_gui_destroy (BasicCell *bcell)
368 {
369  PopBox *box = bcell->gui_private;
370  DateCell *cell = (DateCell *) bcell;
371 
372  if (cell->cell.gui_realize == NULL)
373  {
374  if (box != NULL && box->date_picker != NULL)
375  {
376  date_picker_disconnect_signals (cell);
377  g_object_unref (box->date_picker);
378  box->date_picker = NULL;
379  }
380 
381  /* allow the widget to be shown again */
382  cell->cell.gui_realize = gnc_date_cell_realize;
383  cell->cell.gui_move = NULL;
384  cell->cell.enter_cell = NULL;
385  cell->cell.leave_cell = NULL;
386  cell->cell.gui_destroy = NULL;
387  }
388 }
389 
390 static void
391 gnc_date_cell_destroy (BasicCell *bcell)
392 {
393  DateCell *cell = (DateCell *) bcell;
394  PopBox *box = cell->cell.gui_private;
395 
396  gnc_date_cell_gui_destroy (&(cell->cell));
397 
398  g_free (box);
399 
400  cell->cell.gui_private = NULL;
401  cell->cell.gui_realize = NULL;
402 }
403 
404 void
405 gnc_date_cell_set_value (DateCell *cell, int day, int mon, int year)
406 {
407  PopBox *box = cell->cell.gui_private;
408  struct tm dada;
409  char buff[DATE_BUF];
410 
411  dada.tm_mday = day;
412  dada.tm_mon = mon - 1;
413  dada.tm_year = year - 1900;
414 
415  gnc_tm_set_day_start(&dada);
416  gnc_mktime (&dada);
417 
418  box->date.tm_mday = dada.tm_mday;
419  box->date.tm_mon = dada.tm_mon;
420  box->date.tm_year = dada.tm_year;
421 
422  qof_print_date_dmy_buff (buff, MAX_DATE_LENGTH, dada.tm_mday, dada.tm_mon + 1, dada.tm_year + 1900);
423 
424  gnc_basic_cell_set_value_internal (&cell->cell, buff);
425 
426  if (!box->date_picker)
427  return;
428 
429  block_picker_signals (cell);
430  gnc_date_picker_set_date (box->date_picker, day, mon - 1, year);
431  unblock_picker_signals (cell);
432 }
433 
434 void
436 {
437  PopBox *box = cell->cell.gui_private;
438  char buff[DATE_BUF];
439 
440  gnc_localtime_r (&secs, &(box->date));
441 
443  box->date.tm_mday,
444  box->date.tm_mon + 1,
445  box->date.tm_year + 1900);
446 
447  gnc_basic_cell_set_value_internal (&cell->cell, buff);
448 
449  if (!box->date_picker)
450  return;
451 
452  block_picker_signals (cell);
453  gnc_date_picker_set_date (box->date_picker,
454  box->date.tm_mday,
455  box->date.tm_mon,
456  box->date.tm_year + 1900);
457  unblock_picker_signals (cell);
458 }
459 
460 void
462 {
463  PopBox *box = cell->cell.gui_private;
464  char buff[DATE_BUF];
465 
466  if (!cell)
467  return;
468 
469  gnc_parse_date (&(box->date), cell->cell.value, FALSE);
470 
472  box->date.tm_mday,
473  box->date.tm_mon + 1,
474  box->date.tm_year + 1900);
475 
476  gnc_basic_cell_set_value_internal (&cell->cell, buff);
477 
478  if (!box->date_picker)
479  return;
480 
481  block_picker_signals (cell);
482  gnc_date_picker_set_date (box->date_picker,
483  box->date.tm_mday,
484  box->date.tm_mon,
485  box->date.tm_year + 1900);
486  unblock_picker_signals (cell);
487 }
488 
489 static gboolean
490 gnc_date_cell_direct_update (BasicCell *bcell,
491  int *cursor_position,
492  int *start_selection,
493  int *end_selection,
494  void *gui_data)
495 {
496  DateCell *cell = (DateCell *) bcell;
497  PopBox *box = cell->cell.gui_private;
498  GdkEventKey *event = gui_data;
499  char buff[DATE_BUF];
500 
501  if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
502  return FALSE;
503 
505  box->date.tm_mday,
506  box->date.tm_mon + 1,
507  box->date.tm_year + 1900);
508 
509  gnc_basic_cell_set_value_internal (&cell->cell, buff);
510 
511  *start_selection = 0;
512  *end_selection = -1;
513 
514  if (!box->date_picker)
515  return TRUE;
516 
517  block_picker_signals (cell);
518  gnc_date_picker_set_date (box->date_picker,
519  box->date.tm_mday,
520  box->date.tm_mon,
521  box->date.tm_year + 1900);
522  unblock_picker_signals (cell);
523 
524  return TRUE;
525 }
526 
527 static void
528 gnc_date_cell_modify_verify (BasicCell *_cell,
529  const char *change,
530  int change_len,
531  const char *newval,
532  int newval_len,
533  int *cursor_position,
534  int *start_selection,
535  int *end_selection)
536 {
537  DateCell *cell = (DateCell *) _cell;
538  PopBox *box = cell->cell.gui_private;
539  gboolean accept = FALSE;
540 
541  if (box->in_date_select)
542  {
543  gnc_basic_cell_set_value (_cell, newval);
544  return;
545  }
546 
547  /* if user hit backspace, accept the change */
548  if (change == NULL)
549  accept = TRUE;
550  else if (change_len == 0)
551  accept = TRUE;
552  else
553  {
554  int count = 0;
555  unsigned char separator = dateSeparator ();
556  gboolean ok = TRUE;
557  const gchar *c;
558  gunichar uc;
559 
560  /* accept only numbers or a date separator. Note that the
561  * separator of '-' (for DATE_FORMAT_ISO) takes precedence
562  * over the accelerator below! */
563  c = change;
564  while (*c)
565  {
566  uc = g_utf8_get_char (c);
567 
568  if (!g_unichar_isdigit (uc) && (separator != uc))
569  ok = FALSE;
570 
571  if (separator == uc)
572  count++;
573 
574  c = g_utf8_next_char (c);
575  }
576 
577  c = _cell->value;
578  while (*c)
579  {
580  uc = g_utf8_get_char (c);
581 
582  if (separator == uc)
583  count++;
584 
585  c = g_utf8_next_char (c);
586  }
587 
588  if (2 < count)
589  ok = FALSE;
590 
591  if (ok)
592  accept = TRUE;
593  }
594 
595  /* keep a copy of the new value */
596  if (accept)
597  {
598  gnc_basic_cell_set_value_internal (&cell->cell, newval);
599  gnc_parse_date (&(box->date), newval, FALSE);
600  *end_selection = *start_selection = *cursor_position;
601 
602  if (!box->date_picker)
603  return;
604 
605  block_picker_signals (cell);
606  gnc_date_picker_set_date (box->date_picker,
607  box->date.tm_mday,
608  box->date.tm_mon,
609  box->date.tm_year + 1900);
610  unblock_picker_signals (cell);
611  }
612 }
613 
614 static void
615 gnc_date_cell_realize (BasicCell *bcell, gpointer data)
616 {
617  GnucashSheet *sheet = data;
618  GncItemEdit *item_edit = gnucash_sheet_get_item_edit (sheet);
619  DateCell *cell = (DateCell *) bcell;
620  PopBox *box = cell->cell.gui_private;
621 
622  /* initialize gui-specific, private data */
623  box->sheet = sheet;
624  box->item_edit = item_edit;
625  box->date_picker = GNC_DATE_PICKER (gnc_date_picker_new ());
626  gtk_widget_show_all (GTK_WIDGET(box->date_picker));
627  g_object_ref_sink(box->date_picker);
628 
629  /* to mark cell as realized, remove the realize method */
630  cell->cell.gui_realize = NULL;
631  cell->cell.gui_move = gnc_date_cell_move;
632  cell->cell.enter_cell = gnc_date_cell_enter;
633  cell->cell.leave_cell = gnc_date_cell_leave;
634 }
635 
636 static void
637 gnc_date_cell_move (BasicCell *bcell)
638 {
639  PopBox *box = bcell->gui_private;
640 
641  date_picker_disconnect_signals ((DateCell *) bcell);
642 
643  gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
644  NULL, NULL, NULL, NULL, NULL);
645 
646  box->calendar_popped = FALSE;
647 }
648 
649 static int
650 popup_get_height (GtkWidget *widget,
651  G_GNUC_UNUSED int space_available,
652  G_GNUC_UNUSED int row_height,
653  G_GNUC_UNUSED gpointer user_data)
654 {
655  GtkWidget *cal = GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar);
656  GtkRequisition req;
657 
658  req.height = 0;
659  req.width = 0;
660 
661  gtk_widget_get_preferred_size (cal, &req, NULL);
662 
663  return req.height;
664 }
665 
666 static void
667 popup_set_focus (GtkWidget *widget,
668  G_GNUC_UNUSED gpointer user_data)
669 {
670  gtk_widget_grab_focus (GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar));
671 }
672 
673 static gboolean
674 gnc_date_cell_enter (BasicCell *bcell,
675  G_GNUC_UNUSED int *cursor_position,
676  int *start_selection,
677  int *end_selection)
678 {
679  DateCell *cell = (DateCell *) bcell;
680  PopBox *box = bcell->gui_private;
681 
682  gnc_item_edit_set_popup (box->item_edit, GTK_WIDGET (box->date_picker),
683  popup_get_height, NULL, popup_set_focus,
684  NULL, NULL, NULL);
685 
686  block_picker_signals (cell);
687  gnc_date_picker_set_date (box->date_picker,
688  box->date.tm_mday,
689  box->date.tm_mon,
690  box->date.tm_year + 1900);
691  unblock_picker_signals (cell);
692 
693  date_picker_connect_signals ((DateCell *) bcell);
694 
695  *start_selection = 0;
696  *end_selection = -1;
697 
698  return TRUE;
699 }
700 
701 static void
702 gnc_date_cell_leave (BasicCell *bcell)
703 {
704  time64 time;
705  PopBox *box = bcell->gui_private;
706 
707  date_picker_disconnect_signals ((DateCell *) bcell);
708 
709  gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
710  NULL, NULL, NULL, NULL, NULL);
711 
712  box->calendar_popped = FALSE;
713 
714  /* Refresh the date to expand any shortcuts. */
715  gnc_date_cell_get_date ((DateCell *)bcell, &time, TRUE);
716  gnc_date_cell_set_value_secs ((DateCell *)bcell, time);
717 }
718 
719 void
720 gnc_date_cell_get_date (DateCell *cell, time64 *time, gboolean warn)
721 {
722  PopBox *box = cell->cell.gui_private;
723  if (!cell || !time)
724  return;
725 
726  gnc_parse_date (&(box->date), cell->cell.value, warn);
727  *time = gnc_mktime (&box->date);
728 }
729 
730 static void
731 gnc_date_cell_set_value_internal (BasicCell *_cell, const char *str)
732 {
733  DateCell *cell = (DateCell *) _cell;
734  PopBox *box = cell->cell.gui_private;
735  char buff[DATE_BUF];
736 
737  gnc_parse_date (&(box->date), str, FALSE);
738 
740  box->date.tm_mday,
741  box->date.tm_mon + 1,
742  box->date.tm_year + 1900);
743 
744  gnc_basic_cell_set_value_internal (_cell, buff);
745 
746  if (!box->date_picker)
747  return;
748 
749  block_picker_signals (cell);
750  gnc_date_picker_set_date (box->date_picker,
751  box->date.tm_mday,
752  box->date.tm_mon,
753  box->date.tm_year + 1900);
754  unblock_picker_signals (cell);
755 }
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:925
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:1328
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:114
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:218
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:917
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
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