39 #include <gdk/gdkkeysyms.h>
42 #include "dialog-utils.h"
44 #include "gnucash-date-picker.h"
45 #include "gnucash-item-edit.h"
46 #include "gnucash-sheet.h"
47 #include "gnucash-sheetP.h"
50 #define DATE_BUF (MAX_DATE_LENGTH+1)
58 gboolean signals_connected;
59 gboolean calendar_popped;
60 gboolean in_date_select;
66 static void block_picker_signals (
DateCell *cell);
67 static void unblock_picker_signals (
DateCell *cell);
68 static void gnc_date_cell_realize (
BasicCell *bcell, gpointer w);
69 static void gnc_date_cell_set_value_internal (
BasicCell *bcell,
71 static void gnc_date_cell_move (
BasicCell *bcell);
72 static void gnc_date_cell_gui_destroy (
BasicCell *bcell);
73 static void gnc_date_cell_destroy (
BasicCell *bcell);
74 static void gnc_date_cell_modify_verify (
BasicCell *_cell,
82 static gboolean gnc_date_cell_direct_update (
BasicCell *bcell,
87 static gboolean gnc_date_cell_enter (
BasicCell *bcell,
91 static void gnc_date_cell_leave (
BasicCell *bcell);
94 check_readonly_threshold (
const gchar *datestr, GDate *d)
97 if (g_date_compare(d, readonly_threshold) < 0)
100 gchar *dialog_msg = _(
"The entered date of the new transaction is "
101 "older than the \"Read-Only Threshold\" set for "
102 "this book. This setting can be changed in "
103 "File -> Properties -> Accounts.");
104 gchar *dialog_title = _(
"Cannot store a transaction at this date");
105 GtkWidget *dialog = gtk_message_dialog_new(NULL,
110 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
112 gtk_dialog_run(GTK_DIALOG(dialog));
113 gtk_widget_destroy(dialog);
115 g_warning(
"Entered date %s is before the \"auto-read-only threshold\";"
116 " resetting to the threshold.", datestr);
119 g_date_set_julian (d, g_date_get_julian (readonly_threshold));
120 g_date_free (readonly_threshold);
123 g_date_free (readonly_threshold);
128 gnc_parse_date (
struct tm *parsed,
const char * datestr)
130 int day, month, year;
134 if (!datestr)
return;
141 memset (&tm_today, 0,
sizeof (
struct tm));
143 day = tm_today.tm_mday;
144 month = tm_today.tm_mon + 1;
145 year = tm_today.tm_year + 1900;
150 if (use_autoreadonly)
152 GDate *d = g_date_new_dmy(day, month, year);
153 if (check_readonly_threshold (datestr, d))
155 day = g_date_get_day (d);
156 month = g_date_get_month (d);
157 year = g_date_get_year (d);
162 parsed->tm_mday = day;
163 parsed->tm_mon = month - 1;
164 parsed->tm_year = year - 1900;
166 gnc_tm_set_day_start(parsed);
176 gnc_date_cell_print_date (
DateCell *cell,
char *buff)
178 PopBox *box = cell->cell.gui_private;
182 box->date.tm_mon + 1,
183 box->date.tm_year + 1900);
193 gnc_basic_cell_init (&(cell->cell));
195 cell->cell.is_popup = TRUE;
197 cell->cell.destroy = gnc_date_cell_destroy;
199 cell->cell.gui_realize = gnc_date_cell_realize;
200 cell->cell.gui_destroy = gnc_date_cell_gui_destroy;
201 cell->cell.modify_verify = gnc_date_cell_modify_verify;
202 cell->cell.direct_update = gnc_date_cell_direct_update;
203 cell->cell.set_value = gnc_date_cell_set_value_internal;
208 box->item_edit = NULL;
209 box->date_picker = NULL;
211 box->signals_connected = FALSE;
212 box->calendar_popped = FALSE;
213 box->in_date_select = FALSE;
215 cell->cell.gui_private = box;
220 gnc_date_cell_print_date (cell, buff);
222 gnc_basic_cell_set_value_internal (&cell->cell, buff);
226 gnc_date_cell_new (
void)
232 gnc_date_cell_init (cell);
241 PopBox *box = cell->cell.gui_private;
242 guint day, month, year;
243 char buffer[DATE_BUF];
245 gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
249 box->in_date_select = TRUE;
250 gnucash_sheet_modify_current_cell (box->sheet, buffer);
251 box->in_date_select = FALSE;
253 gnc_item_edit_hide_popup (box->item_edit);
254 box->calendar_popped = FALSE;
261 PopBox *box = cell->cell.gui_private;
262 guint day, month, year;
263 char buffer[DATE_BUF];
265 gtk_calendar_get_date (gdp->calendar, &year, &month, &day);
269 box->in_date_select = TRUE;
270 gnucash_sheet_modify_current_cell (box->sheet, buffer);
271 box->in_date_select = FALSE;
275 key_press_item_cb (
GNCDatePicker *gdp, GdkEventKey *event, gpointer data)
278 PopBox *box = cell->cell.gui_private;
280 switch (event->keyval)
283 gnc_item_edit_hide_popup (box->item_edit);
284 box->calendar_popped = FALSE;
288 gtk_widget_event(GTK_WIDGET (box->sheet), (GdkEvent *) event);
294 date_picker_disconnect_signals (
DateCell *cell)
296 PopBox *box = cell->cell.gui_private;
298 if (!box->signals_connected)
301 g_signal_handlers_disconnect_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
302 0, 0, NULL, NULL, cell);
304 box->signals_connected = FALSE;
308 date_picker_connect_signals (
DateCell *cell)
310 PopBox *box = cell->cell.gui_private;
312 if (box->signals_connected)
315 g_signal_connect (box->date_picker,
"date_selected",
316 G_CALLBACK(date_selected_cb), cell);
318 g_signal_connect(box->date_picker,
"date_picked",
319 G_CALLBACK(date_picked_cb), cell);
321 g_signal_connect(box->date_picker,
"key_press_event",
322 G_CALLBACK(key_press_item_cb), cell);
324 box->signals_connected = TRUE;
328 block_picker_signals (
DateCell *cell)
330 PopBox *box = cell->cell.gui_private;
332 if (!box->signals_connected)
335 g_signal_handlers_block_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
336 0, 0, NULL, NULL, cell);
340 unblock_picker_signals (
DateCell *cell)
342 PopBox *box = cell->cell.gui_private;
344 if (!box->signals_connected)
347 g_signal_handlers_unblock_matched (box->date_picker, G_SIGNAL_MATCH_DATA,
348 0, 0, NULL, NULL, cell);
352 gnc_date_cell_gui_destroy (
BasicCell *bcell)
354 PopBox *box = bcell->gui_private;
357 if (cell->cell.gui_realize == NULL)
359 if (box != NULL && box->date_picker != NULL)
361 date_picker_disconnect_signals (cell);
362 g_object_unref (box->date_picker);
363 box->date_picker = NULL;
367 cell->cell.gui_realize = gnc_date_cell_realize;
368 cell->cell.gui_move = NULL;
369 cell->cell.enter_cell = NULL;
370 cell->cell.leave_cell = NULL;
371 cell->cell.gui_destroy = NULL;
379 PopBox *box = cell->cell.gui_private;
381 gnc_date_cell_gui_destroy (&(cell->cell));
385 cell->cell.gui_private = NULL;
386 cell->cell.gui_realize = NULL;
390 gnc_date_cell_set_value (
DateCell *cell,
int day,
int mon,
int year)
392 PopBox *box = cell->cell.gui_private;
397 dada.tm_mon = mon - 1;
398 dada.tm_year = year - 1900;
400 gnc_tm_set_day_start(&dada);
403 box->date.tm_mday = dada.tm_mday;
404 box->date.tm_mon = dada.tm_mon;
405 box->date.tm_year = dada.tm_year;
409 gnc_basic_cell_set_value_internal (&cell->cell, buff);
411 if (!box->date_picker)
414 block_picker_signals (cell);
415 gnc_date_picker_set_date (box->date_picker, day, mon - 1, year);
416 unblock_picker_signals (cell);
422 PopBox *box = cell->cell.gui_private;
429 box->date.tm_mon + 1,
430 box->date.tm_year + 1900);
432 gnc_basic_cell_set_value_internal (&cell->cell, buff);
434 if (!box->date_picker)
437 block_picker_signals (cell);
438 gnc_date_picker_set_date (box->date_picker,
441 box->date.tm_year + 1900);
442 unblock_picker_signals (cell);
446 gnc_date_cell_commit (
DateCell *cell)
448 PopBox *box = cell->cell.gui_private;
454 gnc_parse_date (&(box->date), cell->cell.value);
458 box->date.tm_mon + 1,
459 box->date.tm_year + 1900);
461 gnc_basic_cell_set_value_internal (&cell->cell, buff);
463 if (!box->date_picker)
466 block_picker_signals (cell);
467 gnc_date_picker_set_date (box->date_picker,
470 box->date.tm_year + 1900);
471 unblock_picker_signals (cell);
475 gnc_date_cell_direct_update (
BasicCell *bcell,
476 int *cursor_position,
477 int *start_selection,
482 PopBox *box = cell->cell.gui_private;
483 GdkEventKey *
event = gui_data;
486 if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
491 box->date.tm_mon + 1,
492 box->date.tm_year + 1900);
494 gnc_basic_cell_set_value_internal (&cell->cell, buff);
496 *start_selection = 0;
499 if (!box->date_picker)
502 block_picker_signals (cell);
503 gnc_date_picker_set_date (box->date_picker,
506 box->date.tm_year + 1900);
507 unblock_picker_signals (cell);
513 gnc_date_cell_modify_verify (
BasicCell *_cell,
518 int *cursor_position,
519 int *start_selection,
523 PopBox *box = cell->cell.gui_private;
524 gboolean accept = FALSE;
526 if (box->in_date_select)
528 gnc_basic_cell_set_value (_cell, newval);
535 else if (change_len == 0)
551 uc = g_utf8_get_char (c);
553 if (!g_unichar_isdigit (uc) && (separator != uc))
559 c = g_utf8_next_char (c);
565 uc = g_utf8_get_char (c);
570 c = g_utf8_next_char (c);
584 gnc_basic_cell_set_value_internal (&cell->cell, newval);
585 gnc_parse_date (&(box->date), newval);
587 if (!box->date_picker)
590 block_picker_signals (cell);
591 gnc_date_picker_set_date (box->date_picker,
594 box->date.tm_year + 1900);
595 unblock_picker_signals (cell);
600 gnc_date_cell_realize (
BasicCell *bcell, gpointer data)
603 GncItemEdit *item_edit = gnucash_sheet_get_item_edit (sheet);
605 PopBox *box = cell->cell.gui_private;
609 box->item_edit = item_edit;
610 box->date_picker = gnc_item_edit_new_date_picker (box->item_edit);
611 g_object_ref_sink(box->date_picker);
614 cell->cell.gui_realize = NULL;
615 cell->cell.gui_move = gnc_date_cell_move;
616 cell->cell.enter_cell = gnc_date_cell_enter;
617 cell->cell.leave_cell = gnc_date_cell_leave;
623 PopBox *box = bcell->gui_private;
625 date_picker_disconnect_signals ((
DateCell *) bcell);
627 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
628 NULL, NULL, NULL, NULL, NULL);
630 box->calendar_popped = FALSE;
634 get_popup_height (GnomeCanvasItem *item,
639 GtkWidget *cal = GTK_WIDGET (GNC_DATE_PICKER (item)->calendar);
645 gtk_widget_size_request (cal, &req);
651 popup_set_focus (GnomeCanvasItem *item,
654 gtk_widget_grab_focus (GTK_WIDGET (GNC_DATE_PICKER (item)->calendar));
659 int *cursor_position,
660 int *start_selection,
664 PopBox *box = bcell->gui_private;
666 gnc_item_edit_set_popup (box->item_edit, GNOME_CANVAS_ITEM (box->date_picker),
667 get_popup_height, NULL, popup_set_focus,
670 block_picker_signals (cell);
671 gnc_date_picker_set_date (box->date_picker,
674 box->date.tm_year + 1900);
675 unblock_picker_signals (cell);
677 date_picker_connect_signals ((
DateCell *) bcell);
679 *start_selection = 0;
689 PopBox *box = bcell->gui_private;
691 date_picker_disconnect_signals ((
DateCell *) bcell);
693 gnc_item_edit_set_popup (box->item_edit, NULL, NULL,
694 NULL, NULL, NULL, NULL, NULL);
696 box->calendar_popped = FALSE;
699 gnc_date_cell_get_date ((
DateCell *)bcell, &ts);
700 gnc_date_cell_set_value_secs ((
DateCell *)bcell, ts.tv_sec);
704 gnc_date_cell_get_date_gdate (
DateCell *cell, GDate *date)
706 PopBox *box = cell->cell.gui_private;
711 gnc_parse_date (&(box->date), cell->cell.value);
715 box->date.tm_mon + 1,
716 box->date.tm_year + 1900);
722 PopBox *box = cell->cell.gui_private;
727 gnc_parse_date (&(box->date), cell->cell.value);
734 gnc_date_cell_set_value_internal (
BasicCell *_cell,
const char *str)
737 PopBox *box = cell->cell.gui_private;
740 gnc_parse_date (&(box->date), str);
744 box->date.tm_mon + 1,
745 box->date.tm_year + 1900);
747 gnc_basic_cell_set_value_internal (_cell, buff);
749 if (!box->date_picker)
752 block_picker_signals (cell);
753 gnc_date_picker_set_date (box->date_picker,
756 box->date.tm_year + 1900);
757 unblock_picker_signals (cell);
utility functions for the GnuCash UI
Use a 64-bit unsigned int timespec.
gchar dateSeparator(void)
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)
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
void gnc_tm_get_today_start(struct tm *tm)
size_t qof_print_date_dmy_buff(gchar *buff, size_t buflen, int day, int month, int year)
gboolean qof_scan_date(const char *buff, int *day, int *month, int *year)
time64 gnc_time(time64 *tbuf)
get the current local time
gboolean qof_book_uses_autoreadonly(const QofBook *book)