#include #include #include #include #include #include #include #include #include "pokysync.h" static OSyncGroup * pokysync_get_backup_group (PokySyncData *data) { OSyncGroup *group; OSyncMember *member; OSyncError *error = NULL; OSyncConfigurationTypes type = NO_CONFIGURATION; group = osync_env_find_group (data->osync, BACKUP_GROUP); if (group) return group; 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, BACKUP_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 ( BACKUP_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 pokysync_sync_animate (PokySyncData *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; direction = (gfloat)roundf (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 pokysync_conflict_cb (OSyncEngine *engine, OSyncMapping *mapping, void *user_data) { GtkWidget *widget; PokySyncData *data = (PokySyncData *)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 pokysync_changestatus_cb (OSyncEngine *engine, OSyncChangeUpdate *status, void *user_data) { PokySyncData *data = (PokySyncData *)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 pokysync_mappingstatus_cb (OSyncMappingUpdate *status, void *user_data) { PokySyncData *data = (PokySyncData *)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 pokysync_sync_finish_cb (gpointer data) { OSyncEngine *engine = (OSyncEngine *)data; g_debug ("Finalizing/freeing sync engine"); osengine_finalize (engine); osengine_free (engine); } static void pokysync_enginestatus_cb (OSyncEngine *engine, OSyncEngineUpdate *status, void *user_data) { GtkWidget *widget; PokySyncData *data = (PokySyncData *)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 (pokysync_sync_finish_cb, engine); } static void pokysync_memberstatus_cb (OSyncMemberUpdate *status, void *user_data) { PokySyncData *data = (PokySyncData *)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 pokysync_backup (PokySyncData *data) { OSyncGroup *group; OSyncEngine *engine; GtkWidget *widget; OSyncError *error = NULL; widget = glade_xml_get_widget (data->xml, "main_notebook"); if (!(group = pokysync_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, pokysync_conflict_cb, data); osengine_set_changestatus_callback ( engine, pokysync_changestatus_cb, data); osengine_set_mappingstatus_callback ( engine, pokysync_mappingstatus_cb, data); osengine_set_enginestatus_callback ( engine, pokysync_enginestatus_cb, data); osengine_set_memberstatus_callback ( engine, pokysync_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)pokysync_sync_animate, data); } static gboolean pokysync_activate_cursor_item_cb (GtkIconView *iconview, PokySyncData *data) { return FALSE; } static void pokysync_item_activated_cb (GtkIconView *iconview, GtkTreePath *arg1, PokySyncData *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"); pokysync_backup (data); return; } } } static void pokysync_sync_button_cb (GtkWidget *source, PokySyncData *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) { pokysync_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 pokysync_chooser_cb (GtkWidget *source, PokySyncData *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; PokySyncData 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 (pokysync_activate_cursor_item_cb), &data); g_signal_connect (G_OBJECT (widget), "item-activated", G_CALLBACK (pokysync_item_activated_cb), &data); widget = glade_xml_get_widget (data.xml, "sync_button"); g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (pokysync_sync_button_cb), &data); widget = glade_xml_get_widget (data.xml, "success_close_button"); g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (pokysync_chooser_cb), &data); widget = glade_xml_get_widget (data.xml, "error_close_button"); g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (pokysync_chooser_cb), &data); gtk_main (); return 0; }