summaryrefslogtreecommitdiffstats
path: root/sync/src/sync_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sync/src/sync_main.c')
-rw-r--r--sync/src/sync_main.c587
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;
+}
+