messenger-gtk

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

accounts.c (6289B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2022--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/accounts.c
     23  */
     24 
     25 #include "accounts.h"
     26 
     27 #include "account_entry.h"
     28 
     29 #include "../account.h"
     30 #include "../application.h"
     31 #include "../ui.h"
     32 
     33 static void
     34 handle_close_button_click(UNUSED GtkButton *button,
     35                           gpointer user_data)
     36 {
     37   g_assert(user_data);
     38   
     39   GtkDialog *dialog = GTK_DIALOG(user_data);
     40   gtk_window_close(GTK_WINDOW(dialog));
     41 }
     42 
     43 static gboolean
     44 _open_new_account_dialog(gpointer user_data)
     45 {
     46   g_assert(user_data);
     47 
     48   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
     49 
     50   ui_new_account_dialog_init(app, &(app->ui.new_account));
     51 
     52   gtk_widget_show(GTK_WIDGET(app->ui.new_account.dialog));
     53   return FALSE;
     54 }
     55 
     56 static void
     57 handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
     58                                       GtkListBoxRow* row,
     59                                       gpointer user_data)
     60 {
     61   g_assert((row) && (user_data));
     62 
     63   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
     64 
     65   // Drop activations of rows which do not contain accounts
     66   if (!gtk_list_box_row_get_selectable(row))
     67   {
     68     app->ui.accounts.show_queued = util_idle_add(
     69 	    G_SOURCE_FUNC(_open_new_account_dialog), app
     70     );
     71 
     72     goto close_dialog;
     73   }
     74 
     75   struct GNUNET_CHAT_Account *account = (struct GNUNET_CHAT_Account*) (
     76     g_object_get_qdata(G_OBJECT(row), app->quarks.data)
     77   );
     78 
     79   if (!account)
     80     goto close_dialog;
     81 
     82   app->ui.state = MESSENGER_STATE_MAIN_WINDOW;
     83   
     84   application_chat_lock(app);
     85   GNUNET_CHAT_connect(app->chat.messenger.handle, account);
     86   application_chat_unlock(app);
     87 
     88   gtk_list_box_unselect_all(app->ui.messenger.accounts_listbox);
     89   gtk_widget_set_sensitive(GTK_WIDGET(app->ui.accounts.dialog), FALSE);
     90 
     91 close_dialog:
     92   gtk_window_close(GTK_WINDOW(app->ui.accounts.dialog));
     93 }
     94 
     95 static void
     96 handle_dialog_destroy(UNUSED GtkWidget *window,
     97                       gpointer user_data)
     98 {
     99   g_assert(user_data);
    100 
    101   MESSENGER_Application *app = (MESSENGER_Application*) user_data;
    102 
    103   ui_accounts_dialog_cleanup(&(app->ui.accounts), app);
    104 
    105   if ((app->ui.accounts.show_queued) ||
    106       (MESSENGER_STATE_MAIN_WINDOW == app->ui.state))
    107     return;
    108 
    109   gtk_widget_destroy(GTK_WIDGET(app->ui.messenger.main_window));
    110 }
    111 
    112 static int
    113 _iterate_accounts(void *cls,
    114                   UNUSED struct GNUNET_CHAT_Handle *handle,
    115                   struct GNUNET_CHAT_Account *account)
    116 {
    117   g_assert((cls) && (account));
    118 
    119   MESSENGER_Application *app = (MESSENGER_Application*) cls;
    120 
    121   UI_ACCOUNT_ENTRY_Handle *entry = ui_account_entry_new(app);
    122 
    123   ui_account_entry_set_account(entry, account);
    124 
    125   gtk_list_box_prepend(app->ui.accounts.accounts_listbox, entry->entry_box);
    126 
    127   GtkListBoxRow *row = GTK_LIST_BOX_ROW(
    128     gtk_widget_get_parent(entry->entry_box)
    129   );
    130 
    131   g_object_set_qdata(G_OBJECT(row), app->quarks.data, account);
    132 
    133   g_object_set_qdata(
    134     G_OBJECT(row),
    135     app->quarks.ui,
    136     entry
    137   );
    138 
    139   return GNUNET_YES;
    140 }
    141 
    142 void
    143 ui_accounts_dialog_init(MESSENGER_Application *app,
    144                         UI_ACCOUNTS_Handle *handle)
    145 {
    146   g_assert((app) && (handle));
    147 
    148   handle->show_queued = 0;
    149 
    150   handle->builder = ui_builder_from_resource(
    151     application_get_resource_path(app, "ui/accounts.ui")
    152   );
    153 
    154   handle->dialog = GTK_DIALOG(
    155     gtk_builder_get_object(handle->builder, "accounts_dialog")
    156   );
    157 
    158   gtk_window_set_transient_for(
    159     GTK_WINDOW(handle->dialog),
    160     GTK_WINDOW(app->ui.messenger.main_window)
    161   );
    162 
    163   handle->accounts_listbox = GTK_LIST_BOX(
    164     gtk_builder_get_object(handle->builder, "accounts_listbox")
    165   );
    166 
    167   g_signal_connect(
    168     handle->accounts_listbox,
    169     "row-activated",
    170     G_CALLBACK(handle_accounts_listbox_row_activated),
    171     app
    172   );
    173 
    174   handle->close_button = GTK_BUTTON(
    175     gtk_builder_get_object(handle->builder, "close_button")
    176   );
    177 
    178   g_signal_connect(
    179     handle->close_button,
    180     "clicked",
    181     G_CALLBACK(handle_close_button_click),
    182     handle->dialog
    183   );
    184 
    185   g_signal_connect(
    186     handle->dialog,
    187     "destroy",
    188     G_CALLBACK(handle_dialog_destroy),
    189     app
    190   );
    191 }
    192 
    193 static void
    194 _ui_accounts_cleanup_listbox(UI_ACCOUNTS_Handle *handle,
    195                              MESSENGER_Application *app)
    196 {
    197   g_assert(handle);
    198 
    199   GList *list = gtk_container_get_children(
    200     GTK_CONTAINER(handle->accounts_listbox)
    201   );
    202 
    203   GList *item = list;
    204   while (item)
    205   {
    206     GtkListBoxRow *row = GTK_LIST_BOX_ROW(item->data);
    207 
    208     if ((!row) || (!gtk_list_box_row_get_selectable(row)))
    209       goto skip_row;
    210 
    211     UI_ACCOUNT_ENTRY_Handle *entry = g_object_get_qdata(
    212       G_OBJECT(row),
    213       app->quarks.ui
    214     );
    215 
    216     gtk_container_remove(
    217       GTK_CONTAINER(handle->accounts_listbox),
    218       GTK_WIDGET(row)
    219     );
    220 
    221     ui_account_entry_delete(entry);
    222 
    223   skip_row:
    224     item = item->next;
    225   }
    226 
    227   if (list)
    228     g_list_free(list);
    229 }
    230 
    231 void
    232 ui_accounts_dialog_refresh(MESSENGER_Application *app,
    233                            UI_ACCOUNTS_Handle *handle)
    234 {
    235   g_assert((app) && (handle));
    236 
    237   if (!(handle->accounts_listbox))
    238     return;
    239 
    240   _ui_accounts_cleanup_listbox(handle, app);
    241 
    242   application_chat_lock(app);
    243 
    244   GNUNET_CHAT_iterate_accounts(
    245     app->chat.messenger.handle,
    246     _iterate_accounts,
    247     app
    248   );
    249 
    250   application_chat_unlock(app);
    251 }
    252 
    253 void
    254 ui_accounts_dialog_cleanup(UI_ACCOUNTS_Handle *handle,
    255                            MESSENGER_Application *app)
    256 {
    257   g_assert((handle) && (app));
    258 
    259   _ui_accounts_cleanup_listbox(handle, app);
    260 
    261   g_object_unref(handle->builder);
    262 
    263   guint show = handle->show_queued;
    264   memset(handle, 0, sizeof(*handle));
    265   handle->show_queued = show;
    266 }