1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2010-2011 Red Hat, 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, see <http://www.gnu.org/licenses/>.
27
#include <glib/gi18n-lib.h>
29
#include <libgnome-desktop/gnome-bg.h>
30
#include <gdesktop-enums.h>
32
#include "cc-appearance-item.h"
33
#include "gdesktop-enums-types.h"
35
#define CC_APPEARANCE_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_APPEARANCE_ITEM, CcAppearanceItemPrivate))
37
struct CcAppearanceItemPrivate
43
GDesktopBackgroundStyle placement;
44
GDesktopBackgroundShading shading;
46
char *secondary_color;
47
char *source_url; /* Used by the Flickr source */
48
char *source_xml; /* Used by the Wallpapers source */
50
gboolean needs_download;
51
CcAppearanceItemFlags flags;
76
static void cc_appearance_item_class_init (CcAppearanceItemClass *klass);
77
static void cc_appearance_item_init (CcAppearanceItem *appearance_item);
78
static void cc_appearance_item_finalize (GObject *object);
80
G_DEFINE_TYPE (CcAppearanceItem, cc_appearance_item, G_TYPE_OBJECT)
83
get_slideshow_icon (void)
87
themed = g_themed_icon_new ("unity-slideshow-emblem");
88
emblem = g_emblem_new_with_origin (themed, G_EMBLEM_ORIGIN_DEVICE);
89
g_object_unref (themed);
94
set_bg_properties (CcAppearanceItem *item)
96
GdkColor pcolor = { 0, 0, 0, 0 };
97
GdkColor scolor = { 0, 0, 0, 0 };
99
if (item->priv->uri) {
103
file = g_file_new_for_commandline_arg (item->priv->uri);
104
filename = g_file_get_path (file);
105
g_object_unref (file);
107
gnome_bg_set_filename (item->priv->bg, filename);
111
if (item->priv->primary_color != NULL) {
112
gdk_color_parse (item->priv->primary_color, &pcolor);
114
if (item->priv->secondary_color != NULL) {
115
gdk_color_parse (item->priv->secondary_color, &scolor);
118
gnome_bg_set_color (item->priv->bg, item->priv->shading, &pcolor, &scolor);
119
gnome_bg_set_placement (item->priv->bg, item->priv->placement);
124
cc_appearance_item_changes_with_time (CcAppearanceItem *item)
128
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), FALSE);
131
if (item->priv->bg != NULL) {
132
changes = gnome_bg_changes_with_time (item->priv->bg);
138
update_size (CcAppearanceItem *item)
140
g_free (item->priv->size);
141
item->priv->size = NULL;
143
if (item->priv->uri == NULL) {
144
item->priv->size = g_strdup ("");
146
if (gnome_bg_has_multiple_sizes (item->priv->bg) || gnome_bg_changes_with_time (item->priv->bg)) {
147
item->priv->size = g_strdup (_("multiple sizes"));
149
/* translators: 100 Ć 100px
150
* Note that this is not an "x", but U+00D7 MULTIPLICATION SIGN */
151
item->priv->size = g_strdup_printf (_("%d \303\227 %d"),
159
render_at_size (GnomeBG *bg,
165
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
166
gnome_bg_draw (bg, pixbuf, gdk_screen_get_default (), FALSE);
172
cc_appearance_item_get_frame_thumbnail (CcAppearanceItem *item,
173
GnomeDesktopThumbnailFactory *thumbs,
179
GdkPixbuf *pixbuf = NULL;
182
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
183
g_return_val_if_fail (width > 0 && height > 0, NULL);
185
set_bg_properties (item);
188
/* FIXME: this doesn't play nice with slideshow stepping at all,
189
* because it will always render the current slideshow frame, which
190
* might not be what we want.
191
* We're lacking an API to draw a high-res GnomeBG manually choosing
192
* the slideshow frame though, so we can't do much better than this
195
pixbuf = render_at_size (item->priv->bg, width, height);
198
pixbuf = gnome_bg_create_frame_thumbnail (item->priv->bg,
200
gdk_screen_get_default (),
205
pixbuf = gnome_bg_create_thumbnail (item->priv->bg,
207
gdk_screen_get_default (),
215
&& gnome_bg_changes_with_time (item->priv->bg)) {
218
emblem = get_slideshow_icon ();
219
icon = g_emblemed_icon_new (G_ICON (pixbuf), emblem);
220
g_object_unref (emblem);
221
g_object_unref (pixbuf);
223
icon = G_ICON (pixbuf);
226
gnome_bg_get_image_size (item->priv->bg,
231
&item->priv->height);
240
cc_appearance_item_get_thumbnail (CcAppearanceItem *item,
241
GnomeDesktopThumbnailFactory *thumbs,
245
return cc_appearance_item_get_frame_thumbnail (item, thumbs, width, height, -1, FALSE);
249
update_info (CcAppearanceItem *item,
256
file = g_file_new_for_uri (item->priv->uri);
258
info = g_file_query_info (file,
259
G_FILE_ATTRIBUTE_STANDARD_NAME ","
260
G_FILE_ATTRIBUTE_STANDARD_SIZE ","
261
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
262
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
263
G_FILE_ATTRIBUTE_TIME_MODIFIED,
264
G_FILE_QUERY_INFO_NONE,
267
g_object_unref (file);
269
info = g_object_ref (_info);
272
g_free (item->priv->mime_type);
273
item->priv->mime_type = NULL;
276
|| g_file_info_get_content_type (info) == NULL) {
277
if (item->priv->uri == NULL) {
278
item->priv->mime_type = g_strdup ("image/x-no-data");
279
g_free (item->priv->name);
280
item->priv->name = g_strdup (_("No Desktop Background"));
283
if (item->priv->name == NULL)
284
item->priv->name = g_strdup (g_file_info_get_display_name (info));
286
item->priv->mime_type = g_strdup (g_file_info_get_content_type (info));
290
g_object_unref (info);
294
cc_appearance_item_load (CcAppearanceItem *item,
297
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), FALSE);
299
if (item->priv->uri == NULL)
302
update_info (item, info);
304
if (item->priv->mime_type != NULL
305
&& (g_str_has_prefix (item->priv->mime_type, "image/")
306
|| strcmp (item->priv->mime_type, "application/xml") == 0)) {
307
set_bg_properties (item);
312
/* FIXME we should handle XML files as well */
313
if (item->priv->mime_type != NULL &&
314
g_str_has_prefix (item->priv->mime_type, "image/")) {
317
filename = g_filename_from_uri (item->priv->uri, NULL, NULL);
318
gdk_pixbuf_get_file_info (filename,
320
&item->priv->height);
329
_set_name (CcAppearanceItem *item,
332
g_free (item->priv->name);
333
item->priv->name = g_strdup (value);
337
cc_appearance_item_get_name (CcAppearanceItem *item)
339
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
341
return item->priv->name;
345
_set_uri (CcAppearanceItem *item,
348
g_free (item->priv->uri);
349
if (value && *value == '\0') {
350
item->priv->uri = NULL;
352
if (value && strstr (value, "://") == NULL)
353
g_warning ("URI '%s' is invalid", value);
354
item->priv->uri = g_strdup (value);
359
cc_appearance_item_get_uri (CcAppearanceItem *item)
361
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
363
return item->priv->uri;
367
_set_placement (CcAppearanceItem *item,
368
GDesktopBackgroundStyle value)
370
item->priv->placement = value;
374
_set_shading (CcAppearanceItem *item,
375
GDesktopBackgroundShading value)
377
item->priv->shading = value;
381
_set_primary_color (CcAppearanceItem *item,
384
g_free (item->priv->primary_color);
385
item->priv->primary_color = g_strdup (value);
389
cc_appearance_item_get_pcolor (CcAppearanceItem *item)
391
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
393
return item->priv->primary_color;
397
_set_secondary_color (CcAppearanceItem *item,
400
g_free (item->priv->secondary_color);
401
item->priv->secondary_color = g_strdup (value);
405
cc_appearance_item_get_scolor (CcAppearanceItem *item)
407
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
409
return item->priv->secondary_color;
412
GDesktopBackgroundStyle
413
cc_appearance_item_get_placement (CcAppearanceItem *item)
415
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), G_DESKTOP_BACKGROUND_STYLE_SCALED);
417
return item->priv->placement;
420
GDesktopBackgroundShading
421
cc_appearance_item_get_shading (CcAppearanceItem *item)
423
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), G_DESKTOP_BACKGROUND_SHADING_SOLID);
425
return item->priv->shading;
429
_set_is_deleted (CcAppearanceItem *item,
432
item->priv->is_deleted = value;
436
_set_source_url (CcAppearanceItem *item,
439
g_free (item->priv->source_url);
440
item->priv->source_url = g_strdup (value);
444
cc_appearance_item_get_source_url (CcAppearanceItem *item)
446
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
448
return item->priv->source_url;
452
_set_source_xml (CcAppearanceItem *item,
455
g_free (item->priv->source_xml);
456
item->priv->source_xml = g_strdup (value);
460
cc_appearance_item_get_source_xml (CcAppearanceItem *item)
462
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
464
return item->priv->source_xml;
468
_set_flags (CcAppearanceItem *item,
469
CcAppearanceItemFlags value)
471
item->priv->flags = value;
474
CcAppearanceItemFlags
475
cc_appearance_item_get_flags (CcAppearanceItem *item)
477
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), 0);
479
return item->priv->flags;
483
cc_appearance_item_get_size (CcAppearanceItem *item)
485
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), NULL);
487
return item->priv->size;
491
_set_needs_download (CcAppearanceItem *item,
494
item->priv->needs_download = value;
498
cc_appearance_item_get_needs_download (CcAppearanceItem *item)
500
g_return_val_if_fail (CC_IS_APPEARANCE_ITEM (item), 0);
502
return item->priv->needs_download;
506
cc_appearance_item_set_property (GObject *object,
511
CcAppearanceItem *self;
513
self = CC_APPEARANCE_ITEM (object);
517
_set_name (self, g_value_get_string (value));
520
_set_uri (self, g_value_get_string (value));
523
_set_placement (self, g_value_get_enum (value));
526
_set_shading (self, g_value_get_enum (value));
528
case PROP_PRIMARY_COLOR:
529
_set_primary_color (self, g_value_get_string (value));
531
case PROP_SECONDARY_COLOR:
532
_set_secondary_color (self, g_value_get_string (value));
534
case PROP_IS_DELETED:
535
_set_is_deleted (self, g_value_get_boolean (value));
537
case PROP_SOURCE_URL:
538
_set_source_url (self, g_value_get_string (value));
540
case PROP_SOURCE_XML:
541
_set_source_xml (self, g_value_get_string (value));
544
_set_flags (self, g_value_get_flags (value));
546
case PROP_NEEDS_DOWNLOAD:
547
_set_needs_download (self, g_value_get_boolean (value));
550
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
556
cc_appearance_item_get_property (GObject *object,
561
CcAppearanceItem *self;
563
self = CC_APPEARANCE_ITEM (object);
567
g_value_set_string (value, self->priv->name);
570
g_value_set_string (value, self->priv->uri);
573
g_value_set_enum (value, self->priv->placement);
576
g_value_set_enum (value, self->priv->shading);
578
case PROP_PRIMARY_COLOR:
579
g_value_set_string (value, self->priv->primary_color);
581
case PROP_SECONDARY_COLOR:
582
g_value_set_string (value, self->priv->secondary_color);
584
case PROP_IS_DELETED:
585
g_value_set_boolean (value, self->priv->is_deleted);
587
case PROP_SOURCE_URL:
588
g_value_set_string (value, self->priv->source_url);
590
case PROP_SOURCE_XML:
591
g_value_set_string (value, self->priv->source_xml);
594
g_value_set_flags (value, self->priv->flags);
597
g_value_set_string (value, self->priv->size);
599
case PROP_NEEDS_DOWNLOAD:
600
g_value_set_boolean (value, self->priv->needs_download);
603
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
609
cc_appearance_item_constructor (GType type,
610
guint n_construct_properties,
611
GObjectConstructParam *construct_properties)
613
CcAppearanceItem *appearance_item;
615
appearance_item = CC_APPEARANCE_ITEM (G_OBJECT_CLASS (cc_appearance_item_parent_class)->constructor (type,
616
n_construct_properties,
617
construct_properties));
619
return G_OBJECT (appearance_item);
623
cc_appearance_item_class_init (CcAppearanceItemClass *klass)
625
GObjectClass *object_class = G_OBJECT_CLASS (klass);
627
object_class->get_property = cc_appearance_item_get_property;
628
object_class->set_property = cc_appearance_item_set_property;
629
object_class->constructor = cc_appearance_item_constructor;
630
object_class->finalize = cc_appearance_item_finalize;
632
g_object_class_install_property (object_class,
634
g_param_spec_string ("name",
639
g_object_class_install_property (object_class,
641
g_param_spec_string ("uri",
646
g_object_class_install_property (object_class,
648
g_param_spec_enum ("placement",
651
G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
652
G_DESKTOP_BACKGROUND_STYLE_SCALED,
655
g_object_class_install_property (object_class,
657
g_param_spec_enum ("shading",
660
G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
661
G_DESKTOP_BACKGROUND_SHADING_SOLID,
663
g_object_class_install_property (object_class,
665
g_param_spec_string ("primary-color",
670
g_object_class_install_property (object_class,
671
PROP_SECONDARY_COLOR,
672
g_param_spec_string ("secondary-color",
678
g_object_class_install_property (object_class,
680
g_param_spec_boolean ("is-deleted",
686
g_object_class_install_property (object_class,
688
g_param_spec_string ("source-url",
694
g_object_class_install_property (object_class,
696
g_param_spec_string ("source-xml",
702
g_object_class_install_property (object_class,
704
g_param_spec_flags ("flags",
707
G_DESKTOP_TYPE_APPEARANCE_ITEM_FLAGS,
711
g_object_class_install_property (object_class,
713
g_param_spec_string ("size",
719
g_object_class_install_property (object_class,
721
g_param_spec_boolean ("needs-download",
728
g_type_class_add_private (klass, sizeof (CcAppearanceItemPrivate));
732
cc_appearance_item_init (CcAppearanceItem *item)
734
item->priv = CC_APPEARANCE_ITEM_GET_PRIVATE (item);
736
item->priv->bg = gnome_bg_new ();
738
item->priv->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
739
item->priv->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
740
item->priv->primary_color = g_strdup ("#000000000000");
741
item->priv->secondary_color = g_strdup ("#000000000000");
742
item->priv->needs_download = TRUE;
743
item->priv->flags = 0;
747
cc_appearance_item_finalize (GObject *object)
749
CcAppearanceItem *item;
751
g_return_if_fail (object != NULL);
752
g_return_if_fail (CC_IS_APPEARANCE_ITEM (object));
754
item = CC_APPEARANCE_ITEM (object);
756
g_return_if_fail (item->priv != NULL);
758
g_free (item->priv->name);
759
g_free (item->priv->uri);
760
g_free (item->priv->primary_color);
761
g_free (item->priv->secondary_color);
762
g_free (item->priv->mime_type);
763
g_free (item->priv->size);
765
if (item->priv->bg != NULL)
766
g_object_unref (item->priv->bg);
768
G_OBJECT_CLASS (cc_appearance_item_parent_class)->finalize (object);
772
cc_appearance_item_new (const char *uri)
776
object = g_object_new (CC_TYPE_APPEARANCE_ITEM,
780
return CC_APPEARANCE_ITEM (object);
784
cc_appearance_item_copy (CcAppearanceItem *item)
786
CcAppearanceItem *ret;
788
ret = cc_appearance_item_new (item->priv->uri);
789
ret->priv->name = g_strdup (item->priv->name);
790
ret->priv->size = g_strdup (item->priv->size);
791
ret->priv->placement = item->priv->placement;
792
ret->priv->shading = item->priv->shading;
793
ret->priv->primary_color = g_strdup (item->priv->primary_color);
794
ret->priv->secondary_color = g_strdup (item->priv->secondary_color);
795
ret->priv->source_url = g_strdup (item->priv->source_url);
796
ret->priv->source_xml = g_strdup (item->priv->source_xml);
797
ret->priv->is_deleted = item->priv->is_deleted;
798
ret->priv->needs_download = item->priv->needs_download;
799
ret->priv->flags = item->priv->flags;
805
flags_to_str (CcAppearanceItemFlags flag)
810
fclass = G_FLAGS_CLASS (g_type_class_peek (G_DESKTOP_TYPE_APPEARANCE_ITEM_FLAGS));
811
value = g_flags_get_first_value (fclass, flag);
815
return value->value_nick;
819
enum_to_str (GType type,
825
eclass = G_ENUM_CLASS (g_type_class_peek (type));
826
value = g_enum_get_value (eclass, v);
830
return value->value_nick;
834
cc_appearance_item_dump (CcAppearanceItem *item)
836
CcAppearanceItemPrivate *priv;
840
g_return_if_fail (CC_IS_APPEARANCE_ITEM (item));
844
g_debug ("name:\t\t\t%s", priv->name);
845
g_debug ("URI:\t\t\t%s", priv->uri ? priv->uri : "NULL");
847
g_debug ("size:\t\t\t'%s'", priv->size);
848
flags = g_string_new (NULL);
849
for (i = 0; i < 5; i++) {
850
if (priv->flags & (1 << i)) {
851
g_string_append (flags, flags_to_str (1 << i));
852
g_string_append_c (flags, ' ');
856
g_string_append (flags, "-none-");
857
g_debug ("flags:\t\t\t%s", flags->str);
858
g_string_free (flags, TRUE);
859
if (priv->primary_color)
860
g_debug ("pcolor:\t\t%s", priv->primary_color);
861
if (priv->secondary_color)
862
g_debug ("scolor:\t\t%s", priv->secondary_color);
863
g_debug ("placement:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, priv->placement));
864
g_debug ("shading:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, priv->shading));
865
if (priv->source_url)
866
g_debug ("source URL:\t\t%s", priv->source_url);
867
if (priv->source_xml)
868
g_debug ("source XML:\t\t%s", priv->source_xml);
869
g_debug ("deleted:\t\t%s", priv->is_deleted ? "yes" : "no");
871
g_debug ("mime-type:\t\t%s", priv->mime_type);
872
g_debug ("dimensions:\t\t%d x %d", priv->width, priv->height);
877
files_equal (const char *a,
880
GFile *file1, *file2;
891
file1 = g_file_new_for_commandline_arg (a);
892
file2 = g_file_new_for_commandline_arg (b);
893
if (g_file_equal (file1, file2) == FALSE)
897
g_object_unref (file1);
898
g_object_unref (file2);
904
colors_equal (const char *a,
907
GdkColor color1, color2;
909
gdk_color_parse (a, &color1);
910
gdk_color_parse (b, &color2);
912
return gdk_color_equal (&color1, &color2);
916
cc_appearance_item_compare (CcAppearanceItem *saved,
917
CcAppearanceItem *configured)
919
CcAppearanceItemFlags flags;
921
flags = saved->priv->flags;
925
if (flags & CC_APPEARANCE_ITEM_HAS_URI) {
926
if (files_equal (saved->priv->uri, configured->priv->uri) == FALSE)
929
if (flags & CC_APPEARANCE_ITEM_HAS_SHADING) {
930
if (saved->priv->shading != configured->priv->shading)
933
if (flags & CC_APPEARANCE_ITEM_HAS_PLACEMENT) {
934
if (saved->priv->placement != configured->priv->placement)
937
if (flags & CC_APPEARANCE_ITEM_HAS_PCOLOR) {
938
if (colors_equal (saved->priv->primary_color,
939
configured->priv->primary_color) == FALSE) {
943
if (flags & CC_APPEARANCE_ITEM_HAS_SCOLOR) {
944
if (colors_equal (saved->priv->secondary_color,
945
configured->priv->secondary_color) == FALSE) {