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);
309 date_picker_disconnect_signals (
DateCell *cell)
311 PopBox *box = cell->cell.gui_private;
313 if (!box->signals_connected)
316 g_signal_handlers_disconnect_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
317 0, 0, NULL, NULL, cell);
319 box->signals_connected = FALSE;
323 date_picker_connect_signals (
DateCell *cell)
325 PopBox *box = cell->cell.gui_private;
327 if (box->signals_connected)
330 g_signal_connect (box->date_picker,
"date_selected",
331 G_CALLBACK(date_selected_cb), cell);
333 g_signal_connect(box->date_picker,
"date_picked",
334 G_CALLBACK(date_picked_cb), cell);
336 g_signal_connect(box->date_picker,
"key_press_event",
337 G_CALLBACK(key_press_item_cb), cell);
339 box->signals_connected = TRUE;
343 block_picker_signals (
DateCell *cell)
345 PopBox *box = cell->cell.gui_private;
347 if (!box->signals_connected)
350 g_signal_handlers_block_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
351 0, 0, NULL, NULL, cell);
355 unblock_picker_signals (
DateCell *cell)
357 PopBox *box = cell->cell.gui_private;
359 if (!box->signals_connected)
362 g_signal_handlers_unblock_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
363 0, 0, NULL, NULL, cell);
367 gnc_date_cell_gui_destroy (BasicCell *bcell)
369 PopBox *box = bcell->gui_private;
372 if (cell->cell.gui_realize == NULL)
374 if (box != NULL && box->date_picker != NULL)
376 date_picker_disconnect_signals (cell);
377 g_object_unref (box->date_picker);
378 box->date_picker = NULL;
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;
391 gnc_date_cell_destroy (BasicCell *bcell)
394 PopBox *box = cell->cell.gui_private;
396 gnc_date_cell_gui_destroy (&(cell->cell));
400 cell->cell.gui_private = NULL;
401 cell->cell.gui_realize = NULL;
407 PopBox *box = cell->cell.gui_private;
412 dada.tm_mon = mon - 1;
413 dada.tm_year = year - 1900;
415 gnc_tm_set_day_start(&dada);
418 box->date.tm_mday = dada.tm_mday;
419 box->date.tm_mon = dada.tm_mon;
420 box->date.tm_year = dada.tm_year;
424 gnc_basic_cell_set_value_internal (&cell->cell, buff);
426 if (!box->date_picker)
429 block_picker_signals (cell);
430 gnc_date_picker_set_date (box->date_picker, day, mon - 1, year);
431 unblock_picker_signals (cell);
437 PopBox *box = cell->cell.gui_private;
444 box->date.tm_mon + 1,
445 box->date.tm_year + 1900);
447 gnc_basic_cell_set_value_internal (&cell->cell, buff);
449 if (!box->date_picker)
452 block_picker_signals (cell);
453 gnc_date_picker_set_date (box->date_picker,
456 box->date.tm_year + 1900);
457 unblock_picker_signals (cell);
463 PopBox *box = cell->cell.gui_private;
469 gnc_parse_date (&(box->date), cell->cell.value, FALSE);
473 box->date.tm_mon + 1,
474 box->date.tm_year + 1900);
476 gnc_basic_cell_set_value_internal (&cell->cell, buff);
478 if (!box->date_picker)
481 block_picker_signals (cell);
482 gnc_date_picker_set_date (box->date_picker,
485 box->date.tm_year + 1900);
486 unblock_picker_signals (cell);
490 gnc_date_cell_direct_update (BasicCell *bcell,
491 int *cursor_position,
492 int *start_selection,
497 PopBox *box = cell->cell.gui_private;
498 GdkEventKey *
event = gui_data;
501 if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
506 box->date.tm_mon + 1,
507 box->date.tm_year + 1900);
509 gnc_basic_cell_set_value_internal (&cell->cell, buff);
511 *start_selection = 0;
514 if (!box->date_picker)
517 block_picker_signals (cell);
518 gnc_date_picker_set_date (box->date_picker,
521 box->date.tm_year + 1900);
522 unblock_picker_signals (cell);
528 gnc_date_cell_modify_verify (BasicCell *_cell,
533 int *cursor_position,
534 int *start_selection,
538 PopBox *box = cell->cell.gui_private;
539 gboolean accept = FALSE;
541 if (box->in_date_select)
543 gnc_basic_cell_set_value (_cell, newval);
550 else if (change_len == 0)
566 uc = g_utf8_get_char (c);
568 if (!g_unichar_isdigit (uc) && (separator != uc))
574 c = g_utf8_next_char (c);
580 uc = g_utf8_get_char (c);
585 c = g_utf8_next_char (c);
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;
602 if (!box->date_picker)
605 block_picker_signals (cell);
606 gnc_date_picker_set_date (box->date_picker,
609 box->date.tm_year + 1900);
610 unblock_picker_signals (cell);
615 gnc_date_cell_realize (BasicCell *bcell, gpointer data)
617 GnucashSheet *sheet = data;
618 GncItemEdit *item_edit = gnucash_sheet_get_item_edit (sheet);
620 PopBox *box = cell->cell.gui_private;
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);
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;
637 gnc_date_cell_move (BasicCell *bcell)
639 PopBox *box = bcell->gui_private;
641 date_picker_disconnect_signals ((
DateCell *) bcell);
643 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
644 NULL, NULL, NULL, NULL, NULL);
646 box->calendar_popped = FALSE;
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)
655 GtkWidget *cal = GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar);
661 gtk_widget_get_preferred_size (cal, &req, NULL);
667 popup_set_focus (GtkWidget *widget,
668 G_GNUC_UNUSED gpointer user_data)
670 gtk_widget_grab_focus (GTK_WIDGET (GNC_DATE_PICKER (widget)->calendar));
674 gnc_date_cell_enter (BasicCell *bcell,
675 G_GNUC_UNUSED
int *cursor_position,
676 int *start_selection,
680 PopBox *box = bcell->gui_private;
682 gnc_item_edit_set_popup (box->item_edit, GTK_WIDGET (box->date_picker),
683 popup_get_height, NULL, popup_set_focus,
686 block_picker_signals (cell);
687 gnc_date_picker_set_date (box->date_picker,
690 box->date.tm_year + 1900);
691 unblock_picker_signals (cell);
693 date_picker_connect_signals ((
DateCell *) bcell);
695 *start_selection = 0;
702 gnc_date_cell_leave (BasicCell *bcell)
705 PopBox *box = bcell->gui_private;
707 date_picker_disconnect_signals ((
DateCell *) bcell);
709 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
710 NULL, NULL, NULL, NULL, NULL);
712 box->calendar_popped = FALSE;
722 PopBox *box = cell->cell.gui_private;
726 gnc_parse_date (&(box->date), cell->cell.value, warn);
731 gnc_date_cell_set_value_internal (BasicCell *_cell,
const char *str)
734 PopBox *box = cell->cell.gui_private;
737 gnc_parse_date (&(box->date), str, FALSE);
741 box->date.tm_mon + 1,
742 box->date.tm_year + 1900);
744 gnc_basic_cell_set_value_internal (_cell, buff);
746 if (!box->date_picker)
749 block_picker_signals (cell);
750 gnc_date_picker_set_date (box->date_picker,
753 box->date.tm_year + 1900);
754 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.