[devhelp: 2/36] book-manager: Move book event monitoring to the book object
- From: Aleksander Morgado <aleksm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [devhelp: 2/36] book-manager: Move book event monitoring to the book object
- Date: Mon, 20 Dec 2010 14:31:35 +0000 (UTC)
commit 11bb88448701035981f43dae758aee26c1c1136e
Author: Aleksander Morgado <aleksander lanedo com>
Date: Thu Dec 2 15:40:41 2010 +0100
book-manager: Move book event monitoring to the book object
src/dh-book-manager.c | 93 ++++++++++-----------------
src/dh-book-manager.h | 16 +++--
src/dh-book.c | 169 +++++++++++++++++++++++++++++++++++++++++++++----
src/dh-book.h | 35 ++++++-----
4 files changed, 220 insertions(+), 93 deletions(-)
---
diff --git a/src/dh-book-manager.c b/src/dh-book-manager.c
index e425097..f0af2b0 100644
--- a/src/dh-book-manager.c
+++ b/src/dh-book-manager.c
@@ -223,38 +223,16 @@ book_manager_booklist_monitor_event_cb (GFileMonitor *file_monitor,
file_uri = g_file_get_uri (file);
g_debug ("CHANGED BOOKLIST DIR '%s'", file_uri);
-}
-
-static void
-book_manager_book_monitor_event_cb (GFileMonitor *file_monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- gpointer user_data)
-{
- gchar *file_uri;
-
- file_uri = g_file_get_uri (file);
-
- g_debug ("CHANGED BOOK DIR '%s'", file_uri);
- switch (event_type) {
- case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
- /* An existing file got modified */
- break;
- default:
- break;
- }
+ g_free (file_uri);
}
static void
book_manager_monitor_path (DhBookManager *book_manager,
- const gchar *path,
- gboolean is_file)
+ const gchar *path)
{
GFileMonitor *file_monitor;
GFile *file;
DhBookManagerPriv *priv;
- GError *error = NULL;
priv = GET_PRIVATE (book_manager);
@@ -266,17 +244,15 @@ book_manager_monitor_path (DhBookManager *book_manager,
return;
}
- /* Create new monitor for the given directory/file */
- file_monitor = g_file_monitor (file,
- G_FILE_MONITOR_NONE,
- NULL,
- &error);
+ /* Create new monitor for the given directory */
+ file_monitor = g_file_monitor_directory (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
if (file_monitor) {
/* Setup changed signal callback */
g_signal_connect (file_monitor, "changed",
- (is_file ?
- G_CALLBACK (book_manager_book_monitor_event_cb) :
- G_CALLBACK (book_manager_booklist_monitor_event_cb)),
+ G_CALLBACK (book_manager_booklist_monitor_event_cb),
book_manager);
/* Create HT if not already there */
@@ -292,10 +268,8 @@ book_manager_monitor_path (DhBookManager *book_manager,
g_object_ref (file),
file_monitor);
} else {
- g_warning ("Couldn't setup to monitor changes on %s '%s': %s",
- is_file ? "file" : "directory",
- path,
- error ? error->message : "unknown");
+ g_warning ("Couldn't setup to monitor changes on directory '%s'",
+ path);
}
g_object_unref (file);
@@ -318,7 +292,7 @@ book_manager_add_from_dir (DhBookManager *book_manager,
}
/* Monitor the directory for changes */
- book_manager_monitor_path (book_manager, dir_path, FALSE);
+ book_manager_monitor_path (book_manager, dir_path);
/* And iterate it */
while ((name = g_dir_read_name (dir)) != NULL) {
@@ -337,10 +311,6 @@ book_manager_add_from_dir (DhBookManager *book_manager,
/* Add book from filepath */
book_manager_add_from_filepath (book_manager,
book_path);
-
- /* Add monitor only if we actually got a valid book */
- book_manager_monitor_path (book_manager, book_dir_path, FALSE);
-
g_free (book_path);
}
g_free (book_dir_path);
@@ -396,9 +366,10 @@ book_manager_add_from_xcode_docset (DhBookManager *book_manager,
return;
}
- /* Monitor the directory for changes (if it works on MacOSX, which
- * I truly don't know if they support something like inotify */
- book_manager_monitor_path (book_manager, dir_path, FALSE);
+ /* Monitor the directory for changes (if it works on MacOSX,
+ * not sure if GIO implements GFileMonitor based on FSEvents
+ * or what */
+ book_manager_monitor_path (book_manager, dir_path);
/* And iterate it, looking for files ending with .devhelp2 */
while ((name = g_dir_read_name (dir)) != NULL) {
@@ -454,9 +425,6 @@ book_manager_add_from_filepath (DhBookManager *book_manager,
priv->books = g_list_insert_sorted (priv->books,
book,
(GCompareFunc)dh_book_cmp_by_title);
-
- /* Add monitor for the specific file */
- book_manager_monitor_path (book_manager, book_path, TRUE);
}
GList *
@@ -469,23 +437,32 @@ dh_book_manager_get_books (DhBookManager *book_manager)
DhBook *
dh_book_manager_get_book_by_name (DhBookManager *book_manager,
- const gchar *name)
+ const gchar *name)
{
- DhBook *book = NULL;
GList *l;
g_return_val_if_fail (book_manager, NULL);
- for (l = GET_PRIVATE (book_manager)->books;
- l && !book;
- l = g_list_next (l)) {
- if (g_strcmp0 (name,
- dh_book_get_name (DH_BOOK (l->data))) == 0) {
- book = l->data;
- }
- }
+ l = g_list_find_custom (GET_PRIVATE (book_manager)->books,
+ name,
+ (GCompareFunc)dh_book_cmp_by_name_str);
+
+ return l ? l->data : NULL;
+}
+
+DhBook *
+dh_book_manager_get_book_by_path (DhBookManager *book_manager,
+ const gchar *path)
+{
+ GList *l;
+
+ g_return_val_if_fail (book_manager, NULL);
+
+ l = g_list_find_custom (GET_PRIVATE (book_manager)->books,
+ path,
+ (GCompareFunc)dh_book_cmp_by_path_str);
- return book;
+ return l ? l->data : NULL;
}
void
diff --git a/src/dh-book-manager.h b/src/dh-book-manager.h
index 3fec290..13e40e6 100644
--- a/src/dh-book-manager.h
+++ b/src/dh-book-manager.h
@@ -48,13 +48,15 @@ struct _DhBookManagerClass {
void (* disabled_book_list_updated) (DhBookManager *book_manager);
};
-GType dh_book_manager_get_type (void) G_GNUC_CONST;
-DhBookManager *dh_book_manager_new (void);
-void dh_book_manager_populate (DhBookManager *book_manager);
-GList *dh_book_manager_get_books (DhBookManager *book_manager);
-DhBook *dh_book_manager_get_book_by_name (DhBookManager *book_manager,
- const gchar *name);
-void dh_book_manager_update (DhBookManager *book_manager);
+GType dh_book_manager_get_type (void) G_GNUC_CONST;
+DhBookManager *dh_book_manager_new (void);
+void dh_book_manager_populate (DhBookManager *book_manager);
+GList *dh_book_manager_get_books (DhBookManager *book_manager);
+DhBook *dh_book_manager_get_book_by_name (DhBookManager *book_manager,
+ const gchar *name);
+DhBook *dh_book_manager_get_book_by_path (DhBookManager *book_manager,
+ const gchar *path);
+void dh_book_manager_update (DhBookManager *book_manager);
G_END_DECLS
diff --git a/src/dh-book.c b/src/dh-book.c
index 179fdd2..5c54366 100644
--- a/src/dh-book.c
+++ b/src/dh-book.c
@@ -28,20 +28,33 @@
#include "dh-parser.h"
#include "dh-book.h"
+/* Timeout to wait for new events in the book so that
+ * they are merged and we don't spam unneeded signals */
+#define EVENT_MERGE_TIMEOUT_SECS 2
+
/* Structure defining basic contents to store about every book */
typedef struct {
/* File path of the book */
- gchar *path;
+ gchar *path;
/* Enable or disabled? */
- gboolean enabled;
+ gboolean enabled;
/* Book name */
- gchar *name;
+ gchar *name;
/* Book title */
- gchar *title;
+ gchar *title;
/* Generated book tree */
- GNode *tree;
+ GNode *tree;
/* Generated list of keywords in the book */
- GList *keywords;
+ GList *keywords;
+
+ /* Monitor of this specific book */
+ GFileMonitor *monitor;
+ /* Last received events */
+ gboolean is_deleted;
+ gboolean is_updated;
+ /* ID of the event source */
+ guint monitor_event_timeout_id;
+
} DhBookPriv;
G_DEFINE_TYPE (DhBook, dh_book, G_TYPE_OBJECT);
@@ -49,11 +62,16 @@ G_DEFINE_TYPE (DhBook, dh_book, G_TYPE_OBJECT);
#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
(instance, DH_TYPE_BOOK, DhBookPriv)
-static void dh_book_init (DhBook *book);
-static void dh_book_class_init (DhBookClass *klass);
+static void dh_book_init (DhBook *book);
+static void dh_book_class_init (DhBookClass *klass);
+static void book_monitor_event_cb (GFileMonitor *file_monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data);
-static void unref_node_link (GNode *node,
- gpointer data);
+static void unref_node_link (GNode *node,
+ gpointer data);
static void
book_finalize (GObject *object)
@@ -77,6 +95,10 @@ book_finalize (GObject *object)
g_list_free (priv->keywords);
}
+ if (priv->monitor) {
+ g_object_unref (priv->monitor);
+ }
+
g_free (priv->title);
g_free (priv->path);
@@ -105,21 +127,26 @@ dh_book_init (DhBook *book)
priv->enabled = TRUE;
priv->tree = NULL;
priv->keywords = NULL;
+ priv->monitor = NULL;
+ priv->is_deleted = FALSE;
+ priv->is_updated = FALSE;
+ priv->monitor_event_timeout_id = 0;
}
static void
-unref_node_link (GNode *node,
- gpointer data)
+unref_node_link (GNode *node,
+ gpointer data)
{
dh_link_unref (node->data);
}
DhBook *
-dh_book_new (const gchar *book_path)
+dh_book_new (const gchar *book_path)
{
DhBookPriv *priv;
DhBook *book;
GError *error = NULL;
+ GFile *book_path_file;
g_return_val_if_fail (book_path, NULL);
@@ -150,9 +177,95 @@ dh_book_new (const gchar *book_path)
/* Setup name */
priv->name = g_strdup (dh_link_get_book_id ((DhLink *)priv->tree->data));
+ /* Setup monitor for changes */
+ book_path_file = g_file_new_for_path (book_path);
+ priv->monitor = g_file_monitor_file (book_path_file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
+ if (priv->monitor) {
+ /* Setup changed signal callback */
+ g_signal_connect (priv->monitor,
+ "changed",
+ G_CALLBACK (book_monitor_event_cb),
+ book);
+ } else {
+ g_warning ("Couldn't setup monitoring of changes in book '%s'",
+ priv->title);
+ }
+ g_object_unref (book_path_file);
+
return book;
}
+static gboolean
+book_monitor_event_timeout_cb (gpointer data)
+{
+ DhBook *book = data;
+ DhBookPriv *priv;
+
+ priv = GET_PRIVATE (book);
+
+ /* We'll get either is_deleted OR is_updated,
+ * not possible to have both or none */
+ if (priv->is_deleted) {
+ g_debug ("Book '%s' was deleted",
+ dh_book_get_title (book));
+ } else if (priv->is_updated) {
+ g_debug ("Book '%s' was updated",
+ dh_book_get_title (book));
+ } else {
+ g_warn_if_reached ();
+ }
+
+ return FALSE;
+}
+
+static void
+book_monitor_event_cb (GFileMonitor *file_monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ DhBook *book = user_data;
+ DhBookPriv *priv;
+ gboolean reset_timer = FALSE;
+
+ priv = GET_PRIVATE (book);
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CREATED:
+ /* This may happen if the file is deleted and then
+ * created right away, as we're merging events.
+ * Treat in the same way as a CHANGES_DONE_HINT, so
+ * fall through the case. */
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ priv->is_deleted = FALSE; /* Reset any previous one */
+ priv->is_updated = TRUE;
+ reset_timer = TRUE;
+ break;
+ case G_FILE_MONITOR_EVENT_DELETED:
+ priv->is_deleted = TRUE;
+ priv->is_updated = FALSE; /* Reset any previous one */
+ reset_timer = TRUE;
+ break;
+ default:
+ /* Ignore all the other events */
+ break;
+ }
+
+ /* Reset timer if any of the flags changed */
+ if (reset_timer) {
+ if (priv->monitor_event_timeout_id != 0) {
+ g_source_remove (priv->monitor_event_timeout_id);
+ }
+ priv->monitor_event_timeout_id = g_timeout_add_seconds (EVENT_MERGE_TIMEOUT_SECS,
+ book_monitor_event_timeout_cb,
+ book);
+ }
+}
+
GList *
dh_book_get_keywords (DhBook *book)
{
@@ -201,6 +314,18 @@ dh_book_get_title (DhBook *book)
return priv->title;
}
+const gchar *
+dh_book_get_path (DhBook *book)
+{
+ DhBookPriv *priv;
+
+ g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+ priv = GET_PRIVATE (book);
+
+ return priv->path;
+}
+
gboolean
dh_book_get_enabled (DhBook *book)
{
@@ -228,6 +353,15 @@ dh_book_cmp_by_path (const DhBook *a,
}
gint
+dh_book_cmp_by_path_str (const DhBook *a,
+ const gchar *b_path)
+{
+ return ((a && b_path) ?
+ g_strcmp0 (GET_PRIVATE (a)->path, b_path) :
+ -1);
+}
+
+gint
dh_book_cmp_by_name (const DhBook *a,
const DhBook *b)
{
@@ -237,6 +371,15 @@ dh_book_cmp_by_name (const DhBook *a,
}
gint
+dh_book_cmp_by_name_str (const DhBook *a,
+ const gchar *b_name)
+{
+ return ((a && b_name) ?
+ g_ascii_strcasecmp (GET_PRIVATE (a)->name, b_name) :
+ -1);
+}
+
+gint
dh_book_cmp_by_title (const DhBook *a,
const DhBook *b)
{
diff --git a/src/dh-book.h b/src/dh-book.h
index 198f2b3..c7ec7e8 100644
--- a/src/dh-book.h
+++ b/src/dh-book.h
@@ -46,21 +46,26 @@ struct _DhBookClass {
GObjectClass parent_class;
};
-GType dh_book_get_type (void) G_GNUC_CONST;
-DhBook *dh_book_new (const gchar *book_path);
-GList *dh_book_get_keywords (DhBook *book);
-GNode *dh_book_get_tree (DhBook *book);
-const gchar *dh_book_get_name (DhBook *book);
-const gchar *dh_book_get_title (DhBook *book);
-gboolean dh_book_get_enabled (DhBook *book);
-void dh_book_set_enabled (DhBook *book,
- gboolean enabled);
-gint dh_book_cmp_by_path (const DhBook *a,
- const DhBook *b);
-gint dh_book_cmp_by_name (const DhBook *a,
- const DhBook *b);
-gint dh_book_cmp_by_title (const DhBook *a,
- const DhBook *b);
+GType dh_book_get_type (void) G_GNUC_CONST;
+DhBook *dh_book_new (const gchar *book_path);
+GList *dh_book_get_keywords (DhBook *book);
+GNode *dh_book_get_tree (DhBook *book);
+const gchar *dh_book_get_name (DhBook *book);
+const gchar *dh_book_get_title (DhBook *book);
+const gchar *dh_book_get_path (DhBook *book);
+gboolean dh_book_get_enabled (DhBook *book);
+void dh_book_set_enabled (DhBook *book,
+ gboolean enabled);
+gint dh_book_cmp_by_path (const DhBook *a,
+ const DhBook *b);
+gint dh_book_cmp_by_path_str (const DhBook *a,
+ const gchar *b_path);
+gint dh_book_cmp_by_name (const DhBook *a,
+ const DhBook *b);
+gint dh_book_cmp_by_name_str (const DhBook *a,
+ const gchar *b_name);
+gint dh_book_cmp_by_title (const DhBook *a,
+ const DhBook *b);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]