[gnome-control-center] Add initial implementation of "background" panel



commit e721f417adfadbe6c7a913b9721fc860433ce165
Author: Thomas Wood <thomas wood intel com>
Date:   Tue Aug 10 15:26:07 2010 +0100

    Add initial implementation of "background" panel
    
    The background settings panel provides a way for users to change the
    desktop background by selecting an image and/or colour.

 configure.ac                                       |   19 +
 panels/Makefile.am                                 |    4 +-
 panels/background/Makefile.am                      |   53 ++
 panels/background/background-module.c              |   41 ++
 panels/background/background.ui                    |  216 +++++++
 panels/background/bg-colors-source.c               |  158 +++++
 panels/background/bg-colors-source.h               |   75 +++
 panels/background/bg-flickr-source.c               |  183 ++++++
 panels/background/bg-flickr-source.h               |   75 +++
 panels/background/bg-pictures-source.c             |  280 +++++++++
 panels/background/bg-pictures-source.h             |   76 +++
 panels/background/bg-wallpapers-source.c           |  237 +++++++
 panels/background/bg-wallpapers-source.h           |   76 +++
 panels/background/cc-background-panel.c            |  647 ++++++++++++++++++++
 panels/background/cc-background-panel.h            |   74 +++
 .../gnome-background-panel.desktop.in.in           |   11 +
 panels/background/gnome-wp-info.c                  |   87 +++
 panels/background/gnome-wp-info.h                  |   45 ++
 panels/background/gnome-wp-item.c                  |  315 ++++++++++
 panels/background/gnome-wp-item.h                  |   92 +++
 panels/background/gnome-wp-xml.c                   |  449 ++++++++++++++
 panels/background/gnome-wp-xml.h                   |   43 ++
 22 files changed, 3255 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4bec8d0..4839fdb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -274,6 +274,23 @@ AC_MSG_RESULT([$enable_examples])
 
 AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_examples" = "xyes")
 
+dnl ==============================================
+dnl libsocialweb
+dnl ==============================================
+
+AC_MSG_CHECKING([Enable libsocialweb support])
+AC_ARG_WITH([libsocialweb],
+   AC_HELP_STRING([--with-libsocialweb],
+                  [enable libsocialweb support]),,
+   [with_libsocialweb=no])
+AC_MSG_RESULT([$with_libsocialweb])
+
+if test "x$with_libsocialweb" == "xyes"; then
+  PKG_CHECK_MODULES(SOCIALWEB, libsocialweb-client)
+  AC_DEFINE(HAVE_LIBSOCIALWEB, 1, [Defined if libsocialweb is available])
+fi
+AM_CONDITIONAL(WITH_LIBSOCIALWEB, test "x$with_libsocialweb" = "xyes")
+
 
 dnl =======================================
 dnl Update Mime Database
@@ -356,6 +373,8 @@ help/Makefile
 libgnome-control-center/Makefile
 libgnome-control-center/libgnome-control-center.pc
 panels/Makefile
+panels/background/Makefile
+panels/background/gnome-background-panel.desktop.in
 panels/datetime/Makefile
 panels/datetime/gnome-datetime-panel.desktop.in
 panels/default-applications/Makefile
diff --git a/panels/Makefile.am b/panels/Makefile.am
index 66a22e3..8e989f9 100644
--- a/panels/Makefile.am
+++ b/panels/Makefile.am
@@ -1,4 +1,6 @@
-SUBDIRS=display \
+SUBDIRS= \
+	background \
+	display \
 	mouse \
 	keyboard \
 	network \
