messenger-gtk

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

commit 35f830ec5f9ea6ff42d2c98e2a0efb40de3dd1f2
parent d71038500f255d3e5b491eea0677d179866044d2
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Sun, 19 Dec 2021 15:07:25 +0100

Added dialog to invite contact to group

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

Diffstat:
MMakefile | 1+
Aresources/ui/invite_contact.ui | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/application.h | 2++
Msrc/ui/chat.c | 25+++++++++++++++++++++++--
Asrc/ui/invite_contact.c | 206+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ui/invite_contact.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 385 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,6 +12,7 @@ SOURCES = messenger_gtk.c\ ui/chat_entry.c\ ui/contact_entry.c\ ui/contacts.c\ + ui/invite_contact.c\ ui/message.c\ ui/messenger.c\ ui/new_contact.c\ diff --git a/resources/ui/invite_contact.ui b/resources/ui/invite_contact.ui @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 + +Copyright (C) 2021 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="GtkDialog" id="invite_contact_dialog"> + <property name="can-focus">False</property> + <property name="modal">True</property> + <property name="window-position">center-on-parent</property> + <property name="type-hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox"> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox"> + <property name="can-focus">False</property> + <property name="layout-style">end</property> + <child> + <object class="GtkButton" id="close_button"> + <property name="label" translatable="yes">Close</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</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">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkSearchEntry" id="contact_search_entry"> + <property name="width-request">250</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="primary-icon-name">edit-find-symbolic</property> + <property name="primary-icon-activatable">False</property> + <property name="primary-icon-sensitive">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="height-request">200</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkListBox" id="contacts_listbox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/src/application.h b/src/application.h @@ -31,6 +31,7 @@ #include "chat/messenger.h" #include "ui/contacts.h" +#include "ui/invite_contact.h" #include "ui/messenger.h" #include "ui/new_contact.h" #include "ui/new_group.h" @@ -73,6 +74,7 @@ typedef struct MESSENGER_Application UI_MESSENGER_Handle messenger; + UI_INVITE_CONTACT_Handle invite_contact; UI_SEND_FILE_Handle send_file; UI_NEW_CONTACT_Handle new_contact; diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -47,15 +47,30 @@ handle_flap_via_button_click(UNUSED GtkButton *button, } static void -handle_chat_contacts_listbox_row_activated(UNUSED GtkListBox *listbox, +handle_chat_contacts_listbox_row_activated(GtkListBox *listbox, GtkListBoxRow *row, gpointer user_data) { MESSENGER_Application *app = (MESSENGER_Application*) user_data; + GtkTextView *text_view = GTK_TEXT_VIEW( + g_hash_table_lookup(app->ui.bindings, listbox) + ); + + if (!text_view) + return; + if (!gtk_list_box_row_get_selectable(row)) { - //g_idle_add(G_SOURCE_FUNC(_open_new_contact_dialog), app); + ui_invite_contact_dialog_init(app, &(app->ui.invite_contact)); + + g_hash_table_insert( + app->ui.bindings, + app->ui.invite_contact.contacts_listbox, + text_view + ); + + gtk_widget_show(GTK_WIDGET(app->ui.invite_contact.dialog)); return; } @@ -375,6 +390,12 @@ ui_chat_new(MESSENGER_Application *app) g_hash_table_insert( app->ui.bindings, + handle->chat_contacts_listbox, + handle->send_text_view + ); + + g_hash_table_insert( + app->ui.bindings, handle->attach_file_button, handle->send_text_view ); diff --git a/src/ui/invite_contact.c b/src/ui/invite_contact.c @@ -0,0 +1,206 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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/invite_contact.c + */ + +#include "invite_contact.h" + +#include "chat_entry.h" +#include "contact_entry.h" +#include "../application.h" + +static void +handle_close_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + GtkDialog *dialog = GTK_DIALOG(user_data); + gtk_window_close(GTK_WINDOW(dialog)); +} + +static void +handle_contacts_listbox_row_activated(GtkListBox* listbox, + GtkListBoxRow* row, + gpointer user_data) +{ + MESSENGER_Application *app = (MESSENGER_Application*) user_data; + + GtkTextView *text_view = GTK_TEXT_VIEW( + g_hash_table_lookup(app->ui.bindings, listbox) + ); + + struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) ( + g_hash_table_lookup(app->ui.bindings, row) + ); + + if ((!contact) || (!GNUNET_CHAT_contact_get_key(contact)) || + (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact)) || + (!text_view)) + goto close_dialog; + + struct GNUNET_CHAT_Context *context = g_hash_table_lookup( + app->ui.bindings, text_view + ); + + if (!context) + goto close_dialog; + + const struct GNUNET_CHAT_Group *group = GNUNET_CHAT_context_get_group( + context + ); + + if (group) + GNUNET_CHAT_group_invite_contact(group, contact); + +close_dialog: + gtk_window_close(GTK_WINDOW(app->ui.invite_contact.dialog)); +} + +static void +handle_dialog_destroy(UNUSED GtkWidget *window, + gpointer user_data) +{ + ui_contacts_dialog_cleanup((UI_CONTACTS_Handle*) user_data); +} + +static int +_iterate_contacts(void *cls, + UNUSED struct GNUNET_CHAT_Handle *handle, + struct GNUNET_CHAT_Contact *contact) +{ + if (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact)) + return GNUNET_YES; + + MESSENGER_Application *app = (MESSENGER_Application*) cls; + + const char *title; + title = GNUNET_CHAT_contact_get_name(contact); + + const char *key = GNUNET_CHAT_contact_get_key(contact); + + UI_CONTACT_ENTRY_Handle *entry = ui_contact_entry_new(); + gtk_list_box_prepend( + app->ui.invite_contact.contacts_listbox, + entry->entry_box + ); + + if (title) + { + gtk_label_set_text(entry->title_label, title); + hdy_avatar_set_text(entry->entry_avatar, title); + } + + if (key) + gtk_label_set_text(entry->subtitle_label, key); + + GtkListBoxRow *row = GTK_LIST_BOX_ROW( + gtk_widget_get_parent(entry->entry_box) + ); + + g_hash_table_insert(app->ui.bindings, row, contact); + + app->ui.invite_contact.contact_entries = g_list_append( + app->ui.invite_contact.contact_entries, + entry + ); + + return GNUNET_YES; +} + +void +ui_invite_contact_dialog_init(MESSENGER_Application *app, + UI_INVITE_CONTACT_Handle *handle) +{ + handle->contact_entries = NULL; + + handle->builder = gtk_builder_new_from_file("resources/ui/invite_contact.ui"); + + handle->dialog = GTK_DIALOG( + gtk_builder_get_object(handle->builder, "invite_contact_dialog") + ); + + gtk_window_set_title( + GTK_WINDOW(handle->dialog), + _("Invite Contact") + ); + + gtk_window_set_transient_for( + GTK_WINDOW(handle->dialog), + GTK_WINDOW(app->ui.messenger.main_window) + ); + + handle->contact_search_entry = GTK_SEARCH_ENTRY( + gtk_builder_get_object(handle->builder, "contact_search_entry") + ); + + handle->contacts_listbox = GTK_LIST_BOX( + gtk_builder_get_object(handle->builder, "contacts_listbox") + ); + + g_signal_connect( + handle->contacts_listbox, + "row-activated", + G_CALLBACK(handle_contacts_listbox_row_activated), + app + ); + + handle->close_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "close_button") + ); + + g_signal_connect( + handle->close_button, + "clicked", + G_CALLBACK(handle_close_button_click), + handle->dialog + ); + + g_signal_connect( + handle->dialog, + "destroy", + G_CALLBACK(handle_dialog_destroy), + handle + ); + + GNUNET_CHAT_iterate_contacts( + app->chat.messenger.handle, + _iterate_contacts, + app + ); +} + +void +ui_invite_contact_dialog_cleanup(UI_INVITE_CONTACT_Handle *handle) +{ + g_object_unref(handle->builder); + + GList *list = handle->contact_entries; + + while (list) { + if (list->data) + ui_contact_entry_delete((UI_CONTACT_ENTRY_Handle*) list->data); + + list = list->next; + } + + if (handle->contact_entries) + g_list_free(handle->contact_entries); +} diff --git a/src/ui/invite_contact.h b/src/ui/invite_contact.h @@ -0,0 +1,51 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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/invite_contact.h + */ + +#ifndef UI_INVITE_CONTACT_H_ +#define UI_INVITE_CONTACT_H_ + +#include "messenger.h" + +typedef struct UI_INVITE_CONTACT_Handle +{ + GList *contact_entries; + + GtkBuilder *builder; + GtkDialog *dialog; + + GtkSearchEntry *contact_search_entry; + + GtkListBox *contacts_listbox; + + GtkButton *close_button; +} UI_INVITE_CONTACT_Handle; + +void +ui_invite_contact_dialog_init(MESSENGER_Application *app, + UI_INVITE_CONTACT_Handle *handle); + +void +ui_invite_contact_dialog_cleanup(UI_INVITE_CONTACT_Handle *handle); + +#endif /* UI_INVITE_CONTACT_H_ */