diff options
Diffstat (limited to 'src/ui/contact_info.c')
-rw-r--r-- | src/ui/contact_info.c | 339 |
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 | ||
29 | static void | 30 | static void |
31 | handle_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 | |||
69 | static void | ||
70 | handle_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 | |||
78 | static 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 | |||
89 | static void | ||
90 | handle_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 | |||
96 | static void | ||
97 | handle_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 | |||
139 | close_dialog: | ||
140 | gtk_window_close(GTK_WINDOW(handle->dialog)); | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | handle_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 | |||
157 | static void | ||
30 | handle_close_button_click(UNUSED GtkButton *button, | 158 | handle_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 | ||
172 | static gboolean | ||
173 | handle_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 | |||
44 | void | 266 | void |
45 | ui_contact_info_dialog_init(MESSENGER_Application *app, | 267 | ui_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 | ||
112 | void | 386 | void |
113 | ui_contact_info_dialog_update(UI_CONTACT_INFO_Handle *handle, | 387 | ui_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 | ||
119 | void | 444 | void |
120 | ui_contact_info_dialog_cleanup(UI_CONTACT_INFO_Handle *handle) | 445 | ui_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 | } |