[libgda] UI: improved date and time entry widgets



commit 44824f5d50b3628ef1e47c54ba6c4c94a0dc278a
Author: Vivien Malerba <malerba gnome-db org>
Date:   Tue Sep 29 21:26:45 2009 +0200

    UI: improved date and time entry widgets
    
    if not date is set, then sets the current date,
    using '+' or '-' now adds or removes a day to the current
    date. For the time entry, pressing SPACE sets the current
    time.

 libgda-ui/data-entries/gdaui-entry-common-time.c |  125 +++++++++++++++++++++-
 libgda-ui/data-entries/gdaui-entry.c             |    1 +
 libgda-ui/data-entries/gdaui-formatted-entry.c   |   36 ++++++-
 libgda-ui/data-entries/gdaui-formatted-entry.h   |    6 +
 4 files changed, 166 insertions(+), 2 deletions(-)
---
diff --git a/libgda-ui/data-entries/gdaui-entry-common-time.c b/libgda-ui/data-entries/gdaui-entry-common-time.c
index 1cabe04..35cd463 100644
--- a/libgda-ui/data-entries/gdaui-entry-common-time.c
+++ b/libgda-ui/data-entries/gdaui-entry-common-time.c
@@ -547,7 +547,6 @@ grab_focus (GdauiEntryWrapper *mgwrap)
 /*
  * callbacks for the date 
  */
-
 static void internal_set_time (GtkWidget *widget, GdauiEntryCommonTime *mgtim);
 static gint date_delete_popup (GtkWidget *widget, GdauiEntryCommonTime *mgtim);
 static gint date_key_press_popup (GtkWidget *widget, GdkEventKey *event, GdauiEntryCommonTime *mgtim);
@@ -556,6 +555,8 @@ static void date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgti
 static void date_day_selected_double_click (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
 static void date_calendar_choose_cb (GtkWidget *button, GdauiEntryCommonTime *mgtim);
 
+static void entry_date_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data);
+
 static GtkWidget *
 create_entry_date (GdauiEntryCommonTime *mgtim)
 {
@@ -578,6 +579,9 @@ create_entry_date (GdauiEntryCommonTime *mgtim)
 		wid = gdaui_formatted_entry_new (str, mask);
 		g_free (str);
 		g_free (mask);
+
+		gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_date_insert_func,
+						       mgtim);
 	}
 	else
 		wid = gdaui_entry_new (NULL, NULL);
@@ -628,6 +632,85 @@ create_entry_date (GdauiEntryCommonTime *mgtim)
 }
 
 static void
+entry_date_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data)
+{
+	GValue *value;
+	GType type;
+
+	type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (data));
+	value = real_get_value (GDAUI_ENTRY_WRAPPER (data));
+	if (!value)
+		return;
+
+	if (G_VALUE_TYPE (value) == GDA_TYPE_NULL) {
+		if (type == G_TYPE_DATE) {
+			/* set current date, whatever @insert_char is */
+			GDate *ndate;
+			ndate = g_new0 (GDate, 1);
+			g_date_set_time_t (ndate, time (NULL));
+
+			gda_value_reset_with_type (value, type);
+			g_value_take_boxed (value, ndate);
+			real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
+		}
+		else if (type == GDA_TYPE_TIMESTAMP) {
+			GValue *tsvalue;
+			tsvalue = gda_value_new_timestamp_from_timet (time (NULL));
+			real_set_value (GDAUI_ENTRY_WRAPPER (data), tsvalue);
+			gda_value_free (tsvalue);
+		}
+	}
+	else {
+		GDate *date = NULL;
+		if (type == G_TYPE_DATE) {
+			date = (GDate*) g_value_get_boxed (value);
+		}
+		else if (type == GDA_TYPE_TIMESTAMP) {
+			const GdaTimestamp *ts;
+			ts = gda_value_get_timestamp (value);
+			date = g_date_new_dmy (ts->day, ts->month, ts->year);
+		}
+
+		if (date) {
+			GDate *ndate;
+			gboolean changed = FALSE;
+
+			ndate = g_new (GDate, 1);
+			*ndate = *date;
+			if ((insert_char == g_utf8_get_char ("+")) ||
+			    (insert_char == g_utf8_get_char ("="))) {
+				g_date_add_days (ndate, 1);
+				changed = TRUE;
+			}
+			else if ((insert_char == g_utf8_get_char ("-")) ||
+				 (insert_char == g_utf8_get_char ("6"))) {
+				g_date_subtract_days (ndate, 1);
+				changed = TRUE;
+			}
+
+			if (changed) {
+				if (type == G_TYPE_DATE) {
+					g_value_take_boxed (value, ndate);
+				}
+				else if (type == GDA_TYPE_TIMESTAMP) {
+					GdaTimestamp *ts;
+					ts = (GdaTimestamp*) gda_timestamp_copy ((gpointer) gda_value_get_timestamp (value));
+					ts->day = g_date_get_day (ndate);
+					ts->month = g_date_get_month (ndate);
+					ts->year = g_date_get_year (ndate);
+					g_date_free (date);
+					g_date_free (ndate);
+					gda_value_set_timestamp (value, ts);
+					gda_timestamp_free (ts);
+				}
+				real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
+			}
+		}
+	}
+	gda_value_free (value);
+}
+
+static void
 internal_set_time (GtkWidget *widget, GdauiEntryCommonTime *mgtim)
 {
 	/* the aim is that when the mode is TIMESTAMP, when the user sets a date,
@@ -902,6 +985,8 @@ position_popup (GdauiEntryCommonTime *mgtim)
 /*
  * callbacks for the time
  */
+static void entry_time_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data);
+
 static GtkWidget *
 create_entry_time (GdauiEntryCommonTime *mgtim)
 {
@@ -921,6 +1006,9 @@ create_entry_time (GdauiEntryCommonTime *mgtim)
 		wid = gdaui_formatted_entry_new (str, mask);
 		g_free (str);
 		g_free (mask);
+
+		gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_time_insert_func,
+						       mgtim);
 	}
 	else
 		wid = gdaui_entry_new (NULL, NULL);
