In a small GUI application I'm writing I wanted to provide an easy way of selecting dates, without having to type all the numbers in by hand. Most of the dates will be in the near past, so a popup calendar widget seems like a good solution. It turns out that although there's a calendar widget in Gtk+, there isn't a widget which would pop it up on demand. The best I've been able to find is the GnomeDateEdit widget in the mostly deprecated libgnomeui.
This is what it looks like if you turn off the time part of the widget, and click on the little arrow next to the text box to pop up the calendar:

You can tell the constructor
(gnome_date_edit_new)
whether you want a widget for selecting only dates or dates and times.
With time selection enabled you get an extra text entry box and popup menu:

The menu gives you a selection of times in a preset range, which you can adjust if you want. By default it looks like this:

I don't think this is a particularly nice design for a date or time selecting widget, but it'll do for my purposes. I thought I'd write a few notes about it, for my own reference more than anything else.
Bug when hiding time widgets
Unfortunately there's an annoying bug which you have to work around to
get a widget which only includes the date part. GnomeDateEdit creates
both parts in either case, and just doesn't ‘show’ the time widgets.
When you call
gtk_widget_show_all
on your window, it recursively displays everything that's not explicitly
hidden, including the time widgets you didn't want. Widget classes are
meant to avoid that, but in this case you have to do it yourself, like
this:
GtkWidget *datesel = gnome_date_edit_new(0, FALSE, TRUE);
gtk_widget_show(datesel);
gtk_widget_set_no_show_all(datesel, TRUE);
Apparently I'm not the first to notice this problem.
Someone else
had the same problem with the Perl Gtk+ bindings, and it's particularly
confusing if you're using Glade, which always uses explicit calls to
gtk_widget_show,
whereas any human author soon gives up bothering with that.
Note that using the alternative
gnome_date_edit_new_flags constructor
will not help with this problem.
Getting and setting date
The final thing you need to be able to do to use this thing is get and
set the date that the widget displays, and possibly to detect changes in
the date. There are methods for getting and setting the date, but
unfortunately, this being C, they work through a time_t
value. You have to be particularly careful to avoid ending up with the
date before the one you selected because of a DST offset throwing it out
of whack (at least I'm guessing that was what was going on, I didn't really
want to investigate so I just started adding twelve hours to the time
returned).
Anyway, here are some snippets of code that might help:
/* Set date (and time if shown). */ gnome_date_edit_set_time((GnomeDateEdit *) datesel, 1206274319); static void handle_date_changed (GnomeDateEdit *widget, gpointer user_data) { time_t new_time; struct tm *t; new_time = gnome_date_edit_get_time(widget); t = gmtime(&new_time); printf("new date: %04d-%02d-%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday); (void) user_data; /* unused */ } /* Detect when new date set on popup calendar. */ g_signal_connect(datesel, "date-changed", G_CALLBACK(handle_date_changed), 0);
The date-changed signal gets sent both when you open the
calendar and when you've selected a new date from it. It doesn't get sent
when the time is changed in the time popup menu, and the other signal,
time-changed, doesn't get sent when the date is changed.
Neither of them is sent when the date or time is altered manually in the
text entry boxes, although such changes do affect the result you get
when you query the time.