[gnome-control-center] online-accounts: Add panel for gnome-online-accounts



commit 896b5e87d994181414ba2197f7f8f8aaf73b98be
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Jun 24 14:17:31 2011 +0100

    online-accounts: Add panel for gnome-online-accounts
    
    https://bugzilla.gnome.org/show_bug.cgi?id=653334

 configure.ac                                       |   11 +
 panels/Makefile.am                                 |    1 +
 panels/online-accounts/Makefile.am                 |   36 ++
 panels/online-accounts/cc-online-accounts-model.c  |  438 ++++++++++++++
 panels/online-accounts/cc-online-accounts-model.h  |   58 ++
 panels/online-accounts/cc-online-accounts-panel.c  |  639 ++++++++++++++++++++
 panels/online-accounts/cc-online-accounts-panel.h  |   40 ++
 .../gnome-online-accounts-panel.desktop.in.in      |   17 +
 panels/online-accounts/icons/16x16/Makefile.am     |   15 +
 panels/online-accounts/icons/16x16/goa-account.png |  Bin 0 -> 846 bytes
 panels/online-accounts/icons/16x16/goa-panel.png   |  Bin 0 -> 917 bytes
 panels/online-accounts/icons/22x22/Makefile.am     |   15 +
 panels/online-accounts/icons/22x22/goa-account.png |  Bin 0 -> 1202 bytes
 panels/online-accounts/icons/22x22/goa-panel.png   |  Bin 0 -> 1431 bytes
 panels/online-accounts/icons/24x24/Makefile.am     |   15 +
 panels/online-accounts/icons/24x24/goa-account.png |  Bin 0 -> 1230 bytes
 panels/online-accounts/icons/24x24/goa-panel.png   |  Bin 0 -> 1469 bytes
 panels/online-accounts/icons/256x256/Makefile.am   |   15 +
 .../online-accounts/icons/256x256/goa-account.png  |  Bin 0 -> 25710 bytes
 panels/online-accounts/icons/256x256/goa-panel.png |  Bin 0 -> 42185 bytes
 panels/online-accounts/icons/32x32/Makefile.am     |   15 +
 panels/online-accounts/icons/32x32/goa-account.png |  Bin 0 -> 1938 bytes
 panels/online-accounts/icons/32x32/goa-panel.png   |  Bin 0 -> 2170 bytes
 panels/online-accounts/icons/48x48/Makefile.am     |   15 +
 panels/online-accounts/icons/48x48/goa-account.png |  Bin 0 -> 3123 bytes
 panels/online-accounts/icons/48x48/goa-panel.png   |  Bin 0 -> 3747 bytes
 panels/online-accounts/icons/Makefile.am           |   18 +
 panels/online-accounts/icons/scalable/Makefile.am  |   13 +
 po/POTFILES.in                                     |    3 +
 29 files changed, 1364 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f8d5ff1..e2785b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,7 @@ PKG_CHECK_MODULES(MEDIA_PANEL, $COMMON_MODULES)
 PKG_CHECK_MODULES(MOUSE_PANEL, $COMMON_MODULES xi >= 1.2
                   gnome-settings-daemon >= $GSD_REQUIRED_VERSION x11)
 PKG_CHECK_MODULES(NETWORK_PANEL, $COMMON_MODULES)
