background: Switch to GtkFlowBox

This is a major rework on how images are loaded and stored.
Unfortunately, this is so entangled that doing each change
as an atomic step is pretty much unfeasible.

The first major change is that BgSource now returns a GListStore
instead of a GtkListStore. This is necessary for us to bind it
to GtkFlowBox, and pretty much signals we're not using any of
the tree/icon views anymore.

Second, the thumbnail factory was moved to BgSource itself. We
only create factories for large thumbnails, so it's not needed
to handle each one of them individually.

At last, switch CcBackgroundChooser to GtkFlowBox, and adjust
the signals we connect to.
This commit is contained in:
Georges Basile Stavracas Neto 2019-05-22 16:06:02 -03:00
parent ee37d0194c
commit c64ab472b6
No known key found for this signature in database
GPG key ID: 886C17EE170D1385
7 changed files with 155 additions and 320 deletions

View file

@ -72,20 +72,11 @@ get_colors_dir (void)
static void
bg_colors_source_add_color (BgColorsSource *self,
GnomeDesktopThumbnailFactory *thumb_factory,
GtkListStore *store,
const char *color,
GtkTreeRowReference **ret_row_ref)
GListStore *store,
const char *color)
{
CcBackgroundItemFlags flags;
g_autoptr(CcBackgroundItem) item = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
cairo_surface_t *surface;
int scale_factor;
int thumbnail_height, thumbnail_width;
GtkTreeIter iter;
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (self));
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (self));
item = cc_background_item_new (NULL);
flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
@ -106,26 +97,7 @@ bg_colors_source_add_color (BgColorsSource *self,
cc_background_item_load (item, NULL);
/* insert the item into the liststore */
scale_factor = bg_source_get_scale_factor (BG_SOURCE (self));
pixbuf = cc_background_item_get_thumbnail (item,
thumb_factory,
thumbnail_width, thumbnail_height,
scale_factor);
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
gtk_list_store_insert_with_values (store, &iter, 0,
0, surface,
1, item,
-1);
cairo_surface_destroy (surface);
if (ret_row_ref)
{
GtkTreePath *path;
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
*ret_row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
gtk_tree_path_free (path);
}
g_list_store_append (store, item);
}
static void
@ -134,7 +106,7 @@ bg_colors_source_constructed (GObject *object)
BgColorsSource *self = BG_COLORS_SOURCE (object);
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
guint i;
GtkListStore *store;
GListStore *store;
g_autoptr(GKeyFile) keyfile = NULL;
g_autofree gchar *path = NULL;
@ -144,9 +116,7 @@ bg_colors_source_constructed (GObject *object)
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
for (i = 0; i < G_N_ELEMENTS (items); i++)
{
bg_colors_source_add_color (self, thumb_factory, store, items[i].pcolor, NULL);
}
bg_colors_source_add_color (self, thumb_factory, store, items[i].pcolor);
keyfile = g_key_file_new ();
path = get_colors_path ();
@ -156,9 +126,7 @@ bg_colors_source_constructed (GObject *object)
colors = g_key_file_get_string_list (keyfile, "Colors", "custom-colors", NULL, NULL);
for (i = 0; colors != NULL && colors[i] != NULL; i++)
{
bg_colors_source_add_color (self, thumb_factory, store, colors[i], NULL);
}
bg_colors_source_add_color (self, thumb_factory, store, colors[i]);
}
}
@ -167,8 +135,8 @@ bg_colors_source_add (BgColorsSource *self,
GdkRGBA *rgba,
GtkTreeRowReference **ret_row_ref)
{
g_autoptr(GnomeDesktopThumbnailFactory) thumb_factory = NULL;
GtkListStore *store;
GnomeDesktopThumbnailFactory *thumb_factory;
GListStore *store;
g_autofree gchar *c = NULL;
g_auto(GStrv) colors = NULL;
gsize len;
@ -182,10 +150,10 @@ bg_colors_source_add (BgColorsSource *self,
(int)(255*rgba->green),
(int)(255*rgba->blue));
thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
thumb_factory = bg_source_get_thumbnail_factory (BG_SOURCE (self));
store = bg_source_get_liststore (BG_SOURCE (self));
bg_colors_source_add_color (self, thumb_factory, store, c, ret_row_ref);
bg_colors_source_add_color (self, thumb_factory, store, c);
/* Save to the keyfile */
dir = get_colors_dir ();

View file

@ -45,8 +45,6 @@ struct _BgPicturesSource
CcBackgroundGriloMiner *grl_miner;
GnomeDesktopThumbnailFactory *thumb_factory;
GFileMonitor *picture_dir_monitor;
GFileMonitor *cache_dir_monitor;
@ -86,7 +84,6 @@ bg_pictures_source_dispose (GObject *object)
}
g_clear_object (&source->grl_miner);
g_clear_object (&source->thumb_factory);
G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object);
}
@ -96,8 +93,6 @@ bg_pictures_source_finalize (GObject *object)
{
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (object);
g_clear_object (&bg_source->thumb_factory);
g_clear_pointer (&bg_source->known_items, g_hash_table_destroy);
g_clear_object (&bg_source->picture_dir_monitor);
@ -116,23 +111,26 @@ bg_pictures_source_class_init (BgPicturesSourceClass *klass)
}
static void
remove_placeholder (BgPicturesSource *bg_source, CcBackgroundItem *item)
remove_placeholder (BgPicturesSource *bg_source,
CcBackgroundItem *item)
{
GtkListStore *store;
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeRowReference *row_ref;
GListStore *store;
guint i;
store = bg_source_get_liststore (BG_SOURCE (bg_source));
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
if (row_ref == NULL)
return;
path = gtk_tree_row_reference_get_path (row_ref);
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
return;
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
{
g_autoptr(CcBackgroundItem) item_n = NULL;
gtk_list_store_remove (store, &iter);
item_n = g_list_model_get_item (G_LIST_MODEL (store), i);
if (item_n == item)
{
g_list_store_remove (store, i);
break;
}
}
}
static gboolean
@ -163,6 +161,27 @@ swap_rotated_pixbuf (GdkPixbuf *pixbuf)
return tmp_pixbuf;
}
static int
sort_func (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
CcBackgroundItem *item_a;
CcBackgroundItem *item_b;
guint64 modified_a;
guint64 modified_b;
int retval;
item_a = (CcBackgroundItem *) a;
item_b = (CcBackgroundItem *) b;
modified_a = cc_background_item_get_modified (item_a);
modified_b = cc_background_item_get_modified (item_b);
retval = modified_b - modified_a;
return retval;
}
static void
picture_scaled (GObject *source_object,
GAsyncResult *res,
@ -174,10 +193,7 @@ picture_scaled (GObject *source_object,
g_autoptr(GdkPixbuf) pixbuf = NULL;
const char *software;
const char *uri;
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeRowReference *row_ref;
GtkListStore *store;
GListStore *store;
cairo_surface_t *surface = NULL;
int scale_factor;
gboolean rotation_applied;
@ -238,26 +254,8 @@ picture_scaled (GObject *source_object,
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
cc_background_item_load (item, NULL);
row_ref = g_object_get_data (G_OBJECT (item), "row-ref");
if (row_ref == NULL)
{
/* insert the item into the liststore if it did not exist */
gtk_list_store_insert_with_values (store, NULL, -1,
0, surface,
1, item,
-1);
}
else
{
path = gtk_tree_row_reference_get_path (row_ref);
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
{
/* otherwise update the thumbnail */
gtk_list_store_set (store, &iter,
0, surface,
-1);
}
}
/* insert the item into the liststore */
g_list_store_insert_sorted (store, item, sort_func, bg_source);
g_hash_table_insert (bg_source->known_items,
bg_pictures_source_get_unique_filename (uri),
@ -367,67 +365,6 @@ in_content_types (const char *content_type)
return FALSE;
}
static gboolean
in_screenshot_types (const char *content_type)
{
guint i;
for (i = 0; screenshot_types[i]; i++)
if (g_str_equal (screenshot_types[i], content_type))
return TRUE;
return FALSE;
}
static cairo_surface_t *
get_content_loading_icon (BgSource *source)
{
GtkIconTheme *theme;
g_autoptr(GtkIconInfo) icon_info = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GdkPixbuf) ret = NULL;
g_autoptr(GError) error = NULL;
int scale_factor;
cairo_surface_t *surface;
int thumbnail_height;
int thumbnail_width;
theme = gtk_icon_theme_get_default ();
icon_info = gtk_icon_theme_lookup_icon (theme,
"content-loading-symbolic",
16,
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
{
g_warning ("Failed to find placeholder icon");
return NULL;
}
pixbuf = gtk_icon_info_load_icon (icon_info, &error);
if (pixbuf == NULL)
{
g_warning ("Failed to load placeholder icon: %s", error->message);
return NULL;
}
thumbnail_height = bg_source_get_thumbnail_height (source);
thumbnail_width = bg_source_get_thumbnail_width (source);
ret = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE,
8, thumbnail_width, thumbnail_height);
gdk_pixbuf_fill (ret, 0x00000000);
/* Put the icon in the middle */
gdk_pixbuf_copy_area (pixbuf, 0, 0,
gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
ret,
(thumbnail_width - gdk_pixbuf_get_width (pixbuf)) / 2,
(thumbnail_height - gdk_pixbuf_get_height (pixbuf)) / 2);
scale_factor = bg_source_get_scale_factor (source);
surface = gdk_cairo_surface_create_from_pixbuf (ret, scale_factor, NULL);
return surface;
}
static GFile *
bg_pictures_source_get_cache_file (void)
{
@ -444,16 +381,10 @@ static gboolean
add_single_file (BgPicturesSource *bg_source,
GFile *file,
const gchar *content_type,
guint64 mtime,
GtkTreeRowReference **ret_row_ref)
guint64 mtime)
{
g_autoptr(CcBackgroundItem) item = NULL;
CcBackgroundItemFlags flags = 0;
GtkListStore *store;
GtkTreeIter iter;
GtkTreePath *path = NULL;
GtkTreeRowReference *row_ref = NULL;
cairo_surface_t *surface = NULL;
g_autofree gchar *source_uri = NULL;
g_autofree gchar *uri = NULL;
gboolean needs_download;
@ -501,25 +432,6 @@ add_single_file (BgPicturesSource *bg_source,
"source-url", source_uri,
NULL);
if (!ret_row_ref && in_screenshot_types (content_type))
goto read_file;
surface = get_content_loading_icon (BG_SOURCE (bg_source));
store = bg_source_get_liststore (BG_SOURCE (bg_source));
/* insert the item into the liststore */
gtk_list_store_insert_with_values (store, &iter, -1,
0, surface,
1, item,
-1);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
g_object_set_data_full (G_OBJECT (item), "row-ref", row_ref, (GDestroyNotify) gtk_tree_row_reference_free);
read_file:
media = g_object_get_data (G_OBJECT (file), "grl-media");
if (media == NULL)
{
@ -568,30 +480,20 @@ add_single_file (BgPicturesSource *bg_source,
retval = TRUE;
out:
if (ret_row_ref)
{
if (row_ref && retval != FALSE)
*ret_row_ref = gtk_tree_row_reference_copy (row_ref);
else
*ret_row_ref = NULL;
}
gtk_tree_path_free (path);
g_clear_pointer (&surface, cairo_surface_destroy);
return retval;
}
static gboolean
add_single_file_from_info (BgPicturesSource *bg_source,
GFile *file,
GFileInfo *info,
GtkTreeRowReference **ret_row_ref)
add_single_file_from_info (BgPicturesSource *bg_source,
GFile *file,
GFileInfo *info)
{
const gchar *content_type;
guint64 mtime;
content_type = g_file_info_get_content_type (info);
mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
return add_single_file (bg_source, file, content_type, mtime, ret_row_ref);
return add_single_file (bg_source, file, content_type, mtime);
}
static gboolean
@ -616,7 +518,7 @@ add_single_file_from_media (BgPicturesSource *bg_source,
else
mtime_unix = g_get_real_time () / G_USEC_PER_SEC;
return add_single_file (bg_source, file, content_type, (guint64) mtime_unix, NULL);
return add_single_file (bg_source, file, content_type, (guint64) mtime_unix);
}
gboolean
@ -633,7 +535,7 @@ bg_pictures_source_add (BgPicturesSource *bg_source,
if (info == NULL)
return FALSE;
retval = add_single_file_from_info (bg_source, file, info, ret_row_ref);
retval = add_single_file_from_info (bg_source, file, info);
return retval;
}
@ -642,21 +544,19 @@ gboolean
bg_pictures_source_remove (BgPicturesSource *bg_source,
const char *uri)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean cont;
GListStore *store;
gboolean retval;
guint i;
retval = FALSE;
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (bg_source)));
store = bg_source_get_liststore (BG_SOURCE (bg_source));
cont = gtk_tree_model_get_iter_first (model, &iter);
while (cont)
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++)
{
g_autoptr(CcBackgroundItem) tmp_item = NULL;
const char *tmp_uri;
gtk_tree_model_get (model, &iter, 1, &tmp_item, -1);
tmp_item = g_list_model_get_item (G_LIST_MODEL (store), i);
tmp_uri = cc_background_item_get_uri (tmp_item);
if (g_str_equal (tmp_uri, uri))
{
@ -665,11 +565,10 @@ bg_pictures_source_remove (BgPicturesSource *bg_source,
g_hash_table_insert (bg_source->known_items,
uuid, NULL);
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
g_list_store_remove (store, i);
retval = TRUE;
break;
}
cont = gtk_tree_model_iter_next (model, &iter);
}
return retval;
}
@ -726,7 +625,7 @@ file_info_async_ready (GObject *source,
file = g_file_get_child (parent, g_file_info_get_name (info));
add_single_file_from_info (bg_source, file, info, NULL);
add_single_file_from_info (bg_source, file, info);
}
g_list_foreach (files, (GFunc) g_object_unref, NULL);
@ -810,33 +709,6 @@ bg_pictures_source_is_known (BgPicturesSource *bg_source,
return GPOINTER_TO_INT (g_hash_table_lookup (bg_source->known_items, uuid));
}
static int
sort_func (GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
BgPicturesSource *bg_source)
{
g_autoptr(CcBackgroundItem) item_a = NULL;
g_autoptr(CcBackgroundItem) item_b = NULL;
guint64 modified_a;
guint64 modified_b;
int retval;
gtk_tree_model_get (model, a,
1, &item_a,
-1);
gtk_tree_model_get (model, b,
1, &item_b,
-1);
modified_a = cc_background_item_get_modified (item_a);
modified_b = cc_background_item_get_modified (item_b);
retval = modified_b - modified_a;
return retval;
}
static void
file_info_ready (GObject *object,
GAsyncResult *res,
@ -856,7 +728,7 @@ file_info_ready (GObject *object,
return;
}
add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info, NULL);
add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info);
}
static void
@ -951,7 +823,6 @@ bg_pictures_source_init (BgPicturesSource *self)
{
const gchar *pictures_path;
g_autofree gchar *cache_path = NULL;
GtkListStore *store;
self->cancellable = g_cancellable_new ();
self->known_items = g_hash_table_new_full (g_str_hash,
@ -971,21 +842,6 @@ bg_pictures_source_init (BgPicturesSource *self)
self->grl_miner = cc_background_grilo_miner_new ();
g_signal_connect_swapped (self->grl_miner, "media-found", G_CALLBACK (media_found_cb), self);
cc_background_grilo_miner_start (self->grl_miner);
self->thumb_factory =
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
store = bg_source_get_liststore (BG_SOURCE (self));
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
1,
(GtkTreeIterCompareFunc)sort_func,
self,
NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
1,
GTK_SORT_ASCENDING);
}
BgPicturesSource *

