aboutsummaryrefslogtreecommitdiff
path: root/src/fs/gnunet-fs-gtk_namespace_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/gnunet-fs-gtk_namespace_manager.c')
-rw-r--r--src/fs/gnunet-fs-gtk_namespace_manager.c970
1 files changed, 970 insertions, 0 deletions
diff --git a/src/fs/gnunet-fs-gtk_namespace_manager.c b/src/fs/gnunet-fs-gtk_namespace_manager.c
new file mode 100644
index 00000000..a7d79376
--- /dev/null
+++ b/src/fs/gnunet-fs-gtk_namespace_manager.c
@@ -0,0 +1,970 @@
1/*
2 This file is part of GNUnet
3 (C) 2005, 2006, 2010, 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/fs/gnunet-fs-gtk_namespace_manager.c
23 * @author LRN
24 */
25#include "gnunet-fs-gtk_common.h"
26#include "gnunet-fs-gtk.h"
27#include <gnunet/gnunet_util_lib.h>
28#include <gnunet/gnunet_fs_service.h>
29
30struct GNUNET_GTK_NamespaceManagerContext
31{
32 GtkBuilder *builder;
33 GtkWidget *known_ns;
34 GtkWidget *ns_order;
35 GtkWidget *ns_details;
36 GtkTreeSelection *known_ns_sel;
37 GtkTreeSelection *ns_order_sel;
38 GtkTreeSelection *ns_details_sel;
39 GtkListStore *ns_order_store;
40 GtkListStore *known_ns_store;
41 GtkListStore *ns_details_store;
42 GtkWindow *namespace_manager;
43 GtkTreeViewColumn *order_rank;
44 GtkTreeViewColumn *order_name;
45 GtkTreeViewColumn *order_id;
46 GtkWidget *details_apply_button;
47 GtkWidget *details_delete_button;
48 int sort_direction;
49 struct GNUNET_CONTAINER_MetaData *uneditable_md;
50};
51
52/**
53 * THIS IS EVIL! Used to avoid opening more than one ns manager
54 * at once. Could be fixed by saving a pointer to the ns manager window
55 * somewhere in the main gnunet-fs-gtk window, but main window does
56 * not have a context structure for such things at the moment, hence
57 * this VERY EVIL GLOBAL VARIABLE!
58 */
59static struct GNUNET_GTK_NamespaceManagerContext *ns_manager = NULL;
60
61#define GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN 0
62#define GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN 1
63#define GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN 2
64#define GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN 3
65#define GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN 4
66#define GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN 5
67#define GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN 6
68#define GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN 7
69
70#define GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN 0
71#define GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN 1
72#define GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN 2
73#define GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN 3
74#define GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN 4
75
76#define GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN 0
77#define GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN 1
78#define GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN 2
79#define GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN 3
80#define GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN 4
81#define GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN 5
82
83static void
84sort_order_list (struct GNUNET_GTK_NamespaceManagerContext *ctx,
85 int sort_column)
86{
87 int sorted = GNUNET_NO;
88 GtkTreeIter iter;
89 gint i;
90 gint row_count;
91 gint *row_indices, *row_ints;
92 gchar **row_strings;
93
94 ctx->sort_direction = ctx->sort_direction <= 0 ? 1 : 0;
95
96 row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (
97 ctx->ns_order_store), NULL);
98 if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
99 ctx->ns_order_store), &iter))
100 return;
101
102 row_indices = g_new0 (gint, row_count);
103 row_ints = g_new0 (gint, row_count);
104 row_strings = g_new0 (gchar *, row_count);
105
106 for (i = 0; i < row_count; i++)
107 {
108 int an_int;
109 char *a_string;
110 row_indices[i] = i;
111 switch (sort_column)
112 {
113 case GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN:
114 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter,
115 sort_column, &an_int, -1);
116 row_ints[i] = an_int;
117 row_strings[i] = NULL;
118 break;
119 case GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN:
120 case GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN:
121 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter,
122 sort_column, &a_string, -1);
123 row_strings[i] = a_string;
124 break;
125 default:
126 row_strings[i] = NULL;
127 break;
128 }
129 if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL (
130 ctx->ns_order_store), &iter))
131 break;
132 }
133
134 while (sorted != GNUNET_YES)
135 {
136 sorted = GNUNET_YES;
137 for (i = 0; i < row_count - 1; i++)
138 {
139 int cmp_result;
140
141 switch (sort_column)
142 {
143 case GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN:
144 cmp_result = row_ints[i] <= row_ints[i + 1] ? 0 : 1;
145 break;
146 case GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN:
147 case GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN:
148 /* FIXME: name can be UTF-8-encoded, use UTF-8-aware comparison func */
149 cmp_result = strcmp (row_strings[i], row_strings[i + 1]);
150 break;
151 default:
152 break;
153 }
154
155 if (((ctx->sort_direction <= 0) && (cmp_result <= 0)) ||
156 ((ctx->sort_direction > 0) && (cmp_result > 0)))
157 {
158 int tmp_int, tmp_index;
159 char *tmp_string;
160 tmp_index = row_indices[i];
161 tmp_int = row_ints[i];
162 tmp_string = row_strings[i];
163 row_indices[i] = row_indices[i + 1];
164 row_ints[i] = row_ints[i + 1];
165 row_strings[i] = row_strings[i + 1];
166 row_ints[i + 1] = tmp_int;
167 row_strings[i + 1] = tmp_string;
168 row_indices[i + 1] = tmp_index;
169 sorted = GNUNET_NO;
170 }
171 }
172 }
173
174 gtk_list_store_reorder (ctx->ns_order_store, row_indices);
175
176 g_free (row_indices);
177 for (i = 0; i < row_count; i++)
178 g_free (row_strings[i]);
179 g_free (row_strings);
180 g_free (row_ints);
181}
182
183void
184GNUNET_GTK_namespace_manager_namespace_order_column_clicked_cb (
185 GtkTreeViewColumn *treeviewcolumn, gpointer user_data)
186{
187 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
188 if (treeviewcolumn == ctx->order_rank)
189 {
190 sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN);
191 }
192 else if (treeviewcolumn == ctx->order_name)
193 {
194 sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN);
195 }
196 else if (treeviewcolumn == ctx->order_id)
197 {
198 sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN);
199 }
200}
201
202void
203GNUNET_GTK_namespace_manager_known_namespaces_delete_button_clicked_cb (
204 GtkButton *button, gpointer user_data)
205{
206 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
207 GtkTreeIter iter;
208 GNUNET_HashCode *nsid;
209 GtkTreeRowReference *order_row, *known_row;
210 struct GNUNET_CONTAINER_MetaData *md;
211
212 if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &iter))
213 return;
214
215 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
216 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid,
217 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row,
218 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md,
219 -1);
220 GNUNET_CONTAINER_meta_data_destroy (md);
221 gtk_list_store_remove (ctx->known_ns_store, &iter);
222 if (order_row != NULL)
223 {
224 if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &iter))
225 {
226 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter,
227 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1);
228 gtk_list_store_remove (ctx->ns_order_store, &iter);
229 if (known_row != NULL)
230 gtk_tree_row_reference_free (known_row);
231 }
232 gtk_tree_row_reference_free (order_row);
233 }
234 GNUNET_free (nsid);
235
236 gtk_list_store_clear (ctx->ns_details_store);
237 GNUNET_CONTAINER_meta_data_destroy (ctx->uneditable_md);
238 ctx->uneditable_md = NULL;
239}
240
241void
242GNUNET_GTK_namespace_manager_known_namespaces_swap_rank_button_clicked_cb (
243 GtkButton *button, gpointer user_data)
244{
245 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
246 GtkTreeIter known_iter, order_iter;
247 GNUNET_HashCode *nsid;
248 int32_t old_rank, new_rank;
249 GtkTreeRowReference *order_row, *known_row;
250
251 if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &known_iter))
252 return;
253
254 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter,
255 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid,
256 GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, &old_rank,
257 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row,
258 -1);
259
260 if (old_rank == 0)
261 new_rank = -1;
262 else
263 new_rank = -old_rank;
264
265 gtk_list_store_set (ctx->known_ns_store, &known_iter,
266 GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, new_rank,
267 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, NULL,
268 -1);
269
270 if (order_row != NULL)
271 {
272 if (new_rank < 0)
273 {
274 if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter))
275 {
276 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter,
277 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1);
278 gtk_list_store_remove (ctx->ns_order_store, &order_iter);
279 if (known_row != NULL)
280 gtk_tree_row_reference_free (known_row);
281 }
282 }
283 gtk_tree_row_reference_free (order_row);
284 }
285 if (new_rank >= 0)
286 {
287 char *name, *identifier;
288 if (order_row != NULL)
289 {
290 /* This should not happen */
291 GNUNET_break (0);
292 }
293 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter,
294 GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, &name,
295 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN, &identifier,
296 -1);
297 known_row = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (
298 ctx->known_ns_store), &known_iter);
299 gtk_list_store_insert_with_values (ctx->ns_order_store, &order_iter, G_MAXINT,
300 GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, new_rank,
301 GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, name,
302 GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN, identifier,
303 GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN, nsid,
304 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, known_row,
305 -1);
306 g_free (name);
307 g_free (identifier);
308 order_row = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (ctx->ns_order_store),
309 &order_iter);
310 gtk_list_store_set (ctx->known_ns_store, &known_iter,
311 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, order_row, -1);
312 }
313}
314
315void
316GNUNET_GTK_namespace_manager_namespace_order_apply_clicked_cb (
317 GtkButton *button, gpointer user_data)
318{
319 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
320 GtkTreeIter iter;
321 gint i;
322 gint row_count;
323 GtkTreeRowReference *known_row;
324
325 row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (
326 ctx->ns_order_store), NULL);
327 if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
328 ctx->ns_order_store), &iter))
329 return;
330
331 for (i = 0; i < row_count; i++)
332 {
333 gtk_list_store_set (ctx->ns_order_store, &iter,
334 GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, i, -1);
335 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &iter,
336 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row, -1);
337 if (known_row == NULL)
338 {
339 /* This is not supposed to happen. What to do? */
340 GNUNET_break (0);
341 }
342 else
343 {
344 GtkTreeIter known_iter;
345 if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (known_row, &known_iter))
346 {
347 gtk_list_store_set (ctx->known_ns_store, &known_iter,
348 GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, i,
349 -1);
350 }
351 }
352 if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL (
353 ctx->ns_order_store), &iter))
354 break;
355 }
356}
357
358void
359GNUNET_GTK_namespace_manager_namespace_details_add_button_clicked_cb (
360 GtkButton *button, gpointer user_data)
361{
362 /* FIXME: add a row to the details list. Disabled at the moment, since
363 * metadata type selection is not implemented.
364 */
365}
366
367void
368GNUNET_GTK_namespace_manager_namespace_details_delete_button_clicked_cb (
369 GtkButton *button, gpointer user_data)
370{
371 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
372 GtkTreeIter iter;
373
374 if (FALSE == gtk_tree_selection_get_selected (ctx->ns_details_sel, NULL, &iter))
375 return;
376
377 gtk_list_store_remove (ctx->ns_details_store, &iter);
378 gtk_widget_set_sensitive (ctx->details_apply_button, TRUE);
379}
380
381void
382GNUNET_GTK_namespace_manager_namespace_details_apply_button_clicked_cb (
383 GtkButton *button, gpointer user_data)
384{
385 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
386 GtkTreeIter iter, known_iter;
387 gint i;
388 gint row_count;
389 struct GNUNET_CONTAINER_MetaData *md, *old_md;
390 char *plugin_name;
391 int type;
392 char *type_name;
393 int format;
394 char *data_mime_type;
395 char *data;
396
397 row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (
398 ctx->ns_details_store), NULL);
399 if ((row_count > 0) && (TRUE != gtk_tree_model_get_iter_first (
400 GTK_TREE_MODEL (ctx->ns_details_store), &iter)))
401 {
402 /* This should not happen */
403 return;
404 }
405
406 if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL,
407 &known_iter))
408 {
409 /* This should not happen */
410 return;
411 }
412
413 md = GNUNET_CONTAINER_meta_data_create ();
414
415 for (i = 0; i < row_count; i++)
416 {
417 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_details_store), &iter,
418 GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN, &plugin_name,
419 GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN, &type,
420 GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, &type_name,
421 GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN, &format,
422 GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN, &data_mime_type,
423 GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, &data,
424 -1);
425 GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
426 type, format, data_mime_type, data, strlen (data) + 1);
427 g_free (plugin_name);
428 g_free (type_name);
429 g_free (data_mime_type);
430 g_free (data);
431 if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL (
432 ctx->ns_details_store), &iter))
433 break;
434 }
435 GNUNET_CONTAINER_meta_data_merge (md,
436 (const struct GNUNET_CONTAINER_MetaData *) ctx->uneditable_md);
437
438 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &known_iter,
439 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &old_md,
440 -1);
441 GNUNET_CONTAINER_meta_data_destroy (old_md);
442 gtk_list_store_set (ctx->known_ns_store, &known_iter,
443 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, md,
444 -1);
445 gtk_widget_set_sensitive (ctx->details_apply_button, FALSE);
446}
447
448void
449GNUNET_GTK_namespace_manager_name_text_editing_started_cb (
450 GtkCellRenderer *renderer, GtkCellEditable *editable, gchar *path,
451 gpointer user_data)
452{
453 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
454
455 if (GTK_IS_ENTRY (editable))
456 {
457 GtkTreePath *tree_path;
458 GtkTreeIter iter;
459 char *non_unique_name = NULL;
460 GtkEntry *entry = GTK_ENTRY (editable);
461
462 tree_path = gtk_tree_path_new_from_string (path);
463 if (tree_path != NULL)
464 {
465 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->known_ns_store),
466 &iter, tree_path))
467 {
468 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
469 GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, &non_unique_name,
470 -1);
471 }
472 gtk_tree_path_free (tree_path);
473 }
474 if (non_unique_name == NULL)
475 {
476 gtk_cell_editable_editing_done (editable);
477 return;
478 }
479 gtk_entry_set_text (entry, non_unique_name);
480 g_free (non_unique_name);
481 }
482}
483
484void
485GNUNET_GTK_namespace_manager_name_text_edited_cb (
486 GtkCellRendererText *renderer, gchar *path, gchar *new_text,
487 gpointer user_data)
488{
489 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
490 char *unique_name;
491 GtkTreeRowReference *order_row;
492
493 if (strlen (new_text) == 0)
494 return;
495
496 GtkTreePath *tree_path;
497 GtkTreeIter iter;
498 tree_path = gtk_tree_path_new_from_string (path);
499 if (tree_path != NULL)
500 {
501 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->known_ns_store),
502 &iter, tree_path))
503 {
504 GNUNET_HashCode *nsid;
505 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
506 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid,
507 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row,
508 -1);
509
510 unique_name = GNUNET_PSEUDONYM_name_uniquify (
511 GNUNET_FS_GTK_get_configuration (), nsid, new_text, NULL);
512
513 gtk_list_store_set (ctx->known_ns_store, &iter,
514 GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, new_text,
515 GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, unique_name,
516 -1);
517
518 if (order_row != NULL)
519 {
520 GtkTreeIter order_iter;
521 if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter))
522 {
523 gtk_list_store_set (ctx->ns_order_store, &order_iter,
524 GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, unique_name,
525 -1);
526 }
527 }
528
529 GNUNET_free (unique_name);
530 }
531 gtk_tree_path_free (tree_path);
532 }
533}
534
535void
536GNUNET_GTK_namespace_manager_namespace_details_type_text_edited_cb (
537 GtkCellRendererText *renderer, gchar *path, gchar *new_text,
538 gpointer user_data)
539{
540 /* Changing metadata type is more difficult than simply entering a
541 * new string, see publication editing dialog. So this is disabled
542 * for now. In fact, it's not going to be a Text renderer when it's done.
543 */
544 /*
545 struct GNUNET_GTK_NamespaceManagerContext *ctx = cls;
546 GtkTreeIter iter;
547 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->ns_details_store),
548 &iter, path))
549 {
550 gtk_list_store_set (ctx->ns_details_store, &iter,
551 GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, new_text,
552 -1);
553 }
554 */
555}
556
557void
558GNUNET_GTK_namespace_manager_namespace_details_value_text_edited_cb (
559 GtkCellRendererText *renderer, gchar *path, gchar *new_text,
560 gpointer user_data)
561{
562 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
563 GtkTreePath *tree_path;
564 GtkTreeIter iter;
565 tree_path = gtk_tree_path_new_from_string (path);
566 if (tree_path != NULL)
567 {
568 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ctx->ns_details_store),
569 &iter, tree_path))
570 {
571 char *old_text;
572 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_details_store), &iter,
573 GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, &old_text,
574 -1);
575 if (strcmp (old_text, new_text) != 0)
576 {
577 gtk_list_store_set (ctx->ns_details_store, &iter,
578 GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, new_text,
579 -1);
580 gtk_widget_set_sensitive (ctx->details_apply_button, TRUE);
581 }
582 g_free (old_text);
583 }
584 gtk_tree_path_free (tree_path);
585 }
586}
587
588/**
589 * Iterator over all known pseudonyms.
590 * Populate "known ns" and "ns order" lists.
591 *
592 * @param cls closure
593 * @param pseudonym hash code of public key of pseudonym
594 * @param md meta data known about the pseudonym
595 * @param rating the local rating of the pseudonym
596 * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
597 */
598static int
599populate_known_ns_list (void *cls, const GNUNET_HashCode *pseudonym,
600 const char *name, const char *unique_name,
601 const struct GNUNET_CONTAINER_MetaData *md, int rating)
602{
603 struct GNUNET_GTK_NamespaceManagerContext *ctx = cls;
604 GNUNET_HashCode *nsid;
605 struct GNUNET_CRYPTO_HashAsciiEncoded identifier;
606 GtkTreeIter known_iter, order_iter;
607 struct GNUNET_CONTAINER_MetaData *md_copy;
608 char *non_null_name, *non_null_unique_name;
609
610 nsid = GNUNET_malloc (sizeof (GNUNET_HashCode));
611 *nsid = *pseudonym;
612
613 GNUNET_CRYPTO_hash_to_enc (nsid, &identifier);
614
615 GNUNET_PSEUDONYM_get_info (GNUNET_FS_GTK_get_configuration (),
616 nsid, NULL, NULL, &non_null_name, NULL);
617 non_null_unique_name = GNUNET_PSEUDONYM_name_uniquify (
618 GNUNET_FS_GTK_get_configuration (), nsid, non_null_name, NULL);
619
620 md_copy = GNUNET_CONTAINER_meta_data_duplicate (md);
621
622 gtk_list_store_insert_with_values (ctx->known_ns_store, &known_iter, G_MAXINT,
623 GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN, FALSE,
624 GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, rating,
625 GNUNET_GTK_KNOWN_NAMESPACES_NAME_COLUMN, non_null_unique_name,
626 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_COLUMN, identifier.encoding,
627 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, nsid,
628 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, NULL,
629 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, md_copy,
630 GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, non_null_name,
631 -1);
632
633 if (rating >= 0)
634 {
635 GtkTreeRowReference *rr = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (
636 ctx->known_ns_store), &known_iter);
637 gtk_list_store_insert_with_values (ctx->ns_order_store, &order_iter, G_MAXINT,
638 GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN, rating,
639 GNUNET_GTK_NAMESPACE_ORDER_NAME_COLUMN, non_null_unique_name,
640 GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_COLUMN, identifier.encoding,
641 GNUNET_GTK_NAMESPACE_ORDER_IDENTIFIER_BIN_COLUMN, nsid,
642 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, rr,
643 -1);
644 rr = GNUNET_GTK_get_reference_from_iter (GTK_TREE_MODEL (ctx->ns_order_store),
645 &order_iter);
646 gtk_list_store_set (ctx->known_ns_store, &known_iter,
647 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, rr, -1);
648 }
649 GNUNET_free (non_null_name);
650 GNUNET_free (non_null_unique_name);
651
652 return GNUNET_OK;
653}
654
655static void
656apply_known_ns_changes (struct GNUNET_GTK_NamespaceManagerContext *ctx)
657{
658 GtkTreeIter iter;
659 gint i;
660 gint row_count;
661 GNUNET_HashCode *nsid;
662 char *name;
663 int32_t rank;
664 struct GNUNET_CONTAINER_MetaData *md;
665
666 row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (
667 ctx->known_ns_store), NULL);
668 if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
669 ctx->known_ns_store), &iter))
670 return;
671
672 for (i = 0; i < row_count; i++)
673 {
674 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
675 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid,
676 GNUNET_GTK_KNOWN_NAMESPACES_NON_UNIQUE_NAME_COLUMN, &name,
677 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md,
678 GNUNET_GTK_KNOWN_NAMESPACES_RANK_COLUMN, &rank,
679 -1);
680 GNUNET_PSEUDONYM_set_info (GNUNET_FS_GTK_get_configuration (),
681 nsid, name, md, rank);
682 g_free (name);
683 if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL (
684 ctx->known_ns_store), &iter))
685 break;
686 }
687}
688
689static void
690free_lists_contents (struct GNUNET_GTK_NamespaceManagerContext *ctx)
691{
692 GtkTreeIter iter;
693 gint i;
694 gint row_count;
695 GNUNET_HashCode *nsid;
696 GtkTreeRowReference *order_row;
697 struct GNUNET_CONTAINER_MetaData *md;
698
699 row_count = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (
700 ctx->known_ns_store), NULL);
701 if (TRUE != gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
702 ctx->known_ns_store), &iter))
703 return;
704
705 for (i = 0; i < row_count; i++)
706 {
707 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
708 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &nsid,
709 GNUNET_GTK_KNOWN_NAMESPACES_ORDER_ROW_REFERENCE_COLUMN, &order_row,
710 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md,
711 -1);
712 if (order_row != NULL)
713 {
714 GtkTreeIter order_iter;
715 if (GNUNET_OK == GNUNET_GTK_get_iter_from_reference (order_row, &order_iter))
716 {
717 GtkTreeRowReference *known_row;
718 gtk_tree_model_get (GTK_TREE_MODEL (ctx->ns_order_store), &order_iter,
719 GNUNET_GTK_NAMESPACE_ORDER_KNOWN_ROW_REFERENCE_COLUMN, &known_row,
720 -1);
721 if (known_row != NULL)
722 gtk_tree_row_reference_free (known_row);
723 }
724 gtk_tree_row_reference_free (order_row);
725 }
726 GNUNET_CONTAINER_meta_data_destroy (md);
727 GNUNET_free (nsid);
728 if (TRUE != gtk_tree_model_iter_next (GTK_TREE_MODEL (
729 ctx->known_ns_store), &iter))
730 break;
731 }
732
733 gtk_list_store_clear (ctx->ns_order_store);
734 gtk_list_store_clear (ctx->known_ns_store);
735 gtk_list_store_clear (ctx->ns_details_store);
736 if (ctx->uneditable_md != NULL)
737 GNUNET_CONTAINER_meta_data_destroy (ctx->uneditable_md);
738}
739
740void
741GNUNET_GTK_namespace_manager_dialog_response_cb (GtkDialog *dialog,
742 gint response_id, gpointer user_data)
743{
744 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
745 switch (response_id)
746 {
747 case GTK_RESPONSE_APPLY:
748 case GTK_RESPONSE_OK:
749 apply_known_ns_changes (ctx);
750 break;
751 default:
752 break;
753 }
754 switch (response_id)
755 {
756 case GTK_RESPONSE_APPLY:
757 break;
758 case GTK_RESPONSE_OK:
759 case GTK_RESPONSE_CANCEL:
760 default:
761 free_lists_contents (ctx);
762 gtk_widget_destroy (GTK_WIDGET (ctx->namespace_manager));
763 GNUNET_free (ctx);
764 ns_manager = NULL;
765 }
766}
767
768
769static gboolean
770mark_as_mine (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
771 gpointer data)
772{
773 const GNUNET_HashCode *mine_id = data;
774 const GNUNET_HashCode *ns_id;
775
776 gtk_tree_model_get (model, iter,
777 GNUNET_GTK_KNOWN_NAMESPACES_IDENTIFIER_BIN_COLUMN, &ns_id, -1);
778
779 if (memcmp (ns_id, mine_id, sizeof (GNUNET_HashCode)) != 0)
780 return FALSE;
781
782 gtk_list_store_set (GTK_LIST_STORE (model), iter,
783 GNUNET_GTK_KNOWN_NAMESPACES_IS_MINE_COLUMN, TRUE, -1);
784 return TRUE;
785}
786
787/**
788 * Callback with information about local (!) namespaces.
789 * Contains the names of the local namespace and the global
790 * ID.
791 *
792 * @param cls closure
793 * @param name human-readable identifier of the namespace
794 * @param id hash identifier for the namespace
795 */
796static void
797mark_namespaces_as_mine (void *cls, const char *name,
798 const GNUNET_HashCode * id)
799{
800 struct GNUNET_GTK_NamespaceManagerContext *ctx = cls;
801
802 gtk_tree_model_foreach (GTK_TREE_MODEL (ctx->known_ns_store), mark_as_mine,
803 (gpointer) id);
804}
805
806/**
807 * Type of a function that libextractor calls for each
808 * meta data item found.
809 *
810 * @param cls closure (user-defined)
811 * @param plugin_name name of the plugin that produced this value;
812 * special values can be used (i.e. '&lt;zlib&gt;' for zlib being
813 * used in the main libextractor library and yielding
814 * meta data).
815 * @param type libextractor-type describing the meta data
816 * @param format basic format information about data
817 * @param data_mime_type mime-type of data (not of the original file);
818 * can be NULL (if mime-type is not known)
819 * @param data actual meta-data found
820 * @param data_len number of bytes in data
821 * @return 0 to continue extracting, 1 to abort
822 */
823static int
824populate_details_list (void *cls, const char *plugin_name,
825 enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format,
826 const char *data_mime_type, const char *data, size_t data_len)
827{
828 struct GNUNET_GTK_NamespaceManagerContext *ctx = cls;
829 const char *type_name;
830 char *data_utf8;
831
832 if (format == EXTRACTOR_METAFORMAT_UTF8 ||
833 format == EXTRACTOR_METAFORMAT_C_STRING)
834 {
835 type_name = EXTRACTOR_metatype_to_string (type);
836 /* TODO: translate type_name using dgettext? */
837 data_utf8 = GNUNET_FS_GTK_dubious_meta_to_utf8 (format, data, data_len);
838 if (data != NULL)
839 {
840 gtk_list_store_insert_with_values (ctx->ns_details_store, NULL, G_MAXINT,
841 GNUNET_GTK_NAMESPACE_DETAILS_PLUGIN_NAME_COLUMN, plugin_name,
842 GNUNET_GTK_NAMESPACE_DETAILS_TYPE_BIN_COLUMN, type,
843 GNUNET_GTK_NAMESPACE_DETAILS_TYPE_COLUMN, type_name,
844 GNUNET_GTK_NAMESPACE_DETAILS_FORMAT_COLUMN,
845 EXTRACTOR_METAFORMAT_UTF8,
846 GNUNET_GTK_NAMESPACE_DETAILS_DATA_MIME_COLUMN, data_mime_type,
847 GNUNET_GTK_NAMESPACE_DETAILS_VALUE_COLUMN, data_utf8,
848 -1);
849 GNUNET_free (data_utf8);
850 return 0;
851 }
852 }
853 GNUNET_CONTAINER_meta_data_insert (ctx->uneditable_md,
854 plugin_name, type, format, data_mime_type, data, data_len);
855 return 0;
856}
857
858static void
859ns_details_selection_changed (GtkTreeSelection *treeselection,
860 gpointer user_data)
861{
862 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
863 GtkTreeIter iter;
864
865 if (FALSE == gtk_tree_selection_get_selected (ctx->ns_details_sel, NULL, &iter))
866 {
867 gtk_widget_set_sensitive (ctx->details_delete_button, FALSE);
868 return;
869 }
870
871 gtk_widget_set_sensitive (ctx->details_delete_button, TRUE);
872}
873
874static void
875known_ns_selection_changed (GtkTreeSelection *treeselection,
876 gpointer user_data)
877{
878 struct GNUNET_GTK_NamespaceManagerContext *ctx = user_data;
879 GtkTreeIter iter;
880 const struct GNUNET_CONTAINER_MetaData *md;
881
882 if (FALSE == gtk_tree_selection_get_selected (ctx->known_ns_sel, NULL, &iter))
883 return;
884
885 gtk_tree_model_get (GTK_TREE_MODEL (ctx->known_ns_store), &iter,
886 GNUNET_GTK_KNOWN_NAMESPACES_METADATA_COLUMN, &md,
887 -1);
888 if (ctx->uneditable_md != NULL)
889 GNUNET_CONTAINER_meta_data_clear (ctx->uneditable_md);
890 else
891 ctx->uneditable_md = GNUNET_CONTAINER_meta_data_create ();
892 gtk_list_store_clear (ctx->ns_details_store);
893 gtk_widget_set_sensitive (ctx->details_apply_button, FALSE);
894 GNUNET_CONTAINER_meta_data_iterate ((const struct GNUNET_CONTAINER_MetaData *) md,
895 populate_details_list, ctx);
896 gtk_widget_set_sensitive (ctx->details_apply_button, FALSE);
897}
898
899void
900GNUNET_GTK_namespace_manager_open ()
901{
902 struct GNUNET_GTK_NamespaceManagerContext *ctx;
903
904 if (ns_manager != NULL)
905 return;
906
907 ctx = GNUNET_malloc (sizeof (struct GNUNET_GTK_NamespaceManagerContext));
908 ctx->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_namespace_manager.glade", ctx);
909 if (ctx->builder == NULL)
910 {
911 GNUNET_break (0);
912 GNUNET_free (ctx);
913 return;
914 }
915
916 /* initialize widget references */
917 ctx->known_ns = GTK_WIDGET (gtk_builder_get_object (ctx->builder,
918 "GNUNET_GTK_namespace_manager_known_treeview"));
919 ctx->ns_order = GTK_WIDGET (gtk_builder_get_object (ctx->builder,
920 "GNUNET_GTK_namespace_manager_namespace_order_treeview"));
921 ctx->ns_details = GTK_WIDGET (gtk_builder_get_object (ctx->builder,
922 "GNUNET_GTK_namespace_manager_namespace_details_treeview"));
923 ctx->known_ns_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (
924 ctx->known_ns));
925 ctx->ns_order_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (
926 ctx->ns_order));
927 ctx->ns_details_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (
928 ctx->ns_details));
929 ctx->ns_order_store = GTK_LIST_STORE (gtk_tree_view_get_model (
930 GTK_TREE_VIEW (ctx->ns_order)));
931 ctx->known_ns_store = GTK_LIST_STORE (gtk_tree_view_get_model (
932 GTK_TREE_VIEW (ctx->known_ns)));
933 ctx->ns_details_store = GTK_LIST_STORE (gtk_tree_view_get_model (
934 GTK_TREE_VIEW (ctx->ns_details)));
935 ctx->namespace_manager = GTK_WINDOW (gtk_builder_get_object (
936 ctx->builder, "GNUNET_GTK_namespace_manager_dialog"));
937 ctx->details_apply_button = GTK_WIDGET (gtk_builder_get_object (ctx->builder,
938 "GNUNET_GTK_namespace_manager_namespace_details_apply_button"));
939 ctx->details_delete_button = GTK_WIDGET (gtk_builder_get_object (ctx->builder,
940 "GNUNET_GTK_namespace_manager_namespace_details_delete_button"));
941 ctx->order_rank = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 0);
942 ctx->order_name = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 1);
943 ctx->order_id = gtk_tree_view_get_column (GTK_TREE_VIEW (ctx->ns_order), 2);
944
945 /* connect signals; FIXME-GTK3: these could be connected with (modern) Glade */
946 g_signal_connect (G_OBJECT (ctx->known_ns_sel), "changed",
947 G_CALLBACK (known_ns_selection_changed), ctx);
948 g_signal_connect (G_OBJECT (ctx->ns_details_sel), "changed",
949 G_CALLBACK (ns_details_selection_changed), ctx);
950
951 /* populate namespace model */
952 (void) GNUNET_PSEUDONYM_list_all (GNUNET_FS_GTK_get_configuration (),
953 populate_known_ns_list, ctx);
954
955 /* mark our own namespaces as such */
956 GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (),
957 mark_namespaces_as_mine, ctx);
958
959 /* sort namespace order list by rank (initially) */
960 sort_order_list (ctx, GNUNET_GTK_NAMESPACE_ORDER_RANK_COLUMN);
961
962 ns_manager = ctx;
963
964 gtk_widget_set_sensitive (ctx->details_apply_button, FALSE);
965
966 /* show dialog */
967 gtk_window_present (GTK_WINDOW (ctx->namespace_manager));
968}
969
970/* end of gnunet-fs-gtk_namespace_manager.c */