@@ -932,6 +1020,41 @@ create_entry_time (GdauiEntryCommonTime *mgtim)
         return wid;
 }
 
+static void
+entry_time_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer data)
+{
+	GValue *value;
+	GType type;
+
+	type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (data));
+	value = real_get_value (GDAUI_ENTRY_WRAPPER (data));
+	if (!value)
+		return;
+
+	if ((type == GDA_TYPE_TIME) && 
+	    (insert_char == g_utf8_get_char (" "))) {
+		/* set current time */
+		gda_value_reset_with_type (value, type);
+		struct tm *ltm;
+		time_t val;
+		
+		val = time (NULL);
+		ltm = localtime ((const time_t *) &val);
+		if (ltm) {
+			GdaTime tim;
+			memset (&tim, 0, sizeof (GdaTime));
+			tim.hour = ltm->tm_hour;
+			tim.minute = ltm->tm_min;
+			tim.second = ltm->tm_sec;
+			tim.fraction = 0;
+			tim.timezone = GDA_TIMEZONE_INVALID;
+			gda_value_set_time (value, (const GdaTime *) &tim);
+			real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
+		}
+	}
+	
+	gda_value_free (value);
+}
 
 /*
  * callbacks for the timestamp
diff --git a/libgda-ui/data-entries/gdaui-entry.c b/libgda-ui/data-entries/gdaui-entry.c
index a333cd3..5eb87fd 100644
--- a/libgda-ui/data-entries/gdaui-entry.c
+++ b/libgda-ui/data-entries/gdaui-entry.c
@@ -435,6 +435,7 @@ gdaui_entry_set_text (GdauiEntry *entry, const gchar *text)
 		signal_handlers_unblock (entry);
 		ENTER_INTERNAL_CHANGES(entry);
 		gtk_entry_set_text (GTK_ENTRY (entry), text); /* emits the "insert-text" signal which is treated */
+		entry->priv->isnull = FALSE; /* in case it has not been set */
 		LEAVE_INTERNAL_CHANGES(entry);
 		g_signal_emit_by_name (entry, "changed");
 	}
diff --git a/libgda-ui/data-entries/gdaui-formatted-entry.c b/libgda-ui/data-entries/gdaui-formatted-entry.c
index c48c7e6..701a0f6 100644
--- a/libgda-ui/data-entries/gdaui-formatted-entry.c
+++ b/libgda-ui/data-entries/gdaui-formatted-entry.c
@@ -30,6 +30,9 @@ struct _GdauiFormattedEntryPrivate {
 	gint     format_clen; /* in characters, not gchar */
 	gchar   *mask; /* ASCII! */
 	gint     mask_len; /* in gchar */
+
+	GdauiFormattedEntryInsertFunc insert_func;
+	gpointer                      insert_func_data;
 };
 
 static void gdaui_formatted_entry_class_init   (GdauiFormattedEntryClass *klass);
