summaryrefslogtreecommitdiff
path: root/panels/online-accounts
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2011-06-24 14:17:31 +0100
committerBastien Nocera <hadess@hadess.net>2011-06-24 15:43:03 +0100
commit896b5e87d994181414ba2197f7f8f8aaf73b98be (patch)
treeb53ad81aa05d6dbe658e50f9a9cfc9318a3b5ec0 /panels/online-accounts
parentd6bc292a69b2677fd65ccd2be1f6a4d7621fa03f (diff)
downloadgnome-control-center-896b5e87d994181414ba2197f7f8f8aaf73b98be.tar.gz
online-accounts: Add panel for gnome-online-accounts
https://bugzilla.gnome.org/show_bug.cgi?id=653334
Diffstat (limited to 'panels/online-accounts')
-rw-r--r--panels/online-accounts/Makefile.am36
-rw-r--r--panels/online-accounts/cc-online-accounts-model.c438
-rw-r--r--panels/online-accounts/cc-online-accounts-model.h58
-rw-r--r--panels/online-accounts/cc-online-accounts-panel.c639
-rw-r--r--panels/online-accounts/cc-online-accounts-panel.h40
-rw-r--r--panels/online-accounts/gnome-online-accounts-panel.desktop.in.in17
-rw-r--r--panels/online-accounts/icons/16x16/Makefile.am15
-rw-r--r--panels/online-accounts/icons/16x16/goa-account.pngbin0 -> 846 bytes
-rw-r--r--panels/online-accounts/icons/16x16/goa-panel.pngbin0 -> 917 bytes
-rw-r--r--panels/online-accounts/icons/22x22/Makefile.am15
-rw-r--r--panels/online-accounts/icons/22x22/goa-account.pngbin0 -> 1202 bytes
-rw-r--r--panels/online-accounts/icons/22x22/goa-panel.pngbin0 -> 1431 bytes
-rw-r--r--panels/online-accounts/icons/24x24/Makefile.am15
-rw-r--r--panels/online-accounts/icons/24x24/goa-account.pngbin0 -> 1230 bytes
-rw-r--r--panels/online-accounts/icons/24x24/goa-panel.pngbin0 -> 1469 bytes
-rw-r--r--panels/online-accounts/icons/256x256/Makefile.am15
-rw-r--r--panels/online-accounts/icons/256x256/goa-account.pngbin0 -> 25710 bytes
-rw-r--r--panels/online-accounts/icons/256x256/goa-panel.pngbin0 -> 42185 bytes
-rw-r--r--panels/online-accounts/icons/32x32/Makefile.am15
-rw-r--r--panels/online-accounts/icons/32x32/goa-account.pngbin0 -> 1938 bytes
-rw-r--r--panels/online-accounts/icons/32x32/goa-panel.pngbin0 -> 2170 bytes
-rw-r--r--panels/online-accounts/icons/48x48/Makefile.am15
-rw-r--r--panels/online-accounts/icons/48x48/goa-account.pngbin0 -> 3123 bytes
-rw-r--r--panels/online-accounts/icons/48x48/goa-panel.pngbin0 -> 3747 bytes
-rw-r--r--panels/online-accounts/icons/Makefile.am18
-rw-r--r--panels/online-accounts/icons/scalable/Makefile.am13
26 files changed, 1349 insertions, 0 deletions
diff --git a/panels/online-accounts/Makefile.am b/panels/online-accounts/Makefile.am
new file mode 100644
index 000000000..2b1454127
--- /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 000000000..393c1e036
--- /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 000000000..a5d44e20d
--- /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 000000000..4d8ec4547
--- /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 000000000..cc1adb472
--- /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 000000000..93d5f4520
--- /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 000000000..52ba27cef
--- /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 000000000..0d231ee31
--- /dev/null
+++ b/panels/online-accounts/icons/16x16/goa-account.png
Binary files 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 000000000..79af92c3e
--- /dev/null
+++ b/panels/online-accounts/icons/16x16/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/22x22/Makefile.am b/panels/online-accounts/icons/22x22/Makefile.am
new file mode 100644
index 000000000..166d6f412
--- /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 000000000..76956c261
--- /dev/null
+++ b/panels/online-accounts/icons/22x22/goa-account.png
Binary files 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 000000000..90e3e35b4
--- /dev/null
+++ b/panels/online-accounts/icons/22x22/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/24x24/Makefile.am b/panels/online-accounts/icons/24x24/Makefile.am
new file mode 100644
index 000000000..547b9f71c
--- /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 000000000..79cf8f4c6
--- /dev/null
+++ b/panels/online-accounts/icons/24x24/goa-account.png
Binary files 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 000000000..2bf182e5b
--- /dev/null
+++ b/panels/online-accounts/icons/24x24/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/256x256/Makefile.am b/panels/online-accounts/icons/256x256/Makefile.am
new file mode 100644
index 000000000..1a18d4245
--- /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 000000000..c07d172ef
--- /dev/null
+++ b/panels/online-accounts/icons/256x256/goa-account.png
Binary files 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 000000000..4ee2d0fa4
--- /dev/null
+++ b/panels/online-accounts/icons/256x256/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/32x32/Makefile.am b/panels/online-accounts/icons/32x32/Makefile.am
new file mode 100644
index 000000000..7d6f2f76b
--- /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 000000000..b4f31d43d
--- /dev/null
+++ b/panels/online-accounts/icons/32x32/goa-account.png
Binary files 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 000000000..302f2d345
--- /dev/null
+++ b/panels/online-accounts/icons/32x32/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/48x48/Makefile.am b/panels/online-accounts/icons/48x48/Makefile.am
new file mode 100644
index 000000000..68d3f7866
--- /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 000000000..8a58ee329
--- /dev/null
+++ b/panels/online-accounts/icons/48x48/goa-account.png
Binary files 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 000000000..7756b5285
--- /dev/null
+++ b/panels/online-accounts/icons/48x48/goa-panel.png
Binary files differ
diff --git a/panels/online-accounts/icons/Makefile.am b/panels/online-accounts/icons/Makefile.am
new file mode 100644
index 000000000..a15d82bf5
--- /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 000000000..f6674cd2f
--- /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