[almanah] Made adding definitions case-insensitive



commit 04dd158392d331c2ac206859e2a005277e53482c
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun May 3 17:01:33 2009 +0100

    Made adding definitions case-insensitive
    
    When adding a definition, pre-existing definitions can populate the Add
    Definition dialogue even if they differ in case to what's been typed.
    Definitions are still stored with their original case in the database.
---
 src/definition-manager-window.c |   53 ++++++++++++++++++++++++++++++++++++++-
 src/main-window.c               |    2 +-
 src/storage-manager.c           |   28 +++++++++++++++++++-
 3 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/src/definition-manager-window.c b/src/definition-manager-window.c
index 05f3fd8..821a046 100644
--- a/src/definition-manager-window.c
+++ b/src/definition-manager-window.c
@@ -32,6 +32,7 @@
 static void almanah_definition_manager_window_dispose (GObject *object);
 static void definition_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahDefinitionManagerWindow *self);
 static void definition_added_cb (AlmanahStorageManager *storage_manager, AlmanahDefinition *definition, AlmanahDefinitionManagerWindow *self);
+static void definition_modified_cb (AlmanahStorageManager *storage_manager, AlmanahDefinition *definition, AlmanahDefinitionManagerWindow *self);
 static void definition_removed_cb (AlmanahStorageManager *storage_manager, const gchar *definition_text, AlmanahDefinitionManagerWindow *self);
 static void populate_definition_store (AlmanahDefinitionManagerWindow *self);
 
@@ -162,8 +163,9 @@ almanah_definition_manager_window_new (void)
 	almanah_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "almanah_dmw_name_label_label")));
 	almanah_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "almanah_dmw_description_label_label")));
 
-	/* Get notifications about added/removed definitions from the storage manager */
+	/* Get notifications about added/modified/removed definitions from the storage manager */
 	g_signal_connect (almanah->storage_manager, "definition-added", G_CALLBACK (definition_added_cb), definition_manager_window);
+	g_signal_connect (almanah->storage_manager, "definition-modified", G_CALLBACK (definition_modified_cb), definition_manager_window);
 	g_signal_connect (almanah->storage_manager, "definition-removed", G_CALLBACK (definition_removed_cb), definition_manager_window);
 
 	/* Set up the treeview */
@@ -277,6 +279,55 @@ definition_added_cb (AlmanahStorageManager *storage_manager, AlmanahDefinition *
 			    -1);
 }
 
