From: Sergio Villar Senin Date: Sun, 29 Jul 2007 17:25:21 +0000 (+0000) Subject: * Added some missing signal disconnections X-Git-Url: http://vcs.maemo.org/git/?a=commitdiff_plain;h=bd2cfef8f71152c3af20769c0045b18874eeee0d;p=modest * Added some missing signal disconnections * Added some missing unref's * Fixed some UI dimming rules * Moved a signal disconnection from finalize to dispose * Fixed the problem of signal disconnections when the MainView is closed * Added a handler that clears the header view if the account is removed * Account Management rewritten * Added some new signals to notify accounts insertions,deletions and changes * Removed the old notification stuff * ModestTnyAccountStore rewritten * Accounts are inserted and deleted one by one * Improved the MMC account management * Uses TnyList instead of GSList * Removed several functions due to code refactoring * Added the proper handlers to the new ModestAccountMgr signals * Moved some account functions to their proper places * Improved ModestConf notification system * Removed the fake notifications in ModestConf * Rewritten the ModestTnyLocalFoldersAccount * Added handlers to ModestFolderView to track account changes * Added handlers to ModestHeaderView to track account changes * Added several proper signal handler connection status detection (no longer uses "> 0") * Added some missing checks in the ModestTnySendQueue * TODO: * check that the gconf changes are really working * account changes are still not detected (think about how to do it, without having to listen for gconf changes) * The MainView paned position is not persistent pmo-sessionwork-r2838 --- diff --git a/src/dbus_api/modest-dbus-callbacks.c b/src/dbus_api/modest-dbus-callbacks.c index 6ab191d..619a706 100644 --- a/src/dbus_api/modest-dbus-callbacks.c +++ b/src/dbus_api/modest-dbus-callbacks.c @@ -1357,8 +1357,7 @@ on_dbus_method_get_folders (DBusConnection *con, DBusMessage *message) * TODO: This is not working. It seems to get only the Merged Folder (with an ID of "" (not NULL)). */ TnyAccount *account_local = - modest_tny_account_store_get_local_folders_account ( - TNY_ACCOUNT_STORE (modest_runtime_get_account_store())); + modest_tny_account_store_get_local_folders_account (modest_runtime_get_account_store()); add_folders_to_list (TNY_FOLDER_STORE (account_local), &folder_names); g_object_unref (account_local); diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 8f7f969..f97cdbf 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -78,16 +78,21 @@ #define YSPACE 0 /* 'private'/'protected' functions */ -static void modest_main_window_class_init (ModestMainWindowClass *klass); -static void modest_main_window_init (ModestMainWindow *obj); -static void modest_main_window_finalize (GObject *obj); +static void modest_main_window_class_init (ModestMainWindowClass *klass); +static void modest_main_window_init (ModestMainWindow *obj); +static void modest_main_window_finalize (GObject *obj); + static gboolean modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata); static void connect_signals (ModestMainWindow *self); -static void restore_settings (ModestMainWindow *self, gboolean do_folder_view_too); +static void modest_main_window_disconnect_signals (ModestWindow *self); + +static void restore_settings (ModestMainWindow *self, + gboolean do_folder_view_too); + static void save_state (ModestWindow *self); static void modest_main_window_show_toolbar (ModestWindow *window, @@ -96,14 +101,14 @@ static void modest_main_window_show_toolbar (ModestWindow *window, static void cancel_progressbar (GtkToolButton *toolbutton, ModestMainWindow *self); -static void on_queue_changed (ModestMailOperationQueue *queue, - ModestMailOperation *mail_op, - ModestMailOperationQueueNotification type, - ModestMainWindow *self); +static void on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestMainWindow *self); static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window); -static void account_number_changed (TnyAccountStore *account_store, +static void account_number_changed (TnyAccountStore *account_store, const gchar *account_name, gpointer user_data); @@ -113,7 +118,8 @@ static gboolean on_inner_widgets_key_pressed (GtkWidget *widget, static void on_configuration_key_changed (ModestConf* conf, const gchar *key, - ModestConfEvent event, + ModestConfEvent event, + ModestConfNotificationId id, ModestMainWindow *self); static void set_toolbar_mode (ModestMainWindow *self, @@ -172,8 +178,8 @@ struct _ModestMainWindowPrivate { GtkWidget *empty_view; /* Progress observers */ - GtkWidget *progress_bar; - GSList *progress_widgets; + GtkWidget *progress_bar; + GSList *progress_widgets; /* Tollbar items */ GtkWidget *progress_toolitem; @@ -206,6 +212,8 @@ struct _ModestMainWindowPrivate { /* Signal handler UIDs */ gint queue_changed_handler_uid; GList *queue_err_signals; + + ModestConfNotificationId notification_id; }; #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_MAIN_WINDOW, \ @@ -299,6 +307,7 @@ modest_main_window_class_init (ModestMainWindowClass *klass) modest_window_class->save_state_func = save_state; modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented; modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented; + modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals; } static void @@ -337,6 +346,10 @@ modest_main_window_finalize (GObject *obj) priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj); + /* Sanity check: shouldn't be needed, the window mgr should + call this function before */ + modest_main_window_disconnect_signals (MODEST_WINDOW (obj)); + modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj); g_slist_free (priv->progress_widgets); @@ -348,10 +361,11 @@ modest_main_window_finalize (GObject *obj) priv->progress_bar_timeout = 0; } - /* Disconnect signal handlers */ - if (priv->queue_changed_handler_uid) - g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (), - priv->queue_changed_handler_uid); + if (priv->notification_id) { + modest_conf_forget_namespace (modest_runtime_get_conf (), + MODEST_CONF_NAMESPACE, + priv->notification_id); + } G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -626,6 +640,20 @@ _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data) } static void +modest_main_window_disconnect_signals (ModestWindow *self) +{ + ModestMainWindowPrivate *priv; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); + + /* Disconnect signal handlers */ + if (g_signal_handler_is_connected (modest_runtime_get_mail_operation_queue (), + priv->queue_changed_handler_uid)) + g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (), + priv->queue_changed_handler_uid); +} + +static void connect_signals (ModestMainWindow *self) { ModestWindowPrivate *parent_priv; @@ -673,7 +701,6 @@ connect_signals (ModestMainWindow *self) self); /* window */ -/* g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */ g_signal_connect (G_OBJECT (self), "window-state-event", G_CALLBACK (modest_main_window_window_state_event), NULL); @@ -684,6 +711,8 @@ connect_signals (ModestMainWindow *self) "queue-changed", G_CALLBACK (on_queue_changed), self); /* Track changes in the device name */ + priv->notification_id = modest_conf_listen_to_namespace (modest_runtime_get_conf (), + MODEST_CONF_NAMESPACE); g_signal_connect (G_OBJECT(modest_runtime_get_conf ()), "key_changed", G_CALLBACK (on_configuration_key_changed), self); @@ -1860,13 +1889,16 @@ modest_main_window_get_contents_style (ModestMainWindow *self) static void on_configuration_key_changed (ModestConf* conf, const gchar *key, - ModestConfEvent event, + ModestConfEvent event, + ModestConfNotificationId id, ModestMainWindow *self) { ModestMainWindowPrivate *priv; TnyAccount *account; - if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME)) + if (!key || + priv->notification_id != id || + strcmp (key, MODEST_CONF_DEVICE_NAME)) return; priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); diff --git a/src/maemo/modest-msg-edit-window.c b/src/maemo/modest-msg-edit-window.c index 93f2c7d..c0ce270 100644 --- a/src/maemo/modest-msg-edit-window.c +++ b/src/maemo/modest-msg-edit-window.c @@ -120,7 +120,8 @@ static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button, ModestMsgEditWindow *window); /* ModestWindow methods implementation */ -static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom); +static void modest_msg_edit_window_disconnect_signals (ModestWindow *window); +static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom); static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window); static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window); static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window); @@ -320,10 +321,9 @@ modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass) modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus; modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar; modest_window_class->save_state_func = save_state; + modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals; g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate)); - - } static void @@ -554,17 +554,25 @@ init_window (ModestMsgEditWindow *obj) } +static void +modest_msg_edit_window_disconnect_signals (ModestWindow *window) +{ + ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window); + if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY), + priv->clipboard_change_handler_id)) + g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), + priv->clipboard_change_handler_id); +} static void modest_msg_edit_window_finalize (GObject *obj) { ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj); - if (priv->clipboard_change_handler_id > 0) { - g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id); - priv->clipboard_change_handler_id = 0; - } + /* Sanity check: shouldn't be needed, the window mgr should + call this function before */ + modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj)); if (priv->draft_msg != NULL) { TnyHeader *header = tny_msg_get_header (priv->draft_msg); @@ -663,7 +671,7 @@ replace_with_attachments (ModestMsgEditWindow *self, GList *attachments) g_object_unref (stream); if (pixbuf != NULL) { - wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); +/* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */ g_object_unref (pixbuf); } } diff --git a/src/maemo/modest-msg-view-window.c b/src/maemo/modest-msg-view-window.c index c02403b..2606530 100644 --- a/src/maemo/modest-msg-view-window.c +++ b/src/maemo/modest-msg-view-window.c @@ -67,8 +67,9 @@ static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget, static void modest_msg_view_window_find_toolbar_search (GtkWidget *widget, ModestMsgViewWindow *obj); -static void modest_msg_view_window_set_zoom (ModestWindow *window, - gdouble zoom); +static void modest_msg_view_window_disconnect_signals (ModestWindow *self); +static void modest_msg_view_window_set_zoom (ModestWindow *window, + gdouble zoom); static gdouble modest_msg_view_window_get_zoom (ModestWindow *window); static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window); static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window); @@ -235,6 +236,7 @@ modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass) modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus; modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus; modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar; + modest_window_class->disconnect_signals_func = modest_msg_view_window_disconnect_signals; g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate)); @@ -438,31 +440,42 @@ init_window (ModestMsgViewWindow *obj, TnyMsg *msg) priv->clipboard_change_handler = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change", G_CALLBACK (modest_msg_view_window_clipboard_owner_change), obj); gtk_widget_show_all (GTK_WIDGET(main_vbox)); - -} - +} static void -modest_msg_view_window_finalize (GObject *obj) +modest_msg_view_window_disconnect_signals (ModestWindow *self) { ModestMsgViewWindowPrivate *priv; - priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj); - if (priv->clipboard_change_handler > 0) { + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY), + priv->clipboard_change_handler)) g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler); - priv->clipboard_change_handler = 0; - } - if (priv->queue_change_handler > 0) { + + if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()), + priv->queue_change_handler)) g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), priv->queue_change_handler); - priv->queue_change_handler = 0; - } - if (priv->account_removed_handler > 0) { + + if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_account_store ()), + priv->account_removed_handler)) g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_account_store ()), priv->account_removed_handler); - priv->account_removed_handler = 0; - } +} + +static void +modest_msg_view_window_finalize (GObject *obj) +{ + ModestMsgViewWindowPrivate *priv; + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj); + + /* Sanity check: shouldn't be needed, the window mgr should + call this function before */ + modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj)); + if (priv->header_model != NULL) { g_object_unref (priv->header_model); priv->header_model = NULL; diff --git a/src/maemo/modest-platform.c b/src/maemo/modest-platform.c index 9939943..edbfee4 100644 --- a/src/maemo/modest-platform.c +++ b/src/maemo/modest-platform.c @@ -63,8 +63,11 @@ static void folder_name_insensitive_press (GtkWidget *widget, ModestWindow *window); static void -on_modest_conf_update_interval_changed (ModestConf* self, const gchar *key, - ModestConfEvent event, gpointer user_data) +on_modest_conf_update_interval_changed (ModestConf* self, + const gchar *key, + ModestConfEvent event, + ModestConfNotificationId id, + gpointer user_data) { if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) { const guint update_interval_minutes = @@ -143,7 +146,13 @@ modest_platform_init (int argc, char *argv[]) /* Make sure that the update interval is changed whenever its gconf key - * is changed: */ + * is changed */ + /* CAUTION: we're not using here the + modest_conf_listen_to_namespace because we know that there + are other parts of Modest listening for this namespace, so + we'll receive the notifications anyway. We basically do not + use it because there is no easy way to do the + modest_conf_forget_namespace */ ModestConf *conf = modest_runtime_get_conf (); g_signal_connect (G_OBJECT(conf), "key_changed", @@ -152,7 +161,7 @@ modest_platform_init (int argc, char *argv[]) /* Get the initial update interval from gconf: */ on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL, - MODEST_CONF_EVENT_KEY_CHANGED, NULL); + MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL); /* initialize the addressbook */ if (!osso_abook_init (&argc, &argv, osso_context)) { diff --git a/src/modest-account-mgr-priv.h b/src/modest-account-mgr-priv.h index cc40a1d..54beffb 100644 --- a/src/modest-account-mgr-priv.h +++ b/src/modest-account-mgr-priv.h @@ -51,10 +51,10 @@ struct _ModestAccountMgrPrivate { ModestConf *modest_conf; /* We store these as they change, and send notifications every X seconds: */ - GSList *changed_conf_keys; - guint timeout; gulong key_changed_handler_uid; GSList* busy_accounts; + + GHashTable *notification_id_accounts; }; #define MODEST_ACCOUNT_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ diff --git a/src/modest-account-mgr.c b/src/modest-account-mgr.c index 5826c61..624bff0 100644 --- a/src/modest-account-mgr.c +++ b/src/modest-account-mgr.c @@ -237,7 +237,8 @@ modest_account_mgr_init (ModestAccountMgr * obj) priv->modest_conf = NULL; priv->busy_accounts = NULL; -/* priv->timeout = g_timeout_add (1000 /\* milliseconds *\/, on_timeout_notify_changes, obj); */ + + priv->notification_id_accounts = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); } static void @@ -246,6 +247,12 @@ modest_account_mgr_finalize (GObject * obj) ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj); + if (priv->notification_id_accounts) { + /* TODO: forget dirs */ + + g_hash_table_destroy (priv->notification_id_accounts); + } + if (priv->key_changed_handler_uid) { g_signal_handler_disconnect (priv->modest_conf, priv->key_changed_handler_uid); @@ -260,10 +267,10 @@ modest_account_mgr_finalize (GObject * obj) /* if (priv->timeout) */ /* g_source_remove (priv->timeout); */ - if (priv->changed_conf_keys) { - g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); - g_slist_free (priv->changed_conf_keys); - } +/* if (priv->changed_conf_keys) { */ +/* g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); */ +/* g_slist_free (priv->changed_conf_keys); */ +/* } */ G_OBJECT_CLASS(parent_class)->finalize (obj); } diff --git a/src/modest-conf.c b/src/modest-conf.c index 9b2d95f..767f5b9 100644 --- a/src/modest-conf.c +++ b/src/modest-conf.c @@ -36,17 +36,17 @@ #include static void modest_conf_class_init (ModestConfClass *klass); + static void modest_conf_init (ModestConf *obj); + static void modest_conf_finalize (GObject *obj); + static void modest_conf_on_change (GConfClient *client, guint conn_id, GConfEntry *entry, gpointer data); + static GConfValueType modest_conf_type_to_gconf_type (ModestConfValueType value_type, GError **err); - -static void -modest_conf_maemo_fake_on_change (ModestConf *conf, const gchar* key, ModestConfEvent event); - /* list my signals */ enum { KEY_CHANGED_SIGNAL, @@ -106,8 +106,8 @@ modest_conf_class_init (ModestConfClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (ModestConfClass,key_changed), NULL, NULL, - modest_marshal_VOID__STRING_INT, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT); + modest_marshal_VOID__STRING_INT_INT, + G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT); } static void @@ -115,7 +115,7 @@ modest_conf_init (ModestConf *obj) { GConfClient *conf = NULL; ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(obj); - GError *err = NULL; +/* GError *err = NULL; */ priv->gconf_client = NULL; @@ -125,27 +125,27 @@ modest_conf_init (ModestConf *obj) g_printerr ("modest: could not get gconf client\n"); return; } - gconf_client_add_dir (conf,MODEST_CONF_NAMESPACE, - GCONF_CLIENT_PRELOAD_NONE, - &err); - if (err) { - g_printerr ("modest: error %d with gconf_client_add_dir: '%s'\n", - err->code, err->message); - g_object_unref (conf); - g_error_free (err); - return; - } +/* gconf_client_add_dir (conf,MODEST_CONF_NAMESPACE, */ +/* GCONF_CLIENT_PRELOAD_NONE, */ +/* &err); */ +/* if (err) { */ +/* g_printerr ("modest: error %d with gconf_client_add_dir: '%s'\n", */ +/* err->code, err->message); */ +/* g_object_unref (conf); */ +/* g_error_free (err); */ +/* return; */ +/* } */ - gconf_client_notify_add (conf, MODEST_CONF_NAMESPACE, - modest_conf_on_change, - obj, NULL, &err); - if (err) { - g_printerr ("modest: gconf_client_notify_add error %d: '%s'\n", - err->code, err->message); - g_object_unref (conf); - g_error_free (err); - return; - } +/* gconf_client_notify_add (conf, MODEST_CONF_NAMESPACE, */ +/* modest_conf_on_change, */ +/* obj, NULL, &err); */ +/* if (err) { */ +/* g_printerr ("modest: gconf_client_notify_add error %d: '%s'\n", */ +/* err->code, err->message); */ +/* g_object_unref (conf); */ +/* g_error_free (err); */ +/* return; */ +/* } */ priv->gconf_client = conf; /* all went well! */ } @@ -265,14 +265,9 @@ modest_conf_set_string (ModestConf* self, const gchar* key, const gchar* val, return FALSE; } - if (gconf_client_set_string (priv->gconf_client, key, val, err)) { - modest_conf_maemo_fake_on_change (self, key, MODEST_CONF_EVENT_KEY_CHANGED); - return TRUE; - } else - return FALSE; + return gconf_client_set_string (priv->gconf_client, key, val, err); } - gboolean modest_conf_set_int (ModestConf* self, const gchar* key, gint val, GError **err) @@ -289,11 +284,7 @@ modest_conf_set_int (ModestConf* self, const gchar* key, gint val, return FALSE; } - if (gconf_client_set_int (priv->gconf_client, key, val, err)) { - modest_conf_maemo_fake_on_change (self, key, MODEST_CONF_EVENT_KEY_CHANGED); - return TRUE; - } else - return FALSE; + return gconf_client_set_int (priv->gconf_client, key, val, err); } @@ -313,11 +304,7 @@ modest_conf_set_bool (ModestConf* self, const gchar* key, gboolean val, return FALSE; } - if (gconf_client_set_bool (priv->gconf_client, key, val, err)) { - modest_conf_maemo_fake_on_change (self, key, MODEST_CONF_EVENT_KEY_CHANGED); - return TRUE; - } else - return FALSE; + return gconf_client_set_bool (priv->gconf_client, key, val, err); } @@ -359,9 +346,6 @@ modest_conf_set_list (ModestConf* self, const gchar* key, "We think that we fixed this, so tell us if you see this.", key); g_slist_free(debug_list); } - - if (result) - modest_conf_maemo_fake_on_change (self, key, MODEST_CONF_EVENT_KEY_CHANGED); return result; } @@ -395,11 +379,7 @@ modest_conf_remove_key (ModestConf* self, const gchar* key, GError **err) retval = gconf_client_recursive_unset (priv->gconf_client,key,0,err); gconf_client_suggest_sync (priv->gconf_client, NULL); - if (retval) { - modest_conf_maemo_fake_on_change (self, key, MODEST_CONF_EVENT_KEY_UNSET); - return TRUE; - } else - return FALSE; + return retval; } @@ -452,9 +432,10 @@ modest_conf_key_is_valid (const gchar* key) return gconf_valid_key (key, NULL); } -/* hmmm... might need to make specific callback for specific keys */ static void -modest_conf_on_change (GConfClient *client, guint conn_id, GConfEntry *entry, +modest_conf_on_change (GConfClient *client, + guint conn_id, + GConfEntry *entry, gpointer data) { ModestConfEvent event; @@ -465,7 +446,7 @@ modest_conf_on_change (GConfClient *client, guint conn_id, GConfEntry *entry, g_signal_emit (G_OBJECT(data), signals[KEY_CHANGED_SIGNAL], 0, - key, event); + key, event, conn_id); } @@ -496,77 +477,57 @@ modest_conf_type_to_gconf_type (ModestConfValueType value_type, GError **err) return gconf_type; } +ModestConfNotificationId +modest_conf_listen_to_namespace (ModestConf *self, + const gchar *namespace) +{ + ModestConfPrivate *priv; + GError *error = NULL; + ModestConfNotificationId notification_id; + g_return_val_if_fail (MODEST_IS_CONF (self), 0); + g_return_val_if_fail (namespace, 0); + + priv = MODEST_CONF_GET_PRIVATE(self); -//////////////////////////////////////////////////////////////////////////////// -/* workaround for the b0rked dbus-gconf on maemo */ -/* fires a fake change notification after 0.3 secs. - * Might not be necessary anymore. */ -#if 0 -#ifdef MODEST_PLATFORM_MAEMO -typedef struct { - GObject *obj; - gchar *key; -} ChangeHelper; - -ChangeHelper* -change_helper_new (ModestConf *conf, const gchar *key) -{ - ChangeHelper *helper = g_slice_alloc (sizeof(ChangeHelper)); - helper->obj = g_object_ref(G_OBJECT(conf)); - helper->key = g_strdup (key); - return helper; + /* Add the namespace to the list of the namespaces that will + be observed */ + gconf_client_add_dir (priv->gconf_client, namespace, + GCONF_CLIENT_PRELOAD_NONE, + &error); + + if (error) + return 0; + + /* Notify every change under namespace */ + notification_id = gconf_client_notify_add (priv->gconf_client, + namespace, + modest_conf_on_change, + self, + NULL, + &error); + if (error) + return 0; + else + return notification_id; } -static void -change_helper_free (ChangeHelper *helper) +void +modest_conf_forget_namespace (ModestConf *self, + const gchar *namespace, + ModestConfNotificationId id) { - g_object_unref (helper->obj); - g_free (helper->key); - helper->key = NULL; - helper->obj = NULL; - g_slice_free (ChangeHelper,helper); -} + ModestConfPrivate *priv; -static gboolean -emit_change_cb (ChangeHelper *helper) -{ - if (!helper) - return FALSE; - g_signal_emit (G_OBJECT(helper->obj),signals[KEY_CHANGED_SIGNAL], 0, - helper->key, MODEST_CONF_EVENT_KEY_CHANGED); - change_helper_free (helper); + g_return_if_fail (MODEST_IS_CONF (self)); + g_return_if_fail (namespace); - return FALSE; -} + priv = MODEST_CONF_GET_PRIVATE(self); -static gboolean -emit_remove_cb (ChangeHelper *helper) -{ - if (!helper) - return FALSE; - g_signal_emit (G_OBJECT(helper->obj),signals[KEY_CHANGED_SIGNAL], 0, - helper->key, MODEST_CONF_EVENT_KEY_UNSET); - change_helper_free (helper); - - return FALSE; -} -#endif /* MODEST_PLATFORM_MAEMO */ -#endif - -static void -modest_conf_maemo_fake_on_change (ModestConf *conf, const gchar* key, ModestConfEvent event) -{ -/* hack for faster notification, might not be necessary anymore: */ -#if 0 -#ifdef MODEST_PLATFORM_MAEMO - - ChangeHelper *helper = change_helper_new (conf,key); - g_timeout_add (100, /* after 100 ms */ - (event == MODEST_CONF_EVENT_KEY_CHANGED) - ? (GSourceFunc)emit_change_cb : (GSourceFunc)emit_remove_cb, - (gpointer)helper); -#endif /* MODEST_PLATFORM_MAEMO */ -#endif + /* Remove the namespace to the list of the namespaces that will + be observed */ + gconf_client_remove_dir (priv->gconf_client, namespace, NULL); + + /* Notify every change under namespace */ + gconf_client_notify_remove (priv->gconf_client, id); } -////////////////////////////////////////////////////////////////////////////////// diff --git a/src/modest-conf.h b/src/modest-conf.h index 0008272..e2bf25a 100644 --- a/src/modest-conf.h +++ b/src/modest-conf.h @@ -46,6 +46,8 @@ G_BEGIN_DECLS typedef struct _ModestConf ModestConf; typedef struct _ModestConfClass ModestConfClass; +typedef guint ModestConfNotificationId; + typedef enum { MODEST_CONF_VALUE_INT, MODEST_CONF_VALUE_BOOL, @@ -64,7 +66,10 @@ struct _ModestConf { struct _ModestConfClass { GObjectClass parent_class; - void (* key_changed) (ModestConf* self, const gchar *key, ModestConfEvent event); + void (* key_changed) (ModestConf* self, + const gchar *key, + ModestConfEvent event, + ModestConfNotificationId id); }; /** @@ -295,6 +300,13 @@ gchar* modest_conf_key_escape (const gchar* str); gchar* modest_conf_key_unescape (const gchar* str); +ModestConfNotificationId modest_conf_listen_to_namespace (ModestConf *self, + const gchar *namespace); + +void modest_conf_forget_namespace (ModestConf *self, + const gchar *namespace, + ModestConfNotificationId id); + G_END_DECLS #endif /* __MODEST_CONF_H__ */ diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index 4d16d48..bea626a 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -1732,8 +1732,8 @@ new_name_valid_if_local_account (ModestMailOperationPrivate *priv, { if (TNY_IS_ACCOUNT (into) && modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) && - modest_tny_local_folders_account_extra_folder_exists (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into), - new_name)) { + modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into), + new_name)) { priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES, @@ -2616,7 +2616,6 @@ on_refresh_folder (TnyFolder *folder, } /* Free */ -/* g_object_unref (helper->mail_op); */ g_slice_free (RefreshAsyncHelper, helper); /* Notify about operation end */ @@ -2675,7 +2674,7 @@ modest_mail_operation_refresh_folder (ModestMailOperation *self, /* Create the helper */ helper = g_slice_new0 (RefreshAsyncHelper); - helper->mail_op = g_object_ref (self); + helper->mail_op = self; helper->user_callback = user_callback; helper->user_data = user_data; diff --git a/src/modest-tny-account-store.c b/src/modest-tny-account-store.c index c416442..5d4ea55 100644 --- a/src/modest-tny-account-store.c +++ b/src/modest-tny-account-store.c @@ -83,18 +83,39 @@ static void modest_tny_account_store_init (gpointer g, gpointer ifac static void modest_tny_account_store_base_init (gpointer g_class); -static void get_server_accounts (TnyAccountStore *self, - TnyList *list, - TnyAccountType type); +static void on_account_inserted (ModestAccountMgr *acc_mgr, + const gchar *account, + gpointer user_data); -static void on_account_inserted (ModestAccountMgr *acc_mgr, - const gchar *account, - gpointer user_data); +static void add_existing_accounts (ModestTnyAccountStore *self); -static void on_account_removed (ModestAccountMgr *acc_mgr, - const gchar *account, - gpointer user_data); +static void insert_account (ModestTnyAccountStore *self, + const gchar *account, + gboolean notify); +static void on_account_removed (ModestAccountMgr *acc_mgr, + const gchar *account, + gpointer user_data); + +static gchar* get_password (TnyAccount *account, + const gchar * prompt_not_used, + gboolean *cancel); + +static void forget_password (TnyAccount *account); + +static void on_vfs_volume_mounted (GnomeVFSVolumeMonitor *volume_monitor, + GnomeVFSVolume *volume, + gpointer user_data); + +static void on_vfs_volume_unmounted (GnomeVFSVolumeMonitor *volume_monitor, + GnomeVFSVolume *volume, + gpointer user_data); + +static void modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, + const gchar *server_account_name); + +static void add_connection_specific_transport_accounts (ModestTnyAccountStore *self, + const gchar *account_name); /* list my signals */ enum { @@ -118,17 +139,12 @@ struct _ModestTnyAccountStorePrivate { gulong acc_inserted_handler; gulong acc_changed_handler; gulong acc_removed_handler; + gulong volume_mounted_handler; + gulong volume_unmounted_handler; - /* We cache the lists of accounts here. - * They are created in our get_accounts_func() implementation. */ + /* We cache the lists of accounts here */ TnyList *store_accounts; TnyList *transport_accounts; - - /* This is also contained in store_accounts, - * but we cached it temporarily separately, - * because we create this while creating the transport accounts, - * but return it when requesting the store accounts: - */ TnyList *store_accounts_outboxes; }; @@ -246,22 +262,14 @@ modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass) g_type_class_add_private (gobject_class, sizeof(ModestTnyAccountStorePrivate)); } - - static void -on_vfs_volume_mounted(GnomeVFSVolumeMonitor *volume_monitor, - GnomeVFSVolume *volume, gpointer user_data); - -static void -on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor, - GnomeVFSVolume *volume, gpointer user_data); - -static void modest_tny_account_store_instance_init (ModestTnyAccountStore *obj) { - ModestTnyAccountStorePrivate *priv = - MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj); + GnomeVFSVolumeMonitor* monitor = NULL; + ModestTnyAccountStorePrivate *priv; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj); priv->cache_dir = NULL; priv->account_mgr = NULL; @@ -272,24 +280,26 @@ modest_tny_account_store_instance_init (ModestTnyAccountStore *obj) * for passwords that are not remembered in the configuration, * so they need to be asked for from the user once in each session: */ - priv->password_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_free); + priv->password_hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); /* A hash-map of modest account names to dialog pointers, * so we can avoid showing the account settings twice for the same modest account: */ priv->account_settings_dialog_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); + g_free, NULL); /* Respond to volume mounts and unmounts, such * as the insertion/removal of the memory card: */ - GnomeVFSVolumeMonitor* monitor = - gnome_vfs_get_volume_monitor(); - g_signal_connect (G_OBJECT(monitor), "volume-mounted", - G_CALLBACK(on_vfs_volume_mounted), - obj); - g_signal_connect (G_OBJECT(monitor), "volume-unmounted", - G_CALLBACK(on_vfs_volume_unmounted), - obj); + monitor = gnome_vfs_get_volume_monitor(); + + priv->volume_mounted_handler = g_signal_connect (G_OBJECT(monitor), + "volume-mounted", + G_CALLBACK(on_vfs_volume_mounted), + obj); + + priv->volume_unmounted_handler = g_signal_connect (G_OBJECT(monitor), "volume-unmounted", + G_CALLBACK(on_vfs_volume_unmounted), + obj); } /* disconnect the list of TnyAccounts */ @@ -311,62 +321,40 @@ foreach_account_append_to_list (gpointer data, tny_list_append (list, G_OBJECT (data)); } - -static void -recreate_all_accounts (ModestTnyAccountStore *self) -{ - /* printf ("DEBUG: %s\n", __FUNCTION__); */ - - ModestTnyAccountStorePrivate *priv = - MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - if (priv->store_accounts_outboxes) { - g_object_unref (priv->store_accounts_outboxes); - priv->store_accounts_outboxes = NULL; - } - - - if (priv->store_accounts) { - g_object_unref (priv->store_accounts); - priv->store_accounts = NULL; - } - - get_server_accounts (TNY_ACCOUNT_STORE(self), - NULL, TNY_ACCOUNT_TYPE_STORE); - - - if (priv->transport_accounts) { - g_object_unref (priv->transport_accounts); - priv->transport_accounts = NULL; - } - - get_server_accounts (TNY_ACCOUNT_STORE(self), NULL, - TNY_ACCOUNT_TYPE_TRANSPORT); -} - +/********************************************************************/ +/* Control the state of the MMC local account */ +/********************************************************************/ static void on_vfs_volume_mounted(GnomeVFSVolumeMonitor *volume_monitor, GnomeVFSVolume *volume, gpointer user_data) { -/* ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data); */ + ModestTnyAccountStore *self; + ModestTnyAccountStorePrivate *priv; + + gchar *uri = NULL; + + self = MODEST_TNY_ACCOUNT_STORE(user_data); + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); /* Check whether this was the external MMC1 card: */ - gchar *uri = gnome_vfs_volume_get_activation_uri (volume); - if (uri && (strcmp (uri, MODEST_MCC1_VOLUMEPATH_URI) == 0)) { - printf ("DEBUG: %s: MMC1 card mounted.\n", __FUNCTION__); - -/* /\* TODO: Just add an account and emit (and respond to) */ -/* * TnyAccountStore::accountinserted signal? */ -/* *\/ */ -/* recreate_all_accounts (self); */ - - /* TODO */ -/* g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, */ -/* NULL); */ -/* g_signal_emit (G_OBJECT (self), */ -/* signals [ACCOUNT_INSERTED_SIGNAL], */ -/* 0, mmc_account); */ + uri = gnome_vfs_volume_get_activation_uri (volume); + + if (uri && (!strcmp (uri, MODEST_MCC1_VOLUMEPATH_URI))) { + TnyAccount *mmc_account; + + mmc_account = modest_tny_account_new_for_local_folders (priv->account_mgr, + priv->session, + MODEST_MCC1_VOLUMEPATH); + + /* Add to the list of store accounts */ + tny_list_append (priv->store_accounts, G_OBJECT (mmc_account)); + + g_signal_emit (G_OBJECT (self), + signals [ACCOUNT_INSERTED_SIGNAL], + 0, mmc_account); + /* Free */ + g_object_unref (mmc_account); } g_free (uri); } @@ -376,96 +364,50 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor, GnomeVFSVolume *volume, gpointer user_data) { -/* ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data); */ - - /* Check whether this was the external MMC1 card: */ - gchar *uri = gnome_vfs_volume_get_activation_uri (volume); - if (uri && (strcmp (uri, MODEST_MCC1_VOLUMEPATH_URI) == 0)) { - printf ("DEBUG: %s: MMC1 card unmounted.\n", __FUNCTION__); - -/* /\* TODO: Just add an account and emit (and respond to) */ -/* * TnyAccountStore::accountinserted signal? */ -/* *\/ */ -/* recreate_all_accounts (self); */ - -/* g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, */ -/* NULL); */ - - /* TODO */ -/* g_signal_emit (G_OBJECT (self), */ -/* signals [ACCOUNT_REMOVED_SIGNAL], */ -/* 0, mmc_account); */ - } - g_free (uri); -} + ModestTnyAccountStore *self; + ModestTnyAccountStorePrivate *priv; + gchar *uri = NULL; -static void -on_account_inserted (ModestAccountMgr *acc_mgr, - const gchar *account, - gpointer user_data) -{ - ModestTnyAccountStorePrivate *priv = NULL; - TnyAccount *store_account = NULL, *transport_account = NULL; - ModestTnyAccountStore *self = NULL; - self = MODEST_TNY_ACCOUNT_STORE(user_data); priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + /* Check whether this was the external MMC1 card: */ + uri = gnome_vfs_volume_get_activation_uri (volume); + if (uri && (strcmp (uri, MODEST_MCC1_VOLUMEPATH_URI) == 0)) { + TnyAccount *mmc_account = NULL; + gboolean found = FALSE; + TnyIterator *iter = NULL; - /* Get the server and the transport account */ - store_account = - modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_STORE); - transport_account = - modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_TRANSPORT); - - /* Add to the cached accounts */ - tny_list_prepend (priv->store_accounts, G_OBJECT (store_account)); - tny_list_prepend (priv->transport_accounts, G_OBJECT (transport_account)); - - /* Notify the observers */ - g_signal_emit (G_OBJECT (self), signals [ACCOUNT_INSERTED_SIGNAL], 0, store_account); - g_signal_emit (G_OBJECT (self), signals [ACCOUNT_INSERTED_SIGNAL], 0, transport_account); + iter = tny_list_create_iterator (priv->store_accounts); + while (!tny_iterator_is_done (iter) && !found) { + TnyAccount *account; - /* Frees */ - g_object_unref (store_account); - g_object_unref (transport_account); -} - -static void -on_account_removed (ModestAccountMgr *acc_mgr, - const gchar *account, - gpointer user_data) -{ - TnyAccount *store_account = NULL, *transport_account = NULL; - ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data); - - /* Get the server and the transport account */ - store_account = - modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_STORE); - transport_account = - modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_TRANSPORT); + account = TNY_ACCOUNT (tny_iterator_get_current (iter)); + if (modest_tny_account_is_memory_card_account (account)) { + found = TRUE; + mmc_account = g_object_ref (account); + } + g_object_unref (account); + tny_iterator_next (iter); + } + g_object_unref (iter); - /* If there was any problem creating the account, for example, - with the configuration system this could not exist */ - if (store_account) { - /* Clear the cache */ - tny_store_account_delete_cache (TNY_STORE_ACCOUNT (store_account)); + if (found) { + /* Remove from the list */ + tny_list_remove (priv->store_accounts, G_OBJECT (mmc_account)); - /* Notify the observers */ - g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, store_account); - g_object_unref (store_account); - } else { - g_warning ("There is no store account for account %s\n", account); - } + /* Notify observers */ + g_signal_emit (G_OBJECT (self), + signals [ACCOUNT_REMOVED_SIGNAL], + 0, mmc_account); - /* If there was any problem creating the account, for example, - with the configuration system this could not exist */ - if (transport_account) { - /* Notify the observers */ - g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, transport_account); - g_object_unref (transport_account); - } else { - g_warning ("There is no transport account for account %s\n", account); + g_object_unref (mmc_account); + } else { + g_warning ("%s: there was no store account for the unmounted MMC", + __FUNCTION__); + } } + g_free (uri); } /** @@ -513,7 +455,7 @@ on_account_changed (ModestAccountMgr *acc_mgr, /* FIXME: make this more finegrained; changes do not really affect _all_ * accounts */ - recreate_all_accounts (self); +/* recreate_all_accounts (self); */ /* TODO: This doesn't actually work, because * a) The account name is not sent correctly per key: @@ -529,20 +471,11 @@ on_account_changed (ModestAccountMgr *acc_mgr, } #endif -/* g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, */ -/* account); */ -} - - -static ModestTnyAccountStore* -get_account_store_for_account (TnyAccount *account) -{ - return MODEST_TNY_ACCOUNT_STORE(g_object_get_data (G_OBJECT(account), - "account_store")); + g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0, account); } -static -void on_account_settings_hide (GtkWidget *widget, gpointer user_data) +static void +on_account_settings_hide (GtkWidget *widget, gpointer user_data) { TnyAccount *account = (TnyAccount*)user_data; @@ -556,8 +489,8 @@ void on_account_settings_hide (GtkWidget *widget, gpointer user_data) g_hash_table_remove (priv->account_settings_dialog_hash, modest_account_name); } -static -gboolean on_idle_wrong_password_warning_only (gpointer user_data) +static gboolean +on_idle_wrong_password_warning_only (gpointer user_data) { gdk_threads_enter(); @@ -573,8 +506,8 @@ gboolean on_idle_wrong_password_warning_only (gpointer user_data) return FALSE; /* Don't show again. */ } -static -gboolean on_idle_wrong_password (gpointer user_data) +static gboolean +on_idle_wrong_password (gpointer user_data) { TnyAccount *account = (TnyAccount*)user_data; /* This is easier than using a struct for the user_data: */ @@ -736,7 +669,8 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc *cancel = FALSE; const gchar *server_account_name = tny_account_get_id (account); - account_store = TNY_ACCOUNT_STORE(get_account_store_for_account (account)); + account_store = TNY_ACCOUNT_STORE(g_object_get_data (G_OBJECT(account), + "account_store")); if (!server_account_name || !account_store) { g_warning ("modest: %s: could not retrieve account_store for account %s", @@ -857,7 +791,8 @@ forget_password (TnyAccount *account) gchar *pwd; const gchar *key; - account_store = TNY_ACCOUNT_STORE(get_account_store_for_account (account)); + account_store = TNY_ACCOUNT_STORE(g_object_get_data (G_OBJECT(account), + "account_store")); self = MODEST_TNY_ACCOUNT_STORE (account_store); priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); key = tny_account_get_id (account); @@ -878,26 +813,11 @@ forget_password (TnyAccount *account) } static void -destroy_password_hashtable (ModestTnyAccountStore *self) -{ - ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - g_free (priv->cache_dir); - priv->cache_dir = NULL; - - if (priv->password_hash) { - g_hash_table_destroy (priv->password_hash); - priv->password_hash = NULL; - } -} - -static void modest_tny_account_store_finalize (GObject *obj) { + GnomeVFSVolumeMonitor *volume_monitor; ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(obj); ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - //gboolean debug = modest_runtime_get_debug_flags() & MODEST_RUNTIME_DEBUG_DEBUG_OBJECTS; g_free (priv->cache_dir); priv->cache_dir = NULL; @@ -906,8 +826,17 @@ modest_tny_account_store_finalize (GObject *obj) g_hash_table_destroy (priv->password_hash); priv->password_hash = NULL; } - - destroy_password_hashtable (self); + + /* Disconnect VFS signals */ + volume_monitor = gnome_vfs_get_volume_monitor (); + if (g_signal_handler_is_connected (volume_monitor, + priv->volume_mounted_handler)) + g_signal_handler_disconnect (volume_monitor, + priv->volume_mounted_handler); + if (g_signal_handler_is_connected (volume_monitor, + priv->volume_unmounted_handler)) + g_signal_handler_disconnect (volume_monitor, + priv->volume_unmounted_handler); if (priv->account_mgr) { /* Disconnect signals */ @@ -945,6 +874,11 @@ modest_tny_account_store_finalize (GObject *obj) g_object_unref (priv->transport_accounts); priv->transport_accounts = NULL; } + + if (priv->store_accounts_outboxes) { + g_object_unref (priv->store_accounts_outboxes); + priv->store_accounts_outboxes = NULL; + } if (priv->session) { camel_object_unref (CAMEL_OBJECT(priv->session)); @@ -956,11 +890,12 @@ modest_tny_account_store_finalize (GObject *obj) ModestTnyAccountStore* -modest_tny_account_store_new (ModestAccountMgr *account_mgr, TnyDevice *device) { - +modest_tny_account_store_new (ModestAccountMgr *account_mgr, + TnyDevice *device) +{ GObject *obj; ModestTnyAccountStorePrivate *priv; -// TnyList *list; + TnyAccount *local_account = NULL; g_return_val_if_fail (account_mgr, NULL); g_return_val_if_fail (device, NULL); @@ -988,266 +923,28 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr, TnyDevice *device) priv->acc_removed_handler = g_signal_connect (G_OBJECT(account_mgr), "account_removed", G_CALLBACK (on_account_removed), obj); - return MODEST_TNY_ACCOUNT_STORE(obj); -} + /* Create the lists of accounts */ + priv->store_accounts = tny_simple_list_new (); + priv->transport_accounts = tny_simple_list_new (); + priv->store_accounts_outboxes = tny_simple_list_new (); -/** Fill the TnyList from the appropriate cached GSList of accounts. */ -static void -get_cached_accounts (TnyAccountStore *self, TnyList *list, TnyAccountType type) -{ - ModestTnyAccountStorePrivate *priv = NULL; - TnyList *accounts = NULL; - - priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self); - accounts = (type == TNY_ACCOUNT_TYPE_STORE) ? priv->store_accounts : priv->transport_accounts; + /* Create the local folders account */ + local_account = + modest_tny_account_new_for_local_folders (priv->account_mgr, priv->session, NULL); + tny_list_append (priv->store_accounts, G_OBJECT(local_account)); + g_object_unref (local_account); - /* Add accounts to the list */ - tny_list_foreach (accounts, foreach_account_append_to_list, list); -} + /* Add the other remote accounts. Do this before adding the + local account, because we need to add our outboxes to the + global OUTBOX hosted in the local account */ + add_existing_accounts (MODEST_TNY_ACCOUNT_STORE (obj)); -static void -create_per_account_local_outbox_folders (TnyAccountStore *self) -{ - ModestTnyAccountStorePrivate *priv; - TnyList *accounts = NULL; - GSList *account_names = NULL, *iter = NULL; - - g_return_if_fail (self); - - priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - /* including disabled accounts */ - account_names = modest_account_mgr_account_names (priv->account_mgr, TRUE); - - accounts = tny_simple_list_new (); - for (iter = account_names; iter; iter = g_slist_next (iter)) { - TnyAccount *tny_account_outbox = NULL; - const gchar* account_name = (const gchar*)iter->data; - - /* Create a per-account local outbox folder (a _store_ account) - * for each _transport_ account: */ - tny_account_outbox = - modest_tny_account_new_for_per_account_local_outbox_folder (priv->account_mgr, - account_name, - priv->session); - /* Cache it */ - tny_list_append (accounts, G_OBJECT (tny_account_outbox)); - g_object_unref (tny_account_outbox); - }; - - /* Free and save */ - modest_account_mgr_free_account_names (account_names); - priv->store_accounts_outboxes = accounts; -} - -/* This function fills the TnyList, and also stores a GSList of the accounts, - * for caching purposes. It creates the TnyAccount objects if necessary. - * The @list parameter may be NULL, if you just want to fill the cache. - */ -static void -get_server_accounts (TnyAccountStore *self, TnyList *list, TnyAccountType type) -{ - GSList *account_names = NULL, *cursor = NULL; - TnyList *accounts = NULL; - ModestTnyAccountStorePrivate *priv = NULL; - - g_return_if_fail (type == TNY_ACCOUNT_TYPE_STORE || - type == TNY_ACCOUNT_TYPE_TRANSPORT); - g_return_if_fail (self); - - priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - /* Do nothing if the accounts are already cached: */ - if (type == TNY_ACCOUNT_TYPE_STORE) { - if (priv->store_accounts) - return; - } else { - if (priv->transport_accounts) - return; - } - - - /* These are account names, not server_account names */ - accounts = tny_simple_list_new (); - account_names = modest_account_mgr_account_names (priv->account_mgr,FALSE); - - for (cursor = account_names; cursor; cursor = cursor->next) { - - gchar *account_name = (gchar*) cursor->data; - - /* we get the server_accounts for enabled accounts */ - if (modest_account_mgr_get_enabled(priv->account_mgr, account_name)) { - - /* Add the account: */ - TnyAccount *tny_account = - modest_tny_account_new_from_account (priv->account_mgr, - account_name, - type, priv->session, - get_password, - forget_password); - if (tny_account) { - /* Forget any cached password for the account, - * so that we use a new account if any. - * TODO: Really we should do this in a more precise way in - * on_account_changed(). - */ - modest_tny_account_store_forget_password_in_memory ( - MODEST_TNY_ACCOUNT_STORE (self), - tny_account_get_id (tny_account)); - - g_object_set_data (G_OBJECT(tny_account), "account_store", - (gpointer)self); - - /* Append to the list and cache it */ - if (list) - tny_list_append (list, G_OBJECT (tny_account)); - tny_list_append (accounts, G_OBJECT (tny_account)); - } else - g_printerr ("modest: failed to create account for %s\n", - account_name); - } - } - - if (type == TNY_ACCOUNT_TYPE_STORE) { - /* Also add the Memory card account if it is mounted: */ - gboolean mmc_is_mounted = FALSE; - GnomeVFSVolumeMonitor* monitor = - gnome_vfs_get_volume_monitor(); - GList* list_volumes = gnome_vfs_volume_monitor_get_mounted_volumes (monitor); - GList *iter = list_volumes; - while (iter) { - GnomeVFSVolume *volume = (GnomeVFSVolume*)iter->data; - if (volume) { - if (!mmc_is_mounted) { - gchar *uri = gnome_vfs_volume_get_activation_uri (volume); - if (uri && (strcmp (uri, MODEST_MCC1_VOLUMEPATH_URI) == 0)) { - mmc_is_mounted = TRUE; - } - g_free (uri); - } - - gnome_vfs_volume_unref(volume); - } - - iter = g_list_next (iter); - } - g_list_free (list_volumes); - - if (mmc_is_mounted) { - TnyAccount *tny_account = - modest_tny_account_new_for_local_folders (priv->account_mgr, - priv->session, MODEST_MCC1_VOLUMEPATH); - - /* Append to the list and cache it */ - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - tny_list_append (accounts, G_OBJECT (tny_account)); - } - } - - /* And add the connection-specific transport accounts, if any. - * Note that these server account instances might never be used - * if their connections are never active: */ - /* Look at each modest account: */ - if (type == TNY_ACCOUNT_TYPE_TRANSPORT) { - GSList *iter_account_names = account_names; - while (iter_account_names) { - const gchar* account_name = (const gchar*)(iter_account_names->data); - GSList *list_specifics = modest_account_mgr_get_list (priv->account_mgr, - account_name, - MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST, - MODEST_CONF_VALUE_STRING, FALSE); - - /* Look at each connection-specific transport account for the - * modest account: */ - GSList *iter = list_specifics; - while (iter) { - /* The list alternates between the connection name and the transport name: */ - /* const gchar* this_connection_name = (const gchar*)(iter->data); */ - iter = g_slist_next (iter); - if (iter) { - const gchar* transport_account_name = (const gchar*)(iter->data); - if (transport_account_name) { - TnyAccount * tny_account = NULL; - /* Add the account: */ - tny_account = modest_tny_account_new_from_server_account_name ( - priv->account_mgr, priv->session, transport_account_name); - if (tny_account) { - modest_tny_account_set_parent_modest_account_name_for_server_account (tny_account, account_name); - g_object_set_data (G_OBJECT(tny_account), "account_store", - (gpointer)self); - - /* Append to the list and cache it */ - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - tny_list_append (accounts, G_OBJECT (tny_account)); - } else - g_printerr ("modest: failed to create smtp-specific account for %s\n", - transport_account_name); - } - } - - iter = g_slist_next (iter); - } - - iter_account_names = g_slist_next (iter_account_names); - } - } - - /* free the account_names */ - modest_account_mgr_free_account_names (account_names); - account_names = NULL; - - /* We also create a per-account local outbox folder (a _store_ account) - * for each _transport_ account. */ - if (!priv->store_accounts_outboxes) - create_per_account_local_outbox_folders (self); - - /* But we only return the per-account local outbox folder when - * _store_ accounts are requested. */ - if (type == TNY_ACCOUNT_TYPE_STORE) { - - /* Also add the local folder pseudo-account: */ - TnyAccount *tny_account = - modest_tny_account_new_for_local_folders (priv->account_mgr, - priv->session, NULL); - - /* Add them to the TnyList: */ - if (priv->store_accounts_outboxes) { - /* Add accounts to the lists */ - if (list) - tny_list_foreach (priv->store_accounts_outboxes, - foreach_account_append_to_list, list); - tny_list_foreach (priv->store_accounts_outboxes, - foreach_account_append_to_list, accounts); - } - - /* Add a merged folder, merging all the per-account outbox folders: */ - modest_tny_local_folders_account_add_merged_outbox_folders ( - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account), priv->store_accounts_outboxes); - - if (priv->store_accounts_outboxes) { - /* We have finished with this temporary list, so free it: */ - g_object_unref (priv->store_accounts_outboxes); - priv->store_accounts_outboxes = NULL; - } - - /* Append to the list and cache it */ - if (list) - tny_list_append (list, G_OBJECT(tny_account)); - tny_list_append (accounts, G_OBJECT(tny_account)); - } - - /* Store the cache: */ - if (type == TNY_ACCOUNT_TYPE_STORE) { - priv->store_accounts = accounts; - } else if (type == TNY_ACCOUNT_TYPE_TRANSPORT) { - priv->transport_accounts = accounts; - } + return MODEST_TNY_ACCOUNT_STORE(obj); } - static void -modest_tny_account_store_get_accounts (TnyAccountStore *self, TnyList *list, +modest_tny_account_store_get_accounts (TnyAccountStore *self, + TnyList *list, TnyGetAccountsRequestType request_type) { ModestTnyAccountStorePrivate *priv; @@ -1257,34 +954,23 @@ modest_tny_account_store_get_accounts (TnyAccountStore *self, TnyList *list, priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - if (request_type == TNY_ACCOUNT_STORE_BOTH) { - modest_tny_account_store_get_accounts (self, list, - TNY_ACCOUNT_STORE_STORE_ACCOUNTS); - modest_tny_account_store_get_accounts (self, list, - TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS); - - tny_session_camel_set_initialized (priv->session); - - return; + switch (request_type) { + case TNY_ACCOUNT_STORE_BOTH: + tny_list_foreach (priv->store_accounts, foreach_account_append_to_list, list); + tny_list_foreach (priv->transport_accounts, foreach_account_append_to_list, list); + break; + case TNY_ACCOUNT_STORE_STORE_ACCOUNTS: + tny_list_foreach (priv->store_accounts, foreach_account_append_to_list, list); + break; + case TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS: + tny_list_foreach (priv->transport_accounts, foreach_account_append_to_list, list); + break; + default: + g_return_if_reached (); } - - if (request_type == TNY_ACCOUNT_STORE_STORE_ACCOUNTS) { - if (!priv->store_accounts) - get_server_accounts (self, list, TNY_ACCOUNT_TYPE_STORE); - else - get_cached_accounts (self, list, TNY_ACCOUNT_TYPE_STORE); - tny_session_camel_set_initialized (priv->session); - - } else if (request_type == TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS) { - if (!priv->transport_accounts) - get_server_accounts (self, list, TNY_ACCOUNT_TYPE_TRANSPORT); - else - get_cached_accounts (self, list, TNY_ACCOUNT_TYPE_TRANSPORT); - - tny_session_camel_set_initialized (priv->session); - } else - g_return_if_reached (); /* incorrect req type */ + /* Initialize session. Why do we need this ??? */ + tny_session_camel_set_initialized (priv->session); } @@ -1531,9 +1217,6 @@ modest_tny_account_store_get_session (TnyAccountStore *self) return MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self)->session; } - - - static TnyAccount* get_tny_account_by (TnyList *accounts, ModestTnyAccountStoreQueryType type, @@ -1588,35 +1271,29 @@ modest_tny_account_store_get_tny_account_by (ModestTnyAccountStore *self, g_return_val_if_fail (str, NULL); priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - /* ******************** WARNING ******************** */ - /* Fill the caches, as that may not have happened yet */ -/* list = TNY_LIST(tny_simple_list_new()); */ -/* modest_tny_account_store_get_accounts (TNY_ACCOUNT_STORE(self), */ -/* list, TNY_ACCOUNT_STORE_BOTH); */ -/* g_object_unref (list); */ - + /* Search in store accounts */ account = get_tny_account_by (priv->store_accounts, type, str); /* If we already found something, no need to search the transport accounts */ if (!account) { account = get_tny_account_by (priv->transport_accounts, type, str); + + /* If we already found something, no need to search the + per-account outbox accounts */ + if (!account) + account = get_tny_account_by (priv->store_accounts_outboxes, type, str); } /* Warn if nothing was found. This is generally unusual. */ if (!account) { - switch (type) { - case MODEST_TNY_ACCOUNT_STORE_QUERY_ID: - g_warning("%s: Failed to find account with ID=%s\n", __FUNCTION__, str); - break; - case MODEST_TNY_ACCOUNT_STORE_QUERY_URL: - g_warning("%s: Failed to find account with URL=%s\n", __FUNCTION__, str); - break; - } + g_warning("%s: Failed to find account with %s=%s\n", + __FUNCTION__, + (type == MODEST_TNY_ACCOUNT_STORE_QUERY_ID) ? "ID" : "URL", + str); } - /* Returns a new reference to the account if found*/ + /* Returns a new reference to the account if found */ return account; } @@ -1639,11 +1316,6 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self, priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - /* ******************** WARNING ******************** */ -/* /\* Make sure that the tny accounts have been created: */ - if (!priv->store_accounts || !priv->transport_accounts) - recreate_all_accounts (self); - account_list = (type == TNY_ACCOUNT_TYPE_STORE) ? priv->store_accounts : priv->transport_accounts; @@ -1760,8 +1432,6 @@ modest_tny_account_store_get_transport_account_for_open_connection (ModestTnyAcc /* If there is no connection-specific transport account (the common case), * just get the regular transport account: */ if (!account) { - /* printf("DEBUG: %s: using regular transport account for account %s.\n", __FUNCTION__, account_name); */ - /* The special local folders don't have transport accounts. */ if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) account = NULL; @@ -1773,37 +1443,15 @@ modest_tny_account_store_get_transport_account_for_open_connection (ModestTnyAcc return account; } -gboolean -modest_tny_account_is_virtual_local_folders (TnyAccount *self) -{ - /* We should make this more sophisticated if we ever use ModestTnyLocalFoldersAccount - * for anything else. */ - return MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self); -} - - -gboolean -modest_tny_account_is_memory_card_account (TnyAccount *self) -{ - if (!self) - return FALSE; - - const gchar* account_id = tny_account_get_id (self); - if (!account_id) - return FALSE; - - return (strcmp (account_id, MODEST_MMC_ACCOUNT_ID) == 0); -} - TnyAccount* -modest_tny_account_store_get_local_folders_account (TnyAccountStore *self) +modest_tny_account_store_get_local_folders_account (ModestTnyAccountStore *self) { TnyAccount *account = NULL; ModestTnyAccountStorePrivate *priv; TnyIterator *iter; gboolean found; - g_return_val_if_fail (self, NULL); + g_return_val_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (self), NULL); priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); @@ -1826,4 +1474,221 @@ modest_tny_account_store_get_local_folders_account (TnyAccountStore *self) return account; } +/*********************************************************************************/ +static void +add_existing_accounts (ModestTnyAccountStore *self) +{ + GSList *account_names = NULL, *iter = NULL; + ModestTnyAccountStorePrivate *priv = NULL; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + /* These are account names, not server_account names */ + account_names = modest_account_mgr_account_names (priv->account_mgr, FALSE); + for (iter = account_names; iter != NULL; iter = g_slist_next (iter)) { + const gchar *account_name = (const gchar*) iter->data; + + /* Insert all enabled accounts without notifying */ + if (modest_account_mgr_get_enabled (priv->account_mgr, account_name)) + insert_account (self, account_name, FALSE); + } + modest_account_mgr_free_account_names (account_names); +} + +static TnyAccount* +create_tny_account (ModestTnyAccountStore *self, + const gchar *name, + TnyAccountType type) +{ + TnyAccount *account = NULL; + ModestTnyAccountStorePrivate *priv = NULL; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + account = modest_tny_account_new_from_account (priv->account_mgr, + name, type, + priv->session, + get_password, + forget_password); + + if (account) { + /* Forget any cached password for the account, so that + we use a new account if any */ + modest_tny_account_store_forget_password_in_memory (self, + tny_account_get_id (account)); + /* Set the account store */ + g_object_set_data (G_OBJECT(account), "account_store", self); + } else { + g_printerr ("modest: failed to create account for %s\n", name); + } + + return account; +} + +/* + * This function will be used for both adding new accounts and for the + * initialization. In the initialization we do not want to emit + * signals so notify will be FALSE, in the case of account additions + * we do want to notify the observers + */ +static void +insert_account (ModestTnyAccountStore *self, + const gchar *account, + gboolean notify) +{ + ModestTnyAccountStorePrivate *priv = NULL; + TnyAccount *store_account = NULL, *transport_account = NULL; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + /* Get the server and the transport account */ + store_account = create_tny_account (self, account, TNY_ACCOUNT_TYPE_STORE); + transport_account = create_tny_account (self, account, TNY_ACCOUNT_TYPE_TRANSPORT); + + /* Add to the list, and notify the observers */ + if (store_account) { + tny_list_append (priv->store_accounts, G_OBJECT (store_account)); + if (notify) + g_signal_emit (G_OBJECT (self), signals [ACCOUNT_INSERTED_SIGNAL], 0, store_account); + g_object_unref (store_account); + } + + /* Add to the list, and notify the observers */ + if (transport_account) { + TnyAccount *account_outbox = NULL, *local_account = NULL; + TnyFolder *per_account_outbox = NULL; + TnyList *folders; + TnyIterator *iter_folders; + + /* Add account to the list */ + tny_list_append (priv->transport_accounts, G_OBJECT (transport_account)); + + /* Add connection-specific transport accounts */ + add_connection_specific_transport_accounts (self, account); + + /* Create per account local outbox */ + account_outbox = + modest_tny_account_new_for_per_account_local_outbox_folder (priv->account_mgr, + account, + priv->session); + tny_list_append (priv->store_accounts_outboxes, G_OBJECT (account_outbox)); + + /* Get the outbox folder */ + folders = tny_simple_list_new (); + tny_folder_store_get_folders (TNY_FOLDER_STORE (account_outbox), + folders, NULL, NULL); + g_assert (tny_list_get_length (folders) == 1); + iter_folders = tny_list_create_iterator (folders); + per_account_outbox = TNY_FOLDER (tny_iterator_get_current (iter_folders)); + g_object_unref (iter_folders); + g_object_unref (account_outbox); + + /* Add the outbox of the new per-account-local-outbox + account to the global local merged OUTBOX of the + local folders account */ + local_account = modest_tny_account_store_get_local_folders_account (MODEST_TNY_ACCOUNT_STORE (self)); + modest_tny_local_folders_account_add_folder_to_outbox (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (local_account), + per_account_outbox); + g_object_unref (local_account); + g_object_unref (per_account_outbox); + + /* Notify the observers */ + if (notify) + g_signal_emit (G_OBJECT (self), signals [ACCOUNT_INSERTED_SIGNAL], 0, transport_account); + g_object_unref (transport_account); + } +} + +static void +on_account_inserted (ModestAccountMgr *acc_mgr, + const gchar *account, + gpointer user_data) +{ + /* Insert the account and notify the observers */ + insert_account (MODEST_TNY_ACCOUNT_STORE (user_data), account, TRUE); +} + +static void +on_account_removed (ModestAccountMgr *acc_mgr, + const gchar *account, + gpointer user_data) +{ + TnyAccount *store_account = NULL, *transport_account = NULL; + ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data); + + /* Get the server and the transport account */ + store_account = + modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_STORE); + transport_account = + modest_tny_account_store_get_server_account (self, account, TNY_ACCOUNT_TYPE_TRANSPORT); + + /* If there was any problem creating the account, for example, + with the configuration system this could not exist */ + if (store_account) { + /* Clear the cache */ + tny_store_account_delete_cache (TNY_STORE_ACCOUNT (store_account)); + + /* Notify the observers */ + g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, store_account); + g_object_unref (store_account); + } else { + g_warning ("There is no store account for account %s\n", account); + } + + /* If there was any problem creating the account, for example, + with the configuration system this could not exist */ + if (transport_account) { + /* Notify the observers */ + g_signal_emit (G_OBJECT (self), signals [ACCOUNT_REMOVED_SIGNAL], 0, transport_account); + g_object_unref (transport_account); + } else { + g_warning ("There is no transport account for account %s\n", account); + } +} + +static void +add_connection_specific_transport_accounts (ModestTnyAccountStore *self, + const gchar *account_name) +{ + ModestTnyAccountStorePrivate *priv = NULL; + GSList *list_specifics = NULL, *iter = NULL; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + list_specifics = modest_account_mgr_get_list (priv->account_mgr, + account_name, + MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST, + MODEST_CONF_VALUE_STRING, FALSE); + + /* Look at each connection-specific transport account for the + * modest account: */ + iter = list_specifics; + while (iter) { + /* The list alternates between the connection name and the transport name: */ + iter = g_slist_next (iter); + if (iter) { + const gchar* transport_account_name = (const gchar*) (iter->data); + if (transport_account_name) { + TnyAccount * tny_account = NULL; + /* Add the account: */ + tny_account = + modest_tny_account_new_from_server_account_name (priv->account_mgr, + priv->session, + transport_account_name); + if (tny_account) { + modest_tny_account_set_parent_modest_account_name_for_server_account (tny_account, + account_name); + g_object_set_data (G_OBJECT(tny_account), + "account_store", + (gpointer)self); + + tny_list_append (priv->transport_accounts, G_OBJECT (tny_account)); + } else + g_printerr ("modest: failed to create smtp-specific account for %s\n", + transport_account_name); + } + } + iter = g_slist_next (iter); + } +} diff --git a/src/modest-tny-account-store.h b/src/modest-tny-account-store.h index a623632..76fbe91 100644 --- a/src/modest-tny-account-store.h +++ b/src/modest-tny-account-store.h @@ -167,27 +167,8 @@ TnySessionCamel* modest_tny_account_store_get_session (TnyAccountStore *se * * Get the user-visible local folders account. **/ -TnyAccount * modest_tny_account_store_get_local_folders_account (TnyAccountStore *self); - -/** modest_tny_account_is_virtual_local_folders: - * @self A TnyAccount. - * - * A convenience function to identify whether TnyAccount - * is the virtual local folders account, containing the folders from local_folders/ - * and the outboxes from outboxes//. - **/ -gboolean modest_tny_account_is_virtual_local_folders (TnyAccount *self); - -/** modest_tny_account_is_memory_card_account: - * @self A TnyAccount. - * - * A convenience function to identify whether TnyAccount - * is the memory card account. - **/ -gboolean -modest_tny_account_is_memory_card_account (TnyAccount *self); +TnyAccount * modest_tny_account_store_get_local_folders_account (ModestTnyAccountStore *self); G_END_DECLS #endif /* __MODEST_TNY_ACCOUNT_STORE_H__ */ - diff --git a/src/modest-tny-account.c b/src/modest-tny-account.c index 070f3a2..c718034 100644 --- a/src/modest-tny-account.c +++ b/src/modest-tny-account.c @@ -736,8 +736,6 @@ modest_tny_account_new_for_per_account_local_outbox_folder (ModestAccountMgr *ac return NULL; } - printf ("DEBUG: %s: Setting session for account: session=%p\n", - __FUNCTION__, session); tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session); /* Make sure that the paths exists on-disk so that TnyCamelStoreAccount can @@ -901,17 +899,43 @@ modest_tny_folder_store_get_local_size (TnyFolderStore *self) return retval; } -const gchar* modest_tny_account_get_parent_modest_account_name_for_server_account (TnyAccount *self) +const gchar* +modest_tny_account_get_parent_modest_account_name_for_server_account (TnyAccount *self) { return (const gchar *)g_object_get_data (G_OBJECT (self), "modest_account"); } -void modest_tny_account_set_parent_modest_account_name_for_server_account (TnyAccount *self, const gchar* parent_modest_acount_name) +void +modest_tny_account_set_parent_modest_account_name_for_server_account (TnyAccount *self, + const gchar* parent_modest_acount_name) { g_object_set_data_full (G_OBJECT(self), "modest_account", (gpointer) g_strdup (parent_modest_acount_name), g_free); } +gboolean +modest_tny_account_is_virtual_local_folders (TnyAccount *self) +{ + /* We should make this more sophisticated if we ever use ModestTnyLocalFoldersAccount + * for anything else. */ + return MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self); +} +gboolean +modest_tny_account_is_memory_card_account (TnyAccount *self) +{ + const gchar* account_id = NULL; + + g_return_val_if_fail (TNY_ACCOUNT (self), FALSE); + if (!self) + return FALSE; + + account_id = tny_account_get_id (self); + + if (!account_id) + return FALSE; + else + return (strcmp (account_id, MODEST_MMC_ACCOUNT_ID) == 0); +} diff --git a/src/modest-tny-account.h b/src/modest-tny-account.h index 867f19a..fdc7340 100644 --- a/src/modest-tny-account.h +++ b/src/modest-tny-account.h @@ -173,7 +173,28 @@ typedef void (*ModestTnyAccountGetMmcAccountNameCallback) (TnyStoreAccount* self * calling the callback (if not NULL) to notify that the name is changed. * if the name was changed. The callback will not be called if the name was not changed. */ -void modest_tny_account_get_mmc_account_name (TnyStoreAccount* self, ModestTnyAccountGetMmcAccountNameCallback callback, gpointer user_data); +void modest_tny_account_get_mmc_account_name (TnyStoreAccount* self, + ModestTnyAccountGetMmcAccountNameCallback callback, + gpointer user_data); + + +/** modest_tny_account_is_virtual_local_folders: + * @self A TnyAccount. + * + * A convenience function to identify whether TnyAccount + * is the virtual local folders account, containing the folders from local_folders/ + * and the outboxes from outboxes//. + **/ +gboolean modest_tny_account_is_virtual_local_folders (TnyAccount *self); + +/** modest_tny_account_is_memory_card_account: + * @self A TnyAccount. + * + * A convenience function to identify whether TnyAccount + * is the memory card account. + **/ +gboolean modest_tny_account_is_memory_card_account (TnyAccount *self); + G_END_DECLS diff --git a/src/modest-tny-folder.c b/src/modest-tny-folder.c index f82a5c8..fd35b01 100644 --- a/src/modest-tny-folder.c +++ b/src/modest-tny-folder.c @@ -338,7 +338,8 @@ modest_tny_folder_get_header_unique_id (TnyHeader *header) return retval; } -TnyAccount *modest_tny_folder_get_account (TnyFolder *folder) +TnyAccount * +modest_tny_folder_get_account (TnyFolder *folder) { TnyAccount *account = NULL; @@ -347,12 +348,10 @@ TnyAccount *modest_tny_folder_get_account (TnyFolder *folder) * because it could be merging folders from multiple accounts. * So we assume that this is the local folders account: */ - account = modest_tny_account_store_get_local_folders_account ( - TNY_ACCOUNT_STORE (modest_runtime_get_account_store())); + account = modest_tny_account_store_get_local_folders_account (modest_runtime_get_account_store()); } else { account = tny_folder_get_account (folder); } return account; } - diff --git a/src/modest-tny-local-folders-account.c b/src/modest-tny-local-folders-account.c index 5fb942d..078183f 100644 --- a/src/modest-tny-local-folders-account.c +++ b/src/modest-tny-local-folders-account.c @@ -51,7 +51,7 @@ typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccount struct _ModestTnyLocalFoldersAccountPrivate { - GSList *list_extra_folders; + TnyMergeFolder *outbox_folder; }; static void get_folders (TnyFolderStore *self, @@ -64,44 +64,9 @@ static TnyFolder* create_folder (TnyFolderStore *self, GError **err); static void -modest_tny_local_folders_account_dispose (GObject *object) -{ - if (G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose) - G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->dispose (object); -} - - -static void -modest_tny_local_folders_account_remove_all_extra_folders (ModestTnyLocalFoldersAccount *store) -{ - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store); - - GSList *iter = priv->list_extra_folders; - while (iter) - { - TnyFolder *folder = (TnyFolder*)iter->data; - if (folder) { - g_object_unref (folder); - iter->data = NULL; - } - - iter = g_slist_next (iter); - } - - g_slist_free (priv->list_extra_folders); - priv->list_extra_folders = NULL; -} - -static void modest_tny_local_folders_account_finalize (GObject *object) { - G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object); - - ModestTnyLocalFoldersAccount *self = - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (object); - - modest_tny_local_folders_account_remove_all_extra_folders (self); + G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object); } static void @@ -111,7 +76,6 @@ modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass * g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate)); - object_class->dispose = modest_tny_local_folders_account_dispose; object_class->finalize = modest_tny_local_folders_account_finalize; /* Override virtual functions from the parent class: */ @@ -122,6 +86,7 @@ modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass * static void modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self) { + /* Do nothing */ } ModestTnyLocalFoldersAccount* @@ -130,24 +95,9 @@ modest_tny_local_folders_account_new (void) return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL); } -void -modest_tny_local_folders_account_add_extra_folder (ModestTnyLocalFoldersAccount *store, - TnyFolder *folder) -{ - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (store); - - /* Check that it isn't already in the list: */ - GSList *exists = g_slist_find (priv->list_extra_folders, folder); - if (exists) - return; - - /* Add it: */ - /* The reference is released in finalize: */ - priv->list_extra_folders = g_slist_append (priv->list_extra_folders, folder); - g_object_ref (folder); -} - +/**********************************************************/ +/* TnyCamelStoreAccount functions redefinitions */ +/**********************************************************/ static gboolean modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder) { @@ -196,156 +146,96 @@ modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFo return retval; } - static void get_folders (TnyFolderStore *self, TnyList *list, TnyFolderStoreQuery *query, GError **err) { - ModestTnyLocalFoldersAccountPrivate *priv = - TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); - + TnyCamelStoreAccountClass *parent_class; + ModestTnyLocalFoldersAccountPrivate *priv; + /* Call the base class implementation: */ - TnyCamelStoreAccountClass *parent_class = g_type_class_peek_parent ( - MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); + parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); parent_class->get_folders_func (self, list, query, err); - /* Add our extra folders only if it passes the query */ - GSList *iter = priv->list_extra_folders; - while (iter) { - TnyFolder *folder = TNY_FOLDER (iter->data); - - if (folder && modest_tny_local_folders_account_query_passes (query, folder)) - tny_list_prepend (list, G_OBJECT (folder)); - - iter = g_slist_next (iter); - } -} - -static void -add_account_folders_to_merged_folder (TnyAccount *account, TnyMergeFolder* merge_folder) -{ - const gchar* account_id = tny_account_get_id (account); - const gboolean is_actual_local_folders_account = account_id && - (strcmp (account_id, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0); - - TnyList *list_outbox_folders = tny_simple_list_new (); - tny_folder_store_get_folders (TNY_FOLDER_STORE (account), - list_outbox_folders, NULL, NULL); - - TnyIterator* iter = tny_list_create_iterator (list_outbox_folders); - while (!tny_iterator_is_done (iter)) - { - TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter)); - - if (folder) { - gboolean add = TRUE; - /* TODO: Do not add outboxes that are inside local-folders/, - * because these are just left-over from earlier Modest versions - * that put the outbox there: */ - if (is_actual_local_folders_account) { - const TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (folder); - if (type == TNY_FOLDER_TYPE_OUTBOX) { - add = FALSE; - } - } - - if (add) - tny_merge_folder_add_folder (merge_folder, folder); - - g_object_unref (folder); - } + /* Add our extra folder only if it passes the query */ + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); - tny_iterator_next (iter); - } - - g_object_unref (list_outbox_folders); + if (priv->outbox_folder && + modest_tny_local_folders_account_query_passes (query, TNY_FOLDER (priv->outbox_folder))) + tny_list_prepend (list, G_OBJECT (priv->outbox_folder)); } -void -modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *self, - TnyList *accounts) +static TnyFolder* +create_folder (TnyFolderStore *self, + const gchar *name, + GError **err) { - TnyMergeFolder *merged_outbox = NULL; - TnyIterator *iter = NULL; + TnyCamelStoreAccountClass *parent_class; - modest_tny_local_folders_account_remove_all_extra_folders (self); - - /* All per-account outbox folders are merged into one folders - * so that they appear as one outbox to the user: */ - merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new(_("mcen_me_folder_outbox"))); - - /* Set type to outbox */ - tny_merge_folder_set_folder_type (merged_outbox, TNY_FOLDER_TYPE_OUTBOX); - - iter = tny_list_create_iterator (accounts); - while (!tny_iterator_is_done (iter)){ - - TnyAccount *account = TNY_ACCOUNT (tny_iterator_get_current (iter)); - - /* Add both outbox account and local-folders account folders - * to our one combined account: - */ - if (MODEST_IS_TNY_OUTBOX_ACCOUNT (account)) { - /* Add the folder to the merged folder. - * We will add it later to the virtual local-folders store: */ - add_account_folders_to_merged_folder (account, merged_outbox); - } - g_object_unref (account); - tny_iterator_next (iter); + parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); + + /* If the folder name is been used by our extra folders */ + if (modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) { + g_set_error (err, TNY_FOLDER_STORE_ERROR, + TNY_FOLDER_STORE_ERROR_CREATE_FOLDER, + "Folder name already in use"); + return NULL; } - g_object_unref (iter); - - /* Add the merged outbox folder to the virtual local-folders store: */ - modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox)); - g_object_unref (merged_outbox); + + /* Call the base class implementation: */ + return parent_class->create_folder_func (self, name, err); } +/*****************************/ +/* Public methods */ +/*****************************/ gboolean -modest_tny_local_folders_account_extra_folder_exists (ModestTnyLocalFoldersAccount *self, - const gchar *name) +modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self, + const gchar *name) { ModestTnyLocalFoldersAccountPrivate *priv; - GSList *iter; - gboolean found; gchar *down_name; + const gchar *type_name; + gboolean retval; /* Check that we're not trying to create/rename any folder - with the same name that our extra folders */ + with the same name that our OUTBOX */ priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); - iter = priv->list_extra_folders; - found = FALSE; down_name = g_utf8_strdown (name, strlen (name)); - while (iter && !found) { - TnyFolder *folder = TNY_FOLDER (iter->data); - const gchar *type_name; - - type_name = modest_local_folder_info_get_type_name (tny_folder_get_folder_type (folder)); - if (!strcmp (type_name, down_name)) - found = TRUE; - else - iter = g_slist_next (iter); - } + + type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_OUTBOX); + if (!strcmp (type_name, down_name)) + retval = TRUE; + else + retval = FALSE; + g_free (down_name); - return found; + return retval; } -static TnyFolder* -create_folder (TnyFolderStore *self, - const gchar *name, - GError **err) +void +modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self, + TnyFolder *per_account_outbox) { - TnyCamelStoreAccountClass *parent_class; + ModestTnyLocalFoldersAccountPrivate *priv; - parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self)); + g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self)); + g_return_if_fail (TNY_IS_FOLDER (per_account_outbox)); - /* If the folder name is been used by our extra folders */ - if (modest_tny_local_folders_account_extra_folder_exists (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) { - g_set_error (err, TNY_FOLDER_STORE_ERROR, - TNY_FOLDER_STORE_ERROR_CREATE_FOLDER, - "Folder name already in use"); - return NULL; + /* We can not test it yet, because there is no API to set the + type of a folder */ +/* g_return_if_fail (tny_folder_get_folder_type (per_account_outbox) == TNY_FOLDER_TYPE_OUTBOX); */ + + priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self); + + /* Create on-demand */ + if (!priv->outbox_folder) { + priv->outbox_folder = TNY_MERGE_FOLDER (tny_merge_folder_new (_("mcen_me_folder_outbox"))); + + /* Set type to outbox */ + tny_merge_folder_set_folder_type (priv->outbox_folder, TNY_FOLDER_TYPE_OUTBOX); } - /* Call the base class implementation: */ - return parent_class->create_folder_func (self, name, err); + /* Add outbox to the global OUTBOX folder */ + tny_merge_folder_add_folder (priv->outbox_folder, per_account_outbox); } diff --git a/src/modest-tny-local-folders-account.h b/src/modest-tny-local-folders-account.h index 388e862..2687d5c 100644 --- a/src/modest-tny-local-folders-account.h +++ b/src/modest-tny-local-folders-account.h @@ -72,14 +72,11 @@ GType modest_tny_local_folders_account_get_type (void); ModestTnyLocalFoldersAccount* modest_tny_local_folders_account_new (void); -void modest_tny_local_folders_account_add_extra_folder (ModestTnyLocalFoldersAccount *store, - TnyFolder *folder); - -void modest_tny_local_folders_account_add_merged_outbox_folders (ModestTnyLocalFoldersAccount *store, - TnyList *accounts); - -gboolean modest_tny_local_folders_account_extra_folder_exists (ModestTnyLocalFoldersAccount *self, - const gchar *name); +gboolean modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self, + const gchar *name); + +void modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self, + TnyFolder *per_account_outbox); G_END_DECLS diff --git a/src/modest-tny-send-queue.c b/src/modest-tny-send-queue.c index 0db96a1..7835838 100644 --- a/src/modest-tny-send-queue.c +++ b/src/modest-tny-send-queue.c @@ -417,8 +417,13 @@ modest_tny_send_queue_try_to_send (ModestTnySendQueue* self) GError *err = NULL; outbox = modest_tny_send_queue_get_outbox (TNY_SEND_QUEUE(self)); + if (!outbox) + return; + tny_folder_get_headers (outbox, headers, TRUE, &err); - if (err != NULL) goto frees; + if (err != NULL) + goto frees; + iter = tny_list_create_iterator (headers); while (!tny_iterator_is_done (iter)) { header = TNY_HEADER (tny_iterator_get_current (iter)); diff --git a/src/modest-ui-dimming-rules.c b/src/modest-ui-dimming-rules.c index c09ba02..c21bf88 100644 --- a/src/modest-ui-dimming-rules.c +++ b/src/modest-ui-dimming-rules.c @@ -35,6 +35,7 @@ #include "modest-ui-dimming-rules.h" #include "modest-dimming-rule.h" #include "modest-tny-folder.h" +#include "modest-tny-account.h" #include "modest-text-utils.h" #include #include @@ -1707,11 +1708,14 @@ _selected_msg_marked_as (ModestWindow *win, if (MODEST_IS_MAIN_WINDOW (win)) main_window = win; - else { + else main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()); - } - + + /* TODO: Javi, what about if the main window does not + exist?. Adding some code to avoid CRITICALs */ + if (!main_window) + return FALSE; /* Get header view to check selected messages */ header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(main_window), diff --git a/src/widgets/modest-account-view.c b/src/widgets/modest-account-view.c index bfe7950..5fd4710 100644 --- a/src/widgets/modest-account-view.c +++ b/src/widgets/modest-account-view.c @@ -199,9 +199,6 @@ update_account_view (ModestAccountMgr *account_mgr, ModestAccountView *view) * current use instead */ cursor = account_names = modest_account_mgr_account_names (account_mgr, TRUE /* only enabled accounts. */); - - if (!account_names) - g_warning ("debug: modest_account_mgr_account_names() returned NULL\n"); while (cursor) { gchar *account_name; diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 77691da..2c06336 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -90,10 +90,11 @@ static gboolean on_key_pressed (GtkWidget *self, GdkEventKey *event, gpointer user_data); -static void on_configuration_key_changed (ModestConf* conf, - const gchar *key, - ModestConfEvent event, - ModestFolderView *self); +static void on_configuration_key_changed (ModestConf* conf, + const gchar *key, + ModestConfEvent event, + ModestConfNotificationId notification_id, + ModestFolderView *self); /* DnD functions */ static void on_drag_data_get (GtkWidget *widget, @@ -146,6 +147,8 @@ struct _ModestFolderViewPrivate { TnyFolder *folder_to_select; /* folder to select after the next update */ + ModestConfNotificationId notification_id; + gulong changed_signal; gulong account_inserted_signal; gulong account_removed_signal; @@ -165,8 +168,8 @@ struct _ModestFolderViewPrivate { gchar *visible_account_id; ModestFolderViewStyle style; - gboolean reselect; /* we use this to force a reselection of the INBOX */ - gboolean show_non_move; + gboolean reselect; /* we use this to force a reselection of the INBOX */ + gboolean show_non_move; }; #define MODEST_FOLDER_VIEW_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), \ @@ -658,10 +661,12 @@ modest_folder_view_init (ModestFolderView *obj) * Track changes in the local account name (in the device it * will be the device name) */ - priv->conf_key_signal = - g_signal_connect (G_OBJECT(conf), - "key_changed", - G_CALLBACK(on_configuration_key_changed), obj); + priv->notification_id = modest_conf_listen_to_namespace (conf, + MODEST_CONF_NAMESPACE); + priv->conf_key_signal = g_signal_connect (G_OBJECT(conf), + "key_changed", + G_CALLBACK(on_configuration_key_changed), + obj); } static void @@ -684,6 +689,12 @@ modest_folder_view_finalize (GObject *obj) priv = MODEST_FOLDER_VIEW_GET_PRIVATE(obj); + if (priv->notification_id) { + modest_conf_forget_namespace (modest_runtime_get_conf (), + MODEST_CONF_NAMESPACE, + priv->notification_id); + } + if (priv->timer_expander != 0) { g_source_remove (priv->timer_expander); priv->timer_expander = 0; @@ -825,6 +836,13 @@ on_account_removed (TnyAccountStore *account_store, ModestFolderViewPrivate *priv; GtkTreeModel *sort_model, *filter_model; + /* Ignore transport account removals, we're not showing them + in the folder view */ + if (TNY_IS_TRANSPORT_ACCOUNT (account)) + return; + + g_print ("--------------------- FOLDER ---------------\n"); + self = MODEST_FOLDER_VIEW (user_data); priv = MODEST_FOLDER_VIEW_GET_PRIVATE (self); @@ -847,10 +865,10 @@ on_account_removed (TnyAccountStore *account_store, /* Call the restore method, this will set the new visible account */ modest_widget_memory_restore (modest_runtime_get_conf(), G_OBJECT(self), MODEST_CONF_FOLDER_VIEW_KEY); - - /* Select the INBOX */ - modest_folder_view_select_first_inbox_or_local (self); } + + /* Select the INBOX */ + modest_folder_view_select_first_inbox_or_local (self); } void @@ -1919,12 +1937,14 @@ on_key_pressed (GtkWidget *self, static void on_configuration_key_changed (ModestConf* conf, const gchar *key, - ModestConfEvent event, + ModestConfEvent event, + ModestConfNotificationId id, ModestFolderView *self) { ModestFolderViewPrivate *priv; - if (!key) + /* Do not listen for changes in other namespaces */ + if (priv->notification_id != id) return; g_return_if_fail (MODEST_IS_FOLDER_VIEW (self)); diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 47cda76..c128ea6 100644 --- a/src/widgets/modest-header-view.c +++ b/src/widgets/modest-header-view.c @@ -71,6 +71,10 @@ static gboolean filter_row (GtkTreeModel *model, GtkTreeIter *iter, gpointer data); +static void on_account_removed (TnyAccountStore *self, + TnyAccount *account, + gpointer user_data); + static void on_selection_changed (GtkTreeSelection *sel, gpointer user_data); @@ -104,13 +108,14 @@ struct _ModestHeaderViewPrivate { ModestEmailClipboard *clipboard; /* Filter tree model */ - gchar **hidding_ids; - guint n_selected; + gchar **hidding_ids; + guint n_selected; - gint sort_colid[2][TNY_FOLDER_TYPE_NUM]; - gint sort_type[2][TNY_FOLDER_TYPE_NUM]; + gint sort_colid[2][TNY_FOLDER_TYPE_NUM]; + gint sort_type[2][TNY_FOLDER_TYPE_NUM]; - gulong selection_changed_handler; + gulong selection_changed_handler; + gulong acc_removed_handler; }; typedef struct _HeadersCountChangedHelper HeadersCountChangedHelper; @@ -507,6 +512,7 @@ modest_header_view_init (ModestHeaderView *obj) priv->hidding_ids = NULL; priv->n_selected = 0; priv->selection_changed_handler = 0; + priv->acc_removed_handler = 0; /* Sort parameters */ for (j=0; j < 2; j++) { @@ -524,16 +530,26 @@ modest_header_view_dispose (GObject *obj) { ModestHeaderView *self; ModestHeaderViewPrivate *priv; + GtkTreeSelection *sel; self = MODEST_HEADER_VIEW(obj); priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + /* Free in the dispose to avoid unref cycles */ if (priv->folder) { tny_folder_remove_observer (priv->folder, TNY_FOLDER_OBSERVER (obj)); g_object_unref (G_OBJECT (priv->folder)); priv->folder = NULL; } + /* We need to do this here in the dispose because the + selection won't exist when finalizing */ + sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(self)); + if (sel && g_signal_handler_is_connected (sel, priv->selection_changed_handler)) { + g_signal_handler_disconnect (sel, priv->selection_changed_handler); + priv->selection_changed_handler = 0; + } + G_OBJECT_CLASS(parent_class)->dispose (obj); } @@ -546,9 +562,10 @@ modest_header_view_finalize (GObject *obj) self = MODEST_HEADER_VIEW(obj); priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); - if (priv->selection_changed_handler) { - g_signal_handler_disconnect (self, priv->selection_changed_handler); - priv->selection_changed_handler = 0; + if (g_signal_handler_is_connected (modest_runtime_get_account_store (), + priv->acc_removed_handler)) { + g_signal_handler_disconnect (modest_runtime_get_account_store (), + priv->acc_removed_handler); } g_mutex_lock (priv->observers_lock); @@ -590,8 +607,8 @@ modest_header_view_new (TnyFolder *folder, ModestHeaderViewStyle style) gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), TRUE); /* alternating row colors */ - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); - + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self)); priv->selection_changed_handler = g_signal_connect_after (sel, "changed", G_CALLBACK(on_selection_changed), self); @@ -602,6 +619,11 @@ modest_header_view_new (TnyFolder *folder, ModestHeaderViewStyle style) g_signal_connect (self, "focus-in-event", G_CALLBACK(on_focus_in), NULL); + priv->acc_removed_handler = g_signal_connect (modest_runtime_get_account_store (), + "account_removed", + G_CALLBACK (on_account_removed), + self); + return GTK_WIDGET(self); } @@ -1668,3 +1690,32 @@ modest_header_view_refilter (ModestHeaderView *header_view) if (GTK_IS_TREE_MODEL_FILTER (model)) gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model)); } + +/* + * Called when an account is removed. If I'm showing a folder of the + * account that has been removed then clear the view + */ +static void +on_account_removed (TnyAccountStore *self, + TnyAccount *account, + gpointer user_data) +{ + ModestHeaderViewPrivate *priv = NULL; + + /* Ignore changes in transport accounts */ + if (TNY_IS_TRANSPORT_ACCOUNT (account)) + return; + + g_print ("--------------------- HEADER ---------------\n"); + + priv = MODEST_HEADER_VIEW_GET_PRIVATE (user_data); + + if (priv->folder) { + TnyAccount *my_account; + + my_account = tny_folder_get_account (priv->folder); + if (my_account == account) + modest_header_view_clear (MODEST_HEADER_VIEW (user_data)); + g_object_unref (account); + } +} diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 042ec02..c60c679 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -43,8 +43,6 @@ static void modest_window_mgr_class_init (ModestWindowMgrClass *klass); static void modest_window_mgr_init (ModestWindowMgr *obj); static void modest_window_mgr_finalize (GObject *obj); -/* static void on_window_destroy (ModestWindow *window, */ -/* ModestWindowMgr *self); */ static gboolean on_window_destroy (ModestWindow *window, GdkEvent *event, ModestWindowMgr *self); @@ -430,8 +428,6 @@ modest_window_mgr_register_window (ModestWindowMgr *self, modest_window_show_toolbar (window, show); } -/* static void */ -/* on_window_destroy (ModestWindow *window, ModestWindowMgr *self) */ static gboolean on_window_destroy (ModestWindow *window, GdkEvent *event, @@ -510,7 +506,7 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, { GList *win; ModestWindowMgrPrivate *priv; - gint *tmp, handler_id; + gulong *tmp, handler_id; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); g_return_if_fail (MODEST_IS_WINDOW (window)); @@ -535,6 +531,15 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, priv->viewer_handlers = NULL; } + /* Remove the viewer window handler from the hash table. The + HashTable could not exist if the main window was closeed + when there were other windows remaining */ + if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) { + tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window); + g_signal_handler_disconnect (window, *tmp); + g_hash_table_remove (priv->viewer_handlers, window); + } + /* Save state */ modest_window_save_state (window); @@ -547,6 +552,9 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, /* Disconnect the "delete-event" handler, we won't need it anymore */ g_signal_handler_disconnect (window, handler_id); + /* Disconnect all the window signals */ + modest_window_disconnect_signals (window); + /* Destroy the window */ gtk_widget_destroy (win->data); diff --git a/src/widgets/modest-window.c b/src/widgets/modest-window.c index eef669d..91394bb 100644 --- a/src/widgets/modest-window.c +++ b/src/widgets/modest-window.c @@ -39,15 +39,21 @@ static void modest_window_class_init (ModestWindowClass *klass); static void modest_window_init (ModestWindow *obj); static void modest_window_finalize (GObject *obj); -static void modest_window_set_zoom_default (ModestWindow *window, - gdouble zoom); -static gdouble modest_window_get_zoom_default (ModestWindow *window); -static gboolean modest_window_zoom_plus_default (ModestWindow *window); -static gboolean modest_window_zoom_minus_default (ModestWindow *window); -static void modest_window_show_toolbar_default (ModestWindow *window, - gboolean show_toolbar); +static gdouble modest_window_get_zoom_default (ModestWindow *window); -static gboolean on_key_pressed (GtkWidget *self, GdkEventKey *event, gpointer user_data); +static gboolean modest_window_zoom_plus_default (ModestWindow *window); + +static gboolean modest_window_zoom_minus_default (ModestWindow *window); + +static void modest_window_disconnect_signals_default (ModestWindow *self); + +static void modest_window_show_toolbar_default (ModestWindow *window, + gboolean show_toolbar); + +static void modest_window_set_zoom_default (ModestWindow *window, + gdouble zoom); + +static gboolean on_key_pressed (GtkWidget *self, GdkEventKey *event, gpointer user_data); /* list my signals */ @@ -106,6 +112,7 @@ modest_window_class_init (ModestWindowClass *klass) klass->zoom_plus_func = modest_window_zoom_plus_default; klass->zoom_minus_func = modest_window_zoom_minus_default; klass->show_toolbar_func = modest_window_show_toolbar_default; + klass->disconnect_signals_func = modest_window_disconnect_signals_default; g_type_class_add_private (gobject_class, sizeof(ModestWindowPrivate)); } @@ -265,6 +272,12 @@ modest_window_show_toolbar (ModestWindow *window, show_toolbar); } +void +modest_window_disconnect_signals (ModestWindow *window) +{ + MODEST_WINDOW_GET_CLASS (window)->disconnect_signals_func (window); +} + /* Default implementations */ @@ -304,7 +317,11 @@ modest_window_show_toolbar_default (ModestWindow *window, g_warning ("modest: You should implement %s", __FUNCTION__); } - +static void +modest_window_disconnect_signals_default (ModestWindow *self) +{ + g_warning ("modest: You should implement %s", __FUNCTION__); +} void modest_window_save_state (ModestWindow *window) diff --git a/src/widgets/modest-window.h b/src/widgets/modest-window.h index eaad895..be1c722 100644 --- a/src/widgets/modest-window.h +++ b/src/widgets/modest-window.h @@ -90,8 +90,8 @@ struct _ModestWindowClass { gboolean (*zoom_plus_func) (ModestWindow *self); gboolean (*zoom_minus_func) (ModestWindow *self); void (*show_toolbar_func) (ModestWindow *self, gboolean show_toolbar); - void (*save_state_func) (ModestWindow *self); + void (*disconnect_signals_func) (ModestWindow *self); }; /** @@ -229,9 +229,12 @@ void modest_window_check_dimming_rules (ModestWindow *self); * dimming rules. * **/ -void -modest_window_check_dimming_rules_group (ModestWindow *self, - const gchar *group_name); +void modest_window_check_dimming_rules_group (ModestWindow *self, + const gchar *group_name); + + +void modest_window_disconnect_signals (ModestWindow *self); + G_END_DECLS