gnome-control-center/panels/online-accounts/cc-online-accounts-model.c
Debarshi Ray d58d426d34 online-accounts: Use g_warning instead of goa_warning
goa_warning is meant for goa-daemon, and it does not really add any
value in this case. Switching to g_warning lets us cut down on the
number of symbols that are exported from libgoabackend.

https://bugzilla.gnome.org/show_bug.cgi?id=693261
2013-02-07 12:59:00 +01:00

437 lines
13 KiB
C

/* -*- 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)
{
g_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>%s</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))
{
g_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))
{
g_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);
}