1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2021 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 //#include <time.h>
22 #include <stdlib.h> /* atoi, atof, atol */
23 #include <libintl.h>
24
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27
28 #include "gtk-dateentry.h"
29
30 #define MYDEBUG 0
31
32 #if MYDEBUG
33 #define DB(x) (x);
34 #else
35 #define DB(x);
36 #endif
37
38
39 enum {
40 CHANGED,
41 LAST_SIGNAL
42 };
43
44
45 enum {
46 PROPERTY_DATE = 5,
47 };
48
49
50 static guint dateentry_signals[LAST_SIGNAL] = {0,};
51
52
53 //G_DEFINE_TYPE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX)
54 G_DEFINE_TYPE_WITH_CODE(GtkDateEntry, gtk_date_entry, GTK_TYPE_BOX, G_ADD_PRIVATE (GtkDateEntry))
55
56
57
58 // todo:finish this
59 // this is to be able to seizure d or d/m or m/d in the gtkdateentry
60
61 /* order of these in the current locale */
62 static GDateDMY dmy_order[3] =
63 {
64 G_DATE_DAY, G_DATE_MONTH, G_DATE_YEAR
65 };
66
67 struct _GDateParseTokens {
68 gint num_ints;
69 gint n[3];
70 guint month;
71 };
72
73 typedef struct _GDateParseTokens GDateParseTokens;
74
75 #define NUM_LEN 10
76
77 static void gtk_date_entry_cb_calendar_today_mark(GtkWidget *calendar, GtkDateEntry *dateentry);
78
79 static void
hb_date_fill_parse_tokens(const gchar * str,GDateParseTokens * pt)80 hb_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
81 {
82 gchar num[4][NUM_LEN+1];
83 gint i;
84 const guchar *s;
85
86 //DB( g_print("\n[dateentry] fill parse token\n") );
87
88 /* We count 4, but store 3; so we can give an error
89 * if there are 4.
90 */
91 num[0][0] = num[1][0] = num[2][0] = num[3][0] = '\0';
92
93 s = (const guchar *) str;
94 pt->num_ints = 0;
95 while (*s && pt->num_ints < 4)
96 {
97
98 i = 0;
99 while (*s && g_ascii_isdigit (*s) && i < NUM_LEN)
100 {
101 num[pt->num_ints][i] = *s;
102 ++s;
103 ++i;
104 }
105
106 if (i > 0)
107 {
108 num[pt->num_ints][i] = '\0';
109 ++(pt->num_ints);
110 }
111
112 if (*s == '\0') break;
113
114 ++s;
115 }
116
117 pt->n[0] = pt->num_ints > 0 ? atoi (num[0]) : 0;
118 pt->n[1] = pt->num_ints > 1 ? atoi (num[1]) : 0;
119 pt->n[2] = pt->num_ints > 2 ? atoi (num[2]) : 0;
120
121 }
122
123
hb_date_parse_tokens(GDate * date,const gchar * str)124 static void hb_date_parse_tokens(GDate *date, const gchar *str)
125 {
126 GDateParseTokens pt;
127
128 hb_date_fill_parse_tokens(str, &pt);
129 DB( g_print(" -> parsetoken return %d values: %d %d %d\n", pt.num_ints, pt.n[0], pt.n[1], pt.n[2]) );
130
131 // initialize with today's date
132 g_date_set_time_t(date, time(NULL));
133
134 switch( pt.num_ints )
135 {
136 case 1:
137 DB( g_print(" -> seizured 1 number\n") );
138 if(g_date_valid_day(pt.n[0]))
139 g_date_set_day(date, pt.n[0]);
140 break;
141 case 2:
142 DB( g_print(" -> seizured 2 numbers\n") );
143 if( dmy_order[0] != G_DATE_YEAR )
144 {
145 if( dmy_order[0] == G_DATE_DAY )
146 {
147 if(g_date_valid_day(pt.n[0]))
148 g_date_set_day(date, pt.n[0]);
149 if(g_date_valid_month(pt.n[1]))
150 g_date_set_month(date, pt.n[1]);
151 }
152 else
153 {
154 if(g_date_valid_day(pt.n[1]))
155 g_date_set_day(date, pt.n[1]);
156 if(g_date_valid_month(pt.n[0]))
157 g_date_set_month(date, pt.n[0]);
158 }
159 }
160 break;
161 }
162 }
163
164
165 static void
update_text(GtkDateEntry * self)166 update_text(GtkDateEntry *self)
167 {
168 GtkDateEntryPrivate *priv = self->priv;
169 gchar label[256];
170
171 DB( g_print("\n[dateentry] update text\n") );
172
173 //%x : The preferred date representation for the current locale without the time.
174 g_date_strftime (label, 256 - 1, "%x", priv->date);
175 gtk_entry_set_text (GTK_ENTRY (priv->entry), label);
176 DB( g_print(" = %s\n", label) );
177 }
178
179
180 static void
eval_date(GtkDateEntry * self)181 eval_date(GtkDateEntry *self)
182 {
183 GtkDateEntryPrivate *priv = self->priv;
184
185 DB( g_print(" pre %d %d %d\n", g_date_get_day(priv->date), g_date_get_month(priv->date), g_date_get_year(priv->date)) );
186
187 g_date_clamp(priv->date, &priv->mindate, &priv->maxdate);
188 DB( g_print(" min %d %d %d\n", g_date_get_day(&priv->mindate), g_date_get_month(&priv->mindate), g_date_get_year(&priv->mindate)) );
189 DB( g_print(" max %d %d %d\n", g_date_get_day(&priv->maxdate), g_date_get_month(&priv->maxdate), g_date_get_year(&priv->maxdate)) );
190
191 update_text(self);
192
193 if(priv->lastdate != g_date_get_julian(priv->date))
194 {
195 DB( g_print(" **emit 'changed' signal**\n") );
196 g_signal_emit_by_name (self, "changed", NULL, NULL);
197 }
198
199 priv->lastdate = g_date_get_julian(priv->date);
200
201 DB( g_print(" post %d %d %d\n", g_date_get_day(priv->date), g_date_get_month(priv->date), g_date_get_year(priv->date)) );
202 }
203
204
205 static void
parse_date(GtkDateEntry * self)206 parse_date(GtkDateEntry *self)
207 {
208 GtkDateEntryPrivate *priv = self->priv;
209 const gchar *str;
210
211 DB( g_print("\n[dateentry] parse date\n") );
212
213 str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
214
215 //1) we parse the string according to the locale
216 g_date_set_parse (priv->date, str);
217 DB( g_print(" parsed '%s' %d %d %d\n", str, g_date_get_day(priv->date), g_date_get_month(priv->date), g_date_get_year(priv->date)) );
218
219 if(!g_date_valid(priv->date) || g_date_get_julian (priv->date) <= HB_MINDATE)
220 {
221 //2) give a try to tokens: day, day/month, month/day
222 hb_date_parse_tokens(priv->date, str);
223 DB( g_print(" tokened %d %d %d\n", g_date_get_day(priv->date), g_date_get_month(priv->date), g_date_get_year(priv->date)) );
224 }
225
226 //3) at last if date still invalid, put today's dateentry_signals
227 // we should consider just warn the user here
228 if(!g_date_valid(priv->date))
229 {
230 g_date_set_time_t(priv->date, time(NULL));
231 }
232 eval_date(self);
233 }
234
235
236 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
237
238
239 static void
gtk_date_entry_set_calendar(GtkWidget * widget,GtkDateEntry * dateentry)240 gtk_date_entry_set_calendar (GtkWidget * widget, GtkDateEntry * dateentry)
241 {
242 GtkDateEntryPrivate *priv = dateentry->priv;
243 guint day, month;
244
245 DB( g_print("\n[dateentry] set calendar\n") );
246
247 /* GtkCalendar expects month to be in 0-11 range (inclusive) */
248 day = g_date_get_day (priv->date);
249 month = g_date_get_month (priv->date) - 1;
250
251 g_signal_handler_block(priv->calendar, priv->hid_dayselect);
252
253 gtk_calendar_select_month (GTK_CALENDAR (priv->calendar),
254 month,
255 g_date_get_year (priv->date));
256 gtk_calendar_select_day (GTK_CALENDAR (priv->calendar), day);
257
258 g_signal_handler_unblock(priv->calendar, priv->hid_dayselect);
259 }
260
261
262
263
264 static void
gtk_date_entry_cb_today_clicked(GtkWidget * widget,GtkDateEntry * dateentry)265 gtk_date_entry_cb_today_clicked (GtkWidget * widget, GtkDateEntry * dateentry)
266 {
267 GtkDateEntryPrivate *priv = dateentry->priv;
268
269 DB( g_print("\n[dateentry] today_clicked\n") );
270
271 //revert to now (today)
272 g_date_set_time_t(priv->date, time(NULL));
273 eval_date(dateentry);
274
275 gtk_date_entry_set_calendar(widget, dateentry);
276
277 gtk_widget_hide (priv->popover);
278 }
279
280
281 static void
gtk_date_entry_cb_calendar_day_selected(GtkWidget * calendar,GtkDateEntry * dateentry)282 gtk_date_entry_cb_calendar_day_selected(GtkWidget * calendar, GtkDateEntry * dateentry)
283 {
284 GtkDateEntryPrivate *priv = dateentry->priv;
285 guint year, month, day;
286
287 DB( g_print("\n[dateentry] calendar_day_selected\n") );
288
289 gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
290 g_date_set_dmy (priv->date, day, month + 1, year);
291 eval_date(dateentry);
292 }
293
294
295 static gint
gtk_date_entry_cb_calendar_day_select_double_click(GtkWidget * calendar,gpointer user_data)296 gtk_date_entry_cb_calendar_day_select_double_click(GtkWidget * calendar, gpointer user_data)
297 {
298 GtkDateEntry *dateentry = user_data;
299 GtkDateEntryPrivate *priv = dateentry->priv;
300
301 DB( g_print("\n[dateentry] calendar_day_select_double_click\n") );
302
303 gtk_widget_hide (priv->popover);
304
305 return FALSE;
306 }
307
308
309 static void
gtk_date_entry_cb_calendar_today_mark(GtkWidget * calendar,GtkDateEntry * dateentry)310 gtk_date_entry_cb_calendar_today_mark(GtkWidget *calendar, GtkDateEntry *dateentry)
311 {
312 GtkDateEntryPrivate *priv = dateentry->priv;
313 guint year, month, day;
314
315 DB( g_print("\n[dateentry] cb_calendar_mark_day\n") );
316
317 gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
318
319 //maybe 1828914
320 gtk_calendar_clear_marks(GTK_CALENDAR(priv->calendar));
321 if( year == g_date_get_year (&priv->nowdate) && month == (g_date_get_month (&priv->nowdate)-1) )
322 gtk_calendar_mark_day(GTK_CALENDAR(priv->calendar), g_date_get_day (&priv->nowdate));
323
324 }
325
326
327 static void
gtk_date_entry_cb_calendar_monthyear(GtkWidget * calendar,GtkDateEntry * dateentry)328 gtk_date_entry_cb_calendar_monthyear(GtkWidget *calendar, GtkDateEntry *dateentry)
329 {
330 GtkDateEntryPrivate *priv = dateentry->priv;
331 guint year, month, day;
332
333 DB( g_print("\n[dateentry] cb_calendar_monthyear\n") );
334
335 gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), &year, &month, &day);
336 if( year < 1900)
337 g_object_set(calendar, "year", 1900, NULL);
338
339 if( year > 2200)
340 g_object_set(calendar, "year", 2200, NULL);
341
342 gtk_date_entry_cb_calendar_today_mark(calendar, dateentry);
343 }
344
345
346 static gint
gtk_date_entry_cb_entry_key_pressed(GtkWidget * widget,GdkEventKey * event,gpointer user_data)347 gtk_date_entry_cb_entry_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
348 {
349 GtkDateEntry *dateentry = user_data;
350 GtkDateEntryPrivate *priv = dateentry->priv;
351 guint action;
352
353 DB( g_print("\n[dateentry] entry key pressed") );
354
355
356 DB( g_print(" state: %s %s\n", (event->state & GDK_SHIFT_MASK) ? "shift" : "", (event->state & GDK_CONTROL_MASK) ? "ctrl" : "" ) );
357 DB( g_print(" kyval: %s %s\n", (event->keyval == GDK_KEY_Up) ? "up" : "", (event->keyval == GDK_KEY_Down) ? "down" : "") );
358
359 if( (event->type != GDK_KEY_PRESS) )
360 return FALSE;
361
362 //#1873643 preserve Up/Down (+ctrl) natural GTK focus change
363 if( (event->state & GDK_CONTROL_MASK) && !(event->state & GDK_SHIFT_MASK) )
364 return FALSE;
365
366 if( (event->keyval == GDK_KEY_Up) || (event->keyval == GDK_KEY_Down) )
367 {
368 //let's bitwise key to an action-id
369 action = 0;
370 action |= (event->state & GDK_SHIFT_MASK) ? 2 : 0;
371 action |= (event->state & GDK_CONTROL_MASK) ? 4 : 0;
372 action |= (event->keyval == GDK_KEY_Down) ? 1 : 0;
373
374 DB( g_print(" action: %d\n", action) );
375
376 switch(action)
377 {
378 case 0: g_date_add_days (priv->date, 1); break;
379 case 1: g_date_subtract_days (priv->date, 1); break;
380 case 2: g_date_add_months (priv->date, 1); break;
381 case 3: g_date_subtract_months (priv->date, 1); break;
382 case 6: g_date_add_years (priv->date, 1); break;
383 case 7: g_date_subtract_years (priv->date, 1); break;
384 }
385
386 eval_date(dateentry);
387
388 //stop handlers
389 return TRUE;
390 }
391 //propagate
392 return FALSE;
393 }
394
395
396 static void
gtk_date_entry_cb_entry_activate(GtkWidget * gtkentry,gpointer user_data)397 gtk_date_entry_cb_entry_activate(GtkWidget *gtkentry, gpointer user_data)
398 {
399 GtkDateEntry *dateentry = user_data;
400
401 DB( g_print("\n[dateentry] entry_activate\n") );
402
403 parse_date(dateentry);
404 eval_date(dateentry);
405 }
406
407
408 static gboolean
gtk_date_entry_cb_entry_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)409 gtk_date_entry_cb_entry_focus_out(GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
410 {
411 GtkDateEntry *dateentry = user_data;
412
413 DB( g_print("\n[dateentry] entry focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry))) );
414
415 parse_date(dateentry);
416 eval_date(dateentry);
417 return FALSE;
418 }
419
420
421 static void
gtk_date_entry_cb_button_clicked(GtkWidget * widget,GtkDateEntry * dateentry)422 gtk_date_entry_cb_button_clicked (GtkWidget * widget, GtkDateEntry * dateentry)
423 {
424 GtkDateEntryPrivate *priv = dateentry->priv;
425
426 DB( g_print("\n[dateentry] button_clicked\n") );
427
428 gtk_date_entry_set_calendar(widget, dateentry);
429
430 gtk_popover_set_relative_to (GTK_POPOVER (priv->popover), GTK_WIDGET (priv->entry));
431 //gtk_widget_get_clip(priv->arrow, &rect);
432 //gtk_popover_set_pointing_to (GTK_POPOVER (priv->popover), &rect);
433
434 gtk_date_entry_cb_calendar_today_mark(widget, dateentry);
435
436 gtk_widget_show_all (priv->popover);
437 }
438
439
440 static void
gtk_date_entry_destroy(GtkWidget * object)441 gtk_date_entry_destroy (GtkWidget *object)
442 {
443 GtkDateEntry *dateentry = GTK_DATE_ENTRY (object);
444 GtkDateEntryPrivate *priv = dateentry->priv;
445
446 g_return_if_fail(object != NULL);
447 g_return_if_fail(GTK_IS_DATE_ENTRY(object));
448
449 DB( g_print("\n[dateentry] destroy\n") );
450
451 DB( g_print(" free gtkentry: %p\n", priv->entry) );
452 DB( g_print(" free arrow: %p\n", priv->button) );
453
454 DB( g_print(" free dateentry: %p\n", dateentry) );
455
456 if(priv->date)
457 g_date_free(priv->date);
458 priv->date = NULL;
459
460 GTK_WIDGET_CLASS (gtk_date_entry_parent_class)->destroy (object);
461 }
462
463
464
465 static void
gtk_date_entry_dispose(GObject * gobject)466 gtk_date_entry_dispose (GObject *gobject)
467 {
468 //GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
469
470 DB( g_print("\n[dateentry] dispose\n") );
471
472
473 //g_clear_object (&self->priv->an_object);
474
475 G_OBJECT_CLASS (gtk_date_entry_parent_class)->dispose (gobject);
476 }
477
478
479
480
481 static void
gtk_date_entry_finalize(GObject * gobject)482 gtk_date_entry_finalize (GObject *gobject)
483 {
484 //GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
485
486 DB( g_print("\n[dateentry] finalize\n") );
487
488
489 //g_date_free(self->date);
490 //g_free (self->priv->a_string);
491
492 /* Always chain up to the parent class; as with dispose(), finalize()
493 * is guaranteed to exist on the parent's class virtual function table
494 */
495 G_OBJECT_CLASS(gtk_date_entry_parent_class)->finalize (gobject);
496 }
497
498
499
500 static void
gtk_date_entry_class_init(GtkDateEntryClass * class)501 gtk_date_entry_class_init (GtkDateEntryClass *class)
502 {
503 GObjectClass *object_class;
504 GtkWidgetClass *widget_class;
505
506 object_class = G_OBJECT_CLASS (class);
507 widget_class = GTK_WIDGET_CLASS (class);
508
509 DB( g_print("\n[dateentry] class_init\n") );
510
511 //object_class->constructor = gtk_date_entry_constructor;
512 //object_class->set_property = gtk_date_entry_set_property;
513 //object_class->get_property = gtk_date_entry_get_property;
514 object_class->dispose = gtk_date_entry_dispose;
515 object_class->finalize = gtk_date_entry_finalize;
516
517 widget_class->destroy = gtk_date_entry_destroy;
518
519 dateentry_signals[CHANGED] =
520 g_signal_new ("changed",
521 G_TYPE_FROM_CLASS (class),
522 G_SIGNAL_RUN_LAST,
523 G_STRUCT_OFFSET (GtkDateEntryClass, changed),
524 NULL, NULL,
525 g_cclosure_marshal_VOID__VOID,
526 G_TYPE_NONE, 0);
527
528 //g_type_class_add_private (object_class, sizeof (GtkDateEntryPrivate));
529
530 }
531
532 static void
gtk_date_entry_init(GtkDateEntry * dateentry)533 gtk_date_entry_init (GtkDateEntry *dateentry)
534 {
535 GtkDateEntryPrivate *priv;
536 GtkWidget *vbox;
537
538 DB( g_print("\n[dateentry] init\n") );
539
540 /* yes, also priv, need to keep the code readable */
541 /*dateentry->priv = G_TYPE_INSTANCE_GET_PRIVATE (dateentry,
542 GTK_TYPE_DATE_ENTRY,
543 GtkDateEntryPrivate);*/
544
545 dateentry->priv = gtk_date_entry_get_instance_private(dateentry);
546
547 priv = dateentry->priv;
548
549 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry)), GTK_STYLE_CLASS_LINKED);
550
551 priv->entry = gtk_entry_new ();
552 //todo: see if really useful
553 gtk_entry_set_width_chars(GTK_ENTRY(priv->entry), 16);
554 gtk_entry_set_max_width_chars(GTK_ENTRY(priv->entry), 16);
555 gtk_box_pack_start (GTK_BOX (dateentry), priv->entry, TRUE, TRUE, 0);
556
557 priv->button = gtk_button_new ();
558 priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
559 gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
560 gtk_box_pack_end (GTK_BOX (dateentry), priv->button, FALSE, FALSE, 0);
561
562 priv->popover = gtk_popover_new (priv->button);
563 gtk_popover_set_position(GTK_POPOVER(priv->popover), GTK_POS_BOTTOM);
564 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
565 gtk_container_add (GTK_CONTAINER (priv->popover), vbox);
566
567 gtk_widget_set_margin_start (vbox, 10);
568 gtk_widget_set_margin_end (vbox, 10);
569 gtk_widget_set_margin_top (vbox, 10);
570 gtk_widget_set_margin_bottom (vbox, 10);
571
572 priv->calendar = gtk_calendar_new ();
573 gtk_box_pack_start(GTK_BOX(vbox), priv->calendar, FALSE, FALSE, 0);
574
575 priv->BT_today = gtk_button_new_with_mnemonic ( gettext("_Today"));
576 gtk_box_pack_start(GTK_BOX(vbox), priv->BT_today, FALSE, FALSE, 0);
577
578 gtk_widget_show_all (GTK_WIDGET(dateentry));
579
580 /* initialize datas */
581 priv->date = g_date_new();
582 g_date_set_time_t(priv->date, time(NULL));
583 g_date_set_time_t(&priv->nowdate, time(NULL));
584 g_date_set_dmy(&priv->mindate, 1, 1, 1900); //693596
585 g_date_set_dmy(&priv->maxdate, 31, 12, 2200); //803533
586 update_text(dateentry);
587
588
589 g_signal_connect (priv->entry, "key-press-event",
590 G_CALLBACK (gtk_date_entry_cb_entry_key_pressed), dateentry);
591
592 g_signal_connect_after (priv->entry, "focus-out-event",
593 G_CALLBACK (gtk_date_entry_cb_entry_focus_out), dateentry);
594
595 g_signal_connect (priv->entry, "activate",
596 G_CALLBACK (gtk_date_entry_cb_entry_activate), dateentry);
597
598
599 g_signal_connect (priv->button, "clicked",
600 G_CALLBACK (gtk_date_entry_cb_button_clicked), dateentry);
601
602
603 g_signal_connect (priv->calendar, "prev-year",
604 G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
605 g_signal_connect (priv->calendar, "next-year",
606 G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
607 g_signal_connect (priv->calendar, "prev-month",
608 G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
609 g_signal_connect (priv->calendar, "next-month",
610 G_CALLBACK (gtk_date_entry_cb_calendar_monthyear), dateentry);
611
612 priv->hid_dayselect = g_signal_connect (priv->calendar, "day-selected",
613 G_CALLBACK (gtk_date_entry_cb_calendar_day_selected), dateentry);
614
615 g_signal_connect (priv->calendar, "day-selected-double-click",
616 G_CALLBACK (gtk_date_entry_cb_calendar_day_select_double_click), dateentry);
617
618 g_signal_connect (priv->BT_today, "clicked",
619 G_CALLBACK (gtk_date_entry_cb_today_clicked), dateentry);
620
621 }
622
623
624 GtkWidget *
gtk_date_entry_new(GtkWidget * label)625 gtk_date_entry_new (GtkWidget *label)
626 {
627 GtkDateEntry *dateentry;
628
629 DB( g_print("\n[dateentry] new\n") );
630
631 dateentry = g_object_new (GTK_TYPE_DATE_ENTRY, NULL);
632
633 if(dateentry)
634 {
635 GtkDateEntryPrivate *priv = dateentry->priv;
636
637 if(label)
638 gtk_label_set_mnemonic_widget (GTK_LABEL(label), priv->entry);
639 }
640 return GTK_WIDGET(dateentry);
641 }
642
643
644 /*
645 **
646 */
647 void
gtk_date_entry_set_mindate(GtkDateEntry * dateentry,guint32 julian_days)648 gtk_date_entry_set_mindate(GtkDateEntry *dateentry, guint32 julian_days)
649 {
650 GtkDateEntryPrivate *priv = dateentry->priv;
651
652 DB( g_print("\n[dateentry] set mindate\n") );
653
654 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
655
656 if(g_date_valid_julian(julian_days))
657 {
658 g_date_set_julian (&priv->mindate, julian_days);
659 }
660 }
661
662
663 /*
664 **
665 */
666 void
gtk_date_entry_set_maxdate(GtkDateEntry * dateentry,guint32 julian_days)667 gtk_date_entry_set_maxdate(GtkDateEntry *dateentry, guint32 julian_days)
668 {
669 GtkDateEntryPrivate *priv = dateentry->priv;
670
671 DB( g_print("\n[dateentry] set maxdate\n") );
672
673 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
674
675 if(g_date_valid_julian(julian_days))
676 {
677 g_date_set_julian (&priv->maxdate, julian_days);
678 }
679 }
680
681
682 /*
683 **
684 */
685 void
gtk_date_entry_set_date(GtkDateEntry * dateentry,guint32 julian_days)686 gtk_date_entry_set_date(GtkDateEntry *dateentry, guint32 julian_days)
687 {
688 GtkDateEntryPrivate *priv = dateentry->priv;
689
690 DB( g_print("\n[dateentry] set date\n") );
691
692 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry));
693
694 if(g_date_valid_julian(julian_days))
695 {
696 g_date_set_julian (priv->date, julian_days);
697 }
698 else
699 {
700 g_date_set_time_t(priv->date, time(NULL));
701 }
702 eval_date(dateentry);
703 }
704
705
706 /*
707 **
708 */
709 guint32
gtk_date_entry_get_date(GtkDateEntry * dateentry)710 gtk_date_entry_get_date(GtkDateEntry *dateentry)
711 {
712 GtkDateEntryPrivate *priv = dateentry->priv;
713
714 DB( g_print("\n[dateentry] get date\n") );
715
716 g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
717
718 return(g_date_get_julian(priv->date));
719 }
720
721
722 GDateWeekday
gtk_date_entry_get_weekday(GtkDateEntry * dateentry)723 gtk_date_entry_get_weekday(GtkDateEntry *dateentry)
724 {
725 GtkDateEntryPrivate *priv = dateentry->priv;
726
727 DB( g_print("\n[dateentry] get weekday\n") );
728
729 g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry), 0);
730
731 return(g_date_get_weekday(priv->date));
732 }
733