messenger-gtk

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

commit 9ff0f0e2e8d554f465d7aad51ce7fb33e61a749c
parent e249e4e634479290b20bed4a95f17446ea2737c3
Author: Jacki <jacki@thejackimonster.de>
Date:   Wed, 14 Feb 2024 04:29:15 +0100

Fix segfault and simplify internal message lists

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

Diffstat:
Msrc/contact.c | 28+++++++++++++++++++++++++++-
Msrc/contact.h | 22++++++++++++++++++++++
Msrc/event.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/ui/chat.c | 54+++++++++++++++++++++++++-----------------------------
Msrc/ui/chat.h | 2--
Msrc/ui/chat_entry.c | 38++++++++++++++++++++++++++++----------
Msrc/ui/message.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/ui/message.h | 12++++++++++++
8 files changed, 275 insertions(+), 82 deletions(-)

diff --git a/src/contact.c b/src/contact.c @@ -63,7 +63,7 @@ contact_destroy_info(struct GNUNET_CHAT_Contact *contact) void contact_set_last_message_to_info(const struct GNUNET_CHAT_Contact *contact, - void *message) + void *message) { MESSENGER_ContactInfo* info = GNUNET_CHAT_contact_get_user_pointer(contact); @@ -101,6 +101,19 @@ contact_add_name_label_to_info(const struct GNUNET_CHAT_Contact *contact, } void +contact_remove_name_label_from_info(const struct GNUNET_CHAT_Contact *contact, + GtkLabel *label) +{ + MESSENGER_ContactInfo* info = GNUNET_CHAT_contact_get_user_pointer(contact); + + if ((!info) || (!label)) + return; + + if (info->name_labels) + info->name_labels = g_list_remove(info->name_labels, label); +} + +void contact_add_name_avatar_to_info(const struct GNUNET_CHAT_Contact *contact, HdyAvatar *avatar) { @@ -117,6 +130,19 @@ contact_add_name_avatar_to_info(const struct GNUNET_CHAT_Contact *contact, } void +contact_remove_name_avatar_from_info(const struct GNUNET_CHAT_Contact *contact, + HdyAvatar *avatar) +{ + MESSENGER_ContactInfo* info = GNUNET_CHAT_contact_get_user_pointer(contact); + + if ((!info) || (!avatar)) + return; + + if (info->name_avatars) + info->name_avatars = g_list_remove(info->name_avatars, avatar); +} + +void contact_update_info(const struct GNUNET_CHAT_Contact *contact) { MESSENGER_ContactInfo* info = GNUNET_CHAT_contact_get_user_pointer(contact); diff --git a/src/contact.h b/src/contact.h @@ -86,6 +86,17 @@ contact_add_name_label_to_info(const struct GNUNET_CHAT_Contact *contact, GtkLabel *label); /** + * Removes a GtkLabel from the list of labels + * which get updated by state changes. + * + * @param contact Chat contact + * @param label Label + */ +void +contact_remove_name_label_from_info(const struct GNUNET_CHAT_Contact *contact, + GtkLabel *label); + +/** * Adds a HdyAvatar to the list of avatars * which get updated by state changes. * @@ -97,6 +108,17 @@ contact_add_name_avatar_to_info(const struct GNUNET_CHAT_Contact *contact, HdyAvatar *avatar); /** + * Removes a HdyAvatar from the list of avatars + * which get updated by state changes. + * + * @param contact Chat contact + * @param avatar Avatar + */ +void +contact_remove_name_avatar_from_info(const struct GNUNET_CHAT_Contact *contact, + HdyAvatar *avatar); + +/** * Updates the connected UI elements for a given * contact depending on the current state. * diff --git a/src/event.c b/src/event.c @@ -24,6 +24,7 @@ #include "event.h" +#include "application.h" #include "contact.h" #include "file.h" #include "ui.h" @@ -37,6 +38,8 @@ static void _close_notification(NotifyNotification* notification, gpointer user_data) { + GNUNET_assert((notification) && (user_data)); + MESSENGER_Application *app = (MESSENGER_Application*) user_data; app->notifications = g_list_remove(app->notifications, notification); @@ -55,6 +58,11 @@ _show_notification(MESSENGER_Application *app, const char *icon, const char *category) { + GNUNET_assert( + (app) && (context) && (contact) && + (text) && (icon) && (category) + ); + if (app->settings.disable_notifications) return; @@ -86,6 +94,8 @@ event_handle_warning(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + const char *text = GNUNET_CHAT_message_get_text(msg); const struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( @@ -107,6 +117,8 @@ event_handle_warning(MESSENGER_Application *app, static gboolean _idle_refresh_accounts(gpointer user_data) { + GNUNET_assert(user_data); + MESSENGER_Application *app = (MESSENGER_Application*) user_data; if (!(app->ui.messenger.main_window)) @@ -125,6 +137,8 @@ refresh_exit: void event_refresh_accounts(MESSENGER_Application *app) { + GNUNET_assert(app); + if (app->ui.messenger.account_refresh) g_source_remove(app->ui.messenger.account_refresh); @@ -140,6 +154,8 @@ event_refresh_accounts(MESSENGER_Application *app) static gboolean _select_chat_to_activate(gpointer user_data) { + GNUNET_assert(user_data); + UI_CHAT_ENTRY_Handle *entry = (UI_CHAT_ENTRY_Handle*) user_data; if ((!entry) || (!(entry->chat)) || (!(entry->entry_box))) @@ -171,6 +187,8 @@ _select_chat_to_activate(gpointer user_data) static gboolean _idle_chat_entry_update(gpointer user_data) { + GNUNET_assert(user_data); + UI_CHAT_ENTRY_Handle *entry = (UI_CHAT_ENTRY_Handle*) user_data; if ((!(entry->chat)) || (!(entry->chat->app)) || @@ -194,6 +212,8 @@ update_exit: static void enqueue_chat_entry_update(UI_CHAT_ENTRY_Handle *entry) { + GNUNET_assert(entry); + if (entry->update) g_source_remove(entry->update); @@ -207,6 +227,8 @@ static void _add_new_chat_entry(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context) { + GNUNET_assert((app) && (context)); + UI_MESSENGER_Handle *ui = &(app->ui.messenger); UI_CHAT_ENTRY_Handle *entry = ui_chat_entry_new(app); @@ -250,6 +272,8 @@ _iterate_profile_contacts(void *cls, UNUSED struct GNUNET_CHAT_Handle *handle, struct GNUNET_CHAT_Contact *contact) { + GNUNET_assert((cls) && (contact)); + MESSENGER_Application *app = (MESSENGER_Application*) cls; struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context( @@ -268,6 +292,8 @@ _iterate_profile_groups(void *cls, UNUSED struct GNUNET_CHAT_Handle *handle, UNUSED struct GNUNET_CHAT_Group *group) { + GNUNET_assert(cls); + MESSENGER_Application *app = (MESSENGER_Application*) cls; struct GNUNET_CHAT_Context *context = GNUNET_CHAT_group_get_context( @@ -285,7 +311,11 @@ static void _clear_chat_entry(GtkWidget *widget, gpointer user_data) { + GNUNET_assert((widget) && (user_data)); + MESSENGER_Application *app = (MESSENGER_Application*) user_data; + UI_MESSENGER_Handle *ui = &(app->ui.messenger); + GtkListBoxRow *row = GTK_LIST_BOX_ROW(widget); if (!gtk_list_box_row_get_selectable(row)) @@ -296,6 +326,8 @@ _clear_chat_entry(GtkWidget *widget, app->quarks.ui ); + ui->chat_entries = g_list_remove(ui->chat_entries, entry); + g_object_set_qdata( G_OBJECT(entry->chat->send_text_view), app->quarks.data, @@ -308,6 +340,8 @@ _clear_chat_entry(GtkWidget *widget, void event_update_profile(MESSENGER_Application *app) { + GNUNET_assert(app); + UI_MESSENGER_Handle *ui = &(app->ui.messenger); CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); @@ -320,12 +354,13 @@ event_update_profile(MESSENGER_Application *app) ui_label_set_text(ui->profile_key_label, key); - gtk_container_foreach( - GTK_CONTAINER(ui->chats_listbox), - _clear_chat_entry, - app + GList *entries = gtk_container_get_children( + GTK_CONTAINER(ui->chats_listbox) ); + g_list_foreach(entries, (GFunc) _clear_chat_entry, app); + g_list_free(entries); + gtk_stack_set_visible_child(ui->chats_stack, ui->no_chat_box); GNUNET_CHAT_iterate_contacts(chat->handle, _iterate_profile_contacts, app); @@ -337,6 +372,8 @@ _cleanup_profile_contacts(void *cls, UNUSED struct GNUNET_CHAT_Handle *handle, struct GNUNET_CHAT_Contact *contact) { + GNUNET_assert((cls) && (contact)); + if (contact) contact_destroy_info(contact); return GNUNET_YES; @@ -345,6 +382,8 @@ _cleanup_profile_contacts(void *cls, void event_cleanup_profile(MESSENGER_Application *app) { + GNUNET_assert(app); + CHAT_MESSENGER_Handle *chat = &(app->chat.messenger); GNUNET_CHAT_iterate_contacts(chat->handle, _cleanup_profile_contacts, NULL); @@ -353,6 +392,8 @@ event_cleanup_profile(MESSENGER_Application *app) gboolean _delayed_context_drop(gpointer user_data) { + GNUNET_assert(user_data); + struct GNUNET_CHAT_Context *context = (struct GNUNET_CHAT_Context*) user_data; struct GNUNET_CHAT_Group *group = GNUNET_CHAT_context_get_group(context); @@ -371,6 +412,8 @@ event_update_chats(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); const enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind( @@ -400,6 +443,8 @@ event_update_chats(MESSENGER_Application *app, static void _update_contact_context(struct GNUNET_CHAT_Contact *contact) { + GNUNET_assert(contact); + struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context( contact ); @@ -420,6 +465,8 @@ event_presence_contact(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( @@ -456,9 +503,7 @@ event_presence_contact(MESSENGER_Application *app, ui_message_update(message, app, msg); _update_contact_context(contact); - - contact_add_name_avatar_to_info(contact, message->sender_avatar); - contact_add_name_label_to_info(contact, message->sender_label); + ui_message_set_contact(message, contact); const enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind( msg @@ -504,6 +549,8 @@ event_update_contacts(UNUSED MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + struct GNUNET_CHAT_Contact *contact = GNUNET_CHAT_message_get_sender( msg ); @@ -526,6 +573,8 @@ static void _event_invitation_accept_click(UNUSED GtkButton *button, gpointer user_data) { + GNUNET_assert(user_data); + struct GNUNET_CHAT_Invitation *invitation = ( (struct GNUNET_CHAT_Invitation*) user_data ); @@ -537,6 +586,8 @@ static void _event_invitation_deny_click(UNUSED GtkButton *button, gpointer user_data) { + GNUNET_assert(user_data); + struct GNUNET_CHAT_Invitation *invitation = ( (struct GNUNET_CHAT_Invitation*) user_data ); @@ -549,6 +600,8 @@ event_invitation(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); if (!handle) @@ -582,8 +635,7 @@ event_invitation(MESSENGER_Application *app, msg ); - contact_add_name_avatar_to_info(sender, message->sender_avatar); - contact_add_name_label_to_info(sender, message->sender_label); + ui_message_set_contact(message, sender); const char *invite_message = _("invited %s to a chat"); const char *recipient_name = ( @@ -632,6 +684,8 @@ event_receive_message(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); if (!handle) @@ -679,8 +733,7 @@ event_receive_message(MESSENGER_Application *app, msg ); - contact_add_name_avatar_to_info(contact, message->sender_avatar); - contact_add_name_label_to_info(contact, message->sender_label); + ui_message_set_contact(message, contact); struct GNUNET_TIME_Absolute timestamp = GNUNET_CHAT_message_get_timestamp( msg @@ -714,26 +767,33 @@ event_delete_message(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); if ((!handle) || (!(handle->chat))) return; - GList *messages = handle->chat->messages; + GList *rows = gtk_container_get_children( + GTK_CONTAINER(handle->chat->messages_listbox) + ); - while (messages) + for (GList *row = rows; row; row = row->next) { - UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) (messages->data); + UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) g_object_get_qdata( + G_OBJECT(row->data), app->quarks.ui + ); if ((message) && (message->msg == GNUNET_CHAT_message_get_target(msg))) { ui_chat_remove_message(handle->chat, app, message); break; } - - messages = messages->next; } + if (rows) + g_list_free(rows); + enqueue_chat_entry_update(handle); } @@ -742,6 +802,8 @@ event_tag_message(MESSENGER_Application *app, struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((app) && (context) && (msg)); + UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); const struct GNUNET_CHAT_Message *target = GNUNET_CHAT_message_get_target(msg); @@ -758,20 +820,25 @@ event_tag_message(MESSENGER_Application *app, if ((!handle) || (!(handle->chat))) return; - GList *messages = handle->chat->messages; + GList *rows = gtk_container_get_children( + GTK_CONTAINER(handle->chat->messages_listbox) + ); - while (messages) + for (GList *row = rows; row; row = row->next) { - UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) (messages->data); + UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) g_object_get_qdata( + G_OBJECT(row->data), app->quarks.ui + ); if ((message) && (message->msg == target)) { ui_message_update(message, app, message->msg); break; } - - messages = messages->next; } + if (rows) + g_list_free(rows); + enqueue_chat_entry_update(handle); } diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -1680,22 +1680,33 @@ ui_chat_update(UI_CHAT_Handle *handle, gtk_widget_set_sensitive(GTK_WIDGET(handle->emoji_button), activated); gtk_widget_set_sensitive(GTK_WIDGET(handle->send_record_button), activated); - if (!(handle->messages)) + GList *rows = gtk_container_get_children( + GTK_CONTAINER(handle->messages_listbox) + ); + + if (!rows) return; - GList *list = handle->messages; - while (list) + UI_MESSAGE_Handle *last_message = NULL; + for (GList *row = rows; row; row = row->next) { - ui_message_refresh((UI_MESSAGE_Handle*) list->data); - list = list->next; + UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) g_object_get_qdata( + G_OBJECT(row->data), app->quarks.ui + ); + + if (!message) + continue; + + ui_message_refresh(message); + last_message = message; } - UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) (handle->messages->data); + g_list_free(rows); - if (!(message->timestamp_label)) + if ((!last_message) || (!(last_message->timestamp_label))) return; - const gchar *time = gtk_label_get_text(message->timestamp_label); + const gchar *time = gtk_label_get_text(last_message->timestamp_label); if (!group) gtk_label_set_text(handle->chat_subtitle, time); @@ -1710,9 +1721,6 @@ ui_chat_delete(UI_CHAT_Handle *handle) g_object_unref(handle->builder); - if (handle->messages) - g_list_free_full(handle->messages, (GDestroyNotify) ui_message_delete); - if (handle->loads) g_list_free_full(handle->loads, (GDestroyNotify) ui_file_load_entry_delete); @@ -1753,22 +1761,8 @@ ui_chat_add_message(UI_CHAT_Handle *handle, ); GtkWidget *row = gtk_widget_get_parent(message->message_box); - g_object_set_qdata(G_OBJECT(row), app->quarks.ui, message); - GList *sibling = handle->messages; - while (sibling) - { - UI_MESSAGE_Handle *latest = (UI_MESSAGE_Handle*) sibling->data; - - if (GNUNET_TIME_absolute_cmp(latest->timestamp, <, message->timestamp)) - break; - - sibling = sibling->next; - } - - handle->messages = g_list_insert_before(handle->messages, sibling, message); - gtk_list_box_invalidate_sort(handle->messages_listbox); } @@ -1779,13 +1773,15 @@ ui_chat_remove_message(UI_CHAT_Handle *handle, { GNUNET_assert((handle) && (message) && (message->message_box)); - handle->messages = g_list_remove(handle->messages, message); - GtkWidget *row = gtk_widget_get_parent(message->message_box); + g_object_set_qdata(G_OBJECT(row), app->quarks.ui, NULL); + + GtkWidget *parent = gtk_widget_get_parent(row); - gtk_container_remove(GTK_CONTAINER(handle->messages_listbox), row); + if (parent == GTK_WIDGET(handle->messages_listbox)) + gtk_container_remove(GTK_CONTAINER(handle->messages_listbox), row); - handle->messages = g_list_append(handle->messages, message); + ui_message_delete(message); } void diff --git a/src/ui/chat.h b/src/ui/chat.h @@ -66,9 +66,7 @@ typedef struct UI_CHAT_Handle MESSENGER_Application *app; - GList *messages; gdouble edge_value; - GList *loads; GtkBuilder *builder; diff --git a/src/ui/chat_entry.c b/src/ui/chat_entry.c @@ -110,22 +110,40 @@ ui_chat_entry_update(UI_CHAT_ENTRY_Handle *handle, ui_chat_update(handle->chat, app, context); - if (!(handle->chat->messages)) + GList *rows = gtk_container_get_children( + GTK_CONTAINER(handle->chat->messages_listbox) + ); + + if (!rows) return; - UI_MESSAGE_Handle *message = ( - (UI_MESSAGE_Handle*) handle->chat->messages->data - ); + UI_MESSAGE_Handle *last_message = NULL; + for (GList *row = rows; row; row = row->next) + { + UI_MESSAGE_Handle *message = (UI_MESSAGE_Handle*) g_object_get_qdata( + G_OBJECT(row->data), app->quarks.ui + ); + + if (!message) + continue; + + last_message = message; + } + + g_list_free(rows); + + if (!last_message) + return; - handle->timestamp = message->timestamp; + handle->timestamp = last_message->timestamp; - const gchar *text = gtk_label_get_text(message->text_label); - const gchar *time = gtk_label_get_text(message->timestamp_label); + const gchar *text = gtk_label_get_text(last_message->text_label); + const gchar *time = gtk_label_get_text(last_message->timestamp_label); if (group) { GString *message_text = g_string_new( - gtk_label_get_text(message->sender_label) + gtk_label_get_text(last_message->sender_label) ); g_string_append_printf( @@ -144,8 +162,8 @@ ui_chat_entry_update(UI_CHAT_ENTRY_Handle *handle, gtk_widget_set_visible( GTK_WIDGET(handle->read_receipt_image), - message->read_receipt_image? gtk_widget_is_visible( - GTK_WIDGET(message->read_receipt_image) + last_message->read_receipt_image? gtk_widget_is_visible( + GTK_WIDGET(last_message->read_receipt_image) ) : FALSE ); diff --git a/src/ui/message.c b/src/ui/message.c @@ -28,6 +28,7 @@ #include <gnunet/gnunet_common.h> #include "../application.h" +#include "../contact.h" #include "../file.h" #include "../ui.h" @@ -37,6 +38,8 @@ handle_downloading_file(void *cls, uint64_t completed, uint64_t size) { + GNUNET_assert((cls) && (file)); + MESSENGER_Application *app = (MESSENGER_Application*) cls; if (!app) @@ -49,17 +52,19 @@ static void handle_file_button_click(GtkButton *button, gpointer user_data) { + GNUNET_assert((button) && (user_data)); + MESSENGER_Application *app = (MESSENGER_Application*) user_data; UI_MESSAGE_Handle* handle = (UI_MESSAGE_Handle*) ( - g_object_get_qdata(G_OBJECT(button), app->quarks.ui) + g_object_get_qdata(G_OBJECT(button), app->quarks.ui) ); if (!handle) return; struct GNUNET_CHAT_File *file = (struct GNUNET_CHAT_File*) ( - g_object_get_qdata(G_OBJECT(handle->file_progress_bar), app->quarks.data) + g_object_get_qdata(G_OBJECT(handle->file_progress_bar), app->quarks.data) ); if (!file) @@ -77,9 +82,9 @@ handle_file_button_click(GtkButton *button, GNUNET_CHAT_file_stop_download(file); gtk_image_set_from_icon_name( - handle->file_status_image, - "folder-download-symbolic", - GTK_ICON_SIZE_BUTTON + handle->file_status_image, + "folder-download-symbolic", + GTK_ICON_SIZE_BUTTON ); } else if (local_size < size) @@ -113,6 +118,8 @@ static void handle_media_button_click(GtkButton *button, gpointer user_data) { + GNUNET_assert((button) && (user_data)); + MESSENGER_Application *app = (MESSENGER_Application*) user_data; UI_MESSAGE_Handle* handle = (UI_MESSAGE_Handle*) ( @@ -152,6 +159,8 @@ handle_media_button_click(GtkButton *button, static int handle_message_redraw_animation(gpointer user_data) { + GNUNET_assert(user_data); + UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data; handle->redraw_animation = 0; @@ -167,9 +176,11 @@ handle_message_redraw_animation(gpointer user_data) static gboolean handle_preview_drawing_area_draw(GtkWidget* drawing_area, - cairo_t* cairo, - gpointer user_data) + cairo_t* cairo, + gpointer user_data) { + GNUNET_assert((drawing_area) && (cairo) && (user_data)); + UI_MESSAGE_Handle *handle = (UI_MESSAGE_Handle*) user_data; GtkStyleContext* context = gtk_widget_get_style_context(drawing_area); @@ -188,17 +199,17 @@ handle_preview_drawing_area_draw(GtkWidget* drawing_area, gdk_pixbuf_animation_iter_advance(handle->preview_animation_iter, NULL); else handle->preview_animation_iter = gdk_pixbuf_animation_get_iter( - handle->preview_animation, NULL + handle->preview_animation, NULL ); image = gdk_pixbuf_animation_iter_get_pixbuf(handle->preview_animation_iter); const int delay = gdk_pixbuf_animation_iter_get_delay_time( - handle->preview_animation_iter + handle->preview_animation_iter ); handle->redraw_animation = g_timeout_add( - delay, handle_message_redraw_animation, handle + delay, handle_message_redraw_animation, handle ); render_image: @@ -211,9 +222,9 @@ render_image: gint optimal_height = width * dheight / dwidth; gtk_widget_set_size_request( - GTK_WIDGET(drawing_area), - width, - optimal_height + GTK_WIDGET(drawing_area), + width, + optimal_height ); double ratio_width = 1.0 * width / dwidth; @@ -228,15 +239,15 @@ render_image: double dy = (height - dheight) * 0.5; const int interp_type = (ratio >= 1.0? - GDK_INTERP_NEAREST : - GDK_INTERP_BILINEAR + GDK_INTERP_NEAREST : + GDK_INTERP_BILINEAR ); GdkPixbuf* scaled = gdk_pixbuf_scale_simple( - image, - dwidth, - dheight, - interp_type + image, + dwidth, + dheight, + interp_type ); gtk_render_icon(context, cairo, scaled, dx, dy); @@ -250,6 +261,8 @@ render_image: static void _clear_message_preview_data(UI_MESSAGE_Handle *handle) { + GNUNET_assert(handle); + if (handle->preview_image) { g_object_unref(handle->preview_image); @@ -286,12 +299,15 @@ UI_MESSAGE_Handle* ui_message_new(MESSENGER_Application *app, UI_MESSAGE_Type type) { + GNUNET_assert(app); + UI_MESSAGE_Handle* handle = g_malloc(sizeof(UI_MESSAGE_Handle)); handle->type = type; handle->timestamp = GNUNET_TIME_absolute_get_zero_(); handle->msg = NULL; + handle->contact = NULL; const char *ui_builder_file; @@ -476,6 +492,8 @@ _iterate_read_receipts(void *cls, const struct GNUNET_CHAT_Contact *contact, int read_receipt) { + GNUNET_assert((cls) && (message) && (contact)); + int *count_read_receipts = (int*) cls; if ((GNUNET_YES == read_receipt) && @@ -488,10 +506,15 @@ _iterate_read_receipts(void *cls, void ui_message_refresh(UI_MESSAGE_Handle *handle) { + GNUNET_assert(handle); + if ((!(handle->msg)) || (GNUNET_YES != GNUNET_CHAT_message_is_sent(handle->msg))) return; + if (!(handle->read_receipt_image)) + return; + int count = 0; if ((0 < GNUNET_CHAT_message_get_read_receipt(handle->msg, _iterate_read_receipts, &count)) && (0 < count)) @@ -526,6 +549,8 @@ _update_invitation_message(UI_MESSAGE_Handle *handle, MESSENGER_Application *app, struct GNUNET_CHAT_Invitation *invitation) { + GNUNET_assert((handle) && (app) && (invitation)); + enum GNUNET_GenericReturnValue accepted, rejected; accepted = GNUNET_CHAT_invitation_is_accepted(invitation); rejected = GNUNET_CHAT_invitation_is_rejected(invitation); @@ -564,6 +589,8 @@ _update_file_message(UI_MESSAGE_Handle *handle, MESSENGER_Application *app, struct GNUNET_CHAT_File *file) { + GNUNET_assert((handle) && (app) && (file)); + const char *filename = GNUNET_CHAT_file_get_name(file); uint64_t size = GNUNET_CHAT_file_get_size(file); @@ -686,6 +713,8 @@ ui_message_update(UI_MESSAGE_Handle *handle, MESSENGER_Application *app, const struct GNUNET_CHAT_Message *msg) { + GNUNET_assert((handle) && (app) && (msg)); + struct GNUNET_CHAT_File *file = NULL; struct GNUNET_CHAT_Invitation *invitation = NULL; @@ -728,8 +757,33 @@ ui_message_update(UI_MESSAGE_Handle *handle, } void +ui_message_set_contact(UI_MESSAGE_Handle *handle, + const struct GNUNET_CHAT_Contact *contact) +{ + GNUNET_assert(handle); + + if (handle->contact) + { + contact_remove_name_avatar_from_info(handle->contact, handle->sender_avatar); + contact_remove_name_label_from_info(handle->contact, handle->sender_label); + } + + if (contact) + { + contact_add_name_avatar_to_info(contact, handle->sender_avatar); + contact_add_name_label_to_info(contact, handle->sender_label); + } + + handle->contact = contact; +} + +void ui_message_delete(UI_MESSAGE_Handle *handle) { + GNUNET_assert(handle); + + ui_message_set_contact(handle, NULL); + _clear_message_preview_data(handle); g_object_unref(handle->builder[1]); diff --git a/src/ui/message.h b/src/ui/message.h @@ -47,6 +47,7 @@ typedef struct UI_MESSAGE_Handle struct GNUNET_TIME_Absolute timestamp; const struct GNUNET_CHAT_Message *msg; + const struct GNUNET_CHAT_Contact *contact; GtkBuilder *builder [2]; GtkWidget *message_box; @@ -126,6 +127,17 @@ ui_message_update(UI_MESSAGE_Handle *handle, const struct GNUNET_CHAT_Message *message); /** + * Sets the contact of a given message handle + * to track contact information widgets. + * + * @param handle Message handle + * @param contact Contact + */ +void +ui_message_set_contact(UI_MESSAGE_Handle *handle, + const struct GNUNET_CHAT_Contact *contact); + +/** * Frees its resources and destroys a given * message handle. *