@@ -111,6 +114,8 @@ gdaui_formatted_entry_init (GdauiFormattedEntry *entry)
 	entry->priv = g_new0 (GdauiFormattedEntryPrivate, 1);
 	entry->priv->format = NULL;
 	entry->priv->mask = NULL;
+	entry->priv->insert_func = NULL;
+	entry->priv->insert_func_data = NULL;
 }
 
 static void 
@@ -319,6 +324,8 @@ gdaui_formatted_entry_assume_insert (GdauiEntry *entry, const gchar *text, gint
 		return;
 
 	_gdaui_entry_block_changes (entry);
+	gboolean inserted = FALSE;
+	gunichar wc;
 	for (ptr = text, i = 0; ptr && *ptr && *fptr; ptr = g_utf8_next_char (ptr)) {
 		while ((pos < fentry->priv->format_clen) &&
 		       !is_writable (fentry, pos, fptr)) {
@@ -328,7 +335,6 @@ gdaui_formatted_entry_assume_insert (GdauiEntry *entry, const gchar *text, gint
 			pos++;
 		}
 		
-		gunichar wc;
 		wc = g_utf8_get_char (ptr);
 		if ((pos < fentry->priv->format_clen) &&
 		    is_allowed (fentry, fptr, wc, &wc)){
@@ -340,12 +346,21 @@ gdaui_formatted_entry_assume_insert (GdauiEntry *entry, const gchar *text, gint
 			usize = g_unichar_to_utf8 (wc, buf);
 			gtk_editable_delete_text ((GtkEditable*) entry, rpos, rpos + 1);
 			gtk_editable_insert_text ((GtkEditable*) entry, buf, usize, &rpos);
+			inserted = TRUE;
 			pos++;
 			fptr = g_utf8_next_char (fptr);
 		}
 	}
 	_gdaui_entry_unblock_changes (entry);
 	*virt_pos = pos;
+
+	if (!inserted && fentry->priv->insert_func) {
+		ptr = g_utf8_next_char (text);
+		if (!*ptr) {
+			wc = g_utf8_get_char (text);
+			fentry->priv->insert_func (fentry, wc, *virt_pos, fentry->priv->insert_func_data);
+		}
+	}
 }
 
 static void
@@ -488,3 +503,22 @@ gdaui_formatted_entry_get_text (GdauiFormattedEntry *entry)
 
 	return text;
 }
+
+/**
+ * gdaui_formatted_entry_set_insert_func
+ * @entry: a #GdauiFormattedEntry widget
+ * @insert_func: a #GdauiFormattedEntryInsertFunc, or %NULL
+ * @data: a pointer which will be passed to @insert_func
+ *
+ * Specifies that @entry should call @insert_func when the user wants to insert a char
+ * which is anot allowed, to perform other actions
+ */
+void
+gdaui_formatted_entry_set_insert_func (GdauiFormattedEntry *entry, GdauiFormattedEntryInsertFunc insert_func,
+				       gpointer data)
+{
+	g_return_val_if_fail (GDAUI_IS_FORMATTED_ENTRY (entry), NULL);
+
+	entry->priv->insert_func = insert_func;
+	entry->priv->insert_func_data = data;
+}
diff --git a/libgda-ui/data-entries/gdaui-formatted-entry.h b/libgda-ui/data-entries/gdaui-formatted-entry.h
index 9c869d1..3fd7183 100644
--- a/libgda-ui/data-entries/gdaui-formatted-entry.h
+++ b/libgda-ui/data-entries/gdaui-formatted-entry.h
@@ -52,6 +52,12 @@ GType                 gdaui_formatted_entry_get_type           (void) G_GNUC_CON
 GtkWidget            *gdaui_formatted_entry_new                (const gchar *format, const gchar *mask);
 gchar                *gdaui_formatted_entry_get_text           (GdauiFormattedEntry *entry);
 
+typedef void (*GdauiFormattedEntryInsertFunc) (GdauiFormattedEntry *entry, gunichar insert_char,
+					       gint virt_pos, gpointer data);
+void                  gdaui_formatted_entry_set_insert_func    (GdauiFormattedEntry *entry,
+								GdauiFormattedEntryInsertFunc insert_func,
+								gpointer data);
+
 G_END_DECLS
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]