#include #include #include #include #include #include #include #include #include #include "sync_main.h" #include "sync_collection.h" #include "sync_group.h" #include "sync_item.h" #include "sync_evo2_item.h" #include "sync_file_item.h" #include "sync_syncml_item.h" #include "sync_syncml_server_item.h" #include "sync_gcal_item.h" static gboolean sync_animate (SyncData *data) { static gint direction = 1; static gint count = 0; if (data->started) { gfloat x, y; GtkWidget *widget = glade_xml_get_widget ( data->xml, "sync_image_mid"); gtk_misc_get_alignment (GTK_MISC (widget), &x, &y); x += 0.05 * direction; if ((x > 1) || (x < 0)) { direction = -direction; } gtk_misc_set_alignment (GTK_MISC (widget), x, y); } else { count ++; if (count >= ANIM_FREQ / SWITCH_FREQ) { GtkWidget *widget = glade_xml_get_widget (data->xml, "prepare_image"); count = 0; if (direction == 1) { gtk_image_set_from_icon_name ( GTK_IMAGE (widget), "gtk-connect", GTK_ICON_SIZE_DIALOG); } else { gtk_image_set_from_icon_name ( GTK_IMAGE (widget), "gtk-disconnect", GTK_ICON_SIZE_DIALOG); } direction = -direction; } } return TRUE; } static void sync_server_started_cb (SyncGroup *group) { g_message ("Server started sync"); } static void sync_server_finished_cb (SyncGroup *group) { g_message ("Server finished sync"); sync_group_autostart (group); } static void sync_server_failed_cb (SyncGroup *group, const gchar *error, SyncData *data) { GtkWidget *dialog, *window; g_warning ("Server sync failed"); window = glade_xml_get_widget (data->xml, "main_window"); dialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "There was an error starting the synchronisation server:\n" "\"%s\"\nWould you like to restart the server?", error); gtk_dialog_add_buttons (GTK_DIALOG (dialog), "_Disable server", GTK_RESPONSE_CANCEL, "_Restart server", GTK_RESPONSE_OK, NULL); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { sync_group_autostart (group); } else { gchar *new_title = g_strconcat (gtk_window_get_title ( GTK_WINDOW (window)), " - Server disabled", NULL); gtk_window_set_title (GTK_WINDOW (window), new_title); g_free (new_title); } gtk_widget_destroy (dialog); } static void sync_started_cb (SyncCollection *collection, SyncData *data) { GtkWidget *widget = glade_xml_get_widget ( data->xml, "sync_progressbar"); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (widget), "Synchronising..."); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), 0); widget = glade_xml_get_widget ( data->xml, "sync_image_notebook"); gtk_notebook_set_current_page ( GTK_NOTEBOOK (widget), IMAGE_TAB_SYNC); data->started = TRUE; } static void sync_progress_cb (SyncCollection *collection, gdouble progress, SyncData *data) { GtkWidget *widget = glade_xml_get_widget ( data->xml, "sync_progressbar"); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), progress); } static void sync_conflict_cb (SyncCollection *collection, SyncGroup *group, SyncData *data) { GtkWidget *widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_CONFLICT); data->group = group; } static void sync_finished_cb (SyncCollection *collection, SyncData *data) { GtkWidget *widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_SUCCESS); g_source_remove (data->animate_id); sync_collection_remove_all (collection); } static void sync_failed_cb (SyncCollection *collection, const gchar *error, SyncData *data) { GtkTextBuffer *buffer; GtkWidget *widget; widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_ERROR); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW ( glade_xml_get_widget (data->xml, "sync_error_textview"))); gtk_text_buffer_set_text (buffer, error, -1); g_source_remove (data->animate_id); sync_collection_remove_all (collection); } gboolean sync_activate_cursor_item_cb (GtkIconView *iconview, SyncData *data) { return FALSE; } void sync_item_activated_cb (GtkIconView *iconview, GtkTreePath *arg1, SyncData *data) { GtkTreeIter iter; if (gtk_tree_model_get_iter ( GTK_TREE_MODEL (data->model), &iter, arg1)) { const gchar *name; SyncType type; GtkWidget *widget; gfloat x, y; gtk_tree_model_get (GTK_TREE_MODEL (data->model), &iter, COL_NAME, &name, COL_TYPE, &type, -1); switch (type) { SyncItem *item, *item2; SyncGroup *group; gchar *path; case TYPE_SYNCML: path = g_strdup_printf (TEMP_PATH, g_getenv ("HOME")); item2 = sync_file_item_new ("Test", path); g_free (path); /* Contacts SyncML item */ item = sync_syncml_item_new ("Server", "http://localhost:8080", CONTACTS, "", "", "card"); group = sync_group_new_with_items ( item2, item); sync_collection_add_group (data->collection, group); g_object_unref (group); g_object_unref (item); /* Events SyncML item */ item = sync_syncml_item_new ("Server", "http://localhost:8080", EVENTS, "", "", "cal"); group = sync_group_new_with_items ( item2, item); sync_collection_add_group (data->collection, group); g_object_unref (group); g_object_unref (item); /* Todo SyncML item */ item = sync_syncml_item_new ("Server", "http://localhost:8080", TODO, "", "", "cal"); group = sync_group_new_with_items ( item2, item); sync_collection_add_group (data->collection, group); g_object_unref (group); g_object_unref (item); /* TODO: Check if notes sync works? */ g_object_unref (item2); break; case TYPE_FILE: path = g_strdup_printf (TEMP_PATH, g_getenv ("HOME")); item = sync_file_item_new ("Test", path); g_free (path); group = sync_group_new_with_items ( data->local_item, item); sync_collection_add_group (data->collection, group); g_object_unref (group); g_object_unref (item); break; case TYPE_GCAL: item2 = sync_gcal_item_new ("GCal", "username", "password"); group = sync_group_new_with_items ( item2, data->local_item); sync_collection_add_group (data->collection, group); g_object_unref (group); g_object_unref (item2); break; default: return; } data->started = FALSE; if (!sync_collection_start (data->collection)) { /* Switch to error tab */ widget = glade_xml_get_widget ( data->xml, "main_notebook"); gtk_notebook_set_current_page ( GTK_NOTEBOOK (widget), TAB_ERROR); return; } /* Set progress bar text */ widget = glade_xml_get_widget (data->xml, "sync_progressbar"); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (widget), "Preparing..."); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), 0); /* Switch to sync/prepare tab and start animation */ widget = glade_xml_get_widget ( data->xml, "sync_image_mid"); gtk_misc_get_alignment (GTK_MISC (widget), &x, &y); gtk_misc_set_alignment (GTK_MISC (widget), 0, y); widget = glade_xml_get_widget ( data->xml, "sync_image_notebook"); gtk_notebook_set_current_page ( GTK_NOTEBOOK (widget), IMAGE_TAB_PREPARE); widget = glade_xml_get_widget (data->xml, "cancel_button"); gtk_widget_set_sensitive (widget, TRUE); widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_SYNC); data->animate_id = g_timeout_add ( ANIM_FREQ, (GSourceFunc)sync_animate, data); } } void sync_sync_button_cb (GtkWidget *source, SyncData *data) { GtkWidget *widget = glade_xml_get_widget (data->xml, "main_iconview"); GList *list = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (widget)); if (list) { sync_item_activated_cb (GTK_ICON_VIEW (widget), list->data, data); g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); g_list_free (list); } } void sync_abort_cb (GtkWidget *source, SyncData *data) { GtkWidget *widget = glade_xml_get_widget (data->xml, "cancel_button"); gtk_widget_set_sensitive (widget, FALSE); widget = glade_xml_get_widget (data->xml, "sync_progressbar"); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (widget), "Aborting..."); if (!sync_collection_abort (data->collection)) { sync_failed_cb (data->collection, "Unknown error", data); } } void sync_conflict_resolve_cb (GtkWidget *source, SyncData *data) { GtkWidget *widget; SyncGroupConflictRes res = IGNORE; if (strcmp (gtk_widget_get_name (source), "abort_button") == 0) { widget = glade_xml_get_widget (data->xml, "cancel_button"); gtk_widget_set_sensitive (widget, FALSE); res = ABORT; } else if (strcmp (gtk_widget_get_name (source), "ignore_button") == 0) res = IGNORE; else if (strcmp (gtk_widget_get_name (source), "use_local_button") == 0) res = USE_ITEM1; else if (strcmp (gtk_widget_get_name (source), "use_ext_button") == 0) res = USE_ITEM2; sync_group_resolve_conflict (data->group, res); widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_SYNC); } void sync_chooser_cb (GtkWidget *source, SyncData *data) { GtkWidget *widget = glade_xml_get_widget (data->xml, "main_notebook"); gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_CHOOSE); } /* From Dates */ static void dates_autoconnect (const gchar *handler_name, GObject *object, const gchar *signal_name, const gchar *signal_data, GObject *connect_object, gboolean after, gpointer user_data) { static GModule *symbols = NULL; GCallback func; GCallback *pfunc = &func; if (!symbols) { symbols = g_module_open(NULL, 0); } if (!g_module_symbol (symbols, handler_name, (gpointer *)pfunc)) { g_warning ("Handler '%s' not found.", handler_name); return; } if (connect_object) { if (after) g_signal_connect_object (object, signal_name, func, connect_object, G_CONNECT_AFTER); else g_signal_connect_object (object, signal_name, func, connect_object, 0); } else { if (after) g_signal_connect_after(object, signal_name, func, user_data); else g_signal_connect(object, signal_name, func, user_data); } } int main (int argc, char **argv) { GtkWidget *widget; GtkTreeIter iter; GtkTreePath *path; GtkIconTheme *icon_theme; gint width = 0, height = 0; SyncData data; SyncItem *server_item; gtk_init (&argc, &argv); glade_init (); /* g_thread_init (NULL); gdk_threads_init ();*/ data.xml = glade_xml_new (XML_FILE, NULL, NULL); if (!data.xml) g_error ("Could not find interface XML file '%s'", XML_FILE); /* Load icons */ icon_theme = gtk_icon_theme_get_default (); gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &width, &height); data.backup_icon = gtk_icon_theme_load_icon (icon_theme, GTK_STOCK_FLOPPY, MIN (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); data.restore_icon = gtk_icon_theme_load_icon (icon_theme, GTK_STOCK_OPEN, MIN (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); data.network_icon = gtk_icon_theme_load_icon (icon_theme, GTK_STOCK_NETWORK, MIN (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); data.add_icon = gtk_icon_theme_load_icon (icon_theme, GTK_STOCK_ADD, MIN (width, height), GTK_ICON_LOOKUP_USE_BUILTIN, NULL); /* Setup icon-view */ widget = glade_xml_get_widget (data.xml, "main_iconview"); data.model = gtk_list_store_new ( 3, G_TYPE_STRING, G_TYPE_INT, GDK_TYPE_PIXBUF); gtk_icon_view_set_model (GTK_ICON_VIEW (widget), GTK_TREE_MODEL (data.model)); gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (widget), COL_PIXBUF); gtk_icon_view_set_text_column (GTK_ICON_VIEW (widget), COL_NAME); /* Create local sync-item and sync collection */ data.collection = sync_collection_new (); /* Test with a local file store, evo2 plug-in is broken? */ data.local_item = sync_evo2_item_new ("Local", NULL, NULL, NULL); /* Create and start server */ server_item = sync_syncml_server_item_new ("Server", "", "", 8080, "card", "cal", "note"); data.server_group = sync_group_new_with_items ( server_item, data.local_item); g_object_unref (server_item); /* Connect up server sync signals (these don't seem to work?) */ /* TODO: Conflicts? */ g_signal_connect (G_OBJECT (data.server_group), "started", G_CALLBACK (sync_server_started_cb), &data); g_signal_connect (G_OBJECT (data.server_group), "finished", G_CALLBACK (sync_server_finished_cb), &data); g_signal_connect (G_OBJECT (data.server_group), "failed", G_CALLBACK (sync_server_failed_cb), &data); sync_group_autostart (data.server_group); /* Insert some items for testing (TODO: look at loading groups later) */ gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "SyncML Test", COL_TYPE, TYPE_SYNCML, COL_PIXBUF, data.network_icon, -1); gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "Evo2 Test", COL_TYPE, TYPE_FILE, COL_PIXBUF, data.backup_icon, -1); gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "GCal Test", COL_TYPE, TYPE_GCAL, COL_PIXBUF, data.network_icon, -1); /* Insert preset items */ /* gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "Backup", COL_TYPE, TYPE_BACKUP, COL_PIXBUF, data.backup_icon, -1); gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "Restore", COL_TYPE, TYPE_RESTORE, COL_PIXBUF, data.restore_icon, -1); gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, G_MAXINT, COL_NAME, "Add target...", COL_TYPE, TYPE_ADD_NEW, COL_PIXBUF, data.add_icon, -1);*/ /* TODO: Avahi detection of local sync servers? */ /* TODO: Bluetooth scanning? */ /* Select first item */ path = gtk_tree_path_new_first (); gtk_icon_view_select_path (GTK_ICON_VIEW (widget), path); gtk_tree_path_free (path); /* Connect signals */ glade_xml_signal_autoconnect_full (data.xml, dates_autoconnect, &data); /* Connect SyncCollection signals */ g_signal_connect (G_OBJECT (data.collection), "started", G_CALLBACK (sync_started_cb), &data); g_signal_connect (G_OBJECT (data.collection), "progress", G_CALLBACK (sync_progress_cb), &data); g_signal_connect (G_OBJECT (data.collection), "conflict", G_CALLBACK (sync_conflict_cb), &data); g_signal_connect (G_OBJECT (data.collection), "finished", G_CALLBACK (sync_finished_cb), &data); g_signal_connect (G_OBJECT (data.collection), "failed", G_CALLBACK (sync_failed_cb), &data); gtk_main (); return 0; }