From 14e071507d45f1c1668ddf569b0f285e21ea36b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 Mar 2011 18:45:51 +0100 Subject: abrt-gui: add inotify-based reloading of dumps Signed-off-by: Denys Vlasenko --- src/gui-gtk/abrt-gtk.c | 37 ++++++++++++++++++------ src/gui-gtk/abrt-gtk.h | 5 +++- src/gui-gtk/main.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 9 deletions(-) (limited to 'src/gui-gtk') diff --git a/src/gui-gtk/abrt-gtk.c b/src/gui-gtk/abrt-gtk.c index ff8575fe..2a52e433 100644 --- a/src/gui-gtk/abrt-gtk.c +++ b/src/gui-gtk/abrt-gtk.c @@ -23,7 +23,7 @@ #include "abrt-gtk.h" #include "libreport-gtk.h" -static const char * const help_uri ="http://docs.fedoraproject.org/en-US/" +static const char help_uri[] = "http://docs.fedoraproject.org/en-US/" "Fedora/14/html/Deployment_Guide/ch-abrt.html"; static GtkListStore *s_dumps_list_store; @@ -84,6 +84,12 @@ void add_directory_to_dirlist(const char *dirname) VERB1 log("added: %s", dirname); } +void rescan_dirs_and_add_to_dirlist(void) +{ + gtk_list_store_clear(s_dumps_list_store); + scan_dirs_and_add_to_dirlist(); +} + /* create_main_window and helpers */ @@ -143,8 +149,7 @@ static void delete_report(GtkTreeView *treeview) { /* Strange. Deletion did not succeed. Someone else deleted it? * Rescan the whole list */ - gtk_list_store_clear(s_dumps_list_store); - scan_dirs_and_add_to_dirlist(); + rescan_dirs_and_add_to_dirlist(); } /* Try to retain the same cursor position */ @@ -183,9 +188,9 @@ static void on_menu_help_cb(GtkMenuItem *menuitem, gpointer unused) static void on_menu_about_cb(GtkMenuItem *menuitem, gpointer unused) { - const char *copyright_str = "Copyright © 2009, 2010, 2011 Red Hat, Inc"; + static const char copyright_str[] = "Copyright © 2009, 2010, 2011 Red Hat, Inc"; - const char *license_str = "This program is free software; you can redistribut" + static const char license_str[] = "This program is free software; you can redistribut" "e it and/or modify it under the terms of the GNU General Public License " "as published by the Free Software Foundation; either version 2 of the Li" "cense, or (at your option) any later version.\n\nThis program is distrib" @@ -195,9 +200,9 @@ static void on_menu_about_cb(GtkMenuItem *menuitem, gpointer unused) "u should have received a copy of the GNU General Public License along wi" "th this program. If not, see ."; - const char *website_url = "https://fedorahosted.org/abrt/"; + static const char website_url[] = "https://fedorahosted.org/abrt/"; - const char *authors[] = { + static const char *authors[] = { "Anton Arapov ", "Karel Klic ", "Jiri Moskovcak ", @@ -208,7 +213,7 @@ static void on_menu_about_cb(GtkMenuItem *menuitem, gpointer unused) NULL }; - const char *artists[] = { + static const char *artists[] = { "Patrick Connelly ", "Máirín Duffy ", "Lapo Calamandrei", @@ -413,6 +418,22 @@ GtkWidget *create_main_window(void) return g_main_window; } +GtkTreePath *get_cursor(void) +{ + GtkTreeView *treeview = GTK_TREE_VIEW(s_treeview); + GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); + if (selection) + { + GtkTreeIter iter; + GtkTreeModel *store = gtk_tree_view_get_model(treeview); + if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE) + { + return gtk_tree_model_get_path(store, &iter); + } + } + return NULL; +} + void sanitize_cursor(GtkTreePath *preferred_path) { GtkTreePath *path; diff --git a/src/gui-gtk/abrt-gtk.h b/src/gui-gtk/abrt-gtk.h index 5dccc991..259797fa 100644 --- a/src/gui-gtk/abrt-gtk.h +++ b/src/gui-gtk/abrt-gtk.h @@ -18,6 +18,9 @@ */ GtkWidget *create_main_window(void); void add_directory_to_dirlist(const char *dirname); +/* May return NULL */ +GtkTreePath *get_cursor(void); void sanitize_cursor(GtkTreePath *preferred_path); +void rescan_dirs_and_add_to_dirlist(void); -void scan_dirs_and_add_to_dirlist(); +void scan_dirs_and_add_to_dirlist(void); diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c index fd1e9d57..10a15af4 100644 --- a/src/gui-gtk/main.c +++ b/src/gui-gtk/main.c @@ -17,6 +17,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include +#include #include "abrtlib.h" #include "parse_options.h" #include "abrt-gtk.h" @@ -26,8 +27,66 @@ #define PROGNAME "abrt-gtk" +static int inotify_fd = -1; +static GIOChannel *channel_inotify; +static int channel_inotify_event_id = -1; static char **s_dirs; +static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused); + +static void init_notify(void) +{ + VERB1 log("Initializing inotify"); + errno = 0; + inotify_fd = inotify_init(); + if (inotify_fd < 0) + perror_msg("inotify_init failed"); + else + { + close_on_exec_on(inotify_fd); + VERB1 log("Adding inotify watch to glib main loop"); + channel_inotify = g_io_channel_unix_new(inotify_fd); + channel_inotify_event_id = g_io_add_watch(channel_inotify, + G_IO_IN, + handle_inotify_cb, + NULL); + } +} + +static void close_notify(void) +{ + //VERB1 log("g_source_remove:"); + g_source_remove(channel_inotify_event_id); + //VERB1 log("g_io_channel_unref:"); + g_io_channel_unref(channel_inotify); + //VERB1 log("close(inotify_fd):"); + close(inotify_fd); + //VERB1 log("Done"); +} + +/* Inotify handler */ +static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) +{ + GtkTreePath *old_path = get_cursor(); + //log("old_path1:'%s'", gtk_tree_path_to_string(old_path)); //leak + + /* We don't bother reading inotify fd. We simply close and reopen it. + * This happens rarely enough to not bother making it efficient. + */ + close_notify(); + init_notify(); + + rescan_dirs_and_add_to_dirlist(); + + /* Try to restore cursor position */ + //log("old_path2:'%s'", gtk_tree_path_to_string(old_path)); //leak + sanitize_cursor(old_path); + if (old_path) + gtk_tree_path_free(old_path); + + return TRUE; /* "please don't remove this event" */ +} + static void scan_directory_and_add_to_dirlist(const char *path) { DIR *dp = opendir(path); @@ -51,6 +110,21 @@ static void scan_directory_and_add_to_dirlist(const char *path) free(full_name); } closedir(dp); + + if (inotify_fd >= 0 && inotify_add_watch(inotify_fd, path, 0 + // | IN_ATTRIB // Metadata changed + // | IN_CLOSE_WRITE // File opened for writing was closed + | IN_CREATE // File/directory created in watched directory + | IN_DELETE // File/directory deleted from watched directory + | IN_DELETE_SELF // Watched file/directory was itself deleted + | IN_MODIFY // File was modified + | IN_MOVE_SELF // Watched file/directory was itself moved + | IN_MOVED_FROM // File moved out of watched directory + | IN_MOVED_TO // File moved into watched directory + ) < 0) + { + perror_msg("inotify_add_watch failed on '%s'", path); + } } void scan_dirs_and_add_to_dirlist(void) @@ -110,6 +184,8 @@ int main(int argc, char **argv) } s_dirs = argv; + init_notify(); + scan_dirs_and_add_to_dirlist(); gtk_widget_show_all(main_window); -- cgit