+PKG_CHECK_MODULES(ONLINE_ACCOUNTS_PANEL, $COMMON_MODULES goa-1.0 goa-backend-1.0)
 PKG_CHECK_MODULES(POWER_PANEL, $COMMON_MODULES upower-glib >= 0.9.1)
 PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES colord >= 0.1.8)
 PKG_CHECK_MODULES(PRINTERS_PANEL, $COMMON_MODULES dbus-glib-1
@@ -320,6 +321,16 @@ panels/media/Makefile
 panels/media/gnome-media-panel.desktop.in
 panels/mouse/Makefile
 panels/mouse/gnome-mouse-panel.desktop.in
+panels/online-accounts/Makefile
+panels/online-accounts/gnome-online-accounts-panel.desktop.in
+panels/online-accounts/icons/Makefile
+panels/online-accounts/icons/16x16/Makefile
+panels/online-accounts/icons/22x22/Makefile
+panels/online-accounts/icons/24x24/Makefile
+panels/online-accounts/icons/32x32/Makefile
+panels/online-accounts/icons/48x48/Makefile
+panels/online-accounts/icons/256x256/Makefile
+panels/online-accounts/icons/scalable/Makefile
 panels/sound/Makefile
 panels/sound/data/Makefile
 panels/sound/data/gnome-sound-panel.desktop.in
diff --git a/panels/Makefile.am b/panels/Makefile.am
index b4e335a..9806c50 100644
--- a/panels/Makefile.am
+++ b/panels/Makefile.am
@@ -7,6 +7,7 @@ SUBDIRS= \
 	display \
 	media \
 	mouse \
+	online-accounts \
 	region \
 	info \
 	sound \
diff --git a/panels/online-accounts/Makefile.am b/panels/online-accounts/Makefile.am
new file mode 100644
index 0000000..2b14541
--- /dev/null
+++ b/panels/online-accounts/Makefile.am
@@ -0,0 +1,36 @@
+cappletname = online-accounts
+
+SUBDIRS = icons
+
+INCLUDES = 						\
+	$(PANEL_CFLAGS)					\
+	$(ONLINE_ACCOUNTS_PANEL_CFLAGS)				\
+	-DGNOMECC_UI_DIR="\"$(uidir)\""			\
+	-DGNOMELOCALEDIR="\"$(datadir)/locale\""	\
+	-DGNOMECC_DATA_DIR="\"$(pkgdatadir)\""		\
+	$(NULL)
+
+ccpanelsdir = $(PANELS_DIR)
+ccpanels_LTLIBRARIES = libonline-accounts.la
+
+libonline_accounts_la_SOURCES =		\
+	cc-online-accounts-model.c	\
+	cc-online-accounts-model.h	\
+	cc-online-accounts-panel.c	\
+	cc-online-accounts-panel.h
+
+libonline_accounts_la_LIBADD = $(PANEL_LIBS) $(ONLINE_ACCOUNTS_PANEL_LIBS)
+libonline_accounts_la_LDFLAGS = $(PANEL_LDFLAGS)
+
+uidir = $(pkgdatadir)/ui
+dist_ui_DATA = online-accounts.ui
+
+ INTLTOOL_DESKTOP_RULE@
+
+desktopdir = $(datadir)/applications
+desktop_in_files = gnome-online-accounts-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/online-accounts/cc-online-accounts-model.c b/panels/online-accounts/cc-online-accounts-model.c
new file mode 100644
index 0000000..393c1e0
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-model.c
@@ -0,0 +1,438 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE
+#include <goabackend/goabackend.h>
+
+#include "cc-online-accounts-model.h"
+
+struct _GoaPanelAccountsModel
+{
+  GtkListStore parent_instance;
+
+  GoaClient *client;
+};
+
+typedef struct
+{
+  GtkListStoreClass parent_class;
+} GoaPanelAccountsModelClass;
+
+enum
+{
+  PROP_0,
+  PROP_CLIENT,
+};
+
+static void init_model (GoaPanelAccountsModel *model);
+
+static gboolean
+find_iter_for_object (GoaPanelAccountsModel *model,
+                      GoaObject             *object,
+                      GtkTreeIter           *out_iter);
+
+static void on_account_added (GoaClient   *client,
+                              GoaObject   *object,
+                              gpointer     user_data);
+
+static void on_account_removed (GoaClient   *client,
+                                GoaObject   *object,
+                                gpointer     user_data);
+
+static void on_account_changed (GoaClient   *client,
+                                GoaObject   *object,
+                                gpointer     user_data);
+
+G_DEFINE_TYPE (GoaPanelAccountsModel, goa_panel_accounts_model, GTK_TYPE_LIST_STORE);
+
+static void
+goa_panel_accounts_model_finalize (GObject *object)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (object);
+
+  g_signal_handlers_disconnect_by_func (model->client, G_CALLBACK (on_account_added), model);
+  g_signal_handlers_disconnect_by_func (model->client, G_CALLBACK (on_account_removed), model);
+  g_signal_handlers_disconnect_by_func (model->client, G_CALLBACK (on_account_changed), model);
+  g_object_unref (model->client);
+
+  G_OBJECT_CLASS (goa_panel_accounts_model_parent_class)->finalize (object);
+}
+
+static void
+goa_panel_accounts_model_init (GoaPanelAccountsModel *model)
+{
+}
+
+static void
+goa_panel_accounts_model_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      g_value_set_object (value, goa_panel_accounts_model_get_client (model));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+goa_panel_accounts_model_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      model->client = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+goa_panel_accounts_model_constructed (GObject *object)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (object);
+  GType types[GOA_PANEL_ACCOUNTS_MODEL_N_COLUMNS];
+
+  G_STATIC_ASSERT (5 == GOA_PANEL_ACCOUNTS_MODEL_N_COLUMNS);
+
+  types[0] = G_TYPE_STRING;
+  types[1] = GOA_TYPE_OBJECT;
+  types[2] = G_TYPE_BOOLEAN;
+  types[3] = G_TYPE_STRING;
+  types[4] = G_TYPE_ICON;
+
+  gtk_list_store_set_column_types (GTK_LIST_STORE (model),
+                                   GOA_PANEL_ACCOUNTS_MODEL_N_COLUMNS,
+                                   types);
+
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+                                        GOA_PANEL_ACCOUNTS_MODEL_COLUMN_SORT_KEY,
+                                        GTK_SORT_ASCENDING);
+
+  g_signal_connect (model->client,
+                    "account-added",
+                    G_CALLBACK (on_account_added),
+                    model);
+  g_signal_connect (model->client,
+                    "account-removed",
+                    G_CALLBACK (on_account_removed),
+                    model);
+  g_signal_connect (model->client,
+                    "account-changed",
+                    G_CALLBACK (on_account_changed),
+                    model);
+
+  init_model (model);
+
+  if (G_OBJECT_CLASS (goa_panel_accounts_model_parent_class)->constructed != NULL)
+    G_OBJECT_CLASS (goa_panel_accounts_model_parent_class)->constructed (object);
+}
+
+static void
+goa_panel_accounts_model_class_init (GoaPanelAccountsModelClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize     = goa_panel_accounts_model_finalize;
+  gobject_class->constructed  = goa_panel_accounts_model_constructed;
+  gobject_class->get_property = goa_panel_accounts_model_get_property;
+  gobject_class->set_property = goa_panel_accounts_model_set_property;
+
+  /**
+   * GoaPanelAccountsModel:client:
+   *
+   * The #GoaClient used by the #GoaPanelAccountsModel instance.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_CLIENT,
+                                   g_param_spec_object ("client",
+                                                        "Client",
+                                                        "The client used by the tree model",
+                                                        GOA_TYPE_CLIENT,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * goa_panel_accounts_model_new:
+ * @client: A #GoaClient.
+ *
+ * Creates a new #GoaPanelAccountsModel for viewing the accounts known
+ * by @client.
+ *
+ * Returns: A #GoaPanelAccountsModel. Free with g_object_unref().
+ */
+GoaPanelAccountsModel *
+goa_panel_accounts_model_new (GoaClient  *client)
+{
+  return GOA_PANEL_ACCOUNTS_MODEL (g_object_new (GOA_TYPE_PANEL_ACCOUNTS_MODEL,
+                                                 "client", client,
+                                                 NULL));
+}
+
+/**
+ * goa_panel_accounts_model_get_client:
+ * @model: A #GoaPanelAccountsModel.
+ *
+ * Gets the #GoaClient used by @model.
+ *
+ * Returns: (transfer none): A #GoaClient. Do not free, the object
+ *   belongs to @model.
+ */
+GoaClient *
+goa_panel_accounts_model_get_client (GoaPanelAccountsModel *model)
+{
+  g_return_val_if_fail (GOA_IS_PANEL_ACCOUNTS_MODEL (model), NULL);
+  return model->client;
+}
+
+/**
+ * goa_panel_accounts_model_get_iter_for_object:
+ * @model: A #GoaPanelAccountsModel.
+ * @object: A #GoaObject.
+ * @iter: (out): Return location for #GtkTreeIter.
+ *
+ * Finds @model<!-- -->'s row for @object.
+ *
+ * Returns: %TRUE if @iter was set, %FALSE if @object wasn't found.
+ */
+gboolean
+goa_panel_accounts_model_get_iter_for_object (GoaPanelAccountsModel  *model,
+                                              GoaObject              *object,
+                                              GtkTreeIter            *iter)
+{
+  g_return_val_if_fail (GOA_IS_PANEL_ACCOUNTS_MODEL (model), FALSE);
+  g_return_val_if_fail (GOA_IS_OBJECT (object), FALSE);
+  g_return_val_if_fail (iter != NULL, FALSE);
+  return find_iter_for_object (model, object, iter);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  GoaObject *object;
+  GtkTreeIter iter;
+  gboolean found;
+} FindIterData;
+
+static gboolean
+find_iter_for_object_cb (GtkTreeModel  *model,
+                         GtkTreePath   *path,
+                         GtkTreeIter   *iter,
+                         gpointer       user_data)
+{
+  FindIterData *data = user_data;
+  GoaObject *iter_object;
+
+  iter_object = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &iter_object,
+                      -1);
+  if (iter_object == NULL)
+    goto out;
+
+  if (iter_object == data->object)
+    {
+      data->iter = *iter;
+      data->found = TRUE;
+      goto out;
+    }
+
+ out:
+  if (iter_object != NULL)
+    g_object_unref (iter_object);
+  return data->found;
+}
+
+static gboolean
+find_iter_for_object (GoaPanelAccountsModel *model,
+                      GoaObject             *object,
+                      GtkTreeIter           *out_iter)
+{
+  FindIterData data;
+  memset (&data, 0, sizeof (data));
+  data.object = object;
+  data.found = FALSE;
+  gtk_tree_model_foreach (GTK_TREE_MODEL (model),
+                          find_iter_for_object_cb,
+                          &data);
+  if (data.found)
+    {
+      if (out_iter != NULL)
+        *out_iter = data.iter;
+    }
+  return data.found;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+set_values (GoaPanelAccountsModel  *model,
+            GoaObject              *object,
+            GtkTreeIter            *iter)
+{
+  GoaAccount *account;
+  GIcon *icon;
+  gchar *markup;
+  GError *error;
+
+  account = goa_object_peek_account (object);
+
+  error = NULL;
+  icon = g_icon_new_for_string (goa_account_get_provider_icon (account), &error);
+  if (icon == NULL)
+    {
+      goa_warning ("Error creating GIcon for account: %s (%s, %d)",
+                   error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+
+  markup = g_strdup_printf ("<b>%s</b>\n"
+                            "<small><span foreground=\"#555555\">%s</span></small>",
+                            goa_account_get_provider_name (account),
+                            goa_account_get_presentation_identity (account));
+
+  gtk_list_store_set (GTK_LIST_STORE (model),
+                      iter,
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_SORT_KEY, goa_account_get_id (account),
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, object,
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ATTENTION_NEEDED, goa_account_get_attention_needed (account),
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_MARKUP, markup,
+                      GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ICON, icon,
+                      -1);
+
+  g_free (markup);
+  g_clear_object (&icon);
+}
+
+static void
+add_account (GoaPanelAccountsModel  *model,
+             GoaObject              *object)
+{
+  GtkTreeIter iter;
+  gtk_list_store_insert (GTK_LIST_STORE (model),
+                         &iter,
+                         G_MAXINT); /* position */
+  set_values (model, object, &iter);
+}
+
+static void
+remove_account (GoaPanelAccountsModel  *model,
+                GoaObject              *object)
+{
+  GtkTreeIter iter;
+  if (!find_iter_for_object (model, object, &iter))
+    {
+      goa_warning ("Error removing object %s - not in tree", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
+    }
+  else
+    {
+      gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+    }
+}
+
+static void
+update_account (GoaPanelAccountsModel  *model,
+                GoaObject              *object)
+{
+  GtkTreeIter iter;
+  if (!find_iter_for_object (model, object, &iter))
+    {
+      goa_warning ("Error updating object %s - not in tree", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
+    }
+  else
+    {
+      set_values (model, object, &iter);
+    }
+}
+
+static void
+init_model (GoaPanelAccountsModel *model)
+{
+  GList *accounts;
+  GList *l;
+
+  accounts = goa_client_get_accounts (model->client);
+  for (l = accounts; l != NULL; l = l->next)
+    {
+      GoaObject *object = GOA_OBJECT (l->data);
+      add_account (model, object);
+    }
+  g_list_foreach (accounts, (GFunc) g_object_unref, NULL);
+  g_list_free (accounts);
+}
+
+static void
+on_account_added (GoaClient   *client,
+                  GoaObject   *object,
+                  gpointer     user_data)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (user_data);
+  add_account (model, object);
+}
+
+static void
+on_account_removed (GoaClient   *client,
+                    GoaObject   *object,
+                    gpointer     user_data)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (user_data);
+  remove_account (model, object);
+}
+
+static void
+on_account_changed (GoaClient   *client,
+                    GoaObject   *object,
+                    gpointer     user_data)
+{
+  GoaPanelAccountsModel *model = GOA_PANEL_ACCOUNTS_MODEL (user_data);
+  update_account (model, object);
+}
diff --git a/panels/online-accounts/cc-online-accounts-model.h b/panels/online-accounts/cc-online-accounts-model.h
new file mode 100644
index 0000000..a5d44e2
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-model.h
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __GOA_PANEL_ACCOUNTS_MODEL_H__
+#define __GOA_PANEL_ACCOUNTS_MODEL_H__
+
+#include <goa/goa.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+struct _GoaPanelAccountsModel;
+typedef struct _GoaPanelAccountsModel GoaPanelAccountsModel;
+
+#define GOA_TYPE_PANEL_ACCOUNTS_MODEL  (goa_panel_accounts_model_get_type ())
+#define GOA_PANEL_ACCOUNTS_MODEL(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), GOA_TYPE_PANEL_ACCOUNTS_MODEL, GoaPanelAccountsModel))
+#define GOA_IS_PANEL_ACCOUNTS_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOA_TYPE_PANEL_ACCOUNTS_MODEL))
+
+enum
+{
+  GOA_PANEL_ACCOUNTS_MODEL_COLUMN_SORT_KEY,
+  GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT,
+  GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ATTENTION_NEEDED,
+  GOA_PANEL_ACCOUNTS_MODEL_COLUMN_MARKUP,
+  GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ICON,
+  GOA_PANEL_ACCOUNTS_MODEL_N_COLUMNS
+};
+
+GType                   goa_panel_accounts_model_get_type            (void) G_GNUC_CONST;
+GoaPanelAccountsModel  *goa_panel_accounts_model_new                 (GoaClient      *client);
+GoaClient              *goa_panel_accounts_model_get_client          (GoaPanelAccountsModel *model);
+gboolean                goa_panel_accounts_model_get_iter_for_object (GoaPanelAccountsModel  *model,
+                                                                      GoaObject              *object,
+                                                                      GtkTreeIter            *iter);
+
+
+G_END_DECLS
+
+#endif /* __GOA_PANEL_ACCOUNTS_MODEL_H__ */
diff --git a/panels/online-accounts/cc-online-accounts-panel.c b/panels/online-accounts/cc-online-accounts-panel.c
new file mode 100644
index 0000000..4d8ec45
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-panel.c
@@ -0,0 +1,639 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE
+#include <goabackend/goabackend.h>
+
+#include "cc-online-accounts-panel.h"
+#include "cc-online-accounts-model.h"
+
+typedef struct _GoaPanelClass GoaPanelClass;
+
+struct _GoaPanel
+{
+  CcPanel parent_instance;
+
+  GtkBuilder *builder;
+
+  GoaClient *client;
+
+  GoaPanelAccountsModel *accounts_model;
+
+  GtkWidget *toolbar;
+  GtkWidget *toolbar_add_button;
+  GtkWidget *toolbar_remove_button;
+  GtkWidget *accounts_treeview;
+  GtkWidget *accounts_vbox;
+};
+
+struct _GoaPanelClass
+{
+  CcPanelClass parent_class;
+};
+
+static void on_tree_view_selection_changed (GtkTreeSelection *selection,
+                                            gpointer          user_data);
+
+static void on_toolbar_add_button_clicked (GtkToolButton *button,
+                                           gpointer       user_data);
+static void on_toolbar_remove_button_clicked (GtkToolButton *button,
+                                              gpointer       user_data);
+
+static void on_account_changed (GoaClient  *client,
+                                GoaObject  *object,
+                                gpointer    user_data);
+
+G_DEFINE_DYNAMIC_TYPE (GoaPanel, goa_panel, CC_TYPE_PANEL);
+
+static void
+goa_panel_finalize (GObject *object)
+{
+  GoaPanel *panel = GOA_PANEL (object);
+
+  g_signal_handlers_disconnect_by_func (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                        G_CALLBACK (on_tree_view_selection_changed),
+                                        panel);
+  if (panel->accounts_model != NULL)
+    g_object_unref (panel->accounts_model);
+  if (panel->client != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (panel->client,
+                                            G_CALLBACK (on_account_changed),
+                                            panel);
+      g_object_unref (panel->client);
+    }
+  g_object_unref (panel->builder);
+
+  G_OBJECT_CLASS (goa_panel_parent_class)->finalize (object);
+}
+
+static void
+goa_panel_init (GoaPanel *panel)
+{
+  GtkWidget *w;
+  GError *error;
+  GtkStyleContext *context;
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+  GtkTreeIter iter;
+
+  panel->builder = gtk_builder_new ();
+  error = NULL;
+  if (gtk_builder_add_from_file (panel->builder,
+                                 GNOMECC_UI_DIR "/online-accounts.ui",
+                                 &error) == 0)
+    {
+      goa_warning ("Error loading UI file: %s (%s, %d)",
+                   error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      goto out;
+    }
+
+  panel->toolbar = GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-tree-toolbar"));
+  panel->toolbar_add_button = GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-tree-toolbutton-add"));
+  g_signal_connect (panel->toolbar_add_button,
+                    "clicked",
+                    G_CALLBACK (on_toolbar_add_button_clicked),
+                    panel);
+  panel->toolbar_remove_button = GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-tree-toolbutton-remove"));
+  g_signal_connect (panel->toolbar_remove_button,
+                    "clicked",
+                    G_CALLBACK (on_toolbar_remove_button_clicked),
+                    panel);
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-tree-scrolledwindow")));
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+  context = gtk_widget_get_style_context (panel->toolbar);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (gtk_builder_get_object (panel->builder, "accounts-notebook")), FALSE);
+
+  panel->accounts_treeview = GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-tree-treeview"));
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                    "changed",
+                    G_CALLBACK (on_tree_view_selection_changed),
+                    panel);
+
+  panel->accounts_vbox = GTK_WIDGET (gtk_builder_get_object (panel->builder, "accounts-vbox"));
+
+  /* TODO: probably want to avoid _sync() ... */
+  error = NULL;
+  panel->client = goa_client_new_sync (NULL /* GCancellable */, &error);
+  if (panel->client == NULL)
+    {
+      goa_warning ("Error getting a GoaClient: %s (%s, %d)",
+                   error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;
+    }
+  g_signal_connect (panel->client,
+                    "account-changed",
+                    G_CALLBACK (on_account_changed),
+                    panel);
+
+  panel->accounts_model = goa_panel_accounts_model_new (panel->client);
+  gtk_tree_view_set_model (GTK_TREE_VIEW (panel->accounts_treeview), GTK_TREE_MODEL (panel->accounts_model));
+
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_append_column (GTK_TREE_VIEW (panel->accounts_treeview), column);
+
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  g_object_set (G_OBJECT (renderer),
+                "stock-size", GTK_ICON_SIZE_DIALOG,
+                NULL);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "gicon", GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ICON,
+                                       NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "markup", GOA_PANEL_ACCOUNTS_MODEL_COLUMN_MARKUP,
+                                       NULL);
+
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  gtk_tree_view_column_pack_end (column, renderer, FALSE);
+  g_object_set (G_OBJECT (renderer),
+                "icon-name", "dialog-error-symbolic",
+                NULL);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "visible", GOA_PANEL_ACCOUNTS_MODEL_COLUMN_ATTENTION_NEEDED,
+                                       NULL);
+
+  /* Select the first row, if any */
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (panel->accounts_model),
+                                     &iter))
+    gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                    &iter);
+
+ out:
+  w = GTK_WIDGET (gtk_builder_get_object (panel->builder, "goa-top-widget"));
+  gtk_widget_reparent (w, GTK_WIDGET (panel));
+  gtk_widget_show_all (w);
+}
+
+static void
+goa_panel_class_init (GoaPanelClass *klass)
+{
+}
+
+static void
+goa_panel_class_finalize (GoaPanelClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = goa_panel_finalize;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+goa_panel_register (GIOModule *module)
+{
+  goa_panel_register_type (G_TYPE_MODULE (module));
+  g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT,
+                                  GOA_TYPE_PANEL,
+                                  "online-accounts",
+                                  0);
+}
+
+void
+g_io_module_load (GIOModule *module)
+{
+  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  goa_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+show_page (GoaPanel *panel,
+           gint page_num)
+{
+  GtkNotebook *notebook;
+  notebook = GTK_NOTEBOOK (gtk_builder_get_object (panel->builder, "accounts-notebook"));
+  gtk_notebook_set_current_page (notebook, page_num);
+}
+
+static void
+show_page_nothing_selected (GoaPanel *panel)
+{
+  show_page (panel, 0);
+}
+
+static void
+on_info_bar_response (GtkInfoBar *info_bar,
+                      gint        response_id,
+                      gpointer    user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                       NULL,
+                                       &iter))
+    {
+      GoaProvider *provider;
+      const gchar *provider_type;
+      GoaAccount *account;
+      GoaObject *object;
+      GtkWindow *parent;
+      GError *error;
+
+      gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model),
+                          &iter,
+                          GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &object,
+                          -1);
+
+      account = goa_object_peek_account (object);
+      provider_type = goa_account_get_provider_type (account);
+      provider = goa_provider_get_for_provider_type (provider_type);
+
+      parent = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel))));
+
+      error = NULL;
+      if (!goa_provider_refresh_account (provider,
+                                         panel->client,
+                                         object,
+                                         parent,
+                                         &error))
+        {
+          if (!(error->domain == GOA_ERROR && error->code == GOA_ERROR_DIALOG_DISMISSED))
+            {
+              GtkWidget *dialog;
+              dialog = gtk_message_dialog_new (parent,
+                                               GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                               GTK_MESSAGE_ERROR,
+                                               GTK_BUTTONS_CLOSE,
+                                               _("Error logging into the account"));
+              gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                        "%s",
+                                                        error->message);
+              gtk_widget_show_all (dialog);
+              gtk_dialog_run (GTK_DIALOG (dialog));
+              gtk_widget_destroy (dialog);
+            }
+          g_error_free (error);
+        }
+      g_object_unref (provider);
+      g_object_unref (object);
+    }
+}
+
+static void
+show_page_account (GoaPanel  *panel,
+                   GoaObject *object)
+{
+  GList *children;
+  GList *l;
+  GtkWidget *table;
+  GtkWidget *bar;
+  GtkWidget *label;
+  GoaProvider *provider;
+  GoaAccount *account;
+  const gchar *provider_type;
+
+  provider = NULL;
+
+  show_page (panel, 1);
+
+  /* Out with the old */
+  children = gtk_container_get_children (GTK_CONTAINER (panel->accounts_vbox));
+  for (l = children; l != NULL; l = l->next)
+    gtk_container_remove (GTK_CONTAINER (panel->accounts_vbox), GTK_WIDGET (l->data));
+  g_list_free (children);
+
+  account = goa_object_peek_account (object);
+  provider_type = goa_account_get_provider_type (account);
+  provider = goa_provider_get_for_provider_type (provider_type);
+
+  /* And in with the new */
+  if (goa_account_get_attention_needed (account))
+    {
+      bar = gtk_info_bar_new ();
+      label = gtk_label_new (_("Expired credentials. Please log in again."));
+      gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
+      if (provider != NULL)
+        gtk_info_bar_add_button (GTK_INFO_BAR (bar), _("_Log In"), GTK_RESPONSE_OK);
+      gtk_box_pack_start (GTK_BOX (panel->accounts_vbox), bar, FALSE, TRUE, 0);
+      g_signal_connect (bar, "response", G_CALLBACK (on_info_bar_response), panel);
+    }
+
+  table = gtk_table_new (3, 2, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 0);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+  gtk_box_pack_start (GTK_BOX (panel->accounts_vbox), table, FALSE, TRUE, 0);
+
+  if (provider != NULL)
+    {
+      goa_provider_show_account (provider,
+                                 panel->client,
+                                 object,
+                                 GTK_BOX (panel->accounts_vbox),
+                                 GTK_TABLE (table));
+    }
+
+  gtk_widget_show_all (panel->accounts_vbox);
+
+  if (provider != NULL)
+    g_object_unref (provider);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_tree_view_selection_changed (GtkTreeSelection *selection,
+                                gpointer          user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+    {
+      GoaObject *object;
+      gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model),
+                          &iter,
+                          GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &object,
+                          -1);
+      show_page_account (panel, object);
+      g_object_unref (object);
+    }
+  else
+    {
+      show_page_nothing_selected (panel);
+    }
+}
+
+static void
+on_account_changed (GoaClient  *client,
+                    GoaObject  *object,
+                    gpointer    user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                       NULL,
+                                       &iter))
+    {
+      GoaObject *selected_object;
+      gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model),
+                          &iter,
+                          GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &selected_object,
+                          -1);
+      if (selected_object == object)
+        show_page_account (panel, selected_object);
+      g_object_unref (selected_object);
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_toolbar_add_button_clicked (GtkToolButton *button,
+                               gpointer       user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GtkWindow *parent;
+  GtkWidget *add_account_button;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *label;
+  GtkWidget *table;
+  GtkWidget *combo_box;
+  gint response;
+  GList *providers;
+  GoaProvider *provider;
+  GList *children;
+  GList *l;
+  GoaObject *object;
+  GError *error;
+
+  provider = NULL;
+  providers = NULL;
+
+  parent = GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel))));
+
+  dialog = gtk_dialog_new ();
+  gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+  vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+  gtk_box_set_spacing (GTK_BOX (vbox), 12);
+
+  label = gtk_label_new (_("To add a new account, first select the account type"));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+
+  label = gtk_label_new (_("Account Type:"));
+  combo_box = gtk_combo_box_text_new ();
+  providers = goa_provider_get_all ();
+  for (l = providers; l != NULL; l = l->next)
+    {
+      gchar *provider_name;
+
+      provider = GOA_PROVIDER (l->data);
+      provider_name = goa_provider_get_provider_name (provider, NULL);
+      gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo_box),
+                                 goa_provider_get_provider_type (provider),
+                                 provider_name);
+      g_free (provider_name);
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+
+  table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
+
+  gtk_table_attach (GTK_TABLE (table), label,
+                    0, 1,
+                    0, 1,
+                    GTK_FILL, GTK_FILL, 0, 0);
+  gtk_table_attach (GTK_TABLE (table), combo_box,
+                    1, 2,
+                    0, 1,
+                    GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+  add_account_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+                                              _("_Add..."), GTK_RESPONSE_OK);
+
+  gtk_widget_show_all (dialog);
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+  if (response != GTK_RESPONSE_OK)
+    {
+      gtk_widget_destroy (dialog);
+      goto out;
+    }
+  gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (add_account_button)), add_account_button);
+
+  provider = goa_provider_get_for_provider_type (gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)));
+  g_assert (provider != NULL);
+
+  /* Prepare GtkDialog for the provider */
+  children = gtk_container_get_children (GTK_CONTAINER (vbox));
+  for (l = children; l != NULL; l = l->next)
+    {
+      GtkWidget *child = GTK_WIDGET (l->data);
+      if (child != gtk_dialog_get_action_area (GTK_DIALOG (dialog)))
+        gtk_container_remove (GTK_CONTAINER (vbox), child);
+    }
+  g_list_free (children);
+
+  error = NULL;
+  object = goa_provider_add_account (provider,
+                                     panel->client,
+                                     GTK_DIALOG (dialog),
+                                     GTK_BOX (vbox),
+                                     &error);
+  if (object != NULL)
+    {
+      GtkTreeIter iter;
+      /* navigate to newly created object */
+      if (goa_panel_accounts_model_get_iter_for_object (panel->accounts_model,
+                                                        object,
+                                                        &iter))
+        {
+          gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                          &iter);
+        }
+      g_object_unref (object);
+      gtk_widget_destroy (dialog);
+    }
+  else
+    {
+      gtk_widget_destroy (dialog);
+      if (!(error->domain == GOA_ERROR && error->code == GOA_ERROR_DIALOG_DISMISSED))
+        {
+          dialog = gtk_message_dialog_new (parent,
+                                           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                           GTK_MESSAGE_ERROR,
+                                           GTK_BUTTONS_CLOSE,
+                                           _("Error creating account"));
+          gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                    "%s",
+                                                    error->message);
+          gtk_widget_show_all (dialog);
+          gtk_dialog_run (GTK_DIALOG (dialog));
+          gtk_widget_destroy (dialog);
+        }
+      g_error_free (error);
+    }
+
+ out:
+  if (provider != NULL)
+    g_object_unref (provider);
+  g_list_foreach (providers, (GFunc) g_object_unref, NULL);
+  g_list_free (providers);
+}
+
+static void
+remove_account_cb (GoaAccount    *account,
+                   GAsyncResult  *res,
+                   gpointer       user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GError *error;
+
+  error = NULL;
+  if (!goa_account_call_remove_finish (account, res, &error))
+    {
+      GtkWidget *dialog;
+      dialog = gtk_message_dialog_new (GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel)))),
+                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                       _("Error removing account"));
+      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                "%s",
+                                                error->message);
+      gtk_widget_show_all (dialog);
+      gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+      g_error_free (error);
+    }
+  g_object_unref (panel);
+}
+
+static void
+on_toolbar_remove_button_clicked (GtkToolButton *button,
+                                  gpointer       user_data)
+{
+  GoaPanel *panel = GOA_PANEL (user_data);
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)),
+                                       NULL,
+                                       &iter))
+    {
+      GoaObject *object;
+      GtkWidget *dialog;
+      gint response;
+
+      gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model),
+                          &iter,
+                          GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &object,
+                          -1);
+
+      dialog = gtk_message_dialog_new (GTK_WINDOW (cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (panel)))),
+                                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_QUESTION,
+                                       GTK_BUTTONS_CANCEL,
+                                       _("Are you sure you want to remove the account?"));
+      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                _("This will not remove the account on the server."));
+      gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Remove"), GTK_RESPONSE_OK);
+      gtk_widget_show_all (dialog);
+      response = gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+
+      if (response == GTK_RESPONSE_OK)
+        {
+          goa_account_call_remove (goa_object_peek_account (object),
+                                   NULL, /* GCancellable */
+                                   (GAsyncReadyCallback) remove_account_cb,
+                                   g_object_ref (panel));
+        }
+      g_object_unref (object);
+    }
+}
diff --git a/panels/online-accounts/cc-online-accounts-panel.h b/panels/online-accounts/cc-online-accounts-panel.h
new file mode 100644
index 0000000..cc1adb4
--- /dev/null
+++ b/panels/online-accounts/cc-online-accounts-panel.h
@@ -0,0 +1,40 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __GOA_PANEL_H__
+#define __GOA_PANEL_H__
+
+#include <libgnome-control-center/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define GOA_TYPE_PANEL  (goa_panel_get_type ())
+#define GOA_PANEL(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), GOA_TYPE_PANEL, GoaPanel))
+#define GOA_IS_PANEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOA_TYPE_PANEL))
+
+typedef struct _GoaPanel              GoaPanel;
+
+GType      goa_panel_get_type   (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GOA_PANEL_H__ */
diff --git a/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in b/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
new file mode 100644
index 0000000..93d5f45
--- /dev/null
+++ b/panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
@@ -0,0 +1,17 @@
+[Desktop Entry]
+_Name=Online Accounts
+_Comment=Manage online accounts
+Exec=gnome-control-center online-accounts
+Icon=goa-panel
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalSettings;
+OnlyShowIn=GNOME;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-control-center
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-Version= VERSION@
+X-GNOME-Settings-Panel=online-accounts
+# Translators: those are keywords for the online-accounts control-center panel
+_X-GNOME-Keywords=Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;
diff --git a/panels/online-accounts/icons/16x16/Makefile.am b/panels/online-accounts/icons/16x16/Makefile.am
new file mode 100644
index 0000000..52ba27c
--- /dev/null
+++ b/panels/online-accounts/icons/16x16/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/16x16/apps
+icon_DATA =				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/16x16/goa-account.png b/panels/online-accounts/icons/16x16/goa-account.png
new file mode 100644
index 0000000..0d231ee
Binary files /dev/null and b/panels/online-accounts/icons/16x16/goa-account.png differ
diff --git a/panels/online-accounts/icons/16x16/goa-panel.png b/panels/online-accounts/icons/16x16/goa-panel.png
new file mode 100644
index 0000000..79af92c
Binary files /dev/null and b/panels/online-accounts/icons/16x16/goa-panel.png differ
diff --git a/panels/online-accounts/icons/22x22/Makefile.am b/panels/online-accounts/icons/22x22/Makefile.am
new file mode 100644
index 0000000..166d6f4
--- /dev/null
+++ b/panels/online-accounts/icons/22x22/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/22x22/apps
+icon_DATA = 				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/22x22/goa-account.png b/panels/online-accounts/icons/22x22/goa-account.png
new file mode 100644
index 0000000..76956c2
Binary files /dev/null and b/panels/online-accounts/icons/22x22/goa-account.png differ
diff --git a/panels/online-accounts/icons/22x22/goa-panel.png b/panels/online-accounts/icons/22x22/goa-panel.png
new file mode 100644
index 0000000..90e3e35
Binary files /dev/null and b/panels/online-accounts/icons/22x22/goa-panel.png differ
diff --git a/panels/online-accounts/icons/24x24/Makefile.am b/panels/online-accounts/icons/24x24/Makefile.am
new file mode 100644
index 0000000..547b9f7
--- /dev/null
+++ b/panels/online-accounts/icons/24x24/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/24x24/apps
+icon_DATA = 				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/24x24/goa-account.png b/panels/online-accounts/icons/24x24/goa-account.png
new file mode 100644
index 0000000..79cf8f4
Binary files /dev/null and b/panels/online-accounts/icons/24x24/goa-account.png differ
diff --git a/panels/online-accounts/icons/24x24/goa-panel.png b/panels/online-accounts/icons/24x24/goa-panel.png
new file mode 100644
index 0000000..2bf182e
Binary files /dev/null and b/panels/online-accounts/icons/24x24/goa-panel.png differ
diff --git a/panels/online-accounts/icons/256x256/Makefile.am b/panels/online-accounts/icons/256x256/Makefile.am
new file mode 100644
index 0000000..1a18d42
--- /dev/null
+++ b/panels/online-accounts/icons/256x256/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/256x256/apps
+icon_DATA = 				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/256x256/goa-account.png b/panels/online-accounts/icons/256x256/goa-account.png
new file mode 100644
index 0000000..c07d172
Binary files /dev/null and b/panels/online-accounts/icons/256x256/goa-account.png differ
diff --git a/panels/online-accounts/icons/256x256/goa-panel.png b/panels/online-accounts/icons/256x256/goa-panel.png
new file mode 100644
index 0000000..4ee2d0f
Binary files /dev/null and b/panels/online-accounts/icons/256x256/goa-panel.png differ
diff --git a/panels/online-accounts/icons/32x32/Makefile.am b/panels/online-accounts/icons/32x32/Makefile.am
new file mode 100644
index 0000000..7d6f2f7
--- /dev/null
+++ b/panels/online-accounts/icons/32x32/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/32x32/apps
+icon_DATA = 				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/32x32/goa-account.png b/panels/online-accounts/icons/32x32/goa-account.png
new file mode 100644
index 0000000..b4f31d4
Binary files /dev/null and b/panels/online-accounts/icons/32x32/goa-account.png differ
diff --git a/panels/online-accounts/icons/32x32/goa-panel.png b/panels/online-accounts/icons/32x32/goa-panel.png
new file mode 100644
index 0000000..302f2d3
Binary files /dev/null and b/panels/online-accounts/icons/32x32/goa-panel.png differ
diff --git a/panels/online-accounts/icons/48x48/Makefile.am b/panels/online-accounts/icons/48x48/Makefile.am
new file mode 100644
index 0000000..68d3f78
--- /dev/null
+++ b/panels/online-accounts/icons/48x48/Makefile.am
@@ -0,0 +1,15 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/48x48/apps
+icon_DATA = 				\
+	goa-panel.png			\
+	goa-account.png			\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/48x48/goa-account.png b/panels/online-accounts/icons/48x48/goa-account.png
new file mode 100644
index 0000000..8a58ee3
Binary files /dev/null and b/panels/online-accounts/icons/48x48/goa-account.png differ
diff --git a/panels/online-accounts/icons/48x48/goa-panel.png b/panels/online-accounts/icons/48x48/goa-panel.png
new file mode 100644
index 0000000..7756b52
Binary files /dev/null and b/panels/online-accounts/icons/48x48/goa-panel.png differ
diff --git a/panels/online-accounts/icons/Makefile.am b/panels/online-accounts/icons/Makefile.am
new file mode 100644
index 0000000..a15d82b
--- /dev/null
+++ b/panels/online-accounts/icons/Makefile.am
@@ -0,0 +1,18 @@
+
+SUBDIRS = 16x16 22x22 24x24 32x32 48x48 256x256 scalable
+
+gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
+
+install-data-hook:
+	@-if test -z "$(DESTDIR)"; then \
+		echo "Updating Gtk icon cache."; \
+		$(gtk_update_icon_cache); \
+	else \
+		echo "*** Icon cache not updated.  After install, run this:"; \
+		echo "***   $(gtk_update_icon_cache)"; \
+	fi
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/panels/online-accounts/icons/scalable/Makefile.am b/panels/online-accounts/icons/scalable/Makefile.am
new file mode 100644
index 0000000..f6674cd
--- /dev/null
+++ b/panels/online-accounts/icons/scalable/Makefile.am
@@ -0,0 +1,13 @@
+NULL =
+
+icondir = $(datadir)/icons/hicolor/scalable/apps
+icon_DATA =				\
+	$(NULL)
+
+EXTRA_DIST = \
+	$(icon_DATA)
+
+clean-local :
+	rm -f *~
+
+-include $(top_srcdir)/git.mk
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c5237d7..f92f1d1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -29,6 +29,9 @@ panels/keyboard/keyboard-shortcuts.c
 panels/media/cc-media-panel.c
 [type: gettext/glade]panels/media/gnome-media-properties.ui
 panels/media/gnome-media-panel.desktop.in.in
+panels/online-accounts/cc-online-accounts-panel.c
+panels/online-accounts/gnome-online-accounts-panel.desktop.in.in
+[type: gettext/glade]panels/online-accounts/online-accounts.ui
 panels/printers/cc-printers-panel.c
 panels/printers/gnome-printers-panel.desktop.in.in
 [type: gettext/glade]panels/printers/new-printer-dialog.ui



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