diff --git a/panels/background/Makefile.am b/panels/background/Makefile.am
new file mode 100644
index 0000000..aa9f1a1
--- /dev/null
+++ b/panels/background/Makefile.am
@@ -0,0 +1,53 @@
+# This is used in GNOMECC_CAPPLETS_CFLAGS
+cappletname = background
+
+uidir = $(pkgdatadir)/ui/background
+dist_ui_DATA = \
+	background.ui
+
+
+INCLUDES = 						\
+	$(PANEL_CFLAGS)					\
+	$(GNOMECC_CAPPLETS_CFLAGS)			\
+	$(DBUS_CFLAGS)					\
+	-DGNOMELOCALEDIR="\"$(datadir)/locale\""	\
+	-DGNOMECC_DATA_DIR="\"$(pkgdatadir)\""		\
+	-DDATADIR="\"$(uidir)\""			\
+	-DGNOME_DESKTOP_USE_UNSTABLE_API		\
+	$(NULL)
+
+ccpanelsdir = $(PANELS_DIR)
+ccpanels_LTLIBRARIES = libbackground.la
+
+libbackground_la_SOURCES =		\
+	background-module.c	\
+	cc-background-panel.c	\
+	cc-background-panel.h	\
+	bg-pictures-source.c			\
+	bg-pictures-source.h			\
+	bg-wallpapers-source.c			\
+	bg-wallpapers-source.h			\
+	bg-colors-source.c			\
+	bg-colors-source.h			\
+	gnome-wp-info.c  gnome-wp-item.c  gnome-wp-xml.c \
+	gnome-wp-info.h  gnome-wp-item.h  gnome-wp-xml.h
+
+
+libbackground_la_LIBADD = $(PANEL_LIBS) $(DBUS_LIBS)
+libbackground_la_LDFLAGS = $(PANEL_LDFLAGS)
+
+if WITH_LIBSOCIALWEB
+libbackground_la_SOURCES += bg-flickr-source.c bg-flickr-source.h
+INCLUDES += $(SOCIALWEB_CFLAGS)
+libbackground_la_LIBADD += $(SOCIALWEB_LIBS)
+endif
+
+ INTLTOOL_DESKTOP_RULE@
+
+desktopdir = $(datadir)/applications
+desktop_in_files = gnome-background-panel.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+CLEANFILES = $(desktop_in_files) $(desktop_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/background/background-module.c b/panels/background/background-module.c
new file mode 100644
index 0000000..0571f5e
--- /dev/null
+++ b/panels/background/background-module.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#include <config.h>
+
+#include "cc-background-panel.h"
+
+#include <glib/gi18n.h>
+
+void
+g_io_module_load (GIOModule *module)
+{
+  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+  /* register the panel */
+  cc_background_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/panels/background/background.ui b/panels/background/background.ui
new file mode 100644
index 0000000..0cd1154
--- /dev/null
+++ b/panels/background/background.ui
@@ -0,0 +1,216 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="style-liststore">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name value -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">Tile</col>
+        <col id="1">wallpaper</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Zoom</col>
+        <col id="1">zoom</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Center</col>
+        <col id="1">centered</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Scale</col>
+        <col id="1">scaled</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Fill</col>
+        <col id="1">stretched</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Span</col>
+        <col id="1">spanned</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkListStore" id="backgrounds-liststore">
+    <columns>
+      <!-- column-name pixbuf -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name data -->
+      <column type="gpointer"/>
+      <!-- column-name source-id -->
+      <column type="guint"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="sources-liststore">
+    <columns>
+      <!-- column-name source-name -->
+      <column type="gchararray"/>
+      <!-- column-name source-id -->
+      <column type="guint"/>
+      <!-- column-name readonly -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+  <object class="GtkVBox" id="background-panel">
+    <property name="visible">True</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkHBox" id="pictures-vbox">
+        <property name="visible">True</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="width_request">150</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="sources-treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">sources-liststore</property>
+                <property name="headers_visible">False</property>
+                <property name="headers_clickable">False</property>
+                <property name="search_column">0</property>
+                <child>
+                  <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                    <property name="title">Sources</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow2">
+            <property name="width_request">400</property>
+            <property name="height_request">300</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkIconView" id="backgrounds-iconview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="row_spacing">4</property>
+                <property name="column_spacing">4</property>
+                <property name="margin">4</property>
+                <child>
+                  <object class="GtkCellRendererPixbuf" id="pixbuf-renderer"/>
+                  <attributes>
+                    <attribute name="pixbuf">0</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="details-box">
+        <property name="width_request">175</property>
+        <property name="visible">True</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkDrawingArea" id="preview-area">
+            <property name="width_request">200</property>
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkLabel" id="background-label">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="edit-hbox">
+                <property name="visible">True</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkComboBox" id="style-combobox">
+                    <property name="visible">True</property>
+                    <property name="model">style-liststore</property>
+                    <property name="active">0</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkColorButton" id="style-color">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="color">#000000000000</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/panels/background/bg-colors-source.c b/panels/background/bg-colors-source.c
new file mode 100644
index 0000000..26e697d
--- /dev/null
+++ b/panels/background/bg-colors-source.c
@@ -0,0 +1,158 @@
+/* bg-colors-source.c */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#include <config.h>
+#include "bg-colors-source.h"
+
+#include "gnome-wp-item.h"
+
+#include <glib/gi18n-lib.h>
+
+G_DEFINE_TYPE (BgColorsSource, bg_colors_source, G_TYPE_OBJECT)
+
+#define COLORS_SOURCE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BG_TYPE_COLORS_SOURCE, BgColorsSourcePrivate))
+
+struct _BgColorsSourcePrivate
+{
+  GtkListStore *store;
+};
+
+
+static void
+bg_colors_source_dispose (GObject *object)
+{
+  BgColorsSourcePrivate *priv = BG_COLORS_SOURCE (object)->priv;
+
+  if (priv->store)
+    {
+      g_object_unref (priv->store);
+      priv->store = NULL;
+    }
+
+  G_OBJECT_CLASS (bg_colors_source_parent_class)->dispose (object);
+}
+
+static void
+bg_colors_source_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (bg_colors_source_parent_class)->finalize (object);
+}
+
+static void
+bg_colors_source_class_init (BgColorsSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (BgColorsSourcePrivate));
+
+  object_class->dispose = bg_colors_source_dispose;
+  object_class->finalize = bg_colors_source_finalize;
+}
+
+static gchar *colors[] =
+{
+  "#c4a000",
+  "#ce5c00",
+  "#8f5902",
+  "#4e9a06",
+  "#204a87",
+  "#5c3566",
+  "#a40000",
+  "#babdb6",
+  "#2e3436",
+  "#000000",
+  NULL
+};
+
+static gchar *color_names[] =
+{
+  N_("Butter"),
+  N_("Orange"),
+  N_("Chocolate"),
+  N_("Chameleon"),
+  N_("Blue"),
+  N_("Plum"),
+  N_("Red"),
+  N_("Aluminium"),
+  N_("Gray"),
+  N_("Black"),
+  NULL
+};
+
+static void
+bg_colors_source_init (BgColorsSource *self)
+{
+  GnomeDesktopThumbnailFactory *thumb_factory;
+  BgColorsSourcePrivate *priv;
+  gchar **c, **n;
+
+
+  priv = self->priv = COLORS_SOURCE_PRIVATE (self);
+
+  priv->store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
+
+  thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+  for (c = colors, n = color_names; *c; c++, n++)
+    {
+      GnomeWPItem *item;
+      GdkPixbuf *pixbuf;
+      GdkColor color;
+
+      item = g_new0 (GnomeWPItem, 1);
+
+      item->filename = g_strdup ("(none)");
+      item->name = g_strdup (_(*n));
+
+      gdk_color_parse (*c, &color);
+      item->pcolor = gdk_color_copy (&color);
+      item->scolor = gdk_color_copy (&color);
+
+      item->shade_type = GNOME_BG_COLOR_SOLID;
+
+      gnome_wp_item_ensure_gnome_bg (item);
+
+      /* insert the item into the liststore */
+      pixbuf = gnome_wp_item_get_thumbnail (item,
+                                            thumb_factory,
+                                            100, 75);
+      gtk_list_store_insert_with_values (priv->store, NULL, 0,
+                                         0, pixbuf,
+                                         1, item,
+                                         -1);
+    }
+
+  g_object_unref (thumb_factory);
+}
+
+BgColorsSource *
+bg_colors_source_new (void)
+{
+  return g_object_new (BG_TYPE_COLORS_SOURCE, NULL);
+}
+
+GtkListStore *
+bg_colors_source_get_liststore (BgColorsSource *source)
+{
+  return source->priv->store;
+}
diff --git a/panels/background/bg-colors-source.h b/panels/background/bg-colors-source.h
new file mode 100644
index 0000000..395b628
--- /dev/null
+++ b/panels/background/bg-colors-source.h
@@ -0,0 +1,75 @@
+/* bg-colors-source.h */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#ifndef _BG_COLORS_SOURCE_H
+#define _BG_COLORS_SOURCE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_COLORS_SOURCE bg_colors_source_get_type()
+
+#define BG_COLORS_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  BG_TYPE_COLORS_SOURCE, BgColorsSource))
+
+#define BG_COLORS_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  BG_TYPE_COLORS_SOURCE, BgColorsSourceClass))
+
+#define BG_IS_COLORS_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  BG_TYPE_COLORS_SOURCE))
+
+#define BG_IS_COLORS_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  BG_TYPE_COLORS_SOURCE))
+
+#define BG_COLORS_SOURCE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  BG_TYPE_COLORS_SOURCE, BgColorsSourceClass))
+
+typedef struct _BgColorsSource BgColorsSource;
+typedef struct _BgColorsSourceClass BgColorsSourceClass;
+typedef struct _BgColorsSourcePrivate BgColorsSourcePrivate;
+
+struct _BgColorsSource
+{
+  GObject parent;
+
+  BgColorsSourcePrivate *priv;
+};
+
+struct _BgColorsSourceClass
+{
+  GObjectClass parent_class;
+};
+
+GType bg_colors_source_get_type (void) G_GNUC_CONST;
+
+BgColorsSource *bg_colors_source_new (void);
+GtkListStore * bg_colors_source_get_liststore (BgColorsSource *source);
+
+G_END_DECLS
+
+#endif /* _BG_COLORS_SOURCE_H */
diff --git a/panels/background/bg-flickr-source.c b/panels/background/bg-flickr-source.c
new file mode 100644
index 0000000..50637d8
--- /dev/null
+++ b/panels/background/bg-flickr-source.c
@@ -0,0 +1,183 @@
+/* bg-flickr-source.c */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#include "bg-flickr-source.h"
+
+#include <libsocialweb-client/sw-client.h>
+#include <libsocialweb-client/sw-item.h>
+#include <libsocialweb-client/sw-client-service.h>
+
+#include "gnome-wp-item.h"
+
+G_DEFINE_TYPE (BgFlickrSource, bg_flickr_source, G_TYPE_OBJECT)
+
+#define FLICKR_SOURCE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BG_TYPE_FLICKR_SOURCE, BgFlickrSourcePrivate))
+
+struct _BgFlickrSourcePrivate
+{
+  GtkListStore *store;
+
+  SwClient *client;
+  SwClientService *service;
+};
+
+
+static void
+bg_flickr_source_dispose (GObject *object)
+{
+  BgFlickrSourcePrivate *priv = BG_FLICKR_SOURCE (object)->priv;
+
+  if (priv->store)
+    {
+      g_object_unref (priv->store);
+      priv->store = NULL;
+    }
+
+  if (priv->client)
+    {
+      g_object_unref (priv->client);
+      priv->client = NULL;
+    }
+
+  if (priv->service)
+    {
+      g_object_unref (priv->service);
+      priv->service = NULL;
+    }
+
+  G_OBJECT_CLASS (bg_flickr_source_parent_class)->dispose (object);
+}
+
+static void
+bg_flickr_source_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (bg_flickr_source_parent_class)->finalize (object);
+}
+
+static void
+bg_flickr_source_class_init (BgFlickrSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (BgFlickrSourcePrivate));
+
+  object_class->dispose = bg_flickr_source_dispose;
+  object_class->finalize = bg_flickr_source_finalize;
+}
+
+static void
+_view_items_added_cb (SwClientItemView *item_view,
+                      GList            *items,
+                      gpointer          userdata)
+{
+  GList *l;
+  BgFlickrSourcePrivate *priv = (BgFlickrSourcePrivate *) userdata;
+
+  for (l = items; l; l = l->next)
+    {
+      GnomeWPItem *item;
+      GdkPixbuf *pixbuf;
+      GdkColor color = { 0, 0, 0, 0 };
+      SwItem *sw_item = (SwItem *) l->data;
+      const gchar *thumb_url;
+
+      item = g_new0 (GnomeWPItem, 1);
+
+      item->options = GNOME_BG_PLACEMENT_ZOOMED;
+      item->name = g_strdup (sw_item_get_value (sw_item, "title"));
+      item->source_url = g_strdup (sw_item_get_value (sw_item,
+                                                      "x-flickr-photo-url"));
+
+      item->pcolor = gdk_color_copy (&color);
+      item->scolor = gdk_color_copy (&color);
+
+      item->shade_type = GNOME_BG_COLOR_SOLID;
+
+      gnome_wp_item_ensure_gnome_bg (item);
+
+      /* insert the item into the liststore */
+      thumb_url = sw_item_get_value (sw_item, "thumbnail");
+      pixbuf = gdk_pixbuf_new_from_file_at_scale (thumb_url, 100, 75, TRUE,
+                                                  NULL);
+      gtk_list_store_insert_with_values (priv->store, NULL, 0,
+                                         0, pixbuf,
+                                         1, item,
+                                         -1);
+    }
+}
+
+static void
+_query_open_view_cb (SwClientService  *service,
+                     SwClientItemView *item_view,
+                     gpointer          userdata)
+{
+
+  if (!item_view)
+  {
+    g_warning ("Could not connect to Flickr service");
+    return;
+  }
+
+  g_signal_connect (item_view,
+                    "items-added",
+                    (GCallback)_view_items_added_cb,
+                    userdata);
+  sw_client_item_view_start (item_view);
+}
+
+static void
+bg_flickr_source_init (BgFlickrSource *self)
+{
+  GnomeDesktopThumbnailFactory *thumb_factory;
+  BgFlickrSourcePrivate *priv;
+
+  priv = self->priv = FLICKR_SOURCE_PRIVATE (self);
+
+  priv->client = sw_client_new ();
+  priv->service = sw_client_get_service (priv->client, "flickr");
+  sw_client_service_query_open_view (priv->service,
+                                     "feed",
+                                     NULL,
+                                     _query_open_view_cb,
+                                     priv);
+
+  priv->store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
+
+  thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+
+
+  g_object_unref (thumb_factory);
+}
+
+BgFlickrSource *
+bg_flickr_source_new (void)
+{
+  return g_object_new (BG_TYPE_FLICKR_SOURCE, NULL);
+}
+
+GtkListStore *
+bg_flickr_source_get_liststore (BgFlickrSource *source)
+{
+  return source->priv->store;
+}
diff --git a/panels/background/bg-flickr-source.h b/panels/background/bg-flickr-source.h
new file mode 100644
index 0000000..880341f
--- /dev/null
+++ b/panels/background/bg-flickr-source.h
@@ -0,0 +1,75 @@
+/* bg-flickr-source.h */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#ifndef _BG_FLICKR_SOURCE_H
+#define _BG_FLICKR_SOURCE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_FLICKR_SOURCE bg_flickr_source_get_type()
+
+#define BG_FLICKR_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  BG_TYPE_FLICKR_SOURCE, BgFlickrSource))
+
+#define BG_FLICKR_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  BG_TYPE_FLICKR_SOURCE, BgFlickrSourceClass))
+
+#define BG_IS_FLICKR_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  BG_TYPE_FLICKR_SOURCE))
+
+#define BG_IS_FLICKR_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  BG_TYPE_FLICKR_SOURCE))
+
+#define BG_FLICKR_SOURCE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  BG_TYPE_FLICKR_SOURCE, BgFlickrSourceClass))
+
+typedef struct _BgFlickrSource BgFlickrSource;
+typedef struct _BgFlickrSourceClass BgFlickrSourceClass;
+typedef struct _BgFlickrSourcePrivate BgFlickrSourcePrivate;
+
+struct _BgFlickrSource
+{
+  GObject parent;
+
+  BgFlickrSourcePrivate *priv;
+};
+
+struct _BgFlickrSourceClass
+{
+  GObjectClass parent_class;
+};
+
+GType bg_flickr_source_get_type (void) G_GNUC_CONST;
+
+BgFlickrSource *bg_flickr_source_new (void);
+GtkListStore * bg_flickr_source_get_liststore (BgFlickrSource *source);
+
+G_END_DECLS
+
+#endif /* _BG_FLICKR_SOURCE_H */
diff --git a/panels/background/bg-pictures-source.c b/panels/background/bg-pictures-source.c
new file mode 100644
index 0000000..e584544
--- /dev/null
+++ b/panels/background/bg-pictures-source.c
@@ -0,0 +1,280 @@
+/* bg-pictures-source.c */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#include "bg-pictures-source.h"
+
+#include "gnome-wp-item.h"
+
+#include <string.h>
+#include <gio/gio.h>
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+
+
+G_DEFINE_TYPE (BgPicturesSource, bg_pictures_source, G_TYPE_OBJECT)
+
+#define PICTURES_SOURCE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BG_TYPE_PICTURES_SOURCE, BgPicturesSourcePrivate))
+
+struct _BgPicturesSourcePrivate
+{
+  GtkListStore *liststore;
+
+  GFile *dir;
+
+  GCancellable *cancellable;
+
+  GnomeDesktopThumbnailFactory *thumb_factory;
+};
+
+
+static void
+bg_pictures_source_get_property (GObject    *object,
+                                  guint       property_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+bg_pictures_source_set_property (GObject      *object,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+bg_pictures_source_dispose (GObject *object)
+{
+  BgPicturesSourcePrivate *priv = BG_PICTURES_SOURCE (object)->priv;
+
+  if (priv->cancellable)
+    {
+      g_cancellable_cancel (priv->cancellable);
+      g_object_unref (priv->cancellable);
+      priv->cancellable = NULL;
+    }
+
+  if (priv->liststore)
+    {
+      g_object_unref (priv->liststore);
+      priv->liststore = NULL;
+    }
+
+  if (priv->thumb_factory)
+    {
+      g_object_unref (priv->thumb_factory);
+      priv->thumb_factory = NULL;
+    }
+
+  if (priv->dir)
+    {
+      g_object_unref (priv->dir);
+      priv->dir = NULL;
+    }
+
+  G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object);
+}
+
+static void
+bg_pictures_source_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (bg_pictures_source_parent_class)->finalize (object);
+}
+
+static void
+bg_pictures_source_class_init (BgPicturesSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (BgPicturesSourcePrivate));
+
+  object_class->get_property = bg_pictures_source_get_property;
+  object_class->set_property = bg_pictures_source_set_property;
+  object_class->dispose = bg_pictures_source_dispose;
+  object_class->finalize = bg_pictures_source_finalize;
+}
+
+static void
+file_info_async_ready (GObject      *source,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+{
+  BgPicturesSourcePrivate *priv = BG_PICTURES_SOURCE (user_data)->priv;
+  GList *files, *l;
+  GError *err = NULL;
+  GFile *parent;
+  gchar *path;
+
+  files = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source),
+                                               res,
+                                               &err);
+
+  if (err)
+    {
+      g_warning ("Could not get pictures file information: %s", err->message);
+      g_error_free (err);
+
+      g_list_foreach (files, (GFunc) g_object_unref, NULL);
+      g_list_free (files);
+      return;
+    }
+
+  parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source));
+  path = g_file_get_path (parent);
+
+
+  /* iterate over the available files */
+  for (l = files; l; l = g_list_next (l))
+    {
+      GFileInfo *info = l->data;
+      const gchar *content_type;
+
+      /* find png and jpeg files */
+      content_type = g_file_info_get_content_type (info);
+
+      if (!content_type)
+        continue;
+
+      if (!strcmp ("image/png", content_type)
+          || !strcmp ("image/jpeg", content_type))
+        {
+          GdkPixbuf *pixbuf;
+          GnomeWPItem *item;
+          gchar *filename;
+          GtkTreeIter iter;
+          GtkTreePath *tree_path;
+
+          filename = g_build_filename (path, g_file_info_get_name (info), NULL);
+
+          /* create a new GnomeWpItem */
+          item = gnome_wp_item_new (filename, NULL,
+                                    priv->thumb_factory);
+
+          if (!item)
+            {
+              g_warning ("Could not load picture \"%s\"", filename);
+              g_free (filename);
+              continue;
+            }
+
+
+
+          /* insert the item into the liststore */
+          pixbuf = gdk_pixbuf_new_from_file_at_scale (filename, 100, 75, TRUE,
+                                                      NULL);
+          gtk_list_store_insert_with_values (priv->liststore, &iter, 0,
+                                             0, pixbuf,
+                                             1, item,
+                                             -1);
+          tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->liststore),
+                                               &iter);
+          item->rowref =
+            gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->liststore),
+                                        tree_path);
+          gtk_tree_path_free (tree_path);
+
+          g_free (filename);
+        }
+    }
+
+  g_list_foreach (files, (GFunc) g_object_unref, NULL);
+  g_list_free (files);
+
+  g_free (path);
+}
+
+static void
+dir_enum_async_ready (GObject      *source,
+                      GAsyncResult *res,
+                      gpointer      user_data)
+{
+  BgPicturesSourcePrivate *priv = BG_PICTURES_SOURCE (user_data)->priv;
+  GFileEnumerator *enumerator;
+  GError *err = NULL;
+
+  enumerator = g_file_enumerate_children_finish (G_FILE (source), res, &err);
+
+  if (err)
+    {
+      g_warning ("Could not fill pictures source: %s", err->message);
+      g_error_free (err);
+      return;
+    }
+
+  /* get the files */
+  g_file_enumerator_next_files_async (enumerator,
+                                      G_MAXINT,
+                                      G_PRIORITY_LOW,
+                                      priv->cancellable,
+                                      file_info_async_ready,
+                                      user_data);
+}
+
+static void
+bg_pictures_source_init (BgPicturesSource *self)
+{
+  const gchar *pictures_path;
+  BgPicturesSourcePrivate *priv;
+  priv = self->priv = PICTURES_SOURCE_PRIVATE (self);
+
+
+  priv->liststore = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
+
+  priv->cancellable = g_cancellable_new ();
+
+  pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+  priv->dir = g_file_new_for_path (pictures_path);
+
+  g_file_enumerate_children_async (priv->dir,
+                                   G_FILE_ATTRIBUTE_STANDARD_NAME ","
+                                   G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                                   G_FILE_QUERY_INFO_NONE,
+                                   G_PRIORITY_LOW, priv->cancellable,
+                                   dir_enum_async_ready, self);
+
+  priv->thumb_factory =
+    gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+}
+
+BgPicturesSource *
+bg_pictures_source_new (void)
+{
+  return g_object_new (BG_TYPE_PICTURES_SOURCE, NULL);
+}
+
+GtkListStore*
+bg_pictures_source_get_liststore (BgPicturesSource *source)
+{
+  return source->priv->liststore;
+}
diff --git a/panels/background/bg-pictures-source.h b/panels/background/bg-pictures-source.h
new file mode 100644
index 0000000..36281bf
--- /dev/null
+++ b/panels/background/bg-pictures-source.h
@@ -0,0 +1,76 @@
+/* bg-pictures-source.h */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+
+#ifndef _BG_PICTURES_SOURCE_H
+#define _BG_PICTURES_SOURCE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_PICTURES_SOURCE bg_pictures_source_get_type()
+
+#define BG_PICTURES_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  BG_TYPE_PICTURES_SOURCE, BgPicturesSource))
+
+#define BG_PICTURES_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  BG_TYPE_PICTURES_SOURCE, BgPicturesSourceClass))
+
+#define BG_IS_PICTURES_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  BG_TYPE_PICTURES_SOURCE))
+
+#define BG_IS_PICTURES_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  BG_TYPE_PICTURES_SOURCE))
+
+#define BG_PICTURES_SOURCE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  BG_TYPE_PICTURES_SOURCE, BgPicturesSourceClass))
+
+typedef struct _BgPicturesSource BgPicturesSource;
+typedef struct _BgPicturesSourceClass BgPicturesSourceClass;
+typedef struct _BgPicturesSourcePrivate BgPicturesSourcePrivate;
+
+struct _BgPicturesSource
+{
+  GObject parent;
+
+  BgPicturesSourcePrivate *priv;
+};
+
+struct _BgPicturesSourceClass
+{
+  GObjectClass parent_class;
+};
+
+GType bg_pictures_source_get_type (void) G_GNUC_CONST;
+
+BgPicturesSource *bg_pictures_source_new (void);
+GtkListStore     *bg_pictures_source_get_liststore (BgPicturesSource *source);
+
+G_END_DECLS
+
+#endif /* _BG_PICTURES_SOURCE_H */
diff --git a/panels/background/bg-wallpapers-source.c b/panels/background/bg-wallpapers-source.c
new file mode 100644
index 0000000..527e664
--- /dev/null
+++ b/panels/background/bg-wallpapers-source.c
@@ -0,0 +1,237 @@
+/* bg-wallpapers-source.c */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+
+#include "bg-wallpapers-source.h"
+
+#include "gnome-wp-item.h"
+#include "gnome-wp-xml.h"
+
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+#include <gio/gio.h>
+
+G_DEFINE_TYPE (BgWallpapersSource, bg_wallpapers_source, G_TYPE_OBJECT)
+
+#define WALLPAPERS_SOURCE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BG_TYPE_WALLPAPERS_SOURCE, BgWallpapersSourcePrivate))
+
+struct _BgWallpapersSourcePrivate
+{
+  GtkListStore *store;
+  GnomeDesktopThumbnailFactory *thumb_factory;
+};
+
+
+static void
+bg_wallpapers_source_get_property (GObject    *object,
+                                   guint       property_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+bg_wallpapers_source_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+bg_wallpapers_source_dispose (GObject *object)
+{
+  BgWallpapersSourcePrivate *priv = BG_WALLPAPERS_SOURCE (object)->priv;
+
+  if (priv->store)
+    {
+      g_object_unref (priv->store);
+      priv->store = NULL;
+    }
+
+  if (priv->thumb_factory)
+    {
+      g_object_unref (priv->thumb_factory);
+      priv->thumb_factory = NULL;
+    }
+
+  G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->dispose (object);
+}
+
+static void
+bg_wallpapers_source_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (bg_wallpapers_source_parent_class)->finalize (object);
+}
+
+static void
+bg_wallpapers_source_class_init (BgWallpapersSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (BgWallpapersSourcePrivate));
+
+  object_class->get_property = bg_wallpapers_source_get_property;
+  object_class->set_property = bg_wallpapers_source_set_property;
+  object_class->dispose = bg_wallpapers_source_dispose;
+  object_class->finalize = bg_wallpapers_source_finalize;
+}
+
+static gboolean
+find_wallpaper (gpointer key,
+                gpointer value,
+                gpointer data)
+{
+  GnomeBG *bg = data;
+  GnomeWPItem *item = value;
+
+  return item->bg == bg;
+}
+
+static void
+item_changed_cb (GnomeBG    *bg,
+                 GnomeWpXml *data)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GnomeWPItem *item;
+
+  item = g_hash_table_find (data->wp_hash, find_wallpaper, bg);
+
+  if (!item)
+    return;
+
+  model = gtk_tree_row_reference_get_model (item->rowref);
+  path = gtk_tree_row_reference_get_path (item->rowref);
+
+  if (gtk_tree_model_get_iter (model, &iter, path))
+    {
+      GdkPixbuf *pixbuf;
+
+      g_signal_handlers_block_by_func (bg, G_CALLBACK (item_changed_cb), data);
+
+      pixbuf = gnome_wp_item_get_thumbnail (item,
+                                            data->thumb_factory,
+                                            data->thumb_width,
+                                            data->thumb_height);
+      if (pixbuf)
+        {
+          gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter,
+                              0, pixbuf, -1);
+          g_object_unref (pixbuf);
+        }
+
+      g_signal_handlers_unblock_by_func (bg, G_CALLBACK (item_changed_cb),
+                                         data);
+    }
+}
+
+
+
+
+static void
+load_wallpapers (gchar                     *key,
+                 GnomeWPItem               *item,
+                 BgWallpapersSourcePrivate *priv)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+  GdkPixbuf *pixbuf;
+
+  if (item->deleted == TRUE)
+    return;
+
+  gtk_list_store_append (GTK_LIST_STORE (priv->store), &iter);
+
+  pixbuf = gnome_wp_item_get_thumbnail (item, priv->thumb_factory,
+                                        100, 75);
+  gnome_wp_item_update_description (item);
+
+  gtk_list_store_set (GTK_LIST_STORE (priv->store), &iter,
+                      0, pixbuf,
+                      1, item,
+                      -1);
+
+  if (pixbuf)
+    g_object_unref (pixbuf);
+
+  path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
+  item->rowref = gtk_tree_row_reference_new (GTK_TREE_MODEL (priv->store), path);
+  ///g_signal_connect (item->bg, "changed", G_CALLBACK (item_changed_cb), priv->wp_xml);
+  gtk_tree_path_free (path);
+}
+
+static void
+bg_wallpapers_source_init (BgWallpapersSource *self)
+{
+  GnomeWpXml *wp_xml;
+  BgWallpapersSourcePrivate *priv;
+
+  priv = self->priv = WALLPAPERS_SOURCE_PRIVATE (self);
+
+  priv->store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
+
+  priv->thumb_factory =
+    gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+  /* set up wallpaper source */
+  wp_xml = g_new0 (GnomeWpXml, 1);
+  wp_xml->wp_hash = g_hash_table_new (g_str_hash, g_str_equal);
+  wp_xml->client = gconf_client_get_default ();
+  wp_xml->wp_model = priv->store;
+  wp_xml->thumb_width = 100;
+  wp_xml->thumb_height = 75;
+  wp_xml->thumb_factory = priv->thumb_factory;
+
+  gnome_wp_xml_load_list (wp_xml);
+  g_hash_table_foreach (wp_xml->wp_hash,
+                        (GHFunc) load_wallpapers,
+                        priv);
+
+  g_hash_table_destroy (wp_xml->wp_hash);
+  g_object_unref (wp_xml->client);
+  g_free (wp_xml);
+}
+
+BgWallpapersSource *
+bg_wallpapers_source_new (void)
+{
+  return g_object_new (BG_TYPE_WALLPAPERS_SOURCE, NULL);
+}
+
+
+GtkListStore *
+bg_wallpapers_source_get_liststore (BgWallpapersSource *source)
+{
+  return source->priv->store;
+}
diff --git a/panels/background/bg-wallpapers-source.h b/panels/background/bg-wallpapers-source.h
new file mode 100644
index 0000000..f9ad58f
--- /dev/null
+++ b/panels/background/bg-wallpapers-source.h
@@ -0,0 +1,76 @@
+/* bg-wallpapers-source.h */
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+
+#ifndef _BG_WALLPAPERS_SOURCE_H
+#define _BG_WALLPAPERS_SOURCE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BG_TYPE_WALLPAPERS_SOURCE bg_wallpapers_source_get_type()
+
+#define BG_WALLPAPERS_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  BG_TYPE_WALLPAPERS_SOURCE, BgWallpapersSource))
+
+#define BG_WALLPAPERS_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  BG_TYPE_WALLPAPERS_SOURCE, BgWallpapersSourceClass))
+
+#define BG_IS_WALLPAPERS_SOURCE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  BG_TYPE_WALLPAPERS_SOURCE))
+
+#define BG_IS_WALLPAPERS_SOURCE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  BG_TYPE_WALLPAPERS_SOURCE))
+
+#define BG_WALLPAPERS_SOURCE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  BG_TYPE_WALLPAPERS_SOURCE, BgWallpapersSourceClass))
+
+typedef struct _BgWallpapersSource BgWallpapersSource;
+typedef struct _BgWallpapersSourceClass BgWallpapersSourceClass;
+typedef struct _BgWallpapersSourcePrivate BgWallpapersSourcePrivate;
+
+struct _BgWallpapersSource
+{
+  GObject parent;
+
+  BgWallpapersSourcePrivate *priv;
+};
+
+struct _BgWallpapersSourceClass
+{
+  GObjectClass parent_class;
+};
+
+GType bg_wallpapers_source_get_type (void) G_GNUC_CONST;
+
+BgWallpapersSource *bg_wallpapers_source_new (void);
+GtkListStore       *bg_wallpapers_source_get_liststore (BgWallpapersSource *source);
+
+G_END_DECLS
+
+#endif /* _BG_WALLPAPERS_SOURCE_H */
diff --git a/panels/background/cc-background-panel.c b/panels/background/cc-background-panel.c
new file mode 100644
index 0000000..02be5d2
--- /dev/null
+++ b/panels/background/cc-background-panel.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#include <config.h>
+
+#include "cc-background-panel.h"
+#include "bg-wallpapers-source.h"
+#include "bg-pictures-source.h"
+#include "bg-colors-source.h"
+
+#ifdef HAVE_LIBSOCIALWEB
+#include "bg-flickr-source.h"
+#endif
+
+#include "gnome-wp-xml.h"
+#include "gnome-wp-item.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+G_DEFINE_DYNAMIC_TYPE (CcBackgroundPanel, cc_background_panel, CC_TYPE_PANEL)
+
+#define BACKGROUND_PANEL_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_BACKGROUND_PANEL, CcBackgroundPanelPrivate))
+
+struct _CcBackgroundPanelPrivate
+{
+  GtkBuilder *builder;
+
+  BgWallpapersSource *wallpapers_source;
+  BgPicturesSource *pictures_source;
+  BgColorsSource *colors_source;
+
+#ifdef HAVE_LIBSOCIALWEB
+  BgFlickrSource *flickr_source;
+#endif
+
+  GtkListStore *selected_store;
+
+  GConfClient *client;
+
+  GnomeDesktopThumbnailFactory *thumb_factory;
+
+  GnomeWPItem *current_background;
+  gboolean current_source_readonly;
+
+  GCancellable *copy_cancellable;
+
+  GtkWidget *spinner;
+};
+
+enum
+{
+  SOURCE_WALLPAPERS,
+  SOURCE_PICTURES,
+  SOURCE_COLORS,
+#ifdef HAVE_LIBSOCIALWEB
+  SOURCE_FLICKR
+#endif
+};
+
+
+#define WID(y) (GtkWidget *) gtk_builder_get_object (priv->builder, y)
+
+static void
+cc_background_panel_get_property (GObject    *object,
+                                  guint       property_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_background_panel_set_property (GObject      *object,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_background_panel_dispose (GObject *object)
+{
+  CcBackgroundPanelPrivate *priv = CC_BACKGROUND_PANEL (object)->priv;
+
+  if (priv->builder)
+    {
+      g_object_unref (priv->builder);
+      priv->builder = NULL;
+    }
+
+  if (priv->wallpapers_source)
+    {
+      g_object_unref (priv->wallpapers_source);
+      priv->wallpapers_source = NULL;
+    }
+
+  if (priv->pictures_source)
+    {
+      g_object_unref (priv->pictures_source);
+      priv->pictures_source = NULL;
+    }
+
+  if (priv->colors_source)
+    {
+      g_object_unref (priv->colors_source);
+      priv->colors_source = NULL;
+    }
+#ifdef HAVE_LIBSOCIALWEB
+  if (priv->flickr_source)
+    {
+      g_object_unref (priv->flickr_source);
+      priv->flickr_source = NULL;
+    }
+#endif
+
+  if (priv->client)
+    {
+      g_object_unref (priv->client);
+      priv->client = NULL;
+    }
+
+  if (priv->copy_cancellable)
+    {
+      g_object_unref (priv->copy_cancellable);
+      priv->copy_cancellable = NULL;
+    }
+
+  if (priv->thumb_factory)
+    {
+      g_object_unref (priv->thumb_factory);
+      priv->thumb_factory = NULL;
+    }
+
+  G_OBJECT_CLASS (cc_background_panel_parent_class)->dispose (object);
+}
+
+static void
+cc_background_panel_finalize (GObject *object)
+{
+  CcBackgroundPanelPrivate *priv = CC_BACKGROUND_PANEL (object)->priv;
+
+  if (priv->current_background)
+    {
+      gnome_wp_item_free (priv->current_background);
+      priv->current_background = NULL;
+    }
+
+  G_OBJECT_CLASS (cc_background_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_background_panel_class_init (CcBackgroundPanelClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (CcBackgroundPanelPrivate));
+
+  object_class->get_property = cc_background_panel_get_property;
+  object_class->set_property = cc_background_panel_set_property;
+  object_class->dispose = cc_background_panel_dispose;
+  object_class->finalize = cc_background_panel_finalize;
+}
+
+static void
+cc_background_panel_class_finalize (CcBackgroundPanelClass *klass)
+{
+
+}
+
+static void
+source_changed_cb (GtkTreeSelection         *selection,
+                   CcBackgroundPanelPrivate *priv)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkListStore *store;
+  GtkIconView *view;
+  guint type;
+
+  gtk_tree_selection_get_selected (selection, &model, &iter);
+  gtk_tree_model_get (model, &iter,
+                      1, &type,
+                      2, &priv->current_source_readonly, -1);
+
+  view = (GtkIconView *) gtk_builder_get_object (priv->builder,
+                                                 "backgrounds-iconview");
+
+  if (type == SOURCE_WALLPAPERS)
+    store = bg_wallpapers_source_get_liststore (priv->wallpapers_source);
+  else if (type == SOURCE_PICTURES)
+    store = bg_pictures_source_get_liststore (priv->pictures_source);
+  else if (type == SOURCE_COLORS)
+    store = bg_colors_source_get_liststore (priv->colors_source);
+#ifdef HAVE_LIBSOCIALWEB
+  else if (type == SOURCE_FLICKR)
+    store = bg_flickr_source_get_liststore (priv->flickr_source);
+#endif
+  else
+    store = NULL;
+
+  priv->selected_store = store;
+
+  gtk_icon_view_set_model (view, GTK_TREE_MODEL (store));
+}
+
+static void
+copy_finished_cb (GObject      *source_object,
+                  GAsyncResult *result,
+                  gpointer      pointer)
+{
+  CcBackgroundPanelPrivate *priv = (CcBackgroundPanelPrivate*) pointer;
+
+  if (priv->spinner)
+    {
+      gtk_widget_destroy (GTK_WIDGET (priv->spinner));
+      priv->spinner = NULL;
+    }
+
+  gtk_widget_show (WID ("preview-area"));
+
+}
+
+static void
+update_preview (CcBackgroundPanelPrivate *priv,
+                GnomeWPItem              *item)
+{
+  gchar *markup;
+
+  if (item && priv->current_background)
+    {
+      if (priv->current_background->pcolor)
+        gdk_color_free (priv->current_background->pcolor);
+      priv->current_background->pcolor = gdk_color_copy (item->pcolor);
+
+      if (priv->current_background->scolor)
+        gdk_color_free (priv->current_background->scolor);
+      priv->current_background->scolor = gdk_color_copy (item->scolor);
+
+
+
+      g_free (priv->current_background->filename);
+      priv->current_background->filename = g_strdup (item->filename);
+
+      g_free (priv->current_background->name);
+      priv->current_background->name = g_strdup (item->name);
+
+      priv->current_background->options = item->options;
+    }
+
+
+  if (!priv->current_source_readonly)
+    gtk_widget_show (WID ("edit-hbox"));
+  else
+    gtk_widget_hide (WID ("edit-hbox"));
+
+  if (priv->current_background)
+    {
+      markup = g_strdup_printf ("<b>%s</b>", priv->current_background->name);
+      gtk_label_set_markup (GTK_LABEL (WID ("background-label")), markup);
+      g_free (markup);
+
+      gtk_color_button_set_color (GTK_COLOR_BUTTON (WID ("style-color")),
+                                  priv->current_background->pcolor);
+
+      gtk_combo_box_set_active (GTK_COMBO_BOX (WID ("style-combobox")),
+                                priv->current_background->options);
+    }
+
+  gtk_widget_queue_draw (WID ("preview-area"));
+}
+
+static void
+backgrounds_changed_cb (GtkIconView              *icon_view,
+                        CcBackgroundPanelPrivate *priv)
+{
+  GtkTreeIter iter;
+  GList *list;
+  GtkTreeModel *model;
+  GnomeWPItem *item;
+  GConfChangeSet *cs;
+  gchar *pcolor, *scolor;
+
+  list = gtk_icon_view_get_selected_items (icon_view);
+
+  if (!list)
+    return;
+
+  model = gtk_icon_view_get_model (icon_view);
+
+  gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) list->data);
+
+  g_list_free (list);
+
+  gtk_tree_model_get (model, &iter, 1, &item, -1);
+
+  cs = gconf_change_set_new ();
+
+  if (!g_strcmp0 (item->filename, "(none)"))
+    {
+      gconf_change_set_set_string (cs, WP_OPTIONS_KEY, "none");
+      gconf_change_set_set_string (cs, WP_FILE_KEY, "");
+    }
+  else if (item->source_url)
+    {
+      GFile *source, *dest;
+      gchar *cache_path;
+      GdkPixbuf *pixbuf;
+
+      cache_path = g_build_filename (g_get_user_cache_dir (),
+                                     "background",
+                                     NULL);
+
+      source = g_file_new_for_uri (item->source_url);
+      dest = g_file_new_for_path (cache_path);
+
+      /* create a blank image to use until the source image is ready */
+      pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
+      gdk_pixbuf_fill (pixbuf, 0x00000000);
+      gdk_pixbuf_save (pixbuf, cache_path, "png", NULL, NULL);
+      g_object_unref (pixbuf);
+
+      if (priv->copy_cancellable)
+        {
+          g_cancellable_cancel (priv->copy_cancellable);
+          g_cancellable_reset (priv->copy_cancellable);
+
+        }
+
+      if (priv->spinner)
+        {
+          gtk_widget_destroy (GTK_WIDGET (priv->spinner));
+          priv->spinner = NULL;
+        }
+
+      /* create a spinner while the file downloads */
+      priv->spinner = gtk_spinner_new ();
+      gtk_spinner_start (GTK_SPINNER (priv->spinner));
+      gtk_box_pack_start (GTK_BOX (WID ("details-box")), priv->spinner, FALSE,
+                          FALSE, 0);
+      gtk_box_reorder_child (GTK_BOX (WID ("details-box")), priv->spinner, 0);
+      gtk_widget_set_size_request (priv->spinner, 150, 75);
+      gtk_widget_show (priv->spinner);
+      gtk_widget_hide (WID ("preview-area"));
+
+
+      g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE,
+                         G_PRIORITY_DEFAULT, priv->copy_cancellable,
+                         NULL, NULL,
+                         copy_finished_cb, priv);
+
+      gconf_change_set_set_string (cs, WP_FILE_KEY,
+                                   cache_path);
+      gconf_change_set_set_string (cs, WP_OPTIONS_KEY,
+                                   wp_item_option_to_string (item->options));
+      g_free (item->filename);
+      item->filename = cache_path;
+    }
+  else
+    {
+       gchar *uri;
+
+       if (g_utf8_validate (item->filename, -1, NULL))
+         uri = g_strdup (item->filename);
+       else
+         uri = g_filename_to_utf8 (item->filename, -1, NULL, NULL, NULL);
+
+       if (uri == NULL)
+         {
+           g_warning ("Failed to convert filename to UTF-8: %s",
+                      item->filename);
+         }
+       else
+         {
+           gconf_change_set_set_string (cs, WP_FILE_KEY, uri);
+           g_free (uri);
+         }
+
+       gconf_change_set_set_string (cs, WP_OPTIONS_KEY,
+                                    wp_item_option_to_string (item->options));
+    }
+
+  gconf_change_set_set_string (cs, WP_SHADING_KEY,
+                               wp_item_shading_to_string (item->shade_type));
+
+  pcolor = gdk_color_to_string (item->pcolor);
+  scolor = gdk_color_to_string (item->scolor);
+  gconf_change_set_set_string (cs, WP_PCOLOR_KEY, pcolor);
+  gconf_change_set_set_string (cs, WP_SCOLOR_KEY, scolor);
+  g_free (pcolor);
+  g_free (scolor);
+
+  gconf_client_commit_change_set (priv->client, cs, TRUE, NULL);
+
+  gconf_change_set_unref (cs);
+
+  /* update the preview information */
+  update_preview (priv, item);
+}
+
+static gboolean
+preview_expose_cb (GtkWidget         *widget,
+                   GdkEventExpose    *expose,
+                   CcBackgroundPanel *panel)
+{
+  cairo_t *cr;
+  GtkAllocation allocation;
+  CcBackgroundPanelPrivate *priv = panel->priv;
+  GdkPixbuf *pixbuf = NULL;
+
+  cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  if (priv->current_background)
+    {
+      pixbuf = gnome_wp_item_get_thumbnail (priv->current_background,
+                                            priv->thumb_factory,
+                                            allocation.width,
+                                            allocation.height);
+      g_object_ref (pixbuf);
+    }
+
+  if (pixbuf)
+    {
+      gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+
+      cairo_paint (cr);
+
+      g_object_unref (pixbuf);
+    }
+
+  cairo_destroy (cr);
+
+  return TRUE;
+}
+
+static void
+style_changed_cb (GtkComboBox       *box,
+                  CcBackgroundPanel *panel)
+{
+  CcBackgroundPanelPrivate *priv = panel->priv;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gchar *value;
+
+  gtk_combo_box_get_active_iter (box, &iter);
+
+  model = gtk_combo_box_get_model (box);
+
+  gtk_tree_model_get (model, &iter, 1, &value, -1);
+
+  gconf_client_set_string (priv->client,
+                           "/desktop/gnome/background/picture_options",
+                           value, NULL);
+
+  g_free (value);
+
+  if (priv->current_background)
+    priv->current_background->options = gtk_combo_box_get_active (box);
+
+  update_preview (priv, NULL);
+}
+
+static void
+color_changed_cb (GtkColorButton    *button,
+                  CcBackgroundPanel *panel)
+{
+  CcBackgroundPanelPrivate *priv = panel->priv;
+  GdkColor color;
+  gchar *value;
+
+  gtk_color_button_get_color (button, &color);
+
+  if (priv->current_background)
+    *priv->current_background->pcolor = color;
+
+  value = gdk_color_to_string (&color);
+
+  gconf_client_set_string (priv->client,
+                           "/desktop/gnome/background/primary_color",
+                           value, NULL);
+
+  gconf_client_set_string (priv->client,
+                           "/desktop/gnome/background/secondary_color",
+                           value, NULL);
+
+  g_free (value);
+
+  update_preview (priv, NULL);
+}
+
+static void
+cc_background_panel_init (CcBackgroundPanel *self)
+{
+  CcBackgroundPanelPrivate *priv;
+  gchar *objects[] = { "backgrounds-liststore", "style-liststore",
+      "sources-liststore", "background-panel", NULL };
+  GError *err = NULL;
+  GtkWidget *widget;
+  GtkTreeSelection *selection;
+  gint width, height;
+  GtkListStore *store;
+  gchar *filename;
+
+  priv = self->priv = BACKGROUND_PANEL_PRIVATE (self);
+
+  priv->builder = gtk_builder_new ();
+
+  gtk_builder_add_objects_from_file (priv->builder,
+                                     DATADIR"/background.ui",
+                                     objects, &err);
+
+  if (err)
+    {
+      g_warning ("Could not load ui: %s", err->message);
+      g_error_free (err);
+      return;
+    }
+
+  priv->client = gconf_client_get_default ();
+
+  store = (GtkListStore*) gtk_builder_get_object (priv->builder,
+                                                  "sources-liststore");
+
+  priv->pictures_source = bg_pictures_source_new ();
+  gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                     0, _("Wallpapers"),
+                                     1, SOURCE_WALLPAPERS,
+                                     2, TRUE, -1);
+
+  priv->wallpapers_source = bg_wallpapers_source_new ();
+  gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                     0, _("Pictures Folder"),
+                                     1, SOURCE_PICTURES,
+                                     2, FALSE, -1);
+
+  priv->colors_source = bg_colors_source_new ();
+  gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                     0, _("Colors"),
+                                     1, SOURCE_COLORS,
+                                     2, TRUE, -1);
+
+#ifdef HAVE_LIBSOCIALWEB
+  priv->flickr_source = bg_flickr_source_new ();
+  gtk_list_store_insert_with_values (store, NULL, G_MAXINT,
+                                     0, _("Flickr"),
+                                     1, SOURCE_FLICKR,
+                                     2, FALSE, -1);
+#endif
+
+
+  /* add the top level widget */
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "background-panel");
+
+  gtk_container_add (GTK_CONTAINER (self), widget);
+  gtk_widget_show_all (GTK_WIDGET (self));
+
+  /* connect to source change signal */
+  widget = WID ("sources-treeview");
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+  g_signal_connect (selection, "changed", G_CALLBACK (source_changed_cb), priv);
+
+  /* connect to the background iconview change signal */
+  widget = WID ("backgrounds-iconview");
+  g_signal_connect (widget, "selection-changed",
+                    G_CALLBACK (backgrounds_changed_cb),
+                    priv);
+
+  /* setup preview area */
+  widget = WID ("preview-area");
+  g_signal_connect (widget, "expose-event", G_CALLBACK (preview_expose_cb),
+                    self);
+
+
+  width = 150;
+  height = width * ((double) gdk_screen_get_height (gdk_screen_get_default ()) /
+    (double) gdk_screen_get_width (gdk_screen_get_default ()));
+
+  gtk_widget_set_size_request (widget, width, height);
+
+  g_signal_connect (WID ("style-combobox"), "changed",
+                    G_CALLBACK (style_changed_cb), self);
+
+  g_signal_connect (WID ("style-color"), "color-set",
+                    G_CALLBACK (color_changed_cb), self);
+
+  priv->copy_cancellable = g_cancellable_new ();
+
+  priv->thumb_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
+
+  /* initalise the current background information from gconf */
+  filename = gconf_client_get_string (priv->client, WP_FILE_KEY, NULL);
+  if (!filename || !g_strcmp0 (filename, ""))
+    {
+      g_free (filename);
+      filename = g_strdup ("(none)");
+    }
+
+  priv->current_background = g_new0 (GnomeWPItem, 1);
+  priv->current_background->filename = filename;
+  priv->current_background->name = g_strdup ("");
+
+  gnome_wp_item_update (priv->current_background);
+  gnome_wp_item_ensure_gnome_bg (priv->current_background);
+
+  update_preview (priv, NULL);
+}
+
+void
+cc_background_panel_register (GIOModule *module)
+{
+  cc_background_panel_register_type (G_TYPE_MODULE (module));
+  g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
+                                  CC_TYPE_BACKGROUND_PANEL,
+                                  "background", 0);
+}
+
diff --git a/panels/background/cc-background-panel.h b/panels/background/cc-background-panel.h
new file mode 100644
index 0000000..d9836b1
--- /dev/null
+++ b/panels/background/cc-background-panel.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Intel, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+
+#ifndef _CC_BACKGROUND_PANEL_H
+#define _CC_BACKGROUND_PANEL_H
+
+#include <libgnome-control-center/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_PANEL cc_background_panel_get_type()
+
+#define CC_BACKGROUND_PANEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  CC_TYPE_BACKGROUND_PANEL, CcBackgroundPanel))
+
+#define CC_BACKGROUND_PANEL_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  CC_TYPE_BACKGROUND_PANEL, CcBackgroundPanelClass))
+
+#define CC_IS_BACKGROUND_PANEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  CC_TYPE_BACKGROUND_PANEL))
+
+#define CC_IS_BACKGROUND_PANEL_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  CC_TYPE_BACKGROUND_PANEL))
+
+#define CC_BACKGROUND_PANEL_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  CC_TYPE_BACKGROUND_PANEL, CcBackgroundPanelClass))
+
+typedef struct _CcBackgroundPanel CcBackgroundPanel;
+typedef struct _CcBackgroundPanelClass CcBackgroundPanelClass;
+typedef struct _CcBackgroundPanelPrivate CcBackgroundPanelPrivate;
+
+struct _CcBackgroundPanel
+{
+  CcPanel parent;
+
+  CcBackgroundPanelPrivate *priv;
+};
+
+struct _CcBackgroundPanelClass
+{
+  CcPanelClass parent_class;
+};
+
+GType cc_background_panel_get_type (void) G_GNUC_CONST;
+
+void  cc_background_panel_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* _CC_BACKGROUND_PANEL_H */
diff --git a/panels/background/gnome-background-panel.desktop.in.in b/panels/background/gnome-background-panel.desktop.in.in
new file mode 100644
index 0000000..67b540d
--- /dev/null
+++ b/panels/background/gnome-background-panel.desktop.in.in
@@ -0,0 +1,11 @@
+[Desktop Entry]
+_Name=Background
+_Comment=Change the background
+Exec=gnome-control-center background
+Icon=preferences-desktop-wallpaper
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;
+OnlyShowIn=GNOME;
+X-GNOME-Settings-Panel=background
diff --git a/panels/background/gnome-wp-info.c b/panels/background/gnome-wp-info.c
new file mode 100644
index 0000000..7df6030
--- /dev/null
+++ b/panels/background/gnome-wp-info.c
@@ -0,0 +1,87 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include "gnome-wp-info.h"
+
+GnomeWPInfo * gnome_wp_info_new (const gchar * uri,
+				 GnomeDesktopThumbnailFactory * thumbs) {
+  GnomeWPInfo *wp;
+  GFile *file;
+  GFileInfo *info;
+
+  file = g_file_new_for_commandline_arg (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_TIME_MODIFIED,
+                            G_FILE_QUERY_INFO_NONE,
+                            NULL, NULL);
+  g_object_unref (file);
+
+  if (info == NULL || g_file_info_get_content_type (info) == NULL) {
+    if (!strcmp (uri, "(none)")) {
+      wp = g_new0 (GnomeWPInfo, 1);
+
+      wp->mime_type = g_strdup ("image/x-no-data");
+      wp->uri = g_strdup (uri);
+      wp->name = g_strdup (_("No Desktop Background"));
+      wp->size = 0;
+    } else {
+      wp = NULL;
+    }
+  } else {
+    wp = g_new0 (GnomeWPInfo, 1);
+
+    wp->uri = g_strdup (uri);
+
+    wp->name = g_strdup (g_file_info_get_name (info));
+    if (g_file_info_get_content_type (info) != NULL)
+      wp->mime_type = g_strdup (g_file_info_get_content_type (info));
+    wp->size = g_file_info_get_size (info);
+    wp->mtime = g_file_info_get_attribute_uint64 (info,
+                                                  G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+    wp->thumburi = gnome_desktop_thumbnail_factory_lookup (thumbs,
+							   uri,
+							   wp->mtime);
+  }
+
+  if (info != NULL)
+    g_object_unref (info);
+
+  return wp;
+}
+
+void gnome_wp_info_free (GnomeWPInfo * info) {
+  if (info == NULL) {
+    return;
+  }
+
+  g_free (info->uri);
+  g_free (info->thumburi);
+  g_free (info->name);
+  g_free (info->mime_type);
+}
diff --git a/panels/background/gnome-wp-info.h b/panels/background/gnome-wp-info.h
new file mode 100644
index 0000000..ea1051e
--- /dev/null
+++ b/panels/background/gnome-wp-info.h
@@ -0,0 +1,45 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GNOME_WP_INFO_H_
+#define _GNOME_WP_INFO_H_
+
+#include <glib.h>
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+
+typedef struct _GnomeWPInfo GnomeWPInfo;
+
+struct _GnomeWPInfo {
+  gchar * uri;
+  gchar * thumburi;
+  gchar * name;
+  gchar * mime_type;
+
+  goffset size;
+
+  time_t mtime;
+};
+
+GnomeWPInfo * gnome_wp_info_new (const gchar * uri,
+				 GnomeDesktopThumbnailFactory * thumbs);
+void gnome_wp_info_free (GnomeWPInfo * info);
+
+#endif
+
diff --git a/panels/background/gnome-wp-item.c b/panels/background/gnome-wp-item.c
new file mode 100644
index 0000000..09685e1
--- /dev/null
+++ b/panels/background/gnome-wp-item.c
@@ -0,0 +1,315 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
+#include <string.h>
+#include "gnome-wp-item.h"
+
+static GConfEnumStringPair options_lookup[] = {
+  { GNOME_BG_PLACEMENT_CENTERED, "centered" },
+  { GNOME_BG_PLACEMENT_FILL_SCREEN, "stretched" },
+  { GNOME_BG_PLACEMENT_SCALED, "scaled" },
+  { GNOME_BG_PLACEMENT_ZOOMED, "zoom" },
+  { GNOME_BG_PLACEMENT_TILED, "wallpaper" },
+  { GNOME_BG_PLACEMENT_SPANNED, "spanned" },
+  { 0, NULL }
+};
+
+static GConfEnumStringPair shade_lookup[] = {
+  { GNOME_BG_COLOR_SOLID, "solid" },
+  { GNOME_BG_COLOR_H_GRADIENT, "horizontal-gradient" },
+  { GNOME_BG_COLOR_V_GRADIENT, "vertical-gradient" },
+  { 0, NULL }
+};
+
+const gchar *wp_item_option_to_string (GnomeBGPlacement type)
+{
+  return gconf_enum_to_string (options_lookup, type);
+}
+
+const gchar *wp_item_shading_to_string (GnomeBGColorType type)
+{
+  return gconf_enum_to_string (shade_lookup, type);
+}
+
+GnomeBGPlacement wp_item_string_to_option (const gchar *option)
+{
+  int i = GNOME_BG_PLACEMENT_SCALED;
+  gconf_string_to_enum (options_lookup, option, &i);
+  return i;
+}
+
+GnomeBGColorType wp_item_string_to_shading (const gchar *shade_type)
+{
+  int i = GNOME_BG_COLOR_SOLID;
+  gconf_string_to_enum (shade_lookup, shade_type, &i);
+  return i;
+}
+
+static void set_bg_properties (GnomeWPItem *item)
+{
+  if (!item->bg)
+    return;
+
+  if (item->filename)
+    gnome_bg_set_filename (item->bg, item->filename);
+
+  gnome_bg_set_color (item->bg, item->shade_type, item->pcolor, item->scolor);
+  gnome_bg_set_placement (item->bg, item->options);
+}
+
+void gnome_wp_item_ensure_gnome_bg (GnomeWPItem *item)
+{
+  if (!item->bg) {
+    item->bg = gnome_bg_new ();
+
+    g_object_set_data (G_OBJECT (item->bg), "gnome-wp-item", item);
+
+    set_bg_properties (item);
+  }
+}
+
+void gnome_wp_item_update (GnomeWPItem *item) {
+  GConfClient *client;
+  GdkColor color1 = { 0, 0, 0, 0 }, color2 = { 0, 0, 0, 0 };
+  gchar *s;
+
+  client = gconf_client_get_default ();
+
+  s = gconf_client_get_string (client, WP_OPTIONS_KEY, NULL);
+  item->options = wp_item_string_to_option (s);
+  g_free (s);
+
+  s = gconf_client_get_string (client, WP_SHADING_KEY, NULL);
+  item->shade_type = wp_item_string_to_shading (s);
+  g_free (s);
+
+  s = gconf_client_get_string (client, WP_PCOLOR_KEY, NULL);
+  if (s != NULL) {
+    gdk_color_parse (s, &color1);
+    g_free (s);
+  }
+
+  s = gconf_client_get_string (client, WP_SCOLOR_KEY, NULL);
+  if (s != NULL) {
+    gdk_color_parse (s, &color2);
+    g_free (s);
+  }
+
+  g_object_unref (client);
+
+  if (item->pcolor != NULL)
+    gdk_color_free (item->pcolor);
+
+  if (item->scolor != NULL)
+    gdk_color_free (item->scolor);
+
+  item->pcolor = gdk_color_copy (&color1);
+  item->scolor = gdk_color_copy (&color2);
+
+  set_bg_properties (item);
+}
+
+GnomeWPItem * gnome_wp_item_new (const gchar * filename,
+				 GHashTable * wallpapers,
+				 GnomeDesktopThumbnailFactory * thumbnails) {
+  GnomeWPItem *item = g_new0 (GnomeWPItem, 1);
+
+  item->filename = g_strdup (filename);
+  item->fileinfo = gnome_wp_info_new (filename, thumbnails);
+
+  if (item->fileinfo != NULL && item->fileinfo->mime_type != NULL &&
+      (g_str_has_prefix (item->fileinfo->mime_type, "image/") ||
+       strcmp (item->fileinfo->mime_type, "application/xml") == 0)) {
+
+    if (g_utf8_validate (item->fileinfo->name, -1, NULL))
+      item->name = g_strdup (item->fileinfo->name);
+    else
+      item->name = g_filename_to_utf8 (item->fileinfo->name, -1, NULL,
+				       NULL, NULL);
+
+    gnome_wp_item_update (item);
+    gnome_wp_item_ensure_gnome_bg (item);
+    gnome_wp_item_update_description (item);
+
+    if (wallpapers)
+      g_hash_table_insert (wallpapers, item->filename, item);
+  } else {
+    gnome_wp_item_free (item);
+    item = NULL;
+  }
+
+  return item;
+}
+
+void gnome_wp_item_free (GnomeWPItem * item) {
+  if (item == NULL) {
+    return;
+  }
+
+  g_free (item->name);
+  g_free (item->filename);
+  g_free (item->description);
+
+  if (item->pcolor != NULL)
+    gdk_color_free (item->pcolor);
+
+  if (item->scolor != NULL)
+    gdk_color_free (item->scolor);
+
+  gnome_wp_info_free (item->fileinfo);
+  if (item->bg)
+    g_object_unref (item->bg);
+
+  gtk_tree_row_reference_free (item->rowref);
+
+  g_free (item);
+}
+
+static GdkPixbuf *
+add_slideshow_frame (GdkPixbuf *pixbuf)
+{
+  GdkPixbuf *sheet, *sheet2;
+  GdkPixbuf *tmp;
+  gint w, h;
+
+  w = gdk_pixbuf_get_width (pixbuf);
+  h = gdk_pixbuf_get_height (pixbuf);
+
+  sheet = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, w, h);
+  gdk_pixbuf_fill (sheet, 0x00000000);
+  sheet2 = gdk_pixbuf_new_subpixbuf (sheet, 1, 1, w - 2, h - 2);
+  gdk_pixbuf_fill (sheet2, 0xffffffff);
+  g_object_unref (sheet2);
+
+  tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w + 6, h + 6);
+
+  gdk_pixbuf_fill (tmp, 0x00000000);
+  gdk_pixbuf_composite (sheet, tmp, 6, 6, w, h, 6.0, 6.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255);
+  gdk_pixbuf_composite (sheet, tmp, 3, 3, w, h, 3.0, 3.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255);
+  gdk_pixbuf_composite (pixbuf, tmp, 0, 0, w, h, 0.0, 0.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255);
+
+  g_object_unref (sheet);
+
+  return tmp;
+}
+
+GdkPixbuf * gnome_wp_item_get_frame_thumbnail (GnomeWPItem * item,
+					       GnomeDesktopThumbnailFactory * thumbs,
+                                               int width,
+                                               int height,
+                                               gint frame) {
+  GdkPixbuf *pixbuf = NULL;
+
+  set_bg_properties (item);
+
+  if (frame != -1)
+    pixbuf = gnome_bg_create_frame_thumbnail (item->bg, thumbs, gdk_screen_get_default (), width, height, frame);
+  else
+    pixbuf = gnome_bg_create_thumbnail (item->bg, thumbs, gdk_screen_get_default(), width, height);
+
+  if (pixbuf && gnome_bg_changes_with_time (item->bg))
+    {
+      GdkPixbuf *tmp;
+
+      tmp = add_slideshow_frame (pixbuf);
+      g_object_unref (pixbuf);
+      pixbuf = tmp;
+    }
+
+  gnome_bg_get_image_size (item->bg, thumbs, width, height, &item->width, &item->height);
+
+  return pixbuf;
+}
+
+
+GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item,
+					 GnomeDesktopThumbnailFactory * thumbs,
+                                         gint width,
+                                         gint height) {
+  return gnome_wp_item_get_frame_thumbnail (item, thumbs, width, height, -1);
+}
+
+void gnome_wp_item_update_description (GnomeWPItem * item) {
+  g_free (item->description);
+
+  if (!strcmp (item->filename, "(none)")) {
+    item->description = g_strdup (item->name);
+  } else {
+    const gchar *description;
+    gchar *size;
+    gchar *dirname = g_path_get_dirname (item->filename);
+
+    description = NULL;
+    size = NULL;
+
+    if (strcmp (item->fileinfo->mime_type, "application/xml") == 0)
+      {
+        if (gnome_bg_changes_with_time (item->bg))
+          description = _("Slide Show");
+        else if (item->width > 0 && item->height > 0)
+          description = _("Image");
+      }
+    else
+      description = g_content_type_get_description (item->fileinfo->mime_type);
+
+    if (gnome_bg_has_multiple_sizes (item->bg))
+      size = g_strdup (_("multiple sizes"));
+    else if (item->width > 0 && item->height > 0) {
+      /* translators: x pixel(s) by y pixel(s) */
+      size = g_strdup_printf (_("%d %s by %d %s"),
+                              item->width,
+                              ngettext ("pixel", "pixels", item->width),
+                              item->height,
+                              ngettext ("pixel", "pixels", item->height));
+    }
+
+    if (description && size) {
+      /* translators: <b>wallpaper name</b>
+       * mime type, size
+       * Folder: /path/to/file
+       */
+      item->description = g_markup_printf_escaped (_("<b>%s</b>\n"
+                                                     "%s, %s\n"
+                                                     "Folder: %s"),
+                                                   item->name,
+                                                   description,
+                                                   size,
+                                                   dirname);
+    } else {
+      /* translators: <b>wallpaper name</b>
+       * Image missing
+       * Folder: /path/to/file
+       */
+      item->description = g_markup_printf_escaped (_("<b>%s</b>\n"
+                                                     "%s\n"
+                                                     "Folder: %s"),
+                                                   item->name,
+                                                   _("Image missing"),
+                                                   dirname);
+    }
+
+    g_free (size);
+    g_free (dirname);
+  }
+}
diff --git a/panels/background/gnome-wp-item.h b/panels/background/gnome-wp-item.h
new file mode 100644
index 0000000..d7b2469
--- /dev/null
+++ b/panels/background/gnome-wp-item.h
@@ -0,0 +1,92 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <glib.h>
+#include <gio/gio.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+#include <libgnomeui/gnome-bg.h>
+
+#include "gnome-wp-info.h"
+
+#ifndef _GNOME_WP_ITEM_H_
+#define _GNOME_WP_ITEM_H_
+
+#define WP_PATH_KEY "/desktop/gnome/background"
+#define WP_FILE_KEY WP_PATH_KEY "/picture_filename"
+#define WP_OPTIONS_KEY WP_PATH_KEY "/picture_options"
+#define WP_SHADING_KEY WP_PATH_KEY "/color_shading_type"
+#define WP_PCOLOR_KEY WP_PATH_KEY "/primary_color"
+#define WP_SCOLOR_KEY WP_PATH_KEY "/secondary_color"
+
+typedef struct _GnomeWPItem GnomeWPItem;
+
+struct _GnomeWPItem {
+  GnomeBG *bg;
+
+  gchar * name;
+  gchar * filename;
+  gchar * description;
+  GnomeBGPlacement options;
+  GnomeBGColorType shade_type;
+
+  gchar * source_url;
+
+  /* Where the Item is in the List */
+  GtkTreeRowReference * rowref;
+
+  /* Real colors */
+  GdkColor * pcolor;
+  GdkColor * scolor;
+
+  GnomeWPInfo * fileinfo;
+
+  /* Did the user remove us? */
+  gboolean deleted;
+
+  /* Width and Height of the original image */
+  gint width;
+  gint height;
+};
+
+GnomeWPItem * gnome_wp_item_new (const gchar *filename,
+				 GHashTable *wallpapers,
+				 GnomeDesktopThumbnailFactory *thumbnails);
+
+void gnome_wp_item_free (GnomeWPItem *item);
+GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem *item,
+					 GnomeDesktopThumbnailFactory *thumbs,
+                                         gint width,
+                                         gint height);
+GdkPixbuf * gnome_wp_item_get_frame_thumbnail (GnomeWPItem *item,
+                                               GnomeDesktopThumbnailFactory *thumbs,
+                                               gint width,
+                                               gint height,
+                                               gint frame);
+void gnome_wp_item_update (GnomeWPItem *item);
+void gnome_wp_item_update_description (GnomeWPItem *item);
+void gnome_wp_item_ensure_gnome_bg (GnomeWPItem *item);
+
+const gchar *wp_item_option_to_string (GnomeBGPlacement type);
+const gchar *wp_item_shading_to_string (GnomeBGColorType type);
+GnomeBGPlacement wp_item_string_to_option (const gchar *option);
+GnomeBGColorType wp_item_string_to_shading (const gchar *shade_type);
+
+#endif
diff --git a/panels/background/gnome-wp-xml.c b/panels/background/gnome-wp-xml.c
new file mode 100644
index 0000000..51aba44
--- /dev/null
+++ b/panels/background/gnome-wp-xml.c
@@ -0,0 +1,449 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "gnome-wp-item.h"
+#include "gnome-wp-xml.h"
+#include <gio/gio.h>
+#include <string.h>
+#include <libxml/parser.h>
+
+static gboolean gnome_wp_xml_get_bool (const xmlNode * parent,
+				       const gchar * prop_name) {
+  xmlChar * prop;
+  gboolean ret_val = FALSE;
+
+  g_return_val_if_fail (parent != NULL, FALSE);
+  g_return_val_if_fail (prop_name != NULL, FALSE);
+
+  prop = xmlGetProp ((xmlNode *) parent, (xmlChar*)prop_name);
+  if (prop != NULL) {
+    if (!g_ascii_strcasecmp ((gchar *)prop, "true") || !g_ascii_strcasecmp ((gchar *)prop, "1")) {
+      ret_val = TRUE;
+    } else {
+      ret_val = FALSE;
+    }
+    g_free (prop);
+  }
+
+  return ret_val;
+}
+
+static void gnome_wp_xml_set_bool (const xmlNode * parent,
+				   const xmlChar * prop_name, gboolean value) {
+  g_return_if_fail (parent != NULL);
+  g_return_if_fail (prop_name != NULL);
+
+  if (value) {
+    xmlSetProp ((xmlNode *) parent, prop_name, (xmlChar *)"true");
+  } else {
+    xmlSetProp ((xmlNode *) parent, prop_name, (xmlChar *)"false");
+  }
+}
+
+static void gnome_wp_load_legacy (GnomeWpXml *data) {
+  FILE * fp;
+  gchar * foo, * filename;
+
+  filename = g_build_filename (g_get_home_dir (), ".gnome2",
+			       "wallpapers.list", NULL);
+
+  if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
+    if ((fp = fopen (filename, "r")) != NULL) {
+      foo = (gchar *) g_malloc (sizeof (gchar) * 4096);
+      while (fgets (foo, 4096, fp)) {
+	GnomeWPItem * item;
+
+	if (foo[strlen (foo) - 1] == '\n') {
+	  foo[strlen (foo) - 1] = '\0';
+	}
+
+	item = g_hash_table_lookup (data->wp_hash, foo);
+	if (item != NULL) {
+	  continue;
+	}
+
+	if (!g_file_test (foo, G_FILE_TEST_EXISTS)) {
+	  continue;
+	}
+
+	item = gnome_wp_item_new (foo, data->wp_hash, data->thumb_factory);
+	if (item != NULL && item->fileinfo == NULL) {
+	  gnome_wp_item_free (item);
+	}
+      }
+      fclose (fp);
+      g_free (foo);
+    }
+  }
+
+  g_free (filename);
+}
+
+static void gnome_wp_xml_load_xml (GnomeWpXml *data,
+				   const gchar * filename) {
+  xmlDoc * wplist;
+  xmlNode * root, * list, * wpa;
+  xmlChar * nodelang;
+  const gchar * const * syslangs;
+  GdkColor color1, color2;
+  gint i;
+
+  wplist = xmlParseFile (filename);
+
+  if (!wplist)
+    return;
+
+  syslangs = g_get_language_names ();
+
+  root = xmlDocGetRootElement (wplist);
+
+  for (list = root->children; list != NULL; list = list->next) {
+    if (!strcmp ((gchar *)list->name, "wallpaper")) {
+      GnomeWPItem * wp;
+      gchar *pcolor = NULL, *scolor = NULL;
+      gchar *s;
+      gboolean have_scale = FALSE, have_shade = FALSE;
+
+      wp = g_new0 (GnomeWPItem, 1);
+
+      wp->deleted = gnome_wp_xml_get_bool (list, "deleted");
+
+      for (wpa = list->children; wpa != NULL; wpa = wpa->next) {
+	if (wpa->type == XML_COMMENT_NODE) {
+	  continue;
+	} else if (!strcmp ((gchar *)wpa->name, "filename")) {
+	  if (wpa->last != NULL && wpa->last->content != NULL) {
+	    const char * none = "(none)";
+	    gchar *content = g_strstrip ((gchar *)wpa->last->content);
+
+	    if (!strcmp (content, none))
+	      wp->filename = g_strdup (content);
+	    else if (g_utf8_validate (content, -1, NULL) &&
+		     g_file_test (content, G_FILE_TEST_EXISTS))
+	      wp->filename = g_strdup (content);
+	    else
+	      wp->filename = g_filename_from_utf8 (content, -1, NULL, NULL, NULL);
+	  } else {
+	    break;
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "name")) {
+	  if (wpa->last != NULL && wpa->last->content != NULL) {
+	    nodelang = xmlNodeGetLang (wpa->last);
+
+	    if (wp->name == NULL && nodelang == NULL) {
+	       wp->name = g_strdup (g_strstrip ((gchar *)wpa->last->content));
+            } else {
+	       for (i = 0; syslangs[i] != NULL; i++) {
+	         if (!strcmp (syslangs[i], (gchar *)nodelang)) {
+	           g_free (wp->name);
+	           wp->name = g_strdup (g_strstrip ((gchar *)wpa->last->content));
+	           break;
+	         }
+	       }
+	    }
+
+	    xmlFree (nodelang);
+	  } else {
+	    break;
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "options")) {
+	  if (wpa->last != NULL) {
+	    wp->options = wp_item_string_to_option (g_strstrip ((gchar *)wpa->last->content));
+	    have_scale = TRUE;
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "shade_type")) {
+	  if (wpa->last != NULL) {
+	    wp->shade_type = wp_item_string_to_shading (g_strstrip ((gchar *)wpa->last->content));
+	    have_shade = TRUE;
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "pcolor")) {
+	  if (wpa->last != NULL) {
+	    pcolor = g_strdup (g_strstrip ((gchar *)wpa->last->content));
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "scolor")) {
+	  if (wpa->last != NULL) {
+	    scolor = g_strdup (g_strstrip ((gchar *)wpa->last->content));
+	  }
+	} else if (!strcmp ((gchar *)wpa->name, "text")) {
+	  /* Do nothing here, libxml2 is being weird */
+	} else {
+	  g_warning ("Unknown Tag: %s", wpa->name);
+	}
+      }
+
+      /* Make sure we don't already have this one and that filename exists */
+      if (wp->filename == NULL ||
+	  g_hash_table_lookup (data->wp_hash, wp->filename) != NULL) {
+
+	gnome_wp_item_free (wp);
+	g_free (pcolor);
+	g_free (scolor);
+	continue;
+      }
+
+      /* Verify the colors and alloc some GdkColors here */
+      if (!have_scale) {
+        s = gconf_client_get_string (data->client, WP_OPTIONS_KEY, NULL);
+        wp->options = wp_item_string_to_option (s);
+        g_free (s);
+      }
+
+      if (!have_shade) {
+        s = gconf_client_get_string (data->client, WP_SHADING_KEY, NULL);
+        wp->shade_type = wp_item_string_to_shading (s);
+        g_free (s);
+      }
+
+      if (pcolor == NULL) {
+	pcolor = gconf_client_get_string (data->client,
+					  WP_PCOLOR_KEY, NULL);
+      }
+      if (scolor == NULL) {
+	scolor = gconf_client_get_string (data->client,
+					  WP_SCOLOR_KEY, NULL);
+      }
+      gdk_color_parse (pcolor, &color1);
+      gdk_color_parse (scolor, &color2);
+      g_free (pcolor);
+      g_free (scolor);
+
+      wp->pcolor = gdk_color_copy (&color1);
+      wp->scolor = gdk_color_copy (&color2);
+
+      if ((wp->filename != NULL &&
+	   g_file_test (wp->filename, G_FILE_TEST_EXISTS)) ||
+	  !strcmp (wp->filename, "(none)")) {
+	wp->fileinfo = gnome_wp_info_new (wp->filename, data->thumb_factory);
+
+	if (wp->name == NULL || !strcmp (wp->filename, "(none)")) {
+	  g_free (wp->name);
+	  wp->name = g_strdup (wp->fileinfo->name);
+	}
+
+        gnome_wp_item_ensure_gnome_bg (wp);
+	gnome_wp_item_update_description (wp);
+	g_hash_table_insert (data->wp_hash, wp->filename, wp);
+      } else {
+	gnome_wp_item_free (wp);
+        wp = NULL;
+      }
+    }
+  }
+  xmlFreeDoc (wplist);
+}
+
+static void gnome_wp_file_changed (GFileMonitor *monitor,
+                                   GFile *file,
+                                   GFile *other_file,
+                                   GFileMonitorEvent event_type,
+                                   GnomeWpXml *data) {
+  gchar * filename;
+
+  switch (event_type) {
+  case G_FILE_MONITOR_EVENT_CHANGED:
+  case G_FILE_MONITOR_EVENT_CREATED:
+    filename = g_file_get_path (file);
+    gnome_wp_xml_load_xml (data, filename);
+    g_free (filename);
+    break;
+  default:
+    break;
+  }
+}
+
+static void gnome_wp_xml_add_monitor (GFile      *directory,
+                                      GnomeWpXml *data) {
+  GFileMonitor *monitor;
+  GError *error = NULL;
+
+  monitor = g_file_monitor_directory (directory,
+                                      G_FILE_MONITOR_NONE,
+                                      NULL,
+                                      &error);
+  if (error != NULL) {
+    gchar *path;
+
+    path = g_file_get_parse_name (directory);
+    g_warning ("Unable to monitor directory %s: %s",
+               path, error->message);
+    g_error_free (error);
+    g_free (path);
+    return;
+  }
+
+  g_signal_connect (monitor, "changed",
+                    G_CALLBACK (gnome_wp_file_changed),
+                    data);
+}
+
+static void gnome_wp_xml_load_from_dir (const gchar *path,
+                                        GnomeWpXml  *data) {
+  GFile *directory;
+  GFileEnumerator *enumerator;
+  GError *error = NULL;
+  GFileInfo *info;
+
+  if (!g_file_test (path, G_FILE_TEST_IS_DIR)) {
+    return;
+  }
+
+  directory = g_file_new_for_path (path);
+  enumerator = g_file_enumerate_children (directory,
+                                          G_FILE_ATTRIBUTE_STANDARD_NAME,
+                                          G_FILE_QUERY_INFO_NONE,
+                                          NULL,
+                                          &error);
+  if (error != NULL) {
+    g_warning ("Unable to check directory %s: %s", path, error->message);
+    g_error_free (error);
+    g_object_unref (directory);
+    return;
+  }
+
+  while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL))) {
+    const gchar *filename;
+    gchar *fullpath;
+
+    filename = g_file_info_get_name (info);
+    fullpath = g_build_filename (path, filename, NULL);
+    g_object_unref (info);
+
+    gnome_wp_xml_load_xml (data, fullpath);
+    g_free (fullpath);
+  }
+  g_file_enumerator_close (enumerator, NULL, NULL);
+
+  gnome_wp_xml_add_monitor (directory, data);
+
+  g_object_unref (directory);
+}
+
+void gnome_wp_xml_load_list (GnomeWpXml *data) {
+  const char * const *system_data_dirs;
+  gchar * datadir;
+  gchar * wpdbfile;
+  gint i;
+
+  wpdbfile = g_build_filename (g_get_home_dir (),
+			       ".gnome2",
+			       "backgrounds.xml",
+			       NULL);
+
+  if (g_file_test (wpdbfile, G_FILE_TEST_EXISTS)) {
+    gnome_wp_xml_load_xml (data, wpdbfile);
+  } else {
+    g_free (wpdbfile);
+    wpdbfile = g_build_filename (g_get_home_dir (),
+				 ".gnome2",
+				 "wp-list.xml",
+				 NULL);
+    if (g_file_test (wpdbfile, G_FILE_TEST_EXISTS)) {
+      gnome_wp_xml_load_xml (data, wpdbfile);
+    }
+  }
+  g_free (wpdbfile);
+
+  datadir = g_build_filename (g_get_user_data_dir (),
+                              "gnome-background-properties",
+                              NULL);
+  gnome_wp_xml_load_from_dir (datadir, data);
+  g_free (datadir);
+
+  system_data_dirs = g_get_system_data_dirs ();
+  for (i = 0; system_data_dirs[i]; i++) {
+    datadir = g_build_filename (system_data_dirs[i],
+                                "gnome-background-properties",
+				NULL);
+    gnome_wp_xml_load_from_dir (datadir, data);
+    g_free (datadir);
+  }
+
+  gnome_wp_load_legacy (data);
+}
+
+static void gnome_wp_list_flatten (const gchar * key, GnomeWPItem * item,
+				   GSList ** list) {
+  g_return_if_fail (key != NULL);
+  g_return_if_fail (item != NULL);
+
+  *list = g_slist_prepend (*list, item);
+}
+
+void gnome_wp_xml_save_list (GnomeWpXml *data) {
+  xmlDoc * wplist;
+  xmlNode * root, * wallpaper, * item;
+  GSList * list = NULL;
+  gchar * wpfile;
+
+  g_hash_table_foreach (data->wp_hash,
+			(GHFunc) gnome_wp_list_flatten, &list);
+  g_hash_table_destroy (data->wp_hash);
+  list = g_slist_reverse (list);
+
+  wpfile = g_build_filename (g_get_home_dir (),
+			     "/.gnome2",
+			     "backgrounds.xml",
+			     NULL);
+
+  xmlKeepBlanksDefault (0);
+
+  wplist = xmlNewDoc ((xmlChar *)"1.0");
+  xmlCreateIntSubset (wplist, (xmlChar *)"wallpapers", NULL, (xmlChar *)"gnome-wp-list.dtd");
+  root = xmlNewNode (NULL, (xmlChar *)"wallpapers");
+  xmlDocSetRootElement (wplist, root);
+
+  while (list != NULL) {
+    GnomeWPItem * wpitem = list->data;
+    const char * none = "(none)";
+    gchar * filename;
+    const gchar * scale, * shade;
+    gchar * pcolor, * scolor;
+
+    if (!strcmp (wpitem->filename, none) ||
+	(g_utf8_validate (wpitem->filename, -1, NULL) &&
+	 g_file_test (wpitem->filename, G_FILE_TEST_EXISTS)))
+      filename = g_strdup (wpitem->filename);
+    else
+      filename = g_filename_to_utf8 (wpitem->filename, -1, NULL, NULL, NULL);
+
+    pcolor = gdk_color_to_string (wpitem->pcolor);
+    scolor = gdk_color_to_string (wpitem->scolor);
+    scale = wp_item_option_to_string (wpitem->options);
+    shade = wp_item_shading_to_string (wpitem->shade_type);
+
+    wallpaper = xmlNewChild (root, NULL, (xmlChar *)"wallpaper", NULL);
+    gnome_wp_xml_set_bool (wallpaper, (xmlChar *)"deleted", wpitem->deleted);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"name", (xmlChar *)wpitem->name);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"filename", (xmlChar *)filename);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"options", (xmlChar *)scale);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"shade_type", (xmlChar *)shade);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"pcolor", (xmlChar *)pcolor);
+    item = xmlNewTextChild (wallpaper, NULL, (xmlChar *)"scolor", (xmlChar *)scolor);
+    g_free (pcolor);
+    g_free (scolor);
+    g_free (filename);
+
+    list = g_slist_delete_link (list, list);
+    gnome_wp_item_free (wpitem);
+  }
+  xmlSaveFormatFile (wpfile, wplist, 1);
+  xmlFreeDoc (wplist);
+  g_free (wpfile);
+}
diff --git a/panels/background/gnome-wp-xml.h b/panels/background/gnome-wp-xml.h
new file mode 100644
index 0000000..2ea8c2a
--- /dev/null
+++ b/panels/background/gnome-wp-xml.h
@@ -0,0 +1,43 @@
+/*
+ *  Authors: Rodney Dawes <dobey ximian com>
+ *
+ *  Copyright 2003-2006 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of version 2 of the GNU General Public License
+ *  as published by the Free Software Foundation
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _GNOME_WP_XML_H_
+#define _GNOME_WP_XML_H_
+
+#include <gconf/gconf-client.h>
+#include <libgnomeui/gnome-desktop-thumbnail.h>
+
+typedef struct _GnomeWpXml GnomeWpXml;
+
+struct _GnomeWpXml
+{
+  GHashTable *wp_hash;
+  GnomeDesktopThumbnailFactory *thumb_factory;
+  GConfClient *client;
+  gint thumb_height;
+  gint thumb_width;
+  GtkListStore *wp_model;
+};
+
+void gnome_wp_xml_load_list (GnomeWpXml *data);
+void gnome_wp_xml_save_list (GnomeWpXml *data);
+
+#endif
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]