diff options
Diffstat (limited to 'src/fs/gnunet-fs-gtk_publish-dialog.c')
-rw-r--r-- | src/fs/gnunet-fs-gtk_publish-dialog.c | 1596 |
1 files changed, 1596 insertions, 0 deletions
diff --git a/src/fs/gnunet-fs-gtk_publish-dialog.c b/src/fs/gnunet-fs-gtk_publish-dialog.c new file mode 100644 index 00000000..1dd67f62 --- /dev/null +++ b/src/fs/gnunet-fs-gtk_publish-dialog.c | |||
@@ -0,0 +1,1596 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2005, 2006, 2010 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_publish-dialog.c | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "gnunet-fs-gtk-common.h" | ||
26 | #include "gnunet-fs-gtk.h" | ||
27 | #include "gnunet-fs-gtk-edit_publish_dialog.h" | ||
28 | #include <gnunet/gnunet_util_lib.h> | ||
29 | #include <gnunet/gnunet_fs_service.h> | ||
30 | |||
31 | #define MARKER_DIR_FILE_SIZE "-" | ||
32 | |||
33 | #define VERBOSE_PROGRESS GNUNET_NO | ||
34 | |||
35 | struct AddDirClientContext; | ||
36 | |||
37 | struct MainPublishingDialogContext | ||
38 | { | ||
39 | GtkBuilder *builder; | ||
40 | GtkBuilder *main_window_builder; | ||
41 | GtkTreeView *pseudonym_treeview; | ||
42 | GtkTreeSelection *pseudonym_selection; | ||
43 | GtkTreeModel *pseudonym_treemodel; | ||
44 | GtkWidget *up_button; | ||
45 | GtkWidget *down_button; | ||
46 | GtkWidget *left_button; | ||
47 | GtkWidget *right_button; | ||
48 | GtkWidget *delete_button; | ||
49 | GtkWidget *edit_button; | ||
50 | GtkWidget *execute_button; | ||
51 | GtkWidget *cancel_button; | ||
52 | GtkTreeView *file_info_treeview; | ||
53 | GtkTreeSelection *file_info_selection; | ||
54 | GtkTreeModel *file_info_treemodel; | ||
55 | GtkWindow *master_pubdialog; | ||
56 | |||
57 | gulong open_directory_handler_id; | ||
58 | GtkBuilder *open_directory_builder; | ||
59 | |||
60 | gulong open_file_handler_id; | ||
61 | GtkBuilder *open_file_builder; | ||
62 | |||
63 | /* To keep multiple scanners running */ | ||
64 | struct AddDirClientContext *adddir_head; | ||
65 | struct AddDirClientContext *adddir_tail; | ||
66 | }; | ||
67 | |||
68 | /* One of these is kept for every directory being opened */ | ||
69 | struct AddDirClientContext | ||
70 | { | ||
71 | struct AddDirClientContext *prev; | ||
72 | struct AddDirClientContext *next; | ||
73 | |||
74 | struct GNUNET_FS_ProcessMetadataContext *pmc; | ||
75 | |||
76 | struct MainPublishingDialogContext *ctx; | ||
77 | struct GNUNET_FS_DirScanner *ds; | ||
78 | |||
79 | struct GNUNET_FS_ShareTreeItem *directory_scan_result; | ||
80 | |||
81 | struct GNUNET_FS_BlockOptions directory_scan_bo; | ||
82 | int directory_scan_do_index; | ||
83 | |||
84 | GtkBuilder *progress_dialog_builder; | ||
85 | GtkWidget *progress_dialog; | ||
86 | GtkProgressBar *progress_dialog_bar; | ||
87 | GtkButton *progress_dialog_cancel; | ||
88 | GtkTextView *progress_dialog_textview; | ||
89 | GtkTextBuffer *progress_dialog_textbuffer; | ||
90 | GtkTextMark *progress_dialog_textmark; | ||
91 | GtkAdjustment *textview_vertial_adjustment; | ||
92 | |||
93 | unsigned int done; | ||
94 | unsigned int total; | ||
95 | }; | ||
96 | |||
97 | |||
98 | static void | ||
99 | selection_changed_cb (GtkTreeSelection * ts, struct MainPublishingDialogContext *ctx); | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Check if two GtkTreeIters refer to the same element. | ||
104 | * | ||
105 | * @param tm tree model of the iterators | ||
106 | * @param i1 first iterator | ||
107 | * @param i2 second iterator | ||
108 | * @return GNUNET_YES if they are equal | ||
109 | */ | ||
110 | static int | ||
111 | gtk_tree_iter_equals (GtkTreeModel * tm, GtkTreeIter * i1, GtkTreeIter * i2) | ||
112 | { | ||
113 | GtkTreePath *p1; | ||
114 | GtkTreePath *p2; | ||
115 | int ret; | ||
116 | |||
117 | p1 = gtk_tree_model_get_path (tm, i1); | ||
118 | p2 = gtk_tree_model_get_path (tm, i2); | ||
119 | ret = gtk_tree_path_compare (p1, p2); | ||
120 | gtk_tree_path_free (p1); | ||
121 | gtk_tree_path_free (p2); | ||
122 | return (0 == ret) ? GNUNET_YES : GNUNET_NO; | ||
123 | } | ||
124 | |||
125 | /* Fill out the main publishing dialog context structure */ | ||
126 | static void | ||
127 | init_ctx (struct MainPublishingDialogContext *ctx) | ||
128 | { | ||
129 | ctx->pseudonym_treeview = GTK_TREE_VIEW (gtk_builder_get_object | ||
130 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_pseudonym_tree_view")); | ||
131 | |||
132 | ctx->up_button = GTK_WIDGET (gtk_builder_get_object | ||
133 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_up_button")); | ||
134 | ctx->down_button = GTK_WIDGET (gtk_builder_get_object | ||
135 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_down_button")); | ||
136 | ctx->left_button = GTK_WIDGET (gtk_builder_get_object | ||
137 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_left_button")); | ||
138 | ctx->right_button = GTK_WIDGET (gtk_builder_get_object | ||
139 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_right_button")); | ||
140 | ctx->delete_button = GTK_WIDGET (gtk_builder_get_object | ||
141 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_delete_button")); | ||
142 | ctx->edit_button = GTK_WIDGET (gtk_builder_get_object | ||
143 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_edit_button")); | ||
144 | ctx->execute_button = GTK_WIDGET (gtk_builder_get_object | ||
145 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_execute_button")); | ||
146 | ctx->cancel_button = GTK_WIDGET (gtk_builder_get_object | ||
147 | (ctx->builder , "GNUNET_GTK_master_publish_dialog_cancel_button")); | ||
148 | ctx->file_info_treeview = GTK_TREE_VIEW (gtk_builder_get_object | ||
149 | (ctx->builder, "GNUNET_GTK_master_publish_dialog_file_information_tree_view")); | ||
150 | |||
151 | ctx->master_pubdialog = | ||
152 | GTK_WINDOW (gtk_builder_get_object | ||
153 | (ctx->builder, "GNUNET_GTK_master_publish_dialog")); | ||
154 | |||
155 | ctx->file_info_selection = gtk_tree_view_get_selection (ctx->file_info_treeview); | ||
156 | ctx->file_info_treemodel = gtk_tree_view_get_model (ctx->file_info_treeview); | ||
157 | ctx->pseudonym_selection = gtk_tree_view_get_selection (ctx->pseudonym_treeview); | ||
158 | ctx->pseudonym_treemodel = gtk_tree_view_get_model (ctx->pseudonym_treeview); | ||
159 | |||
160 | g_signal_connect (G_OBJECT (ctx->file_info_selection), "changed", | ||
161 | G_CALLBACK (selection_changed_cb), ctx); | ||
162 | g_signal_connect (G_OBJECT (ctx->pseudonym_selection), "changed", | ||
163 | G_CALLBACK (selection_changed_cb), ctx); | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Update selectivity in the master dialog. | ||
168 | */ | ||
169 | static void | ||
170 | update_selectivity (struct MainPublishingDialogContext *ctx) | ||
171 | { | ||
172 | GtkTreeIter iter; | ||
173 | GtkTreeIter parent; | ||
174 | GtkTreeIter pred; | ||
175 | int is_dir; | ||
176 | struct GNUNET_FS_FileInformation *fip; | ||
177 | int ns_ok; | ||
178 | gchar *namespace_id; | ||
179 | |||
180 | ns_ok = GNUNET_YES; | ||
181 | if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection, NULL, &iter)) | ||
182 | { | ||
183 | gtk_tree_model_get (ctx->pseudonym_treemodel, &iter, 2, &namespace_id, -1); | ||
184 | if (namespace_id == NULL) | ||
185 | ns_ok = GNUNET_NO; | ||
186 | else | ||
187 | g_free (namespace_id); | ||
188 | } | ||
189 | /* Don't let the user close the dialog until all scanners are finished and | ||
190 | * their windows are closed | ||
191 | */ | ||
192 | if ((gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter)) | ||
193 | && (ns_ok == GNUNET_YES) && ctx->adddir_head == NULL) | ||
194 | gtk_widget_set_sensitive (ctx->execute_button, TRUE); | ||
195 | else | ||
196 | gtk_widget_set_sensitive (ctx->execute_button, FALSE); | ||
197 | if (ctx->adddir_head == NULL) | ||
198 | gtk_widget_set_sensitive (ctx->cancel_button, TRUE); | ||
199 | else | ||
200 | gtk_widget_set_sensitive (ctx->cancel_button, FALSE); | ||
201 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
202 | { | ||
203 | gtk_widget_set_sensitive (ctx->up_button, FALSE); | ||
204 | gtk_widget_set_sensitive (ctx->down_button, FALSE); | ||
205 | gtk_widget_set_sensitive (ctx->left_button, FALSE); | ||
206 | gtk_widget_set_sensitive (ctx->right_button, FALSE); | ||
207 | gtk_widget_set_sensitive (ctx->delete_button, FALSE); | ||
208 | gtk_widget_set_sensitive (ctx->edit_button, FALSE); | ||
209 | return; | ||
210 | } | ||
211 | gtk_widget_set_sensitive (ctx->delete_button, TRUE); | ||
212 | gtk_widget_set_sensitive (ctx->edit_button, TRUE); | ||
213 | |||
214 | /* now figure out which move operations are currently legal */ | ||
215 | GNUNET_assert (TRUE == gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)); | ||
216 | if (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter)) | ||
217 | { | ||
218 | gtk_widget_set_sensitive (ctx->down_button, TRUE); | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | gtk_widget_set_sensitive (ctx->down_button, FALSE); | ||
223 | } | ||
224 | GNUNET_assert (TRUE == gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)); | ||
225 | if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent, &iter)) | ||
226 | { | ||
227 | gtk_widget_set_sensitive (ctx->left_button, TRUE); | ||
228 | GNUNET_assert (TRUE == gtk_tree_model_iter_children (ctx->file_info_treemodel, &pred, &parent)); | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | gtk_widget_set_sensitive (ctx->left_button, FALSE); | ||
233 | GNUNET_assert (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &pred)); | ||
234 | } | ||
235 | /* iterate over 'next' of pred to find out if our | ||
236 | * predecessor is a directory! */ | ||
237 | is_dir = GNUNET_SYSERR; | ||
238 | while (GNUNET_YES != gtk_tree_iter_equals (ctx->file_info_treemodel, &pred, &iter)) | ||
239 | { | ||
240 | gtk_tree_model_get (ctx->file_info_treemodel, &pred, 5, &fip, -1); | ||
241 | is_dir = GNUNET_FS_file_information_is_directory (fip); | ||
242 | GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &pred)); | ||
243 | } | ||
244 | if (GNUNET_YES == is_dir) | ||
245 | { | ||
246 | gtk_widget_set_sensitive (ctx->right_button, TRUE); | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | gtk_widget_set_sensitive (ctx->right_button, FALSE); | ||
251 | } | ||
252 | if (GNUNET_SYSERR != is_dir) | ||
253 | { | ||
254 | gtk_widget_set_sensitive (ctx->up_button, TRUE); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | gtk_widget_set_sensitive (ctx->up_button, FALSE); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Add an empty directory to the tree model. | ||
265 | * | ||
266 | * @param name name for the directory | ||
267 | * @param bo block options | ||
268 | * @param iter parent entry, or NULL for top-level addition | ||
269 | * @param pos iterator to set to the location of the new element | ||
270 | */ | ||
271 | static void | ||
272 | create_dir_at_iter (struct MainPublishingDialogContext *ctx, const char *name, | ||
273 | const struct GNUNET_FS_BlockOptions *bo, GtkTreeIter * iter, | ||
274 | GtkTreeIter * pos) | ||
275 | { | ||
276 | struct GNUNET_FS_FileInformation *fi; | ||
277 | GtkTreeRowReference *row_reference; | ||
278 | GtkTreePath *path; | ||
279 | struct GNUNET_CONTAINER_MetaData *meta; | ||
280 | |||
281 | meta = GNUNET_CONTAINER_meta_data_create (); | ||
282 | GNUNET_FS_meta_data_make_directory (meta); | ||
283 | GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet-gtk>", | ||
284 | EXTRACTOR_METATYPE_FILENAME, | ||
285 | EXTRACTOR_METAFORMAT_UTF8, "text/plain", | ||
286 | name, strlen (name) + 1); | ||
287 | gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel), pos, iter, NULL); | ||
288 | path = gtk_tree_model_get_path (ctx->file_info_treemodel, pos); | ||
289 | row_reference = gtk_tree_row_reference_new (ctx->file_info_treemodel, path); | ||
290 | gtk_tree_path_free (path); | ||
291 | fi = GNUNET_FS_file_information_create_empty_directory | ||
292 | (GNUNET_FS_GTK_get_fs_handle (), row_reference, NULL, meta, bo, name); | ||
293 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
294 | gtk_tree_store_set (GTK_TREE_STORE (ctx->file_info_treemodel), pos, 0, MARKER_DIR_FILE_SIZE, 1, (gboolean) GNUNET_NO, | ||
295 | 2, name, 3, (guint) bo->anonymity_level, 4, | ||
296 | (guint) bo->content_priority, 5, fi, | ||
297 | 6, (guint64) bo->expiration_time.abs_value, | ||
298 | 7, (guint) bo->replication_level, | ||
299 | -1); | ||
300 | update_selectivity (ctx); | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | selection_changed_cb (GtkTreeSelection * ts, struct MainPublishingDialogContext *ctx) | ||
305 | { | ||
306 | update_selectivity (ctx); | ||
307 | } | ||
308 | |||
309 | static void | ||
310 | remove_old_entry (GtkTreeStore * ts, GtkTreeIter * root) | ||
311 | { | ||
312 | GtkTreeIter child; | ||
313 | |||
314 | while (TRUE == | ||
315 | gtk_tree_model_iter_children (GTK_TREE_MODEL (ts), &child, root)) | ||
316 | remove_old_entry (ts, &child); | ||
317 | gtk_tree_store_remove (ts, root); | ||
318 | } | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Move an entry in the tree. | ||
323 | */ | ||
324 | static void | ||
325 | move_entry (struct MainPublishingDialogContext *ctx, GtkTreeModel * tm, GtkTreeIter * old, | ||
326 | GtkTreeIter * newpos, int dsel) | ||
327 | { | ||
328 | struct GNUNET_FS_FileInformation *fip; | ||
329 | gint do_index; | ||
330 | gchar *short_fn; | ||
331 | guint anonymity_level; | ||
332 | guint priority; | ||
333 | guint replication_level; | ||
334 | guint64 expiration_time_abs; | ||
335 | char *fsf; | ||
336 | GtkTreePath *path; | ||
337 | GtkTreeIter child; | ||
338 | GtkTreeIter cnewpos; | ||
339 | GtkTreeRowReference *rr; | ||
340 | GtkTreeRowReference *rr2; | ||
341 | |||
342 | gtk_tree_model_get (tm, old, 0, &fsf, 1, &do_index, 2, &short_fn, 3, | ||
343 | &anonymity_level, 4, &priority, 5, &fip, | ||
344 | 6, &expiration_time_abs, 7, &replication_level, -1); | ||
345 | gtk_tree_store_set (GTK_TREE_STORE (tm), newpos, 0, fsf, 1, do_index, 2, | ||
346 | short_fn, 3, (guint) anonymity_level, 4, (guint) priority, | ||
347 | 5, fip, | ||
348 | 6, expiration_time_abs, | ||
349 | 7, replication_level, -1); | ||
350 | if (dsel == GNUNET_YES) | ||
351 | { | ||
352 | path = gtk_tree_model_get_path (tm, newpos); | ||
353 | rr = gtk_tree_row_reference_new (tm, path); | ||
354 | gtk_tree_path_free (path); | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | rr = NULL; | ||
359 | } | ||
360 | if (TRUE == gtk_tree_model_iter_children (tm, &child, old)) | ||
361 | { | ||
362 | do | ||
363 | { | ||
364 | path = gtk_tree_model_get_path (tm, &child); | ||
365 | rr2 = gtk_tree_row_reference_new (tm, path); | ||
366 | gtk_tree_path_free (path); | ||
367 | gtk_tree_store_insert_before (GTK_TREE_STORE (tm), &cnewpos, newpos, | ||
368 | NULL); | ||
369 | move_entry (ctx, tm, &child, &cnewpos, GNUNET_NO); | ||
370 | path = gtk_tree_row_reference_get_path (rr2); | ||
371 | gtk_tree_row_reference_free (rr2); | ||
372 | GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, &child, path)); | ||
373 | gtk_tree_path_free (path); | ||
374 | } | ||
375 | while (TRUE == gtk_tree_model_iter_next (tm, &child)); | ||
376 | } | ||
377 | g_free (short_fn); | ||
378 | g_free (fsf); | ||
379 | if (dsel == GNUNET_YES) | ||
380 | { | ||
381 | path = gtk_tree_row_reference_get_path (rr); | ||
382 | gtk_tree_row_reference_free (rr); | ||
383 | gtk_tree_view_expand_to_path (ctx->file_info_treeview, path); | ||
384 | GNUNET_assert (TRUE == gtk_tree_model_get_iter (tm, newpos, path)); | ||
385 | gtk_tree_path_free (path); | ||
386 | gtk_tree_selection_select_iter (ctx->file_info_selection, newpos); | ||
387 | } | ||
388 | update_selectivity (ctx); | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
393 | * User has changed the "current" identifier for the content in | ||
394 | * the GtkTreeView. Update the model. | ||
395 | */ | ||
396 | void GNUNET_GTK_master_publish_dialog_pseudonym_updates_renderer_edited_cb | ||
397 | (GtkCellRendererText * renderer, gchar * cpath, gchar * new_text, | ||
398 | struct MainPublishingDialogContext *ctx) | ||
399 | { | ||
400 | GtkTreeIter iter; | ||
401 | |||
402 | if (TRUE != | ||
403 | gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter, cpath)) | ||
404 | { | ||
405 | GNUNET_break (0); | ||
406 | return; | ||
407 | } | ||
408 | gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 5, new_text, -1); | ||
409 | update_selectivity (ctx); | ||
410 | } | ||
411 | |||
412 | |||
413 | /** | ||
414 | * User has changed the "current" identifier for the content in | ||
415 | * the GtkTreeView. Update the model. | ||
416 | */ | ||
417 | void GNUNET_GTK_master_publish_dialog_pseudonym_identifier_renderer_edited_cb | ||
418 | (GtkCellRendererText * renderer, gchar * cpath, gchar * new_text, | ||
419 | struct MainPublishingDialogContext *ctx) | ||
420 | { | ||
421 | GtkTreeIter iter; | ||
422 | |||
423 | if (TRUE != | ||
424 | gtk_tree_model_get_iter_from_string (ctx->pseudonym_treemodel, &iter, cpath)) | ||
425 | { | ||
426 | GNUNET_break (0); | ||
427 | return; | ||
428 | } | ||
429 | gtk_tree_store_set (GTK_TREE_STORE (ctx->pseudonym_treemodel), &iter, 2, new_text, -1); | ||
430 | update_selectivity (ctx); | ||
431 | } | ||
432 | |||
433 | |||
434 | void | ||
435 | GNUNET_GTK_master_publish_dialog_right_button_clicked_cb (GtkWidget * dummy, | ||
436 | struct MainPublishingDialogContext *ctx) | ||
437 | { | ||
438 | GtkTreeIter iter; | ||
439 | GtkTreeIter parent; | ||
440 | GtkTreeIter pred; | ||
441 | GtkTreeIter prev; | ||
442 | GtkTreeIter pos; | ||
443 | |||
444 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
445 | { | ||
446 | GNUNET_break (0); | ||
447 | return; | ||
448 | } | ||
449 | if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent, &iter)) | ||
450 | { | ||
451 | GNUNET_assert (TRUE == gtk_tree_model_iter_children (ctx->file_info_treemodel, &pred, &parent)); | ||
452 | } | ||
453 | else if (TRUE != gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &pred)) | ||
454 | { | ||
455 | GNUNET_break (0); | ||
456 | return; | ||
457 | } | ||
458 | /* iterate over 'next' of pred to find out who our predecessor is! */ | ||
459 | memset (&prev, 0, sizeof (GtkTreeIter)); | ||
460 | while (GNUNET_YES != gtk_tree_iter_equals (ctx->file_info_treemodel, &pred, &iter)) | ||
461 | { | ||
462 | prev = pred; | ||
463 | GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &pred)); | ||
464 | } | ||
465 | gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel), &pos, &prev, NULL); | ||
466 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
467 | { | ||
468 | GNUNET_break (0); | ||
469 | return; | ||
470 | } | ||
471 | move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES); | ||
472 | remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter); | ||
473 | } | ||
474 | |||
475 | |||
476 | void | ||
477 | GNUNET_GTK_master_publish_dialog_left_button_clicked_cb (GtkWidget * dummy, | ||
478 | struct MainPublishingDialogContext *ctx) | ||
479 | { | ||
480 | GtkTreeIter iter; | ||
481 | GtkTreeIter parent; | ||
482 | GtkTreeIter pos; | ||
483 | |||
484 | |||
485 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
486 | { | ||
487 | GNUNET_break (0); | ||
488 | return; | ||
489 | } | ||
490 | if (TRUE != gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent, &iter)) | ||
491 | { | ||
492 | GNUNET_break (0); | ||
493 | return; | ||
494 | } | ||
495 | gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel), &pos, NULL, &parent); | ||
496 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
497 | { | ||
498 | GNUNET_break (0); | ||
499 | return; | ||
500 | } | ||
501 | move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES); | ||
502 | remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter); | ||
503 | } | ||
504 | |||
505 | |||
506 | void | ||
507 | GNUNET_GTK_master_publish_dialog_up_button_clicked_cb (GtkWidget * dummy, | ||
508 | struct MainPublishingDialogContext *ctx) | ||
509 | { | ||
510 | GtkTreeIter iter; | ||
511 | GtkTreeIter parent; | ||
512 | GtkTreeIter pred; | ||
513 | GtkTreeIter prev; | ||
514 | GtkTreeIter *pprev; | ||
515 | GtkTreeIter pos; | ||
516 | |||
517 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
518 | { | ||
519 | GNUNET_break (0); | ||
520 | return; | ||
521 | } | ||
522 | if (TRUE == gtk_tree_model_iter_parent (ctx->file_info_treemodel, &parent, &iter)) | ||
523 | { | ||
524 | GNUNET_assert (TRUE == gtk_tree_model_iter_children (ctx->file_info_treemodel, &pred, &parent)); | ||
525 | pprev = &parent; | ||
526 | } | ||
527 | else if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &pred)) | ||
528 | { | ||
529 | pprev = NULL; | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | GNUNET_break (0); | ||
534 | return; | ||
535 | } | ||
536 | /* iterate over 'next' of pred to find out who our predecessor is! */ | ||
537 | while (GNUNET_YES != gtk_tree_iter_equals (ctx->file_info_treemodel, &pred, &iter)) | ||
538 | { | ||
539 | prev = pred; | ||
540 | pprev = &prev; | ||
541 | GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &pred)); | ||
542 | } | ||
543 | gtk_tree_store_insert_before (GTK_TREE_STORE (ctx->file_info_treemodel), &pos, NULL, pprev); | ||
544 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
545 | { | ||
546 | GNUNET_break (0); | ||
547 | return; | ||
548 | } | ||
549 | move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES); | ||
550 | remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter); | ||
551 | } | ||
552 | |||
553 | |||
554 | void | ||
555 | GNUNET_GTK_master_publish_dialog_down_button_clicked_cb (GtkWidget * dummy, | ||
556 | struct MainPublishingDialogContext *ctx) | ||
557 | { | ||
558 | GtkTreeIter iter; | ||
559 | GtkTreeIter next; | ||
560 | GtkTreeIter pos; | ||
561 | |||
562 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
563 | { | ||
564 | GNUNET_break (0); | ||
565 | return; | ||
566 | } | ||
567 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &next)) | ||
568 | { | ||
569 | GNUNET_break (0); | ||
570 | return; | ||
571 | } | ||
572 | GNUNET_assert (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &next)); | ||
573 | gtk_tree_store_insert_after (GTK_TREE_STORE (ctx->file_info_treemodel), &pos, NULL, &next); | ||
574 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
575 | { | ||
576 | GNUNET_break (0); | ||
577 | return; | ||
578 | } | ||
579 | move_entry (ctx, ctx->file_info_treemodel, &iter, &pos, GNUNET_YES); | ||
580 | remove_old_entry (GTK_TREE_STORE (ctx->file_info_treemodel), &iter); | ||
581 | } | ||
582 | |||
583 | |||
584 | void | ||
585 | GNUNET_GTK_master_publish_dialog_new_button_clicked_cb (GtkWidget * dummy, | ||
586 | struct MainPublishingDialogContext *ctx) | ||
587 | { | ||
588 | GtkTreeIter iter; | ||
589 | GtkTreeIter pos; | ||
590 | struct GNUNET_FS_BlockOptions bo; | ||
591 | |||
592 | /* FIXME: consider opening a dialog to get | ||
593 | * anonymity, priority and expiration prior | ||
594 | * to calling this function (currently we | ||
595 | * use default values for those). | ||
596 | * Or getting these values from the configuration. | ||
597 | */ | ||
598 | bo.anonymity_level = 1; | ||
599 | bo.content_priority = 1000; | ||
600 | bo.expiration_time = | ||
601 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS); | ||
602 | bo.replication_level = 1; | ||
603 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
604 | { | ||
605 | create_dir_at_iter (ctx, "unnamed/", &bo, NULL, &pos); | ||
606 | return; | ||
607 | } | ||
608 | create_dir_at_iter (ctx, "unnamed/", &bo, &iter, &pos); | ||
609 | } | ||
610 | |||
611 | |||
612 | static void | ||
613 | insert_progress_dialog_text (struct AddDirClientContext *adcc, | ||
614 | const char *text) | ||
615 | { | ||
616 | gtk_text_buffer_insert_at_cursor (adcc->progress_dialog_textbuffer, | ||
617 | text, -1); | ||
618 | gtk_text_view_place_cursor_onscreen (adcc->progress_dialog_textview); | ||
619 | gtk_adjustment_set_value (adcc->textview_vertial_adjustment, | ||
620 | gtk_adjustment_get_upper (adcc->textview_vertial_adjustment)); | ||
621 | } | ||
622 | |||
623 | |||
624 | static void | ||
625 | add_item (struct AddDirClientContext *adcc, GtkTreeStore *ts, | ||
626 | struct GNUNET_FS_ShareTreeItem *item, | ||
627 | GtkTreeIter *parent, | ||
628 | GtkTreeIter *sibling, | ||
629 | GtkTreeIter *item_iter) | ||
630 | { | ||
631 | char *file_size_fancy; | ||
632 | struct GNUNET_FS_FileInformation *fi; | ||
633 | GtkTreeRowReference *row_reference; | ||
634 | GtkTreePath *path; | ||
635 | struct stat sbuf; | ||
636 | |||
637 | if (0 != stat (item->filename, | ||
638 | &sbuf)) | ||
639 | { | ||
640 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "stat", item->filename); | ||
641 | return; | ||
642 | } | ||
643 | |||
644 | gtk_tree_store_insert_after (ts, item_iter, parent, sibling); | ||
645 | path = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), item_iter); | ||
646 | row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), path); | ||
647 | gtk_tree_path_free (path); | ||
648 | |||
649 | if (item->is_directory) | ||
650 | { | ||
651 | if (NULL != item->meta) | ||
652 | GNUNET_CONTAINER_meta_data_delete (item->meta, | ||
653 | EXTRACTOR_METATYPE_MIMETYPE, NULL, 0); | ||
654 | else | ||
655 | item->meta = GNUNET_CONTAINER_meta_data_create (); | ||
656 | GNUNET_FS_meta_data_make_directory (item->meta); | ||
657 | if (NULL == item->ksk_uri) | ||
658 | item->ksk_uri = GNUNET_FS_uri_ksk_create (GNUNET_FS_DIRECTORY_MIME, NULL); | ||
659 | else | ||
660 | GNUNET_FS_uri_ksk_add_keyword (item->ksk_uri, GNUNET_FS_DIRECTORY_MIME, | ||
661 | GNUNET_NO); | ||
662 | fi = GNUNET_FS_file_information_create_empty_directory ( | ||
663 | GNUNET_FS_GTK_get_fs_handle (), row_reference, item->ksk_uri, | ||
664 | item->meta, &adcc->directory_scan_bo, item->filename); | ||
665 | } | ||
666 | else | ||
667 | { | ||
668 | fi = GNUNET_FS_file_information_create_from_file ( | ||
669 | GNUNET_FS_GTK_get_fs_handle (), row_reference, item->filename, | ||
670 | item->ksk_uri, item->meta, adcc->directory_scan_do_index, | ||
671 | &adcc->directory_scan_bo); | ||
672 | } | ||
673 | if (item->is_directory) | ||
674 | file_size_fancy = GNUNET_strdup (MARKER_DIR_FILE_SIZE); | ||
675 | else | ||
676 | file_size_fancy = GNUNET_STRINGS_byte_size_fancy (sbuf.st_size); | ||
677 | |||
678 | gtk_tree_store_set (ts, item_iter, 0, file_size_fancy, | ||
679 | 1, (gboolean) adcc->directory_scan_do_index, | ||
680 | 2, item->short_filename, | ||
681 | 3, (guint) adcc->directory_scan_bo.anonymity_level, | ||
682 | 4, (guint) adcc->directory_scan_bo.content_priority, | ||
683 | 5, fi, | ||
684 | 6, (guint64) adcc->directory_scan_bo.expiration_time.abs_value, | ||
685 | 7, (guint) adcc->directory_scan_bo.replication_level, -1); | ||
686 | GNUNET_free (file_size_fancy); | ||
687 | } | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Traverse the share tree and add it to the tree store | ||
692 | * | ||
693 | */ | ||
694 | static void | ||
695 | add_share_items_to_treestore (struct AddDirClientContext *adcc, | ||
696 | struct GNUNET_FS_ShareTreeItem *toplevel, | ||
697 | GtkTreeIter *parent_iter) | ||
698 | { | ||
699 | struct MainPublishingDialogContext *ctx = adcc->ctx; | ||
700 | GtkTreeStore *ts = GTK_TREE_STORE (ctx->file_info_treemodel); | ||
701 | GtkTreeIter *sibling_iter; | ||
702 | GtkTreeIter last_added; | ||
703 | struct GNUNET_FS_ShareTreeItem *item; | ||
704 | |||
705 | sibling_iter = NULL; | ||
706 | for (item = toplevel; item != NULL; item = item->next) | ||
707 | { | ||
708 | add_item (adcc, ts, item, parent_iter, sibling_iter, &last_added); | ||
709 | sibling_iter = &last_added; | ||
710 | if (item->is_directory) | ||
711 | add_share_items_to_treestore (adcc, | ||
712 | item->children_head, | ||
713 | sibling_iter); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | |||
718 | static void | ||
719 | close_scan (struct AddDirClientContext *adcc) | ||
720 | { | ||
721 | gtk_widget_destroy (adcc->progress_dialog); | ||
722 | g_object_unref (G_OBJECT (adcc->progress_dialog_builder)); | ||
723 | GNUNET_CONTAINER_DLL_remove (adcc->ctx->adddir_head, | ||
724 | adcc->ctx->adddir_tail, | ||
725 | adcc); | ||
726 | update_selectivity (adcc->ctx); | ||
727 | GNUNET_free (adcc); | ||
728 | } | ||
729 | |||
730 | |||
731 | static void | ||
732 | directory_scan_cb (void *cls, | ||
733 | const char *filename, int is_directory, | ||
734 | enum GNUNET_FS_DirScannerProgressUpdateReason reason) | ||
735 | { | ||
736 | static struct GNUNET_TIME_Absolute last_pulse; | ||
737 | struct AddDirClientContext *adcc = cls; | ||
738 | char *s; | ||
739 | gdouble fraction; | ||
740 | |||
741 | switch (reason) | ||
742 | { | ||
743 | case GNUNET_FS_DIRSCANNER_FILE_START: | ||
744 | GNUNET_assert (filename != NULL); | ||
745 | if (GNUNET_TIME_absolute_get_duration (last_pulse).rel_value > 100) | ||
746 | { | ||
747 | gtk_progress_bar_pulse (adcc->progress_dialog_bar); | ||
748 | last_pulse = GNUNET_TIME_absolute_get (); | ||
749 | } | ||
750 | #if VERBOSE_PROGRESS | ||
751 | if (is_directory) | ||
752 | { | ||
753 | GNUNET_asprintf (&s, _("Scanning directory `%s'.\n"), filename); | ||
754 | insert_progress_dialog_text (adcc, s); | ||
755 | GNUNET_free (s); | ||
756 | } | ||
757 | else | ||
758 | adcc->total++; | ||
759 | #else | ||
760 | if (! is_directory) | ||
761 | adcc->total++; | ||
762 | #endif | ||
763 | break; | ||
764 | case GNUNET_FS_DIRSCANNER_FILE_IGNORED: | ||
765 | GNUNET_assert (filename != NULL); | ||
766 | GNUNET_asprintf (&s, | ||
767 | _("Failed to scan `%s' (access error). Skipping.\n"), | ||
768 | filename); | ||
769 | #if ! VERBOSE_PROGRESS | ||
770 | gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (adcc->progress_dialog_builder, | ||
771 | "GNUNET_FS_GTK_progress_dialog_scrolled_window"))); | ||
772 | #endif | ||
773 | insert_progress_dialog_text (adcc, s); | ||
774 | GNUNET_free (s); | ||
775 | break; | ||
776 | case GNUNET_FS_DIRSCANNER_ALL_COUNTED: | ||
777 | fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total; | ||
778 | GNUNET_asprintf (&s, "%u/%u (%3f%%)", | ||
779 | adcc->done, | ||
780 | adcc->total, | ||
781 | 100.0 * fraction); | ||
782 | gtk_progress_bar_set_text (adcc->progress_dialog_bar, | ||
783 | s); | ||
784 | GNUNET_free (s); | ||
785 | gtk_progress_bar_set_fraction (adcc->progress_dialog_bar, | ||
786 | fraction); | ||
787 | break; | ||
788 | case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED: | ||
789 | #if VERBOSE_PROGRESS | ||
790 | GNUNET_asprintf (&s, _("Processed file `%s'.\n"), filename); | ||
791 | insert_progress_dialog_text (adcc, s); | ||
792 | GNUNET_free (s); | ||
793 | #endif | ||
794 | adcc->done++; | ||
795 | GNUNET_assert (adcc->done <= adcc->total); | ||
796 | fraction = (adcc->total == 0) ? 1.0 : (1.0 * adcc->done) / adcc->total; | ||
797 | GNUNET_asprintf (&s, "%u/%u (%3f%%)", | ||
798 | adcc->done, | ||
799 | adcc->total, | ||
800 | 100.0 * fraction); | ||
801 | gtk_progress_bar_set_text (adcc->progress_dialog_bar, | ||
802 | s); | ||
803 | GNUNET_free (s); | ||
804 | gtk_progress_bar_set_fraction (adcc->progress_dialog_bar, | ||
805 | fraction); | ||
806 | break; | ||
807 | case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: | ||
808 | insert_progress_dialog_text (adcc, _("Operation failed (press cancel)\n")); | ||
809 | GNUNET_FS_directory_scan_abort (adcc->ds); | ||
810 | adcc->ds = NULL; | ||
811 | break; | ||
812 | case GNUNET_FS_DIRSCANNER_FINISHED: | ||
813 | insert_progress_dialog_text (adcc, _("Scanner has finished.\n")); | ||
814 | adcc->directory_scan_result = GNUNET_FS_directory_scan_get_result (adcc->ds); | ||
815 | adcc->ds = NULL; | ||
816 | GNUNET_FS_share_tree_trim (adcc->directory_scan_result); | ||
817 | add_share_items_to_treestore (adcc, | ||
818 | adcc->directory_scan_result, | ||
819 | NULL); | ||
820 | GNUNET_FS_share_tree_free (adcc->directory_scan_result); | ||
821 | adcc->directory_scan_result = NULL; | ||
822 | update_selectivity (adcc->ctx); | ||
823 | close_scan (adcc); | ||
824 | break; | ||
825 | default: | ||
826 | GNUNET_break (0); | ||
827 | break; | ||
828 | } | ||
829 | } | ||
830 | |||
831 | |||
832 | static void | ||
833 | scan_file_or_directory (struct MainPublishingDialogContext *ctx, | ||
834 | gchar *filename, | ||
835 | struct GNUNET_FS_BlockOptions *bo, | ||
836 | int do_index) | ||
837 | { | ||
838 | struct AddDirClientContext *adcc; | ||
839 | GtkTextIter iter; | ||
840 | |||
841 | adcc = GNUNET_malloc (sizeof (struct AddDirClientContext)); | ||
842 | adcc->ctx = ctx; | ||
843 | GNUNET_CONTAINER_DLL_insert_tail (ctx->adddir_head, ctx->adddir_tail, adcc); | ||
844 | adcc->ds = GNUNET_FS_directory_scan_start (filename, | ||
845 | GNUNET_NO, NULL, &directory_scan_cb, adcc); | ||
846 | adcc->directory_scan_bo = *bo; | ||
847 | adcc->directory_scan_do_index = do_index; | ||
848 | |||
849 | adcc->progress_dialog_builder = GNUNET_GTK_get_new_builder ( | ||
850 | "gnunet_fs_gtk_progress_dialog.glade", adcc); | ||
851 | adcc->progress_dialog = GTK_WIDGET (gtk_builder_get_object ( | ||
852 | adcc->progress_dialog_builder, | ||
853 | "GNUNET_FS_GTK_progress_dialog")); | ||
854 | adcc->progress_dialog_bar = GTK_PROGRESS_BAR (gtk_builder_get_object ( | ||
855 | adcc->progress_dialog_builder, | ||
856 | "GNUNET_FS_GTK_progress_dialog_progressbar")); | ||
857 | adcc->progress_dialog_cancel = GTK_BUTTON (gtk_builder_get_object ( | ||
858 | adcc->progress_dialog_builder, | ||
859 | "GNUNET_FS_GTK_progress_dialog_cancel_button")); | ||
860 | adcc->progress_dialog_textview = GTK_TEXT_VIEW ( | ||
861 | gtk_builder_get_object (adcc->progress_dialog_builder, | ||
862 | "GNUNET_FS_GTK_progress_dialog_textview")); | ||
863 | adcc->textview_vertial_adjustment = GTK_ADJUSTMENT ( | ||
864 | gtk_builder_get_object (adcc->progress_dialog_builder, | ||
865 | "GNUNET_FS_GTK_progress_dialog_textview_vertical_adjustment")); | ||
866 | adcc->progress_dialog_textbuffer = GTK_TEXT_BUFFER ( | ||
867 | gtk_builder_get_object (adcc->progress_dialog_builder, | ||
868 | "GNUNET_FS_GTK_progress_dialog_textbuffer")); | ||
869 | gtk_text_buffer_get_end_iter (adcc->progress_dialog_textbuffer, | ||
870 | &iter); | ||
871 | adcc->progress_dialog_textmark = gtk_text_buffer_create_mark ( | ||
872 | adcc->progress_dialog_textbuffer, "scroll", | ||
873 | &iter, FALSE); | ||
874 | #if VERBOSE_PROGRESS | ||
875 | gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (adcc->progress_dialog_builder, | ||
876 | "GNUNET_FS_GTK_progress_dialog_scrolled_window"))); | ||
877 | #endif | ||
878 | |||
879 | gtk_window_set_transient_for (GTK_WINDOW (adcc->progress_dialog), adcc->ctx->master_pubdialog); | ||
880 | gtk_window_set_title (GTK_WINDOW (adcc->progress_dialog), filename); | ||
881 | gtk_window_present (GTK_WINDOW (adcc->progress_dialog)); | ||
882 | |||
883 | update_selectivity (ctx); | ||
884 | } | ||
885 | |||
886 | |||
887 | static void | ||
888 | publish_directory_dialog_response_cb (GtkDialog * dialog, | ||
889 | gint response_id, | ||
890 | struct MainPublishingDialogContext *ctx) | ||
891 | { | ||
892 | char *filename; | ||
893 | int do_index; | ||
894 | GtkSpinButton *sb; | ||
895 | struct GNUNET_FS_BlockOptions bo; | ||
896 | GtkWidget *ad; | ||
897 | |||
898 | if (g_signal_handler_is_connected (G_OBJECT (dialog), ctx->open_directory_handler_id)) | ||
899 | g_signal_handler_disconnect (G_OBJECT (dialog), ctx->open_directory_handler_id); | ||
900 | ctx->open_directory_handler_id = 0; | ||
901 | |||
902 | ad = GTK_WIDGET (gtk_builder_get_object | ||
903 | (ctx->open_directory_builder, "GNUNET_GTK_publish_directory_dialog")); | ||
904 | if (response_id == -5) | ||
905 | { | ||
906 | filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (ad)); | ||
907 | sb = GTK_SPIN_BUTTON (gtk_builder_get_object | ||
908 | (ctx->open_directory_builder, | ||
909 | "GNUNET_GTK_publish_directory_dialog_expiration_year_spin_button")); | ||
910 | if (!GNUNET_GTK_get_selected_anonymity_level | ||
911 | (ctx->open_directory_builder, "GNUNET_GTK_publish_directory_dialog_anonymity_combobox", | ||
912 | &bo.anonymity_level)) | ||
913 | bo.anonymity_level = 1; | ||
914 | bo.content_priority = | ||
915 | gtk_spin_button_get_value (GTK_SPIN_BUTTON | ||
916 | (gtk_builder_get_object | ||
917 | (ctx->open_directory_builder, | ||
918 | "GNUNET_GTK_publish_directory_dialog_priority_spin_button"))); | ||
919 | bo.replication_level = | ||
920 | gtk_spin_button_get_value (GTK_SPIN_BUTTON | ||
921 | (gtk_builder_get_object | ||
922 | (ctx->open_directory_builder, | ||
923 | "GNUNET_GTK_publish_directory_dialog_replication_spin_button"))); | ||
924 | bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb); | ||
925 | do_index = | ||
926 | gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON | ||
927 | (gtk_builder_get_object | ||
928 | (ctx->open_directory_builder, | ||
929 | "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton"))); | ||
930 | |||
931 | scan_file_or_directory (ctx, filename, &bo, do_index); | ||
932 | g_free (filename); | ||
933 | } | ||
934 | gtk_widget_destroy (ad); | ||
935 | g_object_unref (G_OBJECT (ctx->open_directory_builder)); | ||
936 | } | ||
937 | |||
938 | |||
939 | static void | ||
940 | publish_file_dialog_response_cb (GtkDialog * dialog, | ||
941 | gint response_id, | ||
942 | struct MainPublishingDialogContext *ctx) | ||
943 | { | ||
944 | char *filename; | ||
945 | struct GNUNET_FS_BlockOptions bo; | ||
946 | int do_index; | ||
947 | GtkSpinButton *sb; | ||
948 | GtkWidget *ad; | ||
949 | |||
950 | if (g_signal_handler_is_connected (G_OBJECT (dialog), ctx->open_file_handler_id)) | ||
951 | g_signal_handler_disconnect (G_OBJECT (dialog), ctx->open_file_handler_id); | ||
952 | ctx->open_file_handler_id = 0; | ||
953 | |||
954 | ad = GTK_WIDGET (gtk_builder_get_object | ||
955 | (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog")); | ||
956 | |||
957 | if (response_id == -5) | ||
958 | { | ||
959 | /* OK */ | ||
960 | sb = GTK_SPIN_BUTTON (gtk_builder_get_object | ||
961 | (ctx->open_file_builder, | ||
962 | "GNUNET_GTK_publish_file_dialog_expiration_year_spin_button")); | ||
963 | |||
964 | if (!GNUNET_GTK_get_selected_anonymity_level | ||
965 | (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog_anonymity_combobox", | ||
966 | &bo.anonymity_level)) | ||
967 | bo.anonymity_level = 1; | ||
968 | bo.content_priority = | ||
969 | gtk_spin_button_get_value (GTK_SPIN_BUTTON | ||
970 | (gtk_builder_get_object | ||
971 | (ctx->open_file_builder, | ||
972 | "GNUNET_GTK_publish_file_dialog_priority_spin_button"))); | ||
973 | bo.expiration_time = GNUNET_FS_GTK_get_expiration_time (sb); | ||
974 | bo.replication_level = | ||
975 | gtk_spin_button_get_value (GTK_SPIN_BUTTON | ||
976 | (gtk_builder_get_object | ||
977 | (ctx->open_file_builder, | ||
978 | "GNUNET_GTK_publish_file_dialog_replication_spin_button"))); | ||
979 | do_index = | ||
980 | gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON | ||
981 | (gtk_builder_get_object | ||
982 | (ctx->open_file_builder, | ||
983 | "GNUNET_GTK_publish_file_dialog_do_index_checkbutton"))); | ||
984 | |||
985 | filename = GNUNET_GTK_filechooser_get_filename_utf8 (GTK_FILE_CHOOSER (ad)); | ||
986 | |||
987 | scan_file_or_directory (ctx, filename, &bo, do_index); | ||
988 | |||
989 | g_free (filename); | ||
990 | } | ||
991 | else | ||
992 | { | ||
993 | /* Cancel/Escape/close/etc */ | ||
994 | } | ||
995 | gtk_widget_destroy (ad); | ||
996 | } | ||
997 | |||
998 | |||
999 | void | ||
1000 | GNUNET_GTK_master_publish_dialog_add_button_clicked_cb (GtkWidget * dummy, | ||
1001 | struct MainPublishingDialogContext *ctx) | ||
1002 | { | ||
1003 | GtkWidget *ad; | ||
1004 | |||
1005 | GtkComboBox *combo; | ||
1006 | GtkTreeModel *anon_treemodel; | ||
1007 | |||
1008 | ctx->open_file_builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_publish_file_dialog.glade", ctx); | ||
1009 | GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_file_builder); | ||
1010 | ad = GTK_WIDGET (gtk_builder_get_object | ||
1011 | (ctx->open_file_builder, "GNUNET_GTK_publish_file_dialog")); | ||
1012 | |||
1013 | /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */ | ||
1014 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object ( | ||
1015 | ctx->open_file_builder, | ||
1016 | "GNUNET_GTK_publish_file_dialog_priority_spin_button")), 1000); | ||
1017 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object ( | ||
1018 | ctx->open_file_builder, | ||
1019 | "GNUNET_GTK_publish_file_dialog_replication_spin_button")), 0); | ||
1020 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object ( | ||
1021 | ctx->open_file_builder, | ||
1022 | "GNUNET_GTK_publish_file_dialog_do_index_checkbutton")), TRUE); | ||
1023 | |||
1024 | ctx->open_file_handler_id = g_signal_connect (G_OBJECT (ad), "response", G_CALLBACK (publish_file_dialog_response_cb), ctx); | ||
1025 | |||
1026 | anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object (ctx->main_window_builder, | ||
1027 | "main_window_search_anonymity_liststore")); | ||
1028 | combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_file_builder, | ||
1029 | "GNUNET_GTK_publish_file_dialog_anonymity_combobox")); | ||
1030 | gtk_combo_box_set_model (combo, anon_treemodel); | ||
1031 | |||
1032 | gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog); | ||
1033 | |||
1034 | gtk_window_present (GTK_WINDOW (ad)); | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | struct EditPublishContext | ||
1039 | { | ||
1040 | struct GNUNET_FS_FileInformation *fip; | ||
1041 | |||
1042 | GtkTreeModel *tm; | ||
1043 | |||
1044 | GtkTreeIter iter; | ||
1045 | }; | ||
1046 | |||
1047 | |||
1048 | /** | ||
1049 | * Update tree view based on the information from the | ||
1050 | * GNUNET_FS_FileInformation publish-structure. | ||
1051 | * | ||
1052 | * @param cls closure, a 'struct EditPublishContext *' | ||
1053 | * @param fi the entry in the publish-structure | ||
1054 | * @param length length of the file or directory | ||
1055 | * @param meta metadata for the file or directory (can be modified) | ||
1056 | * @param uri pointer to the keywords that will be used for this entry (can be modified) | ||
1057 | * @param bo block options (can be modified) | ||
1058 | * @param do_index should we index (can be modified) | ||
1059 | * @param client_info pointer to client context set upon creation (can be modified) | ||
1060 | * @return GNUNET_OK to continue, GNUNET_NO to remove | ||
1061 | * this entry from the directory, GNUNET_SYSERR | ||
1062 | * to abort the iteration | ||
1063 | */ | ||
1064 | static int | ||
1065 | update_treeview_after_edit (void *cls, struct GNUNET_FS_FileInformation *fi, | ||
1066 | uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, | ||
1067 | struct GNUNET_FS_Uri **uri, | ||
1068 | struct GNUNET_FS_BlockOptions *bo, int *do_index, | ||
1069 | void **client_info) | ||
1070 | { | ||
1071 | struct EditPublishContext *epc = cls; | ||
1072 | |||
1073 | gtk_tree_store_set (GTK_TREE_STORE (epc->tm), &epc->iter, | ||
1074 | 1, *do_index, | ||
1075 | 3, (guint) bo->anonymity_level, | ||
1076 | 4, (guint) bo->content_priority, | ||
1077 | 6, (guint64) bo->expiration_time.abs_value, | ||
1078 | 7, (guint) bo->replication_level, | ||
1079 | -1); | ||
1080 | return GNUNET_SYSERR; | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | /** | ||
1085 | * Function called when the edit publish dialog has been closed. | ||
1086 | * | ||
1087 | * @param cls closure | ||
1088 | * @param ret GTK_RESPONSE_OK if the dialog was closed with "OK" | ||
1089 | * @param root unused (namespace root name) | ||
1090 | */ | ||
1091 | static void | ||
1092 | master_publish_edit_publish_dialog_cb (gpointer cls, | ||
1093 | gint ret, | ||
1094 | const char *root) | ||
1095 | { | ||
1096 | struct EditPublishContext *cbargs = cls; | ||
1097 | |||
1098 | if (ret == GTK_RESPONSE_OK) | ||
1099 | GNUNET_FS_file_information_inspect (cbargs->fip, &update_treeview_after_edit, cbargs); | ||
1100 | GNUNET_free (cbargs); | ||
1101 | } | ||
1102 | |||
1103 | |||
1104 | void | ||
1105 | GNUNET_GTK_master_publish_dialog_edit_button_clicked_cb (GtkWidget * dummy, | ||
1106 | struct MainPublishingDialogContext *ctx) | ||
1107 | { | ||
1108 | struct EditPublishContext *cbargs; | ||
1109 | GtkListStore *anon_liststore; | ||
1110 | |||
1111 | anon_liststore = GTK_LIST_STORE (gtk_builder_get_object (ctx->main_window_builder, | ||
1112 | "main_window_search_anonymity_liststore")); | ||
1113 | cbargs = GNUNET_malloc (sizeof (struct EditPublishContext)); | ||
1114 | cbargs->tm = ctx->file_info_treemodel; | ||
1115 | if (! gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &cbargs->iter)) | ||
1116 | { | ||
1117 | GNUNET_break (0); | ||
1118 | GNUNET_free (cbargs); | ||
1119 | return; | ||
1120 | } | ||
1121 | gtk_tree_model_get (ctx->file_info_treemodel, &cbargs->iter, | ||
1122 | 5, &cbargs->fip, | ||
1123 | -1); | ||
1124 | /* FIXME: can we just give our anon_liststore out like this? What about | ||
1125 | (unintended) sharing of state? */ | ||
1126 | GNUNET_FS_GTK_edit_publish_dialog (ctx->master_pubdialog, | ||
1127 | cbargs->fip, | ||
1128 | GNUNET_YES, | ||
1129 | anon_liststore, | ||
1130 | &master_publish_edit_publish_dialog_cb, | ||
1131 | cbargs); | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | /** | ||
1136 | * Free row reference stored in the file information's | ||
1137 | * client-info pointer. | ||
1138 | */ | ||
1139 | static int | ||
1140 | free_fi_row_reference (void *cls, struct GNUNET_FS_FileInformation *fi, | ||
1141 | uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, | ||
1142 | struct GNUNET_FS_Uri **uri, | ||
1143 | struct GNUNET_FS_BlockOptions *bo, int *do_index, | ||
1144 | void **client_info) | ||
1145 | { | ||
1146 | GtkTreeRowReference *row = *client_info; | ||
1147 | |||
1148 | if (row == NULL) | ||
1149 | { | ||
1150 | GNUNET_break (0); | ||
1151 | return GNUNET_OK; | ||
1152 | } | ||
1153 | gtk_tree_row_reference_free (row); | ||
1154 | return GNUNET_OK; | ||
1155 | } | ||
1156 | |||
1157 | |||
1158 | void | ||
1159 | GNUNET_GTK_master_publish_dialog_delete_button_clicked_cb (GtkWidget * dummy, | ||
1160 | struct MainPublishingDialogContext *ctx) | ||
1161 | { | ||
1162 | GtkTreeIter iter; | ||
1163 | struct GNUNET_FS_FileInformation *fip; | ||
1164 | |||
1165 | if (TRUE != gtk_tree_selection_get_selected (ctx->file_info_selection, NULL, &iter)) | ||
1166 | { | ||
1167 | GNUNET_break (0); | ||
1168 | return; | ||
1169 | } | ||
1170 | gtk_tree_model_get (ctx->file_info_treemodel, &iter, 5, &fip, -1); | ||
1171 | GNUNET_FS_file_information_destroy (fip, &free_fi_row_reference, NULL); | ||
1172 | gtk_tree_store_remove (GTK_TREE_STORE (ctx->file_info_treemodel), &iter); | ||
1173 | update_selectivity (ctx); | ||
1174 | } | ||
1175 | |||
1176 | |||
1177 | void | ||
1178 | GNUNET_FS_GTK_progress_dialog_cancel_button_clicked_cb (GtkButton *button, | ||
1179 | void *cls) | ||
1180 | { | ||
1181 | struct AddDirClientContext *adcc = cls; | ||
1182 | |||
1183 | if (adcc->ds != NULL) | ||
1184 | { | ||
1185 | /* Still scanning - signal the scanner to finish */ | ||
1186 | GNUNET_FS_directory_scan_abort (adcc->ds); | ||
1187 | adcc->ds = NULL; | ||
1188 | } | ||
1189 | close_scan (adcc); | ||
1190 | } | ||
1191 | |||
1192 | |||
1193 | gboolean | ||
1194 | GNUNET_FS_GTK_progress_dialog_delete_event_cb (GtkWidget *widget, | ||
1195 | GdkEvent * event, | ||
1196 | void *cls) | ||
1197 | { | ||
1198 | /* Don't allow GTK to kill the window, until the scan is finished */ | ||
1199 | return GNUNET_NO; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | void | ||
1204 | GNUNET_GTK_master_publish_dialog_open_button_clicked_cb (GtkWidget * dummy, | ||
1205 | struct MainPublishingDialogContext *ctx) | ||
1206 | { | ||
1207 | GtkWidget *ad; | ||
1208 | |||
1209 | GtkComboBox *combo; | ||
1210 | GtkTreeModel *anon_treemodel; | ||
1211 | |||
1212 | ctx->open_directory_builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_publish_directory_dialog.glade", ctx); | ||
1213 | GNUNET_FS_GTK_setup_expiration_year_adjustment (ctx->open_directory_builder); | ||
1214 | |||
1215 | /* FIXME: Use some kind of adjustable defaults instead of 1000, 0 and TRUE */ | ||
1216 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object ( | ||
1217 | ctx->open_directory_builder, | ||
1218 | "GNUNET_GTK_publish_directory_dialog_priority_spin_button")), 1000); | ||
1219 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtk_builder_get_object ( | ||
1220 | ctx->open_directory_builder, | ||
1221 | "GNUNET_GTK_publish_directory_dialog_replication_spin_button")), 0); | ||
1222 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object ( | ||
1223 | ctx->open_directory_builder, | ||
1224 | "GNUNET_GTK_publish_directory_dialog_do_index_checkbutton")), TRUE); | ||
1225 | |||
1226 | ad = GTK_WIDGET (gtk_builder_get_object | ||
1227 | (ctx->open_directory_builder, "GNUNET_GTK_publish_directory_dialog")); | ||
1228 | |||
1229 | ctx->open_directory_handler_id = g_signal_connect (G_OBJECT (ad), "response", G_CALLBACK (publish_directory_dialog_response_cb), ctx); | ||
1230 | |||
1231 | anon_treemodel = GTK_TREE_MODEL (gtk_builder_get_object (ctx->main_window_builder, | ||
1232 | "main_window_search_anonymity_liststore")); | ||
1233 | combo = GTK_COMBO_BOX (gtk_builder_get_object (ctx->open_directory_builder, | ||
1234 | "GNUNET_GTK_publish_directory_dialog_anonymity_combobox")); | ||
1235 | gtk_combo_box_set_model (combo, anon_treemodel); | ||
1236 | |||
1237 | gtk_window_set_transient_for (GTK_WINDOW (ad), ctx->master_pubdialog); | ||
1238 | |||
1239 | gtk_window_present (GTK_WINDOW (ad)); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | /** | ||
1244 | * Get the file information struct corresponding to the | ||
1245 | * given iter in the publish dialog tree model. Recursively | ||
1246 | * builds the file information struct from the subtree. | ||
1247 | * | ||
1248 | * @param tm model to grab fi from | ||
1249 | * @param iter position to grab fi from | ||
1250 | * @return file information from the given position (never NULL) | ||
1251 | */ | ||
1252 | static struct GNUNET_FS_FileInformation * | ||
1253 | get_file_information (GtkTreeModel * tm, GtkTreeIter * iter) | ||
1254 | { | ||
1255 | struct GNUNET_FS_FileInformation *fi; | ||
1256 | struct GNUNET_FS_FileInformation *fic; | ||
1257 | GtkTreeIter child; | ||
1258 | |||
1259 | gtk_tree_model_get (tm, iter, 5, &fi, -1); | ||
1260 | gtk_tree_store_set (GTK_TREE_STORE (tm), iter, 5, NULL, -1); | ||
1261 | GNUNET_assert (fi != NULL); | ||
1262 | if (gtk_tree_model_iter_children (tm, &child, iter)) | ||
1263 | { | ||
1264 | GNUNET_break (GNUNET_YES == GNUNET_FS_file_information_is_directory (fi)); | ||
1265 | do | ||
1266 | { | ||
1267 | fic = get_file_information (tm, &child); | ||
1268 | GNUNET_break (GNUNET_OK == GNUNET_FS_file_information_add (fi, fic)); | ||
1269 | } | ||
1270 | while (gtk_tree_model_iter_next (tm, &child)); | ||
1271 | } | ||
1272 | return fi; | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | /** | ||
1277 | * Closure for 'add_updateable_to_ts'. | ||
1278 | */ | ||
1279 | struct UpdateableContext | ||
1280 | { | ||
1281 | /** | ||
1282 | * Parent of current insertion. | ||
1283 | */ | ||
1284 | GtkTreeIter *parent; | ||
1285 | |||
1286 | /** | ||
1287 | * Tree store we are modifying. | ||
1288 | */ | ||
1289 | GtkTreeStore *ts; | ||
1290 | |||
1291 | /** | ||
1292 | * Name of the namespace. | ||
1293 | */ | ||
1294 | const char *namespace_name; | ||
1295 | |||
1296 | /** | ||
1297 | * Handle to the namespace. | ||
1298 | */ | ||
1299 | struct GNUNET_FS_Namespace *ns; | ||
1300 | |||
1301 | /** | ||
1302 | * Hash codes of identifiers already added to tree store. | ||
1303 | */ | ||
1304 | struct GNUNET_CONTAINER_MultiHashMap *seen; | ||
1305 | |||
1306 | /** | ||
1307 | * Did the iterator get called? | ||
1308 | */ | ||
1309 | int update_called; | ||
1310 | }; | ||
1311 | |||
1312 | |||
1313 | /** | ||
1314 | * Add updateable entries to the tree view. | ||
1315 | * | ||
1316 | * @param cls closure | ||
1317 | * @param last_id ID to add | ||
1318 | * @param last_uri associated URI | ||
1319 | * @param last_meta associate meta data | ||
1320 | * @param next_id ID for future updates | ||
1321 | */ | ||
1322 | static void | ||
1323 | add_updateable_to_ts (void *cls, const char *last_id, | ||
1324 | const struct GNUNET_FS_Uri *last_uri, | ||
1325 | const struct GNUNET_CONTAINER_MetaData *last_meta, | ||
1326 | const char *next_id) | ||
1327 | { | ||
1328 | struct UpdateableContext *uc = cls; | ||
1329 | struct UpdateableContext sc; | ||
1330 | GtkTreeIter iter; | ||
1331 | GtkTreeIter titer; | ||
1332 | char *desc; | ||
1333 | GNUNET_HashCode hc; | ||
1334 | |||
1335 | uc->update_called = GNUNET_YES; | ||
1336 | GNUNET_CRYPTO_hash (last_id, strlen (last_id), &hc); | ||
1337 | if (NULL != GNUNET_CONTAINER_multihashmap_get (uc->seen, &hc)) | ||
1338 | return; | ||
1339 | GNUNET_CONTAINER_multihashmap_put (uc->seen, &hc, "dummy", | ||
1340 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1341 | /* FIXME: what if this put fails? Not convinced it cannot... */ | ||
1342 | desc = | ||
1343 | GNUNET_CONTAINER_meta_data_get_first_by_types (last_meta, | ||
1344 | EXTRACTOR_METATYPE_DESCRIPTION, | ||
1345 | EXTRACTOR_METATYPE_TITLE, | ||
1346 | EXTRACTOR_METATYPE_BOOK_TITLE, | ||
1347 | EXTRACTOR_METATYPE_FILENAME, | ||
1348 | EXTRACTOR_METATYPE_SUMMARY, | ||
1349 | EXTRACTOR_METATYPE_ALBUM, | ||
1350 | EXTRACTOR_METATYPE_COMMENT, | ||
1351 | EXTRACTOR_METATYPE_SUBJECT, | ||
1352 | -1); | ||
1353 | if (desc == NULL) | ||
1354 | desc = GNUNET_strdup (_("no description supplied")); | ||
1355 | else | ||
1356 | { | ||
1357 | char *utf8_desc = NULL; | ||
1358 | |||
1359 | utf8_desc = | ||
1360 | GNUNET_FS_GTK_dubious_meta_to_utf8 (EXTRACTOR_METAFORMAT_UTF8, desc, | ||
1361 | strlen (desc) + 1); | ||
1362 | GNUNET_free (desc); | ||
1363 | if (utf8_desc != NULL) | ||
1364 | desc = utf8_desc; | ||
1365 | else | ||
1366 | desc = NULL; | ||
1367 | } | ||
1368 | gtk_tree_store_insert_with_values (uc->ts, &iter, uc->parent, G_MAXINT, 0, | ||
1369 | uc->namespace_name, 1, uc->ns, 2, last_id, | ||
1370 | 3, GNUNET_FS_uri_dup (last_uri), 4, | ||
1371 | GNUNET_CONTAINER_meta_data_duplicate | ||
1372 | (last_meta), 5, "", 6, desc, 7, | ||
1373 | TRUE /* update editable (always) */ , | ||
1374 | 8, FALSE | ||
1375 | /* current not editable (only for top-level) */ | ||
1376 | , -1); | ||
1377 | GNUNET_free_non_null (desc); | ||
1378 | sc.parent = &iter; | ||
1379 | sc.ts = uc->ts; | ||
1380 | sc.namespace_name = uc->namespace_name; | ||
1381 | sc.ns = uc->ns; | ||
1382 | sc.seen = uc->seen; | ||
1383 | sc.update_called = GNUNET_NO; | ||
1384 | GNUNET_FS_namespace_list_updateable (uc->ns, next_id, &add_updateable_to_ts, | ||
1385 | &sc); | ||
1386 | if ((sc.update_called == GNUNET_NO) && (next_id != NULL) && | ||
1387 | (strlen (next_id) > 0)) | ||
1388 | { | ||
1389 | /* add leaf */ | ||
1390 | gtk_tree_store_insert_with_values (uc->ts, &titer, &iter, G_MAXINT, 0, | ||
1391 | uc->namespace_name, 1, uc->ns, 2, | ||
1392 | next_id, 3, NULL, 4, NULL, 5, "", 6, "", | ||
1393 | 7, TRUE /* update editable (always) */ , | ||
1394 | 8, FALSE | ||
1395 | /* current not editable (only for top-level) */ | ||
1396 | , -1); | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * Add all updateable entries of the current namespace to the | ||
1403 | * tree store. | ||
1404 | * | ||
1405 | * @param cls the 'GtkTreeStore' to update | ||
1406 | * @param name name of the namespace to add | ||
1407 | * @param id identity of the namespace to add | ||
1408 | */ | ||
1409 | static void | ||
1410 | add_namespace_to_ts (void *cls, const char *name, const GNUNET_HashCode * id) | ||
1411 | { | ||
1412 | GtkTreeStore *ts = cls; | ||
1413 | struct UpdateableContext uc; | ||
1414 | GtkTreeIter iter; | ||
1415 | |||
1416 | uc.parent = &iter; | ||
1417 | uc.namespace_name = name; | ||
1418 | uc.ts = ts; | ||
1419 | uc.ns = GNUNET_FS_namespace_create (GNUNET_FS_GTK_get_fs_handle (), name); | ||
1420 | uc.update_called = GNUNET_NO; | ||
1421 | gtk_tree_store_insert_with_values (ts, &iter, NULL, G_MAXINT, 0, name, 1, | ||
1422 | uc.ns, 2, NULL /* last-id */ , | ||
1423 | 3, NULL /* last-uri (as string!) */ , | ||
1424 | 4, NULL /* meta */ , | ||
1425 | 5, NULL /* next-ID */ , | ||
1426 | 6, NULL /* last-description */ , | ||
1427 | 7, TRUE /* update editable */ , | ||
1428 | 8, TRUE /* current editable */ , | ||
1429 | -1); | ||
1430 | uc.seen = GNUNET_CONTAINER_multihashmap_create (128); | ||
1431 | GNUNET_FS_namespace_list_updateable (uc.ns, NULL, &add_updateable_to_ts, &uc); | ||
1432 | GNUNET_CONTAINER_multihashmap_destroy (uc.seen); | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | static void | ||
1437 | free_pseudonym_tree_store (GtkTreeModel * tm, GtkTreeIter * iter) | ||
1438 | { | ||
1439 | struct GNUNET_CONTAINER_MetaData *meta; | ||
1440 | struct GNUNET_FS_Namespace *ns; | ||
1441 | GtkTreeIter child; | ||
1442 | |||
1443 | gtk_tree_model_get (tm, iter, 1, &ns, 4, &meta, -1); | ||
1444 | if (meta != NULL) | ||
1445 | GNUNET_CONTAINER_meta_data_destroy (meta); | ||
1446 | if (ns != NULL) | ||
1447 | { | ||
1448 | // FIXME: delete ns? | ||
1449 | // GNUNET_FS_namespace_delete (nso, GNUNET_NO); | ||
1450 | } | ||
1451 | if (TRUE == gtk_tree_model_iter_children (tm, &child, iter)) | ||
1452 | { | ||
1453 | do | ||
1454 | { | ||
1455 | free_pseudonym_tree_store (tm, &child); | ||
1456 | } | ||
1457 | while (TRUE == gtk_tree_model_iter_next (tm, &child)); | ||
1458 | } | ||
1459 | } | ||
1460 | |||
1461 | |||
1462 | static void | ||
1463 | free_file_information_tree_store (GtkTreeModel * tm, GtkTreeIter * iter) | ||
1464 | { | ||
1465 | GtkTreeIter child; | ||
1466 | struct GNUNET_FS_FileInformation *fip; | ||
1467 | |||
1468 | gtk_tree_model_get (tm, iter, 5, &fip, -1); | ||
1469 | if (fip != NULL) | ||
1470 | GNUNET_FS_file_information_destroy (fip, NULL, NULL); | ||
1471 | if (TRUE == gtk_tree_model_iter_children (tm, &child, iter)) | ||
1472 | { | ||
1473 | do | ||
1474 | { | ||
1475 | free_file_information_tree_store (tm, &child); | ||
1476 | } | ||
1477 | while (TRUE == gtk_tree_model_iter_next (tm, &child)); | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | static int | ||
1482 | hide_master_publish_dialog (struct MainPublishingDialogContext *ctx, gint ret) | ||
1483 | { | ||
1484 | GtkTreeIter iter; | ||
1485 | gpointer namespace; | ||
1486 | gchar *namespace_id; | ||
1487 | gchar *namespace_uid; | ||
1488 | struct GNUNET_FS_FileInformation *fi; | ||
1489 | |||
1490 | /* Don't close until all scanners are finished */ | ||
1491 | if (ctx->adddir_head != NULL) | ||
1492 | return GNUNET_NO; | ||
1493 | |||
1494 | if (ret == GTK_RESPONSE_OK) | ||
1495 | { | ||
1496 | if (TRUE == gtk_tree_selection_get_selected (ctx->pseudonym_selection, NULL, &iter)) | ||
1497 | { | ||
1498 | gtk_tree_model_get (ctx->pseudonym_treemodel, &iter, 1, &namespace, 2, &namespace_id, 5, | ||
1499 | &namespace_uid, -1); | ||
1500 | } | ||
1501 | else | ||
1502 | { | ||
1503 | namespace = NULL; | ||
1504 | namespace_id = NULL; | ||
1505 | namespace_uid = NULL; | ||
1506 | } | ||
1507 | if (gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter)) | ||
1508 | do | ||
1509 | { | ||
1510 | fi = get_file_information (ctx->file_info_treemodel, &iter); | ||
1511 | /* FIXME: should we convert namespace id and uid from UTF8? */ | ||
1512 | GNUNET_FS_publish_start (GNUNET_FS_GTK_get_fs_handle (), fi, namespace, | ||
1513 | namespace_id, namespace_uid, | ||
1514 | GNUNET_FS_PUBLISH_OPTION_NONE); | ||
1515 | } | ||
1516 | while (gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter)); | ||
1517 | g_free (namespace_id); | ||
1518 | g_free (namespace_uid); | ||
1519 | } | ||
1520 | |||
1521 | /* free state from 'ptm' */ | ||
1522 | if (TRUE == gtk_tree_model_get_iter_first (ctx->pseudonym_treemodel, &iter)) | ||
1523 | do | ||
1524 | { | ||
1525 | free_pseudonym_tree_store (ctx->pseudonym_treemodel, &iter); | ||
1526 | } | ||
1527 | while (TRUE == gtk_tree_model_iter_next (ctx->pseudonym_treemodel, &iter)); | ||
1528 | gtk_tree_store_clear (GTK_TREE_STORE (ctx->pseudonym_treemodel)); | ||
1529 | |||
1530 | /* free state from 'tm' */ | ||
1531 | if (TRUE == gtk_tree_model_get_iter_first (ctx->file_info_treemodel, &iter)) | ||
1532 | do | ||
1533 | { | ||
1534 | free_file_information_tree_store (ctx->file_info_treemodel, &iter); | ||
1535 | } | ||
1536 | while (TRUE == gtk_tree_model_iter_next (ctx->file_info_treemodel, &iter)); | ||
1537 | gtk_tree_store_clear (GTK_TREE_STORE (ctx->file_info_treemodel)); | ||
1538 | gtk_widget_destroy (GTK_WIDGET (ctx->master_pubdialog)); | ||
1539 | g_object_unref (G_OBJECT (ctx->builder)); | ||
1540 | GNUNET_free (ctx); | ||
1541 | return GNUNET_YES; | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | void | ||
1546 | GNUNET_GTK_master_publish_dialog_execute_button_clicked_cb (GtkButton * button, | ||
1547 | struct MainPublishingDialogContext *ctx) | ||
1548 | { | ||
1549 | hide_master_publish_dialog (ctx, GTK_RESPONSE_OK); | ||
1550 | } | ||
1551 | |||
1552 | |||
1553 | void | ||
1554 | GNUNET_GTK_master_publish_dialog_cancel_button_clicked_cb (GtkButton * button, | ||
1555 | struct MainPublishingDialogContext *ctx) | ||
1556 | { | ||
1557 | hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL); | ||
1558 | } | ||
1559 | |||
1560 | |||
1561 | gboolean | ||
1562 | GNUNET_GTK_master_publish_dialog_delete_event_cb (GtkWidget * widget, | ||
1563 | GdkEvent * event, | ||
1564 | struct MainPublishingDialogContext *ctx) | ||
1565 | { | ||
1566 | if (GNUNET_NO == hide_master_publish_dialog (ctx, GTK_RESPONSE_CANCEL)) | ||
1567 | return TRUE; | ||
1568 | return FALSE; | ||
1569 | } | ||
1570 | |||
1571 | |||
1572 | /** | ||
1573 | */ | ||
1574 | void | ||
1575 | GNUNET_GTK_main_menu_file_publish_activate_cb (GtkWidget * dummy, gpointer user_data) | ||
1576 | { | ||
1577 | struct MainPublishingDialogContext *ctx; | ||
1578 | |||
1579 | ctx = GNUNET_malloc (sizeof (struct MainPublishingDialogContext)); | ||
1580 | ctx->builder = GNUNET_GTK_get_new_builder ("gnunet_fs_gtk_publish_dialog.glade", ctx); | ||
1581 | |||
1582 | if (ctx->builder == NULL) | ||
1583 | { | ||
1584 | GNUNET_free (ctx); | ||
1585 | return; | ||
1586 | } | ||
1587 | |||
1588 | init_ctx (ctx); | ||
1589 | ctx->main_window_builder = GTK_BUILDER (user_data); | ||
1590 | GNUNET_FS_namespace_list (GNUNET_FS_GTK_get_fs_handle (), | ||
1591 | &add_namespace_to_ts, GTK_TREE_STORE (ctx->pseudonym_treemodel)); | ||
1592 | gtk_window_present (GTK_WINDOW (ctx->master_pubdialog)); | ||
1593 | } | ||
1594 | |||
1595 | |||
1596 | /* end of gnunet-fs-gtk-main_window_file_publish.c */ | ||