Further GTK+ date/time picker refinement and bugfixes.

This commit is contained in:
Pietro Gagliardi 2016-05-04 21:33:32 -04:00
parent 8b7d661405
commit f0dc52d1dc
3 changed files with 84 additions and 27 deletions

View File

@ -8,3 +8,5 @@
#include <langinfo.h> #include <langinfo.h>
extern GtkWidget *newDTP(void); extern GtkWidget *newDTP(void);
extern GtkWidget *newDP(void);
extern GtkWidget *newTP(void);

View File

@ -18,6 +18,9 @@ struct dateTimePickerWidget {
gulong toggledSignal; gulong toggledSignal;
gboolean hasTime;
gboolean hasDate;
GtkWidget *window; GtkWidget *window;
GtkWidget *box; GtkWidget *box;
GtkWidget *calendar; GtkWidget *calendar;
@ -45,32 +48,42 @@ static int realSpinValue(GtkSpinButton *spinButton)
return (int) gtk_adjustment_get_value(adj); return (int) gtk_adjustment_get_value(adj);
} }
// TODO switch to GDateTime? static GDateTime *selected(dateTimePickerWidget *d)
{
// choose a day for which all times are likely to be valid for the default date in case we're only dealing with time
guint year = 1970, month = 1, day = 1;
guint hour = 0, minute = 0, second = 0;
if (d->hasDate)
gtk_calendar_get_date(GTK_CALENDAR(d->calendar), &year, &month, &day);
if (d->hasTime) {
hour = realSpinValue(GTK_SPIN_BUTTON(d->hours));
if (realSpinValue(GTK_SPIN_BUTTON(d->ampm)) != 0)
hour += 12;
minute = realSpinValue(GTK_SPIN_BUTTON(d->minutes));
second = realSpinValue(GTK_SPIN_BUTTON(d->seconds));
}
return g_date_time_new_local(year, month, day, hour, minute, second);
}
static void setLabel(dateTimePickerWidget *d) static void setLabel(dateTimePickerWidget *d)
{ {
guint year, month, day; GDateTime *dt;
struct tm tm; const char *fmt;
time_t tt; char *msg;
gchar *str;
gtk_calendar_get_date(GTK_CALENDAR(d->calendar), &year, &month, &day); dt = selected(d);
tm.tm_hour = realSpinValue(GTK_SPIN_BUTTON(d->hours)); // TODO switch to D_FMT + " " + T_FMT?
if (realSpinValue(GTK_SPIN_BUTTON(d->ampm)) != 0) if (d->hasDate && d->hasTime)
tm.tm_hour += 12; fmt = nl_langinfo(D_T_FMT);
tm.tm_min = realSpinValue(GTK_SPIN_BUTTON(d->minutes)); else if (d->hasDate)
tm.tm_sec = realSpinValue(GTK_SPIN_BUTTON(d->seconds)); fmt = nl_langinfo(D_FMT);
tm.tm_mon = month; else
tm.tm_mday = day; fmt = nl_langinfo(T_FMT);
tm.tm_year = year - 1900; msg = g_date_time_format(dt, fmt);
tm.tm_isdst = -1; // not available gtk_button_set_label(GTK_BUTTON(d), msg);
// fill in the missing fields g_free(msg);
tt = mktime(&tm); g_date_time_unref(dt);
tm = *localtime(&tt);
// and strip the newline
str = g_strdup(asctime(&tm));
str[strlen(str) - 1] = '\0';
gtk_button_set_label(GTK_BUTTON(d), str);
g_free(str);
} }
static void dateTimeChanged(dateTimePickerWidget *d) static void dateTimeChanged(dateTimePickerWidget *d)
@ -279,6 +292,7 @@ static gboolean zeroPadSpinbox(GtkSpinButton *sb, gpointer data)
return TRUE; return TRUE;
} }
// this is really hacky but we can't use GtkCombobox here :(
static gint ampmSpinboxInput(GtkSpinButton *sb, gpointer ptr, gpointer data) static gint ampmSpinboxInput(GtkSpinButton *sb, gpointer ptr, gpointer data)
{ {
double *out = (double *) ptr; double *out = (double *) ptr;
@ -286,13 +300,14 @@ static gint ampmSpinboxInput(GtkSpinButton *sb, gpointer ptr, gpointer data)
char firstAM, firstPM; char firstAM, firstPM;
text = gtk_entry_get_text(GTK_ENTRY(sb)); text = gtk_entry_get_text(GTK_ENTRY(sb));
firstAM = nl_langinfo(AM_STR)[0]; // TODO don't use ASCII here for case insensitivity
firstPM = nl_langinfo(PM_STR)[0]; firstAM = g_ascii_tolower(nl_langinfo(AM_STR)[0]);
firstPM = g_ascii_tolower(nl_langinfo(PM_STR)[0]);
for (; *text != '\0'; text++) for (; *text != '\0'; text++)
if (*text == firstAM) { if (g_ascii_tolower(*text) == firstAM) {
*out = 0; *out = 0;
return TRUE; return TRUE;
} else if (*text == firstPM) { } else if (g_ascii_tolower(*text) == firstPM) {
*out = 1; *out = 1;
return TRUE; return TRUE;
} }
@ -341,8 +356,21 @@ static void dateChanged(GtkCalendar *c, gpointer data)
dateTimeChanged(d); dateTimeChanged(d);
} }
static void setDateOnly(dateTimePickerWidget *d)
{
d->hasTime = FALSE;
gtk_container_remove(GTK_CONTAINER(d->box), d->timebox);
}
static void setTimeOnly(dateTimePickerWidget *d)
{
d->hasDate = FALSE;
gtk_container_remove(GTK_CONTAINER(d->box), d->calendar);
}
static void dateTimePickerWidget_init(dateTimePickerWidget *d) static void dateTimePickerWidget_init(dateTimePickerWidget *d)
{ {
// TODO give a more pronounced shadow
d->window = gtk_window_new(GTK_WINDOW_POPUP); d->window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_window_set_resizable(GTK_WINDOW(d->window), FALSE); gtk_window_set_resizable(GTK_WINDOW(d->window), FALSE);
gtk_window_set_attached_to(GTK_WINDOW(d->window), GTK_WIDGET(d)); gtk_window_set_attached_to(GTK_WINDOW(d->window), GTK_WIDGET(d));
@ -405,6 +433,9 @@ static void dateTimePickerWidget_init(dateTimePickerWidget *d)
d->keyboard = NULL; d->keyboard = NULL;
d->mouse = NULL; d->mouse = NULL;
d->hasTime = TRUE;
d->hasDate = TRUE;
// TODO set current time to now // TODO set current time to now
} }
@ -433,3 +464,23 @@ GtkWidget *newDTP(void)
setLabel(dateTimePickerWidget(w)); setLabel(dateTimePickerWidget(w));
return w; return w;
} }
GtkWidget *newDP(void)
{
GtkWidget *w;
w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL));
setDateOnly(dateTimePickerWidget(w));
setLabel(dateTimePickerWidget(w));
return w;
}
GtkWidget *newTP(void)
{
GtkWidget *w;
w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL));
setTimeOnly(dateTimePickerWidget(w));
setLabel(dateTimePickerWidget(w));
return w;
}

View File

@ -18,6 +18,10 @@ int main(void)
gtk_container_add(GTK_CONTAINER(mainwin), box); gtk_container_add(GTK_CONTAINER(mainwin), box);
button = newDTP(); button = newDTP();
gtk_container_add(GTK_CONTAINER(box), button); gtk_container_add(GTK_CONTAINER(box), button);
button = newDP();
gtk_container_add(GTK_CONTAINER(box), button);
button = newTP();
gtk_container_add(GTK_CONTAINER(box), button);
gtk_container_add(GTK_CONTAINER(box), gtk_entry_new()); gtk_container_add(GTK_CONTAINER(box), gtk_entry_new());
gtk_widget_show_all(mainwin); gtk_widget_show_all(mainwin);