Merge patch to merge-back sessionwork to trunk
- From: Philip Van Hoof <spam pvanhoof be>
- To: tinymail-devel-list gnome org
- Subject: Merge patch to merge-back sessionwork to trunk
- Date: Tue, 31 Jul 2007 00:50:44 +0200
FYI and attached. This merge-work will most likely be committed tomorrow
noon (noon in Europe).
--
Philip Van Hoof, software developer
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
http://www.pvanhoof.be/blog
Index: libtinymail-gpe/tny-gpe-account-store.c
===================================================================
--- libtinymail-gpe/tny-gpe-account-store.c (revision 2535)
+++ libtinymail-gpe/tny-gpe-account-store.c (working copy)
@@ -153,11 +153,7 @@
gchar *ptr = strrchr (key, '/'); ptr++;
if (!strcmp (ptr, "count"))
- {
kill_stored_accounts (priv);
- g_signal_emit (self,
- tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0);
- }
g_free (key);
@@ -493,35 +489,6 @@
}
-
-void
-tny_gpe_account_store_add_store_account (TnyGpeAccountStore *self, TnyStoreAccount *account)
-{
- TnyGpeAccountStorePriv *priv = TNY_GPE_ACCOUNT_STORE_GET_PRIVATE (self);
-
- tny_gpe_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_gpe_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "store");
- tny_gpe_account_store_notify_add (TNY_ACCOUNT_STORE (self));
-
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
-void
-tny_gpe_account_store_add_transport_account (TnyGpeAccountStore *self, TnyTransportAccount *account)
-{
- TnyGpeAccountStorePriv *priv = TNY_GPE_ACCOUNT_STORE_GET_PRIVATE (self);
-
- tny_gpe_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_gpe_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "transport");
- tny_gpe_account_store_notify_add (TNY_ACCOUNT_STORE (self));
-
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
static TnyDevice*
tny_gpe_account_store_get_device (TnyAccountStore *self)
{
Index: libtinymail-gpe/tny-gpe-account-store.h
===================================================================
--- libtinymail-gpe/tny-gpe-account-store.h (revision 2535)
+++ libtinymail-gpe/tny-gpe-account-store.h (working copy)
@@ -52,9 +52,6 @@
TnyAccountStore* tny_gpe_account_store_new (void);
TnySessionCamel* tny_gpe_account_store_get_session (TnyGpeAccountStore *self);
-void tny_gpe_account_store_add_transport_account (TnyGpeAccountStore *self, TnyTransportAccount *account);
-void tny_gpe_account_store_add_store_account (TnyGpeAccountStore *self, TnyStoreAccount *account);
-
G_END_DECLS
#endif
Index: libtinymail-camel/tny-camel-folder.c
===================================================================
--- libtinymail-camel/tny-camel-folder.c (revision 2535)
+++ libtinymail-camel/tny-camel-folder.c (working copy)
@@ -514,10 +514,17 @@
CamelException ex = CAMEL_EXCEPTION_INITIALISER;
gboolean haderr = FALSE;
- g_assert (TNY_IS_CAMEL_MSG (msg));
+ if (!TNY_IS_CAMEL_MSG (msg))
+ {
+ g_critical ("You must not use a non-TnyCamelMsg implementation "
+ "of TnyMsg with TnyCamelFolder types. This indicates a "
+ "problem in the software (unsupported operation)\n");
+ g_assert (TNY_IS_CAMEL_MSG (msg));
+ }
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_ADD_MSG))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_ADD_MSG))
return;
g_static_rec_mutex_lock (priv->folder_lock);
@@ -538,16 +545,20 @@
GPtrArray *dst_orig_uids = NULL;
gint a = 0, len = 0, nlen = 0;
CamelException ex2 = CAMEL_EXCEPTION_INITIALISER;
+
len = priv->folder->summary->messages->len;
dst_orig_uids = g_ptr_array_sized_new (len);
- for (a = 0; a < len; a++) {
- CamelMessageInfo *om = camel_folder_summary_index (priv->folder->summary, a);
+
+ for (a = 0; a < len; a++)
+ {
+ CamelMessageInfo *om =
+ camel_folder_summary_index (priv->folder->summary, a);
if (om && om->uid)
g_ptr_array_add (dst_orig_uids, g_strdup (om->uid));
if (om)
camel_message_info_free (om);
}
-
+
camel_folder_append_message (priv->folder, message, NULL, NULL, &ex);
priv->unread_length = camel_folder_get_unread_message_count (priv->folder);
priv->cached_length = camel_folder_get_message_count (priv->folder);
@@ -557,8 +568,11 @@
for (a = 0; a < nlen; a++)
{
- CamelMessageInfo *om = camel_folder_summary_index (priv->folder->summary, a);
- if (om && om->uid) {
+ CamelMessageInfo *om =
+ camel_folder_summary_index (priv->folder->summary, a);
+
+ if (om && om->uid)
+ {
gint b = 0;
gboolean found = FALSE;
@@ -648,8 +662,9 @@
g_assert (TNY_IS_HEADER (header));
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REMOVE_MSG))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_REMOVE_MSG))
return;
if (!priv->remove_strat) {
@@ -669,7 +684,6 @@
tny_msg_remove_strategy_perform_remove (priv->remove_strat, self, header, err);
-
/* Notify about unread count */
_tny_camel_folder_check_unread_count (TNY_CAMEL_FOLDER (self));
@@ -795,7 +809,6 @@
{
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
priv->cached_length = len;
-
return;
}
@@ -805,7 +818,6 @@
{
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
priv->local_size = len;
-
return;
}
@@ -819,7 +831,6 @@
tny_camel_folder_get_all_count_default (TnyFolder *self)
{
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
-
return priv->cached_length;
}
@@ -834,7 +845,6 @@
tny_camel_folder_get_account_default (TnyFolder *self)
{
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
-
return TNY_ACCOUNT (g_object_ref (priv->account));
}
@@ -851,12 +861,11 @@
return;
}
-/**
- * When using a #GMainLoop this method will execute a callback using
+/* When using a #GMainLoop this method will execute a callback using
* g_idle_add_full. Note that without a #GMainLoop, the callbacks
* could happen in a worker thread (depends on who call it) at an
- * unknown moment in time (check your locking in this case).
- */
+ * unknown moment in time (check your locking in this case). */
+
static void
execute_callback (gint depth,
gint priority,
@@ -887,8 +896,9 @@
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
CamelException ex = CAMEL_EXCEPTION_INITIALISER;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_SYNC))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_SYNC))
return;
g_static_rec_mutex_lock (priv->folder_lock);
@@ -948,10 +958,10 @@
TnyFolder *self = info->self;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
- _tny_camel_folder_unreason (priv);
-
/* thread reference */
+ _tny_camel_folder_unreason (priv);
g_object_unref (G_OBJECT (self));
+
if (info->err)
g_error_free (info->err);
@@ -960,10 +970,12 @@
tny_idle_stopper_destroy (info->stopper);
info->stopper = NULL;
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
return;
}
@@ -976,16 +988,16 @@
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
TnyFolderChange *change = tny_folder_change_new (self);
- if (info->callback)
- info->callback (info->self, info->cancelled, &info->err, info->user_data);
-
- tny_idle_stopper_stop (info->stopper);
-
tny_folder_change_set_new_all_count (change, priv->cached_length);
tny_folder_change_set_new_unread_count (change, priv->unread_length);
notify_folder_observers_about (self, change);
g_object_unref (change);
+ if (info->callback)
+ info->callback (info->self, info->cancelled, &info->err, info->user_data);
+
+ tny_idle_stopper_stop (info->stopper);
+
return FALSE;
}
@@ -1023,6 +1035,7 @@
if (!load_folder_no_lock (priv))
{
tny_camel_folder_sync_async_destroyer (info);
+ g_slice_free (SyncFolderInfo, thr_user_data);
g_static_rec_mutex_unlock (priv->folder_lock);
return NULL;
}
@@ -1067,6 +1080,7 @@
tny_camel_folder_sync_async_callback, info,
tny_camel_folder_sync_async_destroyer);
+
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
if (!info->had_callback)
@@ -1085,22 +1099,21 @@
tny_camel_folder_sync_async_cancelled_destroyer (gpointer thr_user_data)
{
SyncFolderInfo *info = thr_user_data;
-
g_error_free (info->err);
g_object_unref (info->self);
g_slice_free (SyncFolderInfo, thr_user_data);
+ return;
}
static gboolean
tny_camel_folder_sync_async_cancelled_callback (gpointer thr_user_data)
{
SyncFolderInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, TRUE, &info->err, info->user_data);
-
return FALSE;
}
+
void
tny_camel_folder_sync_async_default (TnyFolder *self, gboolean expunge, TnySyncFolderCallback callback, TnyStatusCallback status_callback, gpointer user_data)
{
@@ -1118,6 +1131,7 @@
info->user_data = user_data;
info->depth = g_main_depth ();
info->expunge = expunge;
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_SYNC))
@@ -1125,7 +1139,6 @@
if (callback) {
info->err = g_error_copy (err);
g_object_ref (info->self);
-
execute_callback (info->depth, G_PRIORITY_DEFAULT,
tny_camel_folder_sync_async_cancelled_callback, info,
tny_camel_folder_sync_async_cancelled_destroyer);
@@ -1137,7 +1150,7 @@
info->stopper = tny_idle_stopper_new();
/* thread reference */
- g_object_ref (G_OBJECT (self));
+ g_object_ref (info->self);
_tny_camel_folder_reason (priv);
_tny_camel_queue_launch (TNY_FOLDER_PRIV_GET_QUEUE (priv),
@@ -1158,8 +1171,6 @@
TnyStatusCallback status_callback;
gpointer user_data;
gboolean cancelled;
- /* This stops us from calling a status callback after the operation has
- * finished. */
TnyIdleStopper* stopper;
guint depth;
GError *err;
@@ -1173,8 +1184,8 @@
/** This is the GDestroyNotify callback provided to g_idle_add_full()
- * for tny_camel_folder_refresh_async_callback().
- */
+ * for tny_camel_folder_refresh_async_callback().*/
+
static void
tny_camel_folder_refresh_async_destroyer (gpointer thr_user_data)
{
@@ -1182,10 +1193,10 @@
TnyFolder *self = info->self;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
- _tny_camel_folder_unreason (priv);
-
/* thread reference */
+ _tny_camel_folder_unreason (priv);
g_object_unref (G_OBJECT (self));
+
if (info->err)
g_error_free (info->err);
@@ -1194,10 +1205,12 @@
tny_idle_stopper_destroy (info->stopper);
info->stopper = NULL;
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
return;
}
@@ -1210,19 +1223,20 @@
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
TnyFolderChange *change = tny_folder_change_new (self);
+ tny_folder_change_set_new_all_count (change, priv->cached_length);
+ tny_folder_change_set_new_unread_count (change, priv->unread_length);
+ notify_folder_observers_about (self, change);
+ g_object_unref (change);
+
if (info->callback)
info->callback (info->self, info->cancelled, &info->err, info->user_data);
/* Prevent status callbacks from being called after this
* (can happen because the 2 idle callbacks have different priorities)
* by causing tny_idle_stopper_is_stopped() to return TRUE. */
+
tny_idle_stopper_stop (info->stopper);
- tny_folder_change_set_new_all_count (change, priv->cached_length);
- tny_folder_change_set_new_unread_count (change, priv->unread_length);
- notify_folder_observers_about (self, change);
- g_object_unref (change);
-
return FALSE;
}
@@ -1260,6 +1274,7 @@
if (!load_folder_no_lock (priv))
{
tny_camel_folder_refresh_async_destroyer (info);
+ g_slice_free (RefreshFolderInfo, info);
g_static_rec_mutex_unlock (priv->folder_lock);
return NULL;
}
@@ -1299,15 +1314,9 @@
info->condition = g_cond_new ();
info->had_callback = FALSE;
- if (info->callback)
- {
- execute_callback (info->depth, G_PRIORITY_DEFAULT,
- tny_camel_folder_refresh_async_callback, info,
- tny_camel_folder_refresh_async_destroyer);
- } else { /* Thread reference */
- g_object_unref (G_OBJECT (self));
- _tny_camel_folder_unreason (priv);
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_folder_refresh_async_callback, info,
+ tny_camel_folder_refresh_async_destroyer);
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
@@ -1333,20 +1342,18 @@
tny_camel_folder_refresh_async_cancelled_destroyer (gpointer thr_user_data)
{
RefreshFolderInfo *info = thr_user_data;
-
g_error_free (info->err);
g_object_unref (info->self);
g_slice_free (RefreshFolderInfo, thr_user_data);
+ return;
}
static gboolean
tny_camel_folder_refresh_async_cancelled_callback (gpointer thr_user_data)
{
RefreshFolderInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, TRUE, &info->err, info->user_data);
-
return FALSE;
}
@@ -1364,6 +1371,7 @@
* Important is to add and remove references. You don't want the reference to
* become zero while doing stuff on the instance in the background, don't you?
**/
+
static void
tny_camel_folder_refresh_async_default (TnyFolder *self, TnyRefreshFolderCallback callback, TnyStatusCallback status_callback, gpointer user_data)
{
@@ -1380,6 +1388,7 @@
info->status_callback = status_callback;
info->user_data = user_data;
info->depth = g_main_depth ();
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
@@ -1387,7 +1396,6 @@
if (callback) {
info->err = g_error_copy (err);
g_object_ref (info->self);
-
execute_callback (info->depth, G_PRIORITY_DEFAULT,
tny_camel_folder_refresh_async_cancelled_callback, info,
tny_camel_folder_refresh_async_cancelled_destroyer);
@@ -1431,8 +1439,9 @@
guint oldlen, oldurlen;
TnyFolderChange *change = NULL;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_REFRESH))
return;
g_static_rec_mutex_lock (priv->folder_lock);
@@ -1444,9 +1453,6 @@
return;
}
- /*_tny_camel_account_start_camel_operation (TNY_CAMEL_ACCOUNT (priv->account),
- NULL, NULL, NULL); */
-
oldlen = priv->cached_length;
oldurlen = priv->unread_length;
@@ -1454,14 +1460,11 @@
camel_folder_refresh_info (priv->folder, &ex);
priv->want_changes = TRUE;
- /* _tny_camel_account_stop_camel_operation (TNY_CAMEL_ACCOUNT (priv->account)); */
-
priv->cached_length = camel_folder_get_message_count (priv->folder);
if (G_LIKELY (priv->folder) && CAMEL_IS_FOLDER (priv->folder) && G_LIKELY (priv->has_summary_cap))
priv->unread_length = (guint) camel_folder_get_unread_message_count (priv->folder);
update_iter_counts (priv);
-
if (camel_exception_is_set (&ex))
{
g_set_error (err, TNY_FOLDER_ERROR,
@@ -1506,14 +1509,11 @@
/* TODO: Proxy instantiation (happens a lot, could use a pool) */
header = _tny_camel_header_new ();
+ _tny_camel_header_set_folder ((TnyCamelHeader *) header, (TnyCamelFolder *) self, priv);
+ _tny_camel_header_set_camel_message_info ((TnyCamelHeader *) header, mi, FALSE);
+ tny_list_prepend (headers, (GObject*) header);
+ g_object_unref (header);
- _tny_camel_header_set_folder (TNY_CAMEL_HEADER (header), TNY_CAMEL_FOLDER (self), priv);
- _tny_camel_header_set_camel_message_info (TNY_CAMEL_HEADER (header), mi, FALSE);
-
- tny_list_prepend (headers, (GObject*)header);
-
- g_object_unref (G_OBJECT (header));
-
return;
}
@@ -1537,9 +1537,6 @@
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
return;
- /* we reason the folder to make sure it does not
- * lose all the references and uncache, causing an interlock */
- _tny_camel_folder_reason (priv);
g_static_rec_mutex_lock (priv->folder_lock);
if (!load_folder_no_lock (priv))
@@ -1549,8 +1546,11 @@
return;
}
- g_object_ref (G_OBJECT (headers));
+ /* We reason the folder to make sure it does not lose all the references
+ * and uncache, causing an interlock */
+ _tny_camel_folder_reason (priv);
+ g_object_ref (headers);
ptr = g_slice_new (FldAndPriv);
ptr->self = self;
ptr->priv = priv;
@@ -1576,7 +1576,8 @@
g_slice_free (FldAndPriv, ptr);
- g_object_unref (G_OBJECT (headers));
+ g_object_unref (headers);
+
g_static_rec_mutex_unlock (priv->folder_lock);
_tny_camel_folder_unreason (priv);
@@ -1612,18 +1613,8 @@
tny_camel_folder_get_msg_async_destroyer (gpointer thr_user_data)
{
GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
- TnyFolderChange *change;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
- if (info->msg)
- {
- change = tny_folder_change_new (info->self);
- tny_folder_change_set_received_msg (change, info->msg);
- notify_folder_observers_about (info->self, change);
- g_object_unref (change);
- g_object_unref (info->msg);
- }
-
/* thread reference */
_tny_camel_folder_unreason (priv);
g_object_unref (info->self);
@@ -1636,10 +1627,12 @@
tny_idle_stopper_destroy (info->stopper);
info->stopper = NULL;
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
return;
}
@@ -1649,13 +1642,25 @@
tny_camel_folder_get_msg_async_callback (gpointer thr_user_data)
{
GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
+ TnyFolderChange *change;
+ TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+ if (info->msg)
+ {
+ change = tny_folder_change_new (info->self);
+ tny_folder_change_set_received_msg (change, info->msg);
+ notify_folder_observers_about (info->self, change);
+ g_object_unref (change);
+ g_object_unref (info->msg);
+ }
+
if (info->callback)
info->callback (info->self, info->cancelled, info->msg, &info->err, info->user_data);
/* Prevent status callbacks from being called after this
* (can happen because the 2 idle callbacks have different priorities)
* by causing tny_idle_stopper_is_stopped() to return TRUE. */
+
tny_idle_stopper_stop (info->stopper);
return FALSE;
@@ -1687,6 +1692,8 @@
GError *err = NULL;
CamelOperation *cancel;
+ /* TNY TODO: Ensure load_folder here */
+
/* This one doesn't use the _tny_camel_account_start_camel_operation
* infrastructure because it doesn't need to cancel existing operations
* due to a patch to camel-lite allowing messages to be fetched while
@@ -1696,14 +1703,14 @@
/* To disable parallel getting of messages while summary is being retreived,
* restore this lock (A) */
-
/* g_static_rec_mutex_lock (priv->folder_lock); */
camel_operation_ref (cancel);
camel_operation_register (cancel);
camel_operation_start (cancel, (char *) "Getting message");
- info->msg = tny_msg_receive_strategy_perform_get_msg (priv->receive_strat, info->self, info->header, &err);
+ info->msg = tny_msg_receive_strategy_perform_get_msg (priv->receive_strat,
+ info->self, info->header, &err);
info->cancelled = camel_operation_cancel_check (cancel);
@@ -1714,7 +1721,6 @@
/* To disable parallel getting of messages while summary is being retreived,
* restore this lock (B) */
-
/* g_static_rec_mutex_unlock (priv->folder_lock); */
info->err = NULL;
@@ -1727,21 +1733,16 @@
} else
info->err = NULL;
+ /* thread reference header */
g_object_unref (info->header);
info->mutex = g_mutex_new ();
info->condition = g_cond_new ();
info->had_callback = FALSE;
- if (info->callback)
- {
- execute_callback (info->depth, G_PRIORITY_DEFAULT,
- tny_camel_folder_get_msg_async_callback, info,
- tny_camel_folder_get_msg_async_destroyer);
- } else {/* thread reference */
- _tny_camel_folder_unreason (priv);
- g_object_unref (info->self);
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_folder_get_msg_async_callback, info,
+ tny_camel_folder_get_msg_async_destroyer);
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
@@ -1762,10 +1763,10 @@
tny_camel_folder_get_msg_async_cancelled_destroyer (gpointer thr_user_data)
{
GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
-
g_error_free (info->err);
g_object_unref (info->self);
g_slice_free (GetMsgInfo, info);
+ return;
}
static gboolean
@@ -1773,10 +1774,8 @@
{
GetMsgInfo *info = (GetMsgInfo *) thr_user_data;
-
if (info->callback)
info->callback (info->self, TRUE, NULL, &info->err, info->user_data);
-
return FALSE;
}
@@ -1804,6 +1803,7 @@
info->status_callback = status_callback;
info->user_data = user_data;
info->depth = g_main_depth ();
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_GET_MSG))
@@ -1827,9 +1827,11 @@
/* thread reference */
_tny_camel_folder_reason (priv);
- g_object_ref (G_OBJECT (info->self));
- g_object_ref (G_OBJECT (info->header));
+ g_object_ref (info->self);
+ /* thread reference header */
+ g_object_ref (info->header);
+
_tny_camel_queue_launch (TNY_FOLDER_PRIV_GET_MSG_QUEUE (priv),
tny_camel_folder_get_msg_async_thread, info);
@@ -1885,8 +1887,9 @@
TnyMsg *retval = NULL;
TnyFolderChange *change;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_GET_MSG))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_GET_MSG))
return NULL;
g_assert (TNY_IS_HEADER (header));
@@ -1941,8 +1944,9 @@
CamelMessageInfo *info;
const gchar *uid;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_GET_MSG))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_GET_MSG))
return NULL;
if (!priv->receive_strat) {
@@ -2040,7 +2044,6 @@
tny_camel_folder_get_id_default (TnyFolder *self)
{
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
-
return priv->folder_name;
}
@@ -2279,10 +2282,10 @@
{
TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
tny_folder_store_observer_update (observer, change);
- g_object_unref (G_OBJECT (observer));
+ g_object_unref (observer);
tny_iterator_next (iter);
}
- g_object_unref (G_OBJECT (iter));
+ g_object_unref (iter);
}
static void
@@ -2307,7 +2310,7 @@
tny_debug ("tny_folder_copy: observers notify folder-del %s\n",
tny_folder_get_name (evt->fol));
- g_object_unref (G_OBJECT (change));
+ g_object_unref (change);
}
cpy_event_free (evt);
@@ -2329,7 +2332,7 @@
else
notify_folder_store_observers_about (evt->str, change);
- g_object_unref (G_OBJECT (change));
+ g_object_unref (change);
tny_debug ("tny_folder_copy: observers notify folder-add %s\n",
tny_folder_get_name (evt->fol));
@@ -2365,7 +2368,6 @@
priv->reason_to_live);
g_propagate_error (err, nerr);
- /* g_error_free (nerr); */
return retc;
}
@@ -2534,8 +2536,9 @@
GError *nerr = NULL;
CpyRecRet *cpyr;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_COPY))
return NULL;
cpyr = tny_camel_folder_copy_shared (self, into, new_name, del, &nerr, rems, adds);
@@ -2547,10 +2550,8 @@
g_slice_free (CpyRecRet, cpyr);
if (nerr != NULL)
- {
g_propagate_error (err, nerr);
- /* g_error_free (nerr); */
- } else
+ else
notify_folder_observers_about_copy (adds, rems, del);
_tny_session_stop_operation (TNY_FOLDER_PRIV_GET_SESSION (priv));
@@ -2590,10 +2591,8 @@
CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
if (info->err == NULL)
- {
notify_folder_observers_about_copy (info->adds, info->rems,
info->delete_originals);
- }
if (info->new_folder)
g_object_unref (info->new_folder);
@@ -2601,7 +2600,6 @@
/* thread reference */
g_object_unref (info->into);
g_object_unref (info->self);
- /* _tny_camel_folder_unreason (priv); */
if (info->err)
g_error_free (info->err);
@@ -2613,11 +2611,14 @@
g_free (info->new_name);
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
+
return;
}
@@ -2645,6 +2646,10 @@
TnyProgressInfo *info = NULL;
/* Send back progress data only for these internal operations */
+
+ if (!what)
+ return;
+
if ((g_ascii_strcasecmp(what, "Renaming folder")) &&
(g_ascii_strcasecmp(what, "Moving messages")) &&
(g_ascii_strcasecmp(what, "Copying messages")))
@@ -2678,10 +2683,10 @@
_tny_camel_account_start_camel_operation (TNY_CAMEL_ACCOUNT (priv->account),
tny_camel_folder_copy_async_status,
- info,
- "Copying folder");
+ info, "Copying folder");
- info->adds = NULL; info->rems = NULL;
+ info->adds = NULL;
+ info->rems = NULL;
cpyr = tny_camel_folder_copy_shared (info->self, info->into,
info->new_name, info->delete_originals, &nerr,
@@ -2699,9 +2704,7 @@
info->err = NULL;
if (nerr != NULL)
- {
g_propagate_error (&info->err, nerr);
- }
g_static_rec_mutex_unlock (priv->folder_lock);
@@ -2709,15 +2712,9 @@
info->condition = g_cond_new ();
info->had_callback = FALSE;
- if (info->callback)
- {
- execute_callback (info->depth, G_PRIORITY_DEFAULT,
- tny_camel_folder_copy_async_callback, info,
- tny_camel_folder_copy_async_destroyer);
- } else { /* Thread reference */
- g_object_unref (info->into);
- g_object_unref (info->self);
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_folder_copy_async_callback, info,
+ tny_camel_folder_copy_async_destroyer);
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
@@ -2737,12 +2734,12 @@
tny_camel_folder_copy_async_cancelled_destroyer (gpointer thr_user_data)
{
CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
-
g_free (info->new_name);
g_error_free (info->err);
g_object_unref (info->self);
g_object_unref (info->into);
g_slice_free (CopyFolderInfo, info);
+ return;
}
static gboolean
@@ -2750,10 +2747,8 @@
{
CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
-
if (info->callback)
info->callback (info->self, info->into, TRUE, NULL, &info->err, info->user_data);
-
return FALSE;
}
@@ -2785,6 +2780,7 @@
info->err = NULL;
info->delete_originals = del;
info->new_name = g_strdup (new_name);
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
@@ -2805,10 +2801,10 @@
/* Use a ref count because we do not know which of the 2 idle callbacks
* will be the last, and we can only unref self in the last callback:
* This is destroyed in the idle GDestroyNotify callback. */
+
info->stopper = tny_idle_stopper_new();
/* thread reference */
-/* _tny_camel_folder_reason (priv); */
g_object_ref (G_OBJECT (info->self));
g_object_ref (G_OBJECT (info->into));
@@ -2909,10 +2905,12 @@
info->stopper = NULL;
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
return;
}
@@ -2921,15 +2919,12 @@
tny_camel_folder_transfer_msgs_async_callback (gpointer thr_user_data)
{
TransferMsgsInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, info->cancelled, &info->err, info->user_data);
-
/* Prevent status callbacks from being called after this
* (can happen because the 2 idle callbacks have different priorities)
* by causing tny_idle_stopper_is_stopped() to return TRUE. */
tny_idle_stopper_stop (info->stopper);
-
return FALSE;
}
@@ -2953,8 +2948,9 @@
g_assert (TNY_IS_FOLDER (folder_src));
g_assert (TNY_IS_FOLDER (folder_dst));
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_TRANSFER_MSGS))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_ERROR,
+ TNY_FOLDER_ERROR_TRANSFER_MSGS))
return;
iter = tny_list_create_iterator (headers);
@@ -3304,20 +3300,9 @@
info->condition = g_cond_new ();
info->had_callback = FALSE;
- /* Call callback function, if it exists */
- if (info->callback)
- {
- execute_callback (info->depth, G_PRIORITY_DEFAULT,
- tny_camel_folder_transfer_msgs_async_callback, info,
- tny_camel_folder_transfer_msgs_async_destroyer);
- } else {
- /* Thread reference */
- _tny_camel_folder_unreason (priv_src);
- g_object_unref (G_OBJECT (info->self));
- g_object_unref (G_OBJECT (info->header_list));
- _tny_camel_folder_unreason (priv_dst);
- g_object_unref (G_OBJECT (info->folder_dst));
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_folder_transfer_msgs_async_callback, info,
+ tny_camel_folder_transfer_msgs_async_destroyer);
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
@@ -3337,21 +3322,19 @@
tny_camel_folder_transfer_msgs_async_cancelled_destroyer (gpointer thr_user_data)
{
TransferMsgsInfo *info = thr_user_data;
-
g_error_free (info->err);
g_object_unref (info->new_header_list);
g_object_unref (info->self);
g_slice_free (TransferMsgsInfo, info);
+ return;
}
static gboolean
tny_camel_folder_transfer_msgs_async_cancelled_callback (gpointer thr_user_data)
{
TransferMsgsInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, TRUE, &info->err, info->user_data);
-
return FALSE;
}
@@ -3385,6 +3368,7 @@
info->user_data = user_data;
info->delete_originals = delete_originals;
info->depth = g_main_depth ();
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_TRANSFER_MSGS))
@@ -3520,9 +3504,10 @@
g_mutex_lock (priv->reason_lock);
priv->reason_to_live--;
-#ifdef DEBUG
+#ifdef DEBUG_EXTRA
g_print ("_tny_camel_folder_unreason (%s) : %d\n",
- priv->folder_name?priv->folder_name:"(cleared)", priv->reason_to_live);
+ priv->folder_name?priv->folder_name:"(cleared)",
+ priv->reason_to_live);
#endif
if (priv->reason_to_live == 0)
@@ -3784,8 +3769,11 @@
_tny_camel_folder_set_unread_count (folder, info->unread);
_tny_camel_folder_set_all_count (folder, info->total);
_tny_camel_folder_set_local_size (folder, info->local_size);
+
if (!info->name)
- g_warning ("Creating invalid folder\n");
+ g_critical ("Creating invalid folder. This indicates a problem "
+ "in the software\n");
+
_tny_camel_folder_set_name (folder, info->name);
_tny_camel_folder_set_iter (folder, info);
@@ -3816,8 +3804,9 @@
TnyFolderStoreChange *change;
CamelException subex = CAMEL_EXCEPTION_INITIALISER;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_STORE_ERROR, TNY_FOLDER_STORE_ERROR_CREATE_FOLDER))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_STORE_ERROR,
+ TNY_FOLDER_STORE_ERROR_CREATE_FOLDER))
return NULL;
if (!name || strlen (name) <= 0)
@@ -3955,11 +3944,11 @@
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
CamelFolderInfo *iter;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, err,
- TNY_FOLDER_STORE_ERROR, TNY_FOLDER_STORE_ERROR_GET_FOLDERS))
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv),
+ priv->account, err, TNY_FOLDER_STORE_ERROR,
+ TNY_FOLDER_STORE_ERROR_GET_FOLDERS))
return;
-
if (!priv->iter && priv->iter_parented)
{
CamelStore *store = priv->store;
@@ -4042,18 +4031,20 @@
/* thread reference */
_tny_camel_folder_unreason (priv);
- g_object_unref (G_OBJECT (info->self));
- g_object_unref (G_OBJECT (info->list));
+ g_object_unref (info->self);
+ g_object_unref (info->list);
if (info->err)
g_error_free (info->err);
_tny_session_stop_operation (info->session);
- g_mutex_lock (info->mutex);
- g_cond_broadcast (info->condition);
- info->had_callback = TRUE;
- g_mutex_unlock (info->mutex);
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
return;
}
@@ -4062,10 +4053,8 @@
tny_camel_folder_get_folders_async_callback (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, info->list, &info->err, info->user_data);
-
return FALSE;
}
@@ -4092,19 +4081,10 @@
info->condition = g_cond_new ();
info->had_callback = FALSE;
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_folder_get_folders_async_callback, info,
+ tny_camel_folder_get_folders_async_destroyer);
- if (info->callback)
- {
- execute_callback (info->depth, G_PRIORITY_DEFAULT,
- tny_camel_folder_get_folders_async_callback, info,
- tny_camel_folder_get_folders_async_destroyer);
- } else {
- /* thread reference */
- _tny_camel_folder_unreason (priv);
- g_object_unref (G_OBJECT (info->self));
- g_object_unref (G_OBJECT (info->list));
- }
-
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
if (!info->had_callback)
@@ -4123,21 +4103,19 @@
tny_camel_folder_get_folders_async_cancelled_destroyer (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
g_error_free (info->err);
g_object_unref (info->self);
g_object_unref (info->list);
g_slice_free (GetFoldersInfo, info);
+ return;
}
static gboolean
tny_camel_folder_get_folders_async_cancelled_callback (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, info->list, &info->err, info->user_data);
-
return FALSE;
}
@@ -4163,6 +4141,7 @@
info->user_data = user_data;
info->query = query;
info->depth = g_main_depth ();
+ info->condition = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), priv->account, &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
@@ -4219,7 +4198,7 @@
if (G_UNLIKELY (!priv->loaded))
if (!load_folder (priv))
return NULL;
-
+
retval = priv->folder;
if (retval)
camel_object_ref (CAMEL_OBJECT (retval));
@@ -4235,8 +4214,7 @@
return;
}
-typedef struct
-{
+typedef struct {
TnyFolder *self;
gint unread;
gint total;
@@ -4265,7 +4243,6 @@
if (do_something)
notify_folder_observers_about (self, change);
-
g_object_unref (change);
return FALSE;
@@ -4275,10 +4252,9 @@
tny_camel_folder_poke_status_destroyer (gpointer data)
{
PokeStatusInfo *info = (PokeStatusInfo *) data;
-
g_object_unref (info->self);
-
g_slice_free (PokeStatusInfo, info);
+ return;
}
@@ -4329,6 +4305,7 @@
if (folder)
g_object_unref (folder);
+
return NULL;
}
@@ -4353,12 +4330,9 @@
{
/* Thread reference */
g_object_ref (self);
-
_tny_camel_queue_launch (TNY_FOLDER_PRIV_GET_QUEUE (priv),
tny_camel_folder_poke_status_thread, self);
- info = NULL;
-
} else {
if (priv->iter) {
info = g_slice_new (PokeStatusInfo);
@@ -4369,14 +4343,12 @@
}
- if (info)
+ if (info)
{
info->self = TNY_FOLDER (g_object_ref (self));
-
execute_callback (g_main_depth (), G_PRIORITY_HIGH,
tny_camel_folder_poke_status_callback, info,
tny_camel_folder_poke_status_destroyer);
-
}
return;
@@ -4543,6 +4515,7 @@
/* iter->uri is a cache.
* Check for strlen(), because camel produces an empty (non-null)
* uri for POP. */
+
if (priv->iter && priv->iter->uri && (strlen (priv->iter->uri) > 0))
{
retval = g_strdup_printf ("%s", priv->iter->uri);
@@ -4558,13 +4531,12 @@
}
}
- if (!retval) { /* Strange, a local one?*/
+ if (!retval) { /* Strange, a local one? */
g_warning ("tny_folder_get_url_string does not have an "
"iter nor account. Using maildir as type.\n");
retval = g_strdup_printf ("maildir://%s", priv->folder_name);
}
- /* printf ("DEBUG: %s: retval='%s'\n", __FUNCTION__, retval); */
return retval;
}
@@ -4609,7 +4581,9 @@
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
#ifdef DEBUG
- g_print ("Finalizing TnyCamelFolder: %s\n", priv->folder_name?priv->folder_name:"(cleared)");
+ g_print ("Finalizing TnyCamelFolder: %s\n",
+ priv->folder_name?priv->folder_name:"(cleared)");
+
if (priv->reason_to_live != 0)
g_print ("Finalizing TnyCamelFolder, yet TnyHeader instances "
"are still alive: %d\n", priv->reason_to_live);
@@ -4618,12 +4592,13 @@
/* Commented because they should not be really needed but some
times they're causing locking problems. TODO: review the
source of this behaviour */
-/* g_static_rec_mutex_lock (priv->obs_lock); */
+
+ /* g_static_rec_mutex_lock (priv->obs_lock); */
if (priv->observers)
g_object_unref (G_OBJECT (priv->observers));
if (priv->sobservers)
g_object_unref (G_OBJECT (priv->sobservers));
-/* g_static_rec_mutex_unlock (priv->obs_lock); */
+ /* g_static_rec_mutex_unlock (priv->obs_lock); */
g_static_rec_mutex_lock (priv->folder_lock);
priv->dont_fkill = FALSE;
Index: libtinymail-camel/tny-camel-account-priv.h
===================================================================
--- libtinymail-camel/tny-camel-account-priv.h (revision 2535)
+++ libtinymail-camel/tny-camel-account-priv.h (working copy)
@@ -67,7 +67,7 @@
RefreshStatusInfo *csyncop;
GList *chooks;
TnyConnectionStatus status;
- gboolean is_connecting;
+ gboolean is_connecting, is_ready;
};
const CamelService* _tny_camel_account_get_service (TnyCamelAccount *self);
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c (revision 2535)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c (working copy)
@@ -1006,8 +1006,8 @@
CamelException *ex)
{
int len = strlen (type), i;
- char *resp;
-
+ char *resp = NULL;
+
len = strlen (type);
for (i = 0; i < response->untagged->len; i++) {
Index: libtinymail-camel/tny-camel-send-queue.c
===================================================================
--- libtinymail-camel/tny-camel-send-queue.c (revision 2535)
+++ libtinymail-camel/tny-camel-send-queue.c (working copy)
@@ -162,7 +162,7 @@
{
TnySendQueue *self = (TnySendQueue *) data;
TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
- TnyCamelAccountPriv *apriv = NULL;
+ /* TnyCamelAccountPriv *apriv = NULL; */
TnyFolder *sentbox, *outbox;
guint i = 0, length = 0;
TnyList *list;
@@ -172,9 +172,9 @@
priv->is_running = TRUE;
priv->creating_spin = FALSE;
- apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
+/* apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
if (apriv)
- tny_session_camel_join_connecting (apriv->session);
+ tny_session_camel_join_connecting (apriv->session); */
list = tny_simple_list_new ();
@@ -388,9 +388,8 @@
tny_camel_send_queue_join_worker (TnyCamelSendQueue *self)
{
TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
- TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->trans_account);
- if (!apriv->session->priv->conthread && priv->thread)
+ if (priv->thread)
g_thread_join (priv->thread);
}
Index: libtinymail-camel/tny-camel-store-account-priv.h
===================================================================
--- libtinymail-camel/tny-camel-store-account-priv.h (revision 2535)
+++ libtinymail-camel/tny-camel-store-account-priv.h (working copy)
@@ -20,8 +20,11 @@
* Boston, MA 02111-1307, USA.
*/
+#include <tny-session-camel.h>
#include <tny-camel-store-account.h>
+
#include "tny-camel-queue-priv.h"
+#include "tny-session-camel-priv.h"
typedef struct _TnyCamelStoreAccountPriv TnyCamelStoreAccountPriv;
@@ -40,5 +43,6 @@
(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_CAMEL_STORE_ACCOUNT, TnyCamelStoreAccountPriv))
void _tny_camel_store_account_emit_conchg_signal (TnyCamelStoreAccount *self);
+void _tny_camel_store_account_queue_going_online (TnyCamelStoreAccount *self, TnySessionCamel *session, gboolean online, go_online_callback_func err_func, gpointer user_data);
#endif
Index: libtinymail-camel/tny-session-camel-priv.h
===================================================================
--- libtinymail-camel/tny-session-camel-priv.h (revision 2535)
+++ libtinymail-camel/tny-session-camel-priv.h (working copy)
@@ -9,21 +9,25 @@
gpointer account_store;
gboolean interactive, prev_constat;
guint connchanged_signal;
- GList *current_accounts;
+
+ GHashTable *current_accounts;
+ GStaticRecMutex *current_accounts_lock;
+
gchar *camel_dir;
gboolean in_auth_function, is_connecting;
- gboolean async_connect;
TnyLockable *ui_lock;
- GMutex *conlock, *queue_lock;
- GThread *conthread;
+ GMutex *queue_lock;
+
gboolean stop_now, initialized;
- gboolean is_inuse, background_thread_running;
+ gboolean is_inuse;
GList *regged_queues;
};
-void _tny_session_camel_add_account_1 (TnySessionCamel *self, TnyCamelAccount *account);
-void _tny_session_camel_add_account_2 (TnySessionCamel *self, TnyCamelAccount *account);
-void _tny_session_camel_forget_account (TnySessionCamel *self, TnyCamelAccount *account);
+typedef void (*go_online_callback_func) (TnySessionCamel *self, TnyCamelAccount *account, GError *err, gpointer user_data);
+void _tny_session_camel_register_account (TnySessionCamel *self, TnyCamelAccount *account);
+void _tny_session_camel_activate_account (TnySessionCamel *self, TnyCamelAccount *account);
+void _tny_session_camel_unregister_account (TnySessionCamel *self, TnyCamelAccount *account);
+
void _tny_session_camel_reg_queue (TnySessionCamel *self, TnyCamelSendQueue *queue);
void _tny_session_camel_unreg_queue (TnySessionCamel *self, TnyCamelSendQueue *queue);
Index: libtinymail-camel/tny-session-camel.c
===================================================================
--- libtinymail-camel/tny-session-camel.c (revision 2535)
+++ libtinymail-camel/tny-session-camel.c (working copy)
@@ -63,6 +63,65 @@
static void tny_session_camel_forget_password (CamelSession *, CamelService *, const char *, const char *, CamelException *);
+
+
+/* Hey Rob, look here! This gets called when the password is needed. It can have
+ * been implemented by the app developer without any Gtk+ code. Sometimes,
+ * however, it will launch Gtk+ code. For example the first time the password
+ * is needed.
+ *
+ * This happens in a thread, so does the tny_session_camel_forget_password. The
+ * thread is always the queue thread of the account.
+ *
+ * This is number #1 */
+
+
+typedef struct
+{
+ TnySessionCamel *self;
+ TnyAccount *account;
+ gchar *prompt, *retval;
+ gboolean cancel;
+ TnyGetPassFunc func;
+
+ GCond* condition;
+ gboolean had_callback;
+ GMutex *mutex;
+
+} HadToWaitForPasswordInfo;
+
+
+static gboolean
+get_password_idle_func (gpointer user_data)
+{
+ HadToWaitForPasswordInfo *info = (HadToWaitForPasswordInfo *) user_data;
+ TnySessionCamel *self = info->self;
+ TnyAccount *account = info->account;
+ TnyGetPassFunc func = info->func;
+
+ tny_lockable_lock (self->priv->ui_lock);
+ info->retval = func (account, info->prompt, &info->cancel);
+ tny_lockable_unlock (self->priv->ui_lock);
+
+ return FALSE;
+}
+
+static void
+get_password_destroy_func (gpointer user_data)
+{
+ HadToWaitForPasswordInfo *info = (HadToWaitForPasswordInfo *) user_data;
+
+ g_object_unref (info->account);
+ camel_object_unref (info->self);
+
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+
+ return;
+}
+
static char *
tny_session_camel_get_password (CamelSession *session, CamelService *service, const char *domain,
const char *prompt, const char *item, guint32 flags, CamelException *ex)
@@ -71,12 +130,13 @@
TnyGetPassFunc func;
TnyAccount *account;
gboolean freeprmpt = FALSE, cancel = FALSE;
- gchar *retval = NULL, *prmpt = (gchar*)prompt;
+ gchar *retval = NULL, *prmpt = (gchar*) prompt;
TnyCamelAccountPriv *apriv = NULL;
account = service->data;
if (account)
{
+ HadToWaitForPasswordInfo *info = NULL;
func = tny_account_get_pass_func (account);
@@ -101,56 +161,118 @@
apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
apriv->in_auth = TRUE;
- tny_lockable_lock (self->priv->ui_lock);
- retval = func (account, prmpt, &cancel);
- tny_lockable_unlock (self->priv->ui_lock);
+ info = g_slice_new (HadToWaitForPasswordInfo);
+ info->mutex = g_mutex_new ();
+ info->condition = g_cond_new ();
+ info->had_callback = FALSE;
+
+ camel_object_ref (self);
+ info->self = self;
+ info->account = TNY_ACCOUNT (g_object_ref (account));
+ info->prompt = prmpt;
+ info->func = func;
+ info->cancel = FALSE;
+ info->retval = NULL;
+
+ g_idle_add_full (G_PRIORITY_DEFAULT,
+ get_password_idle_func, info,
+ get_password_destroy_func);
+
+ /* Wait on the queue for the mainloop callback to be finished */
+ g_mutex_lock (info->mutex);
+ if (!info->had_callback)
+ g_cond_wait (info->condition, info->mutex);
+ g_mutex_unlock (info->mutex);
+
+ g_mutex_free (info->mutex);
+ g_cond_free (info->condition);
+
+ cancel = info->cancel;
+ retval = info->retval;
+
+ g_slice_free (HadToWaitForPasswordInfo, info);
+
apriv->in_auth = FALSE;
if (freeprmpt)
g_free (prmpt);
}
- if (cancel || retval == NULL) {
-
+ if (cancel || retval == NULL)
+ {
GError *err = NULL;
-
_tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), FALSE, &err);
-
if (err)
g_error_free (err);
-
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("You cancelled when you had to enter a password"));
+ if (retval)
+ g_free (retval);
retval = NULL;
}
return retval;
}
-/**
- * tny_session_camel_set_ui_locker:
- * @self: a #TnySessionCamel instance
- * @ui_lock: a #TnyLockable instance
+
+/* Hey Rob, look here! This gets called when the password was wrong. It can
+ * but usually wont use Gtk+ code by the implementer of the function pointer.
+ * Usually the application developer will "forget" the password here. So that
+ * The next request for a password gives the user a password dialog box.
*
- * Set the user interface toolkit locker. The lock and unlock methods of this
- * locker should be implemented with the lock and unlock functionality of your
- * user interface toolkit.
+ * That request will happen by the tny_session_camel_get_password function. This
+ * happens in a thread, so does the tny_session_camel_get_password. The thread
+ * is always the queue thread of the account.
*
- * Good examples are gdk_threads_enter () and gdk_threads_leave () in gtk+.
- **/
-void
-tny_session_camel_set_ui_locker (TnySessionCamel *self, TnyLockable *ui_lock)
+ * This is number #2 */
+
+
+
+typedef struct
{
- TnySessionCamelPriv *priv = self->priv;
- if (priv->ui_lock)
- g_object_unref (G_OBJECT (priv->ui_lock));
- priv->ui_lock = TNY_LOCKABLE (g_object_ref (ui_lock));
- return;
+ TnySessionCamel *self;
+ TnyAccount *account;
+ TnyForgetPassFunc func;
+
+ GCond* condition;
+ gboolean had_callback;
+ GMutex *mutex;
+
+} HadToWaitForForgetInfo;
+
+
+static gboolean
+forget_password_idle_func (gpointer user_data)
+{
+ HadToWaitForForgetInfo *info = (HadToWaitForForgetInfo *) user_data;
+ TnySessionCamel *self = info->self;
+ TnyAccount *account = info->account;
+ TnyForgetPassFunc func = info->func;
+
+ tny_lockable_lock (self->priv->ui_lock);
+ func (account);
+ tny_lockable_unlock (self->priv->ui_lock);
+
+ return FALSE;
}
+static void
+forget_password_destroy_func (gpointer user_data)
+{
+ HadToWaitForForgetInfo *info = (HadToWaitForForgetInfo *) user_data;
+ g_object_unref (info->account);
+ camel_object_unref (info->self);
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+
+ return;
+}
+
static void
tny_session_camel_forget_password (CamelSession *session, CamelService *service, const char *domain, const char *item, CamelException *ex)
{
@@ -162,33 +284,151 @@
if (account)
{
+ HadToWaitForForgetInfo *info = NULL;
+
func = tny_account_get_forget_pass_func (account);
if (!func)
return;
- tny_lockable_lock (self->priv->ui_lock);
- func (account);
- tny_lockable_unlock (self->priv->ui_lock);
+ info = g_slice_new (HadToWaitForForgetInfo);
+
+ info->mutex = g_mutex_new ();
+ info->condition = g_cond_new ();
+ info->had_callback = FALSE;
+
+ camel_object_ref (self);
+ info->self = self;
+ info->account = TNY_ACCOUNT (g_object_ref (account));
+ info->func = func;
+
+ g_idle_add_full (G_PRIORITY_DEFAULT,
+ forget_password_idle_func, info,
+ forget_password_destroy_func);
+
+ /* Wait on the queue for the mainloop callback to be finished */
+ g_mutex_lock (info->mutex);
+ if (!info->had_callback)
+ g_cond_wait (info->condition, info->mutex);
+ g_mutex_unlock (info->mutex);
+
+ g_mutex_free (info->mutex);
+ g_cond_free (info->condition);
+
+ g_slice_free (HadToWaitForForgetInfo, info);
+
}
return;
}
+/* This is a wrapper for the alerting. Called by on_account_connect_done and
+ * tny_session_camel_alert_user (see below for both) */
+
+typedef struct
+{
+ TnySessionCamel *self;
+ TnyAccount *account;
+ TnyAlertType tnytype;
+ gboolean question, retval;
+ GError *err;
+
+ GCond* condition;
+ gboolean had_callback;
+ GMutex *mutex;
+
+} HadToWaitForAlertInfo;
+
+
static gboolean
-tny_session_camel_do_an_error (TnySessionCamel *self, TnyAccount *account, TnyAlertType tnytype, gboolean question, GError *err)
+alert_idle_func (gpointer user_data)
{
- return tny_account_store_alert (
+ HadToWaitForAlertInfo *info = user_data;
+ TnySessionCamel *self = info->self;
+ TnyAccount *account = info->account;
+
+ tny_lockable_lock (self->priv->ui_lock);
+
+ info->retval = tny_account_store_alert (
(TnyAccountStore*) self->priv->account_store,
- account, tnytype, question, (const GError *) err);
+ account, info->tnytype, info->question,
+ (const GError *) info->err);
+
+ tny_lockable_unlock (self->priv->ui_lock);
+
+ return FALSE;
}
+static void
+alert_destroy_func (gpointer user_data)
+{
+ HadToWaitForAlertInfo *info = (HadToWaitForAlertInfo *) user_data;
+
+ if (info->account)
+ g_object_unref (info->account);
+ camel_object_unref (info->self);
+
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+
+ return;
+}
+
+static gboolean
+tny_session_camel_do_an_error (TnySessionCamel *self, TnyAccount *account, TnyAlertType tnytype, gboolean question, GError *err)
+{
+ HadToWaitForAlertInfo *info = NULL;
+ gboolean retval = FALSE;
+
+ info = g_slice_new (HadToWaitForAlertInfo);
+
+ info->mutex = g_mutex_new ();
+ info->condition = g_cond_new ();
+ info->had_callback = FALSE;
+
+ camel_object_ref (self);
+ info->self = self;
+ info->account = account?TNY_ACCOUNT (g_object_ref (account)):NULL;
+ info->tnytype = tnytype;
+ info->question = question;
+ info->err = err;
+ info->retval = FALSE;
+
+ g_idle_add_full (G_PRIORITY_DEFAULT,
+ alert_idle_func, info,
+ alert_destroy_func);
+
+ /* Wait on the queue for the mainloop callback to be finished */
+ g_mutex_lock (info->mutex);
+ if (!info->had_callback)
+ g_cond_wait (info->condition, info->mutex);
+ g_mutex_unlock (info->mutex);
+
+ g_mutex_free (info->mutex);
+ g_cond_free (info->condition);
+
+ retval = info->retval;
+
+ g_slice_free (HadToWaitForAlertInfo, info);
+
+ return retval;
+}
+
/* tny_session_camel_alert_user will for example be called by camel when SSL is on and
- camel_session_get_service is issued (for example TnyCamelTransportAccount and
- TnyCamelStore account issue this function). Its implementation is often done
- with GUI components (it should therefore not be called from a thread). This
- is a known issue (and if someone fixes this, please remove this warning) */
+ * camel_session_get_service is issued (for example TnyCamelTransportAccount and
+ * TnyCamelStore account issue this function). Its implementation is often done
+ * with GUI components (it should therefore not be called from a thread). */
+/* Hey Rob, look here! This is an alert that will be launched from a thread.
+ * usually the queue thread of the account (I think always, but I have to verify
+ * this before making a statement out of it). The user sometimes has to answer
+ * this question. For example with a Yes or a No. The typical example is the
+ * SSL question and error reporting when the connection is lost)
+ *
+ * This is number #3 */
+
static gboolean
tny_session_camel_alert_user (CamelSession *session, CamelSessionAlertType type, CamelException *ex, gboolean cancel, CamelService *service)
{
@@ -196,8 +436,8 @@
TnySessionCamelPriv *priv = self->priv;
gboolean retval = FALSE;
GError *err = NULL;
+ TnyAccount *account = NULL;
- TnyAccount *account = NULL;
if (service && service->data)
account = TNY_ACCOUNT (service->data);
@@ -221,27 +461,47 @@
if (ex->id == CAMEL_EXCEPTION_USER_CANCEL)
g_set_error (&err, TNY_ACCOUNT_STORE_ERROR,
- TNY_ACCOUNT_STORE_ERROR_CANCEL_ALERT, "The connecting was canceled");
- else {
+ TNY_ACCOUNT_STORE_ERROR_CANCEL_ALERT,
+ "The connecting was canceled");
+ else
g_set_error (&err, TNY_ACCOUNT_STORE_ERROR,
_tny_camel_account_get_tny_error_code_for_camel_exception_id (ex),
camel_exception_get_description (ex));
- }
- tny_lockable_lock (self->priv->ui_lock);
+ retval = tny_session_camel_do_an_error (self, account, tnytype,
+ TRUE, err);
- TnyAccount *account = NULL; /* TODO. */
- retval = tny_session_camel_do_an_error (self, account, tnytype, TRUE, err);
-
- tny_lockable_unlock (self->priv->ui_lock);
-
- g_error_free (err);
+ if (err)
+ g_error_free (err);
}
return retval;
}
+
+/**
+ * tny_session_camel_set_ui_locker:
+ * @self: a #TnySessionCamel instance
+ * @ui_lock: a #TnyLockable instance
+ *
+ * Set the user interface toolkit locker. The lock and unlock methods of this
+ * locker should be implemented with the lock and unlock functionality of your
+ * user interface toolkit.
+ *
+ * Good examples are gdk_threads_enter () and gdk_threads_leave () in gtk+.
+ **/
+void
+tny_session_camel_set_ui_locker (TnySessionCamel *self, TnyLockable *ui_lock)
+{
+ TnySessionCamelPriv *priv = self->priv;
+ if (priv->ui_lock)
+ g_object_unref (G_OBJECT (priv->ui_lock));
+ priv->ui_lock = TNY_LOCKABLE (g_object_ref (ui_lock));
+ return;
+}
+
+
CamelFolder *
mail_tool_uri_to_folder (CamelSession *session, const char *uri, guint32 flags, CamelException *ex)
{
@@ -359,20 +619,6 @@
return;
}
-/**
- * tny_session_camel_set_async_connecting:
- * @self: a #TnySessionCamel object
- * @enable: Whether or not to asynchronously connect
- *
- * Set connection strategy
- **/
-void
-tny_session_camel_set_async_connecting (TnySessionCamel *self, gboolean enable)
-{
- g_mutex_lock (self->priv->conlock);
- self->priv->async_connect = enable;
- g_mutex_unlock (self->priv->conlock);
-}
static void
@@ -385,12 +631,18 @@
priv->initialized = FALSE;
priv->stop_now = FALSE;
priv->regged_queues = NULL;
- priv->background_thread_running = FALSE;
priv->is_inuse = FALSE;
- priv->conlock = g_mutex_new ();
priv->queue_lock = g_mutex_new ();
- priv->conthread = NULL;
- priv->current_accounts = NULL;
+
+ /* I know it would be better to have a hashtable that does reference
+ * counting. But then you'll get embraced references, which gobject
+ * can't really handle (unless doing it with a weak reference) */
+
+ priv->current_accounts = g_hash_table_new_full (g_str_hash, g_direct_equal,
+ g_free, NULL);
+
+ priv->current_accounts_lock = g_new0 (GStaticRecMutex, 1);
+ g_static_rec_mutex_init (priv->current_accounts_lock);
priv->prev_constat = FALSE;
priv->device = NULL;
priv->camel_dir = NULL;
@@ -398,198 +650,117 @@
priv->camel_dir = NULL;
priv->in_auth_function = FALSE;
priv->is_connecting = FALSE;
- priv->async_connect = TRUE;
return;
}
-typedef struct
-{
- TnyDevice *device;
- gboolean online, as_thread;
- gpointer user_data;
- TnySessionCamelPriv *priv;
-} BackgroundConnectInfo;
-static gboolean
-background_connect_idle (gpointer data)
+/* Happens at tny_camel_account_set_session. This does very few things, actually.
+ * Maybe we can factor this away and make the tny_camel_account_set_session not
+ * required anymore? Though, the account will always need to know what the session
+ * is. So we'd have to find another way to let the account know about this ... */
+
+void
+_tny_session_camel_register_account (TnySessionCamel *self, TnyCamelAccount *account)
{
- BackgroundConnectInfo *info = data;
- TnySessionCamel *self = info->user_data;
+ TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
TnySessionCamelPriv *priv = self->priv;
- if (priv->account_store)
- {
- g_signal_emit (priv->account_store,
- tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0);
- g_signal_emit (priv->account_store,
- tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_FINISHED], 0);
- }
+ if (apriv->cache_location)
+ g_free (apriv->cache_location);
+ apriv->cache_location = g_strdup (priv->camel_dir);
- return FALSE;
-}
-
-
-
-static void
-background_connect_destroy (gpointer data)
-{
- BackgroundConnectInfo *info = data;
-
- g_object_unref (G_OBJECT (info->device));
- g_slice_free (BackgroundConnectInfo, data);
-
return;
}
-
-
static void
-foreach_account_set_connectivity (gpointer data, gpointer udata)
+on_account_connect_done (TnySessionCamel *self, TnyCamelAccount *account, GError *err, gpointer user_data)
{
- BackgroundConnectInfo *info = udata;
- TnySessionCamel *self = info->user_data;
-
- if (data && TNY_IS_CAMEL_ACCOUNT (data))
- {
- TnyCamelAccount *account = TNY_CAMEL_ACCOUNT (data);
-
- GError *err = NULL;
- TnyCamelAccountPriv *apriv = NULL;
+ TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
- /* We don't go online on transport accounts, yet */
- if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (account))
- {
- g_signal_emit (account,
- tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, info->online);
- return;
- }
+ /* This one happens when a account is finished with connecting. On
+ * failure, err is not NULL on success it is NULL. This happens in a
+ * thread: the queue thread of @account. */
- apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
+ /* Hey Rob, look here! This will happen when you have an error. This
+ * "do_an_error" thing will invoke the alert_func from a thread. */
- apriv->is_connecting = TRUE;
- _tny_camel_account_try_connect (account, FALSE /* info->online */, &err);
+ /* We set the account to ready, so that tny_account_is_ready returns TRUE
+ * from now on. _tny_session_camel_activate_account caused this callback
+ * to happen (either successful or non-successful, this happens for each
+ * account that is internally ready) */
- if (err == NULL)
- _tny_camel_account_set_online (account, info->online, &err);
+ apriv->is_ready = TRUE;
- if (err != NULL)
- {
- if (self->priv->account_store)
- {
- if (info->as_thread)
- tny_lockable_lock (self->priv->ui_lock);
+ if (err)
+ tny_session_camel_do_an_error (self, TNY_ACCOUNT (account),
+ TNY_ALERT_TYPE_ERROR, FALSE, err);
- tny_session_camel_do_an_error (self, TNY_ACCOUNT (account), TNY_ALERT_TYPE_ERROR, FALSE, err);
-
- if (info->as_thread)
- tny_lockable_unlock (self->priv->ui_lock);
- }
- g_error_free (err);
- }
-
- apriv->is_connecting = FALSE;
-
- }
+ return;
}
-typedef struct {
- BackgroundConnectInfo *info;
- TnyCamelAccount *account;
-} AccGoOnlineInfo;
-static gpointer
-account_go_online (gpointer data)
+static void
+tny_session_queue_going_online_for_account (TnySessionCamel *self, TnyCamelAccount *account, gboolean online)
{
- AccGoOnlineInfo *ainfo = (AccGoOnlineInfo *) data;
- TnySessionCamel *self = ainfo->info->user_data;
- TnySessionCamelPriv *priv = self->priv;
- priv->is_connecting = TRUE;
+ /* So this is that wrapper that I talked about (see below). In case we
+ * are a store account, this means that we need to throw the request to
+ * go online to the account's queue. This is implemented in a protected
+ * method in TnyCamelStoreAccount. Go take a look! */
- foreach_account_set_connectivity (ainfo->account, ainfo->info);
+ if (TNY_IS_CAMEL_STORE_ACCOUNT (account))
+ _tny_camel_store_account_queue_going_online (
+ TNY_CAMEL_STORE_ACCOUNT (account), self, online,
+ on_account_connect_done, NULL);
- priv->is_connecting = FALSE;
+ /* Else, if it's a transport account, we don't have any transport
+ * account implementations that actually need to go online at this
+ * moment yet. At the moment of transferring the first message, the
+ * current implementations will automatically connect themselves. */
- camel_object_unref (ainfo->info->user_data);
- g_object_unref (ainfo->account);
-
- g_idle_add_full (G_PRIORITY_HIGH,
- background_connect_idle,
- ainfo->info, background_connect_destroy);
-
- g_slice_free (AccGoOnlineInfo, ainfo);
- /* ainfo->info is freed in the background_connect_destroy */
-
- priv->conthread = NULL;
-
- g_thread_exit (NULL);
- return NULL;
+ if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (account))
+ {
+ g_signal_emit (account,
+ tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, online);
+ return;
+ }
}
+/* This happens when the password function of the account is set. It will after
+ * registering the account for future connection-changes, already set the online
+ * state of it to the current connectivity setting of the device */
-void
-_tny_session_camel_add_account_1 (TnySessionCamel *self, TnyCamelAccount *account)
-{
- TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
- TnySessionCamelPriv *priv = self->priv;
-
- if (apriv->cache_location)
- g_free (apriv->cache_location);
- apriv->cache_location = g_strdup (priv->camel_dir);
- priv->current_accounts = g_list_prepend (priv->current_accounts, account);
-}
-
void
-_tny_session_camel_add_account_2 (TnySessionCamel *self, TnyCamelAccount *account)
+_tny_session_camel_activate_account (TnySessionCamel *self, TnyCamelAccount *account)
{
- TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
TnySessionCamelPriv *priv = self->priv;
- gboolean doit = FALSE;
- if (priv->initialized)
- {
- g_mutex_lock (priv->conlock);
- doit = (priv->conthread == NULL);
- g_mutex_unlock (priv->conlock);
- }
+ g_static_rec_mutex_lock (priv->current_accounts_lock);
- if (priv->initialized && !priv->background_thread_running && doit)
- {
- if (priv->device && TNY_IS_DEVICE (priv->device))
- {
- AccGoOnlineInfo *ainfo = g_slice_new (AccGoOnlineInfo);
- ainfo->info = g_slice_new (BackgroundConnectInfo);
+ /* It would indeed be better to add a reference here. But then you'll
+ * get embraced references at some point. We'll get rid of the instance
+ * in the hashtable before the finalization of it, take a look at the
+ * unregister stuff below. */
- ainfo->info->online = tny_device_is_online (priv->device);
- ainfo->info->as_thread = TRUE;
- ainfo->info->priv = priv;
+ g_hash_table_insert (priv->current_accounts,
+ g_strdup (tny_account_get_id (TNY_ACCOUNT (account))),
+ account);
+ g_static_rec_mutex_unlock (priv->current_accounts_lock);
- ainfo->info->device = g_object_ref (priv->device);
- camel_object_ref (self);
- ainfo->info->user_data = self;
- ainfo->account = TNY_CAMEL_ACCOUNT (g_object_ref (account));
+ tny_session_queue_going_online_for_account (self, account,
+ tny_device_is_online (priv->device));
- camel_session_set_online ((CamelSession *) self, TRUE);
+ return;
+}
- if (priv->account_store)
- {
- g_signal_emit (priv->account_store,
- tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_STARTED], 0);
- }
- g_mutex_lock (priv->conlock);
- if (priv->conthread)
- g_thread_join (priv->conthread);
- priv->conthread = g_thread_create (account_go_online, ainfo, TRUE, NULL);
- g_mutex_unlock (priv->conlock);
- }
- }
-}
+/* This happens when an account gets finalized. We more or less simply get rid
+ * of the instance in the hashtable. */
void
-_tny_session_camel_forget_account (TnySessionCamel *self, TnyCamelAccount *account)
+_tny_session_camel_unregister_account (TnySessionCamel *self, TnyCamelAccount *account)
{
TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (account);
TnySessionCamelPriv *priv = self->priv;
@@ -598,147 +769,100 @@
g_free (apriv->cache_location);
apriv->cache_location = NULL;
- priv->current_accounts = g_list_remove (priv->current_accounts, account);
+ g_static_rec_mutex_lock (priv->current_accounts_lock);
+ g_hash_table_remove (priv->current_accounts,
+ tny_account_get_id (TNY_ACCOUNT (account)));
+ g_static_rec_mutex_unlock (priv->current_accounts_lock);
return;
}
+typedef struct {
+ TnySessionCamel *self;
+ gboolean online;
+} ConChangedForEachInfo;
-
-
-static gpointer
-background_connect_thread (gpointer data)
+static void
+tny_session_camel_connection_changed_for_each (gpointer key, gpointer value, gpointer user_data)
{
- BackgroundConnectInfo *info = data;
- TnySessionCamel *self = info->user_data;
- TnySessionCamelPriv *priv = self->priv;
+ ConChangedForEachInfo *info = (ConChangedForEachInfo *) user_data;
- if (priv->background_thread_running) {
- g_thread_exit (NULL);
- return NULL;
- }
+ /* For each registered account, we'll set its online state. Throwing it
+ * in its queue is implemented in the TnyCamelStoreAccount btw. For now,
+ * because it's shared with the account registration, this is a wrapper */
- priv->background_thread_running = TRUE;
+ tny_session_queue_going_online_for_account (info->self,
+ TNY_CAMEL_ACCOUNT (value), info->online);
- if (priv->stop_now)
- goto stop_now;
-
- priv->is_connecting = TRUE;
-
- if (priv->current_accounts && priv->prev_constat != info->online && priv->account_store)
- {
- GList *copy = priv->current_accounts;
- while (copy)
- {
- if (priv->stop_now)
- goto stop_now;
- foreach_account_set_connectivity (copy->data, info);
- if (priv->stop_now)
- goto stop_now;
- copy = g_list_next (copy);
- }
- }
-
-stop_now:
-
- priv->is_connecting = FALSE;
-
- g_idle_add_full (G_PRIORITY_HIGH,
- background_connect_idle,
- info, background_connect_destroy);
-
- priv->prev_constat = info->online;
-
- priv->conthread = NULL;
- priv->background_thread_running = FALSE;
-
- priv->stop_now = FALSE;
-
- g_thread_exit (NULL);
- return NULL;
+ return;
}
-static gboolean
-do_background_connect_thread (gpointer data)
-{
- BackgroundConnectInfo *info = data;
- TnySessionCamel *self = info->user_data;
- TnySessionCamelPriv *priv = self->priv;
+/* In case our TnyDevice's connection_changed event happened. We'll set all
+ * registered accounts to the proper online state here. Because these accounts
+ * all register their connecting on their own queue, it's not detectable when
+ * connecting got finished. They also all start doing their connecting stuff
+ * in parallel. Quite difficult to know when all are finished with that.
+ *
+ * In stead we provide components, like the TnyGtkFolderStoreTreeModel, that can
+ * cope with connection changes. For example: they'll load-in new folders as
+ * soon as it's known that the account went online. No more accounts-reloaded
+ * things as it's far more fine grained this way ... */
- /* g_mutex_lock (info->priv->conlock); */
- info->priv->conthread = g_thread_create (background_connect_thread, data, TRUE, NULL);
- /* g_mutex_unlock (info->priv->conlock); */
-
- return FALSE;
-}
-
static void
tny_session_camel_connection_changed (TnyDevice *device, gboolean online, gpointer user_data)
{
TnySessionCamel *self = user_data;
TnySessionCamelPriv *priv = self->priv;
- BackgroundConnectInfo *info;
- gboolean inf;
+ ConChangedForEachInfo *info = NULL;
- inf = priv->in_auth_function;
- if (inf) return;
- info = g_slice_new (BackgroundConnectInfo);
+ /* Maybe we can remove this check after Rob is finished with throwing
+ * the questions in the GMainLoop. I'm leaving it here for now ... */
- info->device = g_object_ref (G_OBJECT (device));
+ if (priv->in_auth_function)
+ return;
+
+ info = g_slice_new (ConChangedForEachInfo);
+
info->online = online;
- info->user_data = user_data;
- info->priv = priv;
+ info->self = self;
+
+ /* This Camel API exists, I haven't yet figured out what exactly it does
+ * or change in terms of behaviour. */
+
camel_session_set_online ((CamelSession *) self, online);
+
+ /* As said, we can issue this signal. We can't issue when connecting
+ * actually finished: that's because all accounts register getting
+ * connected on their own queues. So it'll all happen in parallel and
+ * a little bit less in control as when we would dedicate a thread to it,
+ * and in a serialized way get all accounts connected (the old way) */
+
if (priv->account_store)
- {
g_signal_emit (priv->account_store,
tny_account_store_signals [TNY_ACCOUNT_STORE_CONNECTING_STARTED], 0);
- }
+ g_static_rec_mutex_lock (priv->current_accounts_lock);
+ /* So let's look above, at that for_each function ... */
+ g_hash_table_foreach (priv->current_accounts,
+ tny_session_camel_connection_changed_for_each, info);
+ g_static_rec_mutex_unlock (priv->current_accounts_lock);
- if (priv->async_connect)
- {
- gboolean doit = FALSE;
+ g_slice_free (ConChangedForEachInfo, info);
- info->as_thread = TRUE;
-
- if (!priv->conthread)
- do_background_connect_thread (info);
-
- } else {
- info->as_thread = FALSE;
- background_connect_thread (info);
- }
-
return;
}
-/**
- * tny_session_camel_join_connecting
- * @self: a #TnySessionCamel object
- *
- * Join the connection thread
- **/
-void
-tny_session_camel_join_connecting (TnySessionCamel *self)
-{
- TnySessionCamelPriv *priv = self->priv;
- g_mutex_lock (priv->conlock);
- if (priv->conthread)
- g_thread_join (priv->conthread);
- g_mutex_unlock (priv->conlock);
-}
-
/**
* tny_session_camel_set_initialized:
* @self: the #TnySessionCamel instance
*
- * This method must be called one the initial accounts are created in your
- * #TnyAccountStore implementation.
+ * This method must be called once the initial accounts are created in your
+ * #TnyAccountStore implementation and should indicate that the initialization
+ * of your initial accounts is completed.
**/
void
tny_session_camel_set_initialized (TnySessionCamel *self)
@@ -788,6 +912,9 @@
priv->connchanged_signal);
}
+ /* TNY TODO: proper reference counting here please! Note that we can't
+ * have embraced references either. So be careful! */
+
priv->device = device;
return;
@@ -882,6 +1009,10 @@
TnySessionCamel *self = (TnySessionCamel*)object;
TnySessionCamelPriv *priv = self->priv;
+ g_static_rec_mutex_lock (priv->current_accounts_lock);
+ g_hash_table_destroy (priv->current_accounts);
+ g_static_rec_mutex_unlock (priv->current_accounts_lock);
+
g_mutex_lock (priv->queue_lock);
g_list_free (priv->regged_queues);
priv->regged_queues = NULL;
@@ -899,8 +1030,8 @@
if (priv->camel_dir)
g_free (priv->camel_dir);
- g_mutex_free (priv->conlock);
g_mutex_free (priv->queue_lock);
+ g_static_rec_mutex_free (priv->current_accounts_lock);
g_slice_free (TnySessionCamelPriv, self->priv);
@@ -922,7 +1053,6 @@
camel_session_class->thread_msg_free = tny_session_camel_ms_thread_msg_free;
camel_session_class->thread_status = tny_session_camel_ms_thread_status;
-
return;
}
Index: libtinymail-camel/tny-camel-queue.c
===================================================================
--- libtinymail-camel/tny-camel-queue.c (revision 2535)
+++ libtinymail-camel/tny-camel-queue.c (working copy)
@@ -102,7 +102,7 @@
g_mutex_lock (queue->lock);
if (first)
queue->list = g_list_delete_link (queue->list, first);
-
+
if (g_list_length (queue->list) == 0) {
queue->thread = NULL;
queue->stopped = TRUE;
@@ -114,7 +114,7 @@
if (item)
g_slice_free (QueueItem, item);
}
-
+
queue->thread = NULL;
queue->stopped = TRUE;
g_object_unref (queue);
@@ -136,13 +136,19 @@
g_mutex_lock (queue->lock);
queue->list = g_list_append (queue->list, item);
- g_mutex_unlock (queue->lock);
- if (!queue->thread) {
+ if (queue->stopped) {
+ GError *err = NULL;
queue->stopped = FALSE;
+ g_object_ref (queue);
queue->thread = g_thread_create (thread_main_func,
- g_object_ref (queue), TRUE, NULL);
+ queue, TRUE, &err);
+ if (err) {
+ queue->stopped = TRUE;
+ }
}
+ g_mutex_unlock (queue->lock);
+
}
static void
@@ -164,7 +170,7 @@
{
TnyCamelQueue *self = (TnyCamelQueue*)instance;
- self->stopped = FALSE;
+ self->stopped = TRUE;
self->list = NULL;
self->thread = NULL;
self->lock = g_mutex_new ();
Index: libtinymail-camel/tny-camel-store-account.c
===================================================================
--- libtinymail-camel/tny-camel-store-account.c (revision 2535)
+++ libtinymail-camel/tny-camel-store-account.c (working copy)
@@ -83,10 +83,10 @@
{
TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
tny_folder_store_observer_update (observer, change);
- g_object_unref (G_OBJECT (observer));
+ g_object_unref (observer);
tny_iterator_next (iter);
}
- g_object_unref (G_OBJECT (iter));
+ g_object_unref (iter);
}
static gboolean
@@ -97,7 +97,7 @@
g_signal_emit (G_OBJECT (self),
tny_account_signals [TNY_ACCOUNT_CONNECTION_STATUS_CHANGED],
- 0, apriv->status);
+ 0, apriv->status);
return FALSE;
}
@@ -276,6 +276,7 @@
_tny_camel_store_account_emit_conchg_signal (TnyCamelStoreAccount *self)
{
/* tny_camel_store_account_do_emit (self); */
+ return;
}
static void
@@ -410,10 +411,7 @@
"Unknown error while connecting");
}
} else {
-
tny_camel_store_account_do_emit (TNY_CAMEL_STORE_ACCOUNT (self));
-
- /* tny_camel_account_set_online (self, apriv->connected); */
}
g_static_rec_mutex_unlock (apriv->service_lock);
@@ -587,8 +585,6 @@
g_object_unref (priv->queue);
g_object_unref (priv->msg_queue);
- /* Disco store ? */
-
(*parent_class->finalize) (object);
return;
@@ -613,8 +609,6 @@
g_assert (TNY_IS_CAMEL_FOLDER (folder));
- /* TNY TODO: Support non-TnyCamelFolder TnyFolder implementations too */
-
store = CAMEL_STORE (apriv->service);
if (camel_exception_is_set (&ex))
@@ -639,7 +633,6 @@
{
g_warning ("Trying to remove an invalid folder\n");
g_static_rec_mutex_unlock (aspriv->factory_lock);
-
return;
}
@@ -792,10 +785,8 @@
if (nerr != NULL)
g_propagate_error (err, nerr);
-
_tny_session_stop_operation (apriv->session);
-
return;
}
@@ -946,8 +937,6 @@
TnyFolder *fnd = (TnyFolder*) copy->data;
const gchar *name = tny_folder_get_id (fnd);
- /* printf ("COMPARE: [%s] [%s]\n", name, full_name); */
-
if (name && full_name && !strcmp (name, full_name))
{
folder = TNY_CAMEL_FOLDER (g_object_ref (G_OBJECT (fnd)));
@@ -961,8 +950,6 @@
folder = TNY_CAMEL_FOLDER (_tny_camel_folder_new ());
priv->managed_folders = g_list_prepend (priv->managed_folders, folder);
- /* printf ("CREATE: %s\n", full_name); */
-
*was_new = TRUE;
}
@@ -1108,8 +1095,8 @@
GetFoldersInfo *info = thr_user_data;
/* gidle reference */
- g_object_unref (G_OBJECT (info->self));
- g_object_unref (G_OBJECT (info->list));
+ g_object_unref (info->self);
+ g_object_unref (info->list);
if (info->err)
g_error_free (info->err);
@@ -1128,13 +1115,34 @@
tny_camel_store_account_get_folders_async_callback (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, info->list,&info->err, info->user_data);
-
return FALSE;
}
+
+/**
+ * When using a #GMainLoop this method will execute a callback using
+ * g_idle_add_full. Note that without a #GMainLoop, the callbacks
+ * could happen in a worker thread (depends on who call it) at an
+ * unknown moment in time (check your locking in this case).
+ */
+static void
+execute_callback (gint depth,
+ gint priority,
+ GSourceFunc idle_func,
+ gpointer data,
+ GDestroyNotify destroy_func)
+{
+ if (depth > 0){
+ g_idle_add_full (priority, idle_func, data, destroy_func);
+ } else {
+ idle_func (data);
+ destroy_func (data);
+ }
+}
+
+
static gpointer
tny_camel_store_account_get_folders_async_thread (gpointer thr_user_data)
{
@@ -1156,21 +1164,9 @@
info->condition = g_cond_new ();
info->had_callback = FALSE;
- if (info->callback)
- {
- if (info->depth > 0)
- {
- g_idle_add_full (G_PRIORITY_HIGH,
- tny_camel_store_account_get_folders_async_callback,
- info, tny_camel_store_account_get_folders_async_destroyer);
- } else {
- tny_camel_store_account_get_folders_async_callback (info);
- tny_camel_store_account_get_folders_async_destroyer (info);
- }
- } else {
- g_object_unref (G_OBJECT (info->self));
- g_object_unref (G_OBJECT (info->list));
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_store_account_get_folders_async_callback, info,
+ tny_camel_store_account_get_folders_async_destroyer);
/* Wait on the queue for the mainloop callback to be finished */
g_mutex_lock (info->mutex);
@@ -1190,22 +1186,20 @@
tny_camel_store_account_get_folders_async_cancelled_destroyer (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
/* gidle references */
g_object_unref (info->self);
g_object_unref (info->list);
g_error_free (info->err);
g_slice_free (GetFoldersInfo, info);
+ return;
}
static gboolean
tny_camel_store_account_get_folders_async_cancelled_callback (gpointer thr_user_data)
{
GetFoldersInfo *info = thr_user_data;
-
if (info->callback)
info->callback (info->self, info->list, &info->err, info->user_data);
-
return FALSE;
}
@@ -1244,24 +1238,19 @@
g_object_ref (info->self);
g_object_ref (info->list);
- if (info->depth > 0){
- g_idle_add_full (G_PRIORITY_DEFAULT,
- tny_camel_store_account_get_folders_async_cancelled_callback, info,
- tny_camel_store_account_get_folders_async_cancelled_destroyer);
- } else {
- tny_camel_store_account_get_folders_async_cancelled_callback (info);
- tny_camel_store_account_get_folders_async_cancelled_destroyer (info);
- }
+ execute_callback (info->depth, G_PRIORITY_DEFAULT,
+ tny_camel_store_account_get_folders_async_cancelled_callback, info,
+ tny_camel_store_account_get_folders_async_cancelled_destroyer);
}
g_error_free (err);
return;
}
/* thread reference */
- g_object_ref (G_OBJECT (info->self));
- g_object_ref (G_OBJECT (info->list));
+ g_object_ref (info->self);
+ g_object_ref (info->list);
if (info->query)
- g_object_ref (G_OBJECT (info->query));
+ g_object_ref (info->query);
_tny_camel_queue_launch (priv->queue,
tny_camel_store_account_get_folders_async_thread, info);
@@ -1441,8 +1430,6 @@
if (strcasestr (url_string, "maildir"))
{
- // maildir:/home/xxx/.modest/local_folders#New%20folder/1183044323.16675_6.mindcrime_2_S_2_S
-
str = strchr (url_string, '#');
if (str && strlen (str) > 1)
{
@@ -1546,6 +1533,108 @@
return retval;
}
+
+
+typedef struct {
+ TnySessionCamel *session;
+ TnyCamelStoreAccount *self;
+ gboolean online;
+ go_online_callback_func done_func;
+ gpointer user_data;
+} GoingOnlineInfo;
+
+static gpointer
+tny_camel_store_account_queue_going_online_thread (gpointer thr_user_data)
+{
+ GoingOnlineInfo *info = (GoingOnlineInfo*) thr_user_data;
+ TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (info->self);
+ GError *err = NULL;
+
+ /* So this happens in the queue thread. There's only one such thread
+ * for each TnyCamelStoreAccount active at any given moment in time.
+ * This means that operations on the queue, while this is happening,
+ * must wait. */
+
+ /* The info->done_func points to on_account_connect_done in the
+ * TnySessionCamel implementation. Or to the set_online_done handler.
+ * Go take a look! */
+
+ apriv->is_connecting = TRUE;
+
+ /* This is one of those functions that our hero, Rob, is going to
+ * refactor/rename to something that does make sense :-). Isn't that
+ * true Rob? */
+
+ _tny_camel_account_try_connect (TNY_CAMEL_ACCOUNT (info->self),
+ FALSE, &err);
+
+ if (err) {
+ info->done_func (info->session, TNY_CAMEL_ACCOUNT (info->self), err, info->user_data);
+ g_error_free (err);
+ } else {
+
+ /* This one actually sets the account to online. Although Rob
+ * is probably going to improve all this. Right *poke*? */
+
+ _tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->self),
+ info->online, &err);
+
+ if (err) {
+ info->done_func (info->session,
+ TNY_CAMEL_ACCOUNT (info->self), err, info->user_data);
+ g_error_free (err);
+ } else
+ info->done_func (info->session,
+ TNY_CAMEL_ACCOUNT (info->self), NULL, info->user_data);
+
+ }
+
+ apriv->is_connecting = FALSE;
+
+ /* Thread reference */
+ camel_object_unref (info->session);
+ g_object_unref (info->self);
+
+ return NULL;
+}
+
+/* This is that protected implementation that will request to go online, on the
+ * queue of this account @self. Each TnyCamelStoreAccount has two queues: One
+ * queue is dedicated to getting messages. The other, the default queue, is
+ * dedicated to any other operation. Including getting itself connected with an
+ * actual server (that can be both a POP or an IMAP server, depending on the
+ * url-string and/or proto setting of @self). */
+
+void
+_tny_camel_store_account_queue_going_online (TnyCamelStoreAccount *self, TnySessionCamel *session, gboolean online, go_online_callback_func done_func, gpointer user_data)
+{
+ GoingOnlineInfo *info = NULL;
+ GError *err = NULL;
+ TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+ TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
+
+ /* Idle info for the callbacks */
+ info = g_slice_new0 (GoingOnlineInfo);
+
+ info->session = session;
+ info->self = self;
+ info->done_func = done_func;
+ info->online = online;
+ info->user_data = user_data;
+
+ /* thread reference */
+ g_object_ref (info->self);
+ camel_object_ref (info->session);
+
+
+ /* It's indeed a very typical queue operation */
+
+ _tny_camel_queue_launch (priv->queue,
+ tny_camel_store_account_queue_going_online_thread, info);
+
+ return;
+}
+
static void
tny_folder_store_init (gpointer g, gpointer iface_data)
{
Index: libtinymail-camel/tny-session-camel.h
===================================================================
--- libtinymail-camel/tny-session-camel.h (revision 2535)
+++ libtinymail-camel/tny-session-camel.h (working copy)
@@ -51,8 +51,6 @@
void tny_session_camel_set_account_store (TnySessionCamel *self, TnyAccountStore *account_store);
void tny_session_camel_set_device (TnySessionCamel *self, TnyDevice *device);
void tny_session_camel_set_ui_locker (TnySessionCamel *self, TnyLockable *ui_lock);
-void tny_session_camel_join_connecting (TnySessionCamel *self);
-void tny_session_camel_set_async_connecting (TnySessionCamel *self, gboolean enable);
void tny_session_camel_set_initialized (TnySessionCamel *self);
Index: libtinymail-camel/tny-camel-account.c
===================================================================
--- libtinymail-camel/tny-camel-account.c (revision 2535)
+++ libtinymail-camel/tny-camel-account.c (working copy)
@@ -696,7 +696,7 @@
camel_object_ref (session);
priv->session = session;
- _tny_session_camel_add_account_1 (session, self);
+ _tny_session_camel_register_account (session, self);
TNY_CAMEL_ACCOUNT_GET_CLASS (self)->prepare_func (self, FALSE, FALSE);
@@ -886,7 +886,7 @@
reconf_if, TRUE);
if (priv->session)
- _tny_session_camel_add_account_2 (priv->session, TNY_CAMEL_ACCOUNT (self));
+ _tny_session_camel_activate_account (priv->session, TNY_CAMEL_ACCOUNT (self));
g_static_rec_mutex_unlock (priv->service_lock);
@@ -1121,6 +1121,7 @@
TnyCamelAccount *self = (TnyCamelAccount *)instance;
TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+ priv->is_ready = FALSE;
priv->is_connecting = FALSE;
priv->in_auth = FALSE;
priv->csyncop = NULL;
@@ -1159,24 +1160,9 @@
return;
}
-/**
- * tny_camel_account_set_online:
- * @self: a #TnyCamelAccount object
- * @online: whether or not the account is online
- * @err: a #GError instance or NULL
- *
- * Set the connectivity status of an account.
- * Setting this to FALSE means that the account will not attempt to use the network,
- * and will use only the cache.
- * Setting this to TRUE means that the account may use the network to provide up-to-date
- * information.
- *
- **/
-void
-tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, GError **err)
-{
- TNY_CAMEL_ACCOUNT_GET_CLASS (self)->set_online_func (self, online, err);
-}
+/* The is the protected version that will actually set it online. This should
+ * always happen in a thread. In fact, it will always happen in the operations
+ * queue of @self (else it's a bug). */
void
_tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, GError **err)
@@ -1321,54 +1307,170 @@
}
-typedef struct {
- TnyCamelAccount *self;
- gboolean online;
- GError **err;
- GMainLoop *loop;
-} SetOnlineInfo;
-static gpointer
-set_online_thread (gpointer data)
+
+
+/**
+ * tny_camel_account_set_online:
+ * @self: a #TnyCamelAccount object
+ * @online: whether or not the account is online
+ * @callback: a callback when the account went online
+ *
+ * Set the connectivity status of an account. Setting this to FALSE means that
+ * the account will not attempt to use the network, and will use only the cache.
+ * Setting this to TRUE means that the account may use the network to
+ * provide up-to-date information.
+ *
+ * The @callback will be invoke as soon as the account is actually online. It's
+ * guaranteed that the @callback will happen in the mainloop, if available.
+ *
+ **/
+void
+tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, TnyCamelSetOnlineCallback callback)
{
- SetOnlineInfo *info = (SetOnlineInfo *) data;
+ TNY_CAMEL_ACCOUNT_GET_CLASS (self)->set_online_func (self, online, callback);
+}
- _tny_camel_account_set_online (info->self, info->online, info->err);
+typedef struct
+{
+ TnyCamelAccount *account;
+ GError *err;
+ TnyCamelSetOnlineCallback callback;
- if (g_main_loop_is_running (info->loop))
- g_main_loop_quit (info->loop);
+ GCond* condition;
+ gboolean had_callback;
+ GMutex *mutex;
- g_thread_exit (NULL);
- return NULL;
+} OnSetOnlineInfo;
+
+gboolean
+on_set_online_done_idle_func (gpointer data)
+{
+ OnSetOnlineInfo *info = (OnSetOnlineInfo *) data;
+ if (info->callback)
+ info->callback (info->account, info->err);
+ return FALSE;
}
+static void
+on_set_online_done_destroy_func (gpointer data)
+{
+ OnSetOnlineInfo *info = (OnSetOnlineInfo *) data;
+
+ /* We copied it, so we must also free it */
+ if (info->err)
+ g_error_free (info->err);
+
+ /* Thread reference */
+ g_object_unref (info->account);
+
+ if (info->condition) {
+ g_mutex_lock (info->mutex);
+ g_cond_broadcast (info->condition);
+ info->had_callback = TRUE;
+ g_mutex_unlock (info->mutex);
+ }
+
+ return;
+}
+
+/**
+ * When using a #GMainLoop this method will execute a callback using
+ * g_idle_add_full. Note that without a #GMainLoop, the callbacks
+ * could happen in a worker thread (depends on who call it) at an
+ * unknown moment in time (check your locking in this case).
+ */
+static void
+execute_callback (gint depth,
+ gint priority,
+ GSourceFunc idle_func,
+ gpointer data,
+ GDestroyNotify destroy_func)
+{
+ if (depth > 0){
+ g_idle_add_full (priority, idle_func, data, destroy_func);
+ } else {
+ idle_func (data);
+ destroy_func (data);
+ }
+}
+
+static void
+on_set_online_done (TnySessionCamel *self, TnyCamelAccount *account, GError *err, gpointer user_data)
+{
+ OnSetOnlineInfo *info = g_slice_new (OnSetOnlineInfo);
+
+ /* Thread reference */
+ info->account = TNY_CAMEL_ACCOUNT (g_object_ref (account));
+
+ /* We must copy the err because this context will destroy it! */
+ if (err)
+ info->err = g_error_copy (err);
+ else
+ info->err = NULL;
+
+ info->callback = (TnyCamelSetOnlineCallback) user_data;
+
+ info->mutex = g_mutex_new ();
+ info->condition = g_cond_new ();
+ info->had_callback = FALSE;
+
+ execute_callback (/* info->depth */ 10, G_PRIORITY_HIGH,
+ on_set_online_done_idle_func,
+ info, on_set_online_done_destroy_func);
+
+ /* Wait on the queue for the mainloop callback to be finished */
+ g_mutex_lock (info->mutex);
+ if (!info->had_callback)
+ g_cond_wait (info->condition, info->mutex);
+ g_mutex_unlock (info->mutex);
+
+ g_mutex_free (info->mutex);
+ g_cond_free (info->condition);
+
+ g_slice_free (OnSetOnlineInfo, info);
+
+ return;
+}
+
void
-tny_camel_account_set_online_default (TnyCamelAccount *self, gboolean online, GError **err)
+tny_camel_account_set_online_default (TnyCamelAccount *self, gboolean online, TnyCamelSetOnlineCallback callback)
{
- if (g_main_depth () != 0)
+
+ /* In case we are a store account, this means that we need to throw the
+ * request to go online to the account's queue. */
+
+ if (TNY_IS_CAMEL_STORE_ACCOUNT (self))
{
- /* We are being called from the mainnloop */
- SetOnlineInfo *info = g_slice_new (SetOnlineInfo);
- GThread *thread = NULL;
+ TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+ TnySessionCamel *session = priv->session;
- info->self = TNY_CAMEL_ACCOUNT (g_object_ref (self));
- info->online = online;
- info->err = err;
- info->loop = g_main_loop_new (NULL, FALSE);
+ _tny_camel_store_account_queue_going_online (
+ TNY_CAMEL_STORE_ACCOUNT (self), session, online,
+ on_set_online_done, (gpointer) callback);
+ }
- thread = g_thread_create (set_online_thread, info, TRUE, NULL);
- g_main_loop_run (info->loop);
+ /* Else, if it's a transport account, we don't have any transport
+ * account implementations that actually need to go online at this
+ * moment yet. At the moment of transferring the first message, the
+ * current implementations will automatically connect themselves. */
- g_main_loop_unref (info->loop);
- g_object_unref (info->self);
- g_slice_free (SetOnlineInfo, info);
+ if (TNY_IS_CAMEL_TRANSPORT_ACCOUNT (self))
+ {
+ g_signal_emit (self,
+ tny_camel_account_signals [TNY_CAMEL_ACCOUNT_SET_ONLINE_HAPPENED], 0, online);
+ return;
+ }
+}
- } else
- _tny_camel_account_set_online (self, online, err);
+static gboolean
+tny_camel_account_is_ready (TnyAccount *self)
+{
+ TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+ return priv->is_ready;
}
-
static void
tny_camel_account_finalize (GObject *object)
{
@@ -1387,7 +1489,7 @@
}
if (priv->session) {
- _tny_session_camel_forget_account (priv->session, (TnyCamelAccount*) object);
+ _tny_session_camel_unregister_account (priv->session, (TnyCamelAccount*) object);
camel_object_unref (priv->session);
}
_tny_camel_account_start_camel_operation (self, NULL, NULL, NULL);
@@ -1480,6 +1582,7 @@
klass->matches_url_string_func = tny_camel_account_matches_url_string;
klass->start_operation_func = tny_camel_account_start_operation;
klass->stop_operation_func = tny_camel_account_stop_operation;
+ klass->is_ready_func = tny_camel_account_is_ready;
return;
}
@@ -1668,7 +1771,7 @@
g_object_unref (pair);
}
- iter = g_list_next (iter);
+ iter = g_list_next (iter);
}
g_list_free (authtypes);
authtypes = NULL;
@@ -1740,6 +1843,8 @@
tny_camel_account_get_supported_secure_authentication (TnyCamelAccount *self, TnyCamelGetSupportedSecureAuthCallback callback, TnyStatusCallback status_callback, gpointer user_data)
{
TnyCamelAccountPriv *priv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+ GetSupportedAuthInfo *info = NULL;
+
g_return_if_fail (callback);
g_return_if_fail (priv->session);
@@ -1764,7 +1869,7 @@
/* Idle info for the status callback: */
- GetSupportedAuthInfo *info = g_slice_new (GetSupportedAuthInfo);
+ info = g_slice_new (GetSupportedAuthInfo);
info->session = priv->session;
info->err = NULL;
info->self = self;
Index: libtinymail-camel/tny-camel-account.h
===================================================================
--- libtinymail-camel/tny-camel-account.h (revision 2535)
+++ libtinymail-camel/tny-camel-account.h (working copy)
@@ -47,7 +47,9 @@
extern guint tny_camel_account_signals [TNY_CAMEL_ACCOUNT_LAST_SIGNAL];
+typedef void (*TnyCamelSetOnlineCallback) (TnyCamelAccount *account, GError *err);
+
struct _TnyCamelAccount
{
GObject parent;
@@ -88,7 +90,7 @@
void (*add_option_func) (TnyCamelAccount *self, const gchar *option);
- void (*set_online_func) (TnyCamelAccount *self, gboolean online, GError **err);
+ void (*set_online_func) (TnyCamelAccount *self, gboolean online, TnyCamelSetOnlineCallback callback);
/* Abstract methods */
void (*prepare_func) (TnyCamelAccount *self, gboolean recon_if, gboolean reservice);
@@ -102,7 +104,7 @@
void tny_camel_account_add_option (TnyCamelAccount *self, const gchar *option);
void tny_camel_account_set_session (TnyCamelAccount *self, TnySessionCamel *session);
-void tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, GError **err);
+void tny_camel_account_set_online (TnyCamelAccount *self, gboolean online, TnyCamelSetOnlineCallback callback);
typedef void (*TnyCamelGetSupportedSecureAuthCallback) (TnyCamelAccount *self, gboolean cancelled, TnyList *auth_types, GError **err, gpointer user_data);
Index: bindings/python/tinymailmodule.c
===================================================================
--- bindings/python/tinymailmodule.c (revision 2535)
+++ bindings/python/tinymailmodule.c (working copy)
@@ -1,7 +1,7 @@
#include <pygobject.h>
void pytinymail_register_classes (PyObject *d);
-void pytinymail_add_constants(PyObject *module, const gchar *strip_prefix);
+/*void pytinymail_add_constants(PyObject *module, const gchar *strip_prefix);*/
extern PyMethodDef pytinymail_functions[];
DL_EXPORT(void)
@@ -15,7 +15,7 @@
d = PyModule_GetDict (m);
pytinymail_register_classes (d);
- pytinymail_add_constants (m, "TNY_");
+ /*pytinymail_add_constants (m, "TNY_");*/
if (PyErr_Occurred ()) {
Py_FatalError ("can't initialise module tinymail");
Index: libtinymailui-gtk/tny-gtk-folder-store-tree-model.h
===================================================================
--- libtinymailui-gtk/tny-gtk-folder-store-tree-model.h (revision 2535)
+++ libtinymailui-gtk/tny-gtk-folder-store-tree-model.h (working copy)
@@ -59,7 +59,6 @@
GtkTreeStore parent;
GList *first;
GMutex *iterator_lock;
- gboolean is_async;
TnyFolderStoreQuery *query;
GList *store_observables, *folder_observables;
};
@@ -71,7 +70,7 @@
GType tny_gtk_folder_store_tree_model_get_type (void);
GType tny_gtk_folder_store_tree_model_column_get_type (void);
-GtkTreeModel* tny_gtk_folder_store_tree_model_new (gboolean async, TnyFolderStoreQuery *query);
+GtkTreeModel* tny_gtk_folder_store_tree_model_new (TnyFolderStoreQuery *query);
void tny_gtk_folder_store_tree_model_prepend (TnyGtkFolderStoreTreeModel *self, TnyFolderStore* item, const gchar *root_name);
void tny_gtk_folder_store_tree_model_append (TnyGtkFolderStoreTreeModel *self, TnyFolderStore* item, const gchar *root_name);
Index: libtinymailui-gtk/tny-gtk-header-list-model.c
===================================================================
--- libtinymailui-gtk/tny-gtk-header-list-model.c (revision 2535)
+++ libtinymailui-gtk/tny-gtk-header-list-model.c (working copy)
@@ -814,7 +814,7 @@
return;
}
-#ifdef DEBUG
+#ifdef DEBUG_EXTRA
static void forea (gpointer u, gpointer o)
{
g_print ("TnyGtkHeaderListModel::finalize unrefs hdr to: %d\n", ((GObject *)u)->ref_count);
@@ -844,7 +844,7 @@
remove_del_timeouts (self);
-#ifdef DEBUG
+#ifdef DEBUG_EXTRA
g_ptr_array_foreach (priv->items, (GFunc) forea, NULL);
#else
g_ptr_array_foreach (priv->items, (GFunc) g_object_unref, NULL);
Index: libtinymailui-gtk/tny-gtk-folder-store-tree-model.c
===================================================================
--- libtinymailui-gtk/tny-gtk-folder-store-tree-model.c (revision 2535)
+++ libtinymailui-gtk/tny-gtk-folder-store-tree-model.c (working copy)
@@ -29,6 +29,7 @@
#include <tny-folder-store.h>
#include <tny-simple-list.h>
+#include <tny-store-account.h>
#include <tny-folder-store-change.h>
#include <tny-folder-store-observer.h>
#include <tny-folder-change.h>
@@ -39,86 +40,10 @@
#include "tny-gtk-folder-store-tree-model-iterator-priv.h"
static GObjectClass *parent_class = NULL;
-static void recurse_folders_async (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *store, GtkTreeIter *parent_tree_iter);
typedef void (*treeaddfunc) (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent);
-
-typedef struct {
- GtkTreeIter *parent_tree_iter;
- TnyGtkFolderStoreTreeModel *self;
-} AsyncHelpr;
-
static void
-recurse_get_folders_callback (TnyFolderStore *self, TnyList *folders, GError **err, gpointer user_data)
-{
- AsyncHelpr *hlrp = user_data;
- TnyIterator *iter = tny_list_create_iterator (folders);
- TnyGtkFolderStoreTreeModel *me = (TnyGtkFolderStoreTreeModel*) self;
-
- while (!tny_iterator_is_done (iter))
- {
- GtkTreeStore *model = GTK_TREE_STORE (hlrp->self);
- TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
- GtkTreeIter *tree_iter = gtk_tree_iter_copy (hlrp->parent_tree_iter);
-
- tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
- tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));
- me->folder_observables = g_list_prepend (me->folder_observables, folder);
- me->store_observables = g_list_prepend (me->store_observables, folder);
-
- gtk_tree_store_append (model, tree_iter, hlrp->parent_tree_iter);
-
- /* This adds a reference count to folder too. When it gets removed, that
- reference count is decreased automatically by the gtktreestore infra-
- structure. */
-
- gtk_tree_store_set (model, tree_iter,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
- tny_folder_get_name (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
- tny_folder_get_unread_count (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
- tny_folder_get_all_count (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN,
- tny_folder_get_folder_type (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
- folder, -1);
-
- /* TODO: This causes a memory peak at the application's startup.
- *Also look at tny-camel-folder:c:2818... for more information */
-
- tny_folder_poke_status (TNY_FOLDER (folder));
-
- recurse_folders_async (hlrp->self, folder, tree_iter);
-
- g_object_unref (G_OBJECT (folder));
-
- tny_iterator_next (iter);
- }
-
- g_object_unref (G_OBJECT (iter));
- g_object_unref (G_OBJECT (folders));
-
- gtk_tree_iter_free (hlrp->parent_tree_iter);
- g_slice_free (AsyncHelpr, hlrp);
-
-}
-
-
-static void
-recurse_folders_async (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *store, GtkTreeIter *parent_tree_iter)
-{
- AsyncHelpr *hlrp = g_slice_new0 (AsyncHelpr);
- TnyList *folders = tny_simple_list_new ();
-
- hlrp->self = self;
- hlrp->parent_tree_iter = parent_tree_iter;
-
- tny_folder_store_get_folders_async (store, folders, recurse_get_folders_callback, self->query, NULL, hlrp);
-}
-
-static void
recurse_folders_sync (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *store, GtkTreeIter *parent_tree_iter)
{
TnyIterator *iter;
@@ -131,73 +56,145 @@
while (!tny_iterator_is_done (iter))
{
+ GtkTreeModel *mmodel = (GtkTreeModel *) self;
GtkTreeStore *model = GTK_TREE_STORE (self);
GObject *instance = G_OBJECT (tny_iterator_get_current (iter));
GtkTreeIter tree_iter;
-
- gtk_tree_store_append (model, &tree_iter, parent_tree_iter);
-
TnyFolder *folder = NULL;
TnyFolderStore *folder_store = NULL;
-
+ GtkTreeIter miter;
+ gboolean found = FALSE;
+ GObject *mark_for_removal = NULL;
+
if (TNY_IS_FOLDER (instance))
folder = TNY_FOLDER (instance);
-
+
if (TNY_IS_FOLDER_STORE (folder))
folder_store = TNY_FOLDER_STORE (instance);
+
+ /* We check whether we have this folder already in the tree, or
+ * whether it's a brand new one. If it's a new one, we'll add
+ * it, of course */
+
+ if (gtk_tree_model_iter_children (mmodel, &miter, parent_tree_iter))
+ do
+ {
+ GObject *citem = NULL;
+ TnyIterator *niter = NULL;
- if (folder)
- {
- tny_folder_add_observer (folder, TNY_FOLDER_OBSERVER (self));
- me->folder_observables = g_list_prepend (me->folder_observables, folder);
- }
+ gtk_tree_model_get (mmodel, &miter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ &citem, -1);
- if (folder_store)
- {
- tny_folder_store_add_observer (folder_store, TNY_FOLDER_STORE_OBSERVER (self));
- me->store_observables = g_list_prepend (me->store_observables, folder);
- }
+ if (citem == instance)
+ {
+ found = TRUE;
+ break;
+ }
+ if (citem)
+ g_object_unref (citem);
+ /* We search whether this folder that we have in the
+ * model, still exists in the actual list. Because if
+ * not, it probably got removed remotely (and we need
+ * to get rid of it in the model now) */
- /* This adds a reference count to folder too. When it gets removed, that
- reference count is decreased automatically by the gtktreestore infra-
- structure. */
- if (folder)
+ niter = tny_list_create_iterator (folders);
+ while (!tny_iterator_is_done (niter))
+ {
+ TnyFolder *ifound = TNY_FOLDER (tny_iterator_get_current (niter));
+ if (citem == (GObject *) ifound)
+ mark_for_removal = g_object_ref (ifound);
+ g_object_unref (ifound);
+ tny_iterator_next (niter);
+ }
+ g_object_unref (niter);
+
+ } while (gtk_tree_model_iter_next (mmodel, &miter));
+
+ /* It was not found, so let's start adding it to the model! */
+
+ if (!found)
{
- TnyFolder *folder = TNY_FOLDER (instance);
-
- gtk_tree_store_set (model, &tree_iter,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
- tny_folder_get_name (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
- tny_folder_get_unread_count (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
- tny_folder_get_all_count (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN,
- tny_folder_get_folder_type (TNY_FOLDER (folder)),
- TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
- folder, -1);
- }
+ gtk_tree_store_append (model, &tree_iter, parent_tree_iter);
- if (folder_store)
- recurse_folders_sync (self, folder_store, &tree_iter);
+ /* Making self both a folder-store as a folder observer
+ * of this folder. This way we'll get notified when
+ * both a removal and a creation happens. Also when a
+ * rename happens: that's a removal and a creation. */
+ if (folder)
+ {
+ tny_folder_add_observer (folder, TNY_FOLDER_OBSERVER (self));
+ me->folder_observables = g_list_prepend (me->folder_observables, folder);
+ }
- /* TODO: This causes a memory peak at the application's startup.
- *Also look at tny-camel-folder:c:2818... for more information */
+ if (folder_store)
+ {
+ tny_folder_store_add_observer (folder_store, TNY_FOLDER_STORE_OBSERVER (self));
+ me->store_observables = g_list_prepend (me->store_observables, folder);
+ }
- if (folder)
- tny_folder_poke_status (TNY_FOLDER (folder));
- g_object_unref (G_OBJECT (instance));
+ /* This adds a reference count to folder too. When it gets removed, that
+ reference count is decreased automatically by the gtktreestore infra-
+ structure. */
+ if (folder)
+ {
+ TnyFolder *folder = TNY_FOLDER (instance);
+
+ gtk_tree_store_set (model, &tree_iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN,
+ tny_folder_get_name (TNY_FOLDER (folder)),
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
+ tny_folder_get_unread_count (TNY_FOLDER (folder)),
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
+ tny_folder_get_all_count (TNY_FOLDER (folder)),
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN,
+ tny_folder_get_folder_type (TNY_FOLDER (folder)),
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ folder, -1);
+ }
+
+ /* it's a store by itself, so keep on recursing */
+ if (folder_store)
+ recurse_folders_sync (self, folder_store, &tree_iter);
+
+ /* We're a folder, we'll request a status, since we've
+ * set self to be a folder observers of folder, we'll
+ * receive the status update. This makes it possible to
+ * instantly get the unread and total counts, of course.
+ *
+ * Note that the initial value is read from the cache in
+ * case the account is set offline, in TnyCamelFolder.
+ * In case the account is online a STAT for POP or a
+ * STATUS for IMAP is asked during the poke-status impl.
+ *
+ * This means that no priv->folder must be loaded, no
+ * memory peak will happen, few data must be transmitted
+ * in case we're online. Which is perfect! */
+
+ if (folder)
+ tny_folder_poke_status (TNY_FOLDER (folder));
+ } else {
+ if (mark_for_removal)
+ {
+ printf ("We need to remove %s\n",
+ tny_folder_get_id (TNY_FOLDER (mark_for_removal)));
+ }
+ }
+
+ g_object_unref (instance);
+
tny_iterator_next (iter);
}
- g_object_unref (G_OBJECT (iter));
- g_object_unref (G_OBJECT (folders));
+ g_object_unref (iter);
+ g_object_unref (folders);
}
+
static const gchar*
get_root_name (TnyFolderStore *folder_store)
{
@@ -209,6 +206,94 @@
return root_name;
}
+
+static void
+tny_gtk_folder_store_tree_model_on_constatus_changed (TnyAccount *account, TnyConnectionStatus status, TnyGtkFolderStoreTreeModel *self)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (self);
+ GtkTreeIter iter;
+ GtkTreeIter name_iter;
+ gboolean found = FALSE;
+
+ /* This callback handler deals with connection status changes. In case
+ * we got connected, we can expect that, at least sometimes, new folders
+ * might have arrived. We'll need to scan for those, so we'll recursively
+ * start asking the account about its folders. */
+
+ if (status != TNY_CONNECTION_STATUS_CONNECTED)
+ return;
+
+ /* Note that the very first time, this core will pull all folder info.
+ * Note that when it runs, you'll see LIST commands happen on the IMAP
+ * socket. Especially the first time. You'll also see STATUS commands
+ * happen. This is, indeed, normal behaviour when this component is used.*/
+
+ /* But first, let's find-back that damn account so that we have the
+ * actual iter behind it in the model. */
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ do
+ {
+ GObject *citem;
+
+ gtk_tree_model_get (model, &iter,
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ &citem, -1);
+ if (citem == (GObject *) account)
+ {
+ name_iter = iter;
+ found = TRUE;
+ break;
+ }
+ g_object_unref (G_OBJECT (citem));
+
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ /* We found it, so we'll now just recursively start asking for all its
+ * folders and subfolders. The recurse_folders_sync can indeed cope with
+ * folders that already exist (it wont add them a second time). */
+
+ if (found)
+ recurse_folders_sync (self, TNY_FOLDER_STORE (account), &name_iter);
+}
+
+typedef struct
+{
+ TnyGtkFolderStoreTreeModel *self;
+ TnyAccount *account;
+} AccNotYetReadyInfo;
+
+static gboolean
+account_was_not_yet_ready_idle (gpointer user_data)
+{
+ AccNotYetReadyInfo *info = (AccNotYetReadyInfo *) user_data;
+ gboolean repeat = TRUE;
+
+ if (tny_account_is_ready (info->account))
+ {
+ g_signal_connect (info->account, "connection-status-changed",
+ G_CALLBACK (tny_gtk_folder_store_tree_model_on_constatus_changed), info->self);
+
+ tny_gtk_folder_store_tree_model_on_constatus_changed (info->account,
+ tny_account_get_connection_status (info->account), info->self);
+
+ repeat = FALSE;
+ }
+
+ return repeat;
+}
+
+static void
+account_was_not_yet_ready_destroy (gpointer user_data)
+{
+ AccNotYetReadyInfo *info = (AccNotYetReadyInfo *) user_data;
+
+ g_object_unref (info->account);
+ g_object_unref (info->self);
+
+ g_slice_free (AccNotYetReadyInfo, user_data);
+}
+
static void
tny_gtk_folder_store_tree_model_add_i (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *folder_store, treeaddfunc func, const gchar *root_name)
{
@@ -226,54 +311,44 @@
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
folder_store, -1);
- recurse_folders_sync (self, TNY_FOLDER_STORE (folder_store), &name_iter);
+ /* In case we added a store account, it's possible that the account
+ * will have "the account just got connected" events happening. Accounts
+ * that just got connected might have new folders for us to know about.
+ * That's why we'll handle connection changes. */
- /* Add an observer for the root folder store */
- tny_folder_store_add_observer (folder_store, TNY_FOLDER_STORE_OBSERVER (self));
- self->store_observables = g_list_prepend (self->store_observables, folder_store);
+ if (TNY_IS_STORE_ACCOUNT (folder_store)) {
+ if (!tny_account_is_ready (TNY_ACCOUNT (folder_store)))
+ {
+ AccNotYetReadyInfo *info = g_slice_new (AccNotYetReadyInfo);
- g_object_unref (G_OBJECT (folders));
+ info->account = TNY_ACCOUNT (g_object_ref (folder_store));
+ info->self = TNY_GTK_FOLDER_STORE_TREE_MODEL (g_object_ref (self));
- return;
-}
+ g_timeout_add_full (G_PRIORITY_HIGH, 100,
+ account_was_not_yet_ready_idle,
+ info, account_was_not_yet_ready_destroy);
-static void
-tny_gtk_folder_store_tree_model_add_async_i (TnyGtkFolderStoreTreeModel *self, TnyFolderStore *folder_store, treeaddfunc func, const gchar *root_name)
-{
- GtkTreeStore *model = GTK_TREE_STORE (self);
- GtkTreeIter first, *name_iter;
- gboolean need_add = TRUE;
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self), &first))
- {
- func (model, &first, NULL);
- need_add = FALSE;
+ } else
+ g_signal_connect (folder_store, "connection-status-changed",
+ G_CALLBACK (tny_gtk_folder_store_tree_model_on_constatus_changed), self);
}
- name_iter = gtk_tree_iter_copy (&first);
+ recurse_folders_sync (self, TNY_FOLDER_STORE (folder_store), &name_iter);
- if (need_add)
- func (model, name_iter, NULL);
+ /* Add an observer for the root folder store, so that we can observe
+ * the actual account too. */
- /* This adds a reference count to folder_store too. When it gets removed,
- that reference count is decreased automatically by the gtktreestore
- infrastructure. */
+ tny_folder_store_add_observer (folder_store, TNY_FOLDER_STORE_OBSERVER (self));
+ self->store_observables = g_list_prepend (self->store_observables, folder_store);
- gtk_tree_store_set (model, name_iter,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_NAME_COLUMN, root_name,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN, 0,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN, TNY_FOLDER_TYPE_ROOT,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
- folder_store, -1);
+ g_object_unref (G_OBJECT (folders));
- recurse_folders_async (self, TNY_FOLDER_STORE (folder_store), name_iter);
-
return;
}
+
/**
* tny_gtk_folder_store_tree_model_new:
- * @async: Whether or not this component should attempt to asynchronously fill the tree
* @query: the #TnyFolderStoreQuery that will be used to retrieve the folders of each folder_store
*
* Create a new #GtkTreeModel instance suitable for showing
@@ -283,11 +358,13 @@
* #TnyFolderStore instances
**/
GtkTreeModel*
-tny_gtk_folder_store_tree_model_new (gboolean async, TnyFolderStoreQuery *query)
+tny_gtk_folder_store_tree_model_new (TnyFolderStoreQuery *query)
{
TnyGtkFolderStoreTreeModel *self = g_object_new (TNY_TYPE_GTK_FOLDER_STORE_TREE_MODEL, NULL);
- self->is_async = FALSE;
- if (query) self->query = g_object_ref (G_OBJECT (query));
+
+ if (query)
+ self->query = g_object_ref (G_OBJECT (query));
+
return GTK_TREE_MODEL (self);
}
@@ -342,7 +419,7 @@
me->iterator_lock = NULL;
if (me->query)
- g_object_unref (G_OBJECT (me->query));
+ g_object_unref (me->query);
(*parent_class->finalize) (object);
}
@@ -406,15 +483,11 @@
g_mutex_lock (me->iterator_lock);
/* Prepend something to the list */
- g_object_ref (G_OBJECT (item));
+ g_object_ref (item);
me->first = g_list_prepend (me->first, item);
- if (me->is_async)
- tny_gtk_folder_store_tree_model_add_async_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_prepend, root_name);
- else
- tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_prepend, root_name);
+ tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
+ gtk_tree_store_prepend, root_name);
g_mutex_unlock (me->iterator_lock);
}
@@ -428,16 +501,12 @@
g_mutex_lock (me->iterator_lock);
/* Prepend something to the list */
- g_object_ref (G_OBJECT (item));
+ g_object_ref (item);
me->first = g_list_prepend (me->first, item);
- if (me->is_async)
- tny_gtk_folder_store_tree_model_add_async_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_prepend, get_root_name (TNY_FOLDER_STORE (item)));
- else
- tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_prepend, get_root_name (TNY_FOLDER_STORE (item)));
-
+ tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
+ gtk_tree_store_prepend, get_root_name (TNY_FOLDER_STORE (item)));
+
g_mutex_unlock (me->iterator_lock);
}
@@ -457,15 +526,11 @@
g_mutex_lock (me->iterator_lock);
/* Append something to the list */
- g_object_ref (G_OBJECT (item));
+ g_object_ref (item);
me->first = g_list_append (me->first, item);
- if (me->is_async)
- tny_gtk_folder_store_tree_model_add_async_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_append, root_name);
- else
- tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_append, root_name);
+ tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
+ gtk_tree_store_append, root_name);
g_mutex_unlock (me->iterator_lock);
}
@@ -478,15 +543,11 @@
g_mutex_lock (me->iterator_lock);
/* Append something to the list */
- g_object_ref (G_OBJECT (item));
+ g_object_ref (item);
me->first = g_list_append (me->first, item);
- if (me->is_async)
- tny_gtk_folder_store_tree_model_add_async_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_append, get_root_name (TNY_FOLDER_STORE (item)));
- else
- tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
- gtk_tree_store_append, get_root_name (TNY_FOLDER_STORE (item)));
+ tny_gtk_folder_store_tree_model_add_i (me, TNY_FOLDER_STORE (item),
+ gtk_tree_store_append, get_root_name (TNY_FOLDER_STORE (item)));
g_mutex_unlock (me->iterator_lock);
}
@@ -526,14 +587,12 @@
actually really part of the list. */
if (gtk_tree_model_get_iter_first (model, &iter))
- while (gtk_tree_model_iter_next (model, &iter))
+ do
{
- GObject *citem;
-
+ GObject *citem = NULL;
gtk_tree_model_get (model, &iter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
&citem, -1);
-
if (citem == item)
{
/* This removes a reference count */
@@ -541,9 +600,11 @@
g_object_unref (G_OBJECT (item));
break;
}
- g_object_unref (G_OBJECT (citem));
- }
+ if (citem)
+ g_object_unref (G_OBJECT (citem));
+ } while (gtk_tree_model_iter_next (model, &iter));
+
g_mutex_unlock (me->iterator_lock);
}
@@ -593,6 +654,10 @@
TnyFolder *changed_folder = tny_folder_change_get_folder (change);
TnyFolderChangeChanged changed = tny_folder_change_get_changed (change);
+ /* This updater will get the folder out of the model, compare with
+ * the changed_folder pointer, and if there's a match it will update
+ * the values of the model with the values from the folder. */
+
gtk_tree_model_get (model, iter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN,
&type, -1);
@@ -628,14 +693,13 @@
TNY_GTK_FOLDER_STORE_TREE_MODEL_UNREAD_COLUMN,
unread,
TNY_GTK_FOLDER_STORE_TREE_MODEL_ALL_COLUMN,
- total,
- -1);
+ total, -1);
}
- g_object_unref (G_OBJECT (folder));
+ g_object_unref (folder);
}
- g_object_unref (G_OBJECT (changed_folder));
+ g_object_unref (changed_folder);
return FALSE;
}
@@ -648,13 +712,17 @@
TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
GObject *folder = user_data1;
+ /* The deleter will compare all folders in the model with the deleted
+ * folder @folder, and if there's a match it will delete the folder's
+ * row from the model. */
+
gtk_tree_model_get (model, iter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_TYPE_COLUMN,
&type, -1);
if (type != TNY_FOLDER_TYPE_ROOT)
{
- GObject *fol;
+ GObject *fol = NULL;
gtk_tree_model_get (model, iter,
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
@@ -665,7 +733,8 @@
retval = TRUE;
}
- g_object_unref (G_OBJECT (fol));
+ if (fol)
+ g_object_unref (fol);
}
return retval;
@@ -675,6 +744,8 @@
static gboolean
find_store_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *f, gpointer user_data)
{
+ /* Finding the iter for a given folder */
+
do
{
GtkTreeIter child;
@@ -687,14 +758,14 @@
&type, -1);
gtk_tree_model_get (model, iter,
- TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
- &fol, -1);
+ TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
+ &fol, -1);
if (fol == user_data)
found = TRUE;
- if (fol != NULL)
- g_object_unref (G_OBJECT (fol));
+ if (fol)
+ g_object_unref (fol);
if (found) {
*f = *iter;
@@ -798,7 +869,8 @@
GtkTreeIter newiter;
TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
- /* See early added below!
+ /* See early added below! (#CCUX)
+
tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));*/
@@ -823,11 +895,11 @@
TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN,
folder, -1);
- g_object_unref (G_OBJECT (folder));
+ g_object_unref (folder);
tny_iterator_next (miter);
}
- g_object_unref (G_OBJECT (miter));
- g_object_unref (G_OBJECT (created));
+ g_object_unref (miter);
+ g_object_unref (created);
}
g_object_unref (G_OBJECT (parentstore));
}
@@ -844,11 +916,11 @@
{
TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
gtk_tree_model_foreach (model, deleter, folder);
- g_object_unref (G_OBJECT (folder));
+ g_object_unref (folder);
tny_iterator_next (miter);
}
- g_object_unref (G_OBJECT (miter));
- g_object_unref (G_OBJECT (removed));
+ g_object_unref (miter);
+ g_object_unref (removed);
}
@@ -888,7 +960,7 @@
{
TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (miter));
- /* Already added!
+ /* Already added! (#CCUX)
* We can't add these in the idle because the thread might
* be added subfolders right now! (the idle would register
* self as an observer too late!)
@@ -899,11 +971,11 @@
tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (self));
tny_folder_store_add_observer (TNY_FOLDER_STORE (folder), TNY_FOLDER_STORE_OBSERVER (self));
- g_object_unref (G_OBJECT (folder));
+ g_object_unref (folder);
tny_iterator_next (miter);
}
- g_object_unref (G_OBJECT (miter));
- g_object_unref (G_OBJECT (created));
+ g_object_unref (miter);
+ g_object_unref (created);
}
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
Index: tests/c-demo/tny-demoui-summary-view.c
===================================================================
--- tests/c-demo/tny-demoui-summary-view.c (revision 2535)
+++ tests/c-demo/tny-demoui-summary-view.c (working copy)
@@ -93,7 +93,6 @@
GtkComboBox *account_view;
GtkTreeView *mailbox_view, *header_view;
TnyMsgView *msg_view;
- guint accounts_reloaded_signal;
GtkWidget *status, *progress, *online_button, *poke_button, *sync_button;
guint status_id;
gulong mailbox_select_sid;
@@ -276,7 +275,7 @@
}
static void
-reload_accounts_first (TnySummaryView *self, gboolean first_time)
+load_accounts (TnySummaryView *self, gboolean first_time)
{
TnyDemouiSummaryViewPriv *priv = TNY_DEMOUI_SUMMARY_VIEW_GET_PRIVATE (self);
TnyAccountStore *account_store = priv->account_store;
@@ -290,11 +289,7 @@
/* TnyGtkFolderStoreTreeModel is also a TnyList (it simply implements both the
TnyList and the GtkTreeModel interfaces) */
-#if PLATFORM==1
- mailbox_model = tny_gtk_folder_store_tree_model_new (TRUE, NULL);
-#else
- mailbox_model = tny_gtk_folder_store_tree_model_new (FALSE, NULL);
-#endif
+ mailbox_model = tny_gtk_folder_store_tree_model_new (NULL);
g_object_unref (G_OBJECT (query));
@@ -370,19 +365,7 @@
return;
}
-static void
-reload_accounts (TnySummaryView *self)
-{
- reload_accounts_first (self, FALSE);
-}
-static void
-accounts_reloaded (TnyAccountStore *store, gpointer user_data)
-{
- reload_accounts ((TnySummaryView *)user_data);
- return;
-}
-
static void
online_button_toggled (GtkToggleButton *togglebutton, gpointer user_data)
{
@@ -494,16 +477,11 @@
TnyDevice *odevice = tny_account_store_get_device (priv->account_store);
if (g_signal_handler_is_connected (G_OBJECT (odevice), priv->connchanged_signal))
- {
g_signal_handler_disconnect (G_OBJECT (odevice),
priv->connchanged_signal);
- }
- g_signal_handler_disconnect (G_OBJECT (priv->account_store),
- priv->accounts_reloaded_signal);
-
- g_object_unref (G_OBJECT (priv->account_store));
- g_object_unref (G_OBJECT (odevice));
+ g_object_unref (priv->account_store);
+ g_object_unref (odevice);
}
g_object_ref (G_OBJECT (account_store));
@@ -514,12 +492,8 @@
priv->account_store = account_store;
- priv->accounts_reloaded_signal = g_signal_connect (
- G_OBJECT (account_store), "accounts_reloaded",
- G_CALLBACK (accounts_reloaded), self);
+ load_accounts ((TnySummaryView *) self, TRUE);
- reload_accounts_first ((TnySummaryView *) self, TRUE);
-
g_object_unref (G_OBJECT (device));
return;
@@ -1935,16 +1909,11 @@
TnyDemouiSummaryViewPriv *priv = TNY_DEMOUI_SUMMARY_VIEW_GET_PRIVATE (self);
if (priv->current_accounts)
- g_object_unref (G_OBJECT (priv->current_accounts));
+ g_object_unref (priv->current_accounts);
- if (G_LIKELY (priv->account_store))
- {
- g_signal_handler_disconnect (G_OBJECT (priv->account_store),
- priv->accounts_reloaded_signal);
+ if (priv->account_store)
+ g_object_unref (priv->account_store);
- g_object_unref (G_OBJECT (priv->account_store));
- }
-
g_mutex_lock (priv->monitor_lock);
if (priv->monitor)
{
Index: libtinymail-maemo/tny-maemo-account-store.h
===================================================================
--- libtinymail-maemo/tny-maemo-account-store.h (revision 2535)
+++ libtinymail-maemo/tny-maemo-account-store.h (working copy)
@@ -53,9 +53,6 @@
TnyAccountStore* tny_maemo_account_store_new (void);
TnySessionCamel* tny_maemo_account_store_get_session (TnyMaemoAccountStore *self);
-void tny_maemo_account_store_add_store_account (TnyMaemoAccountStore *self, TnyStoreAccount *account);
-void tny_maemo_account_store_add_transport_account (TnyAccountStore *self, TnyTransportAccount *account);
-
G_END_DECLS
#endif
Index: libtinymail-maemo/tny-maemo-account-store.c
===================================================================
--- libtinymail-maemo/tny-maemo-account-store.c (revision 2535)
+++ libtinymail-maemo/tny-maemo-account-store.c (working copy)
@@ -157,11 +157,7 @@
gchar *ptr = strrchr (key, '/'); ptr++;
if (!strcmp (ptr, "count"))
- {
kill_stored_accounts (priv);
- g_signal_emit (self,
- tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0);
- }
g_free (key);
@@ -498,30 +494,6 @@
-void
-tny_maemo_account_store_add_store_account (TnyMaemoAccountStore *self, TnyStoreAccount *account)
-{
- tny_maemo_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_maemo_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "store");
- tny_maemo_account_store_notify_add (TNY_ACCOUNT_STORE (self));
-
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
-void
-tny_maemo_account_store_add_transport_account (TnyAccountStore *self, TnyTransportAccount *account)
-{
- tny_maemo_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_maemo_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "transport");
- tny_maemo_account_store_notify_add (TNY_ACCOUNT_STORE (self));
-
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
static TnyDevice*
tny_maemo_account_store_get_device (TnyAccountStore *self)
{
Index: ChangeLog
===================================================================
--- ChangeLog (revision 2535)
+++ ChangeLog (working copy)
@@ -1,3 +1,16 @@
+2007-07-31 Philip Van Hoof <pvanhoof gnome org>
+
+ * Merging back devel/pvanhoof/sessionwork to trunk/
+
+2007-07-31 Philip Van Hoof <pvanhoof gnome org>
+
+ * Cleaning up, coding style fixes
+ * Review of TnyCamelFolder and TnyCamelStoreAccount
+
+2007-07-30 Philip Van Hoof <pvanhoof gnome org>
+
+ * Various fixes that make Modest actually work with this
+
2007-07-30 Javier Fernandez Garcia-Boente <jfernandez igalia com>
* Fixed some bugs in TnyMergeFolder notification function. This
@@ -23,6 +36,47 @@
* Merging the Cond patch from devel/sessionwork
+2007-07-29 Philip Van Hoof <pvanhoof gnome org>
+
+ * The long awaited alert, get_pass and forget_pass now in the mainloop
+
+ * This was a major API and behaviour change
+
+2007-07-29 Philip Van Hoof <pvanhoof gnome org>
+
+ * Fixed a race condition when the account was or is connection or not
+ yet finished connecting while the connection-status-changed signal was
+ already being used. Introduced a new API for this
+ * Introduced the tny_account_is_ready API, which indicates when an
+ account is not only valid as instance, but also fully registered
+ within the system.
+ * Implemented some missing implementations in TnyCombinedAccount
+
+ * This was a major API change
+
+2007-07-27 Philip Van Hoof <pvanhoof gnome org>
+
+ * Dealing with remotely removed folders
+ * The poke status calls are now on the same queue as the other
+ operations
+ * Rewritten the TnySessionCamel infrastructure that connects accounts
+ and sets them up
+ * Added support for detecting folder changes to
+ TnyGtkFolderStoreTreeModel
+ * API change on tny_camel_account_set_online. The last argument is now
+ a callback rather than a GError. In the callback you can know about
+ when the account got connected and if not, why it failed
+
+ * Cond locks in the queues of the store accounts while the callbacks
+ are happening. This is a significant policy change in locking
+ behaviour that should be well tested.
+
+ * This was a major API change in TnyAccount
+
+2007-07-27 Philip Van Hoof <pvanhoof gnome org>
+
+ * Branchpoint "devel/sessionwork"
+
2007-07-26 Philip Van Hoof <pvanhoof gnome org>
* More granularity in the locking of the POP code
Index: libtinymail-gnome-desktop/tny-gnome-account-store.c
===================================================================
--- libtinymail-gnome-desktop/tny-gnome-account-store.c (revision 2535)
+++ libtinymail-gnome-desktop/tny-gnome-account-store.c (working copy)
@@ -153,13 +153,8 @@
gchar *key = g_strdup (entry->key);
gchar *ptr = strrchr (key, '/'); ptr++;
-
if (!strcmp (ptr, "count"))
- {
kill_stored_accounts (priv);
- g_signal_emit (self,
- tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED], 0);
- }
g_free (key);
@@ -489,44 +484,7 @@
return;
}
-/**
- * tny_gnome_account_store_add_store_account:
- * @self: a #TnyGnomeAccountStore instance
- * @account: a #TnyStoreAccount instance to add
- *
- * Add @account to @self
- **/
-void
-tny_gnome_account_store_add_store_account (TnyGnomeAccountStore *self, TnyStoreAccount *account)
-{
- tny_gnome_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_gnome_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "store");
- tny_gnome_account_store_notify_add (TNY_ACCOUNT_STORE (self));
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
-/**
- * tny_gnome_account_store_add_transport_account:
- * @self: a #TnyGnomeAccountStore instance
- * @account: a #TnyTransportAccount instance to add
- *
- * Add @account to @self
- **/
-void
-tny_gnome_account_store_add_transport_account (TnyGnomeAccountStore *self, TnyTransportAccount *account)
-{
- tny_gnome_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
- tny_gnome_account_store_add_account (TNY_ACCOUNT_STORE (self), TNY_ACCOUNT (account), "transport");
- tny_gnome_account_store_notify_add (TNY_ACCOUNT_STORE (self));
-
- g_signal_emit (self, tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_INSERTED], 0, account);
-
- return;
-}
-
static TnyDevice*
tny_gnome_account_store_get_device (TnyAccountStore *self)
{
Index: libtinymail-gnome-desktop/tny-gnome-account-store.h
===================================================================
--- libtinymail-gnome-desktop/tny-gnome-account-store.h (revision 2535)
+++ libtinymail-gnome-desktop/tny-gnome-account-store.h (working copy)
@@ -52,8 +52,6 @@
TnyAccountStore* tny_gnome_account_store_new (void);
TnySessionCamel* tny_gnome_account_store_get_session (TnyGnomeAccountStore *self);
-void tny_gnome_account_store_add_store_account (TnyGnomeAccountStore *self, TnyStoreAccount *account);
-void tny_gnome_account_store_add_transport_account (TnyGnomeAccountStore *self, TnyTransportAccount *account);
G_END_DECLS
Index: libtinymail-olpc/tny-olpc-account-store.h
===================================================================
--- libtinymail-olpc/tny-olpc-account-store.h (revision 2535)
+++ libtinymail-olpc/tny-olpc-account-store.h (working copy)
@@ -52,9 +52,6 @@
TnyAccountStore* tny_olpc_account_store_new (void);
TnySessionCamel* tny_olpc_account_store_get_session (TnyOlpcAccountStore *self);
-void tny_olpc_account_store_add_store_account (TnyOlpcAccountStore *self, TnyStoreAccount *account);
-void tny_olpc_account_store_add_transport_account (TnyOlpcAccountStore *self, TnyTransportAccount *account);
-
G_END_DECLS
#endif
Index: libtinymail/tny-account-store.c
===================================================================
--- libtinymail/tny-account-store.c (revision 2535)
+++ libtinymail/tny-account-store.c (working copy)
@@ -374,82 +374,6 @@
if (!tny_account_store_initialized)
{
/**
- * TnyAccountStore::account-changed
- * @self: the object on which the signal is emitted
- * @arg1: the #TnyAccount of the account that changed
- * @user_data: user data set when the signal handler was connected
- *
- * API WARNING: This API might change
- *
- * Emitted when an account in the store changed
- */
- tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_CHANGED] =
- g_signal_new ("account_changed",
- TNY_TYPE_ACCOUNT_STORE,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (TnyAccountStoreIface, account_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT);
-
-/**
- * TnyAccountStore::account-inserted
- * @self: the object on which the signal is emitted
- * @arg1: the #TnyAccount of the account that got inserted
- * @user_data: user data set when the signal handler was connected.
- *
- * API WARNING: This API might change
- *
- * Emitted when an account is added to the store
- */
- tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_INSERTED] =
- g_signal_new ("account_inserted",
- TNY_TYPE_ACCOUNT_STORE,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (TnyAccountStoreIface, account_inserted),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT);
-
-/**
- * TnyAccountStore::account-removed
- * @self: the object on which the signal is emitted
- * @arg1: the #TnyAccount of the account that got removed
- * @user_data: user data set when the signal handler was connected.
- *
- * API WARNING: This API might change
- *
- * Emitted when an account is removed from the store
- */
- tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNT_REMOVED] =
- g_signal_new ("account_removed",
- TNY_TYPE_ACCOUNT_STORE,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (TnyAccountStoreIface, account_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT);
-
-/**
- * TnyAccountStore::accounts-reloaded
- * @self: the object on which the signal is emitted
- *
- * API WARNING: This API might change
- *
- * Emitted when the store reloads the accounts
- */
- tny_account_store_signals[TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED] =
- g_signal_new ("accounts_reloaded",
- TNY_TYPE_ACCOUNT_STORE,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (TnyAccountStoreIface, accounts_reloaded),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
-
-
-/**
* TnyAccountStore::connecting-started
* @self: the object on which the signal is emitted
* @user_data: user data set when the signal handler was connected.
@@ -465,23 +389,6 @@
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
-
-/**
- * TnyAccountStore::connecting-finished
- * @self: the object on which the signal is emitted
- * @user_data: user data set when the signal handler was connected.
- *
- * Emitted when the store finished trying to connect the accounts
- */
- tny_account_store_signals[TNY_ACCOUNT_STORE_CONNECTING_FINISHED] =
- g_signal_new ("connecting_finished",
- TNY_TYPE_ACCOUNT_STORE,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (TnyAccountStoreIface, connecting_finished),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
tny_account_store_initialized = TRUE;
}
return;
@@ -584,12 +491,7 @@
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
- { TNY_ACCOUNT_STORE_ACCOUNT_CHANGED, "TNY_ACCOUNT_STORE_ACCOUNT_CHANGED", "changed" },
- { TNY_ACCOUNT_STORE_ACCOUNT_INSERTED, "TNY_ACCOUNT_STORE_ACCOUNT_INSERTED", "inserted" },
- { TNY_ACCOUNT_STORE_ACCOUNT_REMOVED, "TNY_ACCOUNT_STORE_ACCOUNT_REMOVED", "removed" },
- { TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED, "TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED", "reloaded" },
{ TNY_ACCOUNT_STORE_CONNECTING_STARTED, "TNY_ACCOUNT_STORE_CONNECTING_STARTED", "started" },
- { TNY_ACCOUNT_STORE_CONNECTING_FINISHED, "TNY_ACCOUNT_STORE_CONNECTING_FINISHED", "finished" },
{ TNY_ACCOUNT_STORE_LAST_SIGNAL, "TNY_ACCOUNT_STORE_LAST_SIGNAL", "last-signal" },
{ 0, NULL, NULL }
};
Index: libtinymail/tny-account-store.h
===================================================================
--- libtinymail/tny-account-store.h (revision 2535)
+++ libtinymail/tny-account-store.h (working copy)
@@ -35,12 +35,7 @@
enum _TnyAccountStoreSignal
{
- TNY_ACCOUNT_STORE_ACCOUNT_CHANGED,
- TNY_ACCOUNT_STORE_ACCOUNT_INSERTED,
- TNY_ACCOUNT_STORE_ACCOUNT_REMOVED,
- TNY_ACCOUNT_STORE_ACCOUNTS_RELOADED,
TNY_ACCOUNT_STORE_CONNECTING_STARTED,
- TNY_ACCOUNT_STORE_CONNECTING_FINISHED,
TNY_ACCOUNT_STORE_LAST_SIGNAL
};
@@ -80,13 +75,7 @@
TnyAccount* (*find_account_func) (TnyAccountStore *self, const gchar *url_string);
/* Signals */
- void (*account_changed) (TnyAccountStore *self, TnyAccount *account);
- void (*account_inserted) (TnyAccountStore *self, TnyAccount *account);
- void (*account_removed) (TnyAccountStore *self, TnyAccount *account);
- void (*accounts_reloaded) (TnyAccountStore *self);
-
void (*connecting_started) (TnyAccountStore *self);
- void (*connecting_finished) (TnyAccountStore *self);
};
GType tny_account_store_get_type (void);
Index: libtinymail/tny-combined-account.c
===================================================================
--- libtinymail/tny-combined-account.c (revision 2535)
+++ libtinymail/tny-combined-account.c (working copy)
@@ -322,7 +322,40 @@
tny_folder_store_remove_observer (TNY_FOLDER_STORE (priv->store_account), observer);
}
+static void
+tny_combined_account_start_operation (TnyAccount *self, TnyStatusDomain domain, TnyStatusCode code, TnyStatusCallback status_callback, gpointer status_user_data)
+{
+ TnyCombinedAccountPriv *priv = TNY_COMBINED_ACCOUNT_GET_PRIVATE (self);
+ tny_account_start_operation (TNY_ACCOUNT (priv->store_account), domain, code, status_callback, status_user_data);
+
+ return;
+}
+
+static void
+tny_combined_account_stop_operation (TnyAccount *self, gboolean *canceled)
+{
+ TnyCombinedAccountPriv *priv = TNY_COMBINED_ACCOUNT_GET_PRIVATE (self);
+
+ tny_account_stop_operation (TNY_ACCOUNT (priv->store_account), canceled);
+
+ return;
+}
+
+static gboolean
+tny_combined_account_is_ready (TnyAccount *self)
+{
+ TnyCombinedAccountPriv *priv = TNY_COMBINED_ACCOUNT_GET_PRIVATE (self);
+ gboolean retval = FALSE;
+
+ if (tny_account_is_ready (TNY_ACCOUNT (priv->store_account)) &&
+ tny_account_is_ready (TNY_ACCOUNT (priv->transport_account))) {
+ retval = TRUE;
+ }
+ return retval;
+}
+
+
static void
on_subscription_changed_signal (TnyStoreAccount *sa, TnyFolder *folder, gpointer user_data)
{
@@ -473,6 +506,9 @@
klass->get_account_type_func = tny_combined_account_get_account_type;
klass->cancel_func = tny_combined_account_cancel;
klass->matches_url_string_func = tny_combined_account_matches_url_string;
+ klass->start_operation_func = tny_combined_account_start_operation;
+ klass->stop_operation_func = tny_combined_account_stop_operation;
+ klass->is_ready_func = tny_combined_account_is_ready;
}
Index: libtinymail/tny-account.c
===================================================================
--- libtinymail/tny-account.c (revision 2535)
+++ libtinymail/tny-account.c (working copy)
@@ -32,6 +32,35 @@
/**
+ * tny_account_is_ready:
+ * @self: a #TnyAccount object
+ *
+ * Some implementations of #TnyAccount need registration in a subsystem or
+ * factory before they are not only valid instances, but also ready to use. For
+ * example before their connection-status-changed signal emissions are accurate.
+ * This boolean property will tell you if @self is ready for that.
+ *
+ * Return value: whether @self is ready for use
+ **/
+gboolean
+tny_account_is_ready (TnyAccount *self)
+{
+ gboolean retval = FALSE;
+
+#ifdef DBC /* require */
+ g_assert (TNY_IS_ACCOUNT (self));
+ g_assert (TNY_ACCOUNT_GET_IFACE (self)->is_ready_func != NULL);
+#endif
+
+ retval = TNY_ACCOUNT_GET_IFACE (self)->is_ready_func (self);
+
+#ifdef DBC /* ensure*/
+#endif
+
+ return retval;
+}
+
+/**
* tny_account_start_operation:
* @self: a #TnyAccount object
* @domain: the domain of the #TnyStatus instances that will happen in @status_callback
Index: libtinymail/tny-account.h
===================================================================
--- libtinymail/tny-account.h (revision 2535)
+++ libtinymail/tny-account.h (working copy)
@@ -102,6 +102,7 @@
gboolean (*matches_url_string_func) (TnyAccount *self, const gchar *url_string);
void (*start_operation_func) (TnyAccount *self, TnyStatusDomain domain, TnyStatusCode code, TnyStatusCallback status_callback, gpointer status_user_data);
void (*stop_operation_func) (TnyAccount *self, gboolean *canceled);
+ gboolean (*is_ready_func) (TnyAccount *self);
/* Signals*/
void (*connection_status_changed) (TnyAccount *self, TnyConnectionStatus status);
@@ -136,7 +137,9 @@
gboolean tny_account_matches_url_string (TnyAccount *self, const gchar *url_string);
void tny_account_start_operation (TnyAccount *self, TnyStatusDomain domain, TnyStatusCode code, TnyStatusCallback status_callback, gpointer status_user_data);
void tny_account_stop_operation (TnyAccount *self, gboolean *canceled);
+gboolean tny_account_is_ready (TnyAccount *self);
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]