View file

@ -28,7 +28,8 @@
typedef struct
{
GtkListStore *store;
GnomeDesktopThumbnailFactory *thumbnail_factory;
GListStore *store;
GtkWidget *widget;
gint thumbnail_height;
gint thumbnail_width;
@ -116,6 +117,7 @@ bg_source_dispose (GObject *object)
BgSource *source = BG_SOURCE (object);
BgSourcePrivate *priv = bg_source_get_instance_private (source);
g_clear_object (&priv->thumbnail_factory);
g_clear_object (&priv->store);
G_OBJECT_CLASS (bg_source_parent_class)->dispose (object);
@ -135,7 +137,7 @@ bg_source_class_init (BgSourceClass *klass)
pspec = g_param_spec_object ("liststore",
"Liststore",
"Liststore used in the source",
GTK_TYPE_LIST_STORE,
G_TYPE_LIST_STORE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_LISTSTORE, pspec);
@ -151,10 +153,11 @@ static void
bg_source_init (BgSource *self)
{
BgSourcePrivate *priv = bg_source_get_instance_private (self);
priv->store = gtk_list_store_new (3, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_OBJECT, G_TYPE_STRING);
priv->store = g_list_store_new (CC_TYPE_BACKGROUND_ITEM);
priv->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
}
GtkListStore*
GListStore*
bg_source_get_liststore (BgSource *source)
{
BgSourcePrivate *priv;
@ -197,3 +200,14 @@ bg_source_get_thumbnail_width (BgSource *source)
priv = bg_source_get_instance_private (source);
return priv->thumbnail_width;
}
GnomeDesktopThumbnailFactory*
bg_source_get_thumbnail_factory (BgSource *source)
{
BgSourcePrivate *priv;
g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
priv = bg_source_get_instance_private (source);
return priv->thumbnail_factory;
}

View file

@ -22,6 +22,7 @@
#define _BG_SOURCE_H
#include <gtk/gtk.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
G_BEGIN_DECLS
@ -33,7 +34,7 @@ struct _BgSourceClass
GObjectClass parent_class;
};
GtkListStore* bg_source_get_liststore (BgSource *source);
GListStore* bg_source_get_liststore (BgSource *source);
gint bg_source_get_scale_factor (BgSource *source);
@ -41,6 +42,8 @@ gint bg_source_get_thumbnail_height (BgSource *source);
gint bg_source_get_thumbnail_width (BgSource *source);
GnomeDesktopThumbnailFactory* bg_source_get_thumbnail_factory (BgSource *source);
G_END_DECLS
#endif /* _BG_SOURCE_H */

