summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lord <chris@openedhand.com>2006-07-27 10:37:55 +0000
committerChris Lord <chris@openedhand.com>2006-07-27 10:37:55 +0000
commita5b9e23f334523739396389066390b9707822041 (patch)
tree2d6212e92f6c5834de7416a5968dbd97c7ec386f
parent988156e3d43490ca9c2a61b8b45313027a21667c (diff)
downloadsync-a5b9e23f334523739396389066390b9707822041.tar.gz
sync-a5b9e23f334523739396389066390b9707822041.tar.bz2
sync-a5b9e23f334523739396389066390b9707822041.zip
- Minor tweaks to UI
- Refactor into an OpenSync convenience library and the application - Fix various bugs, add progress indicator
-rw-r--r--sync/ChangeLog20
-rw-r--r--sync/data/sync.glade121
-rw-r--r--sync/src/Makefile.am4
-rw-r--r--sync/src/sync.h53
-rw-r--r--sync/src/sync_evo2_item.c93
-rw-r--r--sync/src/sync_evo2_item.h13
-rw-r--r--sync/src/sync_file_item.c63
-rw-r--r--sync/src/sync_file_item.h10
-rw-r--r--sync/src/sync_group.c828
-rw-r--r--sync/src/sync_group.h85
-rw-r--r--sync/src/sync_item.c324
-rw-r--r--sync/src/sync_item.h77
-rw-r--r--sync/src/sync_main.c462
-rw-r--r--sync/src/sync_main.h51
14 files changed, 1815 insertions, 389 deletions
diff --git a/sync/ChangeLog b/sync/ChangeLog
index 40aa389..79e0bed 100644
--- a/sync/ChangeLog
+++ b/sync/ChangeLog
@@ -1,3 +1,23 @@
+2006-07-27 Chris Lord,,, <chris@openedhand.com>
+
+ * data/sync.glade:
+ - Minor tweaks to UI
+
+ * src/Makefile.am:
+ * src/sync.h:
+ * src/sync_evo2_item.c:
+ * src/sync_evo2_item.h:
+ * src/sync_file_item.c:
+ * src/sync_file_item.h:
+ * src/sync_group.c:
+ * src/sync_group.h:
+ * src/sync_item.c:
+ * src/sync_item.h:
+ * src/sync_main.c: (sync_get_backup_group):
+ * src/sync_main.h:
+ - Refactor into an OpenSync convenience library and the application
+ - Fix various bugs, add progress indicator
+
2006-07-24 Chris Lord,,, <chris@openedhand.com>
* configure.ac:
diff --git a/sync/data/sync.glade b/sync/data/sync.glade
index 0db0f91..f8f06f1 100644
--- a/sync/data/sync.glade
+++ b/sync/data/sync.glade
@@ -300,59 +300,136 @@
<property name="spacing">6</property>
<child>
- <widget class="GtkHBox" id="sync_image_hbox">
+ <widget class="GtkNotebook" id="sync_image_notebook">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <property name="tab_pos">GTK_POS_TOP</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
<child>
- <widget class="GtkImage" id="sync_image_left">
+ <widget class="GtkImage" id="prepare_image">
<property name="visible">True</property>
<property name="icon_size">6</property>
- <property name="icon_name">stock_contact</property>
+ <property name="icon_name">gtk-disconnect</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
</packing>
</child>
<child>
- <widget class="GtkImage" id="sync_image_mid">
+ <widget class="GtkLabel" id="label14">
<property name="visible">True</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-copy</property>
- <property name="xalign">0</property>
+ <property name="label" translatable="yes">label14</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
<packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
+ <property name="type">tab</property>
</packing>
</child>
<child>
- <widget class="GtkImage" id="sync_image_right">
+ <widget class="GtkHBox" id="sync_image_hbox">
<property name="visible">True</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-floppy</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="sync_image_left">
+ <property name="visible">True</property>
+ <property name="icon_size">6</property>
+ <property name="icon_name">stock_contact</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkImage" id="sync_image_mid">
+ <property name="visible">True</property>
+ <property name="icon_size">6</property>
+ <property name="icon_name">gtk-copy</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkImage" id="sync_image_right">
+ <property name="visible">True</property>
+ <property name="icon_size">6</property>
+ <property name="icon_name">gtk-floppy</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label15</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
<packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="type">tab</property>
</packing>
</child>
</widget>
@@ -870,7 +947,7 @@
<widget class="GtkLabel" id="error_label">
<property name="visible">True</property>
<property name="label" translatable="yes">An unrecoverable error occurred and the
-synchornisation was aborted.</property>
+synchronisation was aborted.</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
diff --git a/sync/src/Makefile.am b/sync/src/Makefile.am
index 646b906..1682416 100644
--- a/sync/src/Makefile.am
+++ b/sync/src/Makefile.am
@@ -3,7 +3,9 @@ AM_CFLAGS = -Wall -export-dynamic $(SYNC_CFLAGS)
bin_PROGRAMS = sync
-sync_SOURCES = sync_main.c sync.h
+sync_SOURCES = sync_main.c sync.h sync_group.c sync_group.h sync_item.c \
+ sync_item.h sync_evo2_item.c sync_evo2_item.h sync_file_item.c \
+ sync_file_item.h
sync_LDADD = $(SYNC_LIBS)
diff --git a/sync/src/sync.h b/sync/src/sync.h
deleted file mode 100644
index ad46340..0000000
--- a/sync/src/sync.h
+++ /dev/null
@@ -1,53 +0,0 @@
-
-#ifndef SYNC_H
-#define SYNC_H
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <opensync/opensync.h>
-
-#define XML_FILE PKGDATADIR G_DIR_SEPARATOR_S "sync.glade"
-#define BACKUP_GROUP "sync-backup"
-#define BACKUP_PATH "%s" G_DIR_SEPARATOR_S ".gnome2" G_DIR_SEPARATOR_S \
- "sync" G_DIR_SEPARATOR_S "backup"
-
-#define EVO2_PLUGIN "evo2-sync"
-#define EVO2_CONFIG "<config>" \
- "<adress_path>default</adress_path>" \
- "<calendar_path>default</calendar_path>" \
- "<tasks_path>default</tasks_path>" \
- "</config>"
-
-#define FILE_PLUGIN "file-sync"
-#define FILE_CONFIG "<config>" \
- "<path>%s</path>" \
- "<recursive>FALSE</recursive>" \
- "</config>"
-
-enum {
- COL_ID,
- COL_NAME,
- COL_PIXBUF,
-};
-
-enum {
- TAB_CHOOSE = 0,
- TAB_SYNC,
- TAB_CONFLICT,
- TAB_ERROR,
- TAB_SUCCESS
-};
-
-typedef struct {
- GladeXML *xml;
- GdkPixbuf *backup_icon;
- GdkPixbuf *network_icon;
- GtkListStore *model;
- OSyncEnv *osync;
-
- gboolean syncing;
- guint animate_id;
-} SyncData;
-
-
-#endif
diff --git a/sync/src/sync_evo2_item.c b/sync/src/sync_evo2_item.c
new file mode 100644
index 0000000..69a0c65
--- /dev/null
+++ b/sync/src/sync_evo2_item.c
@@ -0,0 +1,93 @@
+
+#include <opensync/opensync.h>
+#include <glib.h>
+#include <string.h>
+#include "sync.h"
+#include "sync_item.h"
+#include "sync_evo2_item.h"
+
+#define EVO2_PLUGIN "evo2-sync"
+#define EVO2_CONFIG "<config>" \
+ "<adress_path>%s</adress_path>" \
+ "<calendar_path>%s</calendar_path>" \
+ "<tasks_path>%s</tasks_path>" \
+ "</config>"
+
+typedef struct {
+ gchar *adr_path;
+ gchar *cal_path;
+ gchar *task_path;
+} SyncEvo2ItemData;
+
+static OSyncMember *
+sync_evo2_item_get_member (SyncItem *item)
+{
+ OSyncMember *member;
+ OSyncError *error = NULL;
+ OSyncConfigurationTypes type = NO_CONFIGURATION;
+
+ /* Setup Evolution2 sync member */
+ member = osync_member_new (sync_group_get_osync_group (
+ sync_item_get_group (item)));
+ 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 {
+ SyncEvo2ItemData *data;
+ gchar *evo2_config;
+
+ data = (SyncEvo2ItemData *)sync_item_get_data (item);
+ evo2_config = g_strdup_printf (EVO2_CONFIG, data->adr_path,
+ data->cal_path, data->task_path);
+ osync_member_set_config (
+ member, evo2_config, strlen (evo2_config));
+ g_free (evo2_config);
+ }
+
+ return member;
+}
+
+static void
+sync_evo2_free_data (SyncEvo2ItemData *data)
+{
+ g_free (data->adr_path);
+ g_free (data->cal_path);
+ g_free (data->task_path);
+ g_free (data);
+}
+
+SyncItem *
+sync_evo2_item_new (const gchar *name, const gchar *address_path,
+ const gchar *calendar_path, const gchar *tasks_path)
+{
+ SyncItem *item;
+ SyncEvo2ItemData *data;
+
+ item = sync_item_new (name, NULL, sync_evo2_item_get_member);
+
+ data = g_new0 (SyncEvo2ItemData, 1);
+ data->adr_path = address_path ?
+ g_strdup (address_path) : g_strdup ("default");
+ data->cal_path = calendar_path ?
+ g_strdup (calendar_path) : g_strdup ("default");
+ data->task_path = tasks_path ?
+ g_strdup (tasks_path) : g_strdup ("default");
+
+ sync_item_set_data (item, data);
+ sync_item_set_data_free_func (
+ item, (SyncItemDataFreeFunc)sync_evo2_free_data);
+
+ return item;
+}
diff --git a/sync/src/sync_evo2_item.h b/sync/src/sync_evo2_item.h
new file mode 100644
index 0000000..9717aae
--- /dev/null
+++ b/sync/src/sync_evo2_item.h
@@ -0,0 +1,13 @@
+
+#ifndef SYNC_EVO2_H
+#define SYNC_EVO2_H
+
+#include <glib.h>
+#include "sync_item.h"
+
+SyncItem * sync_evo2_item_new (const gchar *name,
+ const gchar *address_path,
+ const gchar *calendar_path,
+ const gchar *tasks_path);
+
+#endif
diff --git a/sync/src/sync_file_item.c b/sync/src/sync_file_item.c
new file mode 100644
index 0000000..9e4ce0b
--- /dev/null
+++ b/sync/src/sync_file_item.c
@@ -0,0 +1,63 @@
+
+#include <opensync/opensync.h>
+#include <glib.h>
+#include <string.h>
+#include "sync.h"
+#include "sync_item.h"
+#include "sync_group.h"
+#include "sync_file_item.h"
+
+#define FILE_PLUGIN "file-sync"
+#define FILE_CONFIG "<config>" \
+ "<path>%s</path>" \
+ "<recursive>FALSE</recursive>" \
+ "</config>"
+
+static OSyncMember *
+sync_file_item_get_member (SyncItem *item)
+{
+ OSyncMember *member;
+ OSyncError *error = NULL;
+ OSyncConfigurationTypes type = NO_CONFIGURATION;
+
+ member = osync_member_new (sync_group_get_osync_group (
+ sync_item_get_group (item)));
+ 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 {
+ const gchar *file_path;
+ gchar *file_config;
+
+ file_path = sync_item_get_adr (item);
+ if (g_mkdir_with_parents (file_path, 0755) == -1) {
+ g_warning ("Couldn't create directory '%s'", file_path);
+ return NULL;
+ }
+
+ file_config = g_strdup_printf (FILE_CONFIG, file_path);
+ osync_member_set_config (
+ member, file_config, strlen (file_config));
+ g_free (file_config);
+ }
+
+ return member;
+}
+
+SyncItem *
+sync_file_item_new (const gchar *name, const gchar *adr)
+{
+ return sync_item_new (name, adr, sync_file_item_get_member);
+}
diff --git a/sync/src/sync_file_item.h b/sync/src/sync_file_item.h
new file mode 100644
index 0000000..b1ae516
--- /dev/null
+++ b/sync/src/sync_file_item.h
@@ -0,0 +1,10 @@
+
+#ifndef SYNC_FILE_H
+#define SYNC_FILE_H
+
+#include <glib.h>
+#include "sync_item.h"
+
+SyncItem * sync_file_item_new (const gchar *name, const gchar *adr);
+
+#endif
diff --git a/sync/src/sync_group.c b/sync/src/sync_group.c
new file mode 100644
index 0000000..f9aa6f6
--- /dev/null
+++ b/sync/src/sync_group.c
@@ -0,0 +1,828 @@
+
+#include <glib.h>
+#include <opensync/opensync.h>
+#include <osengine/engine.h>
+#include "sync_group.h"
+#include "sync_item.h"
+
+G_DEFINE_TYPE (SyncGroup, sync_group, G_TYPE_OBJECT);
+
+#define GROUP_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYNC_TYPE_GROUP, SyncGroupPrivate))
+
+/*#define DEBUG*/
+
+typedef struct _SyncGroupPrivate SyncGroupPrivate;
+
+enum {
+ PROP_ITEM1 = 1,
+ PROP_ITEM2,
+ PROP_NAMESPACE,
+};
+
+enum {
+ STARTED,
+ PROGRESS,
+ CONFLICT,
+ FINISHED,
+ FAILED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _SyncGroupPrivate
+{
+ SyncItem *item1;
+ SyncItem *item2;
+ gchar *namespace;
+ OSyncGroup *group;
+ OSyncEngine *engine;
+ OSyncMapping *mapping; /* Required for conflicts */
+
+ gint max_changes; /* Used to work out sync progress */
+ gint changes;
+ guint progress_id;
+ GMutex *mutex;
+};
+
+static OSyncEnv *default_env = NULL;
+
+static void
+sync_group_finalize (GObject *object)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (object);
+
+ /* FIXME: Guard against finalisation during syncs */
+ if (priv->item1) g_object_unref (priv->item1);
+ if (priv->item2) g_object_unref (priv->item2);
+ g_mutex_free (priv->mutex);
+
+ G_OBJECT_CLASS (sync_group_parent_class)->finalize (object);
+}
+
+static void
+sync_group_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SyncGroup *group = SYNC_GROUP (object);
+
+ switch (prop_id) {
+ case PROP_ITEM1 :
+ sync_group_set_item1 (group,
+ g_value_get_object (value));
+ break;
+ case PROP_ITEM2 :
+ sync_group_set_item2 (group,
+ g_value_get_object (value));
+ break;
+ case PROP_NAMESPACE :
+ sync_group_set_namespace (group,
+ g_value_get_string (value));
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (
+ object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+sync_group_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SyncGroup *group = SYNC_GROUP (object);
+
+ switch (prop_id) {
+ case PROP_ITEM1 :
+ g_value_set_object (value,
+ sync_group_get_item1 (group));
+ break;
+ case PROP_ITEM2 :
+ g_value_set_object (value,
+ sync_group_get_item2 (group));
+ break;
+ case PROP_NAMESPACE :
+ g_value_set_string (value,
+ sync_group_get_namespace (group));
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (
+ object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+sync_group_class_init (SyncGroupClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = sync_group_set_property;
+ object_class->get_property = sync_group_get_property;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ITEM1,
+ g_param_spec_object (
+ "item1",
+ ("Item1"),
+ ("The first item in the synchronisation pair"),
+ SYNC_TYPE_ITEM,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_ITEM2,
+ g_param_spec_object (
+ "item2",
+ ("Item2"),
+ ("The second item in the synchronisation pair"),
+ SYNC_TYPE_ITEM,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_NAMESPACE,
+ g_param_spec_string (
+ "namespace",
+ ("Name-space"),
+ ("Name-space of the synchronisation group."),
+ ("libsync"),
+ G_PARAM_READWRITE));
+
+ signals[STARTED] =
+ g_signal_new ("started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SyncGroupClass, started),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[PROGRESS] =
+ g_signal_new ("progress",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SyncGroupClass, progress),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__DOUBLE,
+ G_TYPE_NONE, 1, G_TYPE_DOUBLE);
+ signals[CONFLICT] =
+ g_signal_new ("conflict",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SyncGroupClass, conflict),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[FINISHED] =
+ g_signal_new ("finished",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SyncGroupClass, finished),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[FAILED] =
+ g_signal_new ("failed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SyncGroupClass, failed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (SyncGroupPrivate));
+
+ object_class->finalize = sync_group_finalize;
+}
+
+static void
+sync_group_init (SyncGroup *self)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (self);
+
+ priv->mutex = g_mutex_new ();
+ priv->namespace = g_strdup ("libsync");
+}
+
+SyncGroup*
+sync_group_new (void)
+{
+ return g_object_new (SYNC_TYPE_GROUP, NULL);
+}
+
+SyncGroup *
+sync_group_new_with_items (SyncItem *item1, SyncItem *item2)
+{
+ return g_object_new (SYNC_TYPE_GROUP, "item1", item1, "item2", item2,
+ NULL);
+}
+
+void
+sync_group_set_item1 (SyncGroup *group, SyncItem *item1)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if (priv->item1)
+ sync_item_ungroup (priv->item1);
+ if (item1) {
+ priv->item1 = g_object_ref_sink (item1);
+ sync_item_set_group (item1, group);
+ }
+}
+
+void
+sync_group_set_item2 (SyncGroup *group, SyncItem *item2)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if (priv->item2)
+ sync_item_ungroup (priv->item2);
+ if (item2) {
+ priv->item2 = g_object_ref_sink (item2);
+ sync_item_set_group (item2, group);
+ }
+}
+
+void sync_group_set_namespace (SyncGroup *group, const gchar *namespace)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+ g_free (priv->namespace);
+ priv->namespace = g_strdup (namespace);
+}
+
+SyncItem *
+sync_group_get_item1 (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ return priv->item1;
+}
+
+SyncItem *
+sync_group_get_item2 (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ return priv->item2;
+}
+
+const gchar *
+sync_group_get_namespace (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ return priv->namespace;
+}
+
+static OSyncEnv *
+sync_group_get_default_env ()
+{
+ if (!default_env) {
+ OSyncError *error = NULL;
+ default_env = osync_env_new ();
+ g_debug ("Creating new environment");
+ if (!osync_env_initialize (default_env, &error)) {
+ g_error ("Unable to initialise OSyncEnv: %s",
+ osync_error_print (&error));
+ osync_env_free (default_env);
+ default_env = NULL;
+ }
+ }
+
+ return default_env;
+}
+
+gchar *sync_group_get_name (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if ((!priv->item1) || (!priv->item2)) {
+ g_warning ("%s called on group without two items", G_STRFUNC);
+ return NULL;
+ }
+
+ return g_strdup_printf ("%s-%s-%s",
+ sync_group_get_namespace (group),
+ sync_item_get_name (priv->item1),
+ sync_item_get_name (priv->item2));
+}
+
+gboolean
+sync_group_delete (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+ OSyncEnv *env;
+ OSyncGroup *os_group;
+ OSyncError *error = NULL;
+ gchar *name;
+ SyncItem *item1 = NULL;
+ SyncItem *item2 = NULL;
+
+ if (priv->item1) {
+ item1 = g_object_ref (priv->item1);
+ sync_item_ungroup (priv->item1);
+ }
+ if (priv->item2) {
+ item2 = g_object_ref (priv->item2);
+ sync_item_ungroup (priv->item2);
+ }
+
+ env = sync_group_get_default_env ();
+ name = sync_group_get_name (group);
+ os_group = osync_env_find_group (env, name);
+ g_free (name);
+ if (!os_group) return TRUE;
+
+ if (!osync_group_delete (os_group, &error)) {
+ g_warning ("Failed to delete group: %s",
+ osync_error_print (&error));
+ osync_error_free (&error);
+ return FALSE;
+ }
+
+ if (item1) {
+ sync_group_set_item1 (group, item1);
+ g_object_unref (item1);
+ }
+ if (item2) {
+ sync_group_set_item2 (group, item2);
+ g_object_unref (item2);
+ }
+
+ return TRUE;
+}
+
+gboolean
+sync_group_save (SyncGroup *group)
+{
+ OSyncError *error = NULL;
+ OSyncGroup *os_group = sync_group_get_osync_group (group);
+
+ if (!os_group) {
+ g_warning ("Failed to retrieve OSyncGroup in %s", G_STRFUNC);
+ return FALSE;
+ }
+
+ if (!osync_group_save (os_group, &error)) {
+ g_warning ("Unable to save OSyncGroup: %s",
+ osync_error_print (&error));
+ osync_error_free (&error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+OSyncGroup *
+sync_group_get_osync_group (SyncGroup *group)
+{
+ gchar *name;
+ OSyncEnv *env;
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if ((!priv->item1) || (!priv->item2)) {
+ g_warning ("%s called on group without two items", G_STRFUNC);
+ return NULL;
+ }
+
+ if (priv->group)
+ return priv->group;
+
+ env = sync_group_get_default_env ();
+ name = sync_group_get_name (group);
+ priv->group = osync_env_find_group (env, name);
+
+ if (!priv->group) {
+ priv->group = osync_group_new (env);
+ g_debug ("Creating new group");
+ osync_group_set_name (priv->group, name);
+
+ /* Create OSyncMembers (adds them to group) */
+ sync_item_get_member (priv->item1);
+ sync_item_get_member (priv->item2);
+ }
+ g_free (name);
+
+ return priv->group;
+}
+
+static gboolean
+sync_group_started_idle (SyncGroup *group)
+{
+ g_signal_emit (group, signals[STARTED], 0);
+
+ return FALSE;
+}
+
+static gboolean
+sync_group_progress_idle (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ g_mutex_lock (priv->mutex);
+ g_signal_emit (group, signals[PROGRESS], 0, priv->changes /
+ (gdouble)priv->max_changes);
+ priv->progress_id = 0;
+ g_mutex_unlock (priv->mutex);
+
+ return FALSE;
+}
+
+static gboolean
+sync_group_conflict_idle (SyncGroup *group)
+{
+ g_signal_emit (group, signals[CONFLICT], 0);
+
+ return FALSE;
+}
+
+static void
+sync_group_free_engine (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ osengine_finalize (priv->engine);
+ osengine_free (priv->engine);
+ priv->engine = NULL;
+}
+
+static gboolean
+sync_group_finished_idle (SyncGroup *group)
+{
+ sync_group_free_engine (group);
+ g_signal_emit (group, signals[FINISHED], 0);
+
+ return FALSE;
+}
+
+static gboolean
+sync_group_failed_idle (SyncGroup *group)
+{
+ sync_group_free_engine (group);
+ g_signal_emit (group, signals[FAILED], 0);
+
+ return FALSE;
+}
+
+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)
+{
+ SyncGroup *group = (SyncGroup *)user_data;
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ priv->mapping = mapping;
+ g_idle_add ((GSourceFunc)sync_group_conflict_idle, group);
+}
+
+static void
+sync_changestatus_cb (OSyncEngine *engine, OSyncChangeUpdate *status,
+ void *user_data)
+{
+ SyncGroup *group = (SyncGroup *)user_data;
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ switch (status->type) {
+ case CHANGE_RECEIVED:
+ /* Shouldn't need to lock here, but just in case */
+ g_mutex_lock (priv->mutex);
+ priv->max_changes ++;
+ g_mutex_unlock (priv->mutex);
+#ifdef DEBUG
+ 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)));
+#endif
+ break;
+ case CHANGE_SENT:
+ /* Update progress and add idle func to send progress
+ * signal in main thread.
+ */
+ g_mutex_lock (priv->mutex);
+ if (priv->changes == 0)
+ g_idle_add ((GSourceFunc)
+ sync_group_started_idle, group);
+ priv->changes ++;
+ if (priv->progress_id == 0)
+ priv->progress_id = g_idle_add ((GSourceFunc)
+ sync_group_progress_idle, group);
+ g_mutex_unlock (priv->mutex);
+#ifdef DEBUG
+ 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)));
+#endif
+ break;
+#ifdef DEBUG
+ 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_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;
+#endif
+ }
+}
+#ifdef DEBUG
+static void
+sync_mappingstatus_cb (OSyncMappingUpdate *status, void *user_data)
+{
+/* SyncGroup *group = (SyncGroup *)user_data;
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);*/
+
+ 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;
+ }
+}
+#endif
+static void
+sync_enginestatus_cb (OSyncEngine *engine, OSyncEngineUpdate *status,
+ void *user_data)
+{
+ SyncGroup *group = (SyncGroup *)user_data;
+
+ switch (status->type) {
+#ifdef DEBUG
+ case ENG_PREV_UNCLEAN:
+ g_debug ("The previous synchronization was unclean. "
+ "Slow-syncing");
+ break;
+ case ENG_ENDPHASE_CON:
+ g_debug ("All clients connected or error");
+ break;
+ case ENG_END_CONFLICTS:
+ g_debug ("All conflicts have been reported");
+ break;
+ case ENG_ENDPHASE_READ:
+ g_debug ("All clients sent changes or error");
+ break;
+ case ENG_ENDPHASE_WRITE:
+ g_debug ("All clients have written");
+ break;
+ case ENG_ENDPHASE_DISCON:
+ g_debug ("All clients have disconnected");
+ break;
+#endif
+ case ENG_SYNC_SUCCESSFULL:
+ g_idle_add ((GSourceFunc)
+ sync_group_finished_idle, group);
+ break;
+ case ENG_ERROR:
+ g_idle_add ((GSourceFunc)
+ sync_group_failed_idle, group);
+ break;
+ }
+}
+#ifdef DEBUG
+static void
+sync_memberstatus_cb (OSyncMemberUpdate *status, void *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;
+ }
+}
+#endif
+gboolean
+sync_group_start (SyncGroup *group)
+{
+ OSyncError *error = NULL;
+ OSyncGroup *os_group;
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if (!(os_group = sync_group_get_osync_group (group))) {
+ g_warning ("Failed to create OSyncGroup");
+ return FALSE;
+ }
+
+ /* Save the group (NOTE: Won't be necessary in the future?) */
+ if (!sync_group_save (group)) {
+ g_warning ("Save failed, not starting sync");
+ return FALSE;
+ }
+
+ if (!(priv->engine = osengine_new (os_group, &error))) {
+ g_warning ("Error while creating syncengine: %s",
+ osync_error_print (&error));
+ osync_error_free (&error);
+ return FALSE;
+ }
+
+ osengine_set_conflict_callback (
+ priv->engine, sync_conflict_cb, group);
+ osengine_set_changestatus_callback (
+ priv->engine, sync_changestatus_cb, group);
+#ifdef DEBUG
+ osengine_set_mappingstatus_callback (
+ priv->engine, sync_mappingstatus_cb, group);
+ osengine_set_memberstatus_callback (
+ priv->engine, sync_memberstatus_cb, group);
+#endif
+ osengine_set_enginestatus_callback (
+ priv->engine, sync_enginestatus_cb, group);
+
+ if (!osengine_init (priv->engine, &error)) {
+ g_warning ("Error while initializing syncengine: %s",
+ osync_error_print (&error));
+ osync_error_free (&error);
+ sync_group_free_engine (group);
+ return FALSE;
+ }
+
+ priv->changes = 0;
+ priv->max_changes = 0;
+
+ if (!osengine_synchronize (priv->engine, &error)) {
+ g_warning ("Error while starting synchronization: %s",
+ osync_error_print (&error));
+ osync_error_free (&error);
+ sync_group_free_engine (group);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+sync_group_resolve_conflict (SyncGroup *group, SyncGroupConflictRes res)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ if ((!priv->mapping) || (!priv->engine)) {
+ g_warning ("%s called with no conflict to resolve", G_STRFUNC);
+ return;
+ }
+
+ switch (res) {
+ case USE_ITEM1:
+ case USE_ITEM2:
+ case ABORT:
+ case IGNORE:
+ default:
+ osengine_mapping_ignore_conflict (
+ priv->engine, priv->mapping);
+ }
+
+ priv->mapping = NULL;
+}
+
+void
+sync_group_abort (SyncGroup *group)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+ if (priv->engine) osengine_abort (priv->engine);
+ else g_warning ("%s called, but no sync in progress", G_STRFUNC);
+}
+
+static void
+sync_group_regroup (SyncGroup *group, gboolean item1, gboolean item2)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+
+ /* Regroup items so their members can be recreated */
+ if (priv->group) {
+ SyncItem *item;
+
+ /* Freeing groups with OpenSync removes them from the env */
+ priv->group = NULL;
+
+ if (item1) {
+ item = g_object_ref (priv->item1);
+ sync_item_ungroup (priv->item1);
+ sync_group_set_item1 (group, item);
+ g_object_unref (item);
+ }
+ if (item2) {
+ item = g_object_ref (priv->item2);
+ sync_item_ungroup (priv->item2);
+ sync_group_set_item2 (group, item);
+ g_object_unref (item);
+ }
+ }
+}
+
+void sync_group_remove_item (SyncGroup *group,
+ SyncItem *item)
+{
+ SyncGroupPrivate *priv = GROUP_PRIVATE (group);
+ gboolean item1;
+
+ if (priv->item1 == item) {
+ sync_group_regroup (group, FALSE, TRUE);
+ priv->item1 = NULL;
+ g_object_unref (item);
+ item1 = TRUE;
+ } else if (priv->item2 == item) {
+ sync_group_regroup (group, TRUE, FALSE);
+ priv->item2 = NULL;
+ g_object_unref (item);
+ } else {
+ g_warning ("%s called on group not containing item", G_STRFUNC);
+ return;
+ }
+}
diff --git a/sync/src/sync_group.h b/sync/src/sync_group.h
new file mode 100644
index 0000000..a9e5869
--- /dev/null
+++ b/sync/src/sync_group.h
@@ -0,0 +1,85 @@
+
+#ifndef SYNC_GROUP_H
+#define SYNC_GROUP_H
+
+#include <opensync/opensync.h>
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define SYNC_TYPE_GROUP sync_group_get_type()
+
+#define SYNC_GROUP(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ SYNC_TYPE_GROUP, SyncGroup))
+
+#define SYNC_GROUP_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ SYNC_TYPE_GROUP, SyncGroupClass))
+
+#define SYNC_IS_GROUP(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ SYNC_TYPE_GROUP))
+
+#define SYNC_IS_GROUP_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ SYNC_TYPE_GROUP))
+
+#define SYNC_GROUP_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ SYNC_TYPE_GROUP, SyncGroupClass))
+
+typedef struct {
+ GObject parent;
+} SyncGroup;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ void (* started) (SyncGroup *group);
+ void (* progress) (SyncGroup *group, gdouble progress);
+ void (* conflict) (SyncGroup *group);
+ void (* finished) (SyncGroup *group);
+ void (* failed) (SyncGroup *group);
+} SyncGroupClass;
+
+GType sync_group_get_type (void);
+
+typedef enum {
+ USE_ITEM1,
+ USE_ITEM2,
+ ABORT,
+ IGNORE,
+} SyncGroupConflictRes;
+
+#include "sync_item.h"
+
+SyncGroup * sync_group_new (void);
+SyncGroup * sync_group_new_with_items (SyncItem *item1,
+ SyncItem *item2);
+
+void sync_group_set_item1 (SyncGroup *group,
+ SyncItem *item1);
+void sync_group_set_item2 (SyncGroup *group,
+ SyncItem *item2);
+void sync_group_set_namespace (SyncGroup *group,
+ const gchar *namespace);
+SyncItem * sync_group_get_item1 (SyncGroup *group);
+SyncItem * sync_group_get_item2 (SyncGroup *group);
+OSyncGroup * sync_group_get_osync_group (SyncGroup *group);
+const gchar * sync_group_get_namespace (SyncGroup *group);
+gchar * sync_group_get_name (SyncGroup *group);
+
+gboolean sync_group_start (SyncGroup *group);
+void sync_group_resolve_conflict (SyncGroup *group,
+ SyncGroupConflictRes res);
+void sync_group_abort (SyncGroup *group);
+void sync_group_remove_item (SyncGroup *group,
+ SyncItem *item);
+gboolean sync_group_delete (SyncGroup *group);
+gboolean sync_group_save (SyncGroup *group);
+
+G_END_DECLS
+
+#endif
diff --git a/sync/src/sync_item.c b/sync/src/sync_item.c
new file mode 100644
index 0000000..324972c
--- /dev/null
+++ b/sync/src/sync_item.c
@@ -0,0 +1,324 @@
+
+#include <glib.h>
+#include <opensync/opensync.h>
+#include "sync_item.h"
+#include "sync_group.h"
+
+G_DEFINE_TYPE (SyncItem, sync_item, G_TYPE_INITIALLY_UNOWNED);
+
+#define ITEM_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), SYNC_TYPE_ITEM, SyncItemPrivate))
+
+typedef struct _SyncItemPrivate SyncItemPrivate;
+
+enum {
+ PROP_NAME = 1,
+ PROP_ADR,
+ PROP_DATA,
+ PROP_DATA_FREE_FUNC,
+ PROP_MEMBER_FUNC,
+ PROP_GROUP,
+};
+
+struct _SyncItemPrivate
+{
+ gchar *name;
+ gchar *adr;
+ gpointer data;
+ SyncItemMemberFunc get_member;
+ SyncItemDataFreeFunc free_data;
+ SyncGroup *group;
+ OSyncMember *member;
+};
+
+static void
+sync_item_finalize (GObject *object)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (object);
+
+ g_free (priv->name);
+ g_free (priv->adr);
+ if (priv->free_data && priv->data)
+ priv->free_data (priv->data);
+
+ G_OBJECT_CLASS (sync_item_parent_class)->finalize (object);
+}
+
+static void
+sync_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SyncItem *item = SYNC_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_NAME :
+ sync_item_set_name (item, g_value_get_string (value));
+ break;
+ case PROP_ADR :
+ sync_item_set_adr (item, g_value_get_string (value));
+ break;
+ case PROP_DATA :
+ sync_item_set_data (item, g_value_get_pointer (value));
+ break;
+ case PROP_DATA_FREE_FUNC :
+ sync_item_set_data_free_func (
+ item, g_value_get_pointer (value));
+ break;
+ case PROP_MEMBER_FUNC :
+ sync_item_set_member_func (
+ item, g_value_get_pointer (value));
+ break;
+ case PROP_GROUP :
+ sync_item_set_group (item,
+ SYNC_GROUP (g_value_get_object (value)));
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (
+ object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+sync_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SyncItem *item = SYNC_ITEM (object);
+
+ switch (prop_id) {
+ case PROP_NAME :
+ g_value_set_string (value, sync_item_get_name (item));
+ break;
+ case PROP_ADR :
+ g_value_set_string (value, sync_item_get_adr (item));
+ break;
+ case PROP_DATA :
+ g_value_set_pointer (value, sync_item_get_data (item));
+ break;
+ case PROP_DATA_FREE_FUNC :
+ g_value_set_pointer (
+ value, sync_item_get_data_free_func (item));
+ break;
+ case PROP_MEMBER_FUNC :
+ g_value_set_pointer (
+ value, sync_item_get_member_func (item));
+ break;
+ case PROP_GROUP :
+ g_value_set_object (
+ value, sync_item_get_group (item));
+ break;
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (
+ object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+sync_item_class_init (SyncItemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = sync_item_set_property;
+ object_class->get_property = sync_item_get_property;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_NAME,
+ g_param_spec_string (
+ "name",
+ ("Name"),
+ ("Name of the synchronisation item."),
+ ("Name"),
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_ADR,
+ g_param_spec_string (
+ "adr",
+ ("Address"),
+ ("Location of the synchronisation item."),
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_DATA,
+ g_param_spec_pointer (
+ "data",
+ ("Data"),
+ ("Custom data"),
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_DATA_FREE_FUNC,
+ g_param_spec_pointer (
+ "data_free_func",
+ ("Data Freeing Function"),
+ ("Function pointer to free set custom data."),
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_MEMBER_FUNC,
+ g_param_spec_pointer (
+ "member_func",
+ ("Member Function"),
+ ("Function pointer to retrieve OSyncMember."),
+ G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_GROUP,
+ g_param_spec_object (
+ "group",
+ ("SyncGroup"),
+ ("SyncGroup this item belongs to."),
+ SYNC_TYPE_GROUP,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (klass, sizeof (SyncItemPrivate));
+
+ object_class->finalize = sync_item_finalize;
+}
+
+static void
+sync_item_init (SyncItem *self)
+{
+ /* Make sure this object is floating? */
+ if (g_object_is_floating (G_OBJECT (self)))
+ g_object_force_floating (G_OBJECT (self));
+}
+
+SyncItem*
+sync_item_new (const gchar *name,
+ const gchar *adr,
+ SyncItemMemberFunc member_func)
+{
+ return g_object_new (SYNC_TYPE_ITEM, "name", name, "adr", adr,
+ "member_func", member_func, NULL);
+}
+
+const gchar *
+sync_item_get_name (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->name;
+}
+
+const gchar *
+sync_item_get_adr (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->adr;
+}
+
+gpointer
+sync_item_get_data (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->data;
+}
+
+SyncItemDataFreeFunc
+sync_item_get_data_free_func (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->free_data;
+}
+
+SyncItemMemberFunc
+sync_item_get_member_func (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->get_member;
+}
+
+OSyncMember *
+sync_item_get_member (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+
+ if (!priv->group) {
+ g_warning ("%s called on SyncItem with no group", G_STRFUNC);
+ return NULL;
+ }
+
+ if (!priv->member)
+ priv->member = priv->get_member (item);
+
+ return priv->member;
+}
+
+SyncGroup *
+sync_item_get_group (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ return priv->group;
+}
+
+void
+sync_item_set_name (SyncItem *item, const gchar *name)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ priv->name = g_strdup (name);
+}
+
+void
+sync_item_set_adr (SyncItem *item, const gchar *adr)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ priv->adr = g_strdup (adr);
+}
+
+void
+sync_item_set_data (SyncItem *item, gpointer data)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ if (priv->free_data && priv->data)
+ priv->free_data (priv->data);
+ priv->data = data;
+}
+
+void
+sync_item_set_data_free_func (SyncItem *item,
+ SyncItemDataFreeFunc data_free_func)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ priv->free_data = data_free_func;
+}
+
+void
+sync_item_set_member_func (SyncItem *item,
+ SyncItemMemberFunc member_func)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ priv->get_member = member_func;
+}
+
+void
+sync_item_set_group (SyncItem *item, SyncGroup *group)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ if (priv->group) {
+ g_warning ("SyncItem already contained in a group");
+ return;
+ }
+ priv->group = group;
+}
+
+void
+sync_item_ungroup (SyncItem *item)
+{
+ SyncItemPrivate *priv = ITEM_PRIVATE (item);
+ if (priv->group) {
+ /* Removing the item from the group frees the group, which in
+ * turn frees the member.
+ */
+ sync_group_remove_item (priv->group, item);
+ priv->group = NULL;
+ priv->member = NULL;
+ } else
+ g_warning ("%s called on SyncItem with no group", G_STRFUNC);
+}
diff --git a/sync/src/sync_item.h b/sync/src/sync_item.h
new file mode 100644
index 0000000..f7a4930
--- /dev/null
+++ b/sync/src/sync_item.h
@@ -0,0 +1,77 @@
+
+#ifndef SYNC_ITEM_H
+#define SYNC_ITEM_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <opensync/opensync.h>
+
+G_BEGIN_DECLS
+
+#define SYNC_TYPE_ITEM sync_item_get_type()
+
+#define SYNC_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ SYNC_TYPE_ITEM, SyncItem))
+
+#define SYNC_ITEM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ SYNC_TYPE_ITEM, SyncItemClass))
+
+#define SYNC_IS_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ SYNC_TYPE_ITEM))
+
+#define SYNC_IS_ITEM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ SYNC_TYPE_ITEM))
+
+#define SYNC_ITEM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ SYNC_TYPE_ITEM, SyncItemClass))
+
+typedef struct {
+ GObject parent;
+} SyncItem;
+
+typedef struct {
+ GObjectClass parent_class;
+} SyncItemClass;
+
+typedef OSyncMember * (*SyncItemMemberFunc) (SyncItem *item);
+typedef void (*SyncItemDataFreeFunc) (gpointer data);
+
+GType sync_item_get_type (void);
+
+#include "sync_group.h"
+
+SyncItem * sync_item_new (const gchar * name,
+ const gchar * adr,
+ SyncItemMemberFunc member_func);
+const gchar * sync_item_get_name (SyncItem * item);
+const gchar * sync_item_get_adr (SyncItem * item);
+gpointer sync_item_get_data (SyncItem * item);
+OSyncMember * sync_item_get_member (SyncItem * item);
+SyncGroup * sync_item_get_group (SyncItem * item);
+
+SyncItemDataFreeFunc sync_item_get_data_free_func (SyncItem * item);
+SyncItemMemberFunc sync_item_get_member_func (SyncItem * item);
+
+void sync_item_set_name (SyncItem * item,
+ const gchar * name);
+void sync_item_set_adr (SyncItem * item,
+ const gchar * adr);
+void sync_item_set_data (SyncItem * item,
+ gpointer data);
+void sync_item_set_data_free_func (SyncItem * item,
+ SyncItemDataFreeFunc data_free_func);
+void sync_item_set_member_func (SyncItem * item,
+ SyncItemMemberFunc member_func);
+void sync_item_set_group (SyncItem * item,
+ SyncGroup * group);
+
+void sync_item_ungroup (SyncItem * item);
+
+G_END_DECLS
+
+#endif
diff --git a/sync/src/sync_main.c b/sync/src/sync_main.c
index e83f21d..85ca89c 100644
--- a/sync/src/sync_main.c
+++ b/sync/src/sync_main.c
@@ -9,8 +9,12 @@
#include <opensync/opensync.h>
#include <osengine/engine.h>
-#include "sync.h"
-
+#include "sync_main.h"
+#include "sync_group.h"
+#include "sync_item.h"
+#include "sync_evo2_item.h"
+#include "sync_file_item.h"
+#if 0
static gboolean
sync_clean_backup (SyncData *data)
{
@@ -137,317 +141,94 @@ sync_get_backup_group (SyncData *data)
return group;
}
+#endif
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);
+ static gint count = 0;
- 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 "?";
+ 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;
+ }
}
-}
-
-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);
+ return TRUE;
}
static void
-sync_changestatus_cb (OSyncEngine *engine, OSyncChangeUpdate *status,
- void *user_data)
+sync_started_cb (SyncGroup *group, SyncData *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;
- }
+ 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_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)
+sync_progress_cb (SyncGroup *group, gdouble progress, SyncData *data)
{
- OSyncEngine *engine = (OSyncEngine *)data;
-
- g_debug ("Finalizing/freeing sync engine");
- osengine_finalize (engine);
- osengine_free (engine);
-
- return FALSE;
+ GtkWidget *widget = glade_xml_get_widget (
+ data->xml, "sync_progressbar");
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), progress);
}
static void
-sync_enginestatus_cb (OSyncEngine *engine, OSyncEngineUpdate *status,
- void *user_data)
+sync_conflict_cb (SyncGroup *group, SyncData *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);
+ GtkWidget *widget = glade_xml_get_widget (data->xml, "main_notebook");
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_CONFLICT);
}
static void
-sync_memberstatus_cb (OSyncMemberUpdate *status, void *user_data)
+sync_finished_cb (SyncGroup *group, SyncData *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;
- }
+ 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);
}
static void
-sync_backup (SyncData *data)
+sync_failed_cb (SyncGroup *group, 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);
+ GtkWidget *widget = glade_xml_get_widget (data->xml, "main_notebook");
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_ERROR);
+ g_source_remove (data->animate_id);
}
static gboolean
@@ -464,17 +245,47 @@ sync_item_activated_cb (GtkIconView *iconview, GtkTreePath *arg1,
if (gtk_tree_model_get_iter (
GTK_TREE_MODEL (data->model), &iter, arg1)) {
- gint id;
+ SyncItem *item;
+ const gchar *name;
+ GtkWidget *widget;
+ gfloat x, y;
+
gtk_tree_model_get (GTK_TREE_MODEL (data->model),
- &iter, COL_ID, &id, -1);
+ &iter, COL_NAME, &name, -1);
- /* Special case for back-up item */
- if (id == 0) {
- g_debug ("Performing backup");
- sync_backup (data);
-
+ item = (SyncItem *)g_hash_table_lookup (data->sync_items, name);
+
+ sync_group_set_item2 (data->group, item);
+ data->started = FALSE;
+
+ if (!sync_group_start (data->group)) {
+ /* 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, "main_notebook");
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), TAB_SYNC);
+ data->animate_id = g_timeout_add (
+ ANIM_FREQ, (GSourceFunc)sync_animate, data);
}
}
@@ -506,14 +317,15 @@ main (int argc, char **argv)
GtkTreePath *path;
GtkIconTheme *icon_theme;
gint width = 0, height = 0;
- OSyncError *error = NULL;
SyncData data;
+ SyncItem *preset_item;
+ gchar *temp_path;
gtk_init (&argc, &argv);
glade_init ();
- g_thread_init (NULL);
- gdk_threads_init ();
- /* Must be called due to buggy OpenSync */
+/* g_thread_init (NULL);
+ gdk_threads_init ();*/
+ /* FIXME: Must be called due to buggy OpenSync */
gconf_client_get_default ();
data.xml = glade_xml_new (XML_FILE, NULL, NULL);
@@ -524,38 +336,50 @@ main (int argc, char **argv)
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);
+ 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), 0, NULL);
+ GTK_STOCK_NETWORK, 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_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+ 2, 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 */
+ /* Create local sync-item and sync group */
+ data.local_item = sync_evo2_item_new ("Local", NULL, NULL, NULL);
+ data.group = sync_group_new_with_items (data.local_item, NULL);
+
+ /* Create SyncItem hash-table */
+ data.sync_items = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, g_object_unref);
+ /* Insert preset items */
+ temp_path = g_strdup_printf (TEMP_PATH, g_getenv ("HOME"));
+ preset_item = g_object_ref (sync_file_item_new ("Test", temp_path));
+ g_hash_table_insert (data.sync_items, "Test", preset_item);
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);
+ 0, COL_NAME, "Test", COL_PIXBUF, data.backup_icon, -1);
+ g_free (temp_path);
+
+ /* TODO: Insert saved items */
+ /* TODO: Avahi detection of local sync servers */
+ /* TODO: Bluetooth scanning? */
+ /* Insert backup item */
+ /* Insert restore item */
+
+ /* Select first item */
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",
@@ -579,6 +403,18 @@ main (int argc, char **argv)
widget = glade_xml_get_widget (data.xml, "error_close_button");
g_signal_connect (G_OBJECT (widget), "clicked",
G_CALLBACK (sync_chooser_cb), &data);
+
+ /* Connect SyncGroup signals */
+ g_signal_connect (G_OBJECT (data.group), "started",
+ G_CALLBACK (sync_started_cb), &data);
+ g_signal_connect (G_OBJECT (data.group), "progress",
+ G_CALLBACK (sync_progress_cb), &data);
+ g_signal_connect (G_OBJECT (data.group), "conflict",
+ G_CALLBACK (sync_conflict_cb), &data);
+ g_signal_connect (G_OBJECT (data.group), "finished",
+ G_CALLBACK (sync_finished_cb), &data);
+ g_signal_connect (G_OBJECT (data.group), "failed",
+ G_CALLBACK (sync_failed_cb), &data);
gtk_main ();
diff --git a/sync/src/sync_main.h b/sync/src/sync_main.h
new file mode 100644
index 0000000..528b70e
--- /dev/null
+++ b/sync/src/sync_main.h
@@ -0,0 +1,51 @@
+
+#ifndef SYNC_MAIN_H
+#define SYNC_MAIN_H
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <opensync/opensync.h>
+#include "sync_group.h"
+#include "sync_item.h"
+
+#define XML_FILE PKGDATADIR G_DIR_SEPARATOR_S "sync.glade"
+#define TEMP_PATH "%s" G_DIR_SEPARATOR_S ".gnome2" G_DIR_SEPARATOR_S \
+ "sync" G_DIR_SEPARATOR_S "backup"
+
+#define ANIM_FREQ 100
+#define SWITCH_FREQ 10
+
+enum {
+ COL_NAME,
+ COL_PIXBUF,
+};
+
+enum {
+ TAB_CHOOSE = 0,
+ TAB_SYNC,
+ TAB_CONFLICT,
+ TAB_ERROR,
+ TAB_SUCCESS
+};
+
+enum {
+ IMAGE_TAB_PREPARE = 0,
+ IMAGE_TAB_SYNC,
+};
+
+typedef struct {
+ GladeXML *xml;
+ GdkPixbuf *backup_icon;
+ GdkPixbuf *restore_icon;
+ GdkPixbuf *network_icon;
+ GtkListStore *model;
+ SyncItem *local_item;
+ SyncGroup *group;
+ GHashTable *sync_items;
+
+ gboolean started;
+ guint animate_id;
+} SyncData;
+
+
+#endif