diff options
Diffstat (limited to 'sync/src/sync_main.c')
-rw-r--r-- | sync/src/sync_main.c | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/sync/src/sync_main.c b/sync/src/sync_main.c new file mode 100644 index 0000000..e83f21d --- /dev/null +++ b/sync/src/sync_main.c @@ -0,0 +1,587 @@ + +#include <string.h> +#include <math.h> +#include <glib.h> +#include <glib/gprintf.h> +#include <glib/gstdio.h> +#include <gtk/gtk.h> +#include <glade/glade.h> +#include <opensync/opensync.h> +#include <osengine/engine.h> + +#include "sync.h" + +static gboolean +sync_clean_backup (SyncData *data) +{ + OSyncGroup *group; + GDir *backup_dir; + OSyncError *error = NULL; + GError *gerror = NULL; + const gchar *filename; + + group = osync_env_find_group (data->osync, BACKUP_GROUP); + + /* Delete group */ + if ((group) && (!osync_group_delete(group, &error))) { + g_warning ("Unable to delete backup group: %s\n", + osync_error_print(&error)); + osync_error_free(&error); + return FALSE; + } + + /* Remove backup files */ + if (!g_file_test (BACKUP_PATH, G_FILE_TEST_EXISTS)) return TRUE; + if (!g_file_test (BACKUP_PATH, G_FILE_TEST_IS_DIR)) return FALSE; + if (!(backup_dir = g_dir_open (BACKUP_PATH, 0, &gerror))) { + g_warning ("Error opening backup directory: %s", + gerror->message); + g_error_free (gerror); + return FALSE; + } + while ((filename = g_dir_read_name (backup_dir))) { + if (g_remove (filename) != 0) { + g_warning ("Error removing file: %s", filename); + break; + } + } + g_dir_close (backup_dir); + + /* Remove backup directory */ + if (g_rmdir (BACKUP_PATH) != 0) { + g_warning ("Error removing backup directory"); + return FALSE; + } + + return TRUE; +} + +static OSyncGroup * +sync_get_backup_group (SyncData *data) +{ + OSyncGroup *group; + OSyncMember *member; + OSyncError *error = NULL; + OSyncConfigurationTypes type = NO_CONFIGURATION; + + if (!sync_clean_backup (data)) { + g_warning ("Unable to clear old backup data\n"); + return NULL; + } + + group = osync_group_new (data->osync); + osync_group_set_name (group, BACKUP_GROUP); + + /* Setup Evolution2 sync member */ + member = osync_member_new (group); + if (!osync_member_instance_plugin (member, EVO2_PLUGIN, &error)) { + g_warning ("Error instancing Evolution2 plug-in: %s", + osync_error_print (&error)); + osync_error_free (&error); + return NULL; + } + if (!osync_member_need_config (member, &type, &error)) { + g_warning ("Error reading plug-in config requirements: %s", + osync_error_print (&error)); + osync_error_free (&error); + return NULL; + } + if (type == NO_CONFIGURATION) { + g_warning ( + "Evolution2 plug-in reports no need for configuration"); + } else { + osync_member_set_config ( + member, EVO2_CONFIG, strlen (EVO2_CONFIG)); + } + + /* Setup File sync member */ + member = osync_member_new (group); + if (!osync_member_instance_plugin (member, FILE_PLUGIN, &error)) { + g_warning ("Error instancing file plug-in: %s", + osync_error_print (&error)); + osync_error_free (&error); + return NULL; + } + if (!osync_member_need_config (member, &type, &error)) { + g_warning ("Error reading plug-in config requirements: %s", + osync_error_print (&error)); + osync_error_free (&error); + return NULL; + } + if (type == NO_CONFIGURATION) { + g_warning ( + "File sync plug-in reports no need for configuration"); + } else { + gchar *backup_config, *backup_path; + + backup_path = g_strdup_printf (BACKUP_PATH, g_getenv ("HOME")); + if (g_mkdir_with_parents (backup_path, 0755) == -1) { + g_warning ("Couldn't create backup directory"); + g_free (backup_path); + return NULL; + } + + backup_config = g_strdup_printf (FILE_CONFIG, backup_path); + osync_member_set_config ( + member, backup_config, strlen (backup_config)); + g_free (backup_config); + g_free (backup_path); + } + + /* Save the group */ + if (!osync_group_save (group, &error)) { + g_warning ("Error saving group: %s", + osync_error_print (&error)); + osync_error_free (&error); + } + + return group; +} + +static gboolean +sync_animate (SyncData *data) +{ + static gint direction = 1; + 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); + + return data->syncing; +} + +static const char * +OSyncChangeType2String (OSyncChangeType c) +{ + switch (c) { + case CHANGE_ADDED: return "ADDED"; + case CHANGE_UNMODIFIED: return "UNMODIFIED"; + case CHANGE_DELETED: return "DELETED"; + case CHANGE_MODIFIED: return "MODIFIED"; + default: + case CHANGE_UNKNOWN: return "?"; + } +} + +static void +sync_conflict_cb (OSyncEngine *engine, OSyncMapping *mapping, + void *user_data) +{ + GtkWidget *widget; + SyncData *data = (SyncData *)user_data; + + gdk_threads_enter (); + widget = glade_xml_get_widget (data->xml, "main_notebook"); + gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_CONFLICT); + gdk_threads_leave (); + + osengine_mapping_ignore_conflict (engine, mapping); +} + +static void +sync_changestatus_cb (OSyncEngine *engine, OSyncChangeUpdate *status, + void *user_data) +{ + SyncData *data = (SyncData *)user_data; + + switch (status->type) { + case CHANGE_RECEIVED_INFO: + g_debug ("Received a entry %s without data from member " + "%i. Changetype %s", + osync_change_get_uid (status->change), + status->member_id, + OSyncChangeType2String ( + osync_change_get_changetype ( + status->change))); + break; + case CHANGE_RECEIVED: + g_debug ("Received a entry %s with data of size %i from " + "member %i. Changetype %s", + osync_change_get_uid (status->change), + osync_change_get_datasize (status->change), + status->member_id, + OSyncChangeType2String ( + osync_change_get_changetype ( + status->change))); + break; + case CHANGE_SENT: + g_debug ("Sent a entry %s of size %i to member %i. " + "Changetype %s", + osync_change_get_uid (status->change), + osync_change_get_datasize (status->change), + status->member_id, + OSyncChangeType2String ( + osync_change_get_changetype ( + status->change))); + break; + case CHANGE_WRITE_ERROR: + g_debug ("Error writing entry %s to member %i: %s", + osync_change_get_uid (status->change), + status->member_id, + osync_error_print (&(status->error))); + break; + case CHANGE_RECV_ERROR: + g_debug ("Error reading entry %s from member %i: %s", + osync_change_get_uid (status->change), + status->member_id, + osync_error_print (&(status->error))); + break; + } +} + +static void +sync_mappingstatus_cb (OSyncMappingUpdate *status, void *user_data) +{ + SyncData *data = (SyncData *)user_data; + + switch (status->type) { + case MAPPING_SOLVED: + g_debug ("Mapping solved"); + break; + case MAPPING_SYNCED: + g_debug ("Mapping Synced"); + break; + case MAPPING_WRITE_ERROR: + g_debug ("Mapping Write Error: %s", + osync_error_print (&(status->error))); + break; + } +} + +static gboolean +sync_finish_cb (gpointer data) +{ + OSyncEngine *engine = (OSyncEngine *)data; + + g_debug ("Finalizing/freeing sync engine"); + osengine_finalize (engine); + osengine_free (engine); + + return FALSE; +} + +static void +sync_enginestatus_cb (OSyncEngine *engine, OSyncEngineUpdate *status, + void *user_data) +{ + GtkWidget *widget; + SyncData *data = (SyncData *)user_data; + + switch (status->type) { + case ENG_PREV_UNCLEAN: + g_debug ("The previous synchronization was unclean. " + "Slow-syncing"); + return; + case ENG_ENDPHASE_CON: + g_debug ("All clients connected or error"); + return; + case ENG_END_CONFLICTS: + g_debug ("All conflicts have been reported"); + return; + case ENG_ENDPHASE_READ: + g_debug ("All clients sent changes or error"); + return; + case ENG_ENDPHASE_WRITE: + g_debug ("All clients have written"); + return; + case ENG_ENDPHASE_DISCON: + g_debug ("All clients have disconnected"); + return; + case ENG_SYNC_SUCCESSFULL: + g_debug ("The sync was successful"); + gdk_threads_enter (); + widget = glade_xml_get_widget ( + data->xml, "main_notebook"); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_SUCCESS); + gdk_threads_leave (); + break; + case ENG_ERROR: + g_debug ("The sync failed: %s", + osync_error_print (&(status->error))); + gdk_threads_enter (); + widget = glade_xml_get_widget ( + data->xml, "main_notebook"); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_ERROR); + gdk_threads_leave (); +/* g_debug ("Aborting synchronisation..."); + osengine_abort (engine);*/ + break; + } + + data->syncing = FALSE; + g_debug ("Setting idle function to clean up engine."); + g_idle_add (sync_finish_cb, engine); +} + +static void +sync_memberstatus_cb (OSyncMemberUpdate *status, void *user_data) +{ + SyncData *data = (SyncData *)user_data; + + switch (status->type) { + case MEMBER_CONNECTED: + g_debug ("Member %lli of type %s just connected", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member)); + break; + case MEMBER_DISCONNECTED: + g_debug ("Member %lli of type %s just disconnected", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member)); + break; + case MEMBER_SENT_CHANGES: + g_debug ("Member %lli of type %s just sent all changes", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member)); + break; + case MEMBER_COMMITTED_ALL: + g_debug ( + "Member %lli of type %s committed all changes.", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member)); + break; + case MEMBER_CONNECT_ERROR: + g_debug ("Member %lli of type %s had an " + "error while connecting: %s", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member), + osync_error_print (&(status->error))); + break; + case MEMBER_GET_CHANGES_ERROR: + g_debug ("Member %lli of type %s had an error while " + "getting changes: %s", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member), + osync_error_print (&(status->error))); + break; + case MEMBER_SYNC_DONE_ERROR: + g_debug ("Member %lli of type %s had an error while " + "calling sync done: %s", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member), + osync_error_print (&(status->error))); + break; + case MEMBER_DISCONNECT_ERROR: + g_debug ("Member %lli of type %s had an error while " + "disconnecting: %s", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member), + osync_error_print (&(status->error))); + break; + case MEMBER_COMMITTED_ALL_ERROR: + g_debug ("Member %lli of type %s had an error while " + "commiting changes: %s", + osync_member_get_id (status->member), + osync_member_get_pluginname (status->member), + osync_error_print (&(status->error))); + break; + } +} + +static void +sync_backup (SyncData *data) +{ + OSyncGroup *group; + OSyncEngine *engine; + GtkWidget *widget; + OSyncError *error = NULL; + + widget = glade_xml_get_widget (data->xml, "main_notebook"); + + if (!(group = sync_get_backup_group (data))) { + g_warning ("Unable to retrieve back-up group"); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_ERROR); + return; + } + + if (!(engine = osengine_new (group, &error))) { + g_warning ("Error while creating syncengine: %s", + osync_error_print (&error)); + osync_error_free (&error); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_ERROR); + return; + } + +/* osengine_set_message_callback (engine, NULL, NULL);*/ + osengine_set_conflict_callback ( + engine, sync_conflict_cb, data); + osengine_set_changestatus_callback ( + engine, sync_changestatus_cb, data); + osengine_set_mappingstatus_callback ( + engine, sync_mappingstatus_cb, data); + osengine_set_enginestatus_callback ( + engine, sync_enginestatus_cb, data); + osengine_set_memberstatus_callback ( + engine, sync_memberstatus_cb, data); + + if (!osengine_init (engine, &error)) { + g_warning ("Error while initializing syncengine: %s", + osync_error_print (&error)); + osync_error_free (&error); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_ERROR); + return; + } + + if (!osengine_synchronize (engine, &error)) { + g_warning ("Error while starting synchronization: %s", + osync_error_print (&error)); + osync_error_free (&error); + gtk_notebook_set_current_page ( + GTK_NOTEBOOK (widget), TAB_ERROR); + return; + } + + /* Switch to sync tab */ + gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_SYNC); + /* Start sync animation */ + g_debug ("Started synchronisation..."); + data->syncing = TRUE; + data->animate_id = g_timeout_add ( + 100, (GSourceFunc)sync_animate, data); +} + +static gboolean +sync_activate_cursor_item_cb (GtkIconView *iconview, SyncData *data) +{ + return FALSE; +} + +static 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)) { + gint id; + gtk_tree_model_get (GTK_TREE_MODEL (data->model), + &iter, COL_ID, &id, -1); + + /* Special case for back-up item */ + if (id == 0) { + g_debug ("Performing backup"); + sync_backup (data); + + return; + } + } +} + +static 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); + } +} + +static 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); +} + +int +main (int argc, char **argv) +{ + GtkWidget *widget; + GtkTreeIter iter; + GtkTreePath *path; + GtkIconTheme *icon_theme; + gint width = 0, height = 0; + OSyncError *error = NULL; + SyncData data; + + gtk_init (&argc, &argv); + glade_init (); + g_thread_init (NULL); + gdk_threads_init (); + /* Must be called due to buggy OpenSync */ + gconf_client_get_default (); + + 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), 0, NULL); + data.network_icon = gtk_icon_theme_load_icon (icon_theme, + GTK_STOCK_NETWORK, MIN (width, height), 0, NULL); + + /* Setup icon-view */ + widget = glade_xml_get_widget (data.xml, "main_iconview"); + data.model = gtk_list_store_new ( + 3, G_TYPE_INT, G_TYPE_STRING, 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); + + /* Insert backup item in icon-view */ + gtk_list_store_insert_with_values (GTK_LIST_STORE (data.model), &iter, + 0, COL_ID, 0, COL_NAME, "Backup", + COL_PIXBUF, data.backup_icon, -1); + path = gtk_tree_path_new_first (); + gtk_icon_view_select_path (GTK_ICON_VIEW (widget), path); + gtk_tree_path_free (path); + + /* Create OpenSync environment */ + data.osync = osync_env_new (); + osync_env_set_option (data.osync, + "GROUPS_DIRECTORY", (const char *)NULL); + osync_env_set_option (data.osync, "LOAD_GROUPS", "TRUE"); + osync_env_set_option (data.osync, "LOAD_PLUGINS", "TRUE"); + osync_env_set_option (data.osync, "LOAD_FORMATS", "TRUE"); + if (!osync_env_initialize (data.osync, &error)) { + g_error ("Unable to initialise OpenSync environment: %s", + osync_error_print (&error)); + } + + widget = glade_xml_get_widget (data.xml, "quit_menuitem"); + g_signal_connect (G_OBJECT (widget), "activate", + G_CALLBACK (gtk_main_quit), NULL); + widget = glade_xml_get_widget (data.xml, "main_window"); + g_signal_connect (G_OBJECT (widget), "destroy", + G_CALLBACK (gtk_main_quit), NULL); + widget = glade_xml_get_widget (data.xml, "main_iconview"); + g_signal_connect (G_OBJECT (widget), "activate-cursor-item", + G_CALLBACK (sync_activate_cursor_item_cb), &data); + g_signal_connect (G_OBJECT (widget), "item-activated", + G_CALLBACK (sync_item_activated_cb), &data); + widget = glade_xml_get_widget (data.xml, "sync_button"); + g_signal_connect (G_OBJECT (widget), "clicked", + G_CALLBACK (sync_sync_button_cb), &data); + + widget = glade_xml_get_widget (data.xml, "success_close_button"); + g_signal_connect (G_OBJECT (widget), "clicked", + G_CALLBACK (sync_chooser_cb), &data); + + widget = glade_xml_get_widget (data.xml, "error_close_button"); + g_signal_connect (G_OBJECT (widget), "clicked", + G_CALLBACK (sync_chooser_cb), &data); + + gtk_main (); + + return 0; +} + |