aboutsummaryrefslogtreecommitdiff
path: root/src/ui/contact_info.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/contact_info.c')
-rw-r--r--src/ui/contact_info.c339
1 files changed, 336 insertions, 3 deletions
diff --git a/src/ui/contact_info.c b/src/ui/contact_info.c
index b8e504b..9952ab6 100644
--- a/src/ui/contact_info.c
+++ b/src/ui/contact_info.c
@@ -24,9 +24,137 @@
24 24
25#include "contact_info.h" 25#include "contact_info.h"
26 26
27#include "chat_entry.h"
27#include "../application.h" 28#include "../application.h"
28 29
29static void 30static void
31handle_contact_edit_button_click(UNUSED GtkButton *button,
32 gpointer user_data)
33{
34 UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
35
36 gboolean editable = gtk_widget_is_sensitive(
37 GTK_WIDGET(handle->contact_name_entry)
38 );
39
40 struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) (
41 g_object_get_qdata(
42 G_OBJECT(handle->contact_name_entry),
43 handle->app->quarks.data
44 )
45 );
46
47 const gchar *name = gtk_entry_get_text(handle->contact_name_entry);
48
49 if ((editable) && (contact))
50 GNUNET_CHAT_contact_set_name(
51 contact,
52 (name) && (g_utf8_strlen(name, 1))? name : NULL
53 );
54
55 gtk_image_set_from_icon_name(
56 handle->contact_edit_symbol,
57 editable?
58 "document-edit-symbolic" :
59 "emblem-ok-symbolic",
60 GTK_ICON_SIZE_BUTTON
61 );
62
63 gtk_widget_set_sensitive(
64 GTK_WIDGET(handle->contact_name_entry),
65 !editable
66 );
67}
68
69static void
70handle_contact_name_entry_activate(UNUSED GtkEntry *entry,
71 gpointer user_data)
72{
73 UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
74
75 handle_contact_edit_button_click(handle->contact_edit_button, handle);
76}
77
78static void
79_contact_info_reveal_identity(UI_CONTACT_INFO_Handle *handle)
80{
81 gtk_widget_set_visible(GTK_WIDGET(handle->back_button), TRUE);
82
83 gtk_stack_set_visible_child(
84 handle->contact_info_stack,
85 GTK_WIDGET(handle->id_drawing_area)
86 );
87}
88
89static void
90handle_reveal_identity_button_click(UNUSED GtkButton *button,
91 gpointer user_data)
92{
93 _contact_info_reveal_identity((UI_CONTACT_INFO_Handle*) user_data);
94}
95
96static void
97handle_open_chat_button_click(UNUSED GtkButton *button,
98 gpointer user_data)
99{
100 UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
101
102 struct GNUNET_CHAT_Contact *contact = (struct GNUNET_CHAT_Contact*) (
103 g_object_get_qdata(
104 G_OBJECT(handle->contact_name_entry),
105 handle->app->quarks.data
106 )
107 );
108
109 if (!contact)
110 return;
111
112 struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context(
113 contact
114 );
115
116 if (!context)
117 return;
118
119 if (GNUNET_SYSERR == GNUNET_CHAT_context_get_status(context))
120 {
121 GNUNET_CHAT_context_request(context);
122 goto close_dialog;
123 }
124
125 UI_CHAT_ENTRY_Handle *entry = GNUNET_CHAT_context_get_user_pointer(context);
126
127 if (!entry)
128 return;
129
130 GtkListBoxRow *row = GTK_LIST_BOX_ROW(
131 gtk_widget_get_parent(entry->entry_box)
132 );
133
134 gtk_list_box_select_row(handle->app->ui.messenger.chats_listbox, row);
135 gtk_list_box_invalidate_filter(handle->app->ui.messenger.chats_listbox);
136
137 gtk_widget_activate(GTK_WIDGET(row));
138
139close_dialog:
140 gtk_window_close(GTK_WINDOW(handle->dialog));
141}
142
143static void
144handle_back_button_click(UNUSED GtkButton *button,
145 gpointer user_data)
146{
147 UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
148
149 gtk_widget_set_visible(GTK_WIDGET(handle->back_button), FALSE);
150
151 gtk_stack_set_visible_child(
152 handle->contact_info_stack,
153 handle->details_box
154 );
155}
156
157static void
30handle_close_button_click(UNUSED GtkButton *button, 158handle_close_button_click(UNUSED GtkButton *button,
31 gpointer user_data) 159 gpointer user_data)
32{ 160{
@@ -41,10 +169,106 @@ handle_dialog_destroy(UNUSED GtkWidget *window,
41 ui_contact_info_dialog_cleanup((UI_CONTACT_INFO_Handle*) user_data); 169 ui_contact_info_dialog_cleanup((UI_CONTACT_INFO_Handle*) user_data);
42} 170}
43 171
172static gboolean
173handle_id_drawing_area_draw(GtkWidget* drawing_area,
174 cairo_t* cairo,
175 gpointer user_data)
176{
177 UI_CONTACT_INFO_Handle *handle = (UI_CONTACT_INFO_Handle*) user_data;
178
179 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
180
181 if (!context)
182 return FALSE;
183
184 const guint width = gtk_widget_get_allocated_width(drawing_area);
185 const guint height = gtk_widget_get_allocated_height(drawing_area);
186
187 gtk_render_background(context, cairo, 0, 0, width, height);
188
189 if ((!(handle->qr)) || (handle->qr->width <= 0))
190 return FALSE;
191
192 const guint m = 3;
193 const guint w = handle->qr->width;
194 const guint w2 = w + m * 2;
195
196 guchar *pixels = (guchar*) g_malloc(sizeof(guchar) * w2 * w2 * 3);
197
198 guint x, y, z;
199 for (y = 0; y < w2; y++)
200 for (x = 0; x < w2; x++)
201 {
202 guchar value;
203
204 if ((x >= m) && (y >= m) && (x - m < w) && (y - m < w))
205 value = ((handle->qr->data[(y - m) * w + x - m]) & 1);
206 else
207 value = 0;
208
209 for (z = 0; z < 3; z++)
210 pixels[(y * w2 + x) * 3 + z] = value? 0x00 : 0xff;
211 }
212
213 GdkPixbuf *image = gdk_pixbuf_new_from_data(
214 pixels,
215 GDK_COLORSPACE_RGB,
216 FALSE,
217 8,
218 w2,
219 w2,
220 w2 * 3,
221 NULL,
222 NULL
223 );
224
225 if (!image)
226 return FALSE;
227
228 int dwidth = gdk_pixbuf_get_width(image);
229 int dheight = gdk_pixbuf_get_height(image);
230
231 double ratio_width = 1.0 * width / dwidth;
232 double ratio_height = 1.0 * height / dheight;
233
234 const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
235
236 dwidth = (int) (dwidth * ratio);
237 dheight = (int) (dheight * ratio);
238
239 double dx = (width - dwidth) * 0.5;
240 double dy = (height - dheight) * 0.5;
241
242 const int interp_type = (ratio >= 1.0?
243 GDK_INTERP_NEAREST :
244 GDK_INTERP_BILINEAR
245 );
246
247 GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
248 image,
249 dwidth,
250 dheight,
251 interp_type
252 );
253
254 gtk_render_icon(context, cairo, scaled, dx, dy);
255
256 cairo_fill(cairo);
257
258 g_object_unref(scaled);
259 g_object_unref(image);
260
261 g_free(pixels);
262
263 return FALSE;
264}
265
44void 266void
45ui_contact_info_dialog_init(MESSENGER_Application *app, 267ui_contact_info_dialog_init(MESSENGER_Application *app,
46 UI_CONTACT_INFO_Handle *handle) 268 UI_CONTACT_INFO_Handle *handle)
47{ 269{
270 handle->app = app;
271
48 handle->builder = gtk_builder_new_from_resource( 272 handle->builder = gtk_builder_new_from_resource(
49 application_get_resource_path(app, "ui/contact_info.ui") 273 application_get_resource_path(app, "ui/contact_info.ui")
50 ); 274 );
@@ -70,26 +294,76 @@ ui_contact_info_dialog_init(MESSENGER_Application *app,
70 gtk_builder_get_object(handle->builder, "contact_avatar") 294 gtk_builder_get_object(handle->builder, "contact_avatar")
71 ); 295 );
72 296
73 handle->contact_name = GTK_ENTRY( 297 handle->contact_name_entry = GTK_ENTRY(
74 gtk_builder_get_object(handle->builder, "contact_name") 298 gtk_builder_get_object(handle->builder, "contact_name")
75 ); 299 );
76 300
301 handle->contact_edit_button = GTK_BUTTON(
302 gtk_builder_get_object(handle->builder, "contact_edit_button")
303 );
304
305 handle->contact_edit_symbol = GTK_IMAGE(
306 gtk_builder_get_object(handle->builder, "contact_edit_symbol")
307 );
308
309 g_signal_connect(
310 handle->contact_name_entry,
311 "activate",
312 G_CALLBACK(handle_contact_name_entry_activate),
313 handle
314 );
315
316 g_signal_connect(
317 handle->contact_edit_button,
318 "clicked",
319 G_CALLBACK(handle_contact_edit_button_click),
320 handle
321 );
322
77 handle->reveal_identity_button = GTK_BUTTON( 323 handle->reveal_identity_button = GTK_BUTTON(
78 gtk_builder_get_object(handle->builder, "reveal_identity_button") 324 gtk_builder_get_object(handle->builder, "reveal_identity_button")
79 ); 325 );
80 326
327 g_signal_connect(
328 handle->reveal_identity_button,
329 "clicked",
330 G_CALLBACK(handle_reveal_identity_button_click),
331 handle
332 );
333
81 handle->open_chat_button = GTK_BUTTON( 334 handle->open_chat_button = GTK_BUTTON(
82 gtk_builder_get_object(handle->builder, "open_chat_button") 335 gtk_builder_get_object(handle->builder, "open_chat_button")
83 ); 336 );
84 337
338 g_signal_connect(
339 handle->open_chat_button,
340 "clicked",
341 G_CALLBACK(handle_open_chat_button_click),
342 handle
343 );
344
85 handle->id_drawing_area = GTK_DRAWING_AREA( 345 handle->id_drawing_area = GTK_DRAWING_AREA(
86 gtk_builder_get_object(handle->builder, "id_drawing_area") 346 gtk_builder_get_object(handle->builder, "id_drawing_area")
87 ); 347 );
88 348
349 handle->id_draw_signal = g_signal_connect(
350 handle->id_drawing_area,
351 "draw",
352 G_CALLBACK(handle_id_drawing_area_draw),
353 handle
354 );
355
89 handle->back_button = GTK_BUTTON( 356 handle->back_button = GTK_BUTTON(
90 gtk_builder_get_object(handle->builder, "back_button") 357 gtk_builder_get_object(handle->builder, "back_button")
91 ); 358 );
92 359
360 g_signal_connect(
361 handle->back_button,
362 "clicked",
363 G_CALLBACK(handle_back_button_click),
364 handle
365 );
366
93 handle->close_button = GTK_BUTTON( 367 handle->close_button = GTK_BUTTON(
94 gtk_builder_get_object(handle->builder, "close_button") 368 gtk_builder_get_object(handle->builder, "close_button")
95 ); 369 );
@@ -111,15 +385,74 @@ ui_contact_info_dialog_init(MESSENGER_Application *app,
111 385
112void 386void
113ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle, 387ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle,
114 struct GNUNET_CHAT_Contact *contact) 388 struct GNUNET_CHAT_Contact *contact,
389 gboolean reveal)
115{ 390{
116 // TODO 391 const char *name = GNUNET_CHAT_contact_get_name(contact);
392
393 hdy_avatar_set_text(handle->contact_avatar, name? name : "");
394 gtk_entry_set_text(handle->contact_name_entry, name? name : "");
395
396 g_object_set_qdata(
397 G_OBJECT(handle->contact_name_entry),
398 handle->app->quarks.data,
399 contact
400 );
401
402 const char *key = GNUNET_CHAT_contact_get_key(contact);
403
404 if (handle->qr)
405 QRcode_free(handle->qr);
406
407 if (key)
408 handle->qr = QRcode_encodeString(
409 key,
410 0,
411 QR_ECLEVEL_L,
412 QR_MODE_8,
413 0
414 );
415 else
416 handle->qr = NULL;
417
418 if (handle->id_drawing_area)
419 gtk_widget_queue_draw(GTK_WIDGET(handle->id_drawing_area));
420
421 gtk_widget_set_sensitive(
422 GTK_WIDGET(handle->reveal_identity_button),
423 key? TRUE : FALSE
424 );
425
426 struct GNUNET_CHAT_Context *context = GNUNET_CHAT_contact_get_context(
427 contact
428 );
429
430 gtk_widget_set_sensitive(
431 GTK_WIDGET(handle->open_chat_button),
432 context? TRUE : FALSE
433 );
434
435 gtk_widget_set_visible(
436 GTK_WIDGET(handle->open_chat_button),
437 GNUNET_YES != GNUNET_CHAT_contact_is_owned(contact)
438 );
439
440 if (reveal)
441 _contact_info_reveal_identity(handle);
117} 442}
118 443
119void 444void
120ui_contact_info_dialog_cleanup(UI_CONTACT_INFO_Handle *handle) 445ui_contact_info_dialog_cleanup(UI_CONTACT_INFO_Handle *handle)
121{ 446{
447 g_signal_handler_disconnect(
448 handle->id_drawing_area,
449 handle->id_draw_signal
450 );
451
122 g_object_unref(handle->builder); 452 g_object_unref(handle->builder);
123 453
454 if (handle->qr)
455 QRcode_free(handle->qr);
456
124 memset(handle, 0, sizeof(*handle)); 457 memset(handle, 0, sizeof(*handle));
125} 458}