messenger-gtk

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

invite_contact.c (6278B)


      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/invite_contact.c
     23  */
     24 
     25 #include "invite_contact.h"
     26 
     27 #include "contact_entry.h"
     28 #include "../application.h"
     29 #include "../ui.h"
     30 
     31 static void
     32 handle_close_button_click(UNUSED GtkButton *button,
     33                           gpointer user_data)
     34 {
     35   g_assert(user_data);
     36 
     37   GtkDialog *dialog = GTK_DIALOG(user_data);
     38   gtk_window_close(GTK_WINDOW(dialog));
     39 }
     40 
     41 static void
     42 handle_contacts_listbox_row_activated(GtkListBox* listbox,
     43                                       GtkListBoxRow* row,
     44                                       gpointer user_data)
     45 {
     46   g_assert((listbox) && (row) && (user_data));
     47 
     48   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
     49 
     50   GtkTextView *text_view = GTK_TEXT_VIEW(
     51     g_object_get_qdata(G_OBJECT(listbox), app->quarks.widget)
     52   );
     53 
     54   struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) (
     55     g_object_get_qdata(G_OBJECT(row), app->quarks.data)
     56   );
     57 
     58   application_chat_lock(app);
     59 
     60   if ((!contact) || (!GNUNET_CHAT_contact_get_key(contact)) ||
     61       (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact)) ||
     62       (!text_view))
     63     goto close_dialog;
     64 
     65   struct GNUNET_CHAT_Context *context = (struct GNUNET_CHAT_Context*) (
     66     g_object_get_qdata(G_OBJECT(text_view), app->quarks.data)
     67   );
     68 
     69   if (!context)
     70     goto close_dialog;
     71 
     72   struct GNUNET_CHAT_Group *group = GNUNET_CHAT_context_get_group(
     73     context
     74   );
     75 
     76   if (group)
     77     GNUNET_CHAT_group_invite_contact(group, contact);
     78 
     79 close_dialog:
     80   application_chat_unlock(app);
     81 
     82   gtk_window_close(GTK_WINDOW(app->ui.invite_contact.dialog));
     83 }
     84 
     85 static gboolean
     86 handle_contacts_listbox_filter_func(GtkListBoxRow *row,
     87                                     gpointer user_data)
     88 {
     89   g_assert((row) && (user_data));
     90 
     91   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
     92 
     93   if (!gtk_list_box_row_get_selectable(row))
     94     return TRUE;
     95 
     96   const gchar *filter = gtk_entry_get_text(
     97     GTK_ENTRY(app->ui.invite_contact.contact_search_entry)
     98   );
     99 
    100   if (!filter)
    101     return TRUE;
    102 
    103   UI_CONTACT_ENTRY_Handle *entry = (UI_CONTACT_ENTRY_Handle*) (
    104     g_object_get_qdata(G_OBJECT(row), app->quarks.ui)
    105   );
    106 
    107   if (!entry)
    108     return FALSE;
    109 
    110   const gchar *name = gtk_label_get_text(entry->title_label);
    111 
    112   if (!name)
    113     return FALSE;
    114 
    115   return g_str_match_string(filter, name, TRUE);
    116 }
    117 
    118 static void
    119 handle_contact_search_entry_search_changed(UNUSED GtkSearchEntry* search_entry,
    120                                            gpointer user_data)
    121 {
    122   g_assert(user_data);
    123 
    124   GtkListBox *listbox = GTK_LIST_BOX(user_data);
    125 
    126   gtk_list_box_invalidate_filter(listbox);
    127 }
    128 
    129 static void
    130 handle_dialog_destroy(UNUSED GtkWidget *window,
    131                       gpointer user_data)
    132 {
    133   g_assert(user_data);
    134 
    135   ui_contacts_dialog_cleanup((UI_CONTACTS_Handle*) user_data);
    136 }
    137 
    138 static int
    139 _iterate_contacts(void *cls,
    140                   UNUSED struct GNUNET_CHAT_Handle *handle,
    141                   struct GNUNET_CHAT_Contact *contact)
    142 {
    143   g_assert((cls) && (contact));
    144 
    145   if (GNUNET_YES == GNUNET_CHAT_contact_is_owned(contact))
    146     return GNUNET_YES;
    147 
    148   MESSENGER_Application *app = (MESSENGER_Application*) cls;
    149 
    150   UI_CONTACT_ENTRY_Handle *entry = ui_contact_entry_new(app);
    151   ui_contact_entry_set_contact(entry, contact);
    152 
    153   gtk_list_box_prepend(
    154     app->ui.invite_contact.contacts_listbox,
    155     entry->entry_box
    156   );
    157 
    158   GtkListBoxRow *row = GTK_LIST_BOX_ROW(
    159     gtk_widget_get_parent(entry->entry_box)
    160   );
    161 
    162   g_object_set_qdata(G_OBJECT(row), app->quarks.data, contact);
    163 
    164   g_object_set_qdata_full(
    165     G_OBJECT(row),
    166     app->quarks.ui,
    167     entry,
    168     (GDestroyNotify) ui_contact_entry_delete
    169   );
    170 
    171   return GNUNET_YES;
    172 }
    173 
    174 void
    175 ui_invite_contact_dialog_init(MESSENGER_Application *app,
    176                               UI_INVITE_CONTACT_Handle *handle)
    177 {
    178   g_assert((app) && (handle));
    179 
    180   handle->builder = ui_builder_from_resource(
    181     application_get_resource_path(app, "ui/invite_contact.ui")
    182   );
    183 
    184   handle->dialog = GTK_DIALOG(
    185     gtk_builder_get_object(handle->builder, "invite_contact_dialog")
    186   );
    187 
    188   gtk_window_set_transient_for(
    189     GTK_WINDOW(handle->dialog),
    190     GTK_WINDOW(app->ui.messenger.main_window)
    191   );
    192 
    193   handle->contact_search_entry = GTK_SEARCH_ENTRY(
    194     gtk_builder_get_object(handle->builder, "contact_search_entry")
    195   );
    196 
    197   handle->contacts_listbox = GTK_LIST_BOX(
    198     gtk_builder_get_object(handle->builder, "contacts_listbox")
    199   );
    200 
    201   gtk_list_box_set_filter_func(
    202     handle->contacts_listbox,
    203     handle_contacts_listbox_filter_func,
    204     app,
    205     NULL
    206   );
    207 
    208   g_signal_connect(
    209     handle->contact_search_entry,
    210     "search-changed",
    211     G_CALLBACK(handle_contact_search_entry_search_changed),
    212     handle->contacts_listbox
    213   );
    214 
    215   g_signal_connect(
    216     handle->contacts_listbox,
    217     "row-activated",
    218     G_CALLBACK(handle_contacts_listbox_row_activated),
    219     app
    220   );
    221 
    222   handle->close_button = GTK_BUTTON(
    223     gtk_builder_get_object(handle->builder, "close_button")
    224   );
    225 
    226   g_signal_connect(
    227     handle->close_button,
    228     "clicked",
    229     G_CALLBACK(handle_close_button_click),
    230     handle->dialog
    231   );
    232 
    233   g_signal_connect(
    234     handle->dialog,
    235     "destroy",
    236     G_CALLBACK(handle_dialog_destroy),
    237     handle
    238   );
    239 
    240   GNUNET_CHAT_iterate_contacts(
    241     app->chat.messenger.handle,
    242     _iterate_contacts,
    243     app
    244   );
    245 
    246   gtk_list_box_invalidate_filter(handle->contacts_listbox);
    247 }
    248 
    249 void
    250 ui_invite_contact_dialog_cleanup(UI_INVITE_CONTACT_Handle *handle)
    251 {
    252   g_assert(handle);
    253 
    254   g_object_unref(handle->builder);
    255 
    256   memset(handle, 0, sizeof(*handle));
    257 }