X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-window-mgr.c;h=8dc8cfcf26e34f5f2d42144ad5953932105b3b82;hp=0b0469b01f082a87ed34dd99e1e6c9b70090a893;hb=e28b9dcedc0b54531ea55fee74885ad5d5a11c75;hpb=20f40360ad626eb860e7d106e5dcfd43a59d21d4 diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 0b0469b..8dc8cfc 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -37,6 +37,7 @@ #include "widgets/modest-msg-edit-window.h" #include "widgets/modest-msg-view-window.h" #include "modest-debug.h" +#include /* 'private'/'protected' functions */ @@ -44,52 +45,72 @@ 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 gboolean on_window_destroy (ModestWindow *window, - GdkEvent *event, - ModestWindowMgr *self); - -static gboolean on_modal_window_close (GtkWidget *widget, - GdkEvent *event, - gpointer user_data); - -static void on_modal_dialog_close (GtkDialog *dialog, - gint arg1, - gpointer user_data); - -static const gchar* get_show_toolbar_key (GType window_type, - gboolean fullscreen); +static gboolean modest_window_mgr_register_window_default (ModestWindowMgr *self, + ModestWindow *window, + ModestWindow *parent); +static void modest_window_mgr_unregister_window_default (ModestWindowMgr *self, + ModestWindow *window); +static void modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self, + gboolean on); +static gboolean modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self); +static void modest_window_mgr_show_toolbars_default (ModestWindowMgr *self, + GType window_type, + gboolean show_toolbars, + gboolean fullscreen); +static ModestWindow* modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show); +static GtkWindow *modest_window_mgr_get_modal_default (ModestWindowMgr *self); +static void modest_window_mgr_set_modal_default (ModestWindowMgr *self, + GtkWindow *window, + GtkWindow *parent); +static gboolean modest_window_mgr_close_all_windows_default (ModestWindowMgr *self); +static gboolean modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, + TnyHeader *header, + ModestWindow **win); +static gboolean modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self, + const gchar *msg_uid, + ModestWindow **win); +static GList *modest_window_mgr_get_window_list_default (ModestWindowMgr *self); +static ModestWindow *modest_window_mgr_show_initial_window_default (ModestWindowMgr *self); +static ModestWindow *modest_window_mgr_get_current_top_default (ModestWindowMgr *self); +static gboolean modest_window_mgr_screen_is_on_default (ModestWindowMgr *self); +static void modest_window_mgr_create_caches_default (ModestWindowMgr *self); +static void modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestWindowMgr *self); +static void on_mail_operation_started (ModestMailOperation *mail_op, + gpointer user_data); +static void on_mail_operation_finished (ModestMailOperation *mail_op, + gpointer user_data); /* list my signals */ enum { WINDOW_LIST_EMPTY_SIGNAL, + PROGRESS_LIST_CHANGED_SIGNAL, NUM_SIGNALS }; typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate; struct _ModestWindowMgrPrivate { - GList *window_list; guint banner_counter; ModestWindow *main_window; - GMutex *queue_lock; - GQueue *modal_windows; - - gboolean fullscreen_mode; - GSList *windows_that_prevent_hibernation; GSList *preregistered_uids; - GHashTable *destroy_handlers; - GHashTable *viewer_handlers; guint closing_time; - GSList *modal_handler_uids; GtkWidget *cached_view; GtkWidget *cached_editor; guint idle_load_view_id; guint idle_load_editor_id; + + guint queue_change_handler; + TnyList *progress_operations; + GSList *sighandlers; }; + #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_WINDOW_MGR, \ ModestWindowMgrPrivate)) @@ -127,10 +148,29 @@ static void modest_window_mgr_class_init (ModestWindowMgrClass *klass) { GObjectClass *gobject_class; + ModestWindowMgrClass *mgr_class; + gobject_class = (GObjectClass*) klass; + mgr_class = (ModestWindowMgrClass *) klass; parent_class = g_type_class_peek_parent (klass); gobject_class->finalize = modest_window_mgr_finalize; + mgr_class->register_window = modest_window_mgr_register_window_default; + mgr_class->unregister_window = modest_window_mgr_unregister_window_default; + mgr_class->set_fullscreen_mode = modest_window_mgr_set_fullscreen_mode_default; + mgr_class->get_fullscreen_mode = modest_window_mgr_get_fullscreen_mode_default; + mgr_class->show_toolbars = modest_window_mgr_show_toolbars_default; + mgr_class->get_main_window = modest_window_mgr_get_main_window_default; + mgr_class->get_modal = modest_window_mgr_get_modal_default; + mgr_class->set_modal = modest_window_mgr_set_modal_default; + mgr_class->close_all_windows = modest_window_mgr_close_all_windows_default; + mgr_class->find_registered_header = modest_window_mgr_find_registered_header_default; + mgr_class->find_registered_message_uid = modest_window_mgr_find_registered_message_uid_default; + mgr_class->get_window_list = modest_window_mgr_get_window_list_default; + mgr_class->show_initial_window = modest_window_mgr_show_initial_window_default; + mgr_class->get_current_top = modest_window_mgr_get_current_top_default; + mgr_class->screen_is_on = modest_window_mgr_screen_is_on_default; + mgr_class->create_caches = modest_window_mgr_create_caches_default; g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate)); @@ -150,6 +190,22 @@ modest_window_mgr_class_init (ModestWindowMgrClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * ModestWindowMgr::progress-list-changed + * @self: the #ModestWindowMgr that emits the signal + * @user_data: user data set when the signal handler was connected + * + * Issued whenever the progress mail operations list becomes changed + */ + signals[PROGRESS_LIST_CHANGED_SIGNAL] = + g_signal_new ("progress-list-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ModestWindowMgrClass, progress_list_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static gboolean @@ -177,7 +233,7 @@ load_new_view (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); if ((priv->cached_view == NULL) && (priv->idle_load_view_id == 0)) - priv->idle_load_view_id = g_idle_add ((GSourceFunc) idle_load_view, self); + priv->idle_load_view_id = g_timeout_add (2500, (GSourceFunc) idle_load_view, self); } static void @@ -185,7 +241,7 @@ load_new_editor (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); if ((priv->cached_editor == NULL) && (priv->idle_load_editor_id == 0)) - priv->idle_load_editor_id = g_idle_add ((GSourceFunc) idle_load_editor, self); + priv->idle_load_editor_id = g_timeout_add (5000, (GSourceFunc) idle_load_editor, self); } static void @@ -194,26 +250,20 @@ modest_window_mgr_init (ModestWindowMgr *obj) ModestWindowMgrPrivate *priv; priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj); - priv->window_list = NULL; priv->banner_counter = 0; priv->main_window = NULL; - priv->fullscreen_mode = FALSE; - priv->modal_windows = g_queue_new (); - priv->queue_lock = g_mutex_new (); - priv->preregistered_uids = NULL; - /* Could not initialize it from gconf, singletons are not - ready yet */ - priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - priv->closing_time = 0; - priv->modal_handler_uids = NULL; priv->cached_view = NULL; priv->cached_editor = NULL; + + priv->windows_that_prevent_hibernation = NULL; + + priv->queue_change_handler = 0; + priv->progress_operations = TNY_LIST (tny_simple_list_new ()); } static void @@ -240,47 +290,28 @@ modest_window_mgr_finalize (GObject *obj) priv->cached_editor = NULL; } - if (priv->window_list) { - GList *iter = priv->window_list; - /* unregister pending windows */ - while (iter) { - modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), - MODEST_WINDOW (iter->data)); - iter = g_list_next (iter); - } - g_list_free (priv->window_list); - priv->window_list = NULL; + if (priv->windows_that_prevent_hibernation) { + g_slist_free (priv->windows_that_prevent_hibernation); + priv->cached_editor = NULL; } - g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL); - g_slist_free (priv->preregistered_uids); + modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers); + priv->sighandlers = NULL; - - /* Free the hash table with the handlers */ - if (priv->destroy_handlers) { - g_hash_table_destroy (priv->destroy_handlers); - priv->destroy_handlers = NULL; + if (priv->queue_change_handler > 0) { + g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), + priv->queue_change_handler); + priv->queue_change_handler = 0; } - if (priv->viewer_handlers) { - g_hash_table_destroy (priv->viewer_handlers); - priv->viewer_handlers = NULL; + if (priv->progress_operations) { + g_object_unref (priv->progress_operations); + priv->progress_operations = NULL; } - modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids); - - if (priv->modal_windows) { - g_mutex_lock (priv->queue_lock); - g_queue_free (priv->modal_windows); - priv->modal_windows = NULL; - g_mutex_unlock (priv->queue_lock); - } - g_mutex_free (priv->queue_lock); - - /* Do not unref priv->main_window because it does not hold a - new reference */ + g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL); + g_slist_free (priv->preregistered_uids); - G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -318,7 +349,7 @@ remove_uid (GSList *list, const gchar *uid) GSList *cursor = list, *start = list; if (!uid) - return FALSE; + return list; while (cursor) { GSList *next = g_slist_next (cursor); @@ -350,11 +381,12 @@ modest_window_mgr_register_header (ModestWindowMgr *self, TnyHeader *header, co g_return_if_fail (TNY_IS_HEADER(header)); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - uid = modest_tny_folder_get_header_unique_id (header); - - if (uid == NULL) + if (alt_uid != NULL) { uid = g_strdup (alt_uid); - + } else { + uid = modest_tny_folder_get_header_unique_id (header); + } + if (!has_uid (priv->preregistered_uids, uid)) { MODEST_DEBUG_BLOCK(g_debug ("registering new uid %s", uid);); priv->preregistered_uids = append_uid (priv->preregistered_uids, uid); @@ -413,185 +445,127 @@ modest_window_mgr_register_help_id (ModestWindowMgr *self, GtkWindow *win, const const gchar* modest_window_mgr_get_help_id (ModestWindowMgr *self, GtkWindow *win) { - const gchar* help_id = NULL; - /* we don't need 'self', but for API consistency... */ - g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL); - + g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR (self), NULL); g_return_val_if_fail (win, NULL); - g_return_val_if_fail (GTK_IS_WINDOW(win), NULL); - - if (MODEST_IS_MAIN_WINDOW (win)) { - GtkWidget *folder_view; - TnyFolderStore *folder_store; - - /* Get selected folder */ - folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), - MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); - folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)); - - /* Switch help_id */ - if (folder_store && TNY_IS_FOLDER (folder_store)) { - help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store)); - if (!help_id) - g_warning ("%s: BUG: did not get a valid help_id", __FUNCTION__); - } - if (folder_store) - g_object_unref (folder_store); - } - if (!help_id) - help_id = g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM); - - return help_id; + return g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM); } -static gint -compare_msguids (ModestWindow *win, - const gchar *uid) +gboolean +modest_window_mgr_close_all_windows (ModestWindowMgr *self) { - const gchar *msg_uid; - - if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win))) - return 1; - - /* Get message uid from msg window */ - if (MODEST_IS_MSG_EDIT_WINDOW (win)) { - msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win)); - if (msg_uid && uid &&!strcmp (msg_uid, uid)) - return 0; - } else { - msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win)); - } - - if (msg_uid && uid &&!strcmp (msg_uid, uid)) - return 0; - else - return 1; + return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_windows (self); } -void -modest_window_mgr_close_all_windows (ModestWindowMgr *self) +static gboolean +modest_window_mgr_close_all_windows_default (ModestWindowMgr *self) { - ModestWindowMgrPrivate *priv = NULL; - gboolean ret_value = FALSE; - - g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - - /* If there is a main window then try to close it, and it will - close the others if needed */ - if (priv->main_window) { - g_signal_emit_by_name (priv->main_window, "delete-event", NULL, &ret_value); - } else { - GList *wins = NULL, *next = NULL; - - /* delete-event handler actually removes window_list item, */ - wins = priv->window_list; - while (wins) { - next = g_list_next (wins); - g_signal_emit_by_name (G_OBJECT (wins->data), "delete-event", NULL, &ret_value); - wins = next; - } - } + return TRUE; } gboolean modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header, - ModestWindow **win) + ModestWindow **win) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_header (self, header, win); +} + +static gboolean +modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, TnyHeader *header, + ModestWindow **win) { - ModestWindowMgrPrivate *priv = NULL; gchar* uid = NULL; - gboolean has_header, has_window = FALSE; - GList *item = NULL; g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); g_return_val_if_fail (TNY_IS_HEADER(header), FALSE); - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); uid = modest_tny_folder_get_header_unique_id (header); - + + if (uid) + return modest_window_mgr_find_registered_message_uid (self, uid, win); + else + return FALSE; +} + +gboolean +modest_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid, + ModestWindow **win) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_message_uid (self, msg_uid, win); +} + +static gboolean +modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self, const gchar *msg_uid, + ModestWindow **win) +{ + ModestWindowMgrPrivate *priv = NULL; + gchar* uid = NULL; + gboolean has_header = FALSE; + + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); + g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + if (win) *win = NULL; - has_header = has_uid (priv->preregistered_uids, uid); - - item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids); - if (item) { - has_window = TRUE; - if (win) { - if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) && - (!MODEST_IS_MSG_EDIT_WINDOW (item->data))) - g_debug ("not a valid window!"); - else { - g_debug ("found a window"); - *win = MODEST_WINDOW (item->data); - } - } - } + has_header = has_uid (priv->preregistered_uids, msg_uid); g_free (uid); - - return has_header || has_window; -} - -static const gchar * -get_show_toolbar_key (GType window_type, - gboolean fullscreen) -{ - const gchar *key = NULL; - - if (window_type == MODEST_TYPE_MAIN_WINDOW) - key = (fullscreen) ? - MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN : - MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR; - else if (window_type == MODEST_TYPE_MSG_VIEW_WINDOW) - key = (fullscreen) ? - MODEST_CONF_MSG_VIEW_WINDOW_SHOW_TOOLBAR_FULLSCREEN : - MODEST_CONF_MSG_VIEW_WINDOW_SHOW_TOOLBAR; - else if (window_type == MODEST_TYPE_MSG_EDIT_WINDOW) - key = (fullscreen) ? - MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN : - MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR; - else - g_return_val_if_reached (NULL); - return key; + return has_header; } -void +GList * +modest_window_mgr_get_window_list (ModestWindowMgr *self) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->get_window_list (self); +} + +static GList * +modest_window_mgr_get_window_list_default (ModestWindowMgr *self) +{ + return NULL; +} + +gboolean modest_window_mgr_register_window (ModestWindowMgr *self, - ModestWindow *window) + ModestWindow *window, + ModestWindow *parent) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->register_window (self, window, parent); +} + +static gboolean +modest_window_mgr_register_window_default (ModestWindowMgr *self, + ModestWindow *window, + ModestWindow *parent) { - GList *win; ModestWindowMgrPrivate *priv; - gint *handler_id; - const gchar *key; - g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - win = g_list_find (priv->window_list, window); - if (win) { - /* this is for the case we want to register the window and it was already - * registered. We leave silently. - */ - return; + /* We set up the queue change handler */ + if (priv->queue_change_handler == 0) { + priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), + "queue-changed", + G_CALLBACK (modest_window_mgr_on_queue_changed), + self); } - + /* Check that it's not a second main window */ if (MODEST_IS_MAIN_WINDOW (window)) { if (priv->main_window) { g_warning ("%s: trying to register a second main window", __FUNCTION__); - return; + return FALSE; } else { priv->main_window = window; - load_new_view (self); - load_new_editor (self); } } @@ -600,15 +574,14 @@ modest_window_mgr_register_window (ModestWindowMgr *self, const gchar *uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)); - if (!has_uid (priv->preregistered_uids, uid)) - g_debug ("weird: no uid for window (%s)", uid); - MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid ? uid : "");); - priv->preregistered_uids = - remove_uid (priv->preregistered_uids, - modest_msg_view_window_get_message_uid - (MODEST_MSG_VIEW_WINDOW (window))); + if (has_uid (priv->preregistered_uids, uid)) { + priv->preregistered_uids = + remove_uid (priv->preregistered_uids, + modest_msg_view_window_get_message_uid + (MODEST_MSG_VIEW_WINDOW (window))); + } } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) { const gchar *uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (window)); @@ -620,210 +593,32 @@ modest_window_mgr_register_window (ModestWindowMgr *self, modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (window))); } - - /* Add to list. Keep a reference to the window */ - g_object_ref (window); - priv->window_list = g_list_prepend (priv->window_list, window); - - /* Listen to object destruction */ - handler_id = g_malloc0 (sizeof (gint)); - *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self); - g_hash_table_insert (priv->destroy_handlers, window, handler_id); - - /* If there is a msg view window, let the main window listen the msg-changed signal */ - if (MODEST_IS_MSG_VIEW_WINDOW(window) && priv->main_window) { - gulong *handler; - handler = g_malloc0 (sizeof (gulong)); - *handler = g_signal_connect (window, "msg-changed", - G_CALLBACK (modest_main_window_on_msg_view_window_msg_changed), - priv->main_window); - g_hash_table_insert (priv->viewer_handlers, window, handler); - } - - /* Put into fullscreen if needed */ - if (priv->fullscreen_mode) - gtk_window_fullscreen (GTK_WINDOW (window)); - - /* Show/hide toolbar & fullscreen */ - key = get_show_toolbar_key (G_TYPE_FROM_INSTANCE (window), priv->fullscreen_mode); - modest_window_show_toolbar (window, modest_conf_get_bool (modest_runtime_get_conf (), key, NULL)); -} - -static gboolean -on_window_destroy (ModestWindow *window, - GdkEvent *event, - ModestWindowMgr *self) -{ - gint dialog_response = GTK_RESPONSE_NONE; - - /* Specific stuff first */ - if (MODEST_IS_MAIN_WINDOW (window)) { - ModestWindowMgrPrivate *priv; - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - - /* If more than one window already opened */ - if (g_list_length (priv->window_list) > 1) { - - /* Present the window if it's not visible now */ - if (!gtk_window_has_toplevel_focus (GTK_WINDOW (window))) - gtk_window_present (GTK_WINDOW (window)); - /* Create the confirmation dialog MSG-NOT308 */ - dialog_response = modest_platform_run_confirmation_dialog ( - GTK_WINDOW (window), _("emev_nc_close_windows")); - - /* If the user wants to close all the windows */ - if ((dialog_response == GTK_RESPONSE_OK) - || (dialog_response == GTK_RESPONSE_ACCEPT) - || (dialog_response == GTK_RESPONSE_YES)) - { - GList *iter = priv->window_list; - do { - if (iter->data != window) { - GList *tmp = iter->next; - on_window_destroy (MODEST_WINDOW (iter->data), - event, - self); - iter = tmp; - } else { - iter = g_list_next (iter); - } - } while (iter); - } - else - { - return TRUE; - } - } - } - else { - if (MODEST_IS_MSG_EDIT_WINDOW (window)) { - gboolean sent = FALSE; - gint response = GTK_RESPONSE_ACCEPT; - sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window)); - /* Save currently edited message to Drafts if it was not sent */ - if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) { - - /* Raise the window if it's minimized */ - if (!gtk_window_has_toplevel_focus (GTK_WINDOW (window))) - gtk_window_present (GTK_WINDOW (window)); - - response = - modest_platform_run_confirmation_dialog (GTK_WINDOW (window), - _("mcen_nc_no_email_message_modified_save_changes")); - /* Save to drafts */ - if (response != GTK_RESPONSE_CANCEL) - if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window))) - return TRUE; - } - } - } - - /* Unregister window */ - modest_window_mgr_unregister_window (self, window); - - return FALSE; -} -static void -disconnect_msg_changed (gpointer key, - gpointer value, - gpointer user_data) -{ - guint handler_id; - handler_id = GPOINTER_TO_UINT(value); - - if (key && G_IS_OBJECT(key)) - g_signal_handler_disconnect (G_OBJECT (key), handler_id); + return TRUE; } void modest_window_mgr_unregister_window (ModestWindowMgr *self, ModestWindow *window) { - GList *win; - ModestWindowMgrPrivate *priv; - gulong *tmp, handler_id; + MODEST_WINDOW_MGR_GET_CLASS (self)->unregister_window (self, window); +} +static void +modest_window_mgr_unregister_window_default (ModestWindowMgr *self, + ModestWindow *window) +{ g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); g_return_if_fail (MODEST_IS_WINDOW (window)); - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - - win = g_list_find (priv->window_list, window); - if (!win) { - g_warning ("Trying to unregister a window that has not being registered yet"); - return; - } - - /* If it's the main window unset it */ - if (priv->main_window == window) { - priv->main_window = NULL; - - /* Disconnect all emissions of msg-changed */ - if (priv->viewer_handlers) { - g_hash_table_foreach (priv->viewer_handlers, - disconnect_msg_changed, - NULL); - g_hash_table_destroy (priv->viewer_handlers); - 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); - /* If the viewer was created without a main window - (for example when opening a message through D-Bus - the viewer handlers was not registered */ - if (tmp) { - g_signal_handler_disconnect (window, *tmp); - g_hash_table_remove (priv->viewer_handlers, window); - } - } - /* Save state */ modest_window_save_state (window); - /* Remove from list & hash table */ - priv->window_list = g_list_remove_link (priv->window_list, win); - tmp = g_hash_table_lookup (priv->destroy_handlers, window); - handler_id = *tmp; - g_hash_table_remove (priv->destroy_handlers, window); - - /* cancel open and receive operations */ - if (MODEST_IS_MSG_VIEW_WINDOW (window)) { - ModestMailOperationTypeOperation type; - GSList* pending_ops = NULL; - GSList* tmp_list = NULL; - pending_ops = modest_mail_operation_queue_get_by_source ( - modest_runtime_get_mail_operation_queue (), - G_OBJECT (window)); - while (pending_ops != NULL) { - type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data)); - if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || type == MODEST_MAIL_OPERATION_TYPE_OPEN) { - modest_mail_operation_cancel (pending_ops->data); - } - g_object_unref (G_OBJECT (pending_ops->data)); - tmp_list = pending_ops; - pending_ops = g_slist_next (pending_ops); - g_slist_free_1 (tmp_list); - } - } - - /* 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); - - /* If there are no more windows registered emit the signal */ - if (priv->window_list == NULL && priv->banner_counter == 0) - g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); + gtk_widget_destroy (GTK_WIDGET (window)); } @@ -832,56 +627,26 @@ void modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self, gboolean on) { - ModestWindowMgrPrivate *priv; - GList *win = NULL; - ModestConf *conf; - - g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - - /* If there is no change do nothing */ - if (priv->fullscreen_mode == on) - return; - - priv->fullscreen_mode = on; - - conf = modest_runtime_get_conf (); - - /* Update windows */ - win = priv->window_list; - while (win) { - gboolean show; - const gchar *key = NULL; - - /* Getting this from gconf everytime is not that - expensive, we'll do it just a few times */ - key = get_show_toolbar_key (G_TYPE_FROM_INSTANCE (win->data), on); - show = modest_conf_get_bool (conf, key, NULL); - - /* Set fullscreen/unfullscreen */ - if (on) - gtk_window_fullscreen (GTK_WINDOW (win->data)); - else - gtk_window_unfullscreen (GTK_WINDOW (win->data)); - - /* Show/Hide toolbar */ - modest_window_show_toolbar (MODEST_WINDOW (win->data), show); + MODEST_WINDOW_MGR_GET_CLASS (self)->set_fullscreen_mode (self, on); +} - win = g_list_next (win); - } +static void +modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self, + gboolean on) +{ + return; } gboolean modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self) { - ModestWindowMgrPrivate *priv; - - g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + return MODEST_WINDOW_MGR_GET_CLASS (self)->get_fullscreen_mode (self); +} - return priv->fullscreen_mode; +static gboolean +modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self) +{ + return FALSE; } void @@ -890,57 +655,49 @@ modest_window_mgr_show_toolbars (ModestWindowMgr *self, gboolean show_toolbars, gboolean fullscreen) { - ModestWindowMgrPrivate *priv; - ModestConf *conf; - const gchar *key = NULL; + return MODEST_WINDOW_MGR_GET_CLASS (self)->show_toolbars (self, window_type, show_toolbars, fullscreen); +} + +static void +modest_window_mgr_show_toolbars_default (ModestWindowMgr *self, + GType window_type, + gboolean show_toolbars, + gboolean fullscreen) +{ + return; +} +void +modest_window_mgr_set_main_window (ModestWindowMgr *self, ModestWindow *win) +{ + ModestWindowMgrPrivate *priv; + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - conf = modest_runtime_get_conf (); - - /* If nothing changes then return */ - key = get_show_toolbar_key (window_type, fullscreen); - conf = modest_runtime_get_conf (); - if (modest_conf_get_bool (conf, key, NULL) == show_toolbars) - return; - - /* Save in conf */ - modest_conf_set_bool (conf, key, show_toolbars, NULL); - - /* Apply now if the view mode is the right one */ - if ((fullscreen && priv->fullscreen_mode) || - (!fullscreen && !priv->fullscreen_mode)) { - - GList *win = priv->window_list; - - while (win) { - if (G_TYPE_FROM_INSTANCE (win->data) == window_type) - modest_window_show_toolbar (MODEST_WINDOW (win->data), - show_toolbars); - win = g_list_next (win); - } - } + priv->main_window = win; } ModestWindow* -modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean create) +modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->get_main_window (self, show); +} + +static ModestWindow* +modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show) { ModestWindowMgrPrivate *priv; g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - - /* create the main window, if it hasn't been created yet */ - if (!priv->main_window && create) { - /* modest_window_mgr_register_window will set priv->main_window */ - modest_window_mgr_register_window (self, modest_main_window_new ()); - MODEST_DEBUG_BLOCK( - g_debug ("%s: created main window: %p\n", __FUNCTION__, priv->main_window); - ); - } - - return priv->main_window; + if (priv->main_window) + return priv->main_window; + + if (show) + return modest_main_window_new (); + else return NULL; } @@ -959,61 +716,30 @@ modest_window_mgr_main_window_exists (ModestWindowMgr *self) GtkWindow * modest_window_mgr_get_modal (ModestWindowMgr *self) { - ModestWindowMgrPrivate *priv; - - g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + return MODEST_WINDOW_MGR_GET_CLASS (self)->get_modal (self); +} - return g_queue_peek_head (priv->modal_windows); +static GtkWindow * +modest_window_mgr_get_modal_default (ModestWindowMgr *self) +{ + return NULL; } void modest_window_mgr_set_modal (ModestWindowMgr *self, - GtkWindow *window) + GtkWindow *window, + GtkWindow *parent) { - GtkWindow *old_modal; - ModestWindowMgrPrivate *priv; - - g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - g_mutex_lock (priv->queue_lock); - old_modal = g_queue_peek_head (priv->modal_windows); - g_mutex_unlock (priv->queue_lock); - - if (!old_modal) { - gtk_window_set_modal (window, TRUE); - } else { - /* un-modalize the old one; the one on top should be the - * modal one */ - gtk_window_set_transient_for (window, GTK_WINDOW(old_modal)); - gtk_window_set_modal (window, TRUE); - } + MODEST_WINDOW_MGR_GET_CLASS (self)->set_modal (self, window, parent); +} - /* this will be the new modal window */ - g_mutex_lock (priv->queue_lock); - g_queue_push_head (priv->modal_windows, window); - g_mutex_unlock (priv->queue_lock); - - if (GTK_IS_DIALOG (window)) - /* Note that response is not always enough because it - could be captured and removed easily by dialogs but - works for most of situations */ - priv->modal_handler_uids = - modest_signal_mgr_connect (priv->modal_handler_uids, - G_OBJECT (window), - "response", - G_CALLBACK (on_modal_dialog_close), - self); - else - priv->modal_handler_uids = - modest_signal_mgr_connect (priv->modal_handler_uids, - G_OBJECT (window), - "delete-event", - G_CALLBACK (on_modal_window_close), - self); +static void +modest_window_mgr_set_modal_default (ModestWindowMgr *self, + GtkWindow *window, + GtkWindow *parent) +{ + return; } @@ -1076,113 +802,47 @@ modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self) void modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self) { + GList *window_list; + GList *node; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); - ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - /* Iterate over all windows */ - GList *win = priv->window_list; - while (win) { - ModestWindow *window = MODEST_WINDOW (win->data); + window_list = modest_window_mgr_get_window_list (self); + node = window_list; + while (node) { + ModestWindow *window = MODEST_WINDOW (node->data); if (window) { /* This calls the vfunc, * so each window can do its own thing: */ modest_window_save_state (window); - } - - win = g_list_next (win); - } -} - -static gboolean -idle_top_modal (gpointer data) -{ - ModestWindowMgr *self = MODEST_WINDOW_MGR (data); - ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - GtkWindow *topmost; - - /* Get the top modal */ - g_mutex_lock (priv->queue_lock); - topmost = (GtkWindow *) g_queue_peek_head (priv->modal_windows); - g_mutex_unlock (priv->queue_lock); - - /* Show it */ - if (topmost) - gtk_window_present (topmost); - - return FALSE; -} - -static void -remove_modal_from_queue (GtkWidget *widget, - ModestWindowMgr *self) -{ - ModestWindowMgrPrivate *priv; - GList *item = NULL; - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + } - /* Remove from queue. We don't use remove, because we want to - exit if the widget does not belong to the queue */ - g_mutex_lock (priv->queue_lock); - item = g_queue_find (priv->modal_windows, widget); - if (!item) { - g_warning ("Trying to remove a modal window that is not registered"); - g_mutex_unlock (priv->queue_lock); - return; + node = g_list_next (node); } - g_queue_unlink (priv->modal_windows, item); - g_mutex_unlock (priv->queue_lock); - - /* Disconnect handler */ - priv->modal_handler_uids = - modest_signal_mgr_disconnect (priv->modal_handler_uids, - G_OBJECT (widget), - GTK_IS_DIALOG (widget) ? - "response" : - "destroy-event"); - - /* Schedule the next one for being shown */ - g_idle_add (idle_top_modal, self); -} - -static gboolean -on_modal_window_close (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); - - /* Remove modal window from queue */ - remove_modal_from_queue (widget, self); - - /* Continue */ - return FALSE; -} - -static void -on_modal_dialog_close (GtkDialog *dialog, - gint arg1, - gpointer user_data) -{ - ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); - - /* Remove modal window from queue */ - remove_modal_from_queue (GTK_WIDGET (dialog), self); + g_list_free (window_list); } -gint -modest_window_mgr_num_windows (ModestWindowMgr *self) +guint +modest_window_mgr_get_num_windows (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv; gint num_windows = 0; + GList *window_list; g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1); - + priv = MODEST_WINDOW_MGR_GET_PRIVATE(self); - - if (priv->window_list) - num_windows = g_list_length (priv->window_list); + + window_list = modest_window_mgr_get_window_list (self); + + if (window_list) { + num_windows = g_list_length (window_list); + g_list_free (window_list); + } + + /* Do not take into account the main window if it was hidden */ + if (num_windows && priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window)) + num_windows--; return num_windows + priv->banner_counter; } @@ -1229,7 +889,7 @@ modest_window_mgr_get_msg_view_window (ModestWindowMgr *self) return result; } -void +void modest_window_mgr_register_banner (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv; @@ -1238,10 +898,9 @@ modest_window_mgr_register_banner (ModestWindowMgr *self) priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); priv->banner_counter++; - } -void +void modest_window_mgr_unregister_banner (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv; @@ -1250,8 +909,236 @@ modest_window_mgr_unregister_banner (ModestWindowMgr *self) priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); priv->banner_counter--; - if (priv->window_list == NULL && priv->banner_counter == 0) { + if (modest_window_mgr_get_num_windows (self) == 0) g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0); +} + +ModestWindow * +modest_window_mgr_show_initial_window (ModestWindowMgr *self) +{ + ModestWindow *window = NULL; + + /* Call the children */ + window = MODEST_WINDOW_MGR_GET_CLASS (self)->show_initial_window (self); + + if (window) { + ModestAccountMgr *mgr; + + /* Show the initial window */ + gtk_widget_show (GTK_WIDGET (window)); + + /* If there are no accounts then show the account wizard */ + mgr = modest_runtime_get_account_mgr(); + if (!modest_account_mgr_has_accounts (mgr, TRUE)) { + if (!modest_ui_actions_run_account_setup_wizard (window)) { + g_debug ("%s: couldn't show account setup wizard", __FUNCTION__); + } + } + } + + return window; +} + +static ModestWindow * +modest_window_mgr_show_initial_window_default (ModestWindowMgr *self) +{ + /* By default it returns the main window creating it if + needed */ + return modest_window_mgr_get_main_window (self, TRUE); +} + + +ModestWindow * +modest_window_mgr_get_current_top (ModestWindowMgr *self) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->get_current_top (self); +} + + +static ModestWindow * +modest_window_mgr_get_current_top_default (ModestWindowMgr *self) +{ + g_return_val_if_reached (NULL); +} + +gboolean +modest_window_mgr_screen_is_on (ModestWindowMgr *self) +{ + return MODEST_WINDOW_MGR_GET_CLASS (self)->screen_is_on (self); +} + +static gboolean +modest_window_mgr_screen_is_on_default (ModestWindowMgr *self) +{ + /* Default implementation is assuming screen is always on */ + + return TRUE; +} + +void +modest_window_mgr_create_caches (ModestWindowMgr *mgr) +{ + MODEST_WINDOW_MGR_GET_CLASS (mgr)->create_caches (mgr); +} + +static void +modest_window_mgr_create_caches_default (ModestWindowMgr *self) +{ + load_new_editor (self); + load_new_view (self); +} + +static gboolean +tny_list_find (TnyList *list, GObject *item) +{ + TnyIterator *iterator; + gboolean found = FALSE; + + for (iterator = tny_list_create_iterator (list); + !tny_iterator_is_done (iterator) && !found; + tny_iterator_next (iterator)) { + GObject *current = tny_iterator_get_current (iterator); + if (current == item) + found = TRUE; + g_object_unref (current); + } + g_object_unref (iterator); + + return found; +} + +static void +modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue, + ModestMailOperation *mail_op, + ModestMailOperationQueueNotification type, + ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + /* We register to track progress */ + if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) { + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT (mail_op), + "operation-started", + G_CALLBACK (on_mail_operation_started), + self); + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT (mail_op), + "operation-finished", + G_CALLBACK (on_mail_operation_finished), + self); + } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) { + priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers, + G_OBJECT (mail_op), + "operation-started"); + priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers, + G_OBJECT (mail_op), + "operation-finished"); + if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) { + tny_list_remove (priv->progress_operations, G_OBJECT (mail_op)); + g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0); + } + } +} + +static void +on_mail_operation_started (ModestMailOperation *mail_op, + gpointer user_data) +{ + ModestWindowMgr *self; + ModestWindowMgrPrivate *priv; + ModestMailOperationTypeOperation op_type; + + self = MODEST_WINDOW_MGR (user_data); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + /* First we check if the operation is a send receive operation, + * If now, we don't handle this */ + op_type = modest_mail_operation_get_type_operation (mail_op); + if (op_type != MODEST_MAIL_OPERATION_TYPE_SEND && + op_type != MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) { + return; + } + + if (!tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) { + tny_list_prepend (priv->progress_operations, G_OBJECT (mail_op)); + g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0); + } +} + +static void +on_mail_operation_finished (ModestMailOperation *mail_op, + gpointer user_data) +{ + ModestWindowMgr *self; + ModestWindowMgrPrivate *priv; + + self = MODEST_WINDOW_MGR (user_data); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) { + tny_list_remove (priv->progress_operations, G_OBJECT (mail_op)); + g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0); + } +} + +TnyList * +modest_window_mgr_get_progress_operations (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + return tny_list_copy (priv->progress_operations); +} + +gboolean +modest_window_mgr_has_progress_operation (ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + return tny_list_get_length (priv->progress_operations) > 0; +} + +gboolean +modest_window_mgr_has_progress_operation_on_account (ModestWindowMgr *self, + const gchar *account_name) +{ + ModestWindowMgrPrivate *priv; + gint account_ops = 0; + TnyIterator *iterator; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + if (account_name == NULL) + return 0; + + for (iterator = tny_list_create_iterator (priv->progress_operations); + !tny_iterator_is_done (iterator); + tny_iterator_next (iterator)) { + ModestMailOperation *mail_op; + TnyAccount *account; + + mail_op= MODEST_MAIL_OPERATION (tny_iterator_get_current (iterator)); + account = modest_mail_operation_get_account (mail_op); + + if (account != NULL) { + const gchar *current_name; + + current_name = tny_account_get_id (account); + if (current_name && strcmp (current_name, account_name) == 0) + account_ops ++; + g_object_unref (account); + } + + g_object_unref (mail_op); } + g_object_unref (iterator); + return account_ops; } +