Using the GnomeDateEdit widget

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:

In the top right a text entry box shows the date 20/03/08.  There is a button labeled with a downward-pointing arrow to its right, and below is a calendar showing all the days of March 2008, with the 20th highlighted, and controls at the top for changing the month or year.

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:

There are four controls shown in a row.  First is a text entry box containing a text cursor and the date 23/03/08.  Next to that is a button labeled ‘Calendar’, with a downward-pointing arrow on the right hand side.  Next is a text box containing the time 11:07.  Finally, there is a button which looks like a combo-box popup button, which is labeled with the time 07:00.

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:

There is a text entry box for entering the date, and a button labeled ‘calendar’ next to it.  To the right of them is a text entry box containing the time 11:07.  To the right of that box, where the time popup menu button would normally be, there is a popup menu containing entries for various times (each hour from 07:00 to 19:00), each of which has an arrow next to it indicating that it leads to a submenu.  The item for 11am is selected, and a submenu is popped up next to it, containing items for the four times 11:00, 11:15, 11:30, and 11:45.  The third item in the submenu is currently selected.

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.

< Meanwood Farm in the snow | Lua bug with −0 >

Miniblog

(nuggets of inanity)

Tuesday Apr 24th 2007, 16:54 »
Just took the annual web design survey that AListApart do. I don't realy consider myself to be a web designer, but I have been doing a lot of HTML and CSS lately.
Monday Apr 23rd 2007, 18:23 »
Strange, there appears to be a bare-knuckle boxing match going on in the field outside my flat. Wish they wouldn't make so much noise about it.
Thursday Mar 1st 2007, 18:47 »
“In its written form, Hebrew has no vowels, making it the ideal language for texting.”
—Said in jest on some Radio 4 programme just now.

Archive: 2007 · 2006 · 2005 · 2004
Feed