diff options
author | Eric Koegel <eric.koegel@gmail.com> | 2013-03-30 13:37:15 +0300 |
---|---|---|
committer | Eric Koegel <eric.koegel@gmail.com> | 2013-03-30 13:42:47 +0300 |
commit | 4d154b0614252950576b4ec49f067102f729c796 (patch) | |
tree | 918ea8645fbaad9580e824297a41c0ff7a220be2 | |
parent | 4e51013473eed4a9879267db7d48986061caddd9 (diff) | |
download | xfdesktop-4d154b0614252950576b4ec49f067102f729c796.tar.gz |
Use an async message queue to load preview images
This patch uses the g_async_queue for message passing between the
main thread and the preview thread of the settings app. Doing this
gets rid of the idle timeout callback and a seperate thread loading
function. It also makes it easy to pop any pending previews when
the app changes what the icon view should display.
-rw-r--r-- | settings/main.c | 171 |
1 files changed, 59 insertions, 112 deletions
diff --git a/settings/main.c b/settings/main.c index fab16f90..d04904fc 100644 --- a/settings/main.c +++ b/settings/main.c @@ -84,7 +84,7 @@ typedef struct { GtkTreeModel *model; - GSList *iters; + GtkTreeIter *iter; } PreviewData; typedef struct @@ -115,12 +115,10 @@ typedef struct GtkWidget *random_backdrop_order_chkbox; GThread *preview_thread; - PreviewData *pdata; + GAsyncQueue *preview_queue; XfdesktopThumbnailer *thumbnailer; - gint request_timer_id; - } AppearancePanel; enum @@ -210,87 +208,62 @@ xfdesktop_settings_do_single_preview(GtkTreeModel *model, } } -static gpointer -xfdesktop_settings_create_some_previews(gpointer data) +static void +xfdesktop_settings_free_pdata(gpointer data) { PreviewData *pdata = data; - GSList *l; - - GDK_THREADS_ENTER (); - - for(l = pdata->iters; l && l->data != NULL; l = l->next) - xfdesktop_settings_do_single_preview(pdata->model, l->data); - g_object_unref(G_OBJECT(pdata->model)); - g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL); - g_slist_free(pdata->iters); + gtk_tree_iter_free(pdata->iter); g_free(pdata); - - GDK_THREADS_LEAVE (); - - return NULL; } static gpointer -xfdesktop_settings_create_all_previews(gpointer data) +xfdesktop_settings_create_previews(gpointer data) { - GtkTreeModel *model = data; - GtkTreeView *tree_view; - GtkTreeIter iter; - - GDK_THREADS_ENTER (); + AppearancePanel *panel = data; + PreviewData *pdata = NULL; - if(gtk_tree_model_get_iter_first(model, &iter)) { - do { - xfdesktop_settings_do_single_preview(model, &iter); - } while(gtk_tree_model_iter_next(model, &iter)); - } + while(panel->preview_queue != NULL) { + pdata = g_async_queue_pop(panel->preview_queue); - /* if possible, scroll to the selected image */ - tree_view = g_object_get_data(G_OBJECT(model), "xfdesktop-tree-view"); - if(tree_view) { - GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); + GDK_THREADS_ENTER (); - if(gtk_tree_selection_get_mode(selection) != GTK_SELECTION_MULTIPLE - && gtk_tree_selection_get_selected(selection, NULL, &iter)) - { - GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, 0.0, 0.0); - } - } - g_object_set_data(G_OBJECT(model), "xfdesktop-tree-view", NULL); + xfdesktop_settings_do_single_preview(pdata->model, pdata->iter); - GDK_THREADS_LEAVE (); + xfdesktop_settings_free_pdata(pdata); - g_object_unref(G_OBJECT(model)); + GDK_THREADS_LEAVE (); + } return NULL; } static void -cb_request_timer(gpointer data) +xfdesktop_settings_add_file_to_queue(AppearancePanel *panel, PreviewData *pdata) { - AppearancePanel *panel = data; - PreviewData *pdata = panel->pdata; - TRACE("entering"); - if(pdata == NULL) - return; + g_return_if_fail(panel != NULL); + g_return_if_fail(pdata != NULL); - panel->pdata = NULL; - g_source_remove(panel->request_timer_id); - panel->request_timer_id = 0; + if(panel->preview_queue == NULL) { + panel->preview_queue = g_async_queue_new_full(xfdesktop_settings_free_pdata); + } - if(!g_thread_try_new("xfdesktop_settings_create_some_previews", - xfdesktop_settings_create_some_previews, - pdata, NULL)) - { - g_critical("Unable to create thread for image previews."); - g_object_unref(G_OBJECT(pdata->model)); - g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL); - g_slist_free(pdata->iters); - g_free(pdata); + g_async_queue_push(panel->preview_queue, pdata); + + if(panel->preview_thread == NULL) { + panel->preview_thread = g_thread_try_new("xfdesktop_settings_create_previews", + xfdesktop_settings_create_previews, + panel, NULL); + if(panel->preview_thread == NULL) + { + g_critical("Unable to create thread for image previews."); + if(g_async_queue_try_pop(panel->preview_queue)) + xfdesktop_settings_free_pdata(pdata); + + return; + } } } @@ -302,6 +275,7 @@ cb_thumbnail_ready(XfdesktopThumbnailer *thumbnailer, AppearancePanel *panel = user_data; GtkTreeModel *model = gtk_icon_view_get_model(GTK_ICON_VIEW(panel->image_iconview)); GtkTreeIter iter; + PreviewData *pdata = NULL; if(gtk_tree_model_get_iter_first(model, &iter)) { do { @@ -312,23 +286,12 @@ cb_thumbnail_ready(XfdesktopThumbnailer *thumbnailer, gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_THUMBNAIL, thumb_file, -1); - if(panel->request_timer_id != 0) { - g_source_remove(panel->request_timer_id); - } - - if(panel->pdata == NULL) { - panel->pdata = g_new0(PreviewData, 1); - panel->pdata->model = g_object_ref(G_OBJECT(model)); - } + pdata = g_new0(PreviewData, 1); + pdata->model = g_object_ref(G_OBJECT(model)); - panel->pdata->iters = g_slist_prepend(panel->pdata->iters, gtk_tree_iter_copy(&iter)); + pdata->iter = gtk_tree_iter_copy(&iter); - panel->request_timer_id = g_timeout_add_full( - G_PRIORITY_LOW, - 100, - (GSourceFunc)cb_request_timer, - panel, - NULL); + xfdesktop_settings_add_file_to_queue(panel, pdata); g_free(filename); return; @@ -339,16 +302,22 @@ cb_thumbnail_ready(XfdesktopThumbnailer *thumbnailer, } } -/* Attempts to queue a thumbnail preview */ +/* Attempts to queue a thumbnail preview, otherwise manually loads the file */ static void -xfdesktop_settings_create_thumbnail_preview(GtkTreeModel *model, - GtkTreeIter *iter, - AppearancePanel *panel) +xfdesktop_settings_create_preview(GtkTreeModel *model, + GtkTreeIter *iter, + AppearancePanel *panel) { gchar *filename; gtk_tree_model_get(model, iter, COL_FILENAME, &filename, -1); - xfdesktop_thumbnailer_queue_thumbnail(panel->thumbnailer, filename); + if(!xfdesktop_thumbnailer_queue_thumbnail(panel->thumbnailer, filename)) { + PreviewData *pdata; + pdata = g_new0(PreviewData, 1); + pdata->model = g_object_ref(G_OBJECT(model)); + pdata->iter = gtk_tree_iter_copy(iter); + xfdesktop_settings_add_file_to_queue(panel, pdata); + } } static void @@ -520,7 +489,7 @@ xfdesktop_settings_image_iconview_add(GtkTreeModel *model, COL_COLLATE_KEY, lower, -1); - xfdesktop_settings_create_thumbnail_preview(model, &iter, panel); + xfdesktop_settings_create_preview(model, &iter, panel); added = TRUE; } @@ -790,21 +759,13 @@ xfdesktop_settings_stop_image_loading(AppearancePanel *panel) /* stop any thumbnailing in progress */ xfdesktop_thumbnailer_dequeue_all_thumbnails(panel->thumbnailer); - /* Remove any pending thumbnail updates */ - if(panel->request_timer_id != 0) { - PreviewData *pdata = panel->pdata; - g_source_remove(panel->request_timer_id); - panel->request_timer_id = 0; - g_object_unref(G_OBJECT(pdata->model)); - g_slist_foreach(pdata->iters, (GFunc)gtk_tree_iter_free, NULL); - g_slist_free(pdata->iters); - g_free(pdata); - } - - /* Remove any preview threads that may still be running */ - if(panel->preview_thread != NULL) { - g_thread_unref(panel->preview_thread); - panel->preview_thread = NULL; + /* Remove the previews in the message queue */ + if(panel->preview_queue != NULL) { + while(g_async_queue_length(panel->preview_queue) > 0) { + gpointer data = g_async_queue_try_pop(panel->preview_queue); + if(data) + xfdesktop_settings_free_pdata(data); + } } } @@ -866,20 +827,6 @@ cb_folder_selection_changed(GtkWidget *button, } } - /* Thumbnailer not available, fallback to loading the images in a thread */ - if(!xfdesktop_thumbnailer_service_available(panel->thumbnailer)) { - /* generate previews of each image -- the new thread will own - * the reference on the list store, so let's not unref it here */ - panel->preview_thread = g_thread_try_new("xfdesktop_settings_create_all_previews", - xfdesktop_settings_create_all_previews, - ls, NULL); - - if(panel->preview_thread == NULL) { - g_critical("Failed to spawn thread; backdrop previews will be unavailable."); - g_object_unref(G_OBJECT(ls)); - } - } - g_free(property); } |