static void
bg_colors_source_init (BgColorsSource *self)
{
  GnomeDesktopThumbnailFactory *thumb_factory;
  guint i;
  GtkListStore *store;

  store = bg_source_get_liststore (BG_SOURCE (self));

  thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);

  for (i = 0; i < G_N_ELEMENTS (items); i++)
    {
      CcBackgroundItemFlags flags;
      CcBackgroundItem *item;
      GIcon *pixbuf;

      item = cc_background_item_new (NULL);
      flags = CC_BACKGROUND_ITEM_HAS_PCOLOR |
	      CC_BACKGROUND_ITEM_HAS_SCOLOR |
	      CC_BACKGROUND_ITEM_HAS_SHADING |
	      CC_BACKGROUND_ITEM_HAS_PLACEMENT |
	      CC_BACKGROUND_ITEM_HAS_URI;
      /* It does have a URI, it's "none" */

      g_object_set (G_OBJECT (item),
                    "uri", "file:///" DATADIR "/cinnamon-control-center/pixmaps/noise-texture-light.png",
		    "primary-color", items[i].pcolor,
		    "secondary-color", items[i].pcolor,
		    "shading", items[i].type,
		    "placement", G_DESKTOP_BACKGROUND_STYLE_WALLPAPER,
		    "flags", flags,
		    NULL);
      cc_background_item_load (item, NULL);

      /* insert the item into the liststore */
      pixbuf = cc_background_item_get_thumbnail (item,
						 thumb_factory,
						 THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
      gtk_list_store_insert_with_values (store, NULL, 0,
                                         0, pixbuf,
                                         1, item,
                                         -1);

      g_object_unref (pixbuf);
    }

  g_object_unref (thumb_factory);
}
static gboolean
add_single_file (BgPicturesSource *bg_source,
		 GFile            *file,
		 GFileInfo        *info,
		 const char       *source_uri)
{
  const gchar *content_type;
  CcBackgroundItem *item;
  char *uri;
  guint64 mtime;

  /* find png and jpeg files */
  content_type = g_file_info_get_content_type (info);

  if (!content_type)
    return FALSE;
  if (!in_content_types (content_type))
    return FALSE;

  /* create a new CcBackgroundItem */
  uri = g_file_get_uri (file);
  mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);

  item = cc_background_item_new (uri);
  g_free (uri);
  g_object_set (G_OBJECT (item),
		"flags", CC_BACKGROUND_ITEM_HAS_URI | CC_BACKGROUND_ITEM_HAS_SHADING,
		"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
		"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
                "modified", mtime,
		NULL);
  if (source_uri != NULL)
    g_object_set (G_OBJECT (item), "source-url", source_uri, NULL);

  g_object_set_data (G_OBJECT (file), "item", item);

  g_file_read_async (file, G_PRIORITY_DEFAULT,
                     bg_source->priv->cancellable,
                     picture_opened_for_read, bg_source);
  g_object_unref (file);
  return TRUE;
}
static gboolean
add_single_file (BgPicturesSource *bg_source,
		 GFile            *file,
		 GFileInfo        *info,
		 const char       *source_uri)
{
  const gchar *content_type;

  /* find png and jpeg files */
  content_type = g_file_info_get_content_type (info);

  if (!content_type)
    return FALSE;

  if (g_str_equal ("image/png", content_type) ||
      g_str_equal ("image/jpeg", content_type) ||
      g_str_equal ("image/svg+xml", content_type))
    {
      CcBackgroundItem *item;
      char *uri;

      /* create a new CcBackgroundItem */
      uri = g_file_get_uri (file);
      item = cc_background_item_new (uri);
      g_free (uri);
      g_object_set (G_OBJECT (item),
		    "flags", CC_BACKGROUND_ITEM_HAS_URI | CC_BACKGROUND_ITEM_HAS_SHADING,
		    "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
		    "placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
		    NULL);
      if (source_uri != NULL && !g_file_is_native (file))
        g_object_set (G_OBJECT (item), "source-url", source_uri, NULL);

      g_object_set_data (G_OBJECT (file), "item", item);
      g_file_read_async (file, 0, NULL, picture_opened_for_read, bg_source);
      g_object_unref (file);
      return TRUE;
    }

  return FALSE;
}
static gboolean
add_single_file (BgPicturesSource     *bg_source,
                 GFile                *file,
                 const gchar          *content_type,
                 guint64               mtime,
                 GtkTreeRowReference **ret_row_ref)
{
  CcBackgroundItem *item = NULL;
  CcBackgroundItemFlags flags = 0;
  GtkListStore *store;
  GtkTreeIter iter;
  GtkTreePath *path = NULL;
  GtkTreeRowReference *row_ref = NULL;
  cairo_surface_t *surface = NULL;
  char *source_uri = NULL;
  char *uri = NULL;
  gboolean needs_download;
  gboolean retval = FALSE;
  GFile *pictures_dir, *cache_dir;
  GrlMedia *media;

  /* find png and jpeg files */
  if (!content_type)
    goto out;
  if (!in_content_types (content_type))
    goto out;

  /* create a new CcBackgroundItem */
  uri = g_file_get_uri (file);

  pictures_dir = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
  cache_dir = bg_pictures_source_get_cache_file ();
  needs_download = !g_file_has_parent (file, pictures_dir) &&
          !g_file_has_parent (file, cache_dir);
  g_object_unref (pictures_dir);
  g_object_unref (cache_dir);

  if (!needs_download)
    {
      source_uri = g_strdup (uri);
      flags |= CC_BACKGROUND_ITEM_HAS_URI;
    }
  else
    {
      source_uri = uri;
      uri = NULL;
    }

  item = cc_background_item_new (uri);
  flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT;
  g_object_set (G_OBJECT (item),
		"flags", flags,
		"shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
		"placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM,
                "modified", mtime,
                "needs-download", needs_download,
                "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)
    {
      g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref);
      g_file_read_async (file, G_PRIORITY_DEFAULT,
                         bg_source->priv->cancellable,
                         picture_opened_for_read, bg_source);
    }
  else
    {
      GFile *native_file;
      GFile *thumbnail_file = NULL;
      gchar *native_dir;
      gchar *native_path;
      const gchar *title;
      const gchar *thumbnail_uri;

      title = grl_media_get_title (media);
      g_object_set (G_OBJECT (item), "name", title, NULL);

      thumbnail_uri = grl_media_get_thumbnail (media);
      thumbnail_file = g_file_new_for_uri (thumbnail_uri);

      native_path = gnome_desktop_thumbnail_path_for_uri (source_uri, GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
      native_file = g_file_new_for_path (native_path);

      native_dir = g_path_get_dirname (native_path);
      g_mkdir_with_parents (native_dir, USER_DIR_MODE);

      g_object_set_data_full (G_OBJECT (thumbnail_file), "item", g_object_ref (item), g_object_unref);
      g_object_set_data_full (G_OBJECT (thumbnail_file),
                              "native-file",
                              g_object_ref (native_file),
                              g_object_unref);
      g_file_copy_async (thumbnail_file,
                         native_file,
                         G_FILE_COPY_ALL_METADATA,
                         G_PRIORITY_DEFAULT,
                         bg_source->priv->cancellable,
                         NULL,
                         NULL,
                         picture_copied_for_read,
                         bg_source);

      g_clear_object (&thumbnail_file);
      g_object_unref (native_file);
      g_free (native_dir);
      g_free (native_path);
    }

  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, (GDestroyNotify) cairo_surface_destroy);
  g_clear_object (&item);
  g_object_unref (file);
  g_free (source_uri);
  g_free (uri);
  return retval;
}
static void
load_current_bg (CcBackgroundPanel *self)
{
  CcBackgroundPanelPrivate *priv;
  CcBackgroundItem *saved, *configured;
  gchar *uri, *pcolor, *scolor;

  priv = self->priv;

  /* Load the saved configuration */
  uri = get_save_path ();
  saved = cc_background_xml_get_item (uri);
  g_free (uri);

  /* initalise the current background information from settings */
  uri = g_settings_get_string (priv->settings, WP_URI_KEY);
  if (uri && *uri == '\0')
    {
      g_free (uri);
      uri = NULL;
    }
  else
    {
      GFile *file;

      file = g_file_new_for_commandline_arg (uri);
      g_object_unref (file);
    }
  configured = cc_background_item_new (uri);
  g_free (uri);

  pcolor = g_settings_get_string (priv->settings, WP_PCOLOR_KEY);
  scolor = g_settings_get_string (priv->settings, WP_SCOLOR_KEY);
  g_object_set (G_OBJECT (configured),
		"name", _("Current background"),
		"placement", g_settings_get_enum (priv->settings, WP_OPTIONS_KEY),
		"shading", g_settings_get_enum (priv->settings, WP_SHADING_KEY),
		"primary-color", pcolor,
		"secondary-color", scolor,
		NULL);
  g_free (pcolor);
  g_free (scolor);

  if (saved != NULL && cc_background_item_compare (saved, configured))
    {
      CcBackgroundItemFlags flags;
      flags = cc_background_item_get_flags (saved);
      /* Special case for colours */
      if (cc_background_item_get_placement (saved) == G_DESKTOP_BACKGROUND_STYLE_NONE)
        flags &=~ (CC_BACKGROUND_ITEM_HAS_PCOLOR | CC_BACKGROUND_ITEM_HAS_SCOLOR);
      g_object_set (G_OBJECT (configured),
		    "name", cc_background_item_get_name (saved),
		    "flags", flags,
		    "source-url", cc_background_item_get_source_url (saved),
		    "source-xml", cc_background_item_get_source_xml (saved),
		    NULL);
    }
  if (saved != NULL)
    g_object_unref (saved);

  priv->current_background = configured;
  cc_background_item_load (priv->current_background, NULL);
}
static void
bg_colors_source_add_color (BgColorsSource               *self,
                            GnomeDesktopThumbnailFactory *thumb_factory,
                            GtkListStore                 *store,
                            const char                   *color,
                            GtkTreeRowReference         **ret_row_ref)
{
  CcBackgroundItemFlags flags;
  CcBackgroundItem *item;
  GdkPixbuf *pixbuf;
  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 |
          CC_BACKGROUND_ITEM_HAS_SCOLOR |
          CC_BACKGROUND_ITEM_HAS_SHADING |
          CC_BACKGROUND_ITEM_HAS_PLACEMENT |
          CC_BACKGROUND_ITEM_HAS_URI;
  /* It does have a URI, it's "none" */

  g_object_set (G_OBJECT (item),
                "uri", "file:///" DATADIR "/gnome-control-center/pixmaps/noise-texture-light.png",
                "primary-color", color,
                "secondary-color", color,
                "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID,
                "placement", G_DESKTOP_BACKGROUND_STYLE_WALLPAPER,
                "flags", flags,
                NULL);
  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);

  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);
    }

  cairo_surface_destroy (surface);
  g_object_unref (pixbuf);
  g_object_unref (item);
}