40 #include <glib/gi18n.h> 41 #include <gdk/gdkkeysyms.h> 44 #include "dialog-utils.h" 53 #define DATE_BUF (MAX_DATE_LENGTH+1) 55 typedef struct _PopBox
61 gboolean signals_connected;
62 gboolean calendar_popped;
63 gboolean in_date_select;
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,
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,
85 static gboolean gnc_date_cell_direct_update (BasicCell *bcell,
90 static gboolean gnc_date_cell_enter (BasicCell *bcell,
94 static void gnc_date_cell_leave (BasicCell *bcell);
97 check_readonly_threshold (
const gchar *datestr, GDate *d, gboolean warn)
100 if (g_date_compare(d, readonly_threshold) < 0)
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");
114 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog),
116 gtk_dialog_run (GTK_DIALOG(dialog));
117 gtk_widget_destroy (dialog);
123 g_date_set_julian (d, g_date_get_julian (readonly_threshold));
124 g_date_free (readonly_threshold);
127 g_date_free (readonly_threshold);
132 gnc_parse_date (
struct tm *parsed,
const char * datestr, gboolean warn)
134 int day, month, year;
139 if (!datestr)
return;
146 memset (&tm_today, 0,
sizeof (
struct tm));
148 day = tm_today.tm_mday;
149 month = tm_today.tm_mon + 1;
150 year = tm_today.tm_year + 1900;
153 test_date = g_date_new_dmy (day, month, year);
155 if (!gnc_gdate_in_valid_range (test_date, warn))
158 memset (&tm_today, 0,
sizeof (
struct tm));
160 year = tm_today.tm_year + 1900;
165 if (use_autoreadonly)
167 g_date_set_dmy (test_date, day, month, year);
168 if (check_readonly_threshold (datestr, test_date, warn))
170 day = g_date_get_day (test_date);
171 month = g_date_get_month (test_date);
172 year = g_date_get_year (test_date);
175 g_date_free (test_date);
177 parsed->tm_mday = day;
178 parsed->tm_mon = month - 1;
179 parsed->tm_year = year - 1900;
181 gnc_tm_set_day_start(parsed);
191 gnc_date_cell_print_date (
DateCell *cell,
char *buff)
193 PopBox *box = cell->cell.gui_private;
197 box->date.tm_mon + 1,
198 box->date.tm_year + 1900);
208 gnc_basic_cell_init (&(cell->cell));
210 cell->cell.is_popup = TRUE;
212 cell->cell.destroy = gnc_date_cell_destroy;
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;
223 box->item_edit = NULL;
224 box->date_picker = NULL;
226 box->signals_connected = FALSE;
227 box->calendar_popped = FALSE;
228 box->in_date_select = FALSE;
230 cell->cell.gui_private = box;
235 gnc_date_cell_print_date (cell, buff);
237 gnc_basic_cell_set_value_internal (&cell->cell, buff);
247 gnc_date_cell_init (cell);
256 PopBox *box = cell->cell.gui_private;
257 guint day, month, year;
258 char buffer[DATE_BUF];
260 gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
264 box->in_date_select = TRUE;
265 gnucash_sheet_modify_current_cell (box->sheet, buffer);
266 box->in_date_select = FALSE;
268 gnc_item_edit_hide_popup (box->item_edit);
269 box->calendar_popped = FALSE;
276 PopBox *box = cell->cell.gui_private;
277 guint day, month, year;
278 char buffer[DATE_BUF];
280 gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
284 box->in_date_select = TRUE;
285 gnucash_sheet_modify_current_cell (box->sheet, buffer);
286 box->in_date_select = FALSE;
290 key_press_item_cb (
GNCDatePicker *gdp, GdkEventKey *event, gpointer data)
293 PopBox *box = cell->cell.gui_private;
295 switch (event->keyval)
298 gnc_item_edit_hide_popup (box->item_edit);
299 box->calendar_popped = FALSE;
303 gtk_widget_event(GTK_WIDGET (box->sheet), (GdkEvent *) event);
310 date_picker_disconnect_signals (
DateCell *cell)
312 PopBox *box = cell->cell.gui_private;
314 if (!box->signals_connected)
317 g_signal_handlers_disconnect_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
318 0, 0, NULL, NULL, cell);
320 box->signals_connected = FALSE;
324 date_picker_connect_signals (
DateCell *cell)
326 PopBox *box = cell->cell.gui_private;
328 if (box->signals_connected)
331 g_signal_connect (box->date_picker,
"date_selected",
332 G_CALLBACK(date_selected_cb), cell);
334 g_signal_connect(box->date_picker,
"date_picked",
335 G_CALLBACK(date_picked_cb), cell);
337 g_signal_connect(box->date_picker,
"key_press_event",
338 G_CALLBACK(key_press_item_cb), cell);
340 box->signals_connected = TRUE;
344 block_picker_signals (
DateCell *cell)
346 PopBox *box = cell->cell.gui_private;
348 if (!box->signals_connected)
351 g_signal_handlers_block_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
352 0, 0, NULL, NULL, cell);
356 unblock_picker_signals (
DateCell *cell)
358 PopBox *box = cell->cell.gui_private;
360 if (!box->signals_connected)
363 g_signal_handlers_unblock_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
364 0, 0, NULL, NULL, cell);
368 gnc_date_cell_gui_destroy (BasicCell *bcell)
370 PopBox *box = bcell->gui_private;
373 if (cell->cell.gui_realize == NULL)
375 if (box != NULL && box->date_picker != NULL)
377 date_picker_disconnect_signals (cell);
378 g_object_unref (box->date_picker);
379 box->date_picker = NULL;
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;
392 gnc_date_cell_destroy (BasicCell *bcell)
395 PopBox *box = cell->cell.gui_private;
397 gnc_date_cell_gui_destroy (&(cell->cell));
401 cell->cell.gui_private = NULL;
402 cell->cell.gui_realize = NULL;
408 PopBox *box = cell->cell.gui_private;
413 dada.tm_mon = mon - 1;
414 dada.tm_year = year - 1900;
416 gnc_tm_set_day_start(&dada);
419 box->date.tm_mday = dada.tm_mday;
420 box->date.tm_mon = dada.tm_mon;
421 box->date.tm_year = dada.tm_year;
425 gnc_basic_cell_set_value_internal (&cell->cell, buff);
427 if (!box->date_picker)
430 block_picker_signals (cell);
431 gnc_date_picker_set_date (box->date_picker, day, mon - 1, year);
432 unblock_picker_signals (cell);
438 PopBox *box = cell->cell.gui_private;
445 box->date.tm_mon + 1,
446 box->date.tm_year + 1900);
448 gnc_basic_cell_set_value_internal (&cell->cell, buff);
450 if (!box->date_picker)
453 block_picker_signals (cell);
454 gnc_date_picker_set_date (box->date_picker,
457 box->date.tm_year + 1900);
458 unblock_picker_signals (cell);
464 PopBox *box = cell->cell.gui_private;
470 gnc_parse_date (&(box->date), cell->cell.value, FALSE);
474 box->date.tm_mon + 1,
475 box->date.tm_year + 1900);
477 gnc_basic_cell_set_value_internal (&cell->cell, buff);
479 if (!box->date_picker)
482 block_picker_signals (cell);
483 gnc_date_picker_set_date (box->date_picker,
486 box->date.tm_year + 1900);
487 unblock_picker_signals (cell);
491 gnc_date_cell_direct_update (BasicCell *bcell,
492 int *cursor_position,
493 int *start_selection,
498 PopBox *box = cell->cell.gui_private;
499 GdkEventKey *
event = gui_data;
502 if (event->keyval == GDK_KEY_Escape)
506 const char *value = gnc_table_get_model_entry (box->sheet->table, bcell->cell_name);
508 gnc_basic_cell_set_value_internal (bcell, value);
509 bcell->changed = FALSE;
510 *cursor_position = 0;
511 *start_selection = 0;
518 if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
523 box->date.tm_mon + 1,
524 box->date.tm_year + 1900);
526 gnc_basic_cell_set_value_internal (&cell->cell, buff);
528 *start_selection = 0;
531 if (!box->date_picker)
534 block_picker_signals (cell);
535 gnc_date_picker_set_date (box->date_picker,
538 box->date.tm_year + 1900);
539 unblock_picker_signals (cell);
545 gnc_date_cell_modify_verify (BasicCell *_cell,
550 int *cursor_position,
551 int *start_selection,
555 PopBox *box = cell->cell.gui_private;
556 gboolean accept = FALSE;
558 if (box->in_date_select)
560 gnc_basic_cell_set_value (_cell, newval);
567 else if (change_len == 0)
583 uc = g_utf8_get_char (c);
585 if (!g_unichar_isdigit (uc) && (separator != uc))
591 c = g_utf8_next_char (c);
597 uc = g_utf8_get_char (c);
602 c = g_utf8_next_char (c);
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;
619 if (!box->date_picker)
622 block_picker_signals (cell);
623 gnc_date_picker_set_date (box->date_picker,
626 box->date.tm_year + 1900);
627 unblock_picker_signals (cell);
632 gnc_date_cell_realize (BasicCell *bcell, gpointer data)
634 GnucashSheet *sheet = data;
635 GncItemEdit *item_edit = gnucash_sheet_get_item_edit (sheet);
637 PopBox *box = cell->cell.gui_private;
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);
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;
654 gnc_date_cell_move (BasicCell *bcell)
656 PopBox *box = bcell->gui_private;
658 date_picker_disconnect_signals ((
DateCell *) bcell);
660 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
661 NULL, NULL, NULL, NULL, NULL);
663 box->calendar_popped = FALSE;
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)
672 GtkWidget *cal = GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar);
678 gtk_widget_get_preferred_size (cal, &req, NULL);
684 popup_set_focus (GtkWidget *widget,
685 G_GNUC_UNUSED gpointer user_data)
687 gtk_widget_grab_focus (GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar));
691 gnc_date_cell_enter (BasicCell *bcell,
692 G_GNUC_UNUSED
int *cursor_position,
693 int *start_selection,
697 PopBox *box = bcell->gui_private;
699 gnc_item_edit_set_popup (box->item_edit, GTK_WIDGET (box->date_picker),
700 popup_get_height, NULL, popup_set_focus,
703 block_picker_signals (cell);
704 gnc_date_picker_set_date (box->date_picker,
707 box->date.tm_year + 1900);
708 unblock_picker_signals (cell);
710 date_picker_connect_signals ((
DateCell *) bcell);
712 *start_selection = 0;
719 gnc_date_cell_leave (BasicCell *bcell)
722 PopBox *box = bcell->gui_private;
724 date_picker_disconnect_signals ((
DateCell *) bcell);
726 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
727 NULL, NULL, NULL, NULL, NULL);
729 box->calendar_popped = FALSE;
739 PopBox *box = cell->cell.gui_private;
743 gnc_parse_date (&(box->date), cell->cell.value, warn);
748 gnc_date_cell_set_value_internal (BasicCell *_cell,
const char *str)
751 PopBox *box = cell->cell.gui_private;
754 gnc_parse_date (&(box->date), str, FALSE);
758 box->date.tm_mon + 1,
759 box->date.tm_year + 1900);
761 gnc_basic_cell_set_value_internal (_cell, buff);
763 if (!box->date_picker)
766 block_picker_signals (cell);
767 gnc_date_picker_set_date (box->date_picker,
770 box->date.tm_year + 1900);
771 unblock_picker_signals (cell);
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
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...
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.
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
Returns the GDate that is the threshold for auto-read-only.
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
Public declarations of GnucashRegister class.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
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...
time64 gnc_time(time64 *tbuf)
get the current time
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
The DateCell object implements a date handling cell.
gboolean qof_book_uses_autoreadonly(const QofBook *book)
Returns TRUE if the auto-read-only feature should be used, otherwise FALSE.