1 /*
2 * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2010 David King <davidk@openismus.com>
4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <glib/gi18n-lib.h>
23 #include "gdaui-entry-common-time.h"
24 #include <libgda/gda-data-handler.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <string.h>
27 #include "gdaui-formatted-entry.h"
28 #include <libgda/gda-debug-macros.h>
29
30 /*
31 * Main static functions
32 */
33 static void gdaui_entry_common_time_class_init (GdauiEntryCommonTimeClass * class);
34 static void gdaui_entry_common_time_init (GdauiEntryCommonTime * srv);
35 static void gdaui_entry_common_time_dispose (GObject *object);
36 static void gdaui_entry_common_time_finalize (GObject *object);
37
38 static void gdaui_entry_common_time_set_property (GObject *object,
39 guint param_id,
40 const GValue *value,
41 GParamSpec *pspec);
42 static void gdaui_entry_common_time_get_property (GObject *object,
43 guint param_id,
44 GValue *value,
45 GParamSpec *pspec);
46
47 /* properties */
48 enum
49 {
50 PROP_0,
51 PROP_EDITING_CANCELED,
52 PROP_TYPE
53 };
54
55 /* GtkCellEditable interface */
56 static void gdaui_entry_common_time_cell_editable_init (GtkCellEditableIface *iface);
57 static void gdaui_entry_common_time_start_editing (GtkCellEditable *iface, GdkEvent *event);
58
59 /* virtual functions */
60 static GtkWidget *create_entry (GdauiEntryWrapper *mgwrap);
61 static void real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value);
62 static GValue *real_get_value (GdauiEntryWrapper *mgwrap);
63 static void connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb);
64 static void set_editable (GdauiEntryWrapper *mgwrap, gboolean editable);
65 static void grab_focus (GdauiEntryWrapper *mgwrap);
66
67 /* get a pointer to the parents to be able to call their destructor */
68 static GObjectClass *parent_class = NULL;
69
70
71 /* private structure */
72 struct _GdauiEntryCommonTimePrivate
73 {
74 /* for date */
75 GtkWidget *entry_date;
76 GtkWidget *date;
77 GtkWidget *window;
78 GtkWidget *date_button;
79 gboolean editing_canceled;
80
81 /* for time */
82 GtkWidget *entry_time;
83
84 /* for timestamp */
85 GtkWidget *hbox;
86
87 /* Last value set */
88 GValue *last_value_set;
89 };
90
91 static void
gdaui_entry_common_time_cell_editable_init(GtkCellEditableIface * iface)92 gdaui_entry_common_time_cell_editable_init (GtkCellEditableIface *iface)
93 {
94 iface->start_editing = gdaui_entry_common_time_start_editing;
95 }
96
97 GType
gdaui_entry_common_time_get_type(void)98 gdaui_entry_common_time_get_type (void)
99 {
100 static GType type = 0;
101
102 if (G_UNLIKELY (type == 0)) {
103 static const GTypeInfo info = {
104 sizeof (GdauiEntryCommonTimeClass),
105 (GBaseInitFunc) NULL,
106 (GBaseFinalizeFunc) NULL,
107 (GClassInitFunc) gdaui_entry_common_time_class_init,
108 NULL,
109 NULL,
110 sizeof (GdauiEntryCommonTime),
111 0,
112 (GInstanceInitFunc) gdaui_entry_common_time_init,
113 0
114 };
115
116 static const GInterfaceInfo cell_editable_info = {
117 (GInterfaceInitFunc) gdaui_entry_common_time_cell_editable_init, /* interface_init */
118 NULL, /* interface_finalize */
119 NULL /* interface_data */
120 };
121
122 type = g_type_register_static (GDAUI_TYPE_ENTRY_WRAPPER, "GdauiEntryCommonTime", &info, 0);
123 g_type_add_interface_static (type, GTK_TYPE_CELL_EDITABLE, &cell_editable_info);
124 }
125 return type;
126 }
127
128 static void
gdaui_entry_common_time_class_init(GdauiEntryCommonTimeClass * class)129 gdaui_entry_common_time_class_init (GdauiEntryCommonTimeClass * class)
130 {
131 GObjectClass *object_class = G_OBJECT_CLASS (class);
132
133 parent_class = g_type_class_peek_parent (class);
134
135 object_class->dispose = gdaui_entry_common_time_dispose;
136 object_class->finalize = gdaui_entry_common_time_finalize;
137
138 GDAUI_ENTRY_WRAPPER_CLASS (class)->create_entry = create_entry;
139 GDAUI_ENTRY_WRAPPER_CLASS (class)->real_set_value = real_set_value;
140 GDAUI_ENTRY_WRAPPER_CLASS (class)->real_get_value = real_get_value;
141 GDAUI_ENTRY_WRAPPER_CLASS (class)->connect_signals = connect_signals;
142 GDAUI_ENTRY_WRAPPER_CLASS (class)->set_editable = set_editable;
143 GDAUI_ENTRY_WRAPPER_CLASS (class)->grab_focus = grab_focus;
144
145 /* Properties */
146 object_class->set_property = gdaui_entry_common_time_set_property;
147 object_class->get_property = gdaui_entry_common_time_get_property;
148
149 g_object_class_install_property (object_class, PROP_EDITING_CANCELED,
150 g_param_spec_boolean ("editing-canceled", NULL, NULL, FALSE,
151 G_PARAM_READABLE | G_PARAM_WRITABLE));
152 g_object_class_install_property (object_class, PROP_TYPE,
153 g_param_spec_uint ("type", NULL, NULL, 0, G_MAXUINT, GDA_TYPE_TIME,
154 G_PARAM_WRITABLE | G_PARAM_READABLE));
155 }
156
157 static gboolean
key_press_event_cb(GdauiEntryCommonTime * mgtim,GdkEventKey * key_event,G_GNUC_UNUSED gpointer data)158 key_press_event_cb (GdauiEntryCommonTime *mgtim, GdkEventKey *key_event, G_GNUC_UNUSED gpointer data)
159 {
160 if (key_event->keyval == GDK_KEY_Escape)
161 mgtim->priv->editing_canceled = TRUE;
162 return FALSE;
163 }
164
165 static void
gdaui_entry_common_time_init(GdauiEntryCommonTime * gdaui_entry_common_time)166 gdaui_entry_common_time_init (GdauiEntryCommonTime *gdaui_entry_common_time)
167 {
168 gdaui_entry_common_time->priv = g_new0 (GdauiEntryCommonTimePrivate, 1);
169 gdaui_entry_common_time->priv->entry_date = NULL;
170 gdaui_entry_common_time->priv->entry_time = NULL;
171 gdaui_entry_common_time->priv->date = NULL;
172 gdaui_entry_common_time->priv->window = NULL;
173 gdaui_entry_common_time->priv->date_button = NULL;
174 gdaui_entry_common_time->priv->hbox = NULL;
175 gdaui_entry_common_time->priv->last_value_set = NULL;
176 gdaui_entry_common_time->priv->editing_canceled = FALSE;
177 g_signal_connect (gdaui_entry_common_time, "key-press-event",
178 G_CALLBACK (key_press_event_cb), NULL);
179 }
180
181 /**
182 * gdaui_entry_common_time_new:
183 * @dh: the data handler to be used by the new widget
184 * @type: the requested data type (compatible with @dh)
185 *
186 * Creates a new data entry widget
187 *
188 * Returns: (transfer full): the new widget
189 */
190 GtkWidget *
gdaui_entry_common_time_new(GdaDataHandler * dh,GType type)191 gdaui_entry_common_time_new (GdaDataHandler *dh, GType type)
192 {
193 GObject *obj;
194 GdauiEntryCommonTime *mgtim;
195
196 g_return_val_if_fail (dh && GDA_IS_DATA_HANDLER (dh), NULL);
197 g_return_val_if_fail (gda_data_handler_accepts_g_type (dh, type), NULL);
198
199 obj = g_object_new (GDAUI_TYPE_ENTRY_COMMON_TIME, "handler", dh, NULL);
200 mgtim = GDAUI_ENTRY_COMMON_TIME (obj);
201 gdaui_data_entry_set_value_type (GDAUI_DATA_ENTRY (mgtim), type);
202
203 return GTK_WIDGET (obj);
204 }
205
206
207 static void
gdaui_entry_common_time_dispose(GObject * object)208 gdaui_entry_common_time_dispose (GObject * object)
209 {
210 GdauiEntryCommonTime *gdaui_entry_common_time;
211
212 g_return_if_fail (object != NULL);
213 g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (object));
214
215 gdaui_entry_common_time = GDAUI_ENTRY_COMMON_TIME (object);
216 if (gdaui_entry_common_time->priv) {
217 if (gdaui_entry_common_time->priv->window) {
218 gtk_widget_destroy (gdaui_entry_common_time->priv->window);
219 gdaui_entry_common_time->priv->window = NULL;
220 }
221 }
222
223 /* parent class */
224 parent_class->dispose (object);
225 }
226
227 static void
gdaui_entry_common_time_finalize(GObject * object)228 gdaui_entry_common_time_finalize (GObject * object)
229 {
230 GdauiEntryCommonTime *gdaui_entry_common_time;
231
232 g_return_if_fail (object != NULL);
233 g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (object));
234
235 gdaui_entry_common_time = GDAUI_ENTRY_COMMON_TIME (object);
236 if (gdaui_entry_common_time->priv) {
237 if (gdaui_entry_common_time->priv->last_value_set)
238 gda_value_free (gdaui_entry_common_time->priv->last_value_set);
239
240 g_free (gdaui_entry_common_time->priv);
241 gdaui_entry_common_time->priv = NULL;
242 }
243
244 /* parent class */
245 parent_class->finalize (object);
246 }
247
248 static void
gdaui_entry_common_time_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)249 gdaui_entry_common_time_set_property (GObject *object,
250 guint param_id,
251 const GValue *value,
252 GParamSpec *pspec)
253 {
254 GdauiEntryCommonTime *mgtim;
255
256 mgtim = GDAUI_ENTRY_COMMON_TIME (object);
257 if (mgtim->priv) {
258 switch (param_id) {
259 case PROP_TYPE:
260 gdaui_data_entry_set_value_type (GDAUI_DATA_ENTRY (object), g_value_get_uint (value));
261 break;
262 case PROP_EDITING_CANCELED:
263 TO_IMPLEMENT;
264 break;
265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
267 break;
268 }
269 }
270 }
271
272 static void
gdaui_entry_common_time_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)273 gdaui_entry_common_time_get_property (GObject *object,
274 guint param_id,
275 GValue *value,
276 GParamSpec *pspec)
277 {
278 GdauiEntryCommonTime *mgtim;
279
280 mgtim = GDAUI_ENTRY_COMMON_TIME (object);
281 if (mgtim->priv) {
282 switch (param_id) {
283 case PROP_EDITING_CANCELED:
284 g_value_set_boolean (value, mgtim->priv->editing_canceled);
285 break;
286 case PROP_TYPE:
287 g_value_set_uint (value, gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (object)));
288 break;
289 default:
290 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
291 break;
292 }
293 }
294 }
295
296 static GtkWidget *create_entry_date (GdauiEntryCommonTime *mgtim);
297 static GtkWidget *create_entry_time (GdauiEntryCommonTime *mgtim);
298 static GtkWidget *create_entry_ts (GdauiEntryCommonTime *mgtim);
299 static GtkWidget *
create_entry(GdauiEntryWrapper * mgwrap)300 create_entry (GdauiEntryWrapper *mgwrap)
301 {
302 GdauiEntryCommonTime *mgtim;
303 GtkWidget *entry = NULL;
304 GType type;
305
306 g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap), NULL);
307 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
308 g_return_val_if_fail (mgtim->priv, NULL);
309
310 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
311 if (type == G_TYPE_DATE)
312 entry = create_entry_date (mgtim);
313 else if (type == GDA_TYPE_TIME)
314 entry = create_entry_time (mgtim);
315 else if (type == GDA_TYPE_TIMESTAMP)
316 entry = create_entry_ts (mgtim);
317 else
318 g_assert_not_reached ();
319
320 return entry;
321 }
322
323 static void
real_set_value(GdauiEntryWrapper * mgwrap,const GValue * value)324 real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
325 {
326 GdauiEntryCommonTime *mgtim;
327 GType type;
328 GdaDataHandler *dh;
329
330 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
331 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
332 g_return_if_fail (mgtim->priv);
333
334 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
335 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
336
337 if (type == G_TYPE_DATE) {
338 if (value) {
339 if (gda_value_is_null ((GValue *) value))
340 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
341 else {
342 gchar *str;
343
344 str = gda_data_handler_get_str_from_value (dh, value);
345 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), str);
346 g_free (str);
347 }
348 }
349 else
350 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
351 }
352 else if (type == GDA_TYPE_TIME) {
353 if (value) {
354 if (gda_value_is_null ((GValue *) value))
355 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
356 else {
357 gchar *str;
358
359 str = gda_data_handler_get_str_from_value (dh, value);
360 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), str);
361 g_free (str);
362 }
363 }
364 else
365 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
366 }
367 else if (type == GDA_TYPE_TIMESTAMP) {
368 if (value) {
369 if (gda_value_is_null ((GValue *) value)) {
370 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
371 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
372 }
373 else {
374 gchar *str, *ptr;
375
376 str = gda_data_handler_get_str_from_value (dh, value);
377 ptr = strtok (str, " ");
378 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), ptr);
379 ptr = strtok (NULL, " ");
380 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), ptr);
381 g_free (str);
382 }
383 }
384 else {
385 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
386 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
387 }
388 }
389 else
390 g_assert_not_reached ();
391
392 /* keep track of the last value set */
393 if (mgtim->priv->last_value_set) {
394 gda_value_free (mgtim->priv->last_value_set);
395 mgtim->priv->last_value_set = NULL;
396 }
397 if (value)
398 mgtim->priv->last_value_set = gda_value_copy ((GValue *) value);
399 }
400
401 static GValue *
real_get_value(GdauiEntryWrapper * mgwrap)402 real_get_value (GdauiEntryWrapper *mgwrap)
403 {
404 GValue *value = NULL;
405 GdauiEntryCommonTime *mgtim;
406 GdaDataHandler *dh;
407 gchar *str2;
408 GType type;
409
410 g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap), NULL);
411 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
412 g_return_val_if_fail (mgtim->priv, NULL);
413
414 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
415 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
416
417 if (type == G_TYPE_DATE) {
418 str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_date));
419 if (str2) {
420 value = gda_data_handler_get_value_from_str (dh, str2, type);
421 g_free (str2);
422 }
423 }
424 else if (type == GDA_TYPE_TIME) {
425 str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_time));
426 if (str2) {
427 value = gda_data_handler_get_value_from_str (dh, str2, type);
428 g_free (str2);
429 }
430
431 if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL) &&
432 mgtim->priv->last_value_set &&
433 gda_value_isa (mgtim->priv->last_value_set, GDA_TYPE_TIME)) {
434 /* copy the 'timezone' part, we we have not modified */
435 const GdaTime *dgatime_set = gda_value_get_time (mgtim->priv->last_value_set);
436 GdaTime *gdatime = g_new (GdaTime, 1);
437 *gdatime = *(gda_value_get_time (value));
438 gdatime->timezone = dgatime_set->timezone;
439 gda_value_set_time (value, gdatime);
440 g_free (gdatime);
441 }
442 }
443 else if (type == GDA_TYPE_TIMESTAMP) {
444 gchar *tmpstr, *tmpstr2;
445
446 tmpstr = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_time));
447 tmpstr2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_date));
448 if (tmpstr && tmpstr2) {
449 str2 = g_strdup_printf ("%s %s", tmpstr2, tmpstr);
450 value = gda_data_handler_get_value_from_str (dh, str2, type);
451 g_free (str2);
452 }
453 g_free (tmpstr);
454 g_free (tmpstr2);
455 if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL) &&
456 mgtim->priv->last_value_set &&
457 gda_value_isa (mgtim->priv->last_value_set, GDA_TYPE_TIMESTAMP)) {
458 /* copy the 'fraction' and 'timezone' parts, we have not modified */
459 const GdaTimestamp *dgatime_set = gda_value_get_timestamp (mgtim->priv->last_value_set);
460 GdaTimestamp *gdatime = g_new (GdaTimestamp, 1);
461 *gdatime = *(gda_value_get_timestamp (value));
462 gdatime->fraction = dgatime_set->fraction;
463 gdatime->timezone = dgatime_set->timezone;
464 gda_value_set_timestamp (value, gdatime);
465 g_free (gdatime);
466 }
467 }
468 else
469 g_assert_not_reached ();
470
471 if (!value) {
472 /* in case the gda_data_handler_get_value_from_str() returned an error because
473 the contents of the GtkEntry cannot be interpreted as a GValue */
474 value = gda_value_new_null ();
475 }
476
477 return value;
478 }
479
480 static void
connect_signals(GdauiEntryWrapper * mgwrap,GCallback modify_cb,GCallback activate_cb)481 connect_signals (GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
482 {
483 GdauiEntryCommonTime *mgtim;
484 GType type;
485
486 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
487 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
488 g_return_if_fail (mgtim->priv);
489
490 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
491
492 if ((type == G_TYPE_DATE) || (type == GDA_TYPE_TIMESTAMP)) {
493 g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "changed",
494 modify_cb, mgwrap);
495 g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "activate",
496 activate_cb, mgwrap);
497 }
498
499 if ((type == GDA_TYPE_TIME) || (type == GDA_TYPE_TIMESTAMP)) {
500 g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "changed",
501 modify_cb, mgwrap);
502 g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "activate",
503 activate_cb, mgwrap);
504 }
505 }
506
507 static void
set_editable(GdauiEntryWrapper * mgwrap,gboolean editable)508 set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
509 {
510 GdauiEntryCommonTime *mgtim;
511
512 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
513 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
514 g_return_if_fail (mgtim->priv);
515
516 if (mgtim->priv->entry_date)
517 gtk_editable_set_editable (GTK_EDITABLE (mgtim->priv->entry_date), editable);
518 if (mgtim->priv->entry_time)
519 gtk_editable_set_editable (GTK_EDITABLE (mgtim->priv->entry_time), editable);
520 if (mgtim->priv->date_button)
521 gtk_widget_set_sensitive (mgtim->priv->date_button, editable);
522 }
523
524 static void
grab_focus(GdauiEntryWrapper * mgwrap)525 grab_focus (GdauiEntryWrapper *mgwrap)
526 {
527 GdauiEntryCommonTime *mgtim;
528
529 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
530 mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
531 g_return_if_fail (mgtim->priv);
532
533 if (mgtim->priv->entry_date)
534 gtk_widget_grab_focus (mgtim->priv->entry_date);
535 if (mgtim->priv->entry_time)
536 gtk_widget_grab_focus (mgtim->priv->entry_time);
537 }
538
539
540
541 /*
542 * callbacks for the date
543 */
544 static gint date_delete_popup (GtkWidget *widget, GdauiEntryCommonTime *mgtim);
545 static gint date_key_press_popup (GtkWidget *widget, GdkEventKey *event, GdauiEntryCommonTime *mgtim);
546 static gint date_button_press_popup (GtkWidget *widget, GdkEventButton *event, GdauiEntryCommonTime *mgtim);
547 static void date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
548 static void date_day_selected_double_click (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
549 static void date_calendar_choose_cb (GtkWidget *button, GdauiEntryCommonTime *mgtim);
550
551 static void entry_date_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data);
552
553 static GtkWidget *
create_entry_date(GdauiEntryCommonTime * mgtim)554 create_entry_date (GdauiEntryCommonTime *mgtim)
555 {
556 GtkWidget *wid, *hb, *window, *arrow;
557 GdaDataHandler *dh;
558
559 /* top widget */
560 hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
561
562 /* text entry */
563 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
564 if (GDA_IS_HANDLER_TIME (dh)) {
565 gchar *str, *mask, *ptr;
566 str = gda_handler_time_get_format (GDA_HANDLER_TIME (dh), G_TYPE_DATE);
567 mask = g_strdup (str);
568 for (ptr = mask; *ptr; ptr++) {
569 if (*ptr == '0')
570 *ptr = '-';
571 }
572 wid = gdaui_formatted_entry_new (str, mask);
573 g_free (str);
574 g_free (mask);
575
576 gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_date_insert_func,
577 mgtim);
578 }
579 else
580 wid = gdaui_entry_new (NULL, NULL);
581 gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
582 gtk_widget_show (wid);
583 mgtim->priv->entry_date = wid;
584
585 /* window to hold the calendar popup */
586 window = gtk_window_new (GTK_WINDOW_POPUP);
587 gtk_widget_set_events (window, gtk_widget_get_events (window) | GDK_KEY_PRESS_MASK);
588 gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
589 g_signal_connect (G_OBJECT (window), "delete-event",
590 G_CALLBACK (date_delete_popup), mgtim);
591 g_signal_connect (G_OBJECT (window), "key-press-event",
592 G_CALLBACK (date_key_press_popup), mgtim);
593 g_signal_connect (G_OBJECT (window), "button-press-event",
594 G_CALLBACK (date_button_press_popup), mgtim);
595 mgtim->priv->window = window;
596
597 /* calendar */
598 wid = gtk_calendar_new ();
599 mgtim->priv->date = wid;
600 gtk_container_add (GTK_CONTAINER (window), wid);
601 gtk_widget_show (wid);
602 g_signal_connect (G_OBJECT (wid), "day-selected",
603 G_CALLBACK (date_day_selected), mgtim);
604 g_signal_connect (G_OBJECT (wid), "day-selected-double-click",
605 G_CALLBACK (date_day_selected_double_click), mgtim);
606
607 /* button to pop up the calendar */
608 wid = gtk_button_new ();
609 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
610 gtk_container_add (GTK_CONTAINER (wid), arrow);
611 gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
612 gtk_widget_show_all (wid);
613 g_signal_connect (G_OBJECT (wid), "clicked",
614 G_CALLBACK (date_calendar_choose_cb), mgtim);
615 mgtim->priv->date_button = wid;
616
617 /* padding */
618 wid = gtk_label_new ("");
619 gtk_box_pack_start (GTK_BOX (hb), wid, TRUE, TRUE, 0);
620 gtk_widget_show (wid);
621
622 return hb;
623 }
624
625 static void
entry_date_insert_func(G_GNUC_UNUSED GdauiFormattedEntry * fentry,gunichar insert_char,G_GNUC_UNUSED gint virt_pos,gpointer data)626 entry_date_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar insert_char,
627 G_GNUC_UNUSED gint virt_pos, gpointer data)
628 {
629 GValue *value;
630 GType type;
631
632 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (data));
633 value = real_get_value (GDAUI_ENTRY_WRAPPER (data));
634 if (!value)
635 return;
636
637 if (G_VALUE_TYPE (value) == GDA_TYPE_NULL) {
638 if (type == G_TYPE_DATE) {
639 /* set current date, whatever @insert_char is */
640 GDate *ndate;
641 ndate = g_new0 (GDate, 1);
642 g_date_set_time_t (ndate, time (NULL));
643
644 gda_value_reset_with_type (value, type);
645 g_value_take_boxed (value, ndate);
646 real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
647 }
648 else if (type == GDA_TYPE_TIMESTAMP) {
649 GValue *tsvalue;
650 gchar *str;
651 GdauiEntryCommonTime *mgtim = GDAUI_ENTRY_COMMON_TIME (data);
652 str = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_time));
653 tsvalue = gda_value_new_timestamp_from_timet (time (NULL));
654 real_set_value (GDAUI_ENTRY_WRAPPER (data), tsvalue);
655 gda_value_free (tsvalue);
656 if (str && g_ascii_isdigit (*str))
657 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), str);
658 g_free (str);
659 }
660 }
661 else {
662 GDate *date = NULL;
663 if (type == G_TYPE_DATE) {
664 date = (GDate*) g_value_get_boxed (value);
665 }
666 else if (type == GDA_TYPE_TIMESTAMP) {
667 const GdaTimestamp *ts;
668 ts = gda_value_get_timestamp (value);
669 date = g_date_new_dmy (ts->day, ts->month, ts->year);
670 }
671
672 if (date) {
673 GDate *ndate;
674 gboolean changed = FALSE;
675
676 ndate = g_new (GDate, 1);
677 *ndate = *date;
678 if ((insert_char == g_utf8_get_char ("+")) ||
679 (insert_char == g_utf8_get_char ("="))) {
680 g_date_add_days (ndate, 1);
681 changed = TRUE;
682 }
683 else if ((insert_char == g_utf8_get_char ("-")) ||
684 (insert_char == g_utf8_get_char ("6"))) {
685 g_date_subtract_days (ndate, 1);
686 changed = TRUE;
687 }
688
689 if (changed) {
690 if (type == G_TYPE_DATE) {
691 g_value_take_boxed (value, ndate);
692 }
693 else if (type == GDA_TYPE_TIMESTAMP) {
694 GdaTimestamp *ts;
695 ts = (GdaTimestamp*) gda_timestamp_copy ((gpointer) gda_value_get_timestamp (value));
696 ts->day = g_date_get_day (ndate);
697 ts->month = g_date_get_month (ndate);
698 ts->year = g_date_get_year (ndate);
699 g_date_free (date);
700 g_date_free (ndate);
701 gda_value_set_timestamp (value, ts);
702 gda_timestamp_free (ts);
703 }
704 real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
705 }
706 }
707 }
708 gda_value_free (value);
709 }
710
711 static void
hide_popup(GdauiEntryCommonTime * mgtim)712 hide_popup (GdauiEntryCommonTime *mgtim)
713 {
714 gtk_widget_hide (mgtim->priv->window);
715 gtk_grab_remove (mgtim->priv->window);
716 }
717
718 static gint
date_delete_popup(G_GNUC_UNUSED GtkWidget * widget,GdauiEntryCommonTime * mgtim)719 date_delete_popup (G_GNUC_UNUSED GtkWidget *widget, GdauiEntryCommonTime *mgtim)
720 {
721 hide_popup (mgtim);
722 return TRUE;
723 }
724
725 static gint
date_key_press_popup(GtkWidget * widget,GdkEventKey * event,GdauiEntryCommonTime * mgtim)726 date_key_press_popup (GtkWidget *widget, GdkEventKey *event, GdauiEntryCommonTime *mgtim)
727 {
728 if (event->keyval != GDK_KEY_Escape)
729 return FALSE;
730
731 g_signal_stop_emission_by_name (widget, "key-press-event");
732 hide_popup (mgtim);
733
734 return TRUE;
735 }
736
737 static gint
date_button_press_popup(GtkWidget * widget,GdkEventButton * event,GdauiEntryCommonTime * mgtim)738 date_button_press_popup (GtkWidget *widget, GdkEventButton *event, GdauiEntryCommonTime *mgtim)
739 {
740 GtkWidget *child;
741
742 child = gtk_get_event_widget ((GdkEvent *) event);
743
744 /* We don't ask for button press events on the grab widget, so
745 * if an event is reported directly to the grab widget, it must
746 * be on a window outside the application (and thus we remove
747 * the popup window). Otherwise, we check if the widget is a child
748 * of the grab widget, and only remove the popup window if it
749 * is not.
750 */
751 if (child != widget) {
752 while (child) {
753 if (child == widget)
754 return FALSE;
755 child = gtk_widget_get_parent (child);
756 }
757 }
758
759 hide_popup (mgtim);
760
761 return TRUE;
762 }
763
764 static void
date_day_selected(GtkCalendar * calendar,GdauiEntryCommonTime * mgtim)765 date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
766 {
767 char buffer [256];
768 guint year, month, day;
769 struct tm mtm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
770 char *str_utf8;
771
772 gtk_calendar_get_date (calendar, &year, &month, &day);
773
774 mtm.tm_mday = day;
775 mtm.tm_mon = month;
776 if (year > 1900)
777 mtm.tm_year = year - 1900;
778 else
779 mtm.tm_year = year;
780
781 if (strftime (buffer, sizeof (buffer), "%x", &mtm) == 0)
782 strcpy (buffer, "???");
783 buffer[sizeof(buffer)-1] = '\0';
784
785 str_utf8 = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
786 gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), str_utf8);
787 g_free (str_utf8);
788 }
789
790 static void
date_day_selected_double_click(G_GNUC_UNUSED GtkCalendar * calendar,GdauiEntryCommonTime * mgtim)791 date_day_selected_double_click (G_GNUC_UNUSED GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
792 {
793 hide_popup (mgtim);
794 }
795
796
797 static gboolean popup_grab_on_window (GtkWidget *widget, guint32 activate_time);
798 static void position_popup (GdauiEntryCommonTime *mgtim);
799 static void
date_calendar_choose_cb(GtkWidget * button,GdauiEntryCommonTime * mgtim)800 date_calendar_choose_cb (GtkWidget *button, GdauiEntryCommonTime *mgtim)
801 {
802 GValue *value;
803 guint year=0, month=0, day=0;
804 gboolean unset = TRUE;
805
806 /* setting the calendar to the latest displayed date */
807 value = gdaui_data_entry_get_value (GDAUI_DATA_ENTRY (mgtim));
808
809 if (value && !gda_value_is_null (value)) {
810 const GDate *date;
811 const GdaTimestamp *ts;
812 GType type;
813
814 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
815 if (type == G_TYPE_DATE) {
816 date = (GDate*) g_value_get_boxed (value);
817 if (date) {
818 month = g_date_get_month (date);
819 year = g_date_get_year (date);
820 day = g_date_get_day (date);
821 if ((month != G_DATE_BAD_MONTH) &&
822 (day != G_DATE_BAD_DAY) &&
823 (year != G_DATE_BAD_YEAR)) {
824 month -= 1;
825 unset = FALSE;
826 }
827 }
828 }
829 else if (type == GDA_TYPE_TIMESTAMP) {
830 ts = gda_value_get_timestamp (value);
831 if (ts) {
832 year = ts->year;
833 month = ts->month - 1;
834 day = ts->day;
835 unset = FALSE;
836 }
837 }
838 else
839 g_assert_not_reached ();
840 }
841
842 if (unset) {
843 time_t now;
844 struct tm *stm;
845
846 now = time (NULL);
847 #ifdef HAVE_LOCALTIME_R
848 struct tm tmpstm;
849 stm = localtime_r (&now, &tmpstm);
850 #elif HAVE_LOCALTIME_S
851 struct tm tmpstm;
852 g_assert (localtime_s (&tmpstm, &now) == 0);
853 stm = &tmpstm;
854 #else
855 stm = localtime (&now);
856 #endif
857 year = stm->tm_year + 1900;
858 month = stm->tm_mon;
859 day = stm->tm_mday;
860 }
861
862 gtk_calendar_select_month (GTK_CALENDAR (mgtim->priv->date), month, year);
863 gtk_calendar_select_day (GTK_CALENDAR (mgtim->priv->date), day);
864
865 /* popup window */
866 /* Temporarily grab pointer and keyboard, copied from GnomeDateEdit */
867 if (!popup_grab_on_window (button, gtk_get_current_event_time ()))
868 return;
869
870 position_popup (mgtim);
871 gtk_widget_show (mgtim->priv->window);
872 gtk_grab_add (mgtim->priv->window);
873
874 GdkScreen *screen;
875 gint swidth, sheight;
876 gint root_x, root_y;
877 gint wwidth, wheight;
878 gboolean do_move = FALSE;
879 screen = gtk_window_get_screen (GTK_WINDOW (mgtim->priv->window));
880 if (screen) {
881 swidth = gdk_screen_get_width (screen);
882 sheight = gdk_screen_get_height (screen);
883 }
884 else {
885 swidth = gdk_screen_width ();
886 sheight = gdk_screen_height ();
887 }
888 gtk_window_get_position (GTK_WINDOW (mgtim->priv->window), &root_x, &root_y);
889 gtk_window_get_size (GTK_WINDOW (mgtim->priv->window), &wwidth, &wheight);
890 if (root_x + wwidth > swidth) {
891 do_move = TRUE;
892 root_x = swidth - wwidth;
893 }
894 else if (root_x < 0) {
895 do_move = TRUE;
896 root_x = 0;
897 }
898 if (root_y + wheight > sheight) {
899 do_move = TRUE;
900 root_y = sheight - wheight;
901 }
902 else if (root_y < 0) {
903 do_move = TRUE;
904 root_y = 0;
905 }
906 if (do_move)
907 gtk_window_move (GTK_WINDOW (mgtim->priv->window), root_x, root_y);
908
909 gtk_widget_grab_focus (mgtim->priv->date);
910 popup_grab_on_window (mgtim->priv->window,
911 gtk_get_current_event_time ());
912 }
913
914 static gboolean
popup_grab_on_window(GtkWidget * widget,guint32 activate_time)915 popup_grab_on_window (GtkWidget *widget, guint32 activate_time)
916 {
917 GdkDeviceManager *manager;
918 GdkDevice *pointer;
919 GdkWindow *window;
920 window = gtk_widget_get_window (widget);
921 manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
922 pointer = gdk_device_manager_get_client_pointer (manager);
923 if (gdk_device_grab (pointer, window, GDK_OWNERSHIP_WINDOW, TRUE,
924 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
925 GDK_POINTER_MOTION_MASK,
926 NULL, activate_time) == GDK_GRAB_SUCCESS) {
927 GdkDevice *keyb;
928 keyb = gdk_device_get_associated_device (pointer);
929 if (gdk_device_grab (keyb, window, GDK_OWNERSHIP_WINDOW, TRUE,
930 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, activate_time) ==
931 GDK_GRAB_SUCCESS)
932 return TRUE;
933 else {
934 gdk_device_ungrab (pointer, activate_time);
935 return FALSE;
936 }
937 }
938 return FALSE;
939 }
940
941 static void
position_popup(GdauiEntryCommonTime * mgtim)942 position_popup (GdauiEntryCommonTime *mgtim)
943 {
944 gint x, y;
945 gint bwidth, bheight;
946 GtkRequisition req_minimum, req_natural;
947
948 gtk_widget_get_preferred_size (mgtim->priv->window, &req_minimum,
949 &req_natural);
950
951 gdk_window_get_origin (gtk_widget_get_window (mgtim->priv->date_button), &x, &y);
952 GtkAllocation alloc;
953 gtk_widget_get_allocation (mgtim->priv->date_button, &alloc);
954 x += alloc.x;
955 y += alloc.y;
956 bwidth = alloc.width;
957 bheight = alloc.height;
958
959 x += bwidth - req_natural.width;
960 y += bheight;
961
962 if (x < 0)
963 x = 0;
964
965 if (y < 0)
966 y = 0;
967
968 gtk_window_move (GTK_WINDOW (mgtim->priv->window), x, y);
969 }
970
971
972
973
974 /*
975 * callbacks for the time
976 */
977 static void entry_time_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data);
978
979 static GtkWidget *
create_entry_time(GdauiEntryCommonTime * mgtim)980 create_entry_time (GdauiEntryCommonTime *mgtim)
981 {
982 GtkWidget *wid;
983 GdaDataHandler *dh;
984
985 /* text entry */
986 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
987 if (GDA_IS_HANDLER_TIME (dh)) {
988 gchar *str, *mask, *ptr;
989 str = gda_handler_time_get_format (GDA_HANDLER_TIME (dh), GDA_TYPE_TIME);
990 mask = g_strdup (str);
991 for (ptr = mask; *ptr; ptr++) {
992 if (*ptr == '0')
993 *ptr = '-';
994 }
995 wid = gdaui_formatted_entry_new (str, mask);
996 g_free (str);
997 g_free (mask);
998
999 gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_time_insert_func,
1000 mgtim);
1001 }
1002 else
1003 wid = gdaui_entry_new (NULL, NULL);
1004 mgtim->priv->entry_time = wid;
1005
1006 /* format tooltip */
1007 gtk_widget_set_tooltip_text (wid, _("Format is hh:mm:ss"));
1008
1009 return wid;
1010 }
1011
1012 static void
entry_time_insert_func(G_GNUC_UNUSED GdauiFormattedEntry * fentry,gunichar insert_char,G_GNUC_UNUSED gint virt_pos,gpointer data)1013 entry_time_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar insert_char,
1014 G_GNUC_UNUSED gint virt_pos, gpointer data)
1015 {
1016 GValue *value;
1017 GType type;
1018
1019 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (data));
1020 value = real_get_value (GDAUI_ENTRY_WRAPPER (data));
1021 if (!value)
1022 return;
1023
1024 if (insert_char != g_utf8_get_char (" "))
1025 return;
1026
1027 if (type == GDA_TYPE_TIME) {
1028 /* set current time */
1029 gda_value_reset_with_type (value, type);
1030 struct tm *ltm;
1031 time_t val;
1032
1033 val = time (NULL);
1034 ltm = localtime ((const time_t *) &val);
1035 if (ltm) {
1036 GdaTime tim;
1037 memset (&tim, 0, sizeof (GdaTime));
1038 tim.hour = ltm->tm_hour;
1039 tim.minute = ltm->tm_min;
1040 tim.second = ltm->tm_sec;
1041 tim.fraction = 0;
1042 tim.timezone = GDA_TIMEZONE_INVALID;
1043 gda_value_set_time (value, (const GdaTime *) &tim);
1044 real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
1045 }
1046 }
1047 else if (type == GDA_TYPE_TIMESTAMP && (G_VALUE_TYPE (value) == GDA_TYPE_TIMESTAMP)) {
1048 const GdaTimestamp *ts;
1049 ts = gda_value_get_timestamp (value);
1050 if (ts) {
1051 struct tm *ltm;
1052 time_t val;
1053
1054 val = time (NULL);
1055 ltm = localtime ((const time_t *) &val);
1056 if (ltm) {
1057 GdaTimestamp tim;
1058 tim = *ts;
1059 tim.hour = ltm->tm_hour;
1060 tim.minute = ltm->tm_min;
1061 tim.second = ltm->tm_sec;
1062 tim.fraction = 0;
1063 tim.timezone = GDA_TIMEZONE_INVALID;
1064 gda_value_set_timestamp (value, (const GdaTimestamp *) &tim);
1065 real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
1066 }
1067 }
1068 }
1069 else if (type == GDA_TYPE_TIMESTAMP) {
1070 /* value is GDA_TYPE_NULL */
1071 entry_date_insert_func (NULL, insert_char, 0, data);
1072 }
1073
1074 gda_value_free (value);
1075 }
1076
1077 /*
1078 * callbacks for the timestamp
1079 */
1080 static GtkWidget *
create_entry_ts(GdauiEntryCommonTime * mgtim)1081 create_entry_ts (GdauiEntryCommonTime *mgtim)
1082 {
1083 GtkWidget *hb, *wid;
1084
1085 hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1086
1087 /* date part */
1088 wid = create_entry_date (mgtim);
1089 gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
1090 gtk_widget_show (wid);
1091
1092 /* time part */
1093 wid = create_entry_time (mgtim);
1094 gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
1095 gtk_widget_show (wid);
1096
1097 mgtim->priv->hbox = hb;
1098
1099 return hb;
1100 }
1101
1102
1103
1104 /*
1105 * GtkCellEditable interface
1106 */
1107 static void
gtk_cell_editable_entry_editing_done_cb(G_GNUC_UNUSED GtkEntry * entry,GdauiEntryCommonTime * mgtim)1108 gtk_cell_editable_entry_editing_done_cb (G_GNUC_UNUSED GtkEntry *entry, GdauiEntryCommonTime *mgtim)
1109 {
1110 gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (mgtim));
1111 }
1112
1113 static void
gtk_cell_editable_entry_remove_widget_cb(G_GNUC_UNUSED GtkEntry * entry,GdauiEntryCommonTime * mgtim)1114 gtk_cell_editable_entry_remove_widget_cb (G_GNUC_UNUSED GtkEntry *entry, GdauiEntryCommonTime *mgtim)
1115 {
1116 gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (mgtim));
1117 }
1118
1119 static void
gdaui_entry_common_time_start_editing(GtkCellEditable * iface,GdkEvent * event)1120 gdaui_entry_common_time_start_editing (GtkCellEditable *iface, GdkEvent *event)
1121 {
1122 GdauiEntryCommonTime *mgtim;
1123
1124 g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (iface));
1125 mgtim = GDAUI_ENTRY_COMMON_TIME (iface);
1126 g_return_if_fail (mgtim->priv);
1127
1128 mgtim->priv->editing_canceled = FALSE;
1129 if (mgtim->priv->date_button) {
1130 gtk_widget_destroy (mgtim->priv->date_button);
1131 mgtim->priv->date_button = NULL;
1132 }
1133
1134 if (mgtim->priv->hbox) {
1135 gtk_box_set_spacing (GTK_BOX (mgtim->priv->hbox), 0);
1136 gtk_container_set_border_width (GTK_CONTAINER (mgtim->priv->hbox), 0);
1137 }
1138
1139 if (mgtim->priv->entry_date) {
1140 g_object_set (G_OBJECT (mgtim->priv->entry_date), "has-frame", FALSE, NULL);
1141 gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgtim->priv->entry_date), event);
1142 g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "editing-done",
1143 G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgtim);
1144 g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "remove-widget",
1145 G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgtim);
1146 }
1147
1148 if (mgtim->priv->entry_time) {
1149 g_object_set (G_OBJECT (mgtim->priv->entry_time), "has-frame", FALSE, NULL);
1150 gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgtim->priv->entry_time), event);
1151 g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "editing-done",
1152 G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgtim);
1153 g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "remove-widget",
1154 G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgtim);
1155 }
1156
1157 gdaui_entry_shell_refresh (GDAUI_ENTRY_SHELL (mgtim));
1158
1159 if (mgtim->priv->entry_date)
1160 gtk_widget_grab_focus (mgtim->priv->entry_date);
1161 else
1162 gtk_widget_grab_focus (mgtim->priv->entry_time);
1163 gtk_widget_queue_draw (GTK_WIDGET (mgtim));
1164 }
1165