1
/* bg-pictures-source.c */
3
* Copyright (C) 2010 Intel, Inc
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* Author: Thomas Wood <thomas.wood@intel.com>
23
#include "bg-pictures-source.h"
25
#include "cc-background-item.h"
29
#include <libgnome-desktop/gnome-desktop-thumbnail.h>
30
#include <gdesktop-enums.h>
32
G_DEFINE_TYPE (BgPicturesSource, bg_pictures_source, BG_TYPE_SOURCE)
34
#define PICTURES_SOURCE_PRIVATE(o) \
35
(G_TYPE_INSTANCE_GET_PRIVATE ((o), BG_TYPE_PICTURES_SOURCE, BgPicturesSourcePrivate))
37
#define ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_NAME "," \
38
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
40
struct _BgPicturesSourcePrivate
42
GCancellable *cancellable;
44
GnomeDesktopThumbnailFactory *thumb_factory;
46
GHashTable *known_items;
49
static char *bg_pictures_source_get_unique_filename (const char *uri);
52
bg_pictures_source_get_property (GObject *object,
60
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
65
bg_pictures_source_set_property (GObject *object,
73
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
78
bg_pictures_source_dispose (GObject *object)
80
BgPicturesSourcePrivate *priv = BG_PICTURES_SOURCE (object)->priv;
82
if (priv->cancellable)
84
g_cancellable_cancel (priv->cancellable);
85
g_object_unref (priv->cancellable);
86
priv->cancellable = NULL;
89
if (priv->thumb_factory)
91
g_object_unref (priv->thumb_factory);
92
priv->thumb_factory = NULL;
95
G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object);
99
bg_pictures_source_finalize (GObject *object)
101
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (object);
103
if (bg_source->priv->thumb_factory)
105
g_object_unref (bg_source->priv->thumb_factory);
106
bg_source->priv->thumb_factory = NULL;
109
if (bg_source->priv->known_items)
111
g_hash_table_destroy (bg_source->priv->known_items);
112
bg_source->priv->known_items = NULL;
115
G_OBJECT_CLASS (bg_pictures_source_parent_class)->finalize (object);
119
bg_pictures_source_class_init (BgPicturesSourceClass *klass)
121
GObjectClass *object_class = G_OBJECT_CLASS (klass);
123
g_type_class_add_private (klass, sizeof (BgPicturesSourcePrivate));
125
object_class->get_property = bg_pictures_source_get_property;
126
object_class->set_property = bg_pictures_source_set_property;
127
object_class->dispose = bg_pictures_source_dispose;
128
object_class->finalize = bg_pictures_source_finalize;
132
picture_scaled (GObject *source_object,
136
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (user_data);
137
CcBackgroundItem *item;
138
GError *error = NULL;
140
const char *source_url;
145
store = bg_source_get_liststore (BG_SOURCE (bg_source));
146
item = g_object_get_data (source_object, "item");
148
pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
151
g_warning ("Failed to load image: %s", error->message);
152
g_error_free (error);
153
g_object_unref (item);
157
/* insert the item into the liststore */
158
gtk_list_store_insert_with_values (store, &iter, 0,
162
source_url = cc_background_item_get_source_url (item);
163
if (source_url != NULL)
165
g_hash_table_insert (bg_source->priv->known_items,
166
bg_pictures_source_get_unique_filename (source_url), GINT_TO_POINTER (TRUE));
171
GFile *file, *parent, *dir;
173
cache_path = bg_pictures_source_get_cache_path ();
174
dir = g_file_new_for_path (cache_path);
177
file = g_file_new_for_uri (cc_background_item_get_uri (item));
178
parent = g_file_get_parent (file);
180
if (g_file_equal (parent, dir))
183
basename = g_file_get_basename (file);
184
g_hash_table_insert (bg_source->priv->known_items,
185
basename, GINT_TO_POINTER (TRUE));
187
g_object_unref (file);
188
g_object_unref (parent);
191
g_object_unref (pixbuf);
195
picture_opened_for_read (GObject *source_object,
199
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (user_data);
200
CcBackgroundItem *item;
201
GFileInputStream *stream;
202
GError *error = NULL;
204
item = g_object_get_data (source_object, "item");
205
stream = g_file_read_finish (G_FILE (source_object), res, &error);
210
filename = g_file_get_path (G_FILE (source_object));
211
g_warning ("Failed to load picture '%s': %s", filename, error->message);
213
g_error_free (error);
214
g_object_unref (item);
218
g_object_set_data (G_OBJECT (stream), "item", item);
220
gdk_pixbuf_new_from_stream_at_scale_async (G_INPUT_STREAM (stream),
221
THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT,
224
picture_scaled, bg_source);
225
g_object_unref (stream);
229
add_single_file (BgPicturesSource *bg_source,
232
const char *source_uri)
234
const gchar *content_type;
236
/* find png and jpeg files */
237
content_type = g_file_info_get_content_type (info);
242
if (g_str_equal ("image/png", content_type) ||
243
g_str_equal ("image/jpeg", content_type))
245
CcBackgroundItem *item;
248
/* create a new CcBackgroundItem */
249
uri = g_file_get_uri (file);
250
item = cc_background_item_new (uri);
252
g_object_set (G_OBJECT (item),
253
"flags", CC_BACKGROUND_ITEM_HAS_URI | CC_BACKGROUND_ITEM_HAS_SHADING,
254
"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
255
"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
257
if (source_uri != NULL)
258
g_object_set (G_OBJECT (item), "source-url", source_uri, NULL);
260
g_object_set_data (G_OBJECT (file), "item", item);
261
g_file_read_async (file, 0, NULL, picture_opened_for_read, bg_source);
262
g_object_unref (file);
270
bg_pictures_source_add (BgPicturesSource *bg_source,
277
file = g_file_new_for_uri (uri);
278
info = g_file_query_info (file, ATTRIBUTES, G_FILE_QUERY_INFO_NONE, NULL, NULL);
282
retval = add_single_file (bg_source, file, info, uri);
288
bg_pictures_source_remove (BgPicturesSource *bg_source,
289
CcBackgroundItem *item)
298
model = GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (bg_source)));
299
uri = cc_background_item_get_uri (item);
301
cont = gtk_tree_model_get_iter_first (model, &iter);
304
CcBackgroundItem *tmp_item;
307
gtk_tree_model_get (model, &iter, 1, &tmp_item, -1);
308
tmp_uri = cc_background_item_get_uri (tmp_item);
309
if (g_str_equal (tmp_uri, uri))
314
file = g_file_new_for_uri (uri);
315
uuid = g_file_get_basename (file);
316
g_hash_table_insert (bg_source->priv->known_items,
319
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
321
g_file_trash (file, NULL, NULL);
322
g_object_unref (file);
325
g_object_unref (tmp_item);
326
cont = gtk_tree_model_iter_next (model, &iter);
332
file_info_async_ready (GObject *source,
336
BgPicturesSource *bg_source = BG_PICTURES_SOURCE (user_data);
340
files = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
346
g_warning ("Could not get pictures file information: %s", err->message);
349
g_list_foreach (files, (GFunc) g_object_unref, NULL);
354
parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
356
/* iterate over the available files */
357
for (l = files; l; l = g_list_next (l))
359
GFileInfo *info = l->data;
362
file = g_file_get_child (parent, g_file_info_get_name (info));
364
add_single_file (bg_source, file, info, NULL);
367
g_list_foreach (files, (GFunc) g_object_unref, NULL);
372
dir_enum_async_ready (GObject *source,
376
BgPicturesSourcePrivate *priv = BG_PICTURES_SOURCE (user_data)->priv;
377
GFileEnumerator *enumerator;
380
enumerator = g_file_enumerate_children_finish (G_FILE (source), res, &err);
384
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) == FALSE)
385
g_warning ("Could not fill pictures source: %s", err->message);
391
g_file_enumerator_next_files_async (enumerator,
395
file_info_async_ready,
400
bg_pictures_source_get_cache_path (void)
402
return g_build_filename (g_get_user_cache_dir (),
403
"gnome-control-center",
409
bg_pictures_source_get_unique_filename (const char *uri)
414
csum = g_checksum_new (G_CHECKSUM_SHA256);
415
g_checksum_update (csum, (guchar *) uri, -1);
416
ret = g_strdup (g_checksum_get_string (csum));
417
g_checksum_free (csum);
423
bg_pictures_source_get_unique_path (const char *uri)
425
GFile *parent, *file;
430
cache_path = bg_pictures_source_get_cache_path ();
431
parent = g_file_new_for_path (cache_path);
434
filename = bg_pictures_source_get_unique_filename (uri);
435
file = g_file_get_child (parent, filename);
437
ret = g_file_get_path (file);
438
g_object_unref (file);
444
bg_pictures_source_is_known (BgPicturesSource *bg_source,
450
uuid = bg_pictures_source_get_unique_filename (uri);
451
retval = (GPOINTER_TO_INT (g_hash_table_lookup (bg_source->priv->known_items, uuid)));
458
bg_pictures_source_init (BgPicturesSource *self)
460
const gchar *pictures_path;
461
BgPicturesSourcePrivate *priv;
465
priv = self->priv = PICTURES_SOURCE_PRIVATE (self);
467
priv->cancellable = g_cancellable_new ();
468
priv->known_items = g_hash_table_new_full (g_str_hash,
470
(GDestroyNotify) g_free,
473
pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
474
dir = g_file_new_for_path (pictures_path);
475
g_file_enumerate_children_async (dir,
477
G_FILE_QUERY_INFO_NONE,
478
G_PRIORITY_LOW, priv->cancellable,
479
dir_enum_async_ready, self);
480
g_object_unref (dir);
482
cache_path = bg_pictures_source_get_cache_path ();
483
dir = g_file_new_for_path (cache_path);
484
g_file_enumerate_children_async (dir,
486
G_FILE_QUERY_INFO_NONE,
487
G_PRIORITY_LOW, priv->cancellable,
488
dir_enum_async_ready, self);
489
g_object_unref (dir);
491
priv->thumb_factory =
492
gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
496
bg_pictures_source_new (void)
498
return g_object_new (BG_TYPE_PICTURES_SOURCE, NULL);