From 362784ce756b3f0e31cd451d9ac5e69b909d4053 Mon Sep 17 00:00:00 2001 From: Philip Van Hoof Date: Tue, 31 Jul 2007 08:24:20 +0000 Subject: [PATCH] 2007-07-31 Philip Van Hoof * Merging back devel/sessionwork to trunk/ pmo-trunk-r2866 --- src/dbus_api/modest-dbus-callbacks.c | 3 +- src/maemo/modest-main-window.c | 323 ++++---- src/maemo/modest-msg-edit-window.c | 24 +- src/maemo/modest-msg-view-window.c | 45 +- src/maemo/modest-platform.c | 20 +- src/modest-account-mgr-helpers.c | 4 +- src/modest-account-mgr-priv.h | 4 +- src/modest-account-mgr.c | 270 ++++--- src/modest-account-mgr.h | 10 +- src/modest-conf.c | 199 ++--- src/modest-conf.h | 14 +- src/modest-mail-operation.c | 7 +- src/modest-tny-account-store.c | 1273 ++++++++++++++++---------------- src/modest-tny-account-store.h | 26 +- src/modest-tny-account.c | 32 +- src/modest-tny-account.h | 23 +- src/modest-tny-folder.c | 7 +- src/modest-tny-local-folders-account.c | 244 ++---- src/modest-tny-local-folders-account.h | 13 +- src/modest-tny-send-queue.c | 7 +- src/modest-ui-dimming-rules.c | 10 +- src/widgets/modest-account-view.c | 94 ++- src/widgets/modest-folder-view.c | 176 +++-- src/widgets/modest-header-view.c | 71 +- src/widgets/modest-window-mgr.c | 22 +- src/widgets/modest-window.c | 35 +- src/widgets/modest-window.h | 11 +- 27 files changed, 1512 insertions(+), 1455 deletions(-) diff --git a/src/dbus_api/modest-dbus-callbacks.c b/src/dbus_api/modest-dbus-callbacks.c index c90efe0..601387d 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 955c7f3..9bb6f3f 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 on_account_update (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); } @@ -452,71 +466,71 @@ wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget) /* return FALSE; */ /* } */ -static void -on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data) -{ - if (err) { - printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message); +/* static void */ +/* on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data) */ +/* { */ +/* if (err) { */ +/* printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message); */ - if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL) - /* Don't show waste the user's time by showing him a dialog telling him - * that he has just cancelled something: */ - return; - } +/* if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL) */ +/* /\* Don't show waste the user's time by showing him a dialog telling him */ +/* * that he has just cancelled something: *\/ */ +/* return; */ +/* } */ - /* Get the server name: */ - const gchar* server_name = NULL; +/* /\* Get the server name: *\/ */ +/* const gchar* server_name = NULL; */ - TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account ( - TNY_CAMEL_SEND_QUEUE (self)); - if (server_account) { - server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account)); +/* TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account ( */ +/* TNY_CAMEL_SEND_QUEUE (self)); */ +/* if (server_account) { */ +/* server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account)); */ - g_object_unref (server_account); - server_account = NULL; - } +/* g_object_unref (server_account); */ +/* server_account = NULL; */ +/* } */ - if (!server_name) - server_name = _("Unknown Server"); - - /* Show the appropriate message text for the GError: */ - gchar *message = NULL; - if (err) { - switch (err->code) { - case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED: - message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); - break; - case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE: - message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); - break; - case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED: - /* TODO: This logical ID seems more suitable for a wrong username or password than for a - * wrong authentication method. The user is unlikely to guess at the real cause. - */ - message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name); - break; - case TNY_TRANSPORT_ACCOUNT_ERROR_SEND: - /* TODO: Tinymail is still sending this sometimes when it should - * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. */ - default: - message = g_strdup (_("emev_ib_ui_smtp_send_error")); - break; - } - } else { - message = g_strdup (_("emev_ib_ui_smtp_send_error")); - } +/* if (!server_name) */ +/* server_name = _("Unknown Server"); */ + +/* /\* Show the appropriate message text for the GError: *\/ */ +/* gchar *message = NULL; */ +/* if (err) { */ +/* switch (err->code) { */ +/* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED: */ +/* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */ +/* break; */ +/* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE: */ +/* message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name); */ +/* break; */ +/* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED: */ +/* /\* TODO: This logical ID seems more suitable for a wrong username or password than for a */ +/* * wrong authentication method. The user is unlikely to guess at the real cause. */ +/* *\/ */ +/* message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name); */ +/* break; */ +/* case TNY_TRANSPORT_ACCOUNT_ERROR_SEND: */ +/* /\* TODO: Tinymail is still sending this sometimes when it should */ +/* * send TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL. *\/ */ +/* default: */ +/* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */ +/* break; */ +/* } */ +/* } else { */ +/* message = g_strdup (_("emev_ib_ui_smtp_send_error")); */ +/* } */ - modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message); - g_free (message); +/* modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message); */ +/* g_free (message); */ - /* TODO: Offer to remove the message, to avoid messages in future? */ - /* - TnyFolder *outbox = tny_send_queue_get_outbox (queue); - tny_folder_remove_msg (outbox, header, NULL); - tny_folder_sync (outbox, TRUE, NULL); - g_object_unref (outbox); - */ -} +/* /\* TODO: Offer to remove the message, to avoid messages in future? *\/ */ +/* /\* */ +/* TnyFolder *outbox = tny_send_queue_get_outbox (queue); */ +/* tny_folder_remove_msg (outbox, header, NULL); */ +/* tny_folder_sync (outbox, TRUE, NULL); */ +/* g_object_unref (outbox); */ +/* *\/ */ +/* } */ typedef struct { TnySendQueue *queue; @@ -539,71 +553,71 @@ modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self) priv->queue_err_signals = NULL; } -static void -on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self) -{ - ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); +/* static void */ +/* on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self) */ +/* { */ +/* ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); */ - /* When going online, do the equivalent of pressing the send/receive button, - * as per the specification: - * (without the check for >0 accounts, though that is not specified): */ +/* /\* When going online, do the equivalent of pressing the send/receive button, */ +/* * as per the specification: */ +/* * (without the check for >0 accounts, though that is not specified): *\/ */ - TnyDevice *device = tny_account_store_get_device (store); +/* TnyDevice *device = tny_account_store_get_device (store); */ - /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */ +/* /\* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); *\/ */ - /* Check that we are really online. - * This signal should not be emitted when we are not connected, - * but it seems to happen sometimes: */ - if (!tny_device_is_online (device)) - return; +/* /\* Check that we are really online. */ +/* * This signal should not be emitted when we are not connected, */ +/* * but it seems to happen sometimes: *\/ */ +/* if (!tny_device_is_online (device)) */ +/* return; */ - const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device)); - printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id); +/* const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device)); */ +/* printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id); */ - /* Stop the existing send queues: */ - modest_runtime_remove_all_send_queues (); +/* /\* Stop the existing send queues: *\/ */ +/* modest_runtime_remove_all_send_queues (); */ - /* Create the send queues again, using the appropriate transport accounts - * for this new connection. - * This could be the first time that they are created if this is the first - * connection. */ - /* TODO: Does this really destroy the TnySendQueues and their threads - * We do not want 2 TnySendQueues to exist with the same underlying - * outbox directory. */ - - modest_main_window_cleanup_queue_error_signals (self); - - GSList *account_names = modest_account_mgr_account_names ( - modest_runtime_get_account_mgr(), - TRUE /* enabled accounts only */); - GSList *iter = account_names; - while (iter) { - const gchar *account_name = (const gchar*)(iter->data); - if (account_name) { - TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT ( - modest_tny_account_store_get_transport_account_for_open_connection - (modest_runtime_get_account_store(), account_name)); - if (account) { - /* Q: Is this the first location where the send-queues are requested? */ - QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal); - printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name, - tny_account_get_id(TNY_ACCOUNT(account))); - esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account)); - esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened", - G_CALLBACK (on_sendqueue_error_happened), self); - priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal); - } - } +/* /\* Create the send queues again, using the appropriate transport accounts */ +/* * for this new connection. */ +/* * This could be the first time that they are created if this is the first */ +/* * connection. *\/ */ +/* /\* TODO: Does this really destroy the TnySendQueues and their threads */ +/* * We do not want 2 TnySendQueues to exist with the same underlying */ +/* * outbox directory. *\/ */ + +/* modest_main_window_cleanup_queue_error_signals (self); */ + +/* GSList *account_names = modest_account_mgr_account_names ( */ +/* modest_runtime_get_account_mgr(), */ +/* TRUE /\* enabled accounts only *\/); */ +/* GSList *iter = account_names; */ +/* while (iter) { */ +/* const gchar *account_name = (const gchar*)(iter->data); */ +/* if (account_name) { */ +/* TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT ( */ +/* modest_tny_account_store_get_transport_account_for_open_connection */ +/* (modest_runtime_get_account_store(), account_name)); */ +/* if (account) { */ +/* /\* Q: Is this the first location where the send-queues are requested? *\/ */ +/* QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal); */ +/* printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name, */ +/* tny_account_get_id(TNY_ACCOUNT(account))); */ +/* esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account)); */ +/* esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened", */ +/* G_CALLBACK (on_sendqueue_error_happened), self); */ +/* priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal); */ +/* } */ +/* } */ - iter = g_slist_next (iter); - } +/* iter = g_slist_next (iter); */ +/* } */ - modest_account_mgr_free_account_names (account_names); - account_names = NULL; +/* modest_account_mgr_free_account_names (account_names); */ +/* account_names = NULL; */ - modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self)); -} +/* modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self)); */ +/* } */ static void _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data) @@ -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,13 +711,18 @@ 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); /* Track account changes. We need to refresh the toolbar */ g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()), - "account_update", G_CALLBACK (on_account_update), + "account_inserted", G_CALLBACK (account_number_changed), + self); + g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()), + "account_removed", G_CALLBACK (account_number_changed), self); /* Account store */ @@ -698,10 +730,10 @@ connect_signals (ModestMainWindow *self) "password_requested", G_CALLBACK (modest_ui_actions_on_password_requested), self); - /* Device */ - g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), - "connecting-finished", - G_CALLBACK(on_account_store_connecting_finished), self); +/* /\* Device *\/ */ +/* g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), */ +/* "connecting-finished", */ +/* G_CALLBACK(on_account_store_connecting_finished), self); */ } #if 0 @@ -1194,7 +1226,7 @@ modest_main_window_show_toolbar (ModestWindow *self, gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0); /* Set send & receive button tap and hold menu */ - on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), + account_number_changed (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), NULL, self); } @@ -1218,9 +1250,9 @@ compare_display_names (ModestAccountData *a, } static void -on_account_update (TnyAccountStore *account_store, - const gchar *account_name, - gpointer user_data) +account_number_changed (TnyAccountStore *account_store, + const gchar *account_name, + gpointer user_data) { GSList *account_names, *iter, *accounts; ModestMainWindow *self; @@ -1433,7 +1465,7 @@ on_account_update (TnyAccountStore *account_store, for (i = 0; i < num_accounts; i++) { ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i); - if(account_data->account_name && + if(account_data->account_name && default_account && strcmp (account_data->account_name, default_account) == 0) { gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL); @@ -1861,17 +1893,18 @@ 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; + ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); 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); - if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) return; diff --git a/src/maemo/modest-msg-edit-window.c b/src/maemo/modest-msg-edit-window.c index de7e2a2..da94164 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); @@ -321,10 +322,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 @@ -556,17 +556,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); @@ -674,7 +682,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 762eb10..1baeaa2 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 97fcacf..73d4c1f 100644 --- a/src/maemo/modest-platform.c +++ b/src/maemo/modest-platform.c @@ -60,8 +60,11 @@ static osso_context_t *osso_context = NULL; 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 = @@ -140,7 +143,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", @@ -149,7 +158,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)) { @@ -1337,10 +1346,11 @@ modest_platform_create_folder_view (TnyFolderStoreQuery *query) { GtkWidget *widget = modest_folder_view_new (query); - /* Show all accounts by default */ + /* Show one account by default */ modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE); + /* Restore settings */ modest_widget_memory_restore (modest_runtime_get_conf(), G_OBJECT (widget), diff --git a/src/modest-account-mgr-helpers.c b/src/modest-account-mgr-helpers.c index 5d05bb4..6d08c40 100644 --- a/src/modest-account-mgr-helpers.c +++ b/src/modest-account-mgr-helpers.c @@ -593,9 +593,7 @@ modest_account_mgr_set_default_account (ModestAccountMgr *self, const gchar* ac conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf; - return modest_conf_set_string (conf, MODEST_CONF_DEFAULT_ACCOUNT, - account, NULL); - + return modest_conf_set_string (conf, MODEST_CONF_DEFAULT_ACCOUNT, account, NULL); } gboolean 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 46ed9d4..624bff0 100644 --- a/src/modest-account-mgr.c +++ b/src/modest-account-mgr.c @@ -37,108 +37,109 @@ static void modest_account_mgr_class_init (ModestAccountMgrClass * klass); static void modest_account_mgr_init (ModestAccountMgr * obj); static void modest_account_mgr_finalize (GObject * obj); +static void modest_account_mgr_base_init (gpointer g_class); /* list my signals */ enum { + ACCOUNT_INSERTED_SIGNAL, ACCOUNT_CHANGED_SIGNAL, ACCOUNT_REMOVED_SIGNAL, ACCOUNT_BUSY_SIGNAL, LAST_SIGNAL }; - /* globals */ static GObjectClass *parent_class = NULL; static guint signals[LAST_SIGNAL] = {0}; -/* We signal key changes in batches, every X seconds: */ -static gboolean -on_timeout_notify_changes (gpointer data) -{ - ModestAccountMgr *self = MODEST_ACCOUNT_MGR (data); - ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); +/* /\* We signal key changes in batches, every X seconds: *\/ */ +/* static gboolean */ +/* on_timeout_notify_changes (gpointer data) */ +/* { */ +/* ModestAccountMgr *self = MODEST_ACCOUNT_MGR (data); */ +/* ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); */ - /* TODO: Also store the account names, and notify one list for each account, - * if anything uses the account names. */ +/* /\* TODO: Also store the account names, and notify one list for each account, */ +/* * if anything uses the account names. *\/ */ - if (priv->changed_conf_keys) { - gchar *default_account = - modest_account_mgr_get_default_account (self); +/* if (priv->changed_conf_keys) { */ +/* gchar *default_account = */ +/* modest_account_mgr_get_default_account (self); */ - /* printf ("DEBUG: %s: priv->changed_conf_key length=%d\n", - __FUNCTION__, g_slist_length (priv->changed_conf_keys)); */ - g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0, - default_account, priv->changed_conf_keys, FALSE); +/* /\* printf ("DEBUG: %s: priv->changed_conf_key length=%d\n", */ +/* __FUNCTION__, g_slist_length (priv->changed_conf_keys)); *\/ */ +/* g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0, */ +/* default_account, priv->changed_conf_keys, FALSE); */ - g_free (default_account); +/* g_free (default_account); */ - g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); - g_slist_free (priv->changed_conf_keys); - priv->changed_conf_keys = NULL; - } +/* g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); */ +/* g_slist_free (priv->changed_conf_keys); */ +/* priv->changed_conf_keys = NULL; */ +/* } */ - return TRUE; /* Call this again later. */ -} - -static void -on_key_change (ModestConf *conf, const gchar *key, ModestConfEvent event, gpointer user_data) -{ - ModestAccountMgr *self = MODEST_ACCOUNT_MGR (user_data); - ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); - gboolean is_account_key; - gboolean is_server_account; - gchar* account = NULL; - - /* there is only one not-really-account key which will still emit - * a signal: a change in MODEST_CONF_DEFAULT_ACCOUNT */ - if (key && strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) { - /* Get the default account instead. */ +/* return TRUE; /\* Call this again later. *\/ */ +/* } */ + +/* static void */ +/* on_key_change (ModestConf *conf, const gchar *key, ModestConfEvent event, gpointer user_data) */ +/* { */ +/* ModestAccountMgr *self = MODEST_ACCOUNT_MGR (user_data); */ +/* ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); */ +/* gboolean is_account_key; */ +/* gboolean is_server_account; */ +/* gchar* account = NULL; */ + +/* /\* there is only one not-really-account key which will still emit */ +/* * a signal: a change in MODEST_CONF_DEFAULT_ACCOUNT *\/ */ +/* if (key && strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) { */ +/* /\* Get the default account instead. *\/ */ - /* Store the key for later notification in our timeout callback. - * Notifying for every key change would cause unnecessary work: */ - priv->changed_conf_keys = g_slist_append (priv->changed_conf_keys, - (gpointer) g_strdup (key)); - } +/* /\* Store the key for later notification in our timeout callback. */ +/* * Notifying for every key change would cause unnecessary work: *\/ */ +/* priv->changed_conf_keys = g_slist_append (priv->changed_conf_keys, */ +/* (gpointer) g_strdup (key)); */ +/* } */ - is_account_key = FALSE; - is_server_account = FALSE; - account = _modest_account_mgr_account_from_key (key, &is_account_key, - &is_server_account); - - /* if this is not an account-related key change, ignore */ - if (!account) - return; - - /* account was removed. Do not emit an account removed signal - because it was already being done in the remove_account - method. Do not notify also the removal of the server - account keys for the same reason */ - if ((is_account_key || is_server_account) && - event == MODEST_CONF_EVENT_KEY_UNSET) { - g_free (account); - return; - } - - /* is this account enabled? */ - gboolean enabled = FALSE; - if (is_server_account) - enabled = TRUE; - else - enabled = modest_account_mgr_get_enabled (self, account); - - /* Notify is server account was changed, default account was changed - * or when enabled/disabled changes: - */ - if (enabled || - g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) || - strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) { - /* Store the key for later notification in our timeout callback. - * Notifying for every key change would cause unnecessary work: */ - priv->changed_conf_keys = g_slist_append (NULL, - (gpointer) g_strdup (key)); - } - g_free (account); -} +/* is_account_key = FALSE; */ +/* is_server_account = FALSE; */ +/* account = _modest_account_mgr_account_from_key (key, &is_account_key, */ +/* &is_server_account); */ + +/* /\* if this is not an account-related key change, ignore *\/ */ +/* if (!account) */ +/* return; */ + +/* /\* account was removed. Do not emit an account removed signal */ +/* because it was already being done in the remove_account */ +/* method. Do not notify also the removal of the server */ +/* account keys for the same reason *\/ */ +/* if ((is_account_key || is_server_account) && */ +/* event == MODEST_CONF_EVENT_KEY_UNSET) { */ +/* g_free (account); */ +/* return; */ +/* } */ + +/* /\* is this account enabled? *\/ */ +/* gboolean enabled = FALSE; */ +/* if (is_server_account) */ +/* enabled = TRUE; */ +/* else */ +/* enabled = modest_account_mgr_get_enabled (self, account); */ + +/* /\* Notify is server account was changed, default account was changed */ +/* * or when enabled/disabled changes: */ +/* *\/ */ +/* if (enabled || */ +/* g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) || */ +/* strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) { */ +/* /\* Store the key for later notification in our timeout callback. */ +/* * Notifying for every key change would cause unnecessary work: *\/ */ +/* priv->changed_conf_keys = g_slist_append (NULL, */ +/* (gpointer) g_strdup (key)); */ +/* } */ +/* g_free (account); */ +/* } */ GType @@ -149,7 +150,7 @@ modest_account_mgr_get_type (void) if (!my_type) { static const GTypeInfo my_info = { sizeof (ModestAccountMgrClass), - NULL, /* base init */ + modest_account_mgr_base_init, /* base init */ NULL, /* base finalize */ (GClassInitFunc) modest_account_mgr_class_init, NULL, /* class finalize */ @@ -167,6 +168,53 @@ modest_account_mgr_get_type (void) return my_type; } +static void +modest_account_mgr_base_init (gpointer g_class) +{ + static gboolean modest_account_mgr_initialized = FALSE; + + if (!modest_account_mgr_initialized) { + /* signal definitions */ + signals[ACCOUNT_INSERTED_SIGNAL] = + g_signal_new ("account_inserted", + MODEST_TYPE_ACCOUNT_MGR, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestAccountMgrClass,account_inserted), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[ACCOUNT_REMOVED_SIGNAL] = + g_signal_new ("account_removed", + MODEST_TYPE_ACCOUNT_MGR, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestAccountMgrClass,account_removed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[ACCOUNT_CHANGED_SIGNAL] = + g_signal_new ("account_changed", + MODEST_TYPE_ACCOUNT_MGR, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestAccountMgrClass,account_changed), + NULL, NULL, + modest_marshal_VOID__STRING_POINTER_BOOLEAN, + G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); + + signals[ACCOUNT_BUSY_SIGNAL] = + g_signal_new ("account_busy_changed", + MODEST_TYPE_ACCOUNT_MGR, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestAccountMgrClass,account_busy_changed), + NULL, NULL, + modest_marshal_VOID__STRING_BOOLEAN, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN); + + modest_account_mgr_initialized = TRUE; + } +} + static void modest_account_mgr_class_init (ModestAccountMgrClass * klass) { @@ -178,32 +226,6 @@ modest_account_mgr_class_init (ModestAccountMgrClass * klass) g_type_class_add_private (gobject_class, sizeof (ModestAccountMgrPrivate)); - - /* signal definitions */ - signals[ACCOUNT_REMOVED_SIGNAL] = - g_signal_new ("account_removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestAccountMgrClass,account_removed), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - signals[ACCOUNT_CHANGED_SIGNAL] = - g_signal_new ("account_changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestAccountMgrClass,account_changed), - NULL, NULL, - modest_marshal_VOID__STRING_POINTER_BOOLEAN, - G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); - signals[ACCOUNT_BUSY_SIGNAL] = - g_signal_new ("account_busy_changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestAccountMgrClass,account_busy_changed), - NULL, NULL, - modest_marshal_VOID__STRING_BOOLEAN, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN); } @@ -215,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 @@ -224,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); @@ -235,13 +264,13 @@ modest_account_mgr_finalize (GObject * obj) priv->modest_conf = NULL; } - if (priv->timeout) - g_source_remove (priv->timeout); +/* 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); } @@ -261,10 +290,10 @@ modest_account_mgr_new (ModestConf *conf) g_object_ref (G_OBJECT(conf)); priv->modest_conf = conf; - priv->key_changed_handler_uid = - g_signal_connect (G_OBJECT (conf), "key_changed", - G_CALLBACK (on_key_change), - obj); +/* priv->key_changed_handler_uid = */ +/* g_signal_connect (G_OBJECT (conf), "key_changed", */ +/* G_CALLBACK (on_key_change), */ +/* obj); */ return MODEST_ACCOUNT_MGR (obj); } @@ -358,6 +387,9 @@ modest_account_mgr_add_account (ModestAccountMgr *self, modest_account_mgr_set_enabled (self, name, enabled); + /* Notify the observers */ + g_signal_emit (self, signals[ACCOUNT_INSERTED_SIGNAL], 0, name); + /* if no default account has been defined yet, do so now */ default_account = modest_account_mgr_get_default_account (self); if (!default_account) diff --git a/src/modest-account-mgr.h b/src/modest-account-mgr.h index 9fc6e16..f93a712 100644 --- a/src/modest-account-mgr.h +++ b/src/modest-account-mgr.h @@ -56,6 +56,10 @@ struct _ModestAccountMgr { struct _ModestAccountMgrClass { GObjectClass parent_class; + void (* account_inserted) (ModestAccountMgr *obj, + const gchar* account, + gpointer user_data); + void (* account_removed) (ModestAccountMgr *obj, const gchar* account, gpointer user_data); @@ -67,9 +71,9 @@ struct _ModestAccountMgrClass { gpointer user_data); void (* account_busy_changed) (ModestAccountMgr *obj, - const gchar* account, - gboolean busy, - gpointer user_data); + const gchar* account, + gboolean busy, + gpointer user_data); }; /** 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 b3161ce..9d48dae 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -1752,8 +1752,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, @@ -2636,7 +2636,6 @@ on_refresh_folder (TnyFolder *folder, } /* Free */ -/* g_object_unref (helper->mail_op); */ g_slice_free (RefreshAsyncHelper, helper); /* Notify about operation end */ @@ -2695,7 +2694,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 9426354..b53ff07 100644 --- a/src/modest-tny-account-store.c +++ b/src/modest-tny-account-store.c @@ -73,22 +73,56 @@ #include /* 'private'/'protected' functions */ -static void modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass); -//static void modest_tny_account_store_init (ModestTnyAccountStore *obj); -static void modest_tny_account_store_finalize (GObject *obj); +static void modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass); + +static void modest_tny_account_store_finalize (GObject *obj); -/* implementations for tny-account-store-iface */ static void modest_tny_account_store_instance_init (ModestTnyAccountStore *obj); + static void modest_tny_account_store_init (gpointer g, gpointer iface_data); +static void modest_tny_account_store_base_init (gpointer g_class); + +static void on_account_inserted (ModestAccountMgr *acc_mgr, + const gchar *account, + gpointer user_data); + +static void add_existing_accounts (ModestTnyAccountStore *self); + +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 get_server_accounts (TnyAccountStore *self, - TnyList *list, - TnyAccountType type); +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 { - ACCOUNT_UPDATE_SIGNAL, + ACCOUNT_CHANGED_SIGNAL, + ACCOUNT_INSERTED_SIGNAL, + ACCOUNT_REMOVED_SIGNAL, + PASSWORD_REQUESTED_SIGNAL, LAST_SIGNAL }; @@ -101,18 +135,17 @@ struct _ModestTnyAccountStorePrivate { ModestAccountMgr *account_mgr; TnySessionCamel *session; TnyDevice *device; + + 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. */ - GSList *store_accounts; - GSList *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: - */ - GSList *store_accounts_outboxes; + /* We cache the lists of accounts here */ + TnyList *store_accounts; + TnyList *transport_accounts; + TnyList *store_accounts_outboxes; }; #define MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ @@ -132,7 +165,7 @@ modest_tny_account_store_get_type (void) if (!my_type) { static const GTypeInfo my_info = { sizeof(ModestTnyAccountStoreClass), - NULL, /* base init */ + modest_tny_account_store_base_init, /* base init */ NULL, /* base finalize */ (GClassInitFunc) modest_tny_account_store_class_init, NULL, /* class finalize */ @@ -158,6 +191,65 @@ modest_tny_account_store_get_type (void) return my_type; } + +static void +modest_tny_account_store_base_init (gpointer g_class) +{ + static gboolean tny_account_store_initialized = FALSE; + + if (!tny_account_store_initialized) { + + signals[ACCOUNT_CHANGED_SIGNAL] = + g_signal_new ("account_changed", + MODEST_TYPE_TNY_ACCOUNT_STORE, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestTnyAccountStoreClass, account_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); + + signals[ACCOUNT_INSERTED_SIGNAL] = + g_signal_new ("account_inserted", + MODEST_TYPE_TNY_ACCOUNT_STORE, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestTnyAccountStoreClass, account_inserted), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); + + signals[ACCOUNT_REMOVED_SIGNAL] = + g_signal_new ("account_removed", + MODEST_TYPE_TNY_ACCOUNT_STORE, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestTnyAccountStoreClass, account_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, TNY_TYPE_ACCOUNT); + +/* signals[TNY_ACCOUNT_STORE_CONNECTING_FINISHED] = */ +/* g_signal_new ("connecting_finished", */ +/* TNY_TYPE_ACCOUNT_STORE, */ +/* G_SIGNAL_RUN_FIRST, */ +/* G_STRUCT_OFFSET (TnyAccountStoreIface, connecting_finished), */ +/* NULL, NULL, */ +/* g_cclosure_marshal_VOID__VOID, */ +/* G_TYPE_NONE, 0); */ + + signals[PASSWORD_REQUESTED_SIGNAL] = + g_signal_new ("password_requested", + MODEST_TYPE_TNY_ACCOUNT_STORE, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(ModestTnyAccountStoreClass, password_requested), + NULL, NULL, + modest_marshal_VOID__STRING_POINTER_POINTER_POINTER_POINTER, + G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, + G_TYPE_POINTER); + + tny_account_store_initialized = TRUE; + } +} + + static void modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass) { @@ -169,42 +261,15 @@ modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass) g_type_class_add_private (gobject_class, sizeof(ModestTnyAccountStorePrivate)); - - signals[ACCOUNT_UPDATE_SIGNAL] = - g_signal_new ("account_update", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestTnyAccountStoreClass, account_update), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - signals[PASSWORD_REQUESTED_SIGNAL] = - g_signal_new ("password_requested", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(ModestTnyAccountStoreClass, password_requested), - NULL, NULL, - modest_marshal_VOID__STRING_POINTER_POINTER_POINTER_POINTER, - G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, - G_TYPE_POINTER); } - - 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; @@ -215,169 +280,138 @@ 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); -} - -static void -account_list_free (GSList *accounts) -{ - GSList *cursor = accounts; - - while (cursor) { - if (G_IS_OBJECT(cursor->data)) { /* check twice... */ - const gchar *id = tny_account_get_id(TNY_ACCOUNT(cursor->data)); - modest_runtime_verify_object_last_ref(cursor->data,id); - } - g_object_unref (G_OBJECT(cursor->data)); - cursor = cursor->next; - } - g_slist_free (accounts); -} + 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 */ static void -account_list_disconnect (GSList *accounts) +foreach_account_disconnect (gpointer data, + gpointer user_data) { - GSList *cursor = accounts; - - while (cursor) { - if (TNY_IS_CAMEL_ACCOUNT(cursor->data)) /* check twice... */ - tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(cursor->data), FALSE, NULL); - cursor = g_slist_next (cursor); - } + tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(data), FALSE, NULL); } - static void -recreate_all_accounts (ModestTnyAccountStore *self) +foreach_account_append_to_list (gpointer data, + gpointer user_data) { - /* printf ("DEBUG: %s\n", __FUNCTION__); */ - - ModestTnyAccountStorePrivate *priv = - MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - if (priv->store_accounts_outboxes) { - account_list_free (priv->store_accounts_outboxes); - priv->store_accounts_outboxes = NULL; - } - - - if (priv->store_accounts) { - account_list_free (priv->store_accounts); - priv->store_accounts = NULL; - } - - get_server_accounts (TNY_ACCOUNT_STORE(self), - NULL, TNY_ACCOUNT_TYPE_STORE); - - - if (priv->transport_accounts) { - account_list_free (priv->transport_accounts); - priv->transport_accounts = NULL; - } - - get_server_accounts (TNY_ACCOUNT_STORE(self), NULL, - TNY_ACCOUNT_TYPE_TRANSPORT); + TnyList *list; + + list = TNY_LIST (user_data); + tny_list_append (list, G_OBJECT (data)); } +/********************************************************************/ +/* Control the state of the MMC local account */ +/********************************************************************/ static void on_vfs_volume_mounted(GnomeVFSVolumeMonitor *volume_monitor, - GnomeVFSVolume *volume, gpointer user_data) + 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); - - g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, - NULL); + 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); } static void on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor, - GnomeVFSVolume *volume, gpointer user_data) + 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); + 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); - } - - g_free (uri); -} - -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); - - /* Clear the cache */ - tny_store_account_delete_cache (TNY_STORE_ACCOUNT (store_account)); + TnyAccount *mmc_account = NULL; + gboolean found = FALSE; + TnyIterator *iter = NULL; + + iter = tny_list_create_iterator (priv->store_accounts); + while (!tny_iterator_is_done (iter) && !found) { + TnyAccount *account; + + 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); - /* Notify the observers */ - g_signal_emit (G_OBJECT (self), - tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_REMOVED], - 0, store_account); - g_signal_emit (G_OBJECT (self), - tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_REMOVED], - 0, transport_account); + if (found) { + /* Remove from the list */ + tny_list_remove (priv->store_accounts, G_OBJECT (mmc_account)); /* Make sure that the account is reviewed from the View menu, etc: */ g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, NULL); - /* Frees */ - g_object_unref (store_account); - g_object_unref (transport_account); + /* Notify observers */ + g_signal_emit (G_OBJECT (self), + signals [ACCOUNT_REMOVED_SIGNAL], + 0, mmc_account); + + g_object_unref (mmc_account); + } else { + g_warning ("%s: there was no store account for the unmounted MMC", + __FUNCTION__); + } + } + g_free (uri); } /** @@ -400,9 +434,11 @@ modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, } static void -on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account, - const GSList *keys, gboolean server_account, gpointer user_data) - +on_account_changed (ModestAccountMgr *acc_mgr, + const gchar *account, + const GSList *keys, + gboolean server_account, + gpointer user_data) { printf ("DEBUG: modest: %s\n", __FUNCTION__); @@ -426,7 +462,7 @@ on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account, /* 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: @@ -442,20 +478,11 @@ on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account, } #endif - g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0, - account); + g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_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")); -} - -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; @@ -469,8 +496,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(); @@ -486,8 +513,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: */ @@ -649,7 +676,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", @@ -770,7 +798,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); @@ -791,26 +820,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; @@ -819,10 +833,33 @@ 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 */ + if (g_signal_handler_is_connected (priv->account_mgr, + priv->acc_inserted_handler)) + g_signal_handler_disconnect (priv->account_mgr, + priv->acc_inserted_handler); + if (g_signal_handler_is_connected (priv->account_mgr, + priv->acc_changed_handler)) + g_signal_handler_disconnect (priv->account_mgr, + priv->acc_changed_handler); + if (g_signal_handler_is_connected (priv->account_mgr, + priv->acc_removed_handler)) + g_signal_handler_disconnect (priv->account_mgr, + priv->acc_removed_handler); + g_object_unref (G_OBJECT(priv->account_mgr)); priv->account_mgr = NULL; } @@ -832,19 +869,24 @@ modest_tny_account_store_finalize (GObject *obj) priv->device = NULL; } - /* disconnect all accounts when we are destroyed */ - g_debug ("modest: disconnecting all store accounts"); - account_list_disconnect (priv->store_accounts); - g_debug ("modest: disconnecting all transport accounts"); - account_list_disconnect (priv->transport_accounts); - - /* this includes the local folder */ - account_list_free (priv->store_accounts); - priv->store_accounts = NULL; - - account_list_free (priv->transport_accounts); - priv->transport_accounts = NULL; + /* Destroy all accounts. Disconnect all accounts before they are destroyed */ + if (priv->store_accounts) { + tny_list_foreach (priv->store_accounts, foreach_account_disconnect, NULL); + g_object_unref (priv->store_accounts); + priv->store_accounts = NULL; + } + if (priv->transport_accounts) { + tny_list_foreach (priv->transport_accounts, foreach_account_disconnect, NULL); + 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)); priv->session = NULL; @@ -855,11 +897,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); @@ -875,290 +918,40 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr, TnyDevice *device) g_warning ("failed to get TnySessionCamel"); return NULL; } - + + /* Set the ui locker */ tny_session_camel_set_ui_locker (priv->session, tny_gtk_lockable_new ()); - tny_session_camel_set_async_connecting (priv->session, TRUE); /* Connect signals */ - g_signal_connect (G_OBJECT(account_mgr), "account_changed", - G_CALLBACK (on_account_changed), obj); - g_signal_connect (G_OBJECT(account_mgr), "account_removed", - G_CALLBACK (on_account_removed), obj); + priv->acc_inserted_handler = g_signal_connect (G_OBJECT(account_mgr), "account_inserted", + G_CALLBACK (on_account_inserted), obj); + priv->acc_changed_handler = g_signal_connect (G_OBJECT(account_mgr), "account_changed", + G_CALLBACK (on_account_changed), obj); + priv->acc_removed_handler = g_signal_connect (G_OBJECT(account_mgr), "account_removed", + G_CALLBACK (on_account_removed), 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 (); + + /* 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 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)); return MODEST_TNY_ACCOUNT_STORE(obj); } -/** Fill the TnyList from the appropriate cached GSList of accounts. */ -static void -get_cached_accounts (TnyAccountStore *self, TnyList *list, TnyAccountType type) -{ - ModestTnyAccountStorePrivate *priv; - GSList *accounts, *cursor; - - priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - accounts = (type == TNY_ACCOUNT_TYPE_STORE ? priv->store_accounts : priv->transport_accounts); - - cursor = accounts; - while (cursor) { - if (cursor->data) { - GObject *object = G_OBJECT(cursor->data); - tny_list_prepend (list, object); - } - - cursor = cursor->next; - } -} - static void -create_per_account_local_outbox_folders (TnyAccountStore *self) -{ - g_return_if_fail (self); - - ModestTnyAccountStorePrivate *priv = - MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - - /* printf("DEBUG: %s: priv->store_accounts_outboxes = %p\n", __FUNCTION__, priv->store_accounts_outboxes); */ - - GSList *accounts = NULL; - - GSList *account_names = modest_account_mgr_account_names (priv->account_mgr, - TRUE /* including disabled accounts */); - - GSList *iter = NULL; - for (iter = account_names; iter; iter = g_slist_next (iter)) { - - const gchar* account_name = (const gchar*)iter->data; - - /* Create a per-account local outbox folder (a _store_ account) - * for each _transport_ account: */ - TnyAccount *tny_account_outbox = - modest_tny_account_new_for_per_account_local_outbox_folder ( - priv->account_mgr, account_name, priv->session); - - accounts = g_slist_append (accounts, tny_account_outbox); /* cache it */ - }; - - modest_account_mgr_free_account_names (account_names); - account_names = NULL; - - 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) -{ - g_return_if_fail (self); - - ModestTnyAccountStorePrivate *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 (type == TNY_ACCOUNT_TYPE_TRANSPORT) { - if (priv->transport_accounts) - return; - } - - GSList *account_names = NULL, *cursor = NULL; - GSList *accounts = NULL; - - /* These are account names, not server_account names */ - 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); - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - - accounts = g_slist_append (accounts, tny_account); /* cache it */ - } 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); - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - accounts = g_slist_append (accounts, tny_account); /* cache it */ - } - } - - /* 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); - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - - accounts = g_slist_append (accounts, tny_account); /* cache it */ - } 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 (type == TNY_ACCOUNT_TYPE_TRANSPORT) { - /* Now would be a good time to create the per-account local outbox folder - * _store_ accounts corresponding to 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) { - /* Create them if necessary, - * (which also requires creating the transport accounts, - * if necessary.) */ - if (!priv->store_accounts_outboxes) { - create_per_account_local_outbox_folders (self); - } - - /* 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) { - GSList *iter = NULL; - for (iter = priv->store_accounts_outboxes; iter; iter = g_slist_next (iter)) { - TnyAccount *outbox_account = (TnyAccount*)iter->data; - if (list && outbox_account) - tny_list_prepend (list, G_OBJECT(outbox_account)); - - g_object_ref (outbox_account); - accounts = g_slist_append (accounts, outbox_account); - } - } - - /* 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: */ - account_list_free (priv->store_accounts_outboxes); - priv->store_accounts_outboxes = NULL; - } - - if (list) - tny_list_prepend (list, G_OBJECT(tny_account)); - accounts = g_slist_append (accounts, tny_account); /* cache it */ - } - - if (type == TNY_ACCOUNT_TYPE_STORE) { - /* Store the cache: */ - priv->store_accounts = accounts; - } else if (type == TNY_ACCOUNT_TYPE_TRANSPORT) { - /* Store the cache: */ - priv->transport_accounts = accounts; - } -} - - -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; @@ -1168,34 +961,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); } @@ -1442,93 +1224,83 @@ modest_tny_account_store_get_session (TnyAccountStore *self) return MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self)->session; } - - -TnyAccount* -modest_tny_account_store_get_tny_account_by (ModestTnyAccountStore *self, - ModestTnyAccountStoreQueryType type, - const gchar *str) +static TnyAccount* +get_tny_account_by (TnyList *accounts, + ModestTnyAccountStoreQueryType type, + const gchar *str) { - TnyAccount *account = NULL; - ModestTnyAccountStorePrivate *priv; - GSList *cursor; - const gchar *val = NULL; - TnyList* list; - - - g_return_val_if_fail (self, NULL); - g_return_val_if_fail (str, NULL); - - priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + TnyIterator *iter = NULL; + gboolean found = FALSE; + TnyAccount *retval = NULL; - /* 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); + iter = tny_list_create_iterator (accounts); + while (!tny_iterator_is_done (iter) && !found) { + TnyAccount *tmp_account = NULL; + const gchar *val = NULL; - - - /* Search in store accounts */ - for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) { + tmp_account = TNY_ACCOUNT (tny_iterator_get_current (iter)); switch (type) { case MODEST_TNY_ACCOUNT_STORE_QUERY_ID: - val = tny_account_get_id (TNY_ACCOUNT(cursor->data)); + val = tny_account_get_id (tmp_account); break; case MODEST_TNY_ACCOUNT_STORE_QUERY_URL: - val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data)); + val = tny_account_get_url_string (tmp_account); break; } if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && - tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), str)) { - account = TNY_ACCOUNT (cursor->data); - goto end; + tny_account_matches_url_string (tmp_account, str)) { + retval = g_object_ref (tmp_account); + found = TRUE; } else { if (strcmp (val, str) == 0) { - account = TNY_ACCOUNT(cursor->data); - goto end; + retval = g_object_ref (tmp_account); + found = TRUE; } } + g_object_unref (tmp_account); + tny_iterator_next (iter); } - - /* if we already found something, no need to search the transport accounts */ - for (cursor = priv->transport_accounts; !account && cursor ; cursor = cursor->next) { - switch (type) { - case MODEST_TNY_ACCOUNT_STORE_QUERY_ID: - val = tny_account_get_id (TNY_ACCOUNT(cursor->data)); - break; - case MODEST_TNY_ACCOUNT_STORE_QUERY_URL: - val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data)); - break; - } - - if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && - tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), val)) { - account = TNY_ACCOUNT (cursor->data); - goto end; - } else { - if (strcmp (val, str) == 0) { - account = TNY_ACCOUNT(cursor->data); - goto end; - } - } + g_object_unref (iter); + + return retval; +} + +TnyAccount* +modest_tny_account_store_get_tny_account_by (ModestTnyAccountStore *self, + ModestTnyAccountStoreQueryType type, + const gchar *str) +{ + TnyAccount *account = NULL; + ModestTnyAccountStorePrivate *priv; + + g_return_val_if_fail (self, NULL); + g_return_val_if_fail (str, NULL); + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); + + /* 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); } - end: - if (account) - g_object_ref (G_OBJECT(account)); - else { - /* Warn if nothing was found. This is generally unusual. */ - 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; - } + + /* Warn if nothing was found. This is generally unusual. */ + if (!account) { + 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 */ return account; } @@ -1538,9 +1310,10 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self, TnyAccountType type) { ModestTnyAccountStorePrivate *priv = NULL; - TnyAccount *account = NULL; - GSList *account_list = NULL; - gboolean found = FALSE; + TnyAccount *retval = NULL; + TnyList *account_list = NULL; + TnyIterator *iter = NULL; + gboolean found; g_return_val_if_fail (self, NULL); g_return_val_if_fail (account_name, NULL); @@ -1550,12 +1323,6 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self, priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - /* Make sure that the tny accounts have been created: - * TODO: We might want to do this in several places. - */ - if (!priv->store_accounts || !priv->transport_accounts) - recreate_all_accounts (self); - account_list = (type == TNY_ACCOUNT_TYPE_STORE) ? priv->store_accounts : priv->transport_accounts; @@ -1567,29 +1334,34 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self, } /* Look for the server account */ - while (account_list && !found) { + found = FALSE; + iter = tny_list_create_iterator (account_list); + while (!tny_iterator_is_done (iter) && !found) { const gchar *modest_acc_name; + TnyAccount *tmp_account; - account = TNY_ACCOUNT (account_list->data); + tmp_account = TNY_ACCOUNT (tny_iterator_get_current (iter)); modest_acc_name = - modest_tny_account_get_parent_modest_account_name_for_server_account (account); + modest_tny_account_get_parent_modest_account_name_for_server_account (tmp_account); - if (!strcmp (account_name, modest_acc_name)) + if (!strcmp (account_name, modest_acc_name)) { found = TRUE; - else - account_list = g_slist_next (account_list); + retval = g_object_ref (tmp_account); + } + /* Free and continue */ + g_object_unref (tmp_account); + tny_iterator_next (iter); } if (!found) { - g_printerr ("modest: %s: could not get tny %s account for %s\n. Number of server accounts of this type=%d\n", __FUNCTION__, + g_printerr ("modest: %s: could not get tny %s account for %s\n." \ + "Number of server accounts of this type=%d\n", __FUNCTION__, (type == TNY_ACCOUNT_TYPE_STORE) ? "store" : "transport", - account_name, g_slist_length (account_list)); - } else { - /* Pick a reference */ - g_object_ref (account); + account_name, tny_list_get_length (account_list)); } - return account; + /* Returns a new reference */ + return retval; } static TnyAccount* @@ -1667,8 +1439,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; @@ -1680,51 +1450,252 @@ modest_tny_account_store_get_transport_account_for_open_connection (ModestTnyAcc return account; } -gboolean -modest_tny_account_is_virtual_local_folders (TnyAccount *self) +TnyAccount* +modest_tny_account_store_get_local_folders_account (ModestTnyAccountStore *self) { - /* We should make this more sophisticated if we ever use ModestTnyLocalFoldersAccount - * for anything else. */ - return MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self); -} + TnyAccount *account = NULL; + ModestTnyAccountStorePrivate *priv; + TnyIterator *iter; + gboolean found; + g_return_val_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (self), NULL); + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); -gboolean -modest_tny_account_is_memory_card_account (TnyAccount *self) -{ - if (!self) - return FALSE; + found = FALSE; + iter = tny_list_create_iterator (priv->store_accounts); + while (!tny_iterator_is_done (iter) && !found) { + TnyAccount *tmp_account; - const gchar* account_id = tny_account_get_id (self); - if (!account_id) - return FALSE; + tmp_account = TNY_ACCOUNT (tny_iterator_get_current (iter)); + if (modest_tny_account_is_virtual_local_folders (tmp_account)) { + account = g_object_ref (tmp_account); + found = TRUE; + } + g_object_unref (tmp_account); + tny_iterator_next (iter); + } + g_object_unref (iter); + + /* Returns a new reference to the account */ + return account; +} + +/*********************************************************************************/ +static void +add_existing_accounts (ModestTnyAccountStore *self) +{ + GSList *account_names = NULL, *iter = NULL; + ModestTnyAccountStorePrivate *priv = NULL; - return (strcmp (account_id, MODEST_MMC_ACCOUNT_ID) == 0); + 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); } -TnyAccount* -modest_tny_account_store_get_local_folders_account (TnyAccountStore *self) +static TnyAccount* +create_tny_account (ModestTnyAccountStore *self, + const gchar *name, + TnyAccountType type) { TnyAccount *account = NULL; - ModestTnyAccountStorePrivate *priv; - GSList *cursor; + ModestTnyAccountStorePrivate *priv = NULL; + + priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self); - g_return_val_if_fail (self, NULL); + 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); - for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) { - TnyAccount *this_account = TNY_ACCOUNT(cursor->data); - if (modest_tny_account_is_virtual_local_folders (this_account)) { - account = this_account; - break; - } + /* 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); } - if (account) - g_object_ref (G_OBJECT(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); - return account; + /* 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 6b01a28..76fbe91 100644 --- a/src/modest-tny-account-store.h +++ b/src/modest-tny-account-store.h @@ -75,6 +75,11 @@ struct _ModestTnyAccountStoreClass { gboolean *remember, gboolean *cancel, gpointer user_data); + + /* Signals */ + void (*account_changed) (TnyAccountStore *self, TnyAccount *account); + void (*account_inserted) (TnyAccountStore *self, TnyAccount *account); + void (*account_removed) (TnyAccountStore *self, TnyAccount *account); }; typedef enum { @@ -162,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 2efb499..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,154 +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, - GSList *accounts) +static TnyFolder* +create_folder (TnyFolderStore *self, + const gchar *name, + GError **err) { - 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: */ - TnyMergeFolder *merged_outbox = TNY_MERGE_FOLDER (tny_merge_folder_new(_("mcen_me_folder_outbox"))); - - /* Set type to outbox (NB#61580) */ - tny_merge_folder_set_folder_type (merged_outbox, TNY_FOLDER_TYPE_OUTBOX); - - GSList *iter = accounts; - while (iter) - { - TnyAccount *account = TNY_ACCOUNT (iter->data); - if (account) { - /* 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); - } - } - - iter = g_slist_next (iter); + TnyCamelStoreAccountClass *parent_class; + + 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; } - - /* Add the merged outbox folder to the virtual local-folders store: */ - /* printf ("Debug: %s: adding merged outbox.\n", __FUNCTION__); */ - modest_tny_local_folders_account_add_extra_folder (self, TNY_FOLDER(merged_outbox)); - g_object_unref (merged_outbox); - merged_outbox = NULL; + + /* 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 49b90de..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, - GSList *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 a1dace8..281699c 100644 --- a/src/modest-tny-send-queue.c +++ b/src/modest-tny-send-queue.c @@ -426,8 +426,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 fe4b4cc..03ae721 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 @@ -1708,11 +1709,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 fbac3d9..5fd4710 100644 --- a/src/widgets/modest-account-view.c +++ b/src/widgets/modest-account-view.c @@ -60,23 +60,14 @@ typedef enum { MODEST_ACCOUNT_VIEW_COLUMN_NUM } AccountViewColumns; - -/* list my signals */ -enum { - /* MY_SIGNAL_1, */ - /* MY_SIGNAL_2, */ - LAST_SIGNAL -}; - typedef struct _ModestAccountViewPrivate ModestAccountViewPrivate; struct _ModestAccountViewPrivate { ModestAccountMgr *account_mgr; - gulong sig1, sig2, sig3; - - /* When this is TRUE, we ignore configuration key changes. - * This is useful when making many changes. */ - gboolean block_conf_updates; - + + /* Signal handlers */ + gulong acc_inserted_handler; + gulong acc_removed_handler; + gulong sig3; }; #define MODEST_ACCOUNT_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_ACCOUNT_VIEW, \ @@ -84,9 +75,6 @@ struct _ModestAccountViewPrivate { /* globals */ static GtkTreeViewClass *parent_class = NULL; -/* uncomment the following if you have defined any signals */ -/* static guint signals[LAST_SIGNAL] = {0}; */ - GType modest_account_view_get_type (void) { @@ -131,8 +119,9 @@ modest_account_view_init (ModestAccountView *obj) priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); priv->account_mgr = NULL; - priv->sig1 = 0; - priv->sig2 = 0; + priv->acc_inserted_handler = 0; + priv->acc_removed_handler = 0; + priv->sig3 = 0; } static void @@ -143,12 +132,15 @@ modest_account_view_finalize (GObject *obj) priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE(obj); if (priv->account_mgr) { - if (priv->sig1) + if (g_signal_handler_is_connected (modest_runtime_get_account_store (), + priv->acc_inserted_handler)) g_signal_handler_disconnect (modest_runtime_get_account_store (), - priv->sig1); + priv->acc_inserted_handler); - if (priv->sig2) - g_signal_handler_disconnect (priv->account_mgr, priv->sig2); + 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); if (priv->sig3) g_signal_handler_disconnect (priv->account_mgr, priv->sig3); @@ -207,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; @@ -261,28 +250,11 @@ update_account_view (ModestAccountMgr *account_mgr, ModestAccountView *view) } } - -static void -on_account_changed (ModestAccountMgr *account_mgr, - const gchar* account, GSList *keys, - gboolean server_account, ModestAccountView *self) -{ - /* Never update the view in response to gconf changes. - * Always do it explicitly instead. - * This is because we have no way to avoid 10 updates when changing - * 10 items, and this blocks the UI. - * - * But this block/unblock API might be useful on platforms where the - * notification does not happen so long after the key was set. - * (We have no way to know when the last key was set, to do a final update).. - */ - - update_account_view (account_mgr, self); -} - static void -on_account_busy_changed(ModestAccountMgr *account_mgr, const gchar *account_name, - gboolean busy, ModestAccountView *self) +on_account_busy_changed(ModestAccountMgr *account_mgr, + const gchar *account_name, + gboolean busy, + ModestAccountView *self) { GtkListStore *model = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(self))); GtkTreeIter iter; @@ -313,6 +285,20 @@ on_account_busy_changed(ModestAccountMgr *account_mgr, const gchar *account_name } static void +on_account_inserted (TnyAccountStore *account_store, + TnyAccount *account, + gpointer user_data) +{ + ModestAccountView *self; + ModestAccountViewPrivate *priv; + + self = MODEST_ACCOUNT_VIEW (user_data); + priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE (self); + + update_account_view (priv->account_mgr, self); +} + +static void on_account_removed (TnyAccountStore *account_store, TnyAccount *account, gpointer user_data) @@ -323,7 +309,7 @@ on_account_removed (TnyAccountStore *account_store, self = MODEST_ACCOUNT_VIEW (user_data); priv = MODEST_ACCOUNT_VIEW_GET_PRIVATE (self); - update_account_view (priv->account_mgr, MODEST_ACCOUNT_VIEW (user_data)); + update_account_view (priv->account_mgr, self); } @@ -498,10 +484,14 @@ init_view (ModestAccountView *self) */ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), TRUE); - priv->sig1 = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),"account_removed", - G_CALLBACK(on_account_removed), self); - priv->sig2 = g_signal_connect (G_OBJECT(priv->account_mgr), "account_changed", - G_CALLBACK(on_account_changed), self); + priv->acc_removed_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()), + "account_removed", + G_CALLBACK(on_account_removed), self); + + priv->acc_inserted_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()), + "account_inserted", + G_CALLBACK(on_account_inserted), self); + priv->sig3 = g_signal_connect (G_OBJECT(priv->account_mgr), "account_busy_changed", G_CALLBACK(on_account_busy_changed), self); } diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index 7fe6dd9..51bfcfc 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -69,15 +69,12 @@ static void modest_folder_view_set_account_store (TnyAccountStoreView *s static void on_selection_changed (GtkTreeSelection *sel, gpointer data); -static void on_account_update (TnyAccountStore *account_store, - const gchar *account, - gpointer user_data); - static void on_account_removed (TnyAccountStore *self, TnyAccount *account, gpointer user_data); -static void on_accounts_reloaded (TnyAccountStore *store, +static void on_account_inserted (TnyAccountStore *self, + TnyAccount *account, gpointer user_data); static gint cmp_rows (GtkTreeModel *tree_model, @@ -93,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, @@ -149,9 +147,10 @@ struct _ModestFolderViewPrivate { TnyFolder *folder_to_select; /* folder to select after the next update */ - gulong account_update_signal; + ModestConfNotificationId notification_id; + gulong changed_signal; - gulong accounts_reloaded_signal; + gulong account_inserted_signal; gulong account_removed_signal; gulong conf_key_signal; @@ -169,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), \ @@ -652,10 +651,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 @@ -678,6 +679,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; @@ -685,9 +692,7 @@ modest_folder_view_finalize (GObject *obj) if (priv->account_store) { g_signal_handler_disconnect (G_OBJECT(priv->account_store), - priv->account_update_signal); - g_signal_handler_disconnect (G_OBJECT(priv->account_store), - priv->accounts_reloaded_signal); + priv->account_inserted_signal); g_signal_handler_disconnect (G_OBJECT(priv->account_store), priv->account_removed_signal); g_object_unref (G_OBJECT(priv->account_store)); @@ -747,14 +752,10 @@ modest_folder_view_set_account_store (TnyAccountStoreView *self, TnyAccountStore if (G_UNLIKELY (priv->account_store)) { - if (g_signal_handler_is_connected (G_OBJECT (priv->account_store), - priv->account_update_signal)) - g_signal_handler_disconnect (G_OBJECT (priv->account_store), - priv->account_update_signal); - if (g_signal_handler_is_connected (G_OBJECT (priv->account_store), - priv->accounts_reloaded_signal)) - g_signal_handler_disconnect (G_OBJECT (priv->account_store), - priv->accounts_reloaded_signal); + if (g_signal_handler_is_connected (G_OBJECT (priv->account_store), + priv->account_inserted_signal)) + g_signal_handler_disconnect (G_OBJECT (priv->account_store), + priv->account_inserted_signal); if (g_signal_handler_is_connected (G_OBJECT (priv->account_store), priv->account_removed_signal)) g_signal_handler_disconnect (G_OBJECT (priv->account_store), @@ -765,36 +766,84 @@ modest_folder_view_set_account_store (TnyAccountStoreView *self, TnyAccountStore priv->account_store = g_object_ref (G_OBJECT (account_store)); - priv->account_update_signal = - g_signal_connect (G_OBJECT(account_store), "account_update", - G_CALLBACK (on_account_update), self); - priv->account_removed_signal = g_signal_connect (G_OBJECT(account_store), "account_removed", G_CALLBACK (on_account_removed), self); - priv->accounts_reloaded_signal = - g_signal_connect (G_OBJECT(account_store), "accounts_reloaded", - G_CALLBACK (on_accounts_reloaded), self); + priv->account_inserted_signal = + g_signal_connect (G_OBJECT(account_store), "account_inserted", + G_CALLBACK (on_account_inserted), self); - g_signal_connect (G_OBJECT(account_store), "connecting_finished", - G_CALLBACK (on_accounts_reloaded), self); - on_accounts_reloaded (account_store, (gpointer ) self); +/* g_signal_connect (G_OBJECT(account_store), "connecting_finished", */ +/* G_CALLBACK (on_accounts_reloaded), self); */ + +/* on_accounts_reloaded (account_store, (gpointer ) self); */ + + modest_folder_view_update_model (MODEST_FOLDER_VIEW (self), account_store); g_object_unref (G_OBJECT (device)); } static void +on_account_inserted (TnyAccountStore *account_store, + TnyAccount *account, + gpointer user_data) +{ + ModestFolderViewPrivate *priv; + GtkTreeModel *sort_model, *filter_model; + + /* Ignore transport account insertions, we're not showing them + in the folder view */ + if (TNY_IS_TRANSPORT_ACCOUNT (account)) + return; + + priv = MODEST_FOLDER_VIEW_GET_PRIVATE (user_data); + + /* If we're adding a new account, and there is no previous + one, we need to select the visible server account */ + if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE && + !priv->visible_account_id) + modest_widget_memory_restore (modest_runtime_get_conf(), + G_OBJECT (user_data), + MODEST_CONF_FOLDER_VIEW_KEY); + + /* Get the inner model */ + filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (user_data)); + sort_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model)); + + /* Insert the account in the model */ + tny_list_append (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), + G_OBJECT (account)); +} + +static void on_account_removed (TnyAccountStore *account_store, TnyAccount *account, gpointer user_data) { - ModestFolderView *self = MODEST_FOLDER_VIEW (user_data); + ModestFolderView *self = NULL; 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); + /* TODO: invalidate the cur_folder_* and folder_to_select things */ + + /* Remove the account from the model */ + filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (self)); + sort_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model)); + tny_list_remove (TNY_LIST (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model))), + G_OBJECT (account)); + /* If the removed account is the currently viewed one then clear the configuration value. The new visible account will be the default account */ if (priv->visible_account_id && @@ -806,42 +855,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); } -} - -static void -on_account_update (TnyAccountStore *account_store, - const gchar *account, - gpointer user_data) -{ - ModestFolderView *self = NULL; - ModestFolderViewPrivate *priv; - g_return_if_fail (MODEST_IS_FOLDER_VIEW (user_data)); - self = MODEST_FOLDER_VIEW (user_data); - priv = MODEST_FOLDER_VIEW_GET_PRIVATE (self); - - /* If we're adding a new account, and there is no previous - one, we need to select the visible server account */ - if (priv->style == MODEST_FOLDER_VIEW_STYLE_SHOW_ONE && - !priv->visible_account_id) - modest_widget_memory_restore (modest_runtime_get_conf(), G_OBJECT(self), - MODEST_CONF_FOLDER_VIEW_KEY); - - if (!modest_folder_view_update_model (self, account_store)) - g_printerr ("modest: failed to update model for changes in '%s'", - account); -} - -static void -on_accounts_reloaded (TnyAccountStore *account_store, - gpointer user_data) -{ - g_return_if_fail (MODEST_IS_FOLDER_VIEW (user_data)); - modest_folder_view_update_model (MODEST_FOLDER_VIEW (user_data), account_store); + /* Select the INBOX */ + modest_folder_view_select_first_inbox_or_local (self); } void @@ -1061,7 +1078,7 @@ modest_folder_view_update_model (ModestFolderView *self, /* FIXME: the local accounts are not shown when the query selects only the subscribed folders. */ /* model = tny_gtk_folder_store_tree_model_new (TRUE, priv->query); */ - model = tny_gtk_folder_store_tree_model_new (TRUE, NULL); + model = tny_gtk_folder_store_tree_model_new (NULL); /* Deal with the model via its TnyList Interface, * filling the TnyList via a get_accounts() call: */ @@ -1949,17 +1966,20 @@ 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) - return; g_return_if_fail (MODEST_IS_FOLDER_VIEW (self)); priv = MODEST_FOLDER_VIEW_GET_PRIVATE(self); + /* Do not listen for changes in other namespaces */ + if (priv->notification_id != id) + return; + if (!strcmp (key, MODEST_CONF_DEVICE_NAME)) { g_free (priv->local_account_name); @@ -1978,7 +1998,7 @@ on_configuration_key_changed (ModestConf* conf, } } -void +void modest_folder_view_set_style (ModestFolderView *self, ModestFolderViewStyle style) { diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 5a62caa..bee32a6 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 a66271e..9a8c103 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); @@ -318,8 +316,8 @@ modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *head if (win) *win = NULL; - g_debug ("windows in list: %d", g_list_length (priv->window_list)); - g_debug ("headers in list: %d", g_slist_length (priv->preregistered_uids)); +/* g_debug ("windows in list: %d", g_list_length (priv->window_list)); */ +/* g_debug ("headers in list: %d", g_slist_length (priv->preregistered_uids)); */ has_header = has_uid (priv->preregistered_uids, uid); @@ -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 -- 1.7.9.5