messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit 2cb42b64dfd6531243a6e1208ae3a7acc8a3b6af
parent 9b532460a3da2c29e0d9dd19ac8e28f154201915
Author: Jacki <jacki@thejackimonster.de>
Date:   Wed, 24 Apr 2024 16:26:34 +0200

Implement profile picture loading for accounts

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Asrc/account.c | 271+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/account.h | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/contact.c | 41+++++++++++++++++++++++++++--------------
Msrc/contact.h | 1+
Msrc/event.c | 43++++++++++++++++++++++++++++++++++++++++++-
Msrc/meson.build | 1+
Msrc/ui.c | 12++++++++++++
Msrc/ui.h | 10++++++++++
Msrc/ui/account_entry.c | 18++++++++++++++----
Msrc/ui/account_entry.h | 3+++
Msrc/ui/contact_info.c | 133+++++++++++++++++++++++++++----------------------------------------------------
Msrc/ui/contact_info.h | 4++++
Msrc/ui/messenger.c | 3+--
13 files changed, 533 insertions(+), 109 deletions(-)

diff --git a/src/account.c b/src/account.c @@ -0,0 +1,271 @@ +/* + This file is part of GNUnet. + Copyright (C) 2024 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file account.c + */ + +#include "account.h" + +#include "contact.h" +#include "ui.h" + +#include <gnunet/gnunet_chat_lib.h> +#include <gnunet/gnunet_common.h> +#include <string.h> + +static GList *infos = NULL; + +enum GNUNET_GenericReturnValue +account_create_info(struct GNUNET_CHAT_Account *account) +{ + if ((!account) || (GNUNET_CHAT_account_get_user_pointer(account))) + return GNUNET_NO; + + MESSENGER_AccountInfo *info = g_malloc(sizeof(MESSENGER_AccountInfo)); + + info->account = account; + + info->icon_file = NULL; + info->icon = NULL; + info->task = 0; + + info->name_avatars = NULL; + + infos = g_list_append(infos, info); + + GNUNET_CHAT_account_set_user_pointer(account, info); + return GNUNET_YES; +} + +static void +_destroy_account_info(gpointer data) +{ + g_assert(data); + + MESSENGER_AccountInfo *info = (MESSENGER_AccountInfo*) data; + + if (info->name_avatars) + g_list_free(info->name_avatars); + + if (info->task) + util_source_remove(info->task); + + if (info->icon) + g_object_unref(info->icon); + + if (info->icon_file) + g_object_unref(info->icon_file); + + GNUNET_CHAT_account_set_user_pointer(info->account, NULL); + + g_free(info); +} + +void +account_destroy_info(struct GNUNET_CHAT_Account *account) +{ + g_assert(account); + + MESSENGER_AccountInfo* info = GNUNET_CHAT_account_get_user_pointer(account); + + if (!info) + return; + + if (infos) + infos = g_list_remove(infos, info); + + _destroy_account_info(info); +} + +void +account_cleanup_infos() +{ + if (!infos) + return; + + g_list_free_full(infos, (GDestroyNotify) _destroy_account_info); + + infos = NULL; +} + +void +account_add_name_avatar_to_info(const struct GNUNET_CHAT_Account *account, + HdyAvatar *avatar) +{ + g_assert(avatar); + + MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account); + + if (!info) + return; + + const char *name = GNUNET_CHAT_account_get_name(account); + + ui_avatar_set_text(avatar, name); + ui_avatar_set_icon(avatar, info->icon); + + info->name_avatars = g_list_append(info->name_avatars, avatar); +} + +void +account_remove_name_avatar_from_info(const struct GNUNET_CHAT_Account *account, + HdyAvatar *avatar) +{ + g_assert(avatar); + + MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account); + + if (!info) + return; + + if (info->name_avatars) + info->name_avatars = g_list_remove(info->name_avatars, avatar); +} + +static gboolean +_task_update_avatars(gpointer data) +{ + g_assert(data); + + MESSENGER_AccountInfo *info = (MESSENGER_AccountInfo*) data; + + info->task = 0; + + GList* list; + for (list = info->name_avatars; list; list = list->next) + ui_avatar_set_icon(HDY_AVATAR(list->data), info->icon); + + return FALSE; +} + +static void +_info_profile_downloaded(void *cls, + struct GNUNET_CHAT_File *file, + uint64_t completed, + uint64_t size) +{ + g_assert((cls) && (file)); + + struct GNUNET_CHAT_Account *account = (struct GNUNET_CHAT_Account*) cls; + + MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account); + + if ((!info) || (completed < size)) + return; + + const char *preview = GNUNET_CHAT_file_open_preview(file); + + if (!preview) + return; + + GFile *file_object = g_file_new_for_path(preview); + + if (!file_object) + return; + + if (!(info->icon_file)) + goto skip_comparison; + + if (g_file_equal(info->icon_file, file_object)) + { + g_object_unref(file_object); + return; + } + + g_object_unref(info->icon_file); + +skip_comparison: + info->icon_file = file_object; + + if (info->icon) + g_object_unref(info->icon); + + info->icon = g_file_icon_new(file_object); + + if (!(info->task)) + info->task = util_idle_add(G_SOURCE_FUNC(_task_update_avatars), info); +} + +static enum GNUNET_GenericReturnValue +_account_iterate_attribute(void *cls, + const struct GNUNET_CHAT_Account *account, + const char *name, + const char *value) +{ + g_assert((cls) && (account) && (name)); + + struct GNUNET_CHAT_Handle *handle = (struct GNUNET_CHAT_Handle*) cls; + + MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account); + + if (!info) + return GNUNET_NO; + + if ((0 != strcmp(name, ATTRIBUTE_PROFILE_PICTURE)) || (!value)) + return GNUNET_YES; + + struct GNUNET_CHAT_Uri *uri = GNUNET_CHAT_uri_parse(value, NULL); + + if (!uri) + return GNUNET_YES; + + struct GNUNET_CHAT_File *file = GNUNET_CHAT_request_file(handle, uri); + + if (!file) + goto skip_file; + + if (GNUNET_YES == GNUNET_CHAT_file_is_ready(file)) + _info_profile_downloaded( + info->account, + file, + GNUNET_CHAT_file_get_local_size(file), + GNUNET_CHAT_file_get_size(file) + ); + else if (GNUNET_YES != GNUNET_CHAT_file_is_downloading(file)) + GNUNET_CHAT_file_start_download( + file, + _info_profile_downloaded, + info->account + ); + +skip_file: + GNUNET_CHAT_uri_destroy(uri); + return GNUNET_YES; +} + +void +account_update_attributes(const struct GNUNET_CHAT_Account *account, + MESSENGER_Application *app) +{ + g_assert(app); + + MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account); + + if (!info) + return; + + GNUNET_CHAT_account_get_attributes( + app->chat.messenger.handle, + account, + _account_iterate_attribute, + app->chat.messenger.handle + ); +} diff --git a/src/account.h b/src/account.h @@ -0,0 +1,102 @@ +/* + This file is part of GNUnet. + Copyright (C) 2024 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet 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 + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file account.h + */ + +#ifndef ACCOUNT_H_ +#define ACCOUNT_H_ + +#include "application.h" + +typedef struct MESSENGER_AccountInfo +{ + struct GNUNET_CHAT_Account *account; + + GFile *icon_file; + GIcon *icon; + guint task; + + GList *name_avatars; +} MESSENGER_AccountInfo; + +/** + * Creates an account information struct to potentially + * update all GUI appearances of a specific account at + * once. + * + * @param account Chat account + * @return #GNUNET_YES on info creation, otherwise #GNUNET_NO + */ +enum GNUNET_GenericReturnValue +account_create_info(struct GNUNET_CHAT_Account *account); + +/** + * Destroys and frees resources allocated for a given + * account information struct. + * + * @param account Chat account + */ +void +account_destroy_info(struct GNUNET_CHAT_Account *account); + +/** + * Destroys and frees all resources allocated for + * account information structs to cleanup everything + * on an accounts refresh. + */ +void +account_cleanup_infos(); + +/** + * Adds a HdyAvatar to the list of avatars + * which get updated by state changes. + * + * @param account Chat account + * @param avatar Avatar + */ +void +account_add_name_avatar_to_info(const struct GNUNET_CHAT_Account *account, + HdyAvatar *avatar); + +/** + * Removes a HdyAvatar from the list of avatars + * which get updated by state changes. + * + * @param account Chat account + * @param avatar Avatar + */ +void +account_remove_name_avatar_from_info(const struct GNUNET_CHAT_Account *account, + HdyAvatar *avatar); + +/** + * Updates the connected UI elements for a given + * account based on current attributes changes. + * + * @param account Chat account + * @param app Messenger application + */ +void +account_update_attributes(const struct GNUNET_CHAT_Account *account, + MESSENGER_Application *app); + +#endif /* ACCOUNT_H_ */ diff --git a/src/contact.c b/src/contact.c @@ -25,6 +25,7 @@ #include "contact.h" #include "ui.h" + #include <gnunet/gnunet_chat_lib.h> #include <gnunet/gnunet_common.h> #include <string.h> @@ -38,8 +39,9 @@ contact_create_info(struct GNUNET_CHAT_Contact *contact) MESSENGER_ContactInfo* info = g_malloc(sizeof(MESSENGER_ContactInfo)); info->last_message = NULL; - info->icon = NULL; info->icon_file = NULL; + info->icon = NULL; + info->task = 0; info->name_labels = NULL; info->name_avatars = NULL; @@ -68,6 +70,9 @@ contact_destroy_info(struct GNUNET_CHAT_Contact *contact) if (info->visible_widgets) g_list_free(info->visible_widgets); + if (info->task) + util_source_remove(info->task); + if (info->icon) g_object_unref(info->icon); @@ -149,9 +154,7 @@ contact_add_name_avatar_to_info(const struct GNUNET_CHAT_Contact *contact, const char *name = GNUNET_CHAT_contact_get_name(contact); ui_avatar_set_text(avatar, name); - - if (info->icon) - hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(info->icon)); + ui_avatar_set_icon(avatar, info->icon); info->name_avatars = g_list_append(info->name_avatars, avatar); } @@ -223,15 +226,29 @@ contact_update_info(const struct GNUNET_CHAT_Contact *contact) for (list = info->name_avatars; list; list = list->next) ui_avatar_set_text(HDY_AVATAR(list->data), name); - if (info->icon) - for (list = info->name_avatars; list; list = list->next) - hdy_avatar_set_loadable_icon(HDY_AVATAR(list->data), - G_LOADABLE_ICON(info->icon)); + for (list = info->name_avatars; list; list = list->next) + ui_avatar_set_icon(HDY_AVATAR(list->data), info->icon); for (list = info->visible_widgets; list; list = list->next) gtk_widget_set_visible(GTK_WIDGET(list->data), visible); } +static gboolean +_task_update_avatars(gpointer data) +{ + g_assert(data); + + MESSENGER_ContactInfo *info = (MESSENGER_ContactInfo*) data; + + info->task = 0; + + GList* list; + for (list = info->name_avatars; list; list = list->next) + ui_avatar_set_icon(HDY_AVATAR(list->data), info->icon); + + return FALSE; +} + static void _info_profile_downloaded(void *cls, struct GNUNET_CHAT_File *file, @@ -274,12 +291,8 @@ skip_comparison: info->icon = g_file_icon_new(file_object); - if (!(info->icon)) - return; - - GList* list; - for (list = info->name_avatars; list; list = list->next) - hdy_avatar_set_loadable_icon(HDY_AVATAR(list->data), G_LOADABLE_ICON(info->icon)); + if (!(info->task)) + info->task = util_idle_add(G_SOURCE_FUNC(_task_update_avatars), info); } static enum GNUNET_GenericReturnValue diff --git a/src/contact.h b/src/contact.h @@ -34,6 +34,7 @@ typedef struct MESSENGER_ContactInfo void *last_message; GFile *icon_file; GIcon *icon; + guint task; GList *name_labels; GList *name_avatars; diff --git a/src/event.c b/src/event.c @@ -24,6 +24,7 @@ #include "event.h" +#include "account.h" #include "application.h" #include "contact.h" #include "file.h" @@ -116,6 +117,33 @@ event_handle_warning(MESSENGER_Application *app, ); } +static enum GNUNET_GenericReturnValue +_iterate_reload_account(void *cls, + UNUSED const struct GNUNET_CHAT_Handle *handle, + struct GNUNET_CHAT_Account *account) +{ + g_assert((cls) && (account)); + + MESSENGER_Application *app = (MESSENGER_Application*) cls; + + if (GNUNET_YES == account_create_info(account)) + account_update_attributes(account, app); + + return GNUNET_YES; +} + +static void +_reload_accounts(MESSENGER_Application *app) +{ + account_cleanup_infos(); + + GNUNET_CHAT_iterate_accounts( + app->chat.messenger.handle, + _iterate_reload_account, + app + ); +} + static gboolean _idle_refresh_accounts(gpointer user_data) { @@ -126,6 +154,8 @@ _idle_refresh_accounts(gpointer user_data) if (!(app->ui.messenger.main_window)) goto refresh_exit; + _reload_accounts(app); + if (gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window))) ui_messenger_refresh(app, &(app->ui.messenger)); else @@ -303,9 +333,15 @@ event_update_profile(MESSENGER_Application *app) UI_MESSENGER_Handle *ui = &(app->ui.messenger); CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); + _reload_accounts(app); + const char *name = GNUNET_CHAT_get_name(chat->handle); - ui_avatar_set_text(ui->profile_avatar, name); + account_add_name_avatar_to_info( + GNUNET_CHAT_get_connected(chat->handle), + ui->profile_avatar + ); + ui_label_set_text(ui->profile_label, name); const char *key = GNUNET_CHAT_get_key(chat->handle); @@ -370,6 +406,11 @@ event_cleanup_profile(MESSENGER_Application *app) UI_MESSENGER_Handle *ui = &(app->ui.messenger); CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); + account_remove_name_avatar_from_info( + GNUNET_CHAT_get_connected(chat->handle), + ui->profile_avatar + ); + GList *entries = gtk_container_get_children( GTK_CONTAINER(ui->chats_listbox) ); diff --git a/src/meson.build b/src/meson.build @@ -22,6 +22,7 @@ subdir('chat') subdir('ui') messenger_gtk_sources = files([ + 'account.c', 'account.h', 'application.c', 'application.h', 'contact.c', 'contact.h', 'event.c', 'event.h', diff --git a/src/ui.c b/src/ui.c @@ -164,3 +164,15 @@ ui_avatar_set_text(HdyAvatar *avatar, const char *text) hdy_avatar_set_text(avatar, _text); g_free(_text); } + +void +ui_avatar_set_icon(HdyAvatar *avatar, + GIcon *icon) +{ + g_assert(avatar); + + if (!icon) + hdy_avatar_set_loadable_icon(avatar, NULL); + else + hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(icon)); +} diff --git a/src/ui.h b/src/ui.h @@ -92,4 +92,14 @@ void ui_avatar_set_text(HdyAvatar *avatar, const char *text); +/** + * Sets the icon of a HdyAvatar. + * + * @param avatar Avatar + * @param icon Loadable icon + */ +void +ui_avatar_set_icon(HdyAvatar *avatar, + GIcon *icon); + #endif /* UI_H_ */ diff --git a/src/ui/account_entry.c b/src/ui/account_entry.c @@ -24,6 +24,7 @@ #include "account_entry.h" +#include "../account.h" #include "../application.h" #include "../contact.h" #include "../ui.h" @@ -35,6 +36,7 @@ ui_account_entry_new(MESSENGER_Application *app) UI_ACCOUNT_ENTRY_Handle* handle = g_malloc(sizeof(UI_ACCOUNT_ENTRY_Handle)); + handle->account = NULL; handle->contact = NULL; handle->builder = ui_builder_from_resource( @@ -60,12 +62,19 @@ void ui_account_entry_set_account(UI_ACCOUNT_ENTRY_Handle* handle, const struct GNUNET_CHAT_Account *account) { - g_assert((handle) && (account)); + g_assert(handle); + + if (handle->account) + account_remove_name_avatar_from_info(account, handle->entry_avatar); - const char *name = GNUNET_CHAT_account_get_name(account); + if (account) + { + account_add_name_avatar_to_info(account, handle->entry_avatar); + + ui_label_set_text(handle->entry_label, GNUNET_CHAT_account_get_name(account)); + } - ui_avatar_set_text(handle->entry_avatar, name); - ui_label_set_text(handle->entry_label, name); + handle->account = account; } void @@ -94,6 +103,7 @@ ui_account_entry_delete(UI_ACCOUNT_ENTRY_Handle *handle) { g_assert(handle); + ui_account_entry_set_account(handle, NULL); ui_account_entry_set_contact(handle, NULL); g_object_unref(handle->builder); diff --git a/src/ui/account_entry.h b/src/ui/account_entry.h @@ -27,8 +27,11 @@ #include "messenger.h" +#include <gnunet/gnunet_chat_lib.h> + typedef struct UI_ACCOUNT_ENTRY_Handle { + const struct GNUNET_CHAT_Account *account; const struct GNUNET_CHAT_Contact *contact; GtkBuilder *builder; diff --git a/src/ui/contact_info.c b/src/ui/contact_info.c @@ -26,6 +26,7 @@ #include "chat_entry.h" +#include "../account.h" #include "../application.h" #include "../contact.h" #include "../file.h" @@ -48,19 +49,12 @@ handle_contact_edit_button_click(UNUSED GtkButton *button, GTK_WIDGET(handle->contact_name_entry) ); - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) ( - g_object_get_qdata( - G_OBJECT(handle->contact_name_entry), - handle->app->quarks.data - ) - ); - if (!editable) goto skip_change_name; const gboolean change_own_name = ( - (!contact) || - (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact)) + (!(handle->contact)) || + (GNUNET_YES == GNUNET_CHAT_contact_is_owned(handle->contact)) ); const gchar *name = gtk_entry_get_text(handle->contact_name_entry); @@ -77,7 +71,7 @@ handle_contact_edit_button_click(UNUSED GtkButton *button, ); } else - GNUNET_CHAT_contact_set_name(contact, name); + GNUNET_CHAT_contact_set_name(handle->contact, name); skip_change_name: gtk_image_set_from_icon_name( @@ -258,17 +252,10 @@ handle_block_button_click(UNUSED GtkButton *button, UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data; - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) ( - g_object_get_qdata( - G_OBJECT(handle->block_stack), - handle->app->quarks.data - ) - ); - - if (!contact) + if (!(handle->contact)) return; - GNUNET_CHAT_contact_set_blocked(contact, GNUNET_YES); + GNUNET_CHAT_contact_set_blocked(handle->contact, GNUNET_YES); gtk_stack_set_visible_child( handle->block_stack, @@ -284,17 +271,10 @@ handle_unblock_button_click(UNUSED GtkButton *button, UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data; - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) ( - g_object_get_qdata( - G_OBJECT(handle->block_stack), - handle->app->quarks.data - ) - ); - - if (!contact) + if (!(handle->contact)) return; - GNUNET_CHAT_contact_set_blocked(contact, GNUNET_NO); + GNUNET_CHAT_contact_set_blocked(handle->contact, GNUNET_NO); gtk_stack_set_visible_child( handle->block_stack, @@ -310,18 +290,11 @@ handle_open_chat_button_click(UNUSED GtkButton *button, UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data; - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) ( - g_object_get_qdata( - G_OBJECT(handle->contact_name_entry), - handle->app->quarks.data - ) - ); - - if (!contact) + if (!(handle->contact)) return; struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context( - contact + handle->contact ); if (!context) @@ -697,12 +670,8 @@ handle_value_renderer_edit(GtkCellRendererText *renderer, if (!chat) return; - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) g_object_get_qdata( - G_OBJECT(handle->attributes_tree), - handle->app->quarks.data - ); - - if ((contact) && (GNUNET_YES != GNUNET_CHAT_contact_is_owned(contact))) + if ((handle->contact) && + (GNUNET_YES != GNUNET_CHAT_contact_is_owned(handle->contact))) return; GValue value = G_VALUE_INIT; @@ -802,12 +771,8 @@ handle_share_renderer_toggle(GtkCellRendererToggle *renderer, if (!chat) return; - struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) g_object_get_qdata( - G_OBJECT(handle->sharing_tree), - handle->app->quarks.data - ); - - if ((!contact) || (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact))) + if ((!(handle->contact)) || + (GNUNET_YES == GNUNET_CHAT_contact_is_owned(handle->contact))) return; GValue value_name = G_VALUE_INIT; @@ -820,9 +785,9 @@ handle_share_renderer_toggle(GtkCellRendererToggle *renderer, const gboolean shared = g_value_get_boolean(&value_shared); if (shared) - GNUNET_CHAT_unshare_attribute_from(chat, contact, name); + GNUNET_CHAT_unshare_attribute_from(chat, handle->contact, name); else - GNUNET_CHAT_share_attribute_with(chat, contact, name); + GNUNET_CHAT_share_attribute_with(chat, handle->contact, name); gtk_list_store_set(handle->sharing_list, &iter, 2, !shared, -1); @@ -838,6 +803,9 @@ ui_contact_info_dialog_init(MESSENGER_Application *app, handle->app = app; + handle->account = NULL; + handle->contact = NULL; + handle->builder = ui_builder_from_resource( application_get_resource_path(app, "ui/contact_info.ui") ); @@ -1126,21 +1094,26 @@ _contact_info_update(UI_CONTACT_INFO_Handle *handle, { g_assert(handle); - struct GNUNET_CHAT_Contact *prev = g_object_get_qdata( - G_OBJECT(handle->contact_avatar), - handle->app->quarks.data - ); - - if (prev) - contact_remove_name_avatar_from_info(prev, handle->contact_avatar); + if (handle->contact) + contact_remove_name_avatar_from_info(handle->contact, handle->contact_avatar); if (contact) contact_add_name_avatar_to_info(contact, handle->contact_avatar); - g_object_set_qdata( - G_OBJECT(handle->contact_avatar), - handle->app->quarks.data, - contact - ); + handle->contact = contact; +} + +static void +_account_info_update(UI_CONTACT_INFO_Handle *handle, + const struct GNUNET_CHAT_Account *account) +{ + g_assert(handle); + + if (handle->account) + account_remove_name_avatar_from_info(handle->account, handle->contact_avatar); + if (account) + account_add_name_avatar_to_info(account, handle->contact_avatar); + + handle->account = account; } void @@ -1161,27 +1134,15 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle, if (contact) _contact_info_update(handle, contact); else - ui_avatar_set_text(handle->contact_avatar, name); - - ui_entry_set_text(handle->contact_name_entry, name); - - g_object_set_qdata( - G_OBJECT(handle->contact_name_entry), - handle->app->quarks.data, - contact - ); + { + const struct GNUNET_CHAT_Account *account = GNUNET_CHAT_get_connected( + handle->app->chat.messenger.handle + ); - g_object_set_qdata( - G_OBJECT(handle->attributes_tree), - handle->app->quarks.data, - contact - ); + _account_info_update(handle, account); + } - g_object_set_qdata( - G_OBJECT(handle->sharing_tree), - handle->app->quarks.data, - contact - ); + ui_entry_set_text(handle->contact_name_entry, name); const gboolean editable = ( (!contact) || @@ -1278,12 +1239,6 @@ ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle, !editable ); - g_object_set_qdata( - G_OBJECT(handle->block_stack), - handle->app->quarks.data, - contact - ); - gtk_list_store_clear(handle->attributes_list); gtk_list_store_clear(handle->sharing_list); @@ -1343,7 +1298,9 @@ ui_contact_info_dialog_cleanup(UI_CONTACT_INFO_Handle *handle) handle->id_draw_signal ); + _account_info_update(handle, NULL); _contact_info_update(handle, NULL); + g_object_unref(handle->builder); if (handle->qr) diff --git a/src/ui/contact_info.h b/src/ui/contact_info.h @@ -29,12 +29,16 @@ #include <cairo/cairo.h> #include <gdk/gdkpixbuf.h> +#include <gnunet/gnunet_chat_lib.h> #include <qrencode.h> typedef struct UI_CONTACT_INFO_Handle { MESSENGER_Application *app; + const struct GNUNET_CHAT_Account *account; + struct GNUNET_CHAT_Contact *contact; + GtkBuilder *builder; GtkDialog *dialog; diff --git a/src/ui/messenger.c b/src/ui/messenger.c @@ -709,8 +709,7 @@ _messenger_iterate_accounts(void *cls, UI_ACCOUNT_ENTRY_Handle *entry = ui_account_entry_new(app); - ui_avatar_set_text(entry->entry_avatar, name); - ui_label_set_text(entry->entry_label, name); + ui_account_entry_set_account(entry, account); gtk_list_box_prepend(ui->accounts_listbox, entry->entry_box);