We were assuming that setting stock-size would affect the emblems in GEmblemedIcons, but not the icons themselves. This is a bit weird. GtkCellRendererPixbuf:gicon is meant to work with GtkCellRendererPixbuf:stock-size, and this was only working so far because GTK_ICON_LOOKUP_FORCE_SIZE was not being used when loading the icon. Let's composite the emblems ourselves so that we don't have to depend on this quirky interpretation of stock-size. Unfortunately, we can not directly use the pixbufs because they are unaware of the scale factor and GTK+ will scale them on HiDpi displays. Since our pixbufs already have enough pixels to work well with such devices, scaling them further will lead to giant, fuzzy thumbnails. Hence, we use GtkCellRendererPixbuf:surface with the scale factor codified in it. https://bugzilla.gnome.org/show_bug.cgi?id=732375
1038 lines
33 KiB
C
1038 lines
33 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||
*
|
||
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||
*
|
||
*/
|
||
|
||
#include "config.h"
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
|
||
#include <gtk/gtk.h>
|
||
#include <gio/gio.h>
|
||
#include <glib/gi18n-lib.h>
|
||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||
|
||
#include <libgnome-desktop/gnome-bg.h>
|
||
#include <gdesktop-enums.h>
|
||
|
||
#include "cc-background-item.h"
|
||
#include "gdesktop-enums-types.h"
|
||
|
||
#define CC_BACKGROUND_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_BACKGROUND_ITEM, CcBackgroundItemPrivate))
|
||
|
||
struct CcBackgroundItemPrivate
|
||
{
|
||
/* properties */
|
||
char *name;
|
||
char *uri;
|
||
char *size;
|
||
GDesktopBackgroundStyle placement;
|
||
GDesktopBackgroundShading shading;
|
||
char *primary_color;
|
||
char *secondary_color;
|
||
char *source_url; /* Used by the Flickr source */
|
||
char *source_xml; /* Used by the Wallpapers source */
|
||
gboolean is_deleted;
|
||
gboolean needs_download;
|
||
CcBackgroundItemFlags flags;
|
||
guint64 modified;
|
||
|
||
/* internal */
|
||
GdkPixbuf *slideshow_emblem;
|
||
GnomeBG *bg;
|
||
char *mime_type;
|
||
int width;
|
||
int height;
|
||
};
|
||
|
||
enum {
|
||
PROP_0,
|
||
PROP_NAME,
|
||
PROP_URI,
|
||
PROP_PLACEMENT,
|
||
PROP_SHADING,
|
||
PROP_PRIMARY_COLOR,
|
||
PROP_SECONDARY_COLOR,
|
||
PROP_IS_DELETED,
|
||
PROP_SOURCE_URL,
|
||
PROP_SOURCE_XML,
|
||
PROP_FLAGS,
|
||
PROP_SIZE,
|
||
PROP_NEEDS_DOWNLOAD,
|
||
PROP_MODIFIED
|
||
};
|
||
|
||
static void cc_background_item_class_init (CcBackgroundItemClass *klass);
|
||
static void cc_background_item_init (CcBackgroundItem *background_item);
|
||
static void cc_background_item_finalize (GObject *object);
|
||
|
||
G_DEFINE_TYPE (CcBackgroundItem, cc_background_item, G_TYPE_OBJECT)
|
||
|
||
static GdkPixbuf *slideshow_emblem = NULL;
|
||
|
||
static GIcon *
|
||
get_emblemed_pixbuf (CcBackgroundItem *item, GdkPixbuf *pixbuf, gint scale_factor)
|
||
{
|
||
GIcon *icon = NULL;
|
||
GIcon *retval;
|
||
GtkIconInfo *icon_info = NULL;
|
||
int eh;
|
||
int ew;
|
||
int h;
|
||
int w;
|
||
int x;
|
||
int y;
|
||
|
||
retval = g_object_ref (pixbuf);
|
||
|
||
if (item->priv->slideshow_emblem == NULL) {
|
||
if (slideshow_emblem == NULL) {
|
||
GError *error = NULL;
|
||
GtkIconTheme *theme;
|
||
|
||
icon = g_themed_icon_new ("slideshow-emblem");
|
||
theme = gtk_icon_theme_get_default ();
|
||
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (theme,
|
||
icon,
|
||
16,
|
||
scale_factor,
|
||
GTK_ICON_LOOKUP_FORCE_SIZE |
|
||
GTK_ICON_LOOKUP_USE_BUILTIN);
|
||
slideshow_emblem = gtk_icon_info_load_icon (icon_info, &error);
|
||
if (slideshow_emblem == NULL) {
|
||
g_warning ("Failed to load slideshow emblem: %s", error->message);
|
||
g_error_free (error);
|
||
goto out;
|
||
}
|
||
|
||
g_object_add_weak_pointer (G_OBJECT (slideshow_emblem), (gpointer *) (&slideshow_emblem));
|
||
item->priv->slideshow_emblem = slideshow_emblem;
|
||
} else {
|
||
item->priv->slideshow_emblem = g_object_ref (slideshow_emblem);
|
||
}
|
||
}
|
||
|
||
eh = gdk_pixbuf_get_height (slideshow_emblem);
|
||
ew = gdk_pixbuf_get_width (slideshow_emblem);
|
||
h = gdk_pixbuf_get_height (pixbuf);
|
||
w = gdk_pixbuf_get_width (pixbuf);
|
||
x = w - ew;
|
||
y = h - eh;
|
||
|
||
gdk_pixbuf_composite (slideshow_emblem, pixbuf, x, y, ew, eh, x, y, 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
|
||
|
||
out:
|
||
g_clear_object (&icon_info);
|
||
g_clear_object (&icon);
|
||
return retval;
|
||
}
|
||
|
||
static void
|
||
set_bg_properties (CcBackgroundItem *item)
|
||
{
|
||
GdkColor pcolor = { 0, 0, 0, 0 };
|
||
GdkColor scolor = { 0, 0, 0, 0 };
|
||
|
||
if (item->priv->uri) {
|
||
GFile *file;
|
||
char *filename;
|
||
|
||
file = g_file_new_for_commandline_arg (item->priv->uri);
|
||
filename = g_file_get_path (file);
|
||
g_object_unref (file);
|
||
|
||
gnome_bg_set_filename (item->priv->bg, filename);
|
||
g_free (filename);
|
||
}
|
||
|
||
if (item->priv->primary_color != NULL) {
|
||
gdk_color_parse (item->priv->primary_color, &pcolor);
|
||
}
|
||
if (item->priv->secondary_color != NULL) {
|
||
gdk_color_parse (item->priv->secondary_color, &scolor);
|
||
}
|
||
|
||
gnome_bg_set_color (item->priv->bg, item->priv->shading, &pcolor, &scolor);
|
||
gnome_bg_set_placement (item->priv->bg, item->priv->placement);
|
||
}
|
||
|
||
|
||
gboolean
|
||
cc_background_item_changes_with_time (CcBackgroundItem *item)
|
||
{
|
||
gboolean changes;
|
||
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
|
||
|
||
changes = FALSE;
|
||
if (item->priv->bg != NULL) {
|
||
changes = gnome_bg_changes_with_time (item->priv->bg);
|
||
}
|
||
return changes;
|
||
}
|
||
|
||
static void
|
||
update_size (CcBackgroundItem *item)
|
||
{
|
||
g_clear_pointer (&item->priv->size, g_free);
|
||
|
||
if (item->priv->uri == NULL) {
|
||
item->priv->size = g_strdup ("");
|
||
} else {
|
||
if (gnome_bg_has_multiple_sizes (item->priv->bg) || gnome_bg_changes_with_time (item->priv->bg)) {
|
||
item->priv->size = g_strdup (_("multiple sizes"));
|
||
} else {
|
||
/* translators: 100 × 100px
|
||
* Note that this is not an "x", but U+00D7 MULTIPLICATION SIGN */
|
||
item->priv->size = g_strdup_printf (_("%d \303\227 %d"),
|
||
item->priv->width,
|
||
item->priv->height);
|
||
}
|
||
}
|
||
}
|
||
|
||
static GdkPixbuf *
|
||
render_at_size (GnomeBG *bg,
|
||
gint width,
|
||
gint height)
|
||
{
|
||
GdkPixbuf *pixbuf;
|
||
|
||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
|
||
gnome_bg_draw (bg, pixbuf, gdk_screen_get_default (), FALSE);
|
||
|
||
return pixbuf;
|
||
}
|
||
|
||
GIcon *
|
||
cc_background_item_get_frame_thumbnail (CcBackgroundItem *item,
|
||
GnomeDesktopThumbnailFactory *thumbs,
|
||
int width,
|
||
int height,
|
||
int scale_factor,
|
||
int frame,
|
||
gboolean force_size)
|
||
{
|
||
GdkPixbuf *pixbuf = NULL;
|
||
GIcon *icon = NULL;
|
||
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
g_return_val_if_fail (width > 0 && height > 0, NULL);
|
||
|
||
set_bg_properties (item);
|
||
|
||
if (force_size) {
|
||
/* FIXME: this doesn't play nice with slideshow stepping at all,
|
||
* because it will always render the current slideshow frame, which
|
||
* might not be what we want.
|
||
* We're lacking an API to draw a high-res GnomeBG manually choosing
|
||
* the slideshow frame though, so we can't do much better than this
|
||
* for now.
|
||
*/
|
||
pixbuf = render_at_size (item->priv->bg, width, height);
|
||
} else {
|
||
if (frame >= 0) {
|
||
pixbuf = gnome_bg_create_frame_thumbnail (item->priv->bg,
|
||
thumbs,
|
||
gdk_screen_get_default (),
|
||
width,
|
||
height,
|
||
frame);
|
||
} else {
|
||
pixbuf = gnome_bg_create_thumbnail (item->priv->bg,
|
||
thumbs,
|
||
gdk_screen_get_default (),
|
||
width,
|
||
height);
|
||
}
|
||
}
|
||
|
||
if (pixbuf != NULL
|
||
&& frame != -2
|
||
&& gnome_bg_changes_with_time (item->priv->bg)) {
|
||
icon = get_emblemed_pixbuf (item, pixbuf, scale_factor);
|
||
g_object_unref (pixbuf);
|
||
} else {
|
||
icon = G_ICON (pixbuf);
|
||
}
|
||
|
||
gnome_bg_get_image_size (item->priv->bg,
|
||
thumbs,
|
||
width,
|
||
height,
|
||
&item->priv->width,
|
||
&item->priv->height);
|
||
|
||
update_size (item);
|
||
|
||
return icon;
|
||
}
|
||
|
||
|
||
GIcon *
|
||
cc_background_item_get_thumbnail (CcBackgroundItem *item,
|
||
GnomeDesktopThumbnailFactory *thumbs,
|
||
int width,
|
||
int height,
|
||
int scale_factor)
|
||
{
|
||
return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE);
|
||
}
|
||
|
||
static void
|
||
update_info (CcBackgroundItem *item,
|
||
GFileInfo *_info)
|
||
{
|
||
GFile *file;
|
||
GFileInfo *info;
|
||
|
||
if (_info == NULL) {
|
||
file = g_file_new_for_uri (item->priv->uri);
|
||
|
||
info = g_file_query_info (file,
|
||
G_FILE_ATTRIBUTE_STANDARD_NAME ","
|
||
G_FILE_ATTRIBUTE_STANDARD_SIZE ","
|
||
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
|
||
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
|
||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||
G_FILE_QUERY_INFO_NONE,
|
||
NULL,
|
||
NULL);
|
||
g_object_unref (file);
|
||
} else {
|
||
info = g_object_ref (_info);
|
||
}
|
||
|
||
g_clear_pointer (&item->priv->mime_type, g_free);
|
||
|
||
if (info == NULL
|
||
|| g_file_info_get_content_type (info) == NULL) {
|
||
if (item->priv->uri == NULL) {
|
||
item->priv->mime_type = g_strdup ("image/x-no-data");
|
||
g_free (item->priv->name);
|
||
item->priv->name = g_strdup (_("No Desktop Background"));
|
||
}
|
||
} else {
|
||
if (item->priv->name == NULL)
|
||
item->priv->name = g_strdup (g_file_info_get_display_name (info));
|
||
|
||
item->priv->mime_type = g_strdup (g_file_info_get_content_type (info));
|
||
if (item->priv->modified == 0)
|
||
item->priv->modified = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||
}
|
||
|
||
if (info != NULL)
|
||
g_object_unref (info);
|
||
}
|
||
|
||
gboolean
|
||
cc_background_item_load (CcBackgroundItem *item,
|
||
GFileInfo *info)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
|
||
|
||
if (item->priv->uri == NULL)
|
||
return TRUE;
|
||
|
||
update_info (item, info);
|
||
|
||
if (item->priv->mime_type != NULL
|
||
&& (g_str_has_prefix (item->priv->mime_type, "image/")
|
||
|| strcmp (item->priv->mime_type, "application/xml") == 0)) {
|
||
set_bg_properties (item);
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
|
||
/* FIXME we should handle XML files as well */
|
||
if (item->priv->mime_type != NULL &&
|
||
g_str_has_prefix (item->priv->mime_type, "image/")) {
|
||
char *filename;
|
||
|
||
filename = g_filename_from_uri (item->priv->uri, NULL, NULL);
|
||
gdk_pixbuf_get_file_info (filename,
|
||
&item->priv->width,
|
||
&item->priv->height);
|
||
g_free (filename);
|
||
update_size (item);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
_set_name (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->name);
|
||
item->priv->name = g_strdup (value);
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_name (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->name;
|
||
}
|
||
|
||
static void
|
||
_set_uri (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->uri);
|
||
if (value && *value == '\0') {
|
||
item->priv->uri = NULL;
|
||
} else {
|
||
if (value && strstr (value, "://") == NULL)
|
||
g_warning ("URI '%s' is invalid", value);
|
||
item->priv->uri = g_strdup (value);
|
||
}
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_uri (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->uri;
|
||
}
|
||
|
||
static void
|
||
_set_placement (CcBackgroundItem *item,
|
||
GDesktopBackgroundStyle value)
|
||
{
|
||
item->priv->placement = value;
|
||
}
|
||
|
||
static void
|
||
_set_shading (CcBackgroundItem *item,
|
||
GDesktopBackgroundShading value)
|
||
{
|
||
item->priv->shading = value;
|
||
}
|
||
|
||
static void
|
||
_set_primary_color (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->primary_color);
|
||
item->priv->primary_color = g_strdup (value);
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_pcolor (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->primary_color;
|
||
}
|
||
|
||
static void
|
||
_set_secondary_color (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->secondary_color);
|
||
item->priv->secondary_color = g_strdup (value);
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_scolor (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->secondary_color;
|
||
}
|
||
|
||
GDesktopBackgroundStyle
|
||
cc_background_item_get_placement (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_STYLE_SCALED);
|
||
|
||
return item->priv->placement;
|
||
}
|
||
|
||
GDesktopBackgroundShading
|
||
cc_background_item_get_shading (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), G_DESKTOP_BACKGROUND_SHADING_SOLID);
|
||
|
||
return item->priv->shading;
|
||
}
|
||
|
||
static void
|
||
_set_is_deleted (CcBackgroundItem *item,
|
||
gboolean value)
|
||
{
|
||
item->priv->is_deleted = value;
|
||
}
|
||
|
||
static void
|
||
_set_source_url (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->source_url);
|
||
item->priv->source_url = g_strdup (value);
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_source_url (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->source_url;
|
||
}
|
||
|
||
static void
|
||
_set_source_xml (CcBackgroundItem *item,
|
||
const char *value)
|
||
{
|
||
g_free (item->priv->source_xml);
|
||
item->priv->source_xml = g_strdup (value);
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_source_xml (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->source_xml;
|
||
}
|
||
|
||
static void
|
||
_set_flags (CcBackgroundItem *item,
|
||
CcBackgroundItemFlags value)
|
||
{
|
||
item->priv->flags = value;
|
||
}
|
||
|
||
CcBackgroundItemFlags
|
||
cc_background_item_get_flags (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
|
||
|
||
return item->priv->flags;
|
||
}
|
||
|
||
const char *
|
||
cc_background_item_get_size (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
|
||
|
||
return item->priv->size;
|
||
}
|
||
|
||
static void
|
||
_set_needs_download (CcBackgroundItem *item,
|
||
gboolean value)
|
||
{
|
||
item->priv->needs_download = value;
|
||
}
|
||
|
||
gboolean
|
||
cc_background_item_get_needs_download (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
|
||
|
||
return item->priv->needs_download;
|
||
}
|
||
|
||
static void
|
||
_set_modified (CcBackgroundItem *item,
|
||
guint64 value)
|
||
{
|
||
item->priv->modified = value;
|
||
}
|
||
|
||
guint64
|
||
cc_background_item_get_modified (CcBackgroundItem *item)
|
||
{
|
||
g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), 0);
|
||
|
||
return item->priv->modified;
|
||
}
|
||
|
||
static void
|
||
cc_background_item_set_property (GObject *object,
|
||
guint prop_id,
|
||
const GValue *value,
|
||
GParamSpec *pspec)
|
||
{
|
||
CcBackgroundItem *self;
|
||
|
||
self = CC_BACKGROUND_ITEM (object);
|
||
|
||
switch (prop_id) {
|
||
case PROP_NAME:
|
||
_set_name (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_URI:
|
||
_set_uri (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_PLACEMENT:
|
||
_set_placement (self, g_value_get_enum (value));
|
||
break;
|
||
case PROP_SHADING:
|
||
_set_shading (self, g_value_get_enum (value));
|
||
break;
|
||
case PROP_PRIMARY_COLOR:
|
||
_set_primary_color (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_SECONDARY_COLOR:
|
||
_set_secondary_color (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_IS_DELETED:
|
||
_set_is_deleted (self, g_value_get_boolean (value));
|
||
break;
|
||
case PROP_SOURCE_URL:
|
||
_set_source_url (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_SOURCE_XML:
|
||
_set_source_xml (self, g_value_get_string (value));
|
||
break;
|
||
case PROP_FLAGS:
|
||
_set_flags (self, g_value_get_flags (value));
|
||
break;
|
||
case PROP_NEEDS_DOWNLOAD:
|
||
_set_needs_download (self, g_value_get_boolean (value));
|
||
break;
|
||
case PROP_MODIFIED:
|
||
_set_modified (self, g_value_get_uint64 (value));
|
||
break;
|
||
default:
|
||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void
|
||
cc_background_item_get_property (GObject *object,
|
||
guint prop_id,
|
||
GValue *value,
|
||
GParamSpec *pspec)
|
||
{
|
||
CcBackgroundItem *self;
|
||
|
||
self = CC_BACKGROUND_ITEM (object);
|
||
|
||
switch (prop_id) {
|
||
case PROP_NAME:
|
||
g_value_set_string (value, self->priv->name);
|
||
break;
|
||
case PROP_URI:
|
||
g_value_set_string (value, self->priv->uri);
|
||
break;
|
||
case PROP_PLACEMENT:
|
||
g_value_set_enum (value, self->priv->placement);
|
||
break;
|
||
case PROP_SHADING:
|
||
g_value_set_enum (value, self->priv->shading);
|
||
break;
|
||
case PROP_PRIMARY_COLOR:
|
||
g_value_set_string (value, self->priv->primary_color);
|
||
break;
|
||
case PROP_SECONDARY_COLOR:
|
||
g_value_set_string (value, self->priv->secondary_color);
|
||
break;
|
||
case PROP_IS_DELETED:
|
||
g_value_set_boolean (value, self->priv->is_deleted);
|
||
break;
|
||
case PROP_SOURCE_URL:
|
||
g_value_set_string (value, self->priv->source_url);
|
||
break;
|
||
case PROP_SOURCE_XML:
|
||
g_value_set_string (value, self->priv->source_xml);
|
||
break;
|
||
case PROP_FLAGS:
|
||
g_value_set_flags (value, self->priv->flags);
|
||
break;
|
||
case PROP_SIZE:
|
||
g_value_set_string (value, self->priv->size);
|
||
break;
|
||
case PROP_NEEDS_DOWNLOAD:
|
||
g_value_set_boolean (value, self->priv->needs_download);
|
||
break;
|
||
case PROP_MODIFIED:
|
||
g_value_set_uint64 (value, self->priv->modified);
|
||
break;
|
||
default:
|
||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
break;
|
||
}
|
||
}
|
||
|
||
static GObject *
|
||
cc_background_item_constructor (GType type,
|
||
guint n_construct_properties,
|
||
GObjectConstructParam *construct_properties)
|
||
{
|
||
CcBackgroundItem *background_item;
|
||
|
||
background_item = CC_BACKGROUND_ITEM (G_OBJECT_CLASS (cc_background_item_parent_class)->constructor (type,
|
||
n_construct_properties,
|
||
construct_properties));
|
||
|
||
return G_OBJECT (background_item);
|
||
}
|
||
|
||
static void
|
||
cc_background_item_class_init (CcBackgroundItemClass *klass)
|
||
{
|
||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
||
object_class->get_property = cc_background_item_get_property;
|
||
object_class->set_property = cc_background_item_set_property;
|
||
object_class->constructor = cc_background_item_constructor;
|
||
object_class->finalize = cc_background_item_finalize;
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_NAME,
|
||
g_param_spec_string ("name",
|
||
"name",
|
||
"name",
|
||
NULL,
|
||
G_PARAM_READWRITE));
|
||
g_object_class_install_property (object_class,
|
||
PROP_URI,
|
||
g_param_spec_string ("uri",
|
||
"uri",
|
||
"uri",
|
||
NULL,
|
||
G_PARAM_READWRITE));
|
||
g_object_class_install_property (object_class,
|
||
PROP_PLACEMENT,
|
||
g_param_spec_enum ("placement",
|
||
"placement",
|
||
"placement",
|
||
G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE,
|
||
G_DESKTOP_BACKGROUND_STYLE_SCALED,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_SHADING,
|
||
g_param_spec_enum ("shading",
|
||
"shading",
|
||
"shading",
|
||
G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING,
|
||
G_DESKTOP_BACKGROUND_SHADING_SOLID,
|
||
G_PARAM_READWRITE));
|
||
g_object_class_install_property (object_class,
|
||
PROP_PRIMARY_COLOR,
|
||
g_param_spec_string ("primary-color",
|
||
"primary-color",
|
||
"primary-color",
|
||
"#000000000000",
|
||
G_PARAM_READWRITE));
|
||
g_object_class_install_property (object_class,
|
||
PROP_SECONDARY_COLOR,
|
||
g_param_spec_string ("secondary-color",
|
||
"secondary-color",
|
||
"secondary-color",
|
||
"#000000000000",
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_IS_DELETED,
|
||
g_param_spec_boolean ("is-deleted",
|
||
NULL,
|
||
NULL,
|
||
FALSE,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_SOURCE_URL,
|
||
g_param_spec_string ("source-url",
|
||
"source-url",
|
||
"source-url",
|
||
NULL,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_SOURCE_XML,
|
||
g_param_spec_string ("source-xml",
|
||
"source-xml",
|
||
"source-xml",
|
||
NULL,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_FLAGS,
|
||
g_param_spec_flags ("flags",
|
||
"flags",
|
||
"flags",
|
||
G_DESKTOP_TYPE_BACKGROUND_ITEM_FLAGS,
|
||
0,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_SIZE,
|
||
g_param_spec_string ("size",
|
||
"size",
|
||
"size",
|
||
NULL,
|
||
G_PARAM_READABLE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_NEEDS_DOWNLOAD,
|
||
g_param_spec_boolean ("needs-download",
|
||
NULL,
|
||
NULL,
|
||
TRUE,
|
||
G_PARAM_READWRITE));
|
||
|
||
g_object_class_install_property (object_class,
|
||
PROP_MODIFIED,
|
||
g_param_spec_uint64 ("modified",
|
||
"modified",
|
||
NULL,
|
||
0,
|
||
G_MAXUINT64,
|
||
0,
|
||
G_PARAM_READWRITE));
|
||
|
||
|
||
g_type_class_add_private (klass, sizeof (CcBackgroundItemPrivate));
|
||
}
|
||
|
||
static void
|
||
cc_background_item_init (CcBackgroundItem *item)
|
||
{
|
||
item->priv = CC_BACKGROUND_ITEM_GET_PRIVATE (item);
|
||
|
||
item->priv->bg = gnome_bg_new ();
|
||
|
||
item->priv->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
|
||
item->priv->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
|
||
item->priv->primary_color = g_strdup ("#000000000000");
|
||
item->priv->secondary_color = g_strdup ("#000000000000");
|
||
item->priv->needs_download = TRUE;
|
||
item->priv->flags = 0;
|
||
item->priv->modified = 0;
|
||
}
|
||
|
||
static void
|
||
cc_background_item_finalize (GObject *object)
|
||
{
|
||
CcBackgroundItem *item;
|
||
|
||
g_return_if_fail (object != NULL);
|
||
g_return_if_fail (CC_IS_BACKGROUND_ITEM (object));
|
||
|
||
item = CC_BACKGROUND_ITEM (object);
|
||
|
||
g_return_if_fail (item->priv != NULL);
|
||
|
||
g_free (item->priv->name);
|
||
g_free (item->priv->uri);
|
||
g_free (item->priv->primary_color);
|
||
g_free (item->priv->secondary_color);
|
||
g_free (item->priv->mime_type);
|
||
g_free (item->priv->size);
|
||
g_free (item->priv->source_url);
|
||
g_free (item->priv->source_xml);
|
||
|
||
if (item->priv->bg != NULL)
|
||
g_object_unref (item->priv->bg);
|
||
|
||
g_clear_object (&item->priv->slideshow_emblem);
|
||
|
||
G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
|
||
}
|
||
|
||
CcBackgroundItem *
|
||
cc_background_item_new (const char *uri)
|
||
{
|
||
GObject *object;
|
||
|
||
object = g_object_new (CC_TYPE_BACKGROUND_ITEM,
|
||
"uri", uri,
|
||
NULL);
|
||
|
||
return CC_BACKGROUND_ITEM (object);
|
||
}
|
||
|
||
CcBackgroundItem *
|
||
cc_background_item_copy (CcBackgroundItem *item)
|
||
{
|
||
CcBackgroundItem *ret;
|
||
|
||
ret = cc_background_item_new (item->priv->uri);
|
||
ret->priv->name = g_strdup (item->priv->name);
|
||
ret->priv->size = g_strdup (item->priv->size);
|
||
ret->priv->placement = item->priv->placement;
|
||
ret->priv->shading = item->priv->shading;
|
||
ret->priv->primary_color = g_strdup (item->priv->primary_color);
|
||
ret->priv->secondary_color = g_strdup (item->priv->secondary_color);
|
||
ret->priv->source_url = g_strdup (item->priv->source_url);
|
||
ret->priv->source_xml = g_strdup (item->priv->source_xml);
|
||
ret->priv->is_deleted = item->priv->is_deleted;
|
||
ret->priv->needs_download = item->priv->needs_download;
|
||
ret->priv->flags = item->priv->flags;
|
||
|
||
return ret;
|
||
}
|
||
|
||
static const char *
|
||
flags_to_str (CcBackgroundItemFlags flag)
|
||
{
|
||
GFlagsClass *fclass;
|
||
GFlagsValue *value;
|
||
|
||
fclass = G_FLAGS_CLASS (g_type_class_peek (G_DESKTOP_TYPE_BACKGROUND_ITEM_FLAGS));
|
||
value = g_flags_get_first_value (fclass, flag);
|
||
|
||
g_assert (value);
|
||
|
||
return value->value_nick;
|
||
}
|
||
|
||
static const char *
|
||
enum_to_str (GType type,
|
||
int v)
|
||
{
|
||
GEnumClass *eclass;
|
||
GEnumValue *value;
|
||
|
||
eclass = G_ENUM_CLASS (g_type_class_peek (type));
|
||
value = g_enum_get_value (eclass, v);
|
||
|
||
g_assert (value);
|
||
|
||
return value->value_nick;
|
||
}
|
||
|
||
void
|
||
cc_background_item_dump (CcBackgroundItem *item)
|
||
{
|
||
CcBackgroundItemPrivate *priv;
|
||
GString *flags;
|
||
int i;
|
||
|
||
g_return_if_fail (CC_IS_BACKGROUND_ITEM (item));
|
||
|
||
priv = item->priv;
|
||
|
||
g_debug ("name:\t\t\t%s", priv->name);
|
||
g_debug ("URI:\t\t\t%s", priv->uri ? priv->uri : "NULL");
|
||
if (priv->size)
|
||
g_debug ("size:\t\t\t'%s'", priv->size);
|
||
flags = g_string_new (NULL);
|
||
for (i = 0; i < 5; i++) {
|
||
if (priv->flags & (1 << i)) {
|
||
g_string_append (flags, flags_to_str (1 << i));
|
||
g_string_append_c (flags, ' ');
|
||
}
|
||
}
|
||
if (flags->len == 0)
|
||
g_string_append (flags, "-none-");
|
||
g_debug ("flags:\t\t\t%s", flags->str);
|
||
g_string_free (flags, TRUE);
|
||
if (priv->primary_color)
|
||
g_debug ("pcolor:\t\t\t%s", priv->primary_color);
|
||
if (priv->secondary_color)
|
||
g_debug ("scolor:\t\t\t%s", priv->secondary_color);
|
||
g_debug ("placement:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_STYLE, priv->placement));
|
||
g_debug ("shading:\t\t%s", enum_to_str (G_DESKTOP_TYPE_DESKTOP_BACKGROUND_SHADING, priv->shading));
|
||
if (priv->source_url)
|
||
g_debug ("source URL:\t\t%s", priv->source_url);
|
||
if (priv->source_xml)
|
||
g_debug ("source XML:\t\t%s", priv->source_xml);
|
||
g_debug ("deleted:\t\t%s", priv->is_deleted ? "yes" : "no");
|
||
if (priv->mime_type)
|
||
g_debug ("mime-type:\t\t%s", priv->mime_type);
|
||
g_debug ("dimensions:\t\t%d x %d", priv->width, priv->height);
|
||
g_debug ("modified: %"G_GUINT64_FORMAT, priv->modified);
|
||
g_debug (" ");
|
||
}
|
||
|
||
static gboolean
|
||
files_equal (const char *a,
|
||
const char *b)
|
||
{
|
||
GFile *file1, *file2;
|
||
gboolean retval;
|
||
|
||
if (a == NULL &&
|
||
b == NULL)
|
||
return TRUE;
|
||
|
||
if (a == NULL ||
|
||
b == NULL)
|
||
return FALSE;
|
||
|
||
file1 = g_file_new_for_commandline_arg (a);
|
||
file2 = g_file_new_for_commandline_arg (b);
|
||
if (g_file_equal (file1, file2) == FALSE)
|
||
retval = FALSE;
|
||
else
|
||
retval = TRUE;
|
||
g_object_unref (file1);
|
||
g_object_unref (file2);
|
||
|
||
return retval;
|
||
}
|
||
|
||
static gboolean
|
||
colors_equal (const char *a,
|
||
const char *b)
|
||
{
|
||
GdkColor color1, color2;
|
||
|
||
gdk_color_parse (a, &color1);
|
||
gdk_color_parse (b, &color2);
|
||
|
||
return gdk_color_equal (&color1, &color2);
|
||
}
|
||
|
||
gboolean
|
||
cc_background_item_compare (CcBackgroundItem *saved,
|
||
CcBackgroundItem *configured)
|
||
{
|
||
CcBackgroundItemFlags flags;
|
||
|
||
flags = saved->priv->flags;
|
||
if (flags == 0)
|
||
return FALSE;
|
||
|
||
if (flags & CC_BACKGROUND_ITEM_HAS_URI) {
|
||
if (files_equal (saved->priv->uri, configured->priv->uri) == FALSE)
|
||
return FALSE;
|
||
}
|
||
if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) {
|
||
if (saved->priv->shading != configured->priv->shading)
|
||
return FALSE;
|
||
}
|
||
if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT) {
|
||
if (saved->priv->placement != configured->priv->placement)
|
||
return FALSE;
|
||
}
|
||
if (flags & CC_BACKGROUND_ITEM_HAS_PCOLOR) {
|
||
if (colors_equal (saved->priv->primary_color,
|
||
configured->priv->primary_color) == FALSE) {
|
||
return FALSE;
|
||
}
|
||
}
|
||
if (flags & CC_BACKGROUND_ITEM_HAS_SCOLOR) {
|
||
if (colors_equal (saved->priv->secondary_color,
|
||
configured->priv->secondary_color) == FALSE) {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|