View file

@ -25,13 +25,11 @@
#include "cc-background-xml.h"
#include <cairo-gobject.h>
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include <gio/gio.h>
struct _BgWallpapersSource
{
BgSource parent_instance;
GnomeDesktopThumbnailFactory *thumb_factory;
CcBackgroundXml *xml;
};
@ -42,38 +40,15 @@ load_wallpapers (gchar *key,
CcBackgroundItem *item,
BgWallpapersSource *source)
{
GtkTreeIter iter;
g_autoptr(GdkPixbuf) pixbuf = NULL;
GtkListStore *store = bg_source_get_liststore (BG_SOURCE (source));
cairo_surface_t *surface;
GListStore *store = bg_source_get_liststore (BG_SOURCE (source));
gboolean deleted;
gint scale_factor;
gint thumbnail_height;
gint thumbnail_width;
g_object_get (G_OBJECT (item), "is-deleted", &deleted, NULL);
if (deleted)
return;
gtk_list_store_append (store, &iter);
scale_factor = bg_source_get_scale_factor (BG_SOURCE (source));
thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (source));
thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (source));
pixbuf = cc_background_item_get_thumbnail (item, source->thumb_factory,
thumbnail_width, thumbnail_height,
scale_factor);
if (pixbuf == NULL)
return;
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL);
gtk_list_store_set (store, &iter,
0, surface,
1, item,
2, cc_background_item_get_name (item),
-1);
g_clear_pointer (&surface, cairo_surface_destroy);
g_list_store_append (store, item);
}
static void
@ -136,7 +111,6 @@ bg_wallpapers_source_dispose (GObject *object)
{
BgWallpapersSource *self = BG_WALLPAPERS_SOURCE (object);
g_clear_object (&self->thumb_factory);
g_clear_object (&self->xml);
G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
@ -145,8 +119,6 @@ bg_wallpapers_source_dispose (GObject *object)
static void
bg_wallpapers_source_init (BgWallpapersSource *self)
{
self->thumb_factory =
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
self->xml = cc_background_xml_new ();
}

View file

@ -29,7 +29,7 @@ struct _CcBackgroundChooser
{
GtkBox parent;
GtkIconView *icon_view;
GtkFlowBox *flowbox;
GtkPopover *selection_popover;
BgWallpapersSource *wallpapers_source;
@ -49,42 +49,61 @@ static void
emit_background_chosen (CcBackgroundChooser *self,
CcBackgroundSelectionFlags flags)
{
g_autolist (GtkTreePath) list = NULL;
g_autoptr(GList) list = NULL;
CcBackgroundItem *item;
GtkTreeModel *model;
GtkTreeIter iter;
model = gtk_icon_view_get_model (self->icon_view);
list = gtk_icon_view_get_selected_items (self->icon_view);
list = gtk_flow_box_get_selected_children (self->flowbox);
g_assert (g_list_length (list) == 1);
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) list->data) == FALSE)
return;
gtk_tree_model_get (model, &iter, 1, &item, -1);
item = g_object_get_data (list->data, "item");
g_signal_emit (self, signals[BACKGROUND_CHOSEN], 0, item, flags);
}
static void
setup_icon_view (CcBackgroundChooser *self)
static GtkWidget*
create_widget_func (gpointer model_item,
gpointer user_data)
{
GtkCellRenderer *renderer;
GtkListStore *model;
g_autoptr(GdkPixbuf) pixbuf = NULL;
CcBackgroundChooser *self;
CcBackgroundItem *item;
GtkWidget *child;
GtkWidget *image;
model = bg_source_get_liststore (BG_SOURCE (self->wallpapers_source));
self = CC_BACKGROUND_CHOOSER (user_data);
item = CC_BACKGROUND_ITEM (model_item);
pixbuf = cc_background_item_get_thumbnail (item,
bg_source_get_thumbnail_factory (BG_SOURCE (self->wallpapers_source)),
bg_source_get_thumbnail_width (BG_SOURCE (self->wallpapers_source)),
bg_source_get_thumbnail_height (BG_SOURCE (self->wallpapers_source)),
bg_source_get_scale_factor (BG_SOURCE (self->wallpapers_source)));
image = gtk_image_new_from_pixbuf (pixbuf);
gtk_widget_show (image);
gtk_icon_view_set_model (self->icon_view, GTK_TREE_MODEL (model));
child = g_object_new (GTK_TYPE_FLOW_BOX_CHILD,
"halign", GTK_ALIGN_CENTER,
"valign", GTK_ALIGN_CENTER,
NULL);
gtk_container_add (GTK_CONTAINER (child), image);
gtk_widget_show (child);
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->icon_view),
renderer,
FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self->icon_view),
renderer,
"surface", 0,
NULL);
g_object_set_data_full (G_OBJECT (child), "item", g_object_ref (item), g_object_unref);
return child;
}
static void
setup_flowbox (CcBackgroundChooser *self)
{
GListStore *store;
store = bg_source_get_liststore (BG_SOURCE (self->wallpapers_source));
gtk_flow_box_bind_model (self->flowbox,
G_LIST_MODEL (store),
create_widget_func,
self,
NULL);
}
static void
@ -112,22 +131,11 @@ on_selection_lock_clicked_cb (GtkButton *button,
}
static void
on_selection_changed_cb (GtkIconView *icon_view,
CcBackgroundChooser *self)
{
}
static void
on_item_activated_cb (GtkIconView *icon_view,
GtkTreePath *path,
on_item_activated_cb (GtkFlowBox *flowbox,
GtkFlowBoxChild *child,
CcBackgroundChooser *self)
{
GdkRectangle rect;
g_message ("Item activated");
gtk_icon_view_get_cell_rect (icon_view, path, NULL, &rect);
gtk_popover_set_pointing_to (self->selection_popover, &rect);
gtk_popover_set_relative_to (self->selection_popover, GTK_WIDGET (child));
gtk_popover_popup (self->selection_popover);
}
@ -162,11 +170,10 @@ cc_background_chooser_class_init (CcBackgroundChooserClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-chooser.ui");
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, icon_view);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, flowbox);
gtk_widget_class_bind_template_child (widget_class, CcBackgroundChooser, selection_popover);
gtk_widget_class_bind_template_callback (widget_class, on_item_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, on_selection_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_selection_desktop_lock_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, on_selection_desktop_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, on_selection_lock_clicked_cb);
@ -178,5 +185,5 @@ cc_background_chooser_init (CcBackgroundChooser *self)
gtk_widget_init_template (GTK_WIDGET (self));
self->wallpapers_source = bg_wallpapers_source_new (GTK_WIDGET (self));
setup_icon_view (self);
setup_flowbox (self);
}

View file

@ -21,13 +21,29 @@
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkIconView" id="icon_view">
<object class="GtkBox">
<property name="visible">True</property>
<signal name="item-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
<signal name="selection-changed" handler="on_selection_changed_cb" object="CcBackgroundChooser" swapped="no" />
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="expand">True</property>
<style>
<class name="view" />
</style>
<child>
<object class="GtkFlowBox" id="flowbox">
<property name="visible">True</property>
<property name="margin">12</property>
<property name="column-spacing">12</property>
<property name="row-spacing">12</property>
<property name="homogeneous">True</property>
<property name="halign">center</property>
<property name="min-children-per-line">1</property>
<property name="max-children-per-line">8</property>
<property name="activate-on-single-click">True</property>
<property name="selection-mode">single</property>
<signal name="child-activated" handler="on_item_activated_cb" object="CcBackgroundChooser" swapped="no" />
</object>
</child>
</object>
</child>
</object>
@ -37,7 +53,6 @@
<!-- Desktop & Lock Screen Popover -->
<object class="GtkPopover" id="selection_popover">
<property name="relative-to">icon_view</property>
<property name="position">bottom</property>
<child>
<object class="GtkBox">