+static gboolean
+definition_modified_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer *user_data)
+{
+	gchar *definition_text;
+
+	/* As we haven't yet found the right row, *user_data will be the definition text to find. We need
+	 * to set *user_data to the correct iter once we've found the right row. */
+	gtk_tree_model_get (model, iter, 1, &definition_text, -1);
+	if (strcmp (definition_text, *user_data) == 0) {
+		*user_data = iter;
+		g_free (definition_text);
+		return TRUE;
+	}
+
+	g_free (definition_text);
+	return FALSE;
+}
+
+static void
+definition_modified_cb (AlmanahStorageManager *storage_manager, AlmanahDefinition *definition, AlmanahDefinitionManagerWindow *self)
+{
+	AlmanahDefinitionManagerWindowPrivate *priv = self->priv;
+	GtkTreeIter iter;
+	gpointer user_data;
+	AlmanahDefinition *original_definition;
+
+	/* Find the old definition */
+	user_data = (gpointer) almanah_definition_get_text (definition);
+	gtk_tree_model_foreach (GTK_TREE_MODEL (priv->definition_store), (GtkTreeModelForeachFunc) definition_modified_foreach_cb, &user_data);
+
+	if (user_data == almanah_definition_get_text (definition)) {
+		g_warning ("Couldn't find definition row in tree to modify it.");
+		return;
+	}
+
+	iter = *((GtkTreeIter*) user_data);
+
+	/* Make sure we get a reference to the new definition and drop the reference to the old one */
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->definition_store), &iter, 0, &original_definition, -1);
+	g_object_ref (definition);
+	g_object_unref (original_definition);
+
+	/* Update the definition */
+	gtk_list_store_set (priv->definition_store, &iter,
+			    0, definition,
+			    1, almanah_definition_get_text (definition),
+			    -1);
+}
+
 static void
 definition_removed_cb (AlmanahStorageManager *storage_manager, const gchar *definition_text, AlmanahDefinitionManagerWindow *self)
 {
diff --git a/src/main-window.c b/src/main-window.c
index 48e7470..0b0f83a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -580,7 +580,7 @@ mw_entry_buffer_cursor_position_cb (GObject *object, GParamSpec *pspec, AlmanahM
 		} else if (action != NULL) {
 			/* Force the toggle status on the action */
 			gtk_toggle_action_set_active (action, TRUE);
-		} else {
+		} else if (strcmp (tag_name, "gtkspell-misspelled") != 0) {
 			/* Print a warning about the unknown tag */
 			g_warning (_("Unknown or duplicate text tag \"%s\" in entry. Ignoring."), tag_name);
 		}
diff --git a/src/storage-manager.c b/src/storage-manager.c
index eebb10f..4b095dd 100644
--- a/src/storage-manager.c
+++ b/src/storage-manager.c
@@ -52,6 +52,7 @@ enum {
 enum {
 	SIGNAL_DISCONNECTED,
 	SIGNAL_DEFINITION_ADDED,
+	SIGNAL_DEFINITION_MODIFIED,
 	SIGNAL_DEFINITION_REMOVED,
 	LAST_SIGNAL
 };
@@ -96,6 +97,12 @@ almanah_storage_manager_class_init (AlmanahStorageManagerClass *klass)
 				0, NULL, NULL,
 				g_cclosure_marshal_VOID__OBJECT,
 				G_TYPE_NONE, 1, ALMANAH_TYPE_DEFINITION);
+	storage_manager_signals[SIGNAL_DEFINITION_MODIFIED] = g_signal_new ("definition-modified",
+				G_TYPE_FROM_CLASS (klass),
+				G_SIGNAL_RUN_LAST,
+				0, NULL, NULL,
+				g_cclosure_marshal_VOID__OBJECT,
+				G_TYPE_NONE, 1, ALMANAH_TYPE_DEFINITION);
 	storage_manager_signals[SIGNAL_DEFINITION_REMOVED] = g_signal_new ("definition-removed",
 				G_TYPE_FROM_CLASS (klass),
 				G_SIGNAL_RUN_LAST,
@@ -965,13 +972,15 @@ almanah_storage_manager_get_definitions (AlmanahStorageManager *self)
 	return definitions;
 }
 
+/* Note: this function is case-insensitive, unless the definition text contains Unicode characters
+ * beyond the ASCII range. This is an SQLite bug: http://sqlite.org/lang_expr.html#like */
 AlmanahDefinition *
 almanah_storage_manager_get_definition (AlmanahStorageManager *self, const gchar *definition_text)
 {
 	AlmanahQueryResults *results;
 	AlmanahDefinition *definition;
 
-	results = almanah_storage_manager_query (self, "SELECT definition_type, definition_value, definition_value2, definition_text FROM definitions WHERE definition_text = '%q' LIMIT 1", NULL,
+	results = almanah_storage_manager_query (self, "SELECT definition_type, definition_value, definition_value2, definition_text FROM definitions WHERE definition_text LIKE '%q' LIMIT 1", NULL,
 						 definition_text);
 
 	if (results == NULL || results->rows == 0) {
@@ -996,12 +1005,22 @@ almanah_storage_manager_add_definition (AlmanahStorageManager *self, AlmanahDefi
 	gboolean return_value;
 	const gchar *value, *value2, *text;
 	AlmanahDefinitionType type_id;
+	AlmanahDefinition *real_definition;
 
 	type_id = almanah_definition_get_type_id (definition);
 	value = almanah_definition_get_value (definition);
 	value2 = almanah_definition_get_value2 (definition);
 	text = almanah_definition_get_text (definition);
 
+	/* Check to see if there's already a definition for this text (case-insensitively), and
+	 * use its (correctly-cased) definition text instead of ours */
+	real_definition = almanah_storage_manager_get_definition (self, text);
+	if (real_definition != NULL) {
+		text = almanah_definition_get_text (real_definition);
+		almanah_definition_set_text (definition, text);
+	}
+
+	/* Update/Insert the definition */
 	if (value2 == NULL) {
 		return_value = almanah_storage_manager_query_async (self, "REPLACE INTO definitions (definition_type, definition_value, definition_text) VALUES (%u, '%q', '%q')", NULL, NULL, NULL,
 								    type_id,
@@ -1015,7 +1034,12 @@ almanah_storage_manager_add_definition (AlmanahStorageManager *self, AlmanahDefi
 								    text);
 	}
 
-	if (return_value == TRUE)
+	if (real_definition != NULL)
+		g_object_unref (real_definition);
+
+	if (return_value == TRUE && real_definition != NULL)
+		g_signal_emit (self, storage_manager_signals[SIGNAL_DEFINITION_MODIFIED], 0, definition);
+	else if (return_value == TRUE)
 		g_signal_emit (self, storage_manager_signals[SIGNAL_DEFINITION_ADDED], 0, definition);
 
 	return return_value;



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