GCC Code Coverage Report


Directory: ./
File: panels/background/cc-background-item.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 458 0.0%
Functions: 0 51 0.0%
Branches: 0 253 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2010-2011 Red Hat, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 *
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include <gtk/gtk.h>
26 #include <gio/gio.h>
27 #include <glib/gi18n-lib.h>
28
29 #include <gnome-bg/gnome-bg.h>
30 #include <gdesktop-enums.h>
31
32 #include "cc-background-item.h"
33 #include "gdesktop-enums-types.h"
34 #include "cc-background-enum-types.h"
35
36 typedef struct {
37 int width;
38 int height;
39 int frame;
40 int scale_factor;
41 GdkPixbuf *thumbnail;
42 } CachedThumbnail;
43
44 struct _CcBackgroundItem
45 {
46 GObject parent_instance;
47
48 /* properties */
49 char *name;
50 char *uri;
51 char *uri_dark;
52 char *size;
53 GDesktopBackgroundStyle placement;
54 GDesktopBackgroundShading shading;
55 char *primary_color;
56 char *secondary_color;
57 char *source_url; /* Used by the Flickr source */
58 char *source_xml; /* Used by the Wallpapers source */
59 gboolean is_deleted;
60 gboolean needs_download;
61 CcBackgroundItemFlags flags;
62 guint64 modified;
63
64 /* internal */
65 GnomeBG *bg;
66 char *mime_type;
67 int width;
68 int height;
69
70 GnomeBG *bg_dark;
71
72 CachedThumbnail cached_thumbnail;
73 CachedThumbnail cached_thumbnail_dark;
74 };
75
76 enum {
77 PROP_0,
78 PROP_NAME,
79 PROP_URI,
80 PROP_URI_DARK,
81 PROP_PLACEMENT,
82 PROP_SHADING,
83 PROP_PRIMARY_COLOR,
84 PROP_SECONDARY_COLOR,
85 PROP_IS_DELETED,
86 PROP_SOURCE_URL,
87 PROP_SOURCE_XML,
88 PROP_FLAGS,
89 PROP_SIZE,
90 PROP_NEEDS_DOWNLOAD,
91 PROP_MODIFIED,
92 N_PROPS
93 };
94
95 static GParamSpec *props [N_PROPS];
96
97 static void cc_background_item_finalize (GObject *object);
98
99 G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
100
101 static void
102 set_bg_properties (CcBackgroundItem *item)
103 {
104 GdkRGBA pcolor = { 0, 0, 0, 0 };
105 GdkRGBA scolor = { 0, 0, 0, 0 };
106
107 if (item->uri) {
108 g_autoptr(GFile) file = NULL;
109 g_autofree gchar *filename = NULL;
110
111 file = g_file_new_for_commandline_arg (item->uri);
112 filename = g_file_get_path (file);
113 gnome_bg_set_filename (item->bg, filename);
114 }
115
116 if (item->uri_dark) {
117 g_autoptr(GFile) file = NULL;
118 g_autofree gchar *filename = NULL;
119
120 file = g_file_new_for_commandline_arg (item->uri_dark);
121 filename = g_file_get_path (file);
122 gnome_bg_set_filename (item->bg_dark, filename);
123 }
124
125 if (item->primary_color != NULL) {
126 gdk_rgba_parse (&pcolor, item->primary_color);
127 }
128 if (item->secondary_color != NULL) {
129 gdk_rgba_parse (&scolor, item->secondary_color);
130 }
131
132 gnome_bg_set_rgba (item->bg, item->shading, &pcolor, &scolor);
133 gnome_bg_set_rgba (item->bg_dark, item->shading, &pcolor, &scolor);
134 gnome_bg_set_placement (item->bg, item->placement);
135 gnome_bg_set_placement (item->bg_dark, item->placement);
136 }
137
138
139 gboolean
140 cc_background_item_changes_with_time (CcBackgroundItem *item)
141 {
142 gboolean changes;
143
144 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
145
146 changes = FALSE;
147 if (item->bg != NULL) {
148 changes = gnome_bg_changes_with_time (item->bg);
149 }
150 if (item->bg_dark != NULL) {
151 changes |= gnome_bg_changes_with_time (item->bg_dark);
152 }
153 return changes;
154 }
155
156 gboolean
157 cc_background_item_has_dark_version (CcBackgroundItem *item)
158 {
159 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
160
161 return item->uri && item->uri_dark;
162 }
163
164 static void
165 update_size (CcBackgroundItem *item)
166 {
167 g_clear_pointer (&item->size, g_free);
168
169 if (item->uri == NULL) {
170 item->size = g_strdup ("");
171 } else {
172 if (gnome_bg_has_multiple_sizes (item->bg) || gnome_bg_changes_with_time (item->bg)) {
173 item->size = g_strdup (_("multiple sizes"));
174 } else {
175 gdk_pixbuf_get_file_info (gnome_bg_get_filename (item->bg),
176 &item->width,
177 &item->height);
178 /* translators: 100 × 100px
179 * Note that this is not an "x", but U+00D7 MULTIPLICATION SIGN */
180 item->size = g_strdup_printf (_("%d × %d"),
181 item->width,
182 item->height);
183 }
184 }
185 }
186
187 GdkPixbuf *
188 cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
189 GnomeDesktopThumbnailFactory *thumbs,
190 int width,
191 int height,
192 int scale_factor,
193 int frame,
194 gboolean dark)
195 {
196 GdkPixbuf *pixbuf;
197 CachedThumbnail *thumbnail;
198 GnomeBG *bg;
199 g_autoptr(GdkMonitor) monitor = NULL;
200 GdkDisplay *display;
201 GListModel *monitors;
202 GdkRectangle monitor_layout;
203
204 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
205 g_return_val_if_fail (width > 0 && height > 0, NULL);
206
207 thumbnail = dark ? &item->cached_thumbnail_dark : &item->cached_thumbnail;
208 bg = dark ? item->bg_dark : item->bg;
209
210 /* Use the cached thumbnail if the sizes match */
211 if (thumbnail->thumbnail &&
212 thumbnail->width == width &&
213 thumbnail->height == height &&
214 thumbnail->scale_factor == scale_factor &&
215 thumbnail->frame == frame)
216 return g_object_ref (thumbnail->thumbnail);
217
218 set_bg_properties (item);
219
220 display = gdk_display_get_default ();
221 monitors = gdk_display_get_monitors (display);
222 monitor = g_list_model_get_item (monitors, 0);
223 gdk_monitor_get_geometry (monitor, &monitor_layout);
224
225 if (frame >= 0) {
226 pixbuf = gnome_bg_create_frame_thumbnail (bg,
227 thumbs,
228 &monitor_layout,
229 scale_factor * width,
230 scale_factor * height,
231 frame);
232 } else {
233 pixbuf = gnome_bg_create_thumbnail (bg,
234 thumbs,
235 &monitor_layout,
236 scale_factor * width,
237 scale_factor * height);
238 }
239
240 update_size (item);
241
242 /* Cache the new thumbnail */
243 g_set_object (&thumbnail->thumbnail, pixbuf);
244 thumbnail->width = width;
245 thumbnail->height = height;
246 thumbnail->scale_factor = scale_factor;
247 thumbnail->frame = frame;
248
249 return pixbuf;
250 }
251
252
253 GdkPixbuf *
254 cc_background_item_get_thumbnail (CcBackgroundItem *item,
255 GnomeDesktopThumbnailFactory *thumbs,
256 int width,
257 int height,
258 int scale_factor,
259 gboolean dark)
260 {
261 return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, dark);
262 }
263
264 static void
265 update_info (CcBackgroundItem *item,
266 GFileInfo *_info)
267 {
268 g_autoptr(GFileInfo) info = NULL;
269
270 if (_info == NULL) {
271 g_autoptr(GFile) file = NULL;
272
273 file = g_file_new_for_uri (item->uri);
274
275 info = g_file_query_info (file,
276 G_FILE_ATTRIBUTE_STANDARD_NAME ","
277 G_FILE_ATTRIBUTE_STANDARD_SIZE ","
278 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
279 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
280 G_FILE_ATTRIBUTE_TIME_MODIFIED,
281 G_FILE_QUERY_INFO_NONE,
282 NULL,
283 NULL);
284 } else {
285 info = g_object_ref (_info);
286 }
287
288 g_clear_pointer (&item->mime_type, g_free);
289
290 if (info == NULL
291 || g_file_info_get_content_type (info) == NULL) {
292 if (item->uri == NULL) {
293 item->mime_type = g_strdup ("image/x-no-data");
294 g_free (item->name);
295 item->name = g_strdup (_("No Desktop Background"));
296 }
297 } else {
298 if (item->name == NULL)
299 item->name = g_strdup (g_file_info_get_display_name (info));
300
301 item->mime_type = g_strdup (g_file_info_get_content_type (info));
302 if (item->modified == 0)
303 item->modified = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
304 }
305 }
306
307 gboolean
308 cc_background_item_load (CcBackgroundItem *item,
309 GFileInfo *info)
310 {
311 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
312
313 if (item->uri == NULL)
314 return TRUE;
315
316 update_info (item, info);
317
318 if (item->mime_type != NULL
319 && (g_str_has_prefix (item->mime_type, "image/")
320 || strcmp (item->mime_type, "application/xml") == 0)) {
321 set_bg_properties (item);
322 } else {
323 return FALSE;
324 }
325
326 /* FIXME we should handle XML files as well */
327 if (item->mime_type != NULL &&
328 g_str_has_prefix (item->mime_type, "image/")) {
329 g_autofree gchar *filename = NULL;
330
331 filename = g_filename_from_uri (item->uri, NULL, NULL);
332 gdk_pixbuf_get_file_info (filename,
333 &item->width,
334 &item->height);
335 update_size (item);
336 }
337
338 return TRUE;
339 }
340
341 static void
342 _set_name (CcBackgroundItem *item,
343 const char *value)
344 {
345 g_free (item->name);
346 item->name = g_strdup (value);
347 }
348
349 const char *
350 cc_background_item_get_name (CcBackgroundItem *item)
351 {
352 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
353
354 return item->name;
355 }
356
357 static void
358 _add_flag (CcBackgroundItem *item,
359 CcBackgroundItemFlags flag)
360 {
361 item->flags |= flag;
362 g_object_notify_by_pspec (G_OBJECT (item), props[PROP_FLAGS]);
363 }
364
365 static void
366 _set_uri (CcBackgroundItem *item,
367 const char *value)
368 {
369 g_free (item->uri);
370 if (value && *value == '\0') {
371 item->uri = NULL;
372 } else {
373 if (value && strstr (value, "://") == NULL)
374 g_warning ("URI '%s' is invalid", value);
375 item->uri = g_strdup (value);
376 }
377 _add_flag (item, CC_BACKGROUND_ITEM_HAS_URI);
378 }
379
380
381 static void
382 _set_uri_dark (CcBackgroundItem *item,
383 const char *value)
384 {
385 g_free (item->uri_dark);
386 if (value && *value == '\0') {
387 item->uri_dark = NULL;
388 } else {
389 if (value && strstr (value, "://") == NULL)
390 g_warning ("URI '%s' is invalid", value);
391 item->uri_dark = g_strdup (value);
392 }
393 _add_flag (item, CC_BACKGROUND_ITEM_HAS_URI_DARK);
394 }
395
396 const char *
397 cc_background_item_get_uri (CcBackgroundItem *item)
398 {
399 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
400
401 return item->uri;
402 }
403
404 const char *
405 cc_background_item_get_uri_dark (CcBackgroundItem *item)
406 {
407 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
408
409 return item->uri_dark;
410 }
411
412 static void
413 _set_placement (CcBackgroundItem *item,
414 GDesktopBackgroundStyle value)
415 {
416 item->placement = value;
417 _add_flag (item, CC_BACKGROUND_ITEM_HAS_PLACEMENT);
418 }
419
420 static void
421 _set_shading (CcBackgroundItem *item,
422 GDesktopBackgroundShading value)
423 {
424 item->shading = value;
425 _add_flag (item, CC_BACKGROUND_ITEM_HAS_SHADING);
426 }
427
428 static void
429 _set_primary_color (CcBackgroundItem *item,
430 const char *value)
431 {
432 g_free (item->primary_color);
433 item->primary_color = g_strdup (value);
434 _add_flag (item, CC_BACKGROUND_ITEM_HAS_PCOLOR);
435 }
436
437 const char *
438 cc_background_item_get_pcolor (CcBackgroundItem *item)
439 {
440 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
441
442 return item->primary_color;
443 }
444
445 static void
446 _set_secondary_color (CcBackgroundItem *item,
447 const char *value)
448 {
449 g_free (item->secondary_color);
450 item->secondary_color = g_strdup (value);
451 _add_flag (item, CC_BACKGROUND_ITEM_HAS_SCOLOR);
452 }
453
454 const char *
455 cc_background_item_get_scolor (CcBackgroundItem *item)
456 {
457 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
458
459 return item->secondary_color;
460 }
461
462 GDesktopBackgroundStyle
463 cc_background_item_get_placement (CcBackgroundItem *item)
464 {
465 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_STYLE_SCALED);
466
467 return item->placement;
468 }
469
470 GDesktopBackgroundShading
471 cc_background_item_get_shading (CcBackgroundItem *item)
472 {
473 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_SHADING_SOLID);
474
475 return item->shading;
476 }
477
478 static void
479 _set_is_deleted (CcBackgroundItem *item,
480 gboolean value)
481 {
482 item->is_deleted = value;
483 }
484
485 static void
486 _set_source_url (CcBackgroundItem *item,
487 const char *value)
488 {
489 g_free (item->source_url);
490 item->source_url = g_strdup (value);
491 }
492
493 const char *
494 cc_background_item_get_source_url (CcBackgroundItem *item)
495 {
496 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
497
498 return item->source_url;
499 }
500
501 static void
502 _set_source_xml (CcBackgroundItem *item,
503 const char *value)
504 {
505 g_free (item->source_xml);
506 item->source_xml = g_strdup (value);
507 }
508
509 const char *
510 cc_background_item_get_source_xml (CcBackgroundItem *item)
511 {
512 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
513
514 return item->source_xml;
515 }
516
517 CcBackgroundItemFlags
518 cc_background_item_get_flags (CcBackgroundItem *item)
519 {
520 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
521
522 return item->flags;
523 }
524
525 const char *
526 cc_background_item_get_size (CcBackgroundItem *item)
527 {
528 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
529
530 return item->size;
531 }
532
533 static void
534 _set_needs_download (CcBackgroundItem *item,
535 gboolean value)
536 {
537 item->needs_download = value;
538 }
539
540 gboolean
541 cc_background_item_get_needs_download (CcBackgroundItem *item)
542 {
543 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
544
545 return item->needs_download;
546 }
547
548 static void
549 _set_modified (CcBackgroundItem *item,
550 guint64 value)
551 {
552 item->modified = value;
553 }
554
555 guint64
556 cc_background_item_get_modified (CcBackgroundItem *item)
557 {
558 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
559
560 return item->modified;
561 }
562
563 static void
564 cc_background_item_set_property (GObject *object,
565 guint prop_id,
566 const GValue *value,
567 GParamSpec *pspec)
568 {
569 CcBackgroundItem *self;
570
571 self = CC_BACKGROUND_ITEM (object);
572
573 switch (prop_id) {
574 case PROP_NAME:
575 _set_name (self, g_value_get_string (value));
576 break;
577 case PROP_URI:
578 _set_uri (self, g_value_get_string (value));
579 break;
580 case PROP_URI_DARK:
581 _set_uri_dark (self, g_value_get_string (value));
582 break;
583 case PROP_PLACEMENT:
584 _set_placement (self, g_value_get_enum (value));
585 break;
586 case PROP_SHADING:
587 _set_shading (self, g_value_get_enum (value));
588 break;
589 case PROP_PRIMARY_COLOR:
590 _set_primary_color (self, g_value_get_string (value));
591 break;
592 case PROP_SECONDARY_COLOR:
593 _set_secondary_color (self, g_value_get_string (value));
594 break;
595 case PROP_IS_DELETED:
596 _set_is_deleted (self, g_value_get_boolean (value));
597 break;
598 case PROP_SOURCE_URL:
599 _set_source_url (self, g_value_get_string (value));
600 break;
601 case PROP_SOURCE_XML:
602 _set_source_xml (self, g_value_get_string (value));
603 break;
604 case PROP_NEEDS_DOWNLOAD:
605 _set_needs_download (self, g_value_get_boolean (value));
606 break;
607 case PROP_MODIFIED:
608 _set_modified (self, g_value_get_uint64 (value));
609 break;
610 default:
611 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
612 break;
613 }
614 }
615
616 static void
617 cc_background_item_get_property (GObject *object,
618 guint prop_id,
619 GValue *value,
620 GParamSpec *pspec)
621 {
622 CcBackgroundItem *self;
623
624 self = CC_BACKGROUND_ITEM (object);
625
626 switch (prop_id) {
627 case PROP_NAME:
628 g_value_set_string (value, self->name);
629 break;
630 case PROP_URI:
631 g_value_set_string (value, self->uri);
632 break;
633 case PROP_URI_DARK:
634 g_value_set_string (value, self->uri_dark);
635 break;
636 case PROP_PLACEMENT:
637 g_value_set_enum (value, self->placement);
638 break;
639 case PROP_SHADING:
640 g_value_set_enum (value, self->shading);
641 break;
642 case PROP_PRIMARY_COLOR:
643 g_value_set_string (value, self->primary_color);
644 break;
645 case PROP_SECONDARY_COLOR:
646 g_value_set_string (value, self->secondary_color);
647 break;
648 case PROP_IS_DELETED:
649 g_value_set_boolean (value, self->is_deleted);
650 break;
651 case PROP_SOURCE_URL:
652 g_value_set_string (value, self->source_url);
653 break;
654 case PROP_SOURCE_XML:
655 g_value_set_string (value, self->source_xml);
656 break;
657 case PROP_FLAGS:
658 g_value_set_flags (value, self->flags);
659 break;
660 case PROP_SIZE:
661 g_value_set_string (value, self->size);
662 break;
663 case PROP_NEEDS_DOWNLOAD:
664 g_value_set_boolean (value, self->needs_download);
665 break;
666 case PROP_MODIFIED:
667 g_value_set_uint64 (value, self->modified);
668 break;
669 default:
670 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
671 break;
672 }
673 }
674
675 static GObject *
676 cc_background_item_constructor (GType type,
677 guint n_construct_properties,
678 GObjectConstructParam *construct_properties)
679 {
680 CcBackgroundItem *background_item;
681
682 background_item = CC_BACKGROUND_ITEM (G_OBJECT_CLASS (cc_background_item_parent_class)->constructor (type,
683 n_construct_properties,
684 construct_properties));
685
686 return G_OBJECT (background_item);
687 }
688
689 static void
690 cc_background_item_class_init (CcBackgroundItemClass *klass)
691 {
692 GObjectClass *object_class = G_OBJECT_CLASS (klass);
693
694 object_class->get_property = cc_background_item_get_property;
695 object_class->set_property = cc_background_item_set_property;
696 object_class->constructor = cc_background_item_constructor;
697 object_class->finalize = cc_background_item_finalize;
698
699 props[PROP_NAME] = g_param_spec_string ("name",
700 "name",
701 "name",
702 NULL,
703 G_PARAM_READWRITE);
704
705 props[PROP_URI] = g_param_spec_string ("uri",
706 "uri",
707 "uri",
708 NULL,
709 G_PARAM_READWRITE);
710
711 props[PROP_URI_DARK] = g_param_spec_string ("uri-dark",
712 "uri-dark",
713 "uri-dark",
714 NULL,
715 G_PARAM_READWRITE);
716
717 props[PROP_PLACEMENT] = g_param_spec_enum ("placement",
718 "placement",
719 "placement",
720 G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
721 G_DESKTOP_BACKGROUND_STYLE_SCALED,
722 G_PARAM_READWRITE);
723
724 props[PROP_SHADING] = g_param_spec_enum ("shading",
725 "shading",
726 "shading",
727 G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
728 G_DESKTOP_BACKGROUND_SHADING_SOLID,
729 G_PARAM_READWRITE);
730
731 props[PROP_PRIMARY_COLOR] = g_param_spec_string ("primary-color",
732 "primary-color",
733 "primary-color",
734 "#000000000000",
735 G_PARAM_READWRITE);
736
737 props[PROP_SECONDARY_COLOR] = g_param_spec_string ("secondary-color",
738 "secondary-color",
739 "secondary-color",
740 "#000000000000",
741 G_PARAM_READWRITE);
742
743 props[PROP_IS_DELETED] = g_param_spec_boolean ("is-deleted",
744 NULL,
745 NULL,
746 FALSE,
747 G_PARAM_READWRITE);
748
749 props[PROP_SOURCE_URL] = g_param_spec_string ("source-url",
750 "source-url",
751 "source-url",
752 NULL,
753 G_PARAM_READWRITE);
754
755 props[PROP_SOURCE_XML] = g_param_spec_string ("source-xml",
756 "source-xml",
757 "source-xml",
758 NULL,
759 G_PARAM_READWRITE);
760
761 props[PROP_FLAGS] = g_param_spec_flags ("flags",
762 "flags",
763 "flags",
764 CC_TYPE_BACKGROUND_ITEM_FLAGS,
765 0,
766 G_PARAM_READABLE);
767
768 props[PROP_SIZE] = g_param_spec_string ("size",
769 "size",
770 "size",
771 NULL,
772 G_PARAM_READABLE);
773
774 props[PROP_NEEDS_DOWNLOAD] = g_param_spec_boolean ("needs-download",
775 NULL,
776 NULL,
777 TRUE,
778 G_PARAM_READWRITE);
779
780 props[PROP_MODIFIED] = g_param_spec_uint64 ("modified",
781 "modified",
782 NULL,
783 0,
784 G_MAXUINT64,
785 0,
786 G_PARAM_READWRITE);
787
788 g_object_class_install_properties (object_class, N_PROPS, props);
789 }
790
791 static void
792 cc_background_item_init (CcBackgroundItem *item)
793 {
794 item->bg = gnome_bg_new ();
795 item->bg_dark = gnome_bg_new ();
796
797 item->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
798 item->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
799 item->primary_color = g_strdup ("#000000000000");
800 item->secondary_color = g_strdup ("#000000000000");
801 item->needs_download = TRUE;
802 item->flags = 0;
803 item->modified = 0;
804 }
805
806 static void
807 cc_background_item_finalize (GObject *object)
808 {
809 CcBackgroundItem *item;
810
811 g_return_if_fail (object != NULL);
812 g_return_if_fail (CC_IS_BACKGROUND_ITEM (object));
813
814 item = CC_BACKGROUND_ITEM (object);
815
816 g_return_if_fail (item != NULL);
817
818 g_clear_object (&item->cached_thumbnail.thumbnail);
819 g_clear_object (&item->cached_thumbnail_dark.thumbnail);
820 g_free (item->name);
821 g_free (item->uri);
822 g_free (item->primary_color);
823 g_free (item->secondary_color);
824 g_free (item->mime_type);
825 g_free (item->size);
826 g_free (item->source_url);
827 g_free (item->source_xml);
828
829 g_clear_object (&item->bg);
830 g_clear_object (&item->bg_dark);
831
832 G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
833 }
834
835 CcBackgroundItem *
836 cc_background_item_new (const char *uri)
837 {
838 GObject *object;
839
840 object = g_object_new (CC_TYPE_BACKGROUND_ITEM,
841 "uri", uri,
842 NULL);
843
844 return CC_BACKGROUND_ITEM (object);
845 }
846
847 CcBackgroundItem *
848 cc_background_item_copy (CcBackgroundItem *item)
849 {
850 CcBackgroundItem *ret;
851
852 ret = cc_background_item_new (item->uri);
853 ret->name = g_strdup (item->name);
854 ret->size = g_strdup (item->size);
855 ret->placement = item->placement;
856 ret->shading = item->shading;
857 ret->primary_color = g_strdup (item->primary_color);
858 ret->secondary_color = g_strdup (item->secondary_color);
859 ret->source_url = g_strdup (item->source_url);
860 ret->source_xml = g_strdup (item->source_xml);
861 ret->is_deleted = item->is_deleted;
862 ret->needs_download = item->needs_download;
863 ret->flags = item->flags;
864
865 return ret;
866 }
867
868 static const char *
869 flags_to_str (CcBackgroundItemFlags flag)
870 {
871 GFlagsClass *fclass;
872 GFlagsValue *value;
873
874 fclass = G_FLAGS_CLASS (g_type_class_peek (CC_TYPE_BACKGROUND_ITEM_FLAGS));
875 value = g_flags_get_first_value (fclass, flag);
876
877 g_assert (value);
878
879 return value->value_nick;
880 }
881
882 static const char *
883 enum_to_str (GType type,
884 int v)
885 {
886 GEnumClass *eclass;
887 GEnumValue *value;
888
889 eclass = G_ENUM_CLASS (g_type_class_peek (type));
890 value = g_enum_get_value (eclass, v);
891
892 g_assert (value);
893
894 return value->value_nick;
895 }
896
897 void
898 cc_background_item_dump (CcBackgroundItem *item)
899 {
900 g_autoptr(GString) flags = NULL;
901 int i;
902
903 g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
904
905 g_debug ("name:\t\t\t%s", item->name);
906 g_debug ("URI:\t\t\t%s", item->uri ? item->uri : "NULL");
907 if (item->size)
908 g_debug ("size:\t\t\t'%s'", item->size);
909 flags = g_string_new (NULL);
910 for (i = 0; i < 5; i++) {
911 if (item->flags & (1 << i)) {
912 g_string_append (flags, flags_to_str (1 << i));
913 g_string_append_c (flags, ' ');
914 }
915 }
916 if (flags->len == 0)
917 g_string_append (flags, "-none-");
918 g_debug ("flags:\t\t\t%s", flags->str);
919 if (item->primary_color)
920 g_debug ("pcolor:\t\t\t%s", item->primary_color);
921 if (item->secondary_color)
922 g_debug ("scolor:\t\t\t%s", item->secondary_color);
923 g_debug ("placement:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, item->placement));
924 g_debug ("shading:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, item->shading));
925 if (item->source_url)
926 g_debug ("source URL:\t\t%s", item->source_url);
927 if (item->source_xml)
928 g_debug ("source XML:\t\t%s", item->source_xml);
929 g_debug ("deleted:\t\t%s", item->is_deleted ? "yes" : "no");
930 if (item->mime_type)
931 g_debug ("mime-type:\t\t%s", item->mime_type);
932 g_debug ("dimensions:\t\t%d x %d", item->width, item->height);
933 g_debug ("modified: %"G_GUINT64_FORMAT, item->modified);
934 g_debug (" ");
935 }
936
937 static gboolean
938 files_equal (const char *a,
939 const char *b)
940 {
941 g_autoptr(GFile) file1 = NULL;
942 g_autoptr(GFile) file2 = NULL;
943
944 if (a == NULL && b == NULL)
945 return TRUE;
946
947 if (a == NULL || b == NULL)
948 return FALSE;
949
950 file1 = g_file_new_for_commandline_arg (a);
951 file2 = g_file_new_for_commandline_arg (b);
952
953 return g_file_equal (file1, file2);
954 }
955
956 static gboolean
957 colors_equal (const char *a,
958 const char *b)
959 {
960 GdkRGBA color1, color2;
961
962 gdk_rgba_parse (&color1, a);
963 gdk_rgba_parse (&color2, b);
964
965 return gdk_rgba_equal (&color1, &color2);
966 }
967
968 gboolean
969 cc_background_item_compare (CcBackgroundItem *saved,
970 CcBackgroundItem *configured)
971 {
972 CcBackgroundItemFlags flags;
973
974 flags = saved->flags;
975 if (flags == 0)
976 return FALSE;
977
978 if (flags & CC_BACKGROUND_ITEM_HAS_URI) {
979 if (files_equal (saved->uri, configured->uri) == FALSE)
980 return FALSE;
981 }
982 if (flags & CC_BACKGROUND_ITEM_HAS_URI_DARK) {
983 if (files_equal (saved->uri_dark, configured->uri_dark) == FALSE)
984 return FALSE;
985 }
986 if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) {
987 if (saved->shading != configured->shading)
988 return FALSE;
989 }
990 if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT) {
991 if (saved->placement != configured->placement)
992 return FALSE;
993 }
994 if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR) {
995 if (colors_equal (saved->primary_color,
996 configured->primary_color) == FALSE) {
997 return FALSE;
998 }
999 }
1000 if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR) {
1001 if (colors_equal (saved->secondary_color,
1002 configured->secondary_color) == FALSE) {
1003 return FALSE;
1004 }
1005 }
1006
1007 return TRUE;
1008 }
1009