messenger-gtk

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

commit 69e3d367f8e0d1168d5c6d6daebed1d2722b265c
parent 031a28213115d042de65ce344a8f4a23a8ba056a
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Mon, 10 Jan 2022 17:21:28 +0100

Adding visual list of current uploading files to be sent

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>

Diffstat:
MMakefile | 2++
Mresources/ui.gresource.xml | 4++--
Mresources/ui/chat.ui | 39+++++++++++++++++++++++++++++++++++++--
Aresources/ui/file_load_entry.ui | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/contact.c | 4++--
Msrc/event.c | 23++++-------------------
Asrc/file.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/file.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ui/chat.c | 131++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/ui/chat.h | 28++++++++++++++++++++++++++--
Msrc/ui/chat_entry.c | 6+++---
Asrc/ui/file_load_entry.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ui/file_load_entry.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ui/new_contact.c | 2+-
Msrc/ui/send_file.c | 52++++++++++++++++++++++++++++++++++++++++++++--------
15 files changed, 635 insertions(+), 44 deletions(-)

diff --git a/Makefile b/Makefile @@ -10,12 +10,14 @@ SOURCES = messenger_gtk.c\ application.c\ contact.c\ event.c\ + file.c\ resources.c\ chat/messenger.c\ ui/chat.c\ ui/chat_entry.c\ ui/contact_entry.c\ ui/contacts.c\ + ui/file_load_entry.c\ ui/invite_contact.c\ ui/message.c\ ui/messenger.c\ diff --git a/resources/ui.gresource.xml b/resources/ui.gresource.xml @@ -4,6 +4,7 @@ <file compressed="true">ui/chat_entry.ui</file> <file compressed="true">ui/chat.ui</file> <file compressed="true">ui/contacts.ui</file> + <file compressed="true">ui/file_load_entry.ui</file> <file compressed="true">ui/invite_contact.ui</file> <file compressed="true">ui/message_content.ui</file> <file compressed="true">ui/message.ui</file> @@ -19,4 +20,4 @@ <file compressed="true">ui/send_file.ui</file> <file compressed="true">ui/settings.ui</file> </gresource> -</gresources> -\ No newline at end of file +</gresources> diff --git a/resources/ui/chat.ui b/resources/ui/chat.ui @@ -69,7 +69,6 @@ Author: Tobias Frisch <object class="GtkBox"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="halign">start</property> <property name="margin-start">4</property> <property name="margin-end">4</property> <property name="orientation">vertical</property> @@ -77,6 +76,8 @@ Author: Tobias Frisch <object class="GtkLabel" id="chat_title"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="ellipsize">end</property> + <property name="single-line-mode">True</property> <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> @@ -92,6 +93,8 @@ Author: Tobias Frisch <object class="GtkLabel" id="chat_subtitle"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="ellipsize">end</property> + <property name="single-line-mode">True</property> <property name="xalign">0</property> <attributes> <attribute name="weight" value="light"/> @@ -101,7 +104,7 @@ Author: Tobias Frisch </style> </object> <packing> - <property name="expand">True</property> + <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> @@ -134,6 +137,26 @@ Author: Tobias Frisch <property name="position">1</property> </packing> </child> + <child> + <object class="GtkButton" id="chat_load_button"> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="relief">none</property> + <child> + <object class="GtkSpinner"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="active">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">3</property> + </packing> + </child> <style> <class name=".header-box"/> </style> @@ -530,4 +553,16 @@ Author: Tobias Frisch </packing> </child> </object> + <object class="GtkPopover" id="chat_load_popover"> + <property name="can-focus">False</property> + <property name="relative-to">chat_load_button</property> + <property name="position">bottom</property> + <child> + <object class="GtkListBox" id="chat_load_listbox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="selection-mode">none</property> + </object> + </child> + </object> </interface> diff --git a/resources/ui/file_load_entry.ui b/resources/ui/file_load_entry.ui @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 + +Copyright (C) 2022 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 + +--> +<interface> + <requires lib="gtk+" version="3.24"/> + <object class="GtkBox" id="entry_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">4</property> + <property name="spacing">8</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkImage" id="file_image"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="icon-name">folder-documents-symbolic</property> + <property name="icon_size">3</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="file_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="ellipsize">start</property> + <property name="single-line-mode">True</property> + <property name="xalign">0</property> + <property name="yalign">1</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkProgressBar" id="load_progress_bar"> + <property name="height-request">8</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel_button"> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="valign">center</property> + <property name="relief">none</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="icon-name">process-stop-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">2</property> + </packing> + </child> + </object> +</interface> diff --git a/src/contact.c b/src/contact.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2021 GNUnet e.V. + Copyright (C) 2021--2022 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 @@ -27,7 +27,7 @@ void contact_create_info(struct GNUNET_CHAT_Contact *contact) { - if (GNUNET_CHAT_contact_get_user_pointer(contact)) + if ((!contact) || (GNUNET_CHAT_contact_get_user_pointer(contact))) return; MESSENGER_ContactInfo* info = g_malloc(sizeof(MESSENGER_ContactInfo)); diff --git a/src/event.c b/src/event.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2021 GNUnet e.V. + Copyright (C) 2021--2022 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 @@ -268,12 +268,7 @@ event_joining_contact(MESSENGER_Application *app, gtk_label_set_text(message->text_label, join_message); gtk_label_set_text(message->timestamp_label, time? time : ""); - gtk_container_add( - GTK_CONTAINER(handle->chat->messages_listbox), - message->message_box - ); - - handle->chat->messages = g_list_prepend(handle->chat->messages, message); + ui_chat_add_message(handle->chat, message); ui_chat_entry_update(handle, app, context); } @@ -357,12 +352,7 @@ event_invitation(UNUSED MESSENGER_Application *app, gtk_widget_show(GTK_WIDGET(message->deny_button)); gtk_widget_show(GTK_WIDGET(message->accept_button)); - gtk_container_add( - GTK_CONTAINER(handle->chat->messages_listbox), - message->message_box - ); - - handle->chat->messages = g_list_prepend(handle->chat->messages, message); + ui_chat_add_message(handle->chat, message); ui_chat_entry_update(handle, app, context); } @@ -412,11 +402,6 @@ event_receive_message(UNUSED MESSENGER_Application *app, gtk_label_set_text(message->text_label, text? text : ""); gtk_label_set_text(message->timestamp_label, time? time : ""); - gtk_container_add( - GTK_CONTAINER(handle->chat->messages_listbox), - message->message_box - ); - - handle->chat->messages = g_list_prepend(handle->chat->messages, message); + ui_chat_add_message(handle->chat, message); ui_chat_entry_update(handle, app, context); } diff --git a/src/file.c b/src/file.c @@ -0,0 +1,74 @@ +/* + This file is part of GNUnet. + Copyright (C) 2022 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 file.c + */ + +#include "file.h" + +void +file_create_info(struct GNUNET_CHAT_File *file) +{ + if ((!file) || (GNUNET_CHAT_file_get_user_pointer(file))) + return; + + MESSENGER_FileInfo* info = g_malloc(sizeof(MESSENGER_FileInfo)); + + info->file_messages = NULL; + + GNUNET_CHAT_file_set_user_pointer(file, info); +} + +void +file_destroy_info(struct GNUNET_CHAT_File *file) +{ + MESSENGER_FileInfo* info = GNUNET_CHAT_file_get_user_pointer(file); + + if (!info) + return; + + if (info->file_messages) + g_list_free(info->file_messages); + + g_free(info); + + GNUNET_CHAT_file_set_user_pointer(file, NULL); +} + +void +file_add_ui_message_to_info(const struct GNUNET_CHAT_File *file, + UI_MESSAGE_Handle *message) +{ + MESSENGER_FileInfo* info = GNUNET_CHAT_file_get_user_pointer(file); + + if ((!info) || (!message)) + return; + + info->file_messages = g_list_append(info->file_messages, message); +} + +void +file_update_upload_info(const struct GNUNET_CHAT_File *file, + uint64_t completed, + uint64_t size) +{ + // +} diff --git a/src/file.h b/src/file.h @@ -0,0 +1,51 @@ +/* + This file is part of GNUnet. + Copyright (C) 2022 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 file.h + */ + +#ifndef FILE_H_ +#define FILE_H_ + +#include "application.h" +#include "ui/message.h" + +typedef struct MESSENGER_FileInfo +{ + GList *file_messages; +} MESSENGER_FileInfo; + +void +file_create_info(struct GNUNET_CHAT_File *file); + +void +file_destroy_info(struct GNUNET_CHAT_File *file); + +void +file_add_ui_message_to_info(const struct GNUNET_CHAT_File *file, + UI_MESSAGE_Handle *message); + +void +file_update_upload_info(const struct GNUNET_CHAT_File *file, + uint64_t completed, + uint64_t size); + +#endif /* FILE_H_ */ diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2021 GNUnet e.V. + Copyright (C) 2021--2022 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 @@ -26,6 +26,7 @@ #include <gdk/gdkkeysyms.h> +#include "file_load_entry.h" #include "message.h" #include "messenger.h" #include "picker.h" @@ -40,11 +41,22 @@ handle_flap_via_button_click(UNUSED GtkButton *button, { HdyFlap *flap = HDY_FLAP(user_data); - if (TRUE == hdy_flap_get_reveal_flap(flap)) { + if (TRUE == hdy_flap_get_reveal_flap(flap)) hdy_flap_set_reveal_flap(flap, FALSE); - } else { + else hdy_flap_set_reveal_flap(flap, TRUE); - } +} + +static void +handle_popover_via_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + GtkPopover *popover = GTK_POPOVER(user_data); + + if (gtk_widget_is_visible(GTK_WIDGET(popover))) + gtk_popover_popdown(popover); + else + gtk_popover_popup(popover); } static void @@ -273,12 +285,16 @@ handle_picker_button_click(UNUSED GtkButton *button, UI_CHAT_Handle* ui_chat_new(MESSENGER_Application *app) { + GNUNET_assert(app); + UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle)); UI_MESSENGER_Handle *messenger = &(app->ui.messenger); handle->messages = NULL; handle->edge_value = 0; + handle->loads = NULL; + handle->builder = gtk_builder_new_from_resource( application_get_resource_path(app, "ui/chat.ui") ); @@ -318,6 +334,25 @@ ui_chat_new(MESSENGER_Application *app) gtk_builder_get_object(handle->builder, "chat_subtitle") ); + handle->chat_load_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "chat_load_button") + ); + + handle->chat_load_popover = GTK_POPOVER( + gtk_builder_get_object(handle->builder, "chat_load_popover") + ); + + handle->chat_load_listbox = GTK_LIST_BOX( + gtk_builder_get_object(handle->builder, "chat_load_listbox") + ); + + g_signal_connect( + handle->chat_load_button, + "clicked", + G_CALLBACK(handle_popover_via_button_click), + handle->chat_load_popover + ); + handle->chat_details_button = GTK_BUTTON( gtk_builder_get_object(handle->builder, "chat_details_button") ); @@ -505,6 +540,8 @@ ui_chat_update(UI_CHAT_Handle *handle, MESSENGER_Application *app, const struct GNUNET_CHAT_Context* context) { + GNUNET_assert((handle) && (app) && (context)); + const struct GNUNET_CHAT_Contact* contact; const struct GNUNET_CHAT_Group* group; @@ -586,7 +623,7 @@ 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) + if (!(handle->messages)) return; UI_MESSAGE_Handle *message = ( @@ -602,6 +639,8 @@ ui_chat_update(UI_CHAT_Handle *handle, void ui_chat_delete(UI_CHAT_Handle *handle) { + GNUNET_assert(handle); + ui_picker_delete(handle->picker); g_object_unref(handle->builder); @@ -615,8 +654,90 @@ ui_chat_delete(UI_CHAT_Handle *handle) list = list->next; } + list = handle->loads; + + while (list) { + if (list->data) + ui_file_load_entry_delete((UI_FILE_LOAD_ENTRY_Handle*) list->data); + + list = list->next; + } + if (handle->messages) g_list_free(handle->messages); + if (handle->loads) + g_list_free(handle->loads); + g_free(handle); } + +void +ui_chat_add_message(UI_CHAT_Handle *handle, + UI_MESSAGE_Handle *message) +{ + GNUNET_assert((handle) && (message)); + + gtk_container_add( + GTK_CONTAINER(handle->messages_listbox), + message->message_box + ); + + handle->messages = g_list_prepend(handle->messages, message); +} + +void +ui_chat_remove_message(UI_CHAT_Handle *handle, + UI_MESSAGE_Handle *message) +{ + GNUNET_assert((handle) && (message)); + + handle->messages = g_list_remove(handle->messages, message); + + gtk_container_remove( + GTK_CONTAINER(handle->messages_listbox), + gtk_widget_get_parent(GTK_WIDGET(message->message_box)) + ); +} + +void +ui_chat_add_file_load(UI_CHAT_Handle *handle, + UI_FILE_LOAD_ENTRY_Handle *file_load) +{ + GNUNET_assert((handle) && (file_load)); + + gtk_container_add( + GTK_CONTAINER(handle->chat_load_listbox), + file_load->entry_box + ); + + handle->loads = g_list_append(handle->loads, file_load); + + gtk_widget_show(GTK_WIDGET(handle->chat_load_button)); + + file_load->chat = handle; +} + +void +ui_chat_remove_file_load(UI_CHAT_Handle *handle, + UI_FILE_LOAD_ENTRY_Handle *file_load) +{ + GNUNET_assert((handle) && (file_load) && (handle == file_load->chat)); + + handle->loads = g_list_remove(handle->loads, file_load); + + gtk_container_remove( + GTK_CONTAINER(handle->chat_load_listbox), + gtk_widget_get_parent(GTK_WIDGET(file_load->entry_box)) + ); + + if (handle->loads) + return; + + if (gtk_widget_is_visible(GTK_WIDGET(handle->chat_load_popover))) + gtk_popover_popdown(handle->chat_load_popover); + + gtk_widget_hide(GTK_WIDGET(handle->chat_load_button)); + + file_load->chat = NULL; +} diff --git a/src/ui/chat.h b/src/ui/chat.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2021 GNUnet e.V. + Copyright (C) 2021--2022 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 @@ -32,13 +32,17 @@ #include <gnunet/gnunet_chat_lib.h> typedef struct MESSENGER_Application MESSENGER_Application; +typedef struct UI_MESSAGE_Handle UI_MESSAGE_Handle; typedef struct UI_PICKER_Handle UI_PICKER_Handle; +typedef struct UI_FILE_LOAD_ENTRY_Handle UI_FILE_LOAD_ENTRY_Handle; typedef struct UI_CHAT_Handle { GList *messages; gdouble edge_value; + GList *loads; + GtkBuilder *builder; GtkWidget *chat_box; @@ -48,8 +52,12 @@ typedef struct UI_CHAT_Handle GtkLabel *chat_title; GtkLabel *chat_subtitle; - GtkButton *chat_details_button; + GtkButton *chat_load_button; + GtkPopover *chat_load_popover; + GtkListBox *chat_load_listbox; + + GtkButton *chat_details_button; GtkLabel *chat_details_label; GtkButton *hide_chat_details_button; GtkBox *chat_details_contacts_box; @@ -81,4 +89,20 @@ ui_chat_update(UI_CHAT_Handle *handle, void ui_chat_delete(UI_CHAT_Handle *handle); +void +ui_chat_add_message(UI_CHAT_Handle *handle, + UI_MESSAGE_Handle *message); + +void +ui_chat_remove_message(UI_CHAT_Handle *handle, + UI_MESSAGE_Handle *message); + +void +ui_chat_add_file_load(UI_CHAT_Handle *handle, + UI_FILE_LOAD_ENTRY_Handle *file_load); + +void +ui_chat_remove_file_load(UI_CHAT_Handle *handle, + UI_FILE_LOAD_ENTRY_Handle *file_load); + #endif /* UI_CHAT_H_ */ diff --git a/src/ui/chat_entry.c b/src/ui/chat_entry.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2021 GNUnet e.V. + Copyright (C) 2021--2022 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 @@ -100,12 +100,12 @@ ui_chat_entry_update(UI_CHAT_ENTRY_Handle *handle, hdy_avatar_set_text(handle->entry_avatar, title); } - if (!handle->chat) + if (!(handle->chat)) return; ui_chat_update(handle->chat, app, context); - if (!handle->chat->messages) + if (!(handle->chat->messages)) return; UI_MESSAGE_Handle *message = ( diff --git a/src/ui/file_load_entry.c b/src/ui/file_load_entry.c @@ -0,0 +1,90 @@ +/* + This file is part of GNUnet. + Copyright (C) 2022 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 ui/file_load_entry.c + */ + +#include "file_load_entry.h" + +#include "../application.h" + +#include "chat.h" + +static void +handle_cancel_button_click(GNUNET_UNUSED GtkButton *button, + gpointer user_data) +{ + UI_FILE_LOAD_ENTRY_Handle* handle = (UI_FILE_LOAD_ENTRY_Handle*) user_data; + + if (handle->chat) + ui_chat_remove_file_load(handle->chat, handle); + + // TODO: cancel upload? +} + +UI_FILE_LOAD_ENTRY_Handle* +ui_file_load_entry_new(MESSENGER_Application *app) +{ + UI_FILE_LOAD_ENTRY_Handle* handle = g_malloc(sizeof(UI_FILE_LOAD_ENTRY_Handle)); + + handle->chat = NULL; + + handle->builder = gtk_builder_new_from_resource( + application_get_resource_path(app, "ui/file_load_entry.ui") + ); + + handle->entry_box = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "entry_box") + ); + + handle->file_image = GTK_IMAGE( + gtk_builder_get_object(handle->builder, "file_image") + ); + + handle->file_label = GTK_LABEL( + gtk_builder_get_object(handle->builder, "file_label") + ); + + handle->load_progress_bar = GTK_PROGRESS_BAR( + gtk_builder_get_object(handle->builder, "load_progress_bar") + ); + + handle->cancel_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "cancel_button") + ); + + g_signal_connect( + handle->cancel_button, + "clicked", + G_CALLBACK(handle_cancel_button_click), + handle + ); + + return handle; +} + +void +ui_file_load_entry_delete(UI_FILE_LOAD_ENTRY_Handle *handle) +{ + g_object_unref(handle->builder); + + g_free(handle); +} diff --git a/src/ui/file_load_entry.h b/src/ui/file_load_entry.h @@ -0,0 +1,56 @@ +/* + This file is part of GNUnet. + Copyright (C) 2022 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 ui/file_load_entry.h + */ + +#ifndef UI_FILE_LOAD_ENTRY_H_ +#define UI_FILE_LOAD_ENTRY_H_ + +#include <gnunet/gnunet_chat_lib.h> + +#include "messenger.h" + +typedef struct UI_CHAT_Handle UI_CHAT_Handle; + +typedef struct UI_FILE_LOAD_ENTRY_Handle +{ + UI_CHAT_Handle *chat; + + GtkBuilder *builder; + + GtkWidget *entry_box; + + GtkImage *file_image; + GtkLabel *file_label; + + GtkProgressBar *load_progress_bar; + + GtkButton *cancel_button; +} UI_FILE_LOAD_ENTRY_Handle; + +UI_FILE_LOAD_ENTRY_Handle* +ui_file_load_entry_new(MESSENGER_Application *app); + +void +ui_file_load_entry_delete(UI_FILE_LOAD_ENTRY_Handle *handle); + +#endif /* UI_FILE_LOAD_ENTRY_H_ */ diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c @@ -68,7 +68,7 @@ handle_id_drawing_area_draw(GtkWidget* drawing_area, GdkPixbuf *image = NULL; - if (!handle->image) + if (!(handle->image)) return FALSE; uint w, h; diff --git a/src/ui/send_file.c b/src/ui/send_file.c @@ -24,7 +24,12 @@ #include "send_file.h" +#include "chat.h" +#include "chat_entry.h" +#include "file_load_entry.h" + #include "../application.h" +#include "../file.h" static void handle_cancel_button_click(UNUSED GtkButton *button, @@ -36,11 +41,21 @@ handle_cancel_button_click(UNUSED GtkButton *button, static void handle_sending_upload_file(UNUSED void *cls, - UNUSED const struct GNUNET_CHAT_File *file, + const struct GNUNET_CHAT_File *file, uint64_t completed, uint64_t size) { - printf("UPLOAD: %lu / %lu\n", completed, size); + UI_FILE_LOAD_ENTRY_Handle *file_load = cls; + + gtk_progress_bar_set_fraction( + file_load->load_progress_bar, + 1.0 * completed / size + ); + + file_update_upload_info(file, completed, size); + + if ((completed >= size) && (file_load->chat)) + ui_chat_remove_file_load(file_load->chat, file_load); } static void @@ -67,17 +82,38 @@ handle_send_button_click(GtkButton *button, app->ui.bindings, text_view ); - if (context) - GNUNET_CHAT_context_send_file( + UI_CHAT_ENTRY_Handle *entry = GNUNET_CHAT_context_get_user_pointer(context); + UI_CHAT_Handle *handle = entry? entry->chat : NULL; + + struct GNUNET_CHAT_File *file = NULL; + + if ((context) && (handle)) + { + UI_FILE_LOAD_ENTRY_Handle *file_load = ui_file_load_entry_new(app); + + gtk_label_set_text(file_load->file_label, filename); + gtk_progress_bar_set_fraction(file_load->load_progress_bar, 0.0); + + ui_chat_add_file_load(handle, file_load); + + file = GNUNET_CHAT_context_send_file( context, filename, handle_sending_upload_file, - NULL + file_load ); + } g_free(filename); gtk_window_close(GTK_WINDOW(app->ui.send_file.dialog)); + + if (!file) + return; + + file_create_info(file); + + // TODO: create UI component? } static void @@ -117,7 +153,7 @@ handle_file_drawing_area_draw(GtkWidget* drawing_area, GdkPixbuf *image = handle->image; - if (!handle->animation) + if (!(handle->animation)) goto render_image; if (handle->animation_iter) @@ -219,7 +255,7 @@ handle_file_chooser_button_file_set(GtkFileChooserButton *file_chooser_button, { handle->animation = gdk_pixbuf_animation_new_from_file(filename, NULL); - if (!handle->animation) + if (!(handle->animation)) handle->image = gdk_pixbuf_new_from_file(filename, NULL); g_free(filename); @@ -313,7 +349,7 @@ void ui_send_file_dialog_update(UI_SEND_FILE_Handle *handle, const gchar *filename) { - if (!handle->file_chooser_button) + if (!(handle->file_chooser_button)) return; gtk_file_chooser_set_filename(