aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-03-12 22:59:40 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2022-03-12 22:59:40 +0100
commit85b243c149d96ac88c5afd20993bbe18c50e16ca (patch)
tree99c1e4c205c7fb4c9dc733722adad647e70d3b7f /src/ui
parent4065995bbc9f0c605b63e57574753e7c7ee9985c (diff)
downloadmessenger-gtk-85b243c149d96ac88c5afd20993bbe18c50e16ca.tar.gz
messenger-gtk-85b243c149d96ac88c5afd20993bbe18c50e16ca.zip
Implemented QR generation and usage of lobbies
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/messenger.c94
-rw-r--r--src/ui/messenger.h4
-rw-r--r--src/ui/new_contact.c25
-rw-r--r--src/ui/new_lobby.c404
-rw-r--r--src/ui/new_lobby.h71
5 files changed, 570 insertions, 28 deletions
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
index 246bb9c..270360d 100644
--- a/src/ui/messenger.c
+++ b/src/ui/messenger.c
@@ -31,6 +31,8 @@
31#include "contacts.h" 31#include "contacts.h"
32#include "message.h" 32#include "message.h"
33#include "new_contact.h" 33#include "new_contact.h"
34#include "new_group.h"
35#include "new_lobby.h"
34#include "new_platform.h" 36#include "new_platform.h"
35#include "settings.h" 37#include "settings.h"
36 38
@@ -58,6 +60,19 @@ handle_flap_via_button_click(UNUSED GtkButton* button,
58} 60}
59 61
60static void 62static void
63handle_lobby_button_click(UNUSED GtkButton* button,
64 gpointer user_data)
65{
66 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
67
68 hdy_flap_set_reveal_flap(HDY_FLAP(app->ui.messenger.flap_user_details), FALSE);
69
70 ui_new_lobby_dialog_init(app, &(app->ui.new_lobby));
71
72 gtk_widget_show(GTK_WIDGET(app->ui.new_lobby.dialog));
73}
74
75static void
61_switch_details_revealer_visibility(UI_MESSENGER_Handle *handle, 76_switch_details_revealer_visibility(UI_MESSENGER_Handle *handle,
62 gboolean state) 77 gboolean state)
63{ 78{
@@ -264,6 +279,25 @@ handle_main_window_destroy(UNUSED GtkWidget *window,
264 application_exit(app, MESSENGER_QUIT); 279 application_exit(app, MESSENGER_QUIT);
265} 280}
266 281
282static void
283_switch_accounts_listbox_connection(MESSENGER_Application *app,
284 UI_MESSENGER_Handle *handle,
285 gboolean enabled)
286{
287 if (enabled)
288 handle->accounts_signal = g_signal_connect(
289 handle->accounts_listbox,
290 "row-activated",
291 G_CALLBACK(handle_accounts_listbox_row_activated),
292 app
293 );
294 else
295 g_signal_handler_disconnect(
296 handle->accounts_listbox,
297 handle->accounts_signal
298 );
299}
300
267void 301void
268ui_messenger_init(MESSENGER_Application *app, 302ui_messenger_init(MESSENGER_Application *app,
269 UI_MESSENGER_Handle *handle) 303 UI_MESSENGER_Handle *handle)
@@ -342,8 +376,15 @@ ui_messenger_init(MESSENGER_Application *app,
342 handle->flap_user_details 376 handle->flap_user_details
343 ); 377 );
344 378
345 handle->favourites_button = GTK_BUTTON( 379 handle->lobby_button = GTK_BUTTON(
346 gtk_builder_get_object(handle->builder, "favourites_button") 380 gtk_builder_get_object(handle->builder, "lobby_button")
381 );
382
383 g_signal_connect(
384 handle->lobby_button,
385 "clicked",
386 G_CALLBACK(handle_lobby_button_click),
387 app
347 ); 388 );
348 389
349 handle->account_details_button = GTK_BUTTON( 390 handle->account_details_button = GTK_BUTTON(
@@ -373,12 +414,7 @@ ui_messenger_init(MESSENGER_Application *app,
373 gtk_builder_get_object(handle->builder, "add_account_listbox_row") 414 gtk_builder_get_object(handle->builder, "add_account_listbox_row")
374 ); 415 );
375 416
376 g_signal_connect( 417 _switch_accounts_listbox_connection(app, handle, TRUE);
377 handle->accounts_listbox,
378 "row-activated",
379 G_CALLBACK(handle_accounts_listbox_row_activated),
380 app
381 );
382 418
383 handle->new_contact_button = GTK_BUTTON( 419 handle->new_contact_button = GTK_BUTTON(
384 gtk_builder_get_object(handle->builder, "new_contact_button") 420 gtk_builder_get_object(handle->builder, "new_contact_button")
@@ -522,6 +558,22 @@ _messenger_iterate_accounts(void *cls,
522 return GNUNET_YES; 558 return GNUNET_YES;
523} 559}
524 560
561static void
562_clear_accounts_listbox(GtkWidget *widget,
563 gpointer data)
564{
565 GtkListBoxRow *row = GTK_LIST_BOX_ROW(widget);
566 GtkListBox *listbox = GTK_LIST_BOX(data);
567
568 if ((!row) || (!listbox) || (!gtk_list_box_row_get_selectable(row)))
569 return;
570
571 gtk_container_remove(
572 GTK_CONTAINER(listbox),
573 widget
574 );
575}
576
525void 577void
526ui_messenger_refresh(MESSENGER_Application *app, 578ui_messenger_refresh(MESSENGER_Application *app,
527 UI_MESSENGER_Handle *handle) 579 UI_MESSENGER_Handle *handle)
@@ -529,31 +581,21 @@ ui_messenger_refresh(MESSENGER_Application *app,
529 if (!(handle->accounts_listbox)) 581 if (!(handle->accounts_listbox))
530 return; 582 return;
531 583
532 GList *list = gtk_container_get_children( 584 _switch_accounts_listbox_connection(app, handle, FALSE);
533 GTK_CONTAINER(handle->accounts_listbox)
534 );
535
536 while (list)
537 {
538 GtkListBoxRow *row = GTK_LIST_BOX_ROW(list->data);
539
540 if ((!row) || (!gtk_list_box_row_get_selectable(row)))
541 goto skip_row;
542 585
543 gtk_container_remove( 586 gtk_container_foreach(
544 GTK_CONTAINER(handle->accounts_listbox), 587 GTK_CONTAINER(handle->accounts_listbox),
545 GTK_WIDGET(row) 588 _clear_accounts_listbox,
546 ); 589 handle->accounts_listbox
547 590 );
548 skip_row:
549 list = list->next;
550 }
551 591
552 GNUNET_CHAT_iterate_accounts( 592 GNUNET_CHAT_iterate_accounts(
553 app->chat.messenger.handle, 593 app->chat.messenger.handle,
554 _messenger_iterate_accounts, 594 _messenger_iterate_accounts,
555 app 595 app
556 ); 596 );
597
598 _switch_accounts_listbox_connection(app, handle, TRUE);
557} 599}
558 600
559gboolean 601gboolean
diff --git a/src/ui/messenger.h b/src/ui/messenger.h
index c23a27d..ef1ae60 100644
--- a/src/ui/messenger.h
+++ b/src/ui/messenger.h
@@ -52,7 +52,7 @@ typedef struct UI_MESSENGER_Handle
52 GtkLabel *profile_key_label; 52 GtkLabel *profile_key_label;
53 53
54 GtkButton *hide_user_details_button; 54 GtkButton *hide_user_details_button;
55 GtkButton *favourites_button; 55 GtkButton *lobby_button;
56 GtkButton *account_details_button; 56 GtkButton *account_details_button;
57 GtkImage *account_details_symbol; 57 GtkImage *account_details_symbol;
58 58
@@ -72,6 +72,8 @@ typedef struct UI_MESSENGER_Handle
72 72
73 GtkStack *chats_stack; 73 GtkStack *chats_stack;
74 GtkWidget *no_chat_box; 74 GtkWidget *no_chat_box;
75
76 gulong accounts_signal;
75} UI_MESSENGER_Handle; 77} UI_MESSENGER_Handle;
76 78
77void 79void
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
index 8188740..6438331 100644
--- a/src/ui/new_contact.c
+++ b/src/ui/new_contact.c
@@ -40,8 +40,28 @@ handle_confirm_button_click(UNUSED GtkButton *button,
40{ 40{
41 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 41 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
42 42
43 // TODO: Add new contact 43 const gint id_length = gtk_entry_get_text_length(app->ui.new_contact.id_entry);
44 const gchar *id_text = gtk_entry_get_text(app->ui.new_contact.id_entry);
44 45
46 if (id_length <= 0)
47 goto close_dialog;
48
49 gchar *emsg = NULL;
50 struct GNUNET_CHAT_Uri *uri = GNUNET_CHAT_uri_parse(id_text, &emsg);
51
52 if (uri)
53 {
54 GNUNET_CHAT_lobby_join(app->chat.messenger.handle, uri);
55 GNUNET_CHAT_uri_destroy(uri);
56 }
57
58 if (emsg)
59 {
60 printf("ERROR: %s\n", emsg);
61 GNUNET_free(emsg);
62 }
63
64close_dialog:
45 gtk_window_close(GTK_WINDOW(app->ui.new_contact.dialog)); 65 gtk_window_close(GTK_WINDOW(app->ui.new_contact.dialog));
46} 66}
47 67
@@ -61,6 +81,9 @@ handle_id_drawing_area_draw(GtkWidget* drawing_area,
61 81
62 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area); 82 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
63 83
84 if (!context)
85 return FALSE;
86
64 const guint width = gtk_widget_get_allocated_width(drawing_area); 87 const guint width = gtk_widget_get_allocated_width(drawing_area);
65 const guint height = gtk_widget_get_allocated_height(drawing_area); 88 const guint height = gtk_widget_get_allocated_height(drawing_area);
66 89
diff --git a/src/ui/new_lobby.c b/src/ui/new_lobby.c
new file mode 100644
index 0000000..0a9fe37
--- /dev/null
+++ b/src/ui/new_lobby.c
@@ -0,0 +1,404 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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_lobby.c
23 */
24
25#include "new_lobby.h"
26
27#include "../application.h"
28
29static void
30handle_warning_info_bar_close(GtkInfoBar *info_bar,
31 UNUSED gpointer user_data)
32{
33 gtk_info_bar_set_revealed(info_bar, FALSE);
34}
35
36static void
37handle_warning_info_bar_response(GtkInfoBar *info_bar,
38 UNUSED int response_id,
39 UNUSED gpointer user_data)
40{
41 gtk_info_bar_set_revealed(info_bar, FALSE);
42}
43
44static void
45handle_cancel_button_click(UNUSED GtkButton *button,
46 gpointer user_data)
47{
48 GtkDialog *dialog = GTK_DIALOG(user_data);
49 gtk_window_close(GTK_WINDOW(dialog));
50}
51
52void
53handle_lobby_opened_and_uri_generated(void *cls,
54 const struct GNUNET_CHAT_Uri *uri)
55{
56 MESSENGER_Application *app = (MESSENGER_Application*) cls;
57
58 if (app->ui.new_lobby.qr)
59 QRcode_free(app->ui.new_lobby.qr);
60
61 if (!uri)
62 {
63 if (app->ui.new_lobby.preview_stack)
64 gtk_stack_set_visible_child(
65 app->ui.new_lobby.preview_stack,
66 app->ui.new_lobby.fail_box
67 );
68
69 app->ui.new_lobby.qr = NULL;
70 return;
71 }
72
73 gchar *uri_string = GNUNET_CHAT_uri_to_string(uri);
74
75 app->ui.new_lobby.qr = QRcode_encodeString(
76 uri_string,
77 0,
78 QR_ECLEVEL_L,
79 QR_MODE_8,
80 0
81 );
82
83 if (app->ui.new_lobby.id_drawing_area)
84 gtk_widget_queue_draw(GTK_WIDGET(app->ui.new_lobby.id_drawing_area));
85
86 if (app->ui.new_lobby.preview_stack)
87 gtk_stack_set_visible_child(
88 app->ui.new_lobby.preview_stack,
89 GTK_WIDGET(app->ui.new_lobby.id_drawing_area)
90 );
91
92 if (app->ui.new_lobby.id_entry)
93 gtk_entry_set_text(app->ui.new_lobby.id_entry, uri_string);
94
95 GNUNET_free(uri_string);
96
97 if (!(app->ui.new_lobby.id_entry))
98 return;
99
100 const gint id_length = gtk_entry_get_text_length(app->ui.new_lobby.id_entry);
101
102 gtk_widget_set_sensitive(
103 GTK_WIDGET(app->ui.new_lobby.copy_button),
104 id_length > 0? TRUE : FALSE
105 );
106}
107
108static void
109handle_generate_button_click(UNUSED GtkButton *button,
110 gpointer user_data)
111{
112 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
113
114 GtkTreeModel *model = gtk_combo_box_get_model(
115 app->ui.new_lobby.expiration_combo_box
116 );
117
118 gulong delay = 0;
119
120 GtkTreeIter iter;
121 if (gtk_combo_box_get_active_iter(app->ui.new_lobby.expiration_combo_box,
122 &iter))
123 gtk_tree_model_get(model, &iter, 1, &delay, -1);
124
125 struct GNUNET_TIME_Relative expiration = GNUNET_TIME_relative_multiply(
126 GNUNET_TIME_relative_get_second_(),
127 delay
128 );
129
130 gtk_stack_set_visible_child(
131 app->ui.new_lobby.preview_stack,
132 GTK_WIDGET(app->ui.new_lobby.loading_spinner)
133 );
134
135 gtk_stack_set_visible_child(
136 app->ui.new_lobby.stack,
137 app->ui.new_lobby.copy_box
138 );
139
140 gtk_widget_set_sensitive(GTK_WIDGET(app->ui.new_lobby.copy_button), FALSE);
141
142 gtk_widget_set_visible(GTK_WIDGET(app->ui.new_lobby.generate_button), FALSE);
143 gtk_widget_set_visible(GTK_WIDGET(app->ui.new_lobby.copy_button), TRUE);
144
145 GNUNET_CHAT_lobby_open(
146 app->chat.messenger.handle,
147 expiration,
148 handle_lobby_opened_and_uri_generated,
149 app
150 );
151}
152
153static void
154handle_copy_button_click(UNUSED GtkButton *button,
155 gpointer user_data)
156{
157 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
158
159 const gint id_length = gtk_entry_get_text_length(app->ui.new_lobby.id_entry);
160 const gchar *id_text = gtk_entry_get_text(app->ui.new_lobby.id_entry);
161
162 GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
163
164 if ((clipboard) && (id_length > 0))
165 gtk_clipboard_set_text(clipboard, id_text, id_length);
166
167 gtk_window_close(GTK_WINDOW(app->ui.new_lobby.dialog));
168}
169
170static void
171handle_dialog_destroy(UNUSED GtkWidget *window,
172 gpointer user_data)
173{
174 ui_new_lobby_dialog_cleanup((UI_NEW_LOBBY_Handle*) user_data);
175}
176
177static gboolean
178handle_id_drawing_area_draw(GtkWidget* drawing_area,
179 cairo_t* cairo,
180 gpointer user_data)
181{
182 UI_NEW_LOBBY_Handle *handle = (UI_NEW_LOBBY_Handle*) user_data;
183
184 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
185
186 if (!context)
187 return FALSE;
188
189 const guint width = gtk_widget_get_allocated_width(drawing_area);
190 const guint height = gtk_widget_get_allocated_height(drawing_area);
191
192 gtk_render_background(context, cairo, 0, 0, width, height);
193
194 if ((!(handle->qr)) || (handle->qr->width <= 0))
195 return FALSE;
196
197 const guint m = 3;
198 const guint w = handle->qr->width;
199 const guint w2 = w + m * 2;
200
201 guchar pixels [w2 * w2 * 3];
202
203 guint x, y, z;
204 for (y = 0; y < w2; y++)
205 for (x = 0; x < w2; x++)
206 {
207 guchar value;
208
209 if ((x >= m) && (y >= m) && (x - m < w) && (y - m < w))
210 value = ((handle->qr->data[(y - m) * w + x - m]) & 1);
211 else
212 value = 0;
213
214 for (z = 0; z < 3; z++)
215 pixels[(y * w2 + x) * 3 + z] = value? 0x00 : 0xff;
216 }
217
218 GdkPixbuf *image = gdk_pixbuf_new_from_data(
219 pixels,
220 GDK_COLORSPACE_RGB,
221 FALSE,
222 8,
223 w2,
224 w2,
225 w2 * 3,
226 NULL,
227 NULL
228 );
229
230 if (!image)
231 return FALSE;
232
233 int dwidth = gdk_pixbuf_get_width(image);
234 int dheight = gdk_pixbuf_get_height(image);
235
236 double ratio_width = 1.0 * width / dwidth;
237 double ratio_height = 1.0 * height / dheight;
238
239 const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
240
241 dwidth = (int) (dwidth * ratio);
242 dheight = (int) (dheight * ratio);
243
244 double dx = (width - dwidth) * 0.5;
245 double dy = (height - dheight) * 0.5;
246
247 const int interp_type = (ratio >= 1.0?
248 GDK_INTERP_NEAREST :
249 GDK_INTERP_BILINEAR
250 );
251
252 GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
253 image,
254 dwidth,
255 dheight,
256 interp_type
257 );
258
259 gtk_render_icon(context, cairo, scaled, dx, dy);
260
261 cairo_fill(cairo);
262
263 g_object_unref(scaled);
264 g_object_unref(image);
265
266 return FALSE;
267}
268
269
270void
271ui_new_lobby_dialog_init(MESSENGER_Application *app,
272 UI_NEW_LOBBY_Handle *handle)
273{
274 handle->builder = gtk_builder_new_from_resource(
275 application_get_resource_path(app, "ui/new_lobby.ui")
276 );
277
278 handle->dialog = GTK_DIALOG(
279 gtk_builder_get_object(handle->builder, "new_lobby_dialog")
280 );
281
282 gtk_window_set_transient_for(
283 GTK_WINDOW(handle->dialog),
284 GTK_WINDOW(app->ui.messenger.main_window)
285 );
286
287 handle->warning_info_bar = GTK_INFO_BAR(
288 gtk_builder_get_object(handle->builder, "warning_info_bar")
289 );
290
291 g_signal_connect(
292 handle->warning_info_bar,
293 "close",
294 G_CALLBACK(handle_warning_info_bar_close),
295 NULL
296 );
297
298 g_signal_connect(
299 handle->warning_info_bar,
300 "response",
301 G_CALLBACK(handle_warning_info_bar_response),
302 NULL
303 );
304
305 handle->stack = GTK_STACK(
306 gtk_builder_get_object(handle->builder, "new_lobby_stack")
307 );
308
309 handle->generate_box = GTK_WIDGET(
310 gtk_builder_get_object(handle->builder, "generate_box")
311 );
312
313 handle->copy_box = GTK_WIDGET(
314 gtk_builder_get_object(handle->builder, "copy_box")
315 );
316
317 handle->expiration_combo_box = GTK_COMBO_BOX(
318 gtk_builder_get_object(handle->builder, "expiration_combo_box")
319 );
320
321 handle->preview_stack = GTK_STACK(
322 gtk_builder_get_object(handle->builder, "preview_stack")
323 );
324
325 handle->fail_box = GTK_WIDGET(
326 gtk_builder_get_object(handle->builder, "fail_box")
327 );
328
329 handle->loading_spinner = GTK_SPINNER(
330 gtk_builder_get_object(handle->builder, "loading_spinner")
331 );
332
333 handle->id_drawing_area = GTK_DRAWING_AREA(
334 gtk_builder_get_object(handle->builder, "id_drawing_area")
335 );
336
337 handle->id_draw_signal = g_signal_connect(
338 handle->id_drawing_area,
339 "draw",
340 G_CALLBACK(handle_id_drawing_area_draw),
341 handle
342 );
343
344 handle->id_entry = GTK_ENTRY(
345 gtk_builder_get_object(handle->builder, "id_entry")
346 );
347
348 handle->cancel_button = GTK_BUTTON(
349 gtk_builder_get_object(handle->builder, "cancel_button")
350 );
351
352 g_signal_connect(
353 handle->cancel_button,
354 "clicked",
355 G_CALLBACK(handle_cancel_button_click),
356 handle->dialog
357 );
358
359 handle->generate_button = GTK_BUTTON(
360 gtk_builder_get_object(handle->builder, "generate_button")
361 );
362
363 g_signal_connect(
364 handle->generate_button,
365 "clicked",
366 G_CALLBACK(handle_generate_button_click),
367 app
368 );
369
370 handle->copy_button = GTK_BUTTON(
371 gtk_builder_get_object(handle->builder, "copy_button")
372 );
373
374 g_signal_connect(
375 handle->copy_button,
376 "clicked",
377 G_CALLBACK(handle_copy_button_click),
378 app
379 );
380
381 g_signal_connect(
382 handle->dialog,
383 "destroy",
384 G_CALLBACK(handle_dialog_destroy),
385 handle
386 );
387}
388
389
390void
391ui_new_lobby_dialog_cleanup(UI_NEW_LOBBY_Handle *handle)
392{
393 g_signal_handler_disconnect(
394 handle->id_drawing_area,
395 handle->id_draw_signal
396 );
397
398 g_object_unref(handle->builder);
399
400 if (handle->qr)
401 QRcode_free(handle->qr);
402
403 memset(handle, 0, sizeof(*handle));
404}
diff --git a/src/ui/new_lobby.h b/src/ui/new_lobby.h
new file mode 100644
index 0000000..9d100b6
--- /dev/null
+++ b/src/ui/new_lobby.h
@@ -0,0 +1,71 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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_lobby.h
23 */
24
25#ifndef UI_NEW_LOBBY_H_
26#define UI_NEW_LOBBY_H_
27
28#include "messenger.h"
29
30#include <cairo/cairo.h>
31#include <gdk/gdkpixbuf.h>
32#include <qrencode.h>
33
34typedef struct UI_NEW_LOBBY_Handle
35{
36 GtkBuilder *builder;
37 GtkDialog *dialog;
38
39 GtkInfoBar *warning_info_bar;
40
41 GtkStack *stack;
42 GtkWidget *generate_box;
43 GtkWidget *copy_box;
44
45 GtkComboBox *expiration_combo_box;
46
47 GtkStack *preview_stack;
48 GtkWidget *fail_box;
49
50 GtkSpinner *loading_spinner;
51
52 GtkDrawingArea *id_drawing_area;
53 GtkEntry *id_entry;
54
55 gulong id_draw_signal;
56
57 GtkButton *cancel_button;
58 GtkButton *generate_button;
59 GtkButton *copy_button;
60
61 QRcode *qr;
62} UI_NEW_LOBBY_Handle;
63
64void
65ui_new_lobby_dialog_init(MESSENGER_Application *app,
66 UI_NEW_LOBBY_Handle *handle);
67
68void
69ui_new_lobby_dialog_cleanup(UI_NEW_LOBBY_Handle *handle);
70
71#endif /* UI_NEW_LOBBY_H_ */