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 }