messenger-gtk

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

new_group.c (8344B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2021--2024 GNUnet e.V.
      4 
      5    GNUnet is free software: you can redistribute it and/or modify it
      6    under the terms of the GNU Affero General Public License as published
      7    by the Free Software Foundation, either version 3 of the License,
      8    or (at your option) any later version.
      9 
     10    GNUnet is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    Affero General Public License for more details.
     14 
     15    You should have received a copy of the GNU Affero General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18    SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 /*
     21  * @author Tobias Frisch
     22  * @file ui/new_group.c
     23  */
     24 
     25 #include "new_platform.h"
     26 
     27 #include "contact_entry.h"
     28 #include "../application.h"
     29 #include "../ui.h"
     30 
     31 static void
     32 _open_new_group(GtkEntry *entry,
     33                 GtkListBox *listbox,
     34                 MESSENGER_Application *app)
     35 {
     36   g_assert((entry) && (listbox) && (app));
     37 
     38   const gchar *name = gtk_entry_get_text(entry);
     39 
     40   application_chat_lock(app);
     41 
     42   struct GNUNET_CHAT_Group *group = GNUNET_CHAT_group_create(
     43       app->chat.messenger.handle,
     44       NULL
     45   );
     46 
     47   if ((name) && (strlen(name) > 0))
     48     GNUNET_CHAT_group_set_name(group, name);
     49 
     50   GList *selected = gtk_list_box_get_selected_rows(listbox);
     51 
     52   GList *item = selected;
     53   while (item)
     54   {
     55     if (item->data)
     56     {
     57       GtkListBoxRow *row = GTK_LIST_BOX_ROW(item->data);
     58 
     59       struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) (
     60 	      g_object_get_qdata(G_OBJECT(row), app->quarks.data)
     61       );
     62 
     63       GNUNET_CHAT_group_invite_contact(group, contact);
     64     }
     65 
     66     item = item->next;
     67   }
     68 
     69   application_chat_unlock(app);
     70 
     71   if (selected)
     72     g_list_free(selected);
     73 }
     74 
     75 static void
     76 handle_group_entry_changed(GtkEditable *editable,
     77                            gpointer user_data)
     78 {
     79   g_assert((editable) && (user_data));
     80 
     81   HdyAvatar *avatar = HDY_AVATAR(user_data);
     82   GtkEntry *entry = GTK_ENTRY(editable);
     83 
     84   const gchar *text = gtk_entry_get_text(entry);
     85 
     86   hdy_avatar_set_text(avatar, text);
     87 }
     88 
     89 static void
     90 _go_page_details(UI_NEW_GROUP_Handle *handle)
     91 {
     92   g_assert(handle);
     93 
     94   gtk_stack_set_visible_child(handle->stack, handle->details_box);
     95 
     96   gtk_widget_hide(GTK_WIDGET(handle->previous_button));
     97   gtk_widget_hide(GTK_WIDGET(handle->confirm_button));
     98 
     99   gtk_widget_show(GTK_WIDGET(handle->cancel_button));
    100   gtk_widget_show(GTK_WIDGET(handle->next_button));
    101 }
    102 
    103 static void
    104 _go_page_contacts(UI_NEW_GROUP_Handle *handle)
    105 {
    106   g_assert(handle);
    107 
    108   gtk_stack_set_visible_child(handle->stack, handle->contacts_box);
    109 
    110   gtk_widget_hide(GTK_WIDGET(handle->cancel_button));
    111   gtk_widget_hide(GTK_WIDGET(handle->next_button));
    112 
    113   gtk_widget_show(GTK_WIDGET(handle->previous_button));
    114   gtk_widget_show(GTK_WIDGET(handle->confirm_button));
    115 }
    116 
    117 static void
    118 handle_group_entry_activate(UNUSED GtkEntry *entry,
    119                             gpointer user_data)
    120 {
    121   g_assert(user_data);
    122 
    123   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
    124 
    125   _go_page_contacts(&(app->ui.new_group));
    126 }
    127 
    128 static void
    129 handle_cancel_button_click(UNUSED GtkButton *button,
    130                            gpointer user_data)
    131 {
    132   g_assert(user_data);
    133 
    134   GtkDialog *dialog = GTK_DIALOG(user_data);
    135   gtk_window_close(GTK_WINDOW(dialog));
    136 }
    137 
    138 static void
    139 handle_previous_button_click(UNUSED GtkButton *button,
    140                              gpointer user_data)
    141 {
    142   g_assert(user_data);
    143 
    144   _go_page_details((UI_NEW_GROUP_Handle*) user_data);
    145 }
    146 
    147 static void
    148 handle_next_button_click(UNUSED GtkButton *button,
    149                          gpointer user_data)
    150 {
    151   g_assert(user_data);
    152 
    153   _go_page_contacts((UI_NEW_GROUP_Handle*) user_data);
    154 }
    155 
    156 static void
    157 handle_confirm_button_click(UNUSED GtkButton *button,
    158                             gpointer user_data)
    159 {
    160   g_assert(user_data);
    161 
    162   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
    163 
    164   _open_new_group(
    165       app->ui.new_group.group_entry,
    166       app->ui.new_group.contacts_listbox,
    167       app
    168   );
    169 
    170   gtk_window_close(GTK_WINDOW(app->ui.new_group.dialog));
    171 }
    172 
    173 static void
    174 handle_dialog_destroy(UNUSED GtkWidget *window,
    175                       gpointer user_data)
    176 {
    177   g_assert(user_data);
    178 
    179   ui_new_group_dialog_cleanup((UI_NEW_GROUP_Handle*) user_data);
    180 }
    181 
    182 static int
    183 _iterate_contacts(void *cls,
    184                   UNUSED struct GNUNET_CHAT_Handle *handle,
    185                   struct GNUNET_CHAT_Contact *contact)
    186 {
    187   g_assert((cls) && (contact));
    188 
    189   if (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact))
    190     return GNUNET_YES;
    191 
    192   MESSENGER_Application *app = (MESSENGER_Application*) cls;
    193 
    194   UI_CONTACT_ENTRY_Handle *entry = ui_contact_entry_new(app);
    195   ui_contact_entry_set_contact(entry, contact);
    196 
    197   gtk_list_box_prepend(
    198     app->ui.new_group.contacts_listbox,
    199     entry->entry_box
    200   );
    201 
    202   GtkWidget *row = gtk_widget_get_parent(entry->entry_box);
    203   g_object_set_qdata(G_OBJECT(row), app->quarks.data, contact);
    204 
    205   app->ui.new_group.contact_entries = g_list_append(
    206     app->ui.new_group.contact_entries,
    207     entry
    208   );
    209 
    210   return GNUNET_YES;
    211 }
    212 
    213 void
    214 ui_new_group_dialog_init(MESSENGER_Application *app,
    215                          UI_NEW_GROUP_Handle *handle)
    216 {
    217   g_assert((app) && (handle));
    218 
    219   handle->contact_entries = NULL;
    220 
    221   handle->builder = ui_builder_from_resource(
    222     application_get_resource_path(app, "ui/new_group.ui")
    223   );
    224 
    225   handle->dialog = GTK_DIALOG(
    226     gtk_builder_get_object(handle->builder, "new_group_dialog")
    227   );
    228 
    229   gtk_window_set_transient_for(
    230     GTK_WINDOW(handle->dialog),
    231     GTK_WINDOW(app->ui.messenger.main_window)
    232   );
    233 
    234   handle->stack = GTK_STACK(
    235     gtk_builder_get_object(handle->builder, "new_group_stack")
    236   );
    237 
    238   handle->details_box = GTK_WIDGET(
    239     gtk_builder_get_object(handle->builder, "details_box")
    240   );
    241 
    242   handle->contacts_box = GTK_WIDGET(
    243     gtk_builder_get_object(handle->builder, "contacts_box")
    244   );
    245 
    246   handle->group_avatar = HDY_AVATAR(
    247     gtk_builder_get_object(handle->builder, "group_avatar")
    248   );
    249 
    250   handle->group_avatar_file = GTK_FILE_CHOOSER_BUTTON(
    251     gtk_builder_get_object(handle->builder, "group_avatar_file")
    252   );
    253 
    254   handle->group_entry = GTK_ENTRY(
    255     gtk_builder_get_object(handle->builder, "group_entry")
    256   );
    257 
    258   g_signal_connect(
    259     handle->group_entry,
    260     "changed",
    261     G_CALLBACK(handle_group_entry_changed),
    262     handle->group_avatar
    263   );
    264 
    265   g_signal_connect(
    266     handle->group_entry,
    267     "activate",
    268     G_CALLBACK(handle_group_entry_activate),
    269     app
    270   );
    271 
    272   handle->contact_search_entry = GTK_SEARCH_ENTRY(
    273     gtk_builder_get_object(handle->builder, "contact_search_entry")
    274   );
    275 
    276   handle->contacts_listbox = GTK_LIST_BOX(
    277     gtk_builder_get_object(handle->builder, "contacts_listbox")
    278   );
    279 
    280   handle->cancel_button = GTK_BUTTON(
    281     gtk_builder_get_object(handle->builder, "cancel_button")
    282   );
    283 
    284   g_signal_connect(
    285     handle->cancel_button,
    286     "clicked",
    287     G_CALLBACK(handle_cancel_button_click),
    288     handle->dialog
    289   );
    290 
    291   handle->previous_button = GTK_BUTTON(
    292     gtk_builder_get_object(handle->builder, "previous_button")
    293   );
    294 
    295   g_signal_connect(
    296     handle->previous_button,
    297     "clicked",
    298     G_CALLBACK(handle_previous_button_click),
    299     handle
    300   );
    301 
    302   handle->next_button = GTK_BUTTON(
    303     gtk_builder_get_object(handle->builder, "next_button")
    304   );
    305 
    306   g_signal_connect(
    307     handle->next_button,
    308     "clicked",
    309     G_CALLBACK(handle_next_button_click),
    310     handle
    311   );
    312 
    313   handle->confirm_button = GTK_BUTTON(
    314     gtk_builder_get_object(handle->builder, "confirm_button")
    315   );
    316 
    317   g_signal_connect(
    318     handle->confirm_button,
    319     "clicked",
    320     G_CALLBACK(handle_confirm_button_click),
    321     app
    322   );
    323 
    324   g_signal_connect(
    325     handle->dialog,
    326     "destroy",
    327     G_CALLBACK(handle_dialog_destroy),
    328     handle
    329   );
    330 
    331   GNUNET_CHAT_iterate_contacts(
    332     app->chat.messenger.handle,
    333     _iterate_contacts,
    334     app
    335   );
    336 }
    337 
    338 void
    339 ui_new_group_dialog_cleanup(UI_NEW_GROUP_Handle *handle)
    340 {
    341   g_assert(handle);
    342 
    343   g_object_unref(handle->builder);
    344 
    345   for (GList *list = handle->contact_entries; list; list = list->next)
    346     ui_contact_entry_delete((UI_CONTACT_ENTRY_Handle*) list->data);
    347 
    348   if (handle->contact_entries)
    349     g_list_free(handle->contact_entries);
    350 
    351   memset(handle, 0, sizeof(*handle));
    352 }