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:
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);