5 #include <glib/gi18n.h>
6 #include <dbus/dbus-glib.h>
10 #include <mx-gtk/mx-gtk.h>
12 #include <mx/mx-gtk.h>
17 #include "sync-config-widget.h"
19 /* local copy of GtkInfoBar, used when GTK+ < 2.18 */
20 #include "gtkinfobar.h"
23 #define INDICATOR_SIZE 16
24 #define CHILD_PADDING 3
26 G_DEFINE_TYPE (SyncConfigWidget, sync_config_widget, GTK_TYPE_CONTAINER)
29 typedef struct source_widgets {
36 GtkWidget *source_toggle_label;
51 PROP_CURRENT_SERVICE_NAME,
59 static guint32 signals[LAST_SIGNAL] = {0, };
61 typedef struct save_config_data {
62 SyncConfigWidget *widget;
65 source_widgets *widgets;
69 static void start_session_for_config_write_cb (SyncevoServer *server, char *path, GError *error, save_config_data *data);
70 static void sync_config_widget_update_label (SyncConfigWidget *self);
71 static void sync_config_widget_set_name (SyncConfigWidget *self, const char *name);
74 remove_child (GtkWidget *widget, GtkContainer *container)
76 gtk_container_remove (container, widget);
80 get_service_description (const char *service)
85 /* TRANSLATORS: Descriptions for specific services, shown in service
86 * configuration form */
87 if (strcmp (service, "ScheduleWorld") == 0) {
88 return _("ScheduleWorld enables you to keep your contacts, events, "
89 "tasks, and notes in sync.");
90 }else if (strcmp (service, "Google") == 0) {
91 return _("Google Sync can backup and synchronize your contacts "
92 "with your Gmail contacts.");
93 }else if (strcmp (service, "Funambol") == 0) {
94 /* TRANSLATORS: Please include the word "demo" (or the equivalent in
95 your language): Funambol is going to be a 90 day demo service
97 return _("Backup your contacts and calendar. Sync with a single "
98 "click, anytime, anywhere (DEMO).");
99 }else if (strcmp (service, "Mobical") == 0) {
100 return _("Mobical Backup and Restore service allows you to securely "
101 "backup your personal mobile data for free.");
102 }else if (strcmp (service, "ZYB") == 0) {
103 return _("ZYB is a simple way for people to store and share mobile "
104 "information online.");
105 }else if (strcmp (service, "Memotoo") == 0) {
106 return _("Memotoo lets you access your personal data from any "
107 "computer connected to the Internet.");
114 update_source_uri (char *name,
115 GHashTable *source_configuration,
116 SyncConfigWidget *self)
119 source_widgets *widgets;
121 widgets = (source_widgets*)g_hash_table_lookup (self->sources, name);
126 uri = gtk_entry_get_text (GTK_ENTRY (widgets->entry));
127 g_hash_table_insert (source_configuration, g_strdup ("uri"), g_strdup (uri));
130 static source_widgets *
131 source_widgets_ref (source_widgets *widgets)
140 source_widgets_unref (source_widgets *widgets)
144 if (widgets->count == 0)
145 g_slice_free (source_widgets, widgets);
150 check_source_cb (SyncevoSession *session,
152 source_widgets *widgets)
154 gboolean show = TRUE;
157 if(error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
158 dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_SOURCE_UNUSABLE)) {
161 g_warning ("CheckSource failed: %s", error->message);
162 /* non-fatal, ignore in UI */
164 g_error_free (error);
167 if (widgets->count > 1) {
169 /* NOTE: with the new two sources per row layout not showing things
170 * may look weird in some cases... the layout should really only be
171 * done at this point */
172 gtk_widget_show (widgets->source_toggle_label);
173 gtk_widget_show (widgets->label);
174 gtk_widget_show (widgets->entry);
175 gtk_widget_show (widgets->check);
177 /* next save should disable this source */
178 toggle_set_active (widgets->check, FALSE);
181 source_widgets_unref (widgets);
182 g_object_unref (session);
186 set_config_cb (SyncevoSession *session,
188 save_config_data *data)
191 g_warning ("Error in Session.SetConfig: %s", error->message);
192 g_error_free (error);
193 g_object_unref (session);
194 show_error_dialog (GTK_WIDGET (data->widget),
195 _("Sorry, failed to save the configuration"));
199 if (data->temporary) {
200 syncevo_session_check_source (session,
202 (SyncevoSessionGenericCb)check_source_cb,
205 data->widget->configured = TRUE;
206 g_signal_emit (data->widget, signals[SIGNAL_CHANGED], 0);
207 g_object_unref (session);
213 get_config_for_overwrite_prevention_cb (SyncevoSession *session,
214 SyncevoConfig *config,
216 save_config_data *data)
218 static int index = 0;
223 if (error->code == DBUS_GERROR_REMOTE_EXCEPTION &&
224 dbus_g_error_has_name (error, SYNCEVO_DBUS_ERROR_NO_SUCH_CONFIG)) {
225 /* Config does not exist (as expected), we can now save */
226 syncevo_session_set_config (session,
229 data->widget->config,
230 (SyncevoSessionGenericCb)set_config_cb,
234 g_warning ("Unexpected error in Session.GetConfig: %s", error->message);
235 g_error_free (error);
236 g_object_unref (session);
240 /* Config exists when we are trying to create a new config...
241 * Need to start a new session with another name */
242 g_object_unref (session);
243 name = g_strdup_printf ("%s__%d", data->basename, ++index);
244 sync_config_widget_set_name (data->widget, name);
247 syncevo_server_start_no_sync_session (data->widget->server,
248 data->widget->config_name,
249 (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
254 save_config (save_config_data *data,
255 SyncevoSession *session)
257 SyncConfigWidget *w = data->widget;
260 syncevo_config_free (w->config);
261 w->config = g_hash_table_new (g_str_hash, g_str_equal);
264 /* if this is a client peer (a device) and not configured, we
265 * need to test that we aren't overwriting existing
267 /* TODO: This might be a good thing to do for any configurations.*/
268 if (peer_is_client (w->config) &&
269 !w->configured && !data->temporary) {
271 syncevo_session_get_config (session,
273 (SyncevoSessionGetConfigCb)get_config_for_overwrite_prevention_cb,
276 syncevo_session_set_config (session,
279 data->widget->config,
280 (SyncevoSessionGenericCb)set_config_cb,
286 status_changed_for_config_write_cb (SyncevoSession *session,
287 SyncevoSessionStatus status,
289 SyncevoSourceStatuses *source_statuses,
290 save_config_data *data)
292 if (status == SYNCEVO_STATUS_IDLE) {
293 save_config (data, session);
298 get_status_for_config_write_cb (SyncevoSession *session,
299 SyncevoSessionStatus status,
301 SyncevoSourceStatuses *source_statuses,
303 save_config_data *data)
306 g_warning ("Error in Session.GetStatus: %s", error->message);
307 g_error_free (error);
308 g_object_unref (session);
309 /* TODO show in UI: save failed in service list */
313 syncevo_source_statuses_free (source_statuses);
315 if (status == SYNCEVO_STATUS_IDLE) {
316 save_config (data, session);
322 start_session_for_config_write_cb (SyncevoServer *server,
325 save_config_data *data)
327 SyncevoSession *session;
330 g_warning ("Error in Server.StartSession: %s", error->message);
331 g_error_free (error);
332 /* TODO show in UI: save failed in service list */
336 session = syncevo_session_new (path);
338 /* we want to know about status changes to our session */
339 g_signal_connect (session, "status-changed",
340 G_CALLBACK (status_changed_for_config_write_cb), data);
341 syncevo_session_get_status (session,
342 (SyncevoSessionGetStatusCb)get_status_for_config_write_cb,
347 stop_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
349 save_config_data *data;
355 syncevo_config_set_value (self->config, NULL, "defaultPeer", "");
356 sync_config_widget_set_current (self, FALSE);
358 data = g_slice_new (save_config_data);
360 data->delete = FALSE;
361 data->temporary = FALSE;
362 syncevo_server_start_no_sync_session (self->server,
364 (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
369 use_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
371 save_config_data *data;
372 const char *username, *password, *sync_url, *pretty_name;
373 char *real_url, *device;
374 gboolean send, receive;
375 SyncevoSyncMode mode;
381 if (!self->config_name || strlen (self->config_name) == 0) {
382 g_free (self->config_name);
383 self->config_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->entry)));
386 if (self->mode_changed) {
388 source_widgets *widgets;
390 gboolean client = peer_is_client (self->config);
392 send = toggle_get_active (self->send_check);
393 receive = toggle_get_active (self->receive_check);
395 if (send && receive) {
396 mode = SYNCEVO_SYNC_TWO_WAY;
399 SYNCEVO_SYNC_ONE_WAY_FROM_SERVER :
400 SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT;
401 } else if (receive) {
403 SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT :
404 SYNCEVO_SYNC_ONE_WAY_FROM_SERVER;
406 mode = SYNCEVO_SYNC_NONE;
409 g_hash_table_iter_init (&iter, self->sources);
410 while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&widgets)) {
411 const char *mode_str;
414 active = toggle_get_active (widgets->check) &&
415 GTK_WIDGET_SENSITIVE (widgets->check);
417 mode_str = syncevo_sync_mode_to_string (mode);
421 syncevo_config_set_value (self->config, name, "sync", mode_str);
425 username = gtk_entry_get_text (GTK_ENTRY (self->username_entry));
426 syncevo_config_set_value (self->config, NULL, "username", username);
428 sync_url = gtk_entry_get_text (GTK_ENTRY (self->baseurl_entry));
429 /* make a wild guess if no scheme in url */
430 if (strstr (sync_url, "://") == NULL) {
431 real_url = g_strdup_printf ("http://%s", sync_url);
433 real_url = g_strdup (sync_url);
435 syncevo_config_set_value (self->config, NULL, "syncURL", real_url);
437 password = gtk_entry_get_text (GTK_ENTRY (self->password_entry));
438 syncevo_config_set_value (self->config, NULL, "password", password);
440 syncevo_config_get_value (self->config, NULL, "deviceName", &device);
441 if (!device || strlen (device) == 0) {
442 if (!self->config_name || strlen (self->config_name) == 0 ||
443 !sync_url || strlen (sync_url) == 0) {
444 show_error_dialog (GTK_WIDGET (self),
445 _("Service must have a name and server URL"));
450 syncevo_config_foreach_source (self->config,
451 (ConfigFunc)update_source_uri,
454 pretty_name = gtk_entry_get_text (GTK_ENTRY (self->entry));
455 syncevo_config_set_value (self->config, NULL, "PeerName", pretty_name);
456 syncevo_config_get_value (self->config, NULL, "PeerName", &self->pretty_name);
457 syncevo_config_set_value (self->config, NULL, "defaultPeer", self->config_name);
458 sync_config_widget_set_current (self, TRUE);
460 data = g_slice_new (save_config_data);
462 data->delete = FALSE;
463 data->temporary = FALSE;
464 data->basename = g_strdup (self->config_name);
465 syncevo_server_start_no_sync_session (self->server,
467 (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
474 reset_delete_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
476 char *msg, *yes, *no;
477 save_config_data *data;
483 if (self->has_template) {
484 /*TRANSLATORS: warning dialog text for resetting pre-defined
486 msg = g_strdup_printf
487 (_("Do you want to reset the settings for %s? "
488 "This will not remove any synced information on either end."),
490 /*TRANSLATORS: buttons in reset-service warning dialog */
491 yes = _("Yes, reset");
492 no = _("No, keep settings");
494 /*TRANSLATORS: warning dialog text for deleting user-defined
496 msg = g_strdup_printf
497 (_("Do you want to delete the settings for %s? "
498 "This will not remove any synced information on either "
499 "end but it will remove these settings."),
501 /*TRANSLATORS: buttons in delete-service warning dialog */
502 yes = _("Yes, delete");
503 no = _("No, keep settings");
506 /*TRANSLATORS: decline button in "Reset/delete service" warning dialogs */
507 if (!show_confirmation (GTK_WIDGET (self), msg, yes, no)) {
514 sync_config_widget_set_current (self, FALSE);
517 data = g_slice_new (save_config_data);
520 data->temporary = FALSE;
522 syncevo_server_start_no_sync_session (self->server,
524 (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
528 static void update_buttons (SyncConfigWidget *self)
530 if (self->has_template) {
531 /* TRANSLATORS: button labels in service configuration form */
532 gtk_button_set_label (GTK_BUTTON (self->reset_delete_button),
533 _("Reset settings"));
535 gtk_button_set_label (GTK_BUTTON (self->reset_delete_button),
536 _("Delete settings"));
538 if (self->configured) {
539 gtk_widget_show (GTK_WIDGET (self->reset_delete_button));
541 gtk_widget_hide (GTK_WIDGET (self->reset_delete_button));
544 if (self->current || !self->current_service_name) {
545 gtk_button_set_label (GTK_BUTTON (self->use_button),
548 gtk_button_set_label (GTK_BUTTON (self->use_button),
549 _("Save and replace\ncurrent service"));
554 if (self->current && self->config) {
555 if (peer_is_client (self->config)) {
556 gtk_button_set_label (GTK_BUTTON (self->stop_button),
557 _("Stop using device"));
559 gtk_button_set_label (GTK_BUTTON (self->stop_button),
560 _("Stop using service"));
562 gtk_widget_show (self->stop_button);
564 gtk_widget_hide (self->stop_button);
569 mode_widget_notify_active_cb (GtkWidget *widget,
571 SyncConfigWidget *self)
573 self->mode_changed = TRUE;
577 source_entry_notify_text_cb (GObject *gobject,
579 source_widgets *widgets)
581 gboolean new_editable, old_editable;
584 text = gtk_entry_get_text (GTK_ENTRY (widgets->entry));
585 new_editable = (strlen (text) > 0);
586 old_editable = GTK_WIDGET_SENSITIVE (widgets->check);
587 if (new_editable != old_editable) {
588 gtk_widget_set_sensitive (widgets->check, new_editable);
589 toggle_set_active (widgets->check, new_editable);
594 add_toggle_widget (SyncConfigWidget *self,
597 guint row, guint col)
602 padding = (col == 1) ? 0 : 32;
608 label = gtk_label_new (title);
609 gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
610 gtk_widget_set_size_request (label, 260, -1);
611 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
612 gtk_table_attach (GTK_TABLE (self->mode_table), label,
613 col, col + 1, row, row + 1,
614 GTK_FILL, GTK_FILL, 0, 0);
615 toggle = mx_gtk_light_switch_new ();
616 g_signal_connect_swapped (toggle, "hide",
617 G_CALLBACK (gtk_widget_hide), label);
618 g_signal_connect_swapped (toggle, "show",
619 G_CALLBACK (gtk_widget_show), label);
620 toggle_set_active (toggle, active);
621 g_signal_connect (toggle, "switch-flipped",
622 G_CALLBACK (mode_widget_notify_active_cb), self);
624 toggle = gtk_check_button_new_with_label (title);
625 gtk_widget_set_size_request (toggle, 260, -1);
626 toggle_set_active (toggle, active);
627 g_signal_connect (toggle, "notify::active",
628 G_CALLBACK (mode_widget_notify_active_cb), self);
631 gtk_table_attach (GTK_TABLE (self->mode_table), toggle,
632 col + 1, col + 2, row, row + 1,
633 GTK_FILL, GTK_FILL, padding, 0);
639 /* check if config includes a virtual source that covers the given
642 virtual_source_exists (SyncevoConfig *config, const char *name)
645 const char *source_string;
646 GHashTable *source_config;
648 g_hash_table_iter_init (&iter, config);
649 while (g_hash_table_iter_next (&iter,
650 (gpointer)&source_string,
651 (gpointer)&source_config)) {
654 if (g_str_has_prefix (source_string, "source/")) {
655 const char *uri, *type;
656 type = g_hash_table_lookup (source_config, "type");
657 uri = g_hash_table_lookup (source_config, "uri");
659 if (!uri || !type || !g_str_has_prefix (type, "virtual:")) {
660 /* this source is not defined, or not virtual */
664 strs = g_strsplit (source_string + 7, "+", 0);
665 if (g_strv_length (strs) > 1) {
668 for (i = 0; strs[i]; i++) {
669 if (g_strcmp0 (name, strs[i]) == 0) {
683 init_source (char *name,
684 GHashTable *source_configuration,
685 SyncConfigWidget *self)
687 char *str, *pretty_name;
688 const char *uri, *type;
691 static guint col = 0;
692 source_widgets *widgets;
693 SyncevoSyncMode mode;
694 save_config_data *data;
696 type = g_hash_table_lookup (source_configuration, "type");
697 uri = g_hash_table_lookup (source_configuration, "uri");
698 if (!type || strlen (type) == 0) {
702 if (g_str_has_prefix (type, "virtual:") && !uri) {
703 /* undefined virtual source */
707 if (virtual_source_exists (self->config, name)) {
711 g_object_get (self->mode_table,
715 if (!self->no_source_toggles && col == 0) {
722 self->no_source_toggles = FALSE;
724 widgets = g_slice_new0 (source_widgets);
725 widgets->name = name;
727 g_hash_table_insert (self->sources, name, widgets);
729 widgets->source_toggle_label = self->source_toggle_label;
731 pretty_name = get_pretty_source_name (name);
732 mode = syncevo_sync_mode_from_string
733 (g_hash_table_lookup (source_configuration, "sync"));
735 widgets->check = add_toggle_widget (self,
737 (mode > SYNCEVO_SYNC_NONE),
740 /* TRANSLATORS: label for an entry in service configuration form.
741 * Placeholder is a source name.
742 * Example: "Appointments URI" */
743 str = g_strdup_printf (_("%s URI"), pretty_name);
744 widgets->label = gtk_label_new (str);
746 g_free (pretty_name);
748 g_object_get (self->server_settings_table,
752 gtk_misc_set_alignment (GTK_MISC (widgets->label), 0.0, 0.5);
753 gtk_table_attach (GTK_TABLE (self->server_settings_table), widgets->label,
754 0, 1, row, row + 1, GTK_FILL, GTK_EXPAND, 0, 0);
756 widgets->entry = gtk_entry_new ();
757 gtk_entry_set_max_length (GTK_ENTRY (widgets->entry), 99);
758 gtk_entry_set_width_chars (GTK_ENTRY (widgets->entry), 80);
760 gtk_entry_set_text (GTK_ENTRY (widgets->entry), uri);
762 gtk_table_attach_defaults (GTK_TABLE (self->server_settings_table),
765 g_signal_connect (widgets->entry, "notify::text",
766 G_CALLBACK (source_entry_notify_text_cb), widgets);
768 gtk_widget_set_sensitive (widgets->check,
769 uri && strlen (uri) > 0);
771 /* start a session so we save a temporary config so we can do
772 * CheckSource, and show the source-related widgets if the
773 * source is available */
774 data = g_slice_new (save_config_data);
776 data->delete = FALSE;
777 data->temporary = TRUE;
778 data->widgets = source_widgets_ref (widgets);
780 syncevo_server_start_no_sync_session (self->server,
782 (SyncevoServerStartSessionCb)start_session_for_config_write_cb,
787 get_common_mode (char *name,
788 GHashTable *source_configuration,
789 SyncevoSyncMode *common_mode)
791 SyncevoSyncMode mode;
792 char *mode_str, *type;
794 type = g_hash_table_lookup (source_configuration, "type");
795 if (!type || strlen (type) == 0) {
799 mode_str = g_hash_table_lookup (source_configuration, "sync");
800 mode = syncevo_sync_mode_from_string (mode_str);
802 if (mode == SYNCEVO_SYNC_NONE) {
806 if (*common_mode == SYNCEVO_SYNC_NONE) {
808 } else if (mode != *common_mode) {
809 *common_mode = SYNCEVO_SYNC_UNKNOWN;
814 sync_config_widget_expand_id (SyncConfigWidget *self,
817 if (id && self->config) {
820 if (syncevo_config_get_value (self->config, NULL,
821 "syncURL", &sync_url) &&
822 strncmp (sync_url, id, strlen (id)) == 0) {
824 sync_config_widget_set_expanded (self, TRUE);
825 } else if (self->config_name &&
826 g_strcasecmp (self->config_name, id) == 0) {
828 sync_config_widget_set_expanded (self, TRUE);
834 sync_config_widget_update_expander (SyncConfigWidget *self)
841 GtkWidget *label, *align;
842 SyncevoSyncMode mode = SYNCEVO_SYNC_NONE;
843 gboolean send, receive;
846 gtk_container_foreach (GTK_CONTAINER (self->server_settings_table),
847 (GtkCallback)remove_child,
848 self->server_settings_table);
849 gtk_table_resize (GTK_TABLE (self->server_settings_table),
851 gtk_container_foreach (GTK_CONTAINER (self->mode_table),
852 (GtkCallback)remove_child,
854 gtk_table_resize (GTK_TABLE (self->mode_table),
857 client = peer_is_client (self->config);
859 if (!self->device_template_selected) {
860 gtk_widget_hide (self->settings_box);
861 gtk_widget_show (self->device_selector_box);
862 /* temporary solution for device template selection:
863 * show list of templates only */
865 gtk_widget_show (self->settings_box);
866 gtk_widget_hide (self->device_selector_box);
867 gtk_widget_hide (self->userinfo_table);
868 gtk_widget_hide (self->fake_expander);
871 gtk_widget_show (self->settings_box);
872 gtk_widget_hide (self->device_selector_box);
873 gtk_widget_show (self->userinfo_table);
874 gtk_widget_show (self->fake_expander);
877 syncevo_config_foreach_source (self->config,
878 (ConfigFunc)get_common_mode,
881 case SYNCEVO_SYNC_TWO_WAY:
882 send = receive = TRUE;
884 case SYNCEVO_SYNC_ONE_WAY_FROM_CLIENT:
893 case SYNCEVO_SYNC_ONE_WAY_FROM_SERVER:
903 gtk_widget_show (self->complex_config_info_bar);
907 self->mode_changed = FALSE;
910 if (self->pretty_name) {
911 gtk_entry_set_text (GTK_ENTRY (self->entry), self->pretty_name);
913 if (!self->config_name || strlen (self->config_name) == 0) {
914 gtk_expander_set_expanded (GTK_EXPANDER (self->expander), TRUE);
917 descr = get_service_description (self->config_name);
919 gtk_label_set_text (GTK_LABEL (self->description_label),
920 get_service_description (self->config_name));
921 gtk_widget_show (self->description_label);
923 gtk_widget_hide (self->description_label);
926 update_buttons (self);
928 /* TRANSLATORS: toggles in service configuration form, placeholder is service
930 str = g_strdup_printf (_("Send changes to %s"), self->pretty_name);
931 self->send_check = add_toggle_widget (self, str, send, 0, 0);
932 gtk_widget_show (self->send_check);
935 str = g_strdup_printf (_("Receive changes from %s"), self->pretty_name);
936 self->receive_check = add_toggle_widget (self, str, receive, 0, 1);
937 gtk_widget_show (self->receive_check);
940 align = gtk_alignment_new (0.0, 1.0, 0.0, 0.0);
941 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 10, 0, 0, 0);
942 gtk_widget_show (align);
943 gtk_table_attach (GTK_TABLE (self->mode_table), align,
945 GTK_FILL, GTK_FILL, 0, 0);
947 self->source_toggle_label = gtk_label_new ("");
948 /* TRANSLATORS: Label for the source toggles in configuration form.
949 This is a verb, as in "Sync Calendar". */
950 gtk_label_set_markup (GTK_LABEL (self->source_toggle_label),
952 gtk_widget_show (self->source_toggle_label);
953 gtk_container_add (GTK_CONTAINER (align), self->source_toggle_label);
955 syncevo_config_get_value (self->config, NULL, "username", &username);
956 syncevo_config_get_value (self->config, NULL, "password", &password);
957 syncevo_config_get_value (self->config, NULL, "syncURL", &sync_url);
960 gtk_entry_set_text (GTK_ENTRY (self->username_entry), username);
963 gtk_entry_set_text (GTK_ENTRY (self->password_entry), password);
966 // TRANSLATORS: label of a entry in service configuration
967 label = gtk_label_new (_("Server address"));
968 gtk_misc_set_alignment (GTK_MISC (label), 9.0, 0.5);
969 gtk_widget_show (label);
970 gtk_table_attach (GTK_TABLE (self->server_settings_table), label,
971 0, 1, 0, 1, GTK_FILL, GTK_EXPAND, 0, 0);
973 self->baseurl_entry = gtk_entry_new ();
974 gtk_entry_set_max_length (GTK_ENTRY (self->baseurl_entry), 99);
975 gtk_entry_set_width_chars (GTK_ENTRY (self->baseurl_entry), 80);
977 gtk_entry_set_text (GTK_ENTRY (self->baseurl_entry), sync_url);
979 gtk_widget_show (self->baseurl_entry);
981 gtk_table_attach_defaults (GTK_TABLE (self->server_settings_table),
985 /* update source widgets */
987 g_hash_table_destroy (self->sources);
989 self->sources = g_hash_table_new_full (g_str_hash,
992 (GDestroyNotify)source_widgets_unref);
993 self->no_source_toggles = TRUE;
994 syncevo_config_foreach_source (self->config,
995 (ConfigFunc)init_source,
999 /* only adds config to hashtable and combo */
1001 sync_config_widget_add_config (SyncConfigWidget *self,
1003 SyncevoConfig *config)
1005 GtkListStore *store;
1007 const char *guess_name;
1008 SyncevoConfig *guess_config;
1010 int guess_score, second_guess_score = -1;
1013 store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (self->combo)));
1014 if (syncevo_config_get_value (config, NULL, "score", &str)) {
1015 score = (int)strtol (str, NULL, 10);
1017 gtk_list_store_append (store, &iter);
1018 gtk_list_store_set (store, &iter,
1024 /* make an educated guess if possible */
1025 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1026 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
1032 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)) {
1033 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
1034 2, &second_guess_score,
1038 if (guess_score > 1 && guess_score > second_guess_score) {
1039 gtk_combo_box_set_active (GTK_COMBO_BOX (self->combo), 0);
1040 /* TRANSLATORS: explanation before a device template combobox.
1041 * Placeholder is a device name like 'Nokia N85' or 'Syncevolution
1043 str = g_strdup_printf (_("This device looks like it might be a '%s'. "
1044 "If this is not correct, please take a look at "
1045 "the list of supported devices and pick yours "
1046 "if it is listed"), guess_name);
1048 gtk_combo_box_set_active (GTK_COMBO_BOX (self->combo), -1);
1049 str = g_strdup (_("We don't know what this device is exactly. "
1050 "Please take a look at the list of "
1051 "supported devices and pick yours if it "
1054 gtk_label_set_text (GTK_LABEL (self->device_text), str);
1059 sync_config_widget_update_pretty_name (SyncConfigWidget *self)
1061 self->pretty_name = NULL;
1064 syncevo_config_get_value (self->config, NULL,
1065 "PeerName", &self->pretty_name);
1066 if (!self->pretty_name) {
1067 syncevo_config_get_value (self->config, NULL,
1068 "deviceName", &self->pretty_name);
1072 if (!self->pretty_name) {
1073 self->pretty_name = self->config_name;
1078 sync_config_widget_set_config (SyncConfigWidget *self,
1079 SyncevoConfig *config)
1081 self->config = config;
1082 sync_config_widget_update_pretty_name (self);
1087 setup_service_clicked (GtkButton *btn, SyncConfigWidget *self)
1089 sync_config_widget_set_expanded (self, TRUE);
1093 sync_config_widget_set_name (SyncConfigWidget *self,
1096 g_free (self->config_name);
1097 self->config_name = g_strdup (name);
1098 sync_config_widget_update_pretty_name (self);
1103 device_selection_btn_clicked_cb (GtkButton *btn, SyncConfigWidget *self)
1107 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->combo), &iter)) {
1109 SyncevoConfig *config;
1110 GtkTreeModel *model;
1112 self->device_template_selected = TRUE;
1114 model = gtk_combo_box_get_model(GTK_COMBO_BOX (self->combo));
1115 gtk_tree_model_get (model, &iter, 0, &name, -1 );
1116 gtk_tree_model_get (model, &iter, 1, &config, -1 );
1118 sync_config_widget_set_config (self, config);
1120 sync_config_widget_update_expander (self);
1125 server_settings_notify_expand_cb (GtkExpander *expander,
1127 SyncConfigWidget *self)
1129 /* NOTE: expander can be the fake or real one... */
1130 if (gtk_expander_get_expanded (GTK_EXPANDER (self->fake_expander))) {
1131 g_signal_handlers_disconnect_by_func (self->fake_expander,
1132 server_settings_notify_expand_cb,
1135 gtk_widget_hide (self->fake_expander);
1136 gtk_expander_set_expanded (GTK_EXPANDER (self->fake_expander), FALSE);
1137 gtk_expander_set_expanded (GTK_EXPANDER (self->expander), TRUE);
1138 gtk_widget_show (self->expander);
1140 g_signal_connect (self->expander, "notify::expanded",
1141 G_CALLBACK (server_settings_notify_expand_cb), self);
1143 g_signal_handlers_disconnect_by_func (self->expander,
1144 server_settings_notify_expand_cb,
1147 gtk_widget_hide (self->expander);
1148 gtk_widget_show (self->fake_expander);
1150 g_signal_connect (self->fake_expander, "notify::expanded",
1151 G_CALLBACK (server_settings_notify_expand_cb), self);
1156 load_icon (const char *uri, guint icon_size)
1158 GError *error = NULL;
1160 const char *filename;
1162 if (uri && strlen (uri) > 0) {
1163 if (g_str_has_prefix (uri, "file://")) {
1166 g_warning ("only file:// icon uri is supported: %s", uri);
1167 filename = THEMEDIR "sync-generic.png";
1170 filename = THEMEDIR "sync-generic.png";
1172 pixbuf = gdk_pixbuf_new_from_file_at_scale (filename,
1173 icon_size, icon_size,
1177 g_warning ("Failed to load service icon: %s", error->message);
1178 g_error_free (error);
1186 sync_config_widget_update_label (SyncConfigWidget *self)
1188 if (self->config && self->pretty_name) {
1189 char *url, *sync_url;
1192 syncevo_config_get_value (self->config, NULL, "WebURL", &url);
1193 syncevo_config_get_value (self->config, NULL, "syncURL", &sync_url);
1195 if (self->current) {
1196 str = g_strdup_printf ("<b>%s</b>", self->pretty_name);
1198 str = g_strdup_printf ("%s", self->pretty_name);
1200 if (g_str_has_prefix (sync_url, "obex-bt://")) {
1201 char *tmp = g_strdup_printf (_("%s - Bluetooth device"), str);
1204 } else if (!self->has_template) {
1205 /* TRANSLATORS: service title for services that are not based on a
1206 * template in service list, the placeholder is the name of the service */
1207 char *tmp = g_strdup_printf (_("%s - manually setup"), str);
1210 } else if (url && strlen (url) > 0) {
1211 char *tmp = g_strdup_printf ("%s -",str);
1216 gtk_label_set_markup (GTK_LABEL (self->label), str);
1222 sync_config_widget_set_current_service_name (SyncConfigWidget *self,
1225 g_free (self->current_service_name);
1226 self->current_service_name = g_strdup (name);
1228 update_buttons (self);
1232 sync_config_widget_set_current (SyncConfigWidget *self,
1235 if (self->current != current) {
1236 self->current = current;
1237 sync_config_widget_update_label (self);
1242 set_session (SyncConfigWidget *self, const char *path)
1244 g_free (self->running_session);
1245 self->running_session = g_strdup (path);
1247 gtk_widget_set_sensitive (GTK_WIDGET (self->reset_delete_button),
1248 !self->running_session);
1249 gtk_widget_set_sensitive (GTK_WIDGET (self->use_button),
1250 !self->running_session);
1252 /* TODO: maybe add a explanation text somewhere:
1253 * "Configuration changes are not possible while a sync is in progress" */
1257 session_changed_cb (SyncevoServer *server,
1260 SyncConfigWidget *self)
1263 set_session (self, path);
1264 } else if (g_strcmp0 (self->running_session, path) == 0 ) {
1265 set_session (self, NULL);
1270 get_sessions_cb (SyncevoServer *server,
1271 SyncevoSessions *sessions,
1273 SyncConfigWidget *self)
1276 g_warning ("Server.GetSessions failed: %s", error->message);
1277 g_error_free (error);
1278 /* non-fatal, ignore in UI */
1280 g_object_unref (self);
1284 set_session (self, syncevo_sessions_index (sessions, 0));
1285 syncevo_sessions_free (sessions);
1286 g_object_unref (self);
1290 sync_config_widget_set_server (SyncConfigWidget *self,
1291 SyncevoServer *server)
1294 g_signal_handlers_disconnect_by_func (self->server,
1297 g_object_unref (self->server);
1298 self->server = NULL;
1300 if (!server && !self->server) {
1304 self->server = g_object_ref (server);
1306 /* monitor sessions so we can set editing buttons insensitive */
1307 g_signal_connect (self->server, "session-changed",
1308 G_CALLBACK (session_changed_cb), self);
1310 /* reference is released in callback */
1311 g_object_ref (self);
1312 syncevo_server_get_sessions (self->server,
1313 (SyncevoServerGetSessionsCb)get_sessions_cb,
1318 sync_config_widget_set_property (GObject *object,
1320 const GValue *value,
1323 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
1325 switch (property_id) {
1327 sync_config_widget_set_server (self, g_value_get_pointer (value));
1330 sync_config_widget_set_name (self, g_value_get_string (value));
1333 sync_config_widget_set_config (self, g_value_get_pointer (value));
1336 sync_config_widget_set_current (self, g_value_get_boolean (value));
1338 case PROP_HAS_TEMPLATE:
1339 sync_config_widget_set_has_template (self, g_value_get_boolean (value));
1341 case PROP_CONFIGURED:
1342 sync_config_widget_set_configured (self, g_value_get_boolean (value));
1344 case PROP_CURRENT_SERVICE_NAME:
1345 sync_config_widget_set_current_service_name (self, g_value_get_string (value));
1348 sync_config_widget_set_expanded (self, g_value_get_boolean (value));
1351 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1356 sync_config_widget_get_property (GObject *object,
1361 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
1363 switch (property_id) {
1365 g_value_set_pointer (value, self->server);
1367 g_value_set_string (value, self->config_name);
1369 g_value_set_pointer (value, self->config);
1371 g_value_set_boolean (value, self->current);
1372 case PROP_HAS_TEMPLATE:
1373 g_value_set_boolean (value, self->has_template);
1374 case PROP_CONFIGURED:
1375 g_value_set_boolean (value, self->configured);
1376 case PROP_CURRENT_SERVICE_NAME:
1377 g_value_set_string (value, self->current_service_name);
1379 g_value_set_boolean (value, self->expanded);
1381 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1386 sync_config_widget_dispose (GObject *object)
1388 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (object);
1390 sync_config_widget_set_server (self, NULL);
1392 syncevo_config_free (self->config);
1394 self->config = NULL;
1396 g_free (self->config_name);
1397 self->config_name = NULL;
1398 g_free (self->current_service_name);
1399 self->current_service_name = NULL;
1400 g_free (self->running_session);
1401 self->running_session = NULL;
1402 if (self->sources) {
1403 g_hash_table_destroy (self->sources);
1404 self->sources = NULL;
1409 G_OBJECT_CLASS (sync_config_widget_parent_class)->dispose (object);
1413 init_default_config (SyncConfigWidget *self)
1415 sync_config_widget_set_name (self, "");
1416 self->has_template = FALSE;
1418 syncevo_config_set_value (self->config, NULL, "username", "");
1419 syncevo_config_set_value (self->config, NULL, "password", "");
1420 syncevo_config_set_value (self->config, NULL, "syncURL", "");
1421 syncevo_config_set_value (self->config, NULL, "WebURL", "");
1422 syncevo_config_set_value (self->config, "memo", "uri", "");
1423 syncevo_config_set_value (self->config, "todo", "uri", "");
1424 syncevo_config_set_value (self->config, "addressbook", "uri", "");
1425 syncevo_config_set_value (self->config, "calendar", "uri", "");
1430 label_button_expose_cb (GtkWidget *widget,
1431 GdkEventExpose *event,
1432 SyncConfigWidget *self)
1434 GtkExpanderStyle style;
1435 gint indicator_x, indicator_y;
1437 indicator_x = widget->style->xthickness + INDICATOR_SIZE / 2;
1438 indicator_y = widget->style->ythickness +
1439 widget->allocation.height / 2;
1441 if (self->expanded) {
1442 style = GTK_EXPANDER_EXPANDED;
1444 style = GTK_EXPANDER_COLLAPSED;
1447 gtk_paint_expander (widget->style,
1461 sync_config_widget_expose_event (GtkWidget *widget,
1462 GdkEventExpose *event)
1465 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
1467 rect.x = widget->allocation.x;
1468 rect.y = widget->allocation.y;
1469 rect.height = widget->allocation.height;
1470 rect.width = widget->allocation.width;
1472 gtk_paint_box (widget->style,
1484 gtk_container_propagate_expose (GTK_CONTAINER (self),
1485 self->label_box, event);
1486 gtk_container_propagate_expose (GTK_CONTAINER (self),
1487 self->expando_box, event);
1494 sync_config_widget_size_allocate (GtkWidget *widget,
1495 GtkAllocation *allocation)
1498 GtkAllocation alloc;
1499 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
1501 GTK_WIDGET_CLASS (sync_config_widget_parent_class)->size_allocate (widget,
1504 gtk_widget_size_request (self->label_box, &req);
1506 alloc.x = allocation->x + widget->style->xthickness;
1507 alloc.y = allocation->y + widget->style->ythickness;
1508 alloc.width = allocation->width - 2 * widget->style->xthickness;
1509 alloc.height = req.height;
1511 gtk_widget_size_allocate (self->label_box, &alloc);
1514 if (self->expanded) {
1515 gtk_widget_size_request (self->expando_box, &req);
1517 alloc.x = allocation->x + 2 * widget->style->xthickness;
1518 alloc.y = allocation->y + widget->style->ythickness +
1519 alloc.height + CHILD_PADDING;
1520 alloc.width = allocation->width - 4 * widget->style->xthickness;
1521 alloc.height = req.height;
1523 gtk_widget_size_allocate (self->expando_box, &alloc);
1528 sync_config_widget_size_request (GtkWidget *widget,
1529 GtkRequisition *requisition)
1531 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
1534 requisition->width = widget->style->xthickness * 2;
1535 requisition->height = widget->style->ythickness * 2;
1537 gtk_widget_size_request (self->label_box, &req);
1539 requisition->width += req.width;
1540 requisition->height = MAX (req.height, INDICATOR_SIZE) +
1541 widget->style->ythickness * 2;
1543 if (self->expanded) {
1545 gtk_widget_size_request (self->expando_box, &req);
1546 requisition->width = MAX (requisition->width,
1547 req.width + widget->style->xthickness * 4);
1548 requisition->height += req.height + 2 * widget->style->ythickness;
1553 sync_config_widget_constructor (GType gtype,
1555 GObjectConstructParam *properties)
1557 SyncConfigWidget *self;
1558 GObjectClass *parent_class;
1562 parent_class = G_OBJECT_CLASS (sync_config_widget_parent_class);
1563 self = SYNC_CONFIG_WIDGET (parent_class->constructor (gtype,
1567 if (!self->config || !self->server) {
1568 g_warning ("No SyncevoServer or Syncevoconfig set for SyncConfigWidget");
1569 return G_OBJECT (self);
1572 if (g_strcmp0 (self->config_name, "default") == 0) {
1574 init_default_config (self);
1575 gtk_widget_show (self->entry);
1576 gtk_widget_hide (self->label);
1578 gtk_widget_hide (self->entry);
1579 gtk_widget_show (self->label);
1582 syncevo_config_get_value (self->config, NULL, "WebURL", &url);
1583 syncevo_config_get_value (self->config, NULL, "IconURI", &icon);
1585 buf = load_icon (icon, SYNC_UI_LIST_ICON_SIZE);
1586 gtk_image_set_from_pixbuf (GTK_IMAGE (self->image), buf);
1587 g_object_unref (buf);
1589 if (url && strlen (url) > 0) {
1590 gtk_link_button_set_uri (GTK_LINK_BUTTON (self->link), url);
1591 gtk_widget_show (self->link);
1593 gtk_widget_hide (self->link);
1596 sync_config_widget_update_label (self);
1597 sync_config_widget_update_expander (self);
1599 /* hack to get focus in the right place on "Setup new service" */
1600 if (GTK_WIDGET_VISIBLE (self->entry)) {
1601 gtk_widget_grab_focus (self->entry);
1604 return G_OBJECT (self);
1608 sync_config_widget_map (GtkWidget *widget)
1610 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
1612 if (self->label_box && GTK_WIDGET_VISIBLE (self->expando_box)) {
1613 gtk_widget_map (self->label_box);
1615 if (self->expando_box && GTK_WIDGET_VISIBLE (self->expando_box)) {
1616 gtk_widget_map (self->expando_box);
1618 GTK_WIDGET_CLASS (sync_config_widget_parent_class)->map (widget);
1622 sync_config_widget_unmap (GtkWidget *widget)
1624 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (widget);
1626 GTK_WIDGET_CLASS (sync_config_widget_parent_class)->unmap (widget);
1628 if (self->label_box) {
1629 gtk_widget_unmap (self->label_box);
1631 if (self->expando_box) {
1632 gtk_widget_unmap (self->expando_box);
1637 sync_config_widget_add (GtkContainer *container,
1640 g_warning ("Can't add widgets in to SyncConfigWidget!");
1644 sync_config_widget_remove (GtkContainer *container,
1647 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (container);
1650 if (self->label_box == widget) {
1651 gtk_widget_unparent (widget);
1652 self->label_box = NULL;
1654 if (self->expando_box == widget) {
1655 gtk_widget_unparent (widget);
1656 self->expando_box = NULL;
1661 sync_config_widget_forall (GtkContainer *container,
1662 gboolean include_internals,
1663 GtkCallback callback,
1664 gpointer callback_data)
1666 SyncConfigWidget *self = SYNC_CONFIG_WIDGET (container);
1668 if (self->label_box) {
1669 (* callback) (self->label_box, callback_data);
1671 if (self->expando_box) {
1672 (* callback) (self->expando_box, callback_data);
1678 sync_config_widget_class_init (SyncConfigWidgetClass *klass)
1680 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1681 GtkWidgetClass *w_class = GTK_WIDGET_CLASS (klass);
1682 GtkContainerClass *c_class = GTK_CONTAINER_CLASS (klass);
1685 object_class->set_property = sync_config_widget_set_property;
1686 object_class->get_property = sync_config_widget_get_property;
1687 object_class->dispose = sync_config_widget_dispose;
1688 object_class->constructor = sync_config_widget_constructor;
1690 w_class->expose_event = sync_config_widget_expose_event;
1691 w_class->size_request = sync_config_widget_size_request;
1692 w_class->size_allocate = sync_config_widget_size_allocate;
1693 w_class->map = sync_config_widget_map;
1694 w_class->unmap = sync_config_widget_unmap;
1696 c_class->add = sync_config_widget_add;
1697 c_class->remove = sync_config_widget_remove;
1698 c_class->forall = sync_config_widget_forall;
1700 pspec = g_param_spec_pointer ("server",
1702 "The SyncevoServer to use in Syncevolution DBus calls",
1703 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1704 g_object_class_install_property (object_class, PROP_SERVER, pspec);
1706 pspec = g_param_spec_string ("name",
1707 "Configuration name",
1708 "The name of the Syncevolution service configuration",
1710 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1711 g_object_class_install_property (object_class, PROP_NAME, pspec);
1713 pspec = g_param_spec_pointer ("config",
1715 "The SyncevoConfig struct this widget represents. Takes ownership.",
1716 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1717 g_object_class_install_property (object_class, PROP_CONFIG, pspec);
1719 pspec = g_param_spec_boolean ("current",
1721 "Whether the service is currently used",
1724 g_object_class_install_property (object_class, PROP_CURRENT, pspec);
1726 pspec = g_param_spec_boolean ("has-template",
1728 "Whether the service has a matching template",
1730 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1731 g_object_class_install_property (object_class, PROP_HAS_TEMPLATE, pspec);
1733 pspec = g_param_spec_boolean ("configured",
1735 "Whether the service has a configuration already",
1737 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
1738 g_object_class_install_property (object_class, PROP_CONFIGURED, pspec);
1740 pspec = g_param_spec_string ("current-service-name",
1741 "Current service name",
1742 "The name of the currently used service or NULL",
1745 g_object_class_install_property (object_class, PROP_CURRENT_SERVICE_NAME, pspec);
1747 pspec = g_param_spec_boolean ("expanded",
1749 "Whether the expander is open or closed",
1752 g_object_class_install_property (object_class, PROP_EXPANDED, pspec);
1754 signals[SIGNAL_CHANGED] =
1755 g_signal_new ("changed",
1756 G_TYPE_FROM_CLASS (klass),
1757 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
1758 G_STRUCT_OFFSET (SyncConfigWidgetClass, changed),
1760 g_cclosure_marshal_VOID__VOID,
1767 label_enter_notify_cb (GtkWidget *widget,
1768 GdkEventCrossing *event,
1769 SyncConfigWidget *self)
1771 if (!self->expanded) {
1772 gtk_widget_show (self->button);
1774 gtk_widget_set_state (self->label_box, GTK_STATE_PRELIGHT);
1778 label_leave_notify_cb (GtkWidget *widget,
1779 GdkEventCrossing *event,
1780 SyncConfigWidget *self)
1782 if (event->detail != GDK_NOTIFY_INFERIOR) {
1783 gtk_widget_hide (self->button);
1784 gtk_widget_set_state (self->label_box, GTK_STATE_NORMAL);
1789 device_combo_changed (GtkComboBox *combo,
1790 SyncConfigWidget *self)
1794 selected = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo));
1795 gtk_widget_set_sensitive (self->device_select_btn, selected != NULL);
1799 label_button_release_cb (GtkWidget *widget,
1800 GdkEventButton *event,
1801 SyncConfigWidget *self)
1804 if (event->button == 1) {
1805 sync_config_widget_set_expanded (self,
1806 !sync_config_widget_get_expanded (self));
1811 compare_list_items (GtkTreeModel *model,
1814 SyncConfigWidget *self)
1816 int score_a, score_b;
1818 gtk_tree_model_get(model, a, 2, &score_a, -1);
1819 gtk_tree_model_get(model, b, 2, &score_b, -1);
1821 return score_a - score_b;
1825 sync_config_widget_init (SyncConfigWidget *self)
1827 GtkWidget *tmp_box, *hbox, *cont, *vbox, *label;
1828 GtkListStore *store;
1829 GtkCellRenderer *renderer;
1831 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (self), GTK_NO_WINDOW);
1833 self->label_box = gtk_event_box_new ();
1834 gtk_widget_set_app_paintable (self->label_box, TRUE);
1835 gtk_widget_show (self->label_box);
1836 gtk_widget_set_parent (self->label_box, GTK_WIDGET (self));
1837 gtk_widget_set_size_request (self->label_box, -1, SYNC_UI_LIST_ICON_SIZE + 6);
1838 g_signal_connect (self->label_box, "enter-notify-event",
1839 G_CALLBACK (label_enter_notify_cb), self);
1840 g_signal_connect (self->label_box, "leave-notify-event",
1841 G_CALLBACK (label_leave_notify_cb), self);
1842 g_signal_connect (self->label_box, "button-release-event",
1843 G_CALLBACK (label_button_release_cb), self);
1844 g_signal_connect (self->label_box, "expose-event",
1845 G_CALLBACK (label_button_expose_cb), self);
1847 hbox = gtk_hbox_new (FALSE, 0);
1848 gtk_widget_show (hbox);
1849 gtk_container_add (GTK_CONTAINER (self->label_box), hbox);
1851 self->image = gtk_image_new ();
1852 /* leave room for drawing the expander indicator in expose handler */
1853 gtk_widget_set_size_request (self->image,
1854 SYNC_UI_LIST_ICON_SIZE + INDICATOR_SIZE,
1855 SYNC_UI_LIST_ICON_SIZE);
1856 gtk_misc_set_alignment (GTK_MISC (self->image), 1.0, 0.5);
1857 gtk_widget_show (self->image);
1858 gtk_box_pack_start (GTK_BOX (hbox), self->image, FALSE, FALSE, 8);
1860 tmp_box = gtk_hbox_new (FALSE, 0);
1861 gtk_widget_show (tmp_box);
1862 gtk_box_pack_start (GTK_BOX (hbox), tmp_box, FALSE, FALSE, 8);
1864 self->label = gtk_label_new ("");
1865 gtk_label_set_max_width_chars (GTK_LABEL (self->label), 60);
1866 gtk_label_set_ellipsize (GTK_LABEL (self->label), PANGO_ELLIPSIZE_END);
1867 gtk_misc_set_alignment (GTK_MISC (self->label), 0.0, 0.5);
1868 gtk_widget_show (self->label);
1869 gtk_box_pack_start (GTK_BOX (tmp_box), self->label, FALSE, FALSE, 0);
1871 self->entry = gtk_entry_new ();
1872 gtk_widget_set_no_show_all (self->entry, TRUE);
1873 gtk_box_pack_start (GTK_BOX (tmp_box), self->entry, FALSE, FALSE, 4);
1875 vbox = gtk_vbox_new (FALSE, 0);
1876 gtk_widget_show (vbox);
1877 gtk_box_pack_start (GTK_BOX (tmp_box), vbox, FALSE, FALSE, 0);
1879 /* TRANSLATORS: link button in service configuration form */
1880 self->link = gtk_link_button_new_with_label ("", _("Launch website"));
1881 gtk_widget_set_no_show_all (self->link, TRUE);
1882 gtk_box_pack_start (GTK_BOX (vbox), self->link, TRUE, FALSE, 0);
1884 vbox = gtk_vbox_new (FALSE, 0);
1885 gtk_widget_show (vbox);
1886 gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 32);
1888 /* TRANSLATORS: button in service configuration form */
1889 self->button = gtk_button_new_with_label (_("Setup now"));
1890 gtk_widget_set_size_request (self->button, SYNC_UI_LIST_BTN_WIDTH, -1);
1891 g_signal_connect (self->button, "clicked",
1892 G_CALLBACK (setup_service_clicked), self);
1893 gtk_box_pack_start (GTK_BOX (vbox), self->button, TRUE, FALSE, 0);
1895 /* label_box built, now build expando_box */
1897 self->expando_box = gtk_hbox_new (FALSE, 0);
1898 gtk_widget_set_no_show_all (self->expando_box, TRUE);
1899 gtk_widget_set_parent (self->expando_box, GTK_WIDGET (self));
1901 self->device_selector_box = gtk_vbox_new (FALSE, 0);
1902 gtk_box_pack_start (GTK_BOX (self->expando_box), self->device_selector_box,
1905 hbox = gtk_hbox_new (FALSE, 8);
1906 gtk_widget_show (hbox);
1907 gtk_box_pack_start (GTK_BOX (self->device_selector_box), hbox,
1909 self->device_text = gtk_label_new (("We don't know what this device is exactly. "
1910 "Please take a look at the list of "
1911 "supported devices and pick yours if it "
1913 gtk_widget_show (self->device_text);
1914 gtk_label_set_line_wrap (GTK_LABEL (self->device_text), TRUE);
1915 gtk_widget_set_size_request (self->device_text, 600, -1);
1916 gtk_box_pack_start (GTK_BOX (hbox), self->device_text,
1920 hbox = gtk_hbox_new (FALSE, 16);
1921 gtk_widget_show (hbox);
1922 gtk_box_pack_start (GTK_BOX (self->device_selector_box), hbox,
1925 store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
1926 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
1927 2, GTK_SORT_DESCENDING);
1928 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), 2,
1929 (GtkTreeIterCompareFunc)compare_list_items,
1932 self->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
1933 g_object_unref (G_OBJECT (store));
1934 gtk_widget_set_size_request (self->combo, 200, -1);
1935 gtk_widget_show (self->combo);
1936 gtk_box_pack_start (GTK_BOX (hbox), self->combo, FALSE, TRUE, 0);
1938 renderer = gtk_cell_renderer_text_new ();
1939 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(self->combo), renderer, TRUE);
1940 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(self->combo), renderer,
1943 g_signal_connect (self->combo, "changed",
1944 G_CALLBACK (device_combo_changed), self);
1947 self->device_select_btn = gtk_button_new_with_label ("Use these settings");
1948 gtk_widget_set_sensitive (self->device_select_btn, FALSE);
1949 gtk_widget_show (self->device_select_btn);
1950 gtk_box_pack_start (GTK_BOX (hbox), self->device_select_btn,
1952 g_signal_connect (self->device_select_btn, "clicked",
1953 G_CALLBACK (device_selection_btn_clicked_cb), self);
1955 /* settings_box has normal expander contents */
1956 self->settings_box = gtk_vbox_new (FALSE, 0);
1957 gtk_widget_show (self->settings_box);
1958 gtk_box_pack_start (GTK_BOX (self->expando_box), self->settings_box,
1961 vbox = gtk_vbox_new (FALSE, 8);
1962 gtk_widget_show (vbox);
1963 gtk_box_pack_start (GTK_BOX (self->settings_box), vbox, TRUE, TRUE, 0);
1965 tmp_box = gtk_vbox_new (FALSE, 0);
1966 gtk_widget_show (tmp_box);
1967 gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 8);
1969 self->description_label = gtk_label_new ("");
1970 gtk_misc_set_alignment (GTK_MISC (self->description_label), 0.0, 0.5);
1971 gtk_widget_set_size_request (self->description_label, 700, -1);
1972 gtk_box_pack_start (GTK_BOX (tmp_box), self->description_label, FALSE, FALSE, 0);
1974 tmp_box = gtk_hbox_new (FALSE, 0);
1975 gtk_widget_show (tmp_box);
1976 gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 0);
1978 self->userinfo_table = gtk_table_new (4, 2, FALSE);
1979 gtk_table_set_row_spacings (GTK_TABLE (self->userinfo_table), 2);
1980 gtk_table_set_col_spacings (GTK_TABLE (self->userinfo_table), 5);
1981 gtk_widget_show (self->userinfo_table);
1982 gtk_box_pack_start (GTK_BOX (tmp_box), self->userinfo_table, FALSE, FALSE, 0);
1984 /* TRANSLATORS: labels of entries in service configuration form */
1985 label = gtk_label_new (_("Username"));
1986 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1987 gtk_widget_show (label);
1988 gtk_table_attach_defaults (GTK_TABLE (self->userinfo_table), label,
1992 self->username_entry = gtk_entry_new ();
1993 gtk_widget_show (self->username_entry);
1994 gtk_entry_set_width_chars (GTK_ENTRY (self->username_entry), 40);
1995 gtk_entry_set_max_length (GTK_ENTRY (self->username_entry), 99);
1996 gtk_table_attach_defaults (GTK_TABLE (self->userinfo_table), self->username_entry,
2000 label = gtk_label_new (_("Password"));
2001 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2002 gtk_widget_show (label);
2003 gtk_table_attach_defaults (GTK_TABLE (self->userinfo_table), label,
2007 self->password_entry = gtk_entry_new ();
2008 gtk_widget_show (self->password_entry);
2009 gtk_entry_set_width_chars (GTK_ENTRY (self->password_entry), 40);
2010 gtk_entry_set_visibility (GTK_ENTRY (self->password_entry), FALSE);
2011 gtk_entry_set_max_length (GTK_ENTRY (self->password_entry), 99);
2012 gtk_table_attach_defaults (GTK_TABLE (self->userinfo_table), self->password_entry,
2016 self->complex_config_info_bar = gtk_info_bar_new ();
2017 gtk_info_bar_set_message_type (GTK_INFO_BAR (self->complex_config_info_bar),
2018 GTK_MESSAGE_WARNING);
2019 gtk_box_pack_start (GTK_BOX (vbox), self->complex_config_info_bar,
2021 /* TRANSLATORS: warning in service configuration form for people
2022 who have modified the configuration via other means. */
2023 label = gtk_label_new (_("Current configuration is more complex "
2024 "than what can be shown here. Changes to sync "
2025 "mode or synced data types will overwrite that "
2027 gtk_widget_set_size_request (label, 600, -1);
2028 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
2029 gtk_widget_show (label);
2030 cont = gtk_info_bar_get_content_area (
2031 GTK_INFO_BAR (self->complex_config_info_bar));
2032 gtk_container_add (GTK_CONTAINER (cont), label);
2034 self->mode_table = gtk_table_new (4, 1, FALSE);
2035 gtk_table_set_row_spacings (GTK_TABLE (self->mode_table), 2);
2036 gtk_table_set_col_spacings (GTK_TABLE (self->mode_table), 5);
2037 gtk_widget_show (self->mode_table);
2038 gtk_box_pack_start (GTK_BOX (vbox), self->mode_table, FALSE, FALSE, 0);
2040 /* TRANSLATORS: this is the epander label for server settings
2041 in service configuration form */
2042 self->expander = gtk_expander_new (_("Hide server settings"));
2043 gtk_box_pack_start (GTK_BOX (vbox), self->expander, FALSE, FALSE, 8);
2045 tmp_box = gtk_hbox_new (FALSE, 0);
2046 gtk_widget_show (tmp_box);
2047 gtk_container_add (GTK_CONTAINER (self->expander), tmp_box);
2049 self->server_settings_table = gtk_table_new (1, 1, FALSE);
2050 gtk_table_set_row_spacings (GTK_TABLE (self->server_settings_table), 2);
2051 gtk_table_set_col_spacings (GTK_TABLE (self->server_settings_table), 5);
2052 gtk_widget_show (self->server_settings_table);
2053 gtk_box_pack_start (GTK_BOX (tmp_box), self->server_settings_table, FALSE, FALSE, 0);
2056 tmp_box = gtk_hbox_new (FALSE, 0);
2057 gtk_widget_show (tmp_box);
2058 gtk_box_pack_start (GTK_BOX (vbox), tmp_box, FALSE, FALSE, 8);
2060 /* TRANSLATORS: this is the epander label for server settings
2061 in service configuration form */
2062 self->fake_expander = gtk_expander_new (_("Show server settings"));
2063 gtk_widget_show (self->fake_expander);
2064 gtk_box_pack_start (GTK_BOX (tmp_box), self->fake_expander, FALSE, FALSE, 0);
2065 g_signal_connect (self->fake_expander, "notify::expanded",
2066 G_CALLBACK (server_settings_notify_expand_cb), self);
2068 self->use_button = gtk_button_new ();
2069 gtk_widget_show (self->use_button);
2070 gtk_box_pack_end (GTK_BOX (tmp_box), self->use_button, FALSE, FALSE, 8);
2071 g_signal_connect (self->use_button, "clicked",
2072 G_CALLBACK (use_clicked_cb), self);
2074 self->stop_button = gtk_button_new ();
2075 gtk_box_pack_end (GTK_BOX (tmp_box), self->stop_button, FALSE, FALSE, 8);
2076 g_signal_connect (self->stop_button, "clicked",
2077 G_CALLBACK (stop_clicked_cb), self);
2079 self->reset_delete_button = gtk_button_new ();
2080 gtk_widget_show (self->reset_delete_button);
2081 gtk_box_pack_end (GTK_BOX (tmp_box), self->reset_delete_button, FALSE, FALSE, 8);
2082 g_signal_connect (self->reset_delete_button, "clicked",
2083 G_CALLBACK (reset_delete_clicked_cb), self);
2088 sync_config_widget_new (SyncevoServer *server,
2090 SyncevoConfig *config,
2092 const char *current_service_name,
2093 gboolean configured,
2094 gboolean has_template)
2096 return g_object_new (SYNC_TYPE_CONFIG_WIDGET,
2101 "current-service-name", current_service_name,
2102 "configured", configured,
2103 "has-template", has_template,
2108 sync_config_widget_set_expanded (SyncConfigWidget *self, gboolean expanded)
2110 g_return_if_fail (SYNC_IS_CONFIG_WIDGET (self));
2112 if (self->expanded != expanded) {
2114 self->expanded = expanded;
2115 if (self->expanded) {
2116 gtk_widget_hide (self->button);
2117 gtk_widget_show (self->expando_box);
2118 if (GTK_WIDGET_VISIBLE (self->entry)) {
2119 gtk_widget_grab_focus (self->entry);
2121 gtk_widget_grab_focus (self->username_entry);
2124 gtk_widget_show (self->button);
2125 gtk_widget_hide (self->expando_box);
2127 g_object_notify (G_OBJECT (self), "expanded");
2133 sync_config_widget_get_expanded (SyncConfigWidget *self)
2135 return self->expanded;
2139 sync_config_widget_set_has_template (SyncConfigWidget *self, gboolean has_template)
2141 if (self->has_template != has_template) {
2142 self->has_template = has_template;
2143 update_buttons (self);
2144 sync_config_widget_update_label (self);
2149 sync_config_widget_get_has_template (SyncConfigWidget *self)
2151 return self->has_template;
2155 sync_config_widget_set_configured (SyncConfigWidget *self, gboolean configured)
2157 if (self->configured != configured) {
2158 self->configured = configured;
2159 self->device_template_selected = configured;
2160 update_buttons (self);
2165 sync_config_widget_get_configured (SyncConfigWidget *self)
2167 return self->configured;
2172 sync_config_widget_get_current (SyncConfigWidget *widget)
2174 return widget->current;
2178 sync_config_widget_get_name (SyncConfigWidget *widget)
2180 return widget->config_name;
2184 sync_config_widget_add_alternative_config (SyncConfigWidget *self,
2185 const char *template_name,
2186 SyncevoConfig *config,
2187 gboolean configured)
2189 sync_config_widget_add_config (self, template_name, config);
2191 sync_config_widget_set_config (self, config);
2192 sync_config_widget_set_configured (self, TRUE);
2196 sync_config_widget_update_expander (self);