'smart qotes' now will replace '<', '>' and '&' inside 'pre' and 'code' tags
[k8lowj.git] / src / datesel.c
blobfbe9183c8ed98b07214646de07fdb283b0d45004
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
5 */
7 #include "gtk-all.h"
8 #include "util-gtk.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "liblj/livejournal.h"
13 #include "datesel.h"
15 struct _DateSel {
16 GtkButton parent;
17 GtkWidget *label;
19 guint timeout_id;
21 struct tm date;
22 gboolean backdated;
25 static void datesel_init(DateSel *ds);
26 static void datesel_class_init(GtkButtonClass *class);
27 static void datesel_dialog_run(DateSel *ds);
29 static void timeout_enable(DateSel *ds, gboolean usenow);
31 /* gtk stuff */
32 GObjectClass *parent_class = NULL;
34 GType
35 datesel_get_type(void) {
36 static GType ds_type = 0;
37 if (!ds_type) {
38 static const GTypeInfo ds_info = {
39 sizeof(GtkButtonClass),
40 NULL,
41 NULL,
42 (GClassInitFunc)datesel_class_init,
43 NULL,
44 NULL,
45 sizeof(DateSel),
47 (GInstanceInitFunc) datesel_init,
49 ds_type = g_type_register_static(GTK_TYPE_BUTTON, "DateSel",
50 &ds_info, 0);
52 return ds_type;
55 static void
56 datesel_finalize(GObject *obj) {
57 timeout_enable(DATESEL(obj), FALSE);
58 G_OBJECT_CLASS(parent_class)->finalize(obj);
61 static void
62 datesel_class_init(GtkButtonClass *class) {
63 GObjectClass *oclass = G_OBJECT_CLASS(class);
64 parent_class = g_type_class_peek_parent(class);
65 oclass->finalize = datesel_finalize;
68 static void
69 update_display(DateSel *ds) {
70 char *ljdate = lj_tm_to_ljdate_noseconds(&ds->date);
71 gtk_label_set_text(GTK_LABEL(ds->label), ljdate);
72 g_free(ljdate);
75 static gboolean
76 timeout_cb(DateSel *ds) {
77 time_t curtime_time_t = time(NULL);
78 struct tm *curtime = localtime(&curtime_time_t);
79 ds->date = *curtime;
80 update_display(ds);
81 return TRUE;
84 static void
85 timeout_enable(DateSel *ds, gboolean usenow) {
86 if (usenow && !ds->timeout_id) {
87 timeout_cb(ds);
88 ds->timeout_id = g_timeout_add(10*1000, /* every 10 sec. */
89 (GSourceFunc)timeout_cb, ds);
90 } else if (!usenow && ds->timeout_id) {
91 g_source_remove(ds->timeout_id);
92 ds->timeout_id = 0;
96 static void
97 datesel_init(DateSel *ds) {
98 ds->label = gtk_label_new("meow");
99 gtk_container_add(GTK_CONTAINER(ds), ds->label);
100 gtk_button_set_relief(GTK_BUTTON(ds), GTK_RELIEF_NONE);
101 g_signal_connect(G_OBJECT(ds), "clicked",
102 G_CALLBACK(datesel_dialog_run), NULL);
104 ds->timeout_id = 0;
105 timeout_enable(ds, TRUE);
108 GtkWidget*
109 datesel_new(void) {
110 DateSel *ds = DATESEL(g_object_new(datesel_get_type(), NULL));
112 return GTK_WIDGET(ds);
115 void
116 datesel_get_tm(DateSel *ds, struct tm *ptm) {
117 if (ds->timeout_id)
118 memset(ptm, 0, sizeof(struct tm));
119 else
120 *ptm = ds->date;
123 void
124 datesel_set_tm(DateSel *ds, struct tm *ptm) {
125 if (ptm && ptm->tm_year) {
126 ds->date = *ptm;
127 timeout_enable(ds, FALSE);
128 } else {
129 timeout_enable(ds, TRUE);
131 update_display(ds);
134 gboolean
135 datesel_get_backdated(DateSel *ds) {
136 return ds->backdated;
139 void
140 datesel_set_backdated(DateSel *ds, gboolean backdated) {
141 ds->backdated = backdated;
144 static void
145 usenow_cb(GtkToggleButton *cb, GtkWidget *box) {
146 if (gtk_toggle_button_get_active(cb))
147 gtk_widget_hide(box);
148 else
149 gtk_widget_show(box);
152 static void
153 backdated_cb(GtkToggleButton *cb, DateSel *ds) {
154 ds->backdated = gtk_toggle_button_get_active(cb);
157 static gboolean
158 minute_output_cb(GtkSpinButton *s) {
159 char buf[5];
160 g_snprintf(buf, 5, "%02d", (int)gtk_spin_button_get_value(s));
161 if (strcmp(buf, gtk_entry_get_text(GTK_ENTRY(s))) != 0)
162 gtk_entry_set_text(GTK_ENTRY(s), buf);
163 return TRUE;
166 static void
167 datesel_dialog_run(DateSel *ds) {
168 GtkWidget *dlg, *vbox;
169 GtkWidget *datebox, *cal;
170 GtkAdjustment *houradj, *minadj;
171 GtkWidget *hbox, *label, *hourspin, *minspin;
172 GtkWidget *check, *backdated;
173 guint year, month, day;
175 dlg = gtk_dialog_new_with_buttons(_("Select Date"),
176 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ds))),
177 GTK_DIALOG_MODAL,
178 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
179 NULL);
180 gtk_window_set_resizable(GTK_WINDOW(dlg), FALSE);
182 datebox = gtk_vbox_new(FALSE, 5);
183 cal = gtk_calendar_new();
184 gtk_calendar_select_month(GTK_CALENDAR(cal), ds->date.tm_mon, ds->date.tm_year+1900);
185 gtk_calendar_select_day(GTK_CALENDAR(cal), ds->date.tm_mday);
186 gtk_box_pack_start(GTK_BOX(datebox), cal, TRUE, TRUE, 0);
188 hbox = gtk_hbox_new(FALSE, 5);
189 label = gtk_label_new_with_mnemonic(_("_Time:"));
190 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
191 houradj = (GtkAdjustment*)gtk_adjustment_new(ds->date.tm_hour, 0, 23, 1, 4, 4);
192 hourspin = gtk_spin_button_new(houradj, 1.0, 0);
193 gtk_label_set_mnemonic_widget(GTK_LABEL(label), hourspin);
195 minadj = (GtkAdjustment*)gtk_adjustment_new(ds->date.tm_min, 0, 59, 1, 10, 10);
196 minspin = gtk_spin_button_new(minadj, 1.0, 0);
197 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(minspin), TRUE);
198 g_signal_connect(G_OBJECT(minspin), "output",
199 G_CALLBACK(minute_output_cb), NULL);
201 if (gtk_widget_get_direction(hbox) == GTK_TEXT_DIR_RTL) {
202 /* even though we're right-to-left, hours still should
203 * be on the left of minutes. */
204 gtk_box_pack_start(GTK_BOX(hbox), minspin, FALSE, FALSE, 0);
205 gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(":"),
206 FALSE, FALSE, 0);
207 gtk_box_pack_start(GTK_BOX(hbox), hourspin, FALSE, FALSE, 0);
208 } else {
209 gtk_box_pack_start(GTK_BOX(hbox), hourspin, FALSE, FALSE, 0);
210 gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(":"),
211 FALSE, FALSE, 0);
212 gtk_box_pack_start(GTK_BOX(hbox), minspin, FALSE, FALSE, 0);
215 gtk_box_pack_start(GTK_BOX(datebox), hbox, FALSE, FALSE, 0);
217 check = gtk_check_button_new_with_mnemonic(_("Use _current date/time"));
218 g_signal_connect(G_OBJECT(check), "toggled",
219 G_CALLBACK(usenow_cb), datebox);
221 backdated = gtk_check_button_new_with_mnemonic(_("Entry is _backdated"));
222 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(backdated), ds->backdated);
223 g_signal_connect(G_OBJECT(backdated), "toggled",
224 G_CALLBACK(backdated_cb), ds);
226 vbox = gtk_vbox_new(FALSE, 10);
227 gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
228 gtk_box_pack_start(GTK_BOX(vbox), datebox, TRUE, TRUE, 0);
229 gtk_box_pack_start(GTK_BOX(vbox), backdated, FALSE, FALSE, 0);
231 jam_dialog_set_contents(GTK_DIALOG(dlg), vbox);
233 /* set it active here so it can hide the contents if necessary. */
234 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), ds->timeout_id != 0);
236 gtk_dialog_run(GTK_DIALOG(dlg));
238 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) {
239 timeout_enable(ds, TRUE);
240 } else {
241 timeout_enable(ds, FALSE);
242 gtk_calendar_get_date(GTK_CALENDAR(cal), &year, &month, &day);
243 ds->date.tm_year = year-1900;
244 ds->date.tm_mon = month;
245 ds->date.tm_mday = day;
246 ds->date.tm_hour = gtk_spin_button_get_value_as_int(
247 GTK_SPIN_BUTTON(hourspin));
248 ds->date.tm_min = gtk_spin_button_get_value_as_int(
249 GTK_SPIN_BUTTON(minspin));
251 update_display(ds);
252 gtk_widget_destroy(dlg);