messenger-gtk

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

ui.c (5834B)


      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.c
     23  */
     24 
     25 #include "ui.h"
     26 
     27 #include <gnunet/gnunet_common.h>
     28 
     29 GtkBuilder*
     30 ui_builder_from_resource(const char *resource_path)
     31 {
     32   GtkBuilder *builder = gtk_builder_new();
     33 
     34   if (!builder)
     35     return NULL;
     36 
     37   gtk_builder_set_translation_domain(builder, MESSENGER_APPLICATION_DOMAIN);
     38 
     39   if (!gtk_builder_add_from_resource(builder, resource_path, NULL))
     40   {
     41     g_object_unref(builder);
     42     return NULL;
     43   }
     44 
     45   return builder;
     46 }
     47 
     48 void
     49 ui_label_set_text(GtkLabel *label, const char *text)
     50 {
     51   g_assert(label);
     52 
     53   if (!text)
     54   {
     55     gtk_label_set_text(label, "");
     56     return;
     57   }
     58 
     59   gchar *_text = g_locale_to_utf8(text, -1, NULL, NULL, NULL);
     60   gtk_label_set_text(label, _text);
     61   g_free(_text);
     62 }
     63 
     64 void
     65 ui_label_set_markup_text(GtkLabel *label,
     66                          const char *text)
     67 {
     68   g_assert(label);
     69 
     70   if (!text)
     71   {
     72     gtk_label_set_markup(label, "");
     73     return;
     74   }
     75 
     76   gchar *_text = g_locale_to_utf8(text, -1, NULL, NULL, NULL);
     77   gchar *_escaped = g_markup_escape_text(_text, -1);
     78 
     79   if (_escaped)
     80   {
     81     g_free(_text);
     82     _text = _escaped;
     83   }
     84 
     85   GError *error = NULL;
     86   GRegex *regex = g_regex_new(
     87     "https?://(www.)?[-a-z0-9@:%._\\+~#=/&?]+",
     88     G_REGEX_MULTILINE | G_REGEX_OPTIMIZE,
     89     G_REGEX_MATCH_DEFAULT,
     90     &error
     91   );
     92 
     93   if (error)
     94   {
     95     fprintf (stderr, "ERROR: %s (%d)\n", error->message, error->code);
     96     g_error_free(error);
     97     goto skip_regex;
     98   }
     99 
    100   if (!regex)
    101     goto skip_regex;
    102 
    103   gchar *_replaced = g_regex_replace(
    104     regex,
    105     _text,
    106     -1,
    107     0,
    108     "<a href=\"\\0\">\\0</a>",
    109     G_REGEX_MATCH_DEFAULT,
    110     &error
    111   );
    112 
    113   if (error)
    114   {
    115     fprintf (stderr, "%s\n", error->message);
    116     g_error_free(error);
    117   }
    118 
    119   if (_replaced)
    120   {
    121     g_free(_text);
    122     _text = _replaced;
    123   }
    124 
    125 skip_regex:
    126   if (regex)
    127     g_regex_unref(regex);
    128 
    129   gtk_label_set_markup(label, _text);
    130   g_free(_text);
    131 }
    132 
    133 void
    134 ui_label_set_size(GtkLabel *label,
    135                   uint64_t size)
    136 {
    137   g_assert(label);
    138 
    139   GString* string = g_string_new(NULL);
    140   
    141   if (size < 100)
    142     g_string_printf(string, "%lu B", size);
    143   else
    144   {
    145     char dim = 'K';
    146     size = (size + 50) / 100;
    147 
    148     while (size >= 1000)
    149     {
    150       size = (size + 500) / 1000;
    151       switch (dim)
    152       {
    153         case 'K':
    154           dim = 'M';
    155           break;
    156         case 'M':
    157           dim = 'G';
    158           break;
    159         case 'G':
    160           dim = 'T';
    161           break;
    162         case 'T':
    163           dim = 'P';
    164           break;
    165         default:
    166           break;
    167       }
    168     }
    169 
    170     g_string_printf(
    171       string,
    172       "%lu.%lu %cB",
    173       size / 10,
    174       size % 10,
    175       dim
    176     );
    177   }
    178 
    179   gtk_label_set_text(label, string->str);
    180   g_string_free(string, TRUE);
    181 }
    182 
    183 void
    184 ui_entry_set_text(GtkEntry *entry, const char *text)
    185 {
    186   g_assert(entry);
    187 
    188   if (!text)
    189   {
    190     gtk_entry_set_text(entry, "");
    191     return;
    192   }
    193 
    194   gchar *_text = g_locale_to_utf8(text, -1, NULL, NULL, NULL);
    195   gtk_entry_set_text(entry, _text);
    196   g_free(_text);
    197 }
    198 
    199 char*
    200 ui_entry_get_text(GtkEntry *entry)
    201 {
    202   g_assert(entry);
    203 
    204   const gchar *text = gtk_entry_get_text(entry);
    205 
    206   if (!text)
    207     return NULL;
    208 
    209   gchar *_text = g_locale_from_utf8(text, -1, NULL, NULL, NULL);
    210   char *result = GNUNET_strdup(_text);
    211   g_free(_text);
    212 
    213   return result;
    214 }
    215 
    216 void
    217 ui_avatar_set_text(HdyAvatar *avatar, const char *text)
    218 {
    219   g_assert(avatar);
    220 
    221   if (!text)
    222   {
    223     const gchar *state = hdy_avatar_get_text(avatar);
    224 
    225     if ((!state) || (!g_utf8_strlen(state, 1)))
    226       return;
    227 
    228     hdy_avatar_set_text(avatar, "");
    229     return;
    230   }
    231 
    232   gchar *_text = g_locale_to_utf8(text, -1, NULL, NULL, NULL);
    233   hdy_avatar_set_text(avatar, _text);
    234   g_free(_text);
    235 }
    236 
    237 void
    238 ui_avatar_set_icon(HdyAvatar *avatar,
    239                    GIcon *icon)
    240 {
    241   g_assert(avatar);
    242 
    243   if (!icon)
    244     hdy_avatar_set_loadable_icon(avatar, NULL);
    245   else
    246     hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(icon));
    247 }
    248 
    249 gboolean
    250 ui_find_qdata_in_container(GtkContainer *container,
    251                            GQuark quark,
    252                            const gpointer data)
    253 {
    254   g_assert((container) && (data));
    255 
    256   GList* children = gtk_container_get_children(container);
    257   GList *item = children;
    258 
    259   while (item)
    260   {
    261     GtkWidget *widget = GTK_WIDGET(item->data);
    262 
    263     if (data == g_object_get_qdata(G_OBJECT(widget), quark))
    264       break;
    265 
    266     item = item->next;
    267   }
    268 
    269   if (children)
    270     g_list_free(children);
    271 
    272   return item? TRUE : FALSE;
    273 }
    274 
    275 void
    276 ui_clear_container_of_missing_qdata(GtkContainer *container,
    277                                     GQuark quark,
    278                                     const GList *list)
    279 {
    280   g_assert(container);
    281 
    282   GList* children = gtk_container_get_children(container);
    283   GList *item = children;
    284 
    285   while (item) {
    286     GtkWidget *widget = GTK_WIDGET(item->data);
    287     const GList *data = list;
    288 
    289     while (data)
    290     {
    291       if (data->data == g_object_get_qdata(G_OBJECT(widget), quark))
    292         break;
    293 
    294       data = data->next;
    295     }
    296 
    297     if (!data)
    298       gtk_container_remove(container, widget);
    299 
    300     item = item->next;
    301   }
    302 
    303   if (children)
    304     g_list_free(children);
    305 }