diff options
author | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2016-11-09 14:43:41 -0200 |
---|---|---|
committer | Debarshi Ray <debarshir@gnome.org> | 2016-11-30 17:16:35 +0100 |
commit | bdde40ac159064761f626e01801e75b385fcb82e (patch) | |
tree | 71347278d2969467c0521a96c038418f17e6a53e | |
parent | 902ab4e44897b149f85607a1cc4c6259eddef4e1 (diff) | |
download | gnome-control-center-bdde40ac159064761f626e01801e75b385fcb82e.tar.gz |
online-accounts: Use a listbox instead of a treeview
As part of the port to the redesigned Online Accounts panel,
the main widget to be displayed is a GtkListBox, so we can have
finer control of the UI elements and eventually be able to put
real widgets instead of using cell renderers.
This commit, then, makes the Online Account panel use a listbox
widget in the sidebar. The behavior of the panel was not changed.
Since its using a listbox now, we can drop the custom GoaPanelAccountsModel
class.
https://bugzilla.gnome.org/show_bug.cgi?id=774222
-rw-r--r-- | panels/online-accounts/Makefile.am | 2 | ||||
-rw-r--r-- | panels/online-accounts/cc-online-accounts-model.c | 435 | ||||
-rw-r--r-- | panels/online-accounts/cc-online-accounts-model.h | 56 | ||||
-rw-r--r-- | panels/online-accounts/cc-online-accounts-panel.c | 442 | ||||
-rw-r--r-- | panels/online-accounts/online-accounts.ui | 15 |
5 files changed, 243 insertions, 707 deletions
diff --git a/panels/online-accounts/Makefile.am b/panels/online-accounts/Makefile.am index e35717247..4ae1ab807 100644 --- a/panels/online-accounts/Makefile.am +++ b/panels/online-accounts/Makefile.am @@ -19,8 +19,6 @@ libonline_accounts_la_SOURCES = \ $(BUILT_SOURCES) \ cc-online-accounts-add-account-dialog.c \ cc-online-accounts-add-account-dialog.h \ - cc-online-accounts-model.c \ - cc-online-accounts-model.h \ cc-online-accounts-panel.c \ cc-online-accounts-panel.h diff --git a/panels/online-accounts/cc-online-accounts-model.c b/panels/online-accounts/cc-online-accounts-model.c deleted file mode 100644 index 72cad3370..000000000 --- a/panels/online-accounts/cc-online-accounts-model.c +++ /dev/null @@ -1,435 +0,0 @@ -/* -*- 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, see <http://www.gnu.org/licenses/>. - * - * 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); -} diff --git a/panels/online-accounts/cc-online-accounts-model.h b/panels/online-accounts/cc-online-accounts-model.h deleted file mode 100644 index 5fb36bd2d..000000000 --- a/panels/online-accounts/cc-online-accounts-model.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- 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, see <http://www.gnu.org/licenses/>. - * - * 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 index 502ef9483..3d339f1d4 100644 --- a/panels/online-accounts/cc-online-accounts-panel.c +++ b/panels/online-accounts/cc-online-accounts-panel.c @@ -32,7 +32,6 @@ #include "cc-online-accounts-panel.h" #include "cc-online-accounts-add-account-dialog.h" -#include "cc-online-accounts-model.h" #include "cc-online-accounts-resources.h" struct _CcGoaPanel @@ -41,8 +40,7 @@ struct _CcGoaPanel GoaClient *client; - GoaPanelAccountsModel *accounts_model; - + GtkWidget *accounts_listbox; GtkWidget *accounts_notebook; GtkWidget *accounts_tree_box; GtkWidget *accounts_tree_label; @@ -50,20 +48,11 @@ struct _CcGoaPanel GtkWidget *toolbar; GtkWidget *toolbar_add_button; GtkWidget *toolbar_remove_button; - GtkWidget *accounts_treeview; GtkWidget *accounts_vbox; }; -static void on_model_row_deleted (GtkTreeModel *tree_model, - GtkTreePath *path, - gpointer user_data); -static void on_model_row_inserted (GtkTreeModel *tree_model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data); - -static void on_tree_view_selection_changed (GtkTreeSelection *selection, - gpointer user_data); +static void on_listbox_selection_changed (CcGoaPanel *self, + GtkListBoxRow *selected_row); static void on_toolbar_add_button_clicked (GtkToolButton *button, gpointer user_data); @@ -73,12 +62,22 @@ static void on_toolbar_remove_button_clicked (GtkToolButton *button, static void on_add_button_clicked (GtkButton *button, gpointer user_data); +static void fill_accounts_listbox (CcGoaPanel *self); + +static void on_account_added (GoaClient *client, + GoaObject *object, + gpointer user_data); + static void on_account_changed (GoaClient *client, GoaObject *object, gpointer user_data); -static gboolean select_account_by_id (CcGoaPanel *panel, - const gchar *account_id); +static void on_account_removed (GoaClient *client, + GoaObject *object, + gpointer user_data); + +static void select_account_by_id (CcGoaPanel *panel, + const gchar *account_id); static void add_account (CcGoaPanel *panel, GoaProvider *provider, GVariant *preseed); @@ -90,6 +89,23 @@ enum { PROP_PARAMETERS }; +static gint +sort_func (GtkListBoxRow *a, + GtkListBoxRow *b, + gpointer user_data) +{ + GoaObject *a_obj, *b_obj; + GoaAccount *a_account, *b_account; + + a_obj = g_object_get_data (G_OBJECT (a), "goa-object"); + a_account = goa_object_peek_account (a_obj); + + b_obj = g_object_get_data (G_OBJECT (b), "goa-object"); + b_account = goa_object_peek_account (b_obj); + + return g_strcmp0 (goa_account_get_id (a_account), goa_account_get_id (b_account)); +} + static void command_add (CcGoaPanel *panel, GVariant *parameters) @@ -185,7 +201,6 @@ cc_goa_panel_finalize (GObject *object) { CcGoaPanel *panel = CC_GOA_PANEL (object); - g_clear_object (&panel->accounts_model); g_clear_object (&panel->client); G_OBJECT_CLASS (cc_goa_panel_parent_class)->finalize (object); @@ -195,15 +210,17 @@ static void cc_goa_panel_init (CcGoaPanel *panel) { GError *error; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkTreeIter iter; GNetworkMonitor *monitor; g_resources_register (cc_online_accounts_get_resource ()); gtk_widget_init_template (GTK_WIDGET (panel)); + gtk_list_box_set_sort_func (GTK_LIST_BOX (panel->accounts_listbox), + sort_func, + panel, + NULL); + monitor = g_network_monitor_get_default(); g_object_bind_property (monitor, "network-available", @@ -218,11 +235,6 @@ cc_goa_panel_init (CcGoaPanel *panel) G_CALLBACK (on_toolbar_remove_button_clicked), panel); - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)), - "changed", - G_CALLBACK (on_tree_view_selection_changed), - panel); - g_object_bind_property (monitor, "network-available", panel->add_account_button, "sensitive", G_BINDING_SYNC_CREATE); @@ -240,60 +252,26 @@ cc_goa_panel_init (CcGoaPanel *panel) error->message, g_quark_to_string (error->domain), error->code); gtk_widget_set_sensitive (GTK_WIDGET (panel), FALSE); g_error_free (error); - goto out; + return; } + + g_signal_connect (panel->client, + "account-added", + G_CALLBACK (on_account_added), + panel); + 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)); - g_signal_connect (panel->accounts_model, "row-deleted", G_CALLBACK (on_model_row_deleted), panel); - g_signal_connect (panel->accounts_model, "row-inserted", G_CALLBACK (on_model_row_inserted), panel); - - 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), - "follow-state", TRUE, - "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, TRUE); - g_object_set (G_OBJECT (renderer), - "ellipsize", PANGO_ELLIPSIZE_END, - "ellipsize-set", TRUE, - NULL); - 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-warning-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: + g_signal_connect (panel->client, + "account-removed", + G_CALLBACK (on_account_removed), + panel); + + fill_accounts_listbox (panel); + gtk_widget_show_all (GTK_WIDGET (panel)); } @@ -319,8 +297,8 @@ cc_goa_panel_class_init (CcGoaPanelClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/online-accounts/online-accounts.ui"); + gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_listbox); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_notebook); - gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_treeview); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_tree_box); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_tree_label); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, accounts_vbox); @@ -328,6 +306,8 @@ cc_goa_panel_class_init (CcGoaPanelClass *klass) gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, toolbar); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, toolbar_add_button); gtk_widget_class_bind_template_child (widget_class, CcGoaPanel, toolbar_remove_button); + + gtk_widget_class_bind_template_callback (widget_class, on_listbox_selection_changed); } /* ---------------------------------------------------------------------------------------------------- */ @@ -391,142 +371,210 @@ show_page_account (CcGoaPanel *panel, /* ---------------------------------------------------------------------------------------------------- */ -static gboolean +static void select_account_by_id (CcGoaPanel *panel, const gchar *account_id) { - GoaObject *goa_object = NULL; - GtkTreeIter iter; - gboolean iter_set = FALSE; + GtkListBoxRow *account_row; + GList *children, *l; - goa_object = goa_client_lookup_by_id (panel->client, account_id); - if (goa_object != NULL) - { - iter_set = goa_panel_accounts_model_get_iter_for_object (panel->accounts_model, - goa_object, - &iter); - g_object_unref (goa_object); - } + account_row = NULL; + children = gtk_container_get_children (GTK_CONTAINER (panel->accounts_listbox)); - if (iter_set) + for (l = children; l != NULL; l = l->next) { - GtkTreePath *path; - GtkTreeView *tree_view; - GtkTreeSelection *selection; - - tree_view = GTK_TREE_VIEW (panel->accounts_treeview); - selection = gtk_tree_view_get_selection (tree_view); - gtk_tree_selection_select_iter (selection, &iter); - path = gtk_tree_model_get_path (GTK_TREE_MODEL (panel->accounts_model), &iter); - gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0); - gtk_tree_path_free (path); + GoaAccount *account; + GoaObject *row_object; + + row_object = g_object_get_data (l->data, "goa-object"); + account = goa_object_peek_account (row_object); + + if (g_strcmp0 (goa_account_get_id (account), account_id) == 0) + { + account_row = l->data; + break; + } } - return iter_set; + gtk_list_box_select_row (GTK_LIST_BOX (panel->accounts_listbox), account_row); + + g_list_free (children); } static void -on_tree_view_selection_changed (GtkTreeSelection *selection, - gpointer user_data) +on_listbox_selection_changed (CcGoaPanel *self, + GtkListBoxRow *selected_row) { - CcGoaPanel *panel = CC_GOA_PANEL (user_data); - GtkTreeIter iter; - - if (gtk_tree_selection_get_selected (selection, NULL, &iter)) + if (selected_row != NULL) { GoaObject *object; gboolean is_locked; - gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model), - &iter, - GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &object, - -1); - show_page_account (panel, object); - + object = g_object_get_data (G_OBJECT (selected_row), "goa-object"); is_locked = goa_account_get_is_locked (goa_object_peek_account (object)); - gtk_widget_set_sensitive (panel->toolbar_remove_button, !is_locked); - g_object_unref (object); + show_page_account (self, object); + + gtk_widget_set_sensitive (self->toolbar_remove_button, !is_locked); } else { - show_page_nothing_selected (panel); + show_page_nothing_selected (self); } } static void -on_account_changed (GoaClient *client, - GoaObject *object, - gpointer user_data) +fill_accounts_listbox (CcGoaPanel *self) { - CcGoaPanel *panel = CC_GOA_PANEL (user_data); - GtkTreeIter iter; + GList *accounts, *l; + GtkListBoxRow *first_row; - if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)), - NULL, - &iter)) + accounts = goa_client_get_accounts (self->client); + + if (accounts == NULL) { - 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); + show_page_nothing_selected (self); } -} - -/* ---------------------------------------------------------------------------------------------------- */ + else + { + for (l = accounts; l != NULL; l = l->next) + on_account_added (self->client, l->data, self); -static void -on_model_row_changed (GtkTreeModel *tree_model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) -{ - GtkTreeSelection *selection = GTK_TREE_SELECTION (user_data); + /* Select the first row */ + first_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->accounts_listbox), 0); + gtk_list_box_select_row (GTK_LIST_BOX (self->accounts_listbox), first_row); + } - gtk_tree_selection_select_iter (selection, iter); - g_signal_handlers_disconnect_by_func (tree_model, G_CALLBACK (on_model_row_changed), user_data); + g_list_free_full (accounts, g_object_unref); } static void -on_model_row_deleted (GtkTreeModel *tree_model, - GtkTreePath *path, - gpointer user_data) +on_account_added (GoaClient *client, + GoaObject *object, + gpointer user_data) { - CcGoaPanel *panel = CC_GOA_PANEL (user_data); - GtkTreeIter iter; - GtkTreeSelection *selection; + CcGoaPanel *self = user_data; + GtkWidget *row, *icon, *label, *box; + GoaAccount *account; + GError *error; + GIcon *gicon; + gchar* title = NULL; + + account = goa_object_peek_account (object); + + /* The main grid */ + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_widget_show (box); + + /* The provider icon */ + icon = gtk_image_new (); - if (!gtk_tree_model_get_iter (tree_model, &iter, path)) + error = NULL; + gicon = g_icon_new_for_string (goa_account_get_provider_icon (account), &error); + if (error != NULL) { - if (!gtk_tree_path_prev (path)) - return; + g_warning ("Error creating GIcon for account: %s (%s, %d)", + error->message, + g_quark_to_string (error->domain), + error->code); + + g_clear_error (&error); + } + else + { + gtk_image_set_from_gicon (GTK_IMAGE (icon), gicon, GTK_ICON_SIZE_DIALOG); } - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)); - gtk_tree_selection_select_path (selection, path); + gtk_container_add (GTK_CONTAINER (box), icon); + + /* The name of the provider */ + title = g_strdup_printf ("<b>%s</b>\n<small>%s</small>", + goa_account_get_provider_name (account), + goa_account_get_presentation_identity (account)); + + label = g_object_new (GTK_TYPE_LABEL, + "ellipsize", PANGO_ELLIPSIZE_END, + "label", title, + "xalign", 0.0, + "use-markup", TRUE, + "hexpand", TRUE, + NULL); + gtk_container_add (GTK_CONTAINER (box), label); + + /* "Needs attention" icon */ + icon = gtk_image_new_from_icon_name ("dialog-warning-symbolic", GTK_ICON_SIZE_BUTTON); + gtk_widget_set_no_show_all (icon, TRUE); + g_object_bind_property (goa_object_peek_account (object), + "attention-needed", + icon, + "visible", + G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); + gtk_container_add (GTK_CONTAINER (box), icon); + + /* The row */ + row = gtk_list_box_row_new (); + g_object_set_data (G_OBJECT (row), "goa-object", object); + gtk_container_add (GTK_CONTAINER (row), box); + + /* Add to the listbox */ + gtk_container_add (GTK_CONTAINER (self->accounts_listbox), row); + gtk_widget_show_all (row); + + g_clear_pointer (&title, g_free); + g_clear_object (&gicon); } static void -on_model_row_inserted (GtkTreeModel *tree_model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) +on_account_changed (GoaClient *client, + GoaObject *object, + gpointer user_data) { CcGoaPanel *panel = CC_GOA_PANEL (user_data); - GtkTreeSelection *selection; + GtkListBoxRow *selected_row; + GoaObject *selected_object; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (panel->accounts_treeview)); - if (gtk_tree_selection_get_selected (selection, NULL, NULL)) + selected_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (panel->accounts_listbox)); + if (selected_row == NULL) return; - /* An empty row has been inserted and is going to be filled in, so - * we expect selection to stay valid. - */ - g_signal_connect (tree_model, "row-changed", G_CALLBACK (on_model_row_changed), selection); + selected_object = g_object_get_data (G_OBJECT (selected_row), "goa-object"); + + if (selected_object == object) + show_page_account (panel, selected_object); +} + +static void +on_account_removed (GoaClient *client, + GoaObject *object, + gpointer user_data) +{ + CcGoaPanel *self = user_data; + GList *children, *l; + + children = gtk_container_get_children (GTK_CONTAINER (self->accounts_listbox)); + + for (l = children; l != NULL; l = l->next) + { + GoaObject *row_object; + + row_object = GOA_OBJECT (g_object_get_data (l->data, "goa-object")); + + if (row_object == object) + { + GtkListBoxRow *row = NULL; + + if (l->next != NULL) + row = GTK_LIST_BOX_ROW (l->next->data); + else if (l->prev != NULL) + row = GTK_LIST_BOX_ROW (l->prev->data); + + gtk_list_box_select_row (GTK_LIST_BOX (self->accounts_listbox), row); + gtk_widget_destroy (l->data); + break; + } + } + + g_list_free (children); } /* ---------------------------------------------------------------------------------------------------- */ @@ -584,16 +632,8 @@ get_all_providers_cb (GObject *source, if (object != NULL) { - GtkTreeIter iter; - /* navigate to newly created object */ - if (goa_panel_accounts_model_get_iter_for_object (data->panel->accounts_model, - object, - &iter)) - { - gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->panel->accounts_treeview)), - &iter); - } - g_object_unref (object); + GoaAccount *account = goa_object_peek_account (object); + select_account_by_id (data->panel, goa_account_get_id (account)); } if (error != NULL) @@ -681,41 +721,35 @@ on_toolbar_remove_button_clicked (GtkToolButton *button, gpointer user_data) { CcGoaPanel *panel = CC_GOA_PANEL (user_data); - GtkTreeIter iter; + GtkListBoxRow *selected_row; + GoaObject *object; + GtkWidget *dialog; + gint response; - 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; + selected_row = gtk_list_box_get_selected_row (GTK_LIST_BOX (panel->accounts_listbox)); + if (selected_row == NULL) + return; - gtk_tree_model_get (GTK_TREE_MODEL (panel->accounts_model), - &iter, - GOA_PANEL_ACCOUNTS_MODEL_COLUMN_OBJECT, &object, - -1); + object = g_object_get_data (G_OBJECT (selected_row), "goa-object"); - 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); + 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); + if (response == GTK_RESPONSE_OK) + { + goa_account_call_remove (goa_object_peek_account (object), + NULL, /* GCancellable */ + (GAsyncReadyCallback) remove_account_cb, + g_object_ref (panel)); } } diff --git a/panels/online-accounts/online-accounts.ui b/panels/online-accounts/online-accounts.ui index add2a995b..80560c8ca 100644 --- a/panels/online-accounts/online-accounts.ui +++ b/panels/online-accounts/online-accounts.ui @@ -31,18 +31,13 @@ <property name="shadow_type">in</property> <property name="min_content_height">300</property> <child> - <object class="GtkTreeView" id="accounts_treeview"> - <property name="width_request">278</property> + <object class="GtkListBox" id="accounts_listbox"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="show_expanders">False</property> - <property name="level_indentation">12</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection"> - <property name="mode">browse</property> - </object> - </child> + <property name="hexpand">False</property> + <property name="width_request">278</property> + <property name="selection_mode">browse</property> + <signal name="row-selected" handler="on_listbox_selection_changed" object="CcGoaPanel" swapped="yes" /> </object> </child> </object> |