1 /* Demonstration of a UI driven publisher.
2 * This example (publisher-ui.c) is in the public domain.
3 */
4 #include <glib/gstdio.h>
5 #include <gtk/gtk.h>
6
7 #include <libepc/publisher.h>
8 #include <libepc-ui/progress-window.h>
9
10 #define GET_WIDGET(builder, name) (GTK_WIDGET (gtk_builder_get_object ((builder), (name))))
11 #define EPC_TYPE_DEMO_CONTENTS (epc_demo_item_get_type ())
12
13 typedef struct _EpcDemoItem EpcDemoItem;
14
15 typedef void (*UpdateItemFunc) (EpcDemoItem *item,
16 const gchar *text);
17 typedef void (*ForeachItemFunc) (EpcDemoItem *item,
18 gpointer data);
19
20 struct _EpcDemoItem
21 {
22 volatile gint ref_count;
23
24 gchar *name;
25 gchar *text;
26 gchar *username;
27 gchar *password;
28 gchar *bookmark;
29 };
30
31 static EpcPublisher *publisher = NULL;
32 static gboolean updating_selection = FALSE;
33 static GtkTextBuffer *text_buffer = NULL;
34 static GtkListStore *item_list = NULL;
35 static guint auto_save_id = 0;
36
37 static GtkBuilder *builder = NULL;
38 static GtkWidget *item_view = NULL;
39
40 void about_button_clicked_cb (GtkWidget *widget);
41 void add_item_clicked_cb (void);
42 void remove_item_clicked_cb (void);
43 void username_changed_cb (GtkEntry *entry);
44 void password_changed_cb (GtkEntry *entry);
45 void bookmark_changed_cb (GtkEntry *entry);
46 void service_name_changed_cb (GtkEntry *entry);
47 void publish_state_toggled_cb (GtkToggleToolButton *button);
48 void encryption_state_toggled_cb (GtkToggleToolButton *button);
49 void main_window_destroy_cb (void);
50
51 static EpcDemoItem*
epc_demo_item_new(const gchar * name,const gchar * text)52 epc_demo_item_new (const gchar *name,
53 const gchar *text)
54 {
55 EpcDemoItem *self = g_slice_new0 (EpcDemoItem);
56
57 self->ref_count = 1;
58
59 if (name)
60 self->name = g_strdup (name);
61 if (text)
62 self->text = g_strdup (text);
63
64 return self;
65 }
66
67 static gpointer
epc_demo_item_ref(gpointer boxed)68 epc_demo_item_ref (gpointer boxed)
69 {
70 EpcDemoItem *self = boxed;
71
72 g_atomic_int_inc (&self->ref_count);
73
74 return self;
75 }
76
77 static void
epc_demo_item_unref(gpointer boxed)78 epc_demo_item_unref (gpointer boxed)
79 {
80 EpcDemoItem *self = boxed;
81
82 if (g_atomic_int_dec_and_test (&self->ref_count))
83 {
84 g_free (self->name);
85 g_free (self->text);
86 g_free (self->username);
87 g_free (self->password);
88 g_free (self->bookmark);
89
90 g_slice_free (EpcDemoItem, self);
91 }
92 }
93
94 static EpcDemoItem*
epc_demo_item_load(GKeyFile * settings,const gchar * group)95 epc_demo_item_load (GKeyFile *settings,
96 const gchar *group)
97 {
98 EpcDemoItem *self = NULL;
99
100 if (g_key_file_has_group (settings, group))
101 {
102 self = epc_demo_item_new (NULL, NULL);
103
104 self->name = g_key_file_get_string (settings, group, "Name", NULL);
105 self->text = g_key_file_get_string (settings, group, "Text", NULL);
106
107 self->username = g_key_file_get_string (settings, group, "Username", NULL);
108 self->password = g_key_file_get_string (settings, group, "Password", NULL);
109 self->bookmark = g_key_file_get_string (settings, group, "Bookmark", NULL);
110 }
111
112 return self;
113 }
114
115 static void
epc_demo_item_save(EpcDemoItem * self,GKeyFile * settings)116 epc_demo_item_save (EpcDemoItem *self,
117 GKeyFile *settings)
118 {
119 gchar *group = g_strdup_printf ("Item: %s", self->name);
120
121 g_key_file_set_string (settings, group, "Name", self->name);
122 g_key_file_set_string (settings, group, "Text", self->text ? self->text : "");
123
124 if (self->username)
125 g_key_file_set_string (settings, group, "Username", self->username);
126 if (self->password)
127 g_key_file_set_string (settings, group, "Password", self->password);
128 if (self->bookmark)
129 g_key_file_set_string (settings, group, "Bookmark", self->bookmark);
130
131 g_free (group);
132 }
133
134 static void
epc_demo_item_set_text(EpcDemoItem * self,const gchar * text)135 epc_demo_item_set_text (EpcDemoItem *self,
136 const gchar *text)
137 {
138 g_return_if_fail (self);
139
140 g_free (self->text);
141 self->text = (text && *text ? g_strdup (text) : NULL);
142 }
143
144 static void
epc_demo_item_set_username(EpcDemoItem * self,const gchar * text)145 epc_demo_item_set_username (EpcDemoItem *self,
146 const gchar *text)
147 {
148 g_return_if_fail (self);
149
150 g_free (self->username);
151 self->username = (text && *text ? g_strdup (text) : NULL);
152 }
153
154 static void
epc_demo_item_set_password(EpcDemoItem * self,const gchar * text)155 epc_demo_item_set_password (EpcDemoItem *self,
156 const gchar *text)
157 {
158 g_return_if_fail (self);
159
160 g_free (self->password);
161 self->password = (text && *text ? g_strdup (text) : NULL);
162 }
163
164 static void
epc_demo_item_set_bookmark(EpcDemoItem * self,const gchar * text)165 epc_demo_item_set_bookmark (EpcDemoItem *self,
166 const gchar *text)
167 {
168 g_return_if_fail (self);
169
170 g_free (self->bookmark);
171 self->bookmark = (text && *text ? g_strdup (text) : NULL);
172 }
173
174 static GType
epc_demo_item_get_type(void)175 epc_demo_item_get_type (void)
176 {
177 static GType type = G_TYPE_INVALID;
178
179 if (G_UNLIKELY (!type))
180 type = g_boxed_type_register_static ("EpcDemoItem",
181 epc_demo_item_ref,
182 epc_demo_item_unref);
183
184 return type;
185 }
186
187 static void
show_error(GtkWidget * parent,const gchar * title,GError * error)188 show_error (GtkWidget *parent,
189 const gchar *title,
190 GError *error)
191 {
192 GtkWidget *dialog;
193
194 if (parent)
195 parent = gtk_widget_get_toplevel (parent);
196
197 dialog = gtk_message_dialog_new_with_markup (parent ? GTK_WINDOW (parent) : NULL,
198 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
199 GTK_MESSAGE_ERROR,
200 GTK_BUTTONS_CLOSE,
201 "<big><b>%s</b></big>\n\n%s.",
202 title, error->message);
203
204 gtk_dialog_run (GTK_DIALOG (dialog));
205 gtk_widget_destroy (dialog);
206 }
207
208 static void
load_ui(const gchar * path)209 load_ui (const gchar *path)
210 {
211 gchar *dirname = g_path_get_dirname (path);
212
213 if (!g_str_has_suffix (dirname, ".libs"))
214 {
215 GError *error = NULL;
216 gchar *filename;
217
218 filename = g_build_filename (dirname, "publisher.ui", NULL);
219 gtk_builder_add_from_file (builder, filename, &error);
220
221 if (error)
222 {
223 show_error (NULL, "Cannot load user interface.", error);
224 g_error_free (error);
225 }
226
227 g_free (filename);
228 }
229 else
230 load_ui (dirname);
231
232 g_free (dirname);
233 }
234
235 static gchar*
get_settings_filename(void)236 get_settings_filename (void)
237 {
238 return g_build_filename (g_get_user_config_dir (), "libepc",
239 g_get_prgname (), "settings", NULL);
240 }
241
242 static void
load_settings(void)243 load_settings (void)
244 {
245 gchar *filename = get_settings_filename ();
246 GKeyFile *settings = g_key_file_new ();
247 gchar **groups = NULL;
248 gchar *text;
249 gint i;
250
251 g_key_file_load_from_file (settings, filename, 0, NULL);
252 groups = g_key_file_get_groups (settings, NULL);
253
254 if (!item_list)
255 item_list = gtk_list_store_new (2, G_TYPE_STRING, EPC_TYPE_DEMO_CONTENTS);
256 else
257 gtk_list_store_clear (item_list);
258
259 gtk_toggle_tool_button_set_active (
260 GTK_TOGGLE_TOOL_BUTTON (GET_WIDGET (builder, "encryption-state")),
261 g_key_file_get_boolean (settings, "Settings", "Encrypted", NULL));
262
263 text = g_key_file_get_string (settings, "Settings", "ServiceName", NULL);
264
265 if (text)
266 gtk_entry_set_text (GTK_ENTRY (GET_WIDGET (builder, "service-name")), text);
267
268 g_free (text);
269
270 for (i = 0; groups[i]; ++i)
271 if (g_str_has_prefix (groups[i], "Item: "))
272 {
273 EpcDemoItem *item = epc_demo_item_load (settings, groups[i]);
274 GtkTreeIter iter;
275
276 if (!item)
277 continue;
278
279 gtk_list_store_append (item_list, &iter);
280 gtk_list_store_set (item_list, &iter, 0, item->name, 1, item, -1);
281
282 epc_demo_item_unref (item);
283 }
284
285 g_key_file_free (settings);
286 g_strfreev (groups);
287 g_free (filename);
288 }
289
290 static void
foreach_item(ForeachItemFunc callback,gpointer user_data)291 foreach_item (ForeachItemFunc callback,
292 gpointer user_data)
293 {
294 GtkTreeModel *model = GTK_TREE_MODEL (item_list);
295 GtkTreeIter iter;
296
297 if (gtk_tree_model_get_iter_first (model, &iter))
298 do
299 {
300 EpcDemoItem *item = NULL;
301 gtk_tree_model_get (model, &iter, 1, &item, -1);
302
303 if (item)
304 {
305 callback (item, user_data);
306 epc_demo_item_unref (item);
307 }
308 }
309 while (gtk_tree_model_iter_next (model, &iter));
310 }
311
312 static gboolean
auto_save_cb(gpointer data G_GNUC_UNUSED)313 auto_save_cb (gpointer data G_GNUC_UNUSED)
314 {
315 gchar *filename = get_settings_filename ();
316 GKeyFile *settings = g_key_file_new ();
317 gchar **groups = NULL;
318 GtkWidget *widget;
319 gint i;
320
321 gchar *settings_data;
322 gsize settings_len;
323
324 g_key_file_load_from_file (settings, filename, 0, NULL);
325 groups = g_key_file_get_groups (settings, NULL);
326
327 widget = GET_WIDGET (builder, "encryption-state");
328 g_key_file_set_boolean (settings, "Settings", "Encrypted",
329 gtk_toggle_tool_button_get_active (
330 GTK_TOGGLE_TOOL_BUTTON (widget)));
331
332 widget = GET_WIDGET (builder, "service-name");
333 g_key_file_set_string (settings, "Settings", "ServiceName",
334 gtk_entry_get_text (GTK_ENTRY (widget)));
335
336 for (i = 0; groups[i]; ++i)
337 if (g_str_has_prefix (groups[i], "Item: "))
338 g_key_file_remove_group (settings, groups[i], NULL);
339
340 foreach_item ((ForeachItemFunc) epc_demo_item_save, settings);
341 settings_data = g_key_file_to_data (settings, &settings_len, NULL);
342
343 if (settings_data)
344 {
345 g_mkdir_with_parents (filename, 0700);
346 g_rmdir (filename);
347
348 g_debug ("%s: filename=%s", G_STRFUNC, filename);
349 g_file_set_contents (filename, settings_data, settings_len, NULL);
350 g_free (settings_data);
351 }
352
353 g_key_file_free (settings);
354 g_strfreev (groups);
355 g_free (filename);
356
357 auto_save_id = 0;
358
359 return FALSE;
360 }
361
362 static void
schedule_auto_save(void)363 schedule_auto_save (void)
364 {
365 if (0 == auto_save_id)
366 auto_save_id = g_timeout_add (5 * 1000, auto_save_cb, NULL);
367 }
368
369 void
about_button_clicked_cb(GtkWidget * widget)370 about_button_clicked_cb (GtkWidget *widget)
371 {
372 GtkWidget *dialog = GET_WIDGET (builder, "about-dialog");
373 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gtk_widget_get_toplevel (widget)));
374 gtk_dialog_run (GTK_DIALOG (dialog));
375 gtk_widget_hide (dialog);
376 }
377
378 void
add_item_clicked_cb(void)379 add_item_clicked_cb (void)
380 {
381 GtkTreeSelection *selection;
382 GtkTreeIter list_iter, iter;
383 GtkTreeViewColumn *column;
384 GtkTreeModel *model;
385 GtkTreePath *path;
386
387 gtk_widget_grab_focus (item_view);
388 column = gtk_tree_view_get_column (GTK_TREE_VIEW (item_view), 0);
389 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (item_view));
390
391 if (gtk_tree_selection_get_selected (selection, &model, &iter))
392 {
393 path = gtk_tree_model_get_path (model, &iter);
394 gtk_tree_view_set_cursor (GTK_TREE_VIEW (item_view), path, NULL, FALSE);
395 gtk_tree_path_free (path);
396 }
397
398 gtk_list_store_append (item_list, &list_iter);
399 gtk_list_store_set (item_list, &list_iter, 0, "New Item", -1);
400
401 gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (model),
402 &iter, &list_iter);
403
404 path = gtk_tree_model_get_path (model, &iter);
405 gtk_tree_view_set_cursor (GTK_TREE_VIEW (item_view), path, column, TRUE);
406 gtk_tree_path_free (path);
407 }
408
409 static void
remove_item(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreeIter * iter)410 remove_item (GtkTreeSelection *selection,
411 GtkTreeModel *model,
412 GtkTreeIter *iter)
413 {
414 EpcDemoItem *item = NULL;
415 GtkTreePath *path = NULL;
416 GtkTreeIter child_iter;
417
418 gtk_tree_model_get (model, iter, 1, &item, -1);
419
420 if (item)
421 {
422 epc_publisher_remove (publisher, item->name);
423 epc_demo_item_unref (item);
424 }
425
426 path = gtk_tree_model_get_path (model, iter);
427 gtk_tree_view_set_cursor (GTK_TREE_VIEW (item_view), path, NULL, FALSE);
428
429 if (GTK_IS_TREE_MODEL_SORT (model))
430 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
431 &child_iter, iter);
432 else
433 child_iter = *iter;
434
435 gtk_list_store_remove (item_list, &child_iter);
436
437 if (gtk_tree_model_get_iter (model, iter, path) ||
438 (gtk_tree_path_prev (path) && gtk_tree_model_get_iter (model, iter, path)))
439 gtk_tree_selection_select_iter (selection, iter);
440
441 gtk_tree_path_free (path);
442 }
443
444 void
remove_item_clicked_cb(void)445 remove_item_clicked_cb (void)
446 {
447 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (item_view));
448 GtkTreeModel *model = NULL;
449 GtkTreeIter iter;
450
451 if (gtk_tree_selection_get_selected (selection, &model, &iter))
452 remove_item (selection, model, &iter);
453 }
454
455 static EpcDemoItem*
get_selected_item(GtkTreeSelection * selection)456 get_selected_item (GtkTreeSelection *selection)
457 {
458 GtkTreeModel *model = NULL;
459 EpcDemoItem *item = NULL;
460 GtkTreeIter iter;
461
462 if (updating_selection)
463 return NULL;
464
465 if (!selection)
466 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (item_view));
467 if (gtk_tree_selection_get_selected (selection, &model, &iter))
468 gtk_tree_model_get (model, &iter, 1, &item, -1);
469
470 return item;
471 }
472
473 static void
selection_changed_cb(GtkTreeSelection * selection)474 selection_changed_cb (GtkTreeSelection *selection)
475 {
476 EpcDemoItem *item;
477
478 g_return_if_fail (!updating_selection);
479 item = get_selected_item (selection);
480 updating_selection = TRUE;
481
482 if (item)
483 {
484 gtk_text_buffer_set_text (text_buffer,
485 item->text ? item->text : "",
486 -1);
487
488 gtk_entry_set_text (GTK_ENTRY (GET_WIDGET (builder, "username")),
489 item->username ? item->username : "");
490 gtk_entry_set_text (GTK_ENTRY (GET_WIDGET (builder, "password")),
491 item->password ? item->password : "");
492 gtk_entry_set_text (GTK_ENTRY (GET_WIDGET (builder, "bookmark")),
493 item->bookmark ? item->bookmark: "");
494
495 epc_demo_item_unref (item);
496 }
497
498 gtk_widget_set_sensitive (GET_WIDGET (builder, "item-vbox"), NULL != item);
499 gtk_widget_set_sensitive (GET_WIDGET (builder, "remove-item"), NULL != item);
500
501 updating_selection = FALSE;
502 }
503
504 static void
update_item(UpdateItemFunc update,const gchar * text)505 update_item (UpdateItemFunc update,
506 const gchar *text)
507 {
508 EpcDemoItem *item = get_selected_item (NULL);
509
510 if (item)
511 {
512 update (item, text);
513 epc_demo_item_unref (item);
514 schedule_auto_save ();
515 }
516 }
517
518 void
username_changed_cb(GtkEntry * entry)519 username_changed_cb (GtkEntry *entry)
520 {
521 update_item (epc_demo_item_set_username, gtk_entry_get_text (entry));
522 }
523
524 void
password_changed_cb(GtkEntry * entry)525 password_changed_cb (GtkEntry *entry)
526 {
527 update_item (epc_demo_item_set_password, gtk_entry_get_text (entry));
528 }
529
530 void
bookmark_changed_cb(GtkEntry * entry)531 bookmark_changed_cb (GtkEntry *entry)
532 {
533 update_item (epc_demo_item_set_bookmark, gtk_entry_get_text (entry));
534 }
535
536 static void
text_buffer_changed_cb(GtkTextBuffer * buffer)537 text_buffer_changed_cb (GtkTextBuffer *buffer)
538 {
539 GtkTextIter start, end;
540 gchar *text;
541
542 gtk_text_buffer_get_bounds (buffer, &start, &end);
543 text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
544 update_item (epc_demo_item_set_text, text);
545 g_free (text);
546 }
547
548 static gchar*
get_service_name(GtkEntry * entry)549 get_service_name (GtkEntry *entry)
550 {
551 const gchar *pattern = gtk_entry_get_text (entry);
552 GError *error = NULL;
553 gchar *name;
554
555 name = epc_publisher_expand_name (pattern, &error);
556
557 if (!name)
558 show_error (GTK_WIDGET (entry), "Cannot change service name", error);
559
560 g_clear_error (&error);
561
562 return name;
563 }
564
565 static EpcProtocol
get_protocol(GtkToggleToolButton * button)566 get_protocol (GtkToggleToolButton *button)
567 {
568 gboolean encryption = gtk_toggle_tool_button_get_active (button);
569 return (encryption ? EPC_PROTOCOL_HTTPS : EPC_PROTOCOL_HTTP);
570 }
571
572 void
service_name_changed_cb(GtkEntry * entry)573 service_name_changed_cb (GtkEntry *entry)
574 {
575 if (publisher)
576 {
577 gchar *name = get_service_name (entry);
578
579 if (name)
580 epc_publisher_set_service_name (publisher, name);
581
582 g_free (name);
583 }
584
585 schedule_auto_save ();
586 }
587
588 static EpcContents*
item_contents_handler(EpcPublisher * publisher G_GNUC_UNUSED,const gchar * key G_GNUC_UNUSED,gpointer data)589 item_contents_handler (EpcPublisher *publisher G_GNUC_UNUSED,
590 const gchar *key G_GNUC_UNUSED,
591 gpointer data)
592 {
593 EpcDemoItem *item = data;
594 const gchar *type = "text/plain";
595 const gchar *text = item->text ? item->text : "";
596
597 if (g_str_has_prefix (text, "<html>"))
598 type = "text/html";
599
600 return epc_contents_new_dup (type, text, -1);
601 }
602
603 static gboolean
auth_handler(EpcAuthContext * context,const gchar * username,gpointer data G_GNUC_UNUSED)604 auth_handler (EpcAuthContext *context,
605 const gchar *username,
606 gpointer data G_GNUC_UNUSED)
607 {
608 EpcPublisher *publisher = epc_auth_context_get_publisher (context);
609 const gchar *key = epc_auth_context_get_key (context);
610 EpcDemoItem *item = epc_publisher_lookup (publisher, key);
611
612 g_return_val_if_fail (NULL != item, FALSE);
613
614 if (!item->username || !*item->username)
615 return TRUE;
616
617 return
618 NULL != username &&
619 g_str_equal (username, item->username) &&
620 epc_auth_context_check_password (context, item->password);
621 }
622
623 static void
publish_item_cb(EpcDemoItem * item,gpointer data G_GNUC_UNUSED)624 publish_item_cb (EpcDemoItem *item,
625 gpointer data G_GNUC_UNUSED)
626 {
627 epc_publisher_add_handler (publisher, item->name, item_contents_handler,
628 epc_demo_item_ref (item),
629 epc_demo_item_unref);
630 epc_publisher_set_auth_handler (publisher, item->name,
631 auth_handler, NULL, NULL);
632 }
633
634 void
publish_state_toggled_cb(GtkToggleToolButton * button)635 publish_state_toggled_cb (GtkToggleToolButton *button)
636 {
637 gboolean publish = gtk_toggle_tool_button_get_active (button);
638 GError *error = NULL;
639
640 if (!publish)
641 epc_publisher_quit (publisher);
642 else if (!epc_publisher_run_async (publisher, &error))
643 show_error (GTK_WIDGET (button), "Cannot start publisher", error);
644
645 g_clear_error (&error);
646 }
647
648 void
encryption_state_toggled_cb(GtkToggleToolButton * button)649 encryption_state_toggled_cb (GtkToggleToolButton *button)
650 {
651 if (publisher)
652 {
653 gboolean was_running;
654 GError *error = NULL;
655
656 was_running = epc_publisher_quit (publisher);
657 epc_publisher_set_protocol (publisher, get_protocol (button));
658
659 if (was_running && !epc_publisher_run_async (publisher, &error))
660 show_error (GTK_WIDGET (button), "Cannot restart publisher", error);
661
662 g_clear_error (&error);
663 }
664
665 schedule_auto_save ();
666 }
667
668 static void
cell_editing_canceled_cb(void)669 cell_editing_canceled_cb (void)
670 {
671 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (item_view));
672 GtkTreeModel *model = NULL;
673 EpcDemoItem *item = NULL;
674 GtkTreeIter iter;
675
676 if (gtk_tree_selection_get_selected (selection, &model, &iter))
677 gtk_tree_model_get (model, &iter, 1, &item, -1);
678
679 if (!item)
680 remove_item (selection, model, &iter);
681 else
682 epc_demo_item_unref (item);
683 }
684
685 static void
cell_item_edited_cb(GtkCellRendererText * cell G_GNUC_UNUSED,const gchar * path,const gchar * text)686 cell_item_edited_cb (GtkCellRendererText *cell G_GNUC_UNUSED,
687 const gchar *path,
688 const gchar *text)
689 {
690 GtkTreeIter iter, child_iter;
691 GtkTreeModel *model;
692 EpcDemoItem *item;
693
694 model = gtk_tree_view_get_model (GTK_TREE_VIEW (item_view));
695
696 if (gtk_tree_model_get_iter_from_string (model, &iter, path))
697 {
698 const gchar *base_name = text;
699 gchar *unique_name = NULL;
700 gint unique_index = 1;
701
702 gtk_tree_model_get (model, &iter, 1, &item, -1);
703
704 if (item && item->name)
705 epc_publisher_remove (publisher, item->name);
706
707 while (epc_publisher_has_key (publisher, text))
708 {
709 g_free (unique_name);
710
711 unique_name = g_strdup_printf ("%s #%d", base_name, unique_index);
712 unique_index += 1;
713
714 text = unique_name;
715 }
716
717 if (item)
718 {
719 g_free (item->name);
720 item->name = g_strdup (text);
721 }
722 else
723 item = epc_demo_item_new (text, NULL);
724
725 publish_item_cb (item, NULL);
726
727 gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
728 &child_iter, &iter);
729 gtk_list_store_set (item_list, &child_iter, 0, text, 1, item, -1);
730
731 selection_changed_cb (NULL);
732 epc_demo_item_unref (item);
733 schedule_auto_save ();
734 }
735 }
736
737 void
main_window_destroy_cb(void)738 main_window_destroy_cb (void)
739 {
740 if (auto_save_id)
741 {
742 g_source_remove (auto_save_id);
743 auto_save_cb (NULL);
744 }
745
746 gtk_main_quit ();
747 }
748
749 static void
create_publisher(void)750 create_publisher (void)
751 {
752 GtkToggleToolButton *encryption = NULL;
753 GtkEntry *service_name_entry = NULL;
754 gchar *service_name = NULL;
755
756 encryption = GTK_TOGGLE_TOOL_BUTTON (GET_WIDGET (builder, "encryption-state"));
757 service_name_entry = GTK_ENTRY (GET_WIDGET (builder, "service-name"));
758 service_name = get_service_name (service_name_entry);
759
760 g_assert (NULL == publisher);
761 publisher = epc_publisher_new (service_name, "test-publisher", NULL);
762 epc_publisher_set_protocol (publisher, get_protocol (encryption));
763 foreach_item (publish_item_cb, NULL);
764
765 g_free (service_name);
766 }
767
768 int
main(int argc,char * argv[])769 main (int argc,
770 char *argv[])
771 {
772 GtkCellRenderer *cell;
773 GtkTreeModel *sorted;
774 GtkTreeSelection *selection;
775
776 GtkWidget *text_view;
777 GtkWidget *main_window;
778
779 g_set_application_name ("Easy Publisher Example");
780
781 gtk_init (&argc, &argv);
782
783 builder = gtk_builder_new ();
784 load_ui (argv[0]);
785 load_settings ();
786
787 create_publisher ();
788 gtk_builder_connect_signals (builder, NULL);
789
790 item_view = GET_WIDGET (builder, "item-view");
791 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (item_view));
792 g_signal_connect (selection, "changed", G_CALLBACK (selection_changed_cb), NULL);
793
794 cell = gtk_cell_renderer_text_new ();
795 g_object_set (cell, "editable", TRUE, NULL);
796
797 g_object_connect (cell,
798 "signal::editing-canceled", cell_editing_canceled_cb, NULL,
799 "signal::edited", cell_item_edited_cb, NULL,
800 NULL);
801
802 gtk_tree_view_append_column (GTK_TREE_VIEW (item_view),
803 gtk_tree_view_column_new_with_attributes (
804 NULL, cell, "text", 0, NULL));
805
806 sorted = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (item_list));
807 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sorted), 0, GTK_SORT_ASCENDING);
808 gtk_tree_view_set_model (GTK_TREE_VIEW (item_view), sorted);
809
810 text_view = GET_WIDGET (builder, "text-view");
811 text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
812 g_signal_connect (text_buffer, "changed", G_CALLBACK (text_buffer_changed_cb), NULL);
813
814 main_window = GET_WIDGET (builder, "main-window");
815 epc_progress_window_install (GTK_WINDOW (main_window));
816 gtk_widget_show (main_window);
817
818 gtk_main ();
819
820 if (publisher)
821 g_object_unref (publisher);
822
823 g_object_unref (builder);
824
825 return 0